diff -r 000000000000 -r 16d8024aca5e src/hbcore/vkbhosts/hbabstractvkbhost.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hbcore/vkbhosts/hbabstractvkbhost.cpp Mon Apr 19 14:02:13 2010 +0300 @@ -0,0 +1,953 @@ +/**************************************************************************** +** +** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (developer.feedback@nokia.com) +** +** This file is part of the HbCore module of the UI Extensions for Mobile. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at developer.feedback@nokia.com. +** +****************************************************************************/ +#include "hbabstractvkbhost.h" +#include "hbabstractvkbhost_p.h" +#include "hbinputvirtualkeyboard.h" +#include "hbinputsettingproxy.h" +#include "hbinputmethod.h" +#include "hbdeviceprofile.h" +#include "hbmainwindow.h" +#include "hbpopup.h" +#include "hbview.h" + +#include + +const int HbAnimationTime = 200; +const qreal HbEditorExtraMargin = 5.0; +const qreal HbCursorLineMargin = 15.0; +const qreal HbContainerBorderMargin = 20.0; +const qreal HbHeightVerticalFactor = 0.5; +const qreal HbHeightHorizFactor = 0.7; + +/*! +\proto +\class HbAbstractVkbHost +\brief Base class for HbCore's virtual keyboard hosts. + +This class contains common code for HbCore's virtual keyboard hosts. +*/ + +/// @cond + +HbAbstractVkbHostPrivate::HbAbstractVkbHostPrivate(HbAbstractVkbHost *myHost, QGraphicsWidget *containerWidget) +: q_ptr(myHost), +mCallback(0), +mKeypad(0), +mContainerWidget(containerWidget), +mTimeLine(HbAnimationTime), +mKeypadStatus(HbVkbHost::HbVkbStatusClosed), +mKeypadOperationOngoing(false), +mOriginalContainerPosition(QPointF(0,0)), +mContainerMovementStartingPoint(QPointF(0, 0)), +mContainerMovementVector(QPointF(0, 0)), +mKeypadMovementStartingPoint(QPointF(0, 0)), +mKeypadMovementVector(QPointF(0, 0)), +mInputMethod(0), +mKeypadStatusBeforeOrientationChange(HbVkbHost::HbVkbStatusClosed) +{ +} + +void HbAbstractVkbHostPrivate::prepareAnimationsCommon() +{ + if (mContainerWidget && mKeypad) { + // If the keyboard is not already open, remember the original position. + // That is where the container will eventually be returned to. + if (mKeypadStatus == HbVkbHost::HbVkbStatusClosed) { + mOriginalContainerPosition = mContainerWidget->pos(); + } + + // Initialize movement variables to starting values. These will + // be fine tuned later. + mKeypadMovementVector = QPointF(0, 0); + mContainerMovementVector = QPointF(0, 0); + mContainerMovementStartingPoint = mContainerWidget->pos(); + mKeypadMovementStartingPoint = mKeypad->pos(); + } + + mScreenSize = screenSize(); +} + +bool HbAbstractVkbHostPrivate::prepareContainerAnimation(HbVkbHost::HbVkbStatus status) +{ + if (!mKeypad || !mContainerWidget || !mInputMethod || !mInputMethod->focusObject()) { + return false; + } + + if (status == HbVkbHost::HbVkbStatusOpened) { + // Calculate the area that remains visible when the keypad is open. + QRectF visibleArea = QRectF(0.0, 0.0, mScreenSize.width(), mScreenSize.height() - mKeypad->size().height()); + + // Find out the container area. + QRectF containerArea = mContainerWidget->sceneBoundingRect(); + containerArea.adjust(0.0, -HbContainerBorderMargin, 0.0, HbContainerBorderMargin); + + if (visibleArea.contains(containerArea)) { + // The whole container is already inside the visible area, nothing to do. + return false; + } + + if (visibleArea.height() >= containerArea.height()) { + // It isn't in the visible area yet but fits there. Let's move it there. + mContainerMovementVector = QPointF(0.0, visibleArea.bottom() - containerArea.bottom()); + return true; + } + + // Find out the editor bounding box and add a small margin to height. + QRectF editorGeometry = mInputMethod->focusObject()->editorGeometry(); + editorGeometry.adjust(0.0, -HbCursorLineMargin, 0.0, HbCursorLineMargin); + + // Then see if the editor is already inside the visible area. + // If it isn't, see if it would fit there. + if (!visibleArea.contains(editorGeometry)) { + if (editorGeometry.width() <= visibleArea.width() && + editorGeometry.height() <= visibleArea.height()) { + // Yes, it fits into visible area, let's move it there so that + // the whole editor area is in use right away. + // First check if we want to move it to upper or lower + // part of the visible area. + if (editorGeometry.top() <= visibleArea.top()) { + // It goes to the upper part of the visible area. + mContainerMovementVector = QPointF(0.0, -editorGeometry.top()); + } else { + mContainerMovementVector = QPointF(0.0, visibleArea.bottom() - editorGeometry.bottom()); + } + + return true; + } + } + + // The editor is either already inside the visible area or doesn't fit there. + // Let's see if the cursor is visble. + // First find out micro focus rectangle and increase the height by a small margin. + QRectF microFocus = mInputMethod->focusObject()->microFocus(); + microFocus.setTop(microFocus.top() - HbEditorExtraMargin); + microFocus.setBottom(microFocus.bottom() + HbEditorExtraMargin); + + // Check whether the cursor rectangle is inside visible area. + if (!visibleArea.contains(microFocus)) { + // The cursor is outside the visible area. Figure out how much and + // to which direction the container has to be moved. + if (microFocus.bottom() <= visibleArea.top()) { + // It goes to the upper part of the visible area. + mContainerMovementVector = QPointF(0.0, HbCursorLineMargin - microFocus.top()); + } else { + mContainerMovementVector = QPointF(0.0, visibleArea.bottom() - HbCursorLineMargin - microFocus.bottom()); + } + + return true; + } + } else { + // It is going to be closed or minimized. + mContainerMovementVector = mOriginalContainerPosition - mContainerMovementStartingPoint; + return true; + } + + return false; +} + +bool HbAbstractVkbHostPrivate::prepareKeypadAnimation(HbVkbHost::HbVkbStatus status) +{ + if (status == HbVkbHost::HbVkbStatusOpened) { + if (mKeypadStatus == HbVkbHost::HbVkbStatusClosed) { + // Set up keyboard open animation. + mKeypadMovementStartingPoint.setY(mScreenSize.height()); + mKeypadMovementVector.setY(-mKeypad->size().height()); + if (!disableCursorShift()) { + // Initialize keypad position + mKeypad->setPos(mKeypadMovementStartingPoint); + } + return true; + } else if (mKeypadStatus == HbVkbHost::HbVkbStatusMinimized && mCallback) { + mKeypadMovementVector.setY(-(mKeypad->size().height() - mCallback->minimizedKeyboardSize().height())); + return true; + } + } else if (status == HbVkbHost::HbVkbStatusMinimized && mCallback) { + mKeypadMovementVector = QPointF(0, mKeypad->size().height() - mCallback->minimizedKeyboardSize().height()); + } else { + // It is going to be closed. + mKeypadMovementVector = QPointF(0, mKeypad->size().height()); + return true; + } + + return false; +} + +bool HbAbstractVkbHostPrivate::prepareAnimations(HbVkbHost::HbVkbStatus status) +{ + prepareAnimationsCommon(); + + return (prepareContainerAnimation(status) | + prepareKeypadAnimation(status)); +} + +void HbAbstractVkbHostPrivate::connectSignals() +{ + if (mContainerWidget) { + q_ptr->connect(mContainerWidget, SIGNAL(yChanged()), q_ptr, SLOT(ensureCursorVisibility())); + } + + HbWidget *hbWidget = qobject_cast(mContainerWidget); + if (hbWidget) { + HbMainWindow* mainWindow = hbWidget->mainWindow(); + if (mainWindow) { + q_ptr->connect(mainWindow, SIGNAL(aboutToChangeOrientation()), q_ptr, SLOT(orientationAboutToChange())); + q_ptr->connect(mainWindow, SIGNAL(orientationChanged(Qt::Orientation)), q_ptr, SLOT(orientationChanged(Qt::Orientation))); + } + } + + HbPopup *popup = qobject_cast(mContainerWidget); + if (popup) { + q_ptr->connect(popup, SIGNAL(aboutToHide()), q_ptr, SLOT(containerAboutToClose())); + } +} + +void HbAbstractVkbHostPrivate::disconnectSignals() +{ + if (mContainerWidget) { + q_ptr->disconnect(mContainerWidget, SIGNAL(yChanged()), q_ptr, SLOT(ensureCursorVisibility())); + } + + HbWidget *hbWidget = qobject_cast(mContainerWidget); + if (hbWidget) { + HbMainWindow* mainWindow = hbWidget->mainWindow(); + if (mainWindow) { + q_ptr->disconnect(mainWindow, SIGNAL(aboutToChangeOrientation()), q_ptr, SLOT(orientationAboutToChange())); + q_ptr->disconnect(mainWindow, SIGNAL(orientationChanged(Qt::Orientation)), q_ptr, SLOT(orientationChanged(Qt::Orientation))); + } + } + + HbPopup *popup = qobject_cast(mContainerWidget); + if (popup) { + q_ptr->disconnect(popup, SIGNAL(aboutToHide()), q_ptr, SLOT(containerAboutToClose())); + } +} + +void HbAbstractVkbHostPrivate::openKeypad() +{ + if (mContainerWidget) { + HbMainWindow* mainWin = mainWindow(); + if (mainWin && mKeypad) { + if (mKeypad->scene() != mainWin->scene()) { + // Add keypad to scene if it is not already in there. + mainWin->scene()->addItem(mKeypad); + } + + if (mKeypadStatus != HbVkbHost::HbVkbStatusOpened) { + mCallback->aboutToOpen(q_ptr); + q_ptr->resizeKeyboard(); // Make sure that the keyboard doesn't exceed given boundaries. + } + + if (prepareAnimations(HbVkbHost::HbVkbStatusOpened)) { + // Run the animation + mKeypadStatus = HbVkbHost::HbVkbStatusOpened; + mTimeLine.start(); + } + } + } +} + +void HbAbstractVkbHostPrivate::closeKeypad() +{ + // Since the keypad is already in a minimized state we should not play animation. + if (mKeypadStatus == HbVkbHost::HbVkbStatusMinimized) { + closeKeypadWithoutAnimation(); + } + + if (mKeypadStatus != HbVkbHost::HbVkbStatusClosed) { + mCallback->aboutToClose(q_ptr); + + if (prepareAnimations(HbVkbHost::HbVkbStatusClosed)) { + mKeypadStatus = HbVkbHost::HbVkbStatusClosed; + mTimeLine.start(); + } + } +} + +void HbAbstractVkbHostPrivate::minimizeKeypad() +{ + if (mCallback && mKeypadStatus != HbVkbHost::HbVkbStatusMinimized) { + mCallback->aboutToClose(q_ptr); + if (mContainerWidget) { + if (prepareAnimations(HbVkbHost::HbVkbStatusMinimized)) { + mKeypadStatus = HbVkbHost::HbVkbStatusMinimized; + mTimeLine.start(); + } + } + } +} + +void HbAbstractVkbHostPrivate::openKeypadWithoutAnimation() +{ + HbMainWindow *mainWin = mainWindow(); + if (mKeypadStatus!= HbVkbHost::HbVkbStatusOpened && mKeypad && mContainerWidget && mainWin) { + if (mKeypad->scene() != mainWin->scene()) { + // Add item to scene if it is not already in there. + mainWin->scene()->addItem(mKeypad); + } + + if (mKeypadStatus != HbVkbHost::HbVkbStatusOpened) { + mCallback->aboutToOpen(q_ptr); + q_ptr->resizeKeyboard(); // Make sure that the keyboard doesn't exceed given boundaries. + } + + if (prepareAnimations(HbVkbHost::HbVkbStatusOpened)) { + if (!disableCursorShift()) { + // Move the container widget to keep the focused line visible. + mContainerWidget->setPos(mContainerWidget->pos() + mContainerMovementVector); + + // Move the keypad + mKeypad->setPos(mKeypadMovementStartingPoint + mKeypadMovementVector); + } + + mKeypadStatus = HbVkbHost::HbVkbStatusOpened; + q_ptr->openFinished(); + } + } +} + +void HbAbstractVkbHostPrivate::openMinimizedKeypad() +{ + // No need of any animation as this minimized keypad is very small to be a candidate for an + // animation. + HbMainWindow *mainWin = mainWindow(); + if (mainWin && mKeypad && mContainerWidget) { + if (mKeypad->scene() != mainWin->scene()) { + // Add item to scene if it is not already in there. + mainWin->scene()->addItem(mKeypad); + } + + if (mKeypadStatus != HbVkbHost::HbVkbStatusMinimized) { + mCallback->aboutToOpen(q_ptr); + q_ptr->resizeKeyboard(); // Make sure that the keyboard doesn't exceed given boundaries. + } + + if (prepareAnimations(HbVkbHost::HbVkbStatusMinimized)) { + if (!disableCursorShift()) { + mKeypad->setPos(0.0, mScreenSize.height() - mCallback->minimizedKeyboardSize().height()); + } + mKeypadStatus = HbVkbHost::HbVkbStatusMinimized; + mCallback->keyboardMinimized(q_ptr); + } + } +} + +void HbAbstractVkbHostPrivate::closeKeypadWithoutAnimation() +{ + if (mKeypadStatus != HbVkbHost::HbVkbStatusClosed && mKeypad) { + mCallback->aboutToClose(q_ptr); + // Set original content widget position + mKeypadStatus = HbVkbHost::HbVkbStatusClosed; + + if (!disableCursorShift()) { + // Return the container widget to original position. + mContainerWidget->setPos(mOriginalContainerPosition); + } + + // Hide the keypad + mKeypad->hide(); + mCallback = 0; + } +} + +void HbAbstractVkbHostPrivate::minimizeKeypadWithoutAnimation() +{ + HbMainWindow *mainWin = mainWindow(); + if (mKeypadStatus != HbVkbHost::HbVkbStatusMinimized && mKeypad && mainWin) { + mCallback->aboutToClose(q_ptr); + if (mKeypad->scene() != mainWin->scene()) { + // Add item to scene if it is not already in there. + mainWin->scene()->addItem(mKeypad); + } + + if (!disableCursorShift()) { + // Return the container widget to original position. + mContainerWidget->setPos(mOriginalContainerPosition); + + // Set the keypad to minimized position. + mKeypad->setPos(QPointF(0.0, mScreenSize.height() - mCallback->minimizedKeyboardSize().height())); + } + + mKeypadStatus = HbVkbHost::HbVkbStatusMinimized; + } +} + +void HbAbstractVkbHostPrivate::cancelAnimationAndHideVkbWidget() +{ + if (mTimeLine.state() == QTimeLine::Running) { + mTimeLine.stop(); + + if (!disableCursorShift()) { + mContainerWidget->setPos(mOriginalContainerPosition); + } + + if (mKeypad) { + mKeypad->hide(); + } + + // Clear possible pending call. + mPendingCall.vkb = 0; + + mKeypadStatus = HbVkbHost::HbVkbStatusClosed; + } +} + +HbMainWindow *HbAbstractVkbHostPrivate::mainWindow() const +{ + HbWidget *hbWidget = qobject_cast(mContainerWidget); + if (hbWidget) { + return hbWidget->mainWindow(); + } + + return qobject_cast(qApp->activeWindow()); +} + +QSizeF HbAbstractVkbHostPrivate::screenSize() const +{ + HbMainWindow *mainWin = mainWindow(); + QSizeF result = static_cast(HbDeviceProfile::profile(mainWin).logicalSize()); + + // do some sanity checking for the size got from device profile + if( result.isNull() || result.width() < 200 || result.height() < 200 ) { + qWarning("VkbHost error: size from device profile is faulty, using fallback!"); + if (mainWin) { + if (mainWin->orientation() == Qt::Horizontal) { + result.setWidth(640); + result.setHeight(360); + } else { + result.setWidth(360); + result.setHeight(640); + } + } + } + + return result; +} + +bool HbAbstractVkbHostPrivate::disableCursorShift() { + + if (!mInputMethod + || mainWindow()) { + return false; + } + + if ( (mainWindow()->orientation() == Qt::Horizontal) + && (mInputMethod->inputState().inputMode() == HbInputModeHwrChinese + || mInputMethod->inputState().inputMode() == HbInputModeHwrChineseFull) ) { + return true; + } + return false; +} + + +/// @endcond + + +HbAbstractVkbHost::HbAbstractVkbHost(HbWidget *containerWidget) : d_ptr(new HbAbstractVkbHostPrivate(this, containerWidget)) +{ + Q_D(HbAbstractVkbHost); + + setParent(containerWidget); + HbVkbHost::attachHost(this, containerWidget); + + connect(&d->mTimeLine, SIGNAL(finished()), this, SLOT(animationFinished())); + connect(&d->mTimeLine, SIGNAL(valueChanged(qreal)), this, SLOT(animValueChanged(qreal))); +} + +HbAbstractVkbHost::HbAbstractVkbHost(QGraphicsWidget *containerWidget) : d_ptr(new HbAbstractVkbHostPrivate(this, containerWidget)) +{ + Q_D(HbAbstractVkbHost); + + setParent(containerWidget); + HbVkbHost::attachHost(this, containerWidget); + + connect(&d->mTimeLine, SIGNAL(finished()), this, SLOT(animationFinished())); + connect(&d->mTimeLine, SIGNAL(valueChanged(qreal)), this, SLOT(animValueChanged(qreal))); +} + +HbAbstractVkbHost::HbAbstractVkbHost(HbAbstractVkbHostPrivate *dd) : d_ptr(dd) +{ + Q_D(HbAbstractVkbHost); + + setParent(d->mContainerWidget); + HbVkbHost::attachHost(this, d->mContainerWidget); + + connect(&d->mTimeLine, SIGNAL(finished()), this, SLOT(animationFinished())); + connect(&d->mTimeLine, SIGNAL(valueChanged(qreal)), this, SLOT(animValueChanged(qreal))); +} + +HbAbstractVkbHost::~HbAbstractVkbHost() +{ + delete d_ptr; +} + +/*! +\reimp +*/ +HbVkbHost::HbVkbStatus HbAbstractVkbHost::keypadStatus() const +{ + Q_D(const HbAbstractVkbHost); + return d->mKeypadStatus; +} + +/*! +\reimp +*/ +void HbAbstractVkbHost::openKeypad(HbVirtualKeyboard *vkb, HbInputMethod* owner, bool animationAllowed) +{ + Q_D(HbAbstractVkbHost); + + if (owner) { + d->mInputMethod = owner; + } + + if ((d->mKeypadStatus != HbVkbStatusMinimized) && (!vkb || !owner)) { + // The caller is opening the keypad for the first time but didn't supply + // all the needed parameters. Null parameters are ok only if minimized + // keypad is reopened. + return; + } + + if (d->mTimeLine.state() == QTimeLine::Running) { + // The previous keyboard is still closing. Set the call pending and return. + d->mPendingCall.vkb = vkb; + d->mPendingCall.animationAllowed = animationAllowed; + return; + } + + if (!d->mKeypadOperationOngoing) { + d->mKeypadOperationOngoing = true; + + if (vkb && (d->mCallback != vkb || !d->mKeypad)) { + // This keypad is opened for the first time or it was opened before but some other keypad + // was opened in between. + d->mCallback = vkb; + d->mKeypad = vkb->asGraphicsWidget(); + } + + if (!d->mKeypad) { + // Keyboard widget creation failed for some reason, can't go on. + d->mCallback = 0; + return; + } + + if (animationAllowed) { + d->openKeypad(); + } else { + d->openKeypadWithoutAnimation(); + } + + d->connectSignals(); + d->mKeypadOperationOngoing = false; + } +} + +/*! +\reimp +*/ +void HbAbstractVkbHost::closeKeypad(bool animationAllowed) +{ + Q_D(HbAbstractVkbHost); + + if (d->mKeypadStatus != HbVkbStatusClosed && !d->mKeypadOperationOngoing) { + d->mKeypadOperationOngoing = true; + + if (animationAllowed) { + d->closeKeypad(); + } else { + d->closeKeypadWithoutAnimation(); + } + + d->disconnectSignals(); + d->mKeypadOperationOngoing = false; + } +} + +/*! +\reimp +*/ +int HbAbstractVkbHost::priority() const +{ + return 0; +} + +/*! +This slot is called every time an animation frame is drawn. +*/ +void HbAbstractVkbHost::animValueChanged(qreal value) +{ + Q_D(HbAbstractVkbHost); + + if (!d->disableCursorShift()) { + // Move the container. + if (d->mContainerWidget) { + d->mContainerWidget->setPos(d->mContainerMovementStartingPoint + (d->mContainerMovementVector * value)); + } + + // Move keypad + if (d->mKeypad) { + d->mKeypad->setPos(d->mKeypadMovementStartingPoint + (d->mKeypadMovementVector * value)); + } + } + + if (d->mCallback) { + d->mCallback->keyboardAnimationFrame(HbVirtualKeyboard::HbVkbAnimOpen, value); + } +} + +/*! +\deprecated HbAbstractVkbHost::openAnimValueChanged(qreal) + is deprecated. +*/ +void HbAbstractVkbHost::openAnimValueChanged(qreal value) +{ + Q_UNUSED(value); +} + +/*! +\deprecated HbAbstractVkbHost::closeAnimValueChanged(qreal) + is deprecated. +*/ +void HbAbstractVkbHost::closeAnimValueChanged(qreal value) +{ + Q_UNUSED(value); +} + +/*! +\deprecated HbAbstractVkbHost::openFinished() + is deprecated. +*/ +void HbAbstractVkbHost::openFinished() +{ +} + +/*! +\deprecated HbAbstractVkbHost::closeFinished() + is deprecated. +*/ +void HbAbstractVkbHost::closeFinished() +{ +} + +/*! +This slot is called when an animation sequence is completed. +*/ +void HbAbstractVkbHost::animationFinished() +{ + Q_D(HbAbstractVkbHost); + + if (d->mContainerWidget && d->mKeypad && d->mCallback && d->mInputMethod) { + if (!d->disableCursorShift()) { + // Make sure the container reached target position. + d->mContainerWidget->setPos(d->mContainerMovementStartingPoint + d->mContainerMovementVector); + + // Make sure the keypad reached target position. + d->mKeypad->setPos(d->mKeypadMovementStartingPoint + d->mKeypadMovementVector); + } + + // Notify + if (d->mKeypadStatus == HbVkbHost::HbVkbStatusOpened) { + d->mCallback->keyboardOpened(this); + + if (d->mInputMethod->focusObject()) { + // This is hopefully temporary... + QTextEdit *textEdit = qobject_cast(d->mInputMethod->focusObject()->object()); + if (textEdit) { + textEdit->ensureCursorVisible(); + } + } + + // Make sure the keypad never steals focus. + d->mKeypad->setFlag(QGraphicsItem::ItemIsPanel, true); + d->mKeypad->setActive(false); + emit keypadOpened(); + } else if (d->mKeypadStatus == HbVkbHost::HbVkbStatusMinimized) { + d->mCallback->keyboardMinimized(this); + emit keypadClosed(); + } else { + // It was closed. + d->mKeypad->hide(); + d->mCallback->keyboardClosed(this); + emit keypadClosed(); + + if (d->mPendingCall.vkb) { + // There was an open call pending. Do it now. + HbVirtualKeyboard *vkb = d->mPendingCall.vkb; + d->mPendingCall.vkb = 0; + openKeypad(vkb, d->mInputMethod, d->mPendingCall.animationAllowed); + } + } + } +} + +/*! +\reimp +*/ +QSizeF HbAbstractVkbHost::keyboardArea() const +{ + Q_D(const HbAbstractVkbHost); + + HbMainWindow *mainWindow = d->mainWindow(); + if (d->mContainerWidget && mainWindow) { + QSizeF screenSize = d->screenSize(); + + if (mainWindow->orientation() == Qt::Horizontal) { + return QSizeF(screenSize.width(), screenSize.height() * HbHeightHorizFactor); + } else { + return QSizeF(screenSize.width(), screenSize.height() * HbHeightVerticalFactor); + } + } + + return QSizeF(0.0, 0.0); +} + +/*! +\reimp +*/ +void HbAbstractVkbHost::preferredSizeChanged(const QSizeF& newSize) +{ + Q_UNUSED(newSize); +} + +/*! +This slot is connected to orientation change warning signal from the framework +and notifies setting proxy. Notification will then be delivered through setting proxy to all the +interested parties. +*/ +void HbAbstractVkbHost::orientationAboutToChange() +{ + Q_D(HbAbstractVkbHost); + d->mKeypadStatusBeforeOrientationChange = d->mKeypadStatus; + HbInputSettingProxy::instance()->notifyScreenOrientationChange(); +} + +/*! +This slot is connected to orientation change signal from the framework and notifies +the setting proxy. Notification will then be froearded to other interested parties +by the setting proxy. +*/ +void HbAbstractVkbHost::orientationChanged(Qt::Orientation orientation) +{ + HbInputSettingProxy::instance()->setScreenOrientation(orientation); +} + +/*! +\reimp +*/ +HbVirtualKeyboard* HbAbstractVkbHost::activeKeypad() const +{ + Q_D(const HbAbstractVkbHost); + return d->mCallback; +} + +/*! +\reimp +*/ +void HbAbstractVkbHost::ensureCursorVisibility() +{ + Q_D(HbAbstractVkbHost); + + if ((d->mTimeLine.state() == QTimeLine::Running) || + (d->mKeypadStatus == HbVkbStatusClosed) || + (d->mKeypadStatus == HbVkbStatusMinimized) || + !d->mContainerWidget) { + return; + } + + // This will refresh the situation if needed. + d->openKeypad(); +} + +/*! +Returns the area inside active main window view that will remain visible when the +virtual keyboard is open. +*/ +QRectF HbAbstractVkbHost::activeViewRect() const +{ + Q_D(const HbAbstractVkbHost); + + HbMainWindow *mainWindow = d->mainWindow(); + if (d->mContainerWidget && mainWindow) { + QSizeF vpSize = d->screenSize(); + QRectF viewport = QRectF(QPointF(0.0, 0.0), QPointF(vpSize.width(), vpSize.height())); + + viewport.setHeight(viewport.height() - confirmedKeyboardSize().height()); + return viewport; + } + + return QRectF(); +} + +/*! +Returns confirmed keyboard size. The method first queries preferred keyboard +size and then clips it against maximum allowed keyboard size. Resulting size is returned. +*/ +QSizeF HbAbstractVkbHost::confirmedKeyboardSize()const +{ + Q_D(const HbAbstractVkbHost); + + if (d->mCallback && d->mKeypad) { + QSizeF kbArea = keyboardArea(); + QSizeF confirmed = d->mCallback->preferredKeyboardSize(); + + if (confirmed.width() > kbArea.width()) { + confirmed.setWidth(kbArea.width()); + } + if (confirmed.height() > kbArea.height()) { + confirmed.setHeight(kbArea.height()); + } + + return QSizeF(confirmed); + } + + return QSizeF(); +} + +/*! +Resizes keyboard widget to its preferred size and makes sure that +the size does not exceed the size that host is willing to give to it. +*/ +void HbAbstractVkbHost::resizeKeyboard() +{ + Q_D(HbAbstractVkbHost); + + if (d->mKeypad) { + QSizeF currentSize = d->mKeypad->size(); + QSizeF newSize = confirmedKeyboardSize(); + if (currentSize != newSize) { + d->mKeypad->resize(newSize); + } + } +} + +/*! +\reimp +*/ +QRectF HbAbstractVkbHost::applicationArea() const +{ + Q_D(const HbAbstractVkbHost); + + if (d->mKeypadStatus == HbVkbStatusOpened) { + return activeViewRect(); + } + + return QRectF(); +} + +/*! +\reimp +*/ +void HbAbstractVkbHost::minimizeKeypad(bool animationAllowed) +{ + Q_D(HbAbstractVkbHost); + if (d->mKeypadStatus != HbVkbStatusClosed && !d->mKeypadOperationOngoing) { + d->mKeypadOperationOngoing = true; + + if (animationAllowed) { + d->minimizeKeypad(); + } else { + d->minimizeKeypadWithoutAnimation(); + } + + d->mKeypadOperationOngoing = false; + } +} + +/*! +\reimp +*/ +void HbAbstractVkbHost::openMinimizedKeypad(HbVirtualKeyboard *vkb, HbInputMethod* owner) +{ + Q_D(HbAbstractVkbHost); + d->mInputMethod = owner; + + if (!d->mKeypadOperationOngoing) { + d->mKeypadOperationOngoing = true; + + if (d->mCallback != vkb || !d->mKeypad) { + // This keypad is opened for the first time or it was opened before but some other keypad + // was opened in between. + d->mCallback = vkb; + d->mKeypad = vkb->asGraphicsWidget(); + } + + if (!d->mKeypad) { + // Keyboard widget creation failed for some reason, can't go on. + d->mCallback = 0; + return; + } + + d->openMinimizedKeypad(); + d->connectSignals(); + d->mKeypadOperationOngoing = false; + } +} + +/*! +\reimp +*/ +HbVkbHost::HbVkbStatus HbAbstractVkbHost::keypadStatusBeforeOrientationChange() const +{ + Q_D(const HbAbstractVkbHost); + return d->mKeypadStatusBeforeOrientationChange; +} + +/*! +This slot is called when active HbView changes. +*/ +void HbAbstractVkbHost::currentViewChanged(HbView *view) +{ + Q_D(HbAbstractVkbHost); + + if (view != d->mContainerWidget) { + if (d->mTimeLine.state() == QTimeLine::Running) { + d->cancelAnimationAndHideVkbWidget(); + if (d->mCallback) { + d->mCallback->keyboardClosed(this); + } + emit keypadClosed(); + } else if (d->mKeypadStatus != HbVkbStatusClosed) { + d->closeKeypadWithoutAnimation(); + } + } +} + +/*! +\reimp +*/ +void HbAbstractVkbHost::refresh() +{ + Q_D(HbAbstractVkbHost); + + if (d->mKeypadStatus == HbVkbHost::HbVkbStatusOpened && + d->mTimeLine.state() != QTimeLine::Running) { + d->prepareAnimationsCommon(); + if (d->prepareContainerAnimation(HbVkbHost::HbVkbStatusOpened)) { + // Container status needs to be updated. Run the animation. + d->mTimeLine.start(); + } + } +} + +// End of file