--- a/src/hbcore/vkbhosts/hbabstractvkbhost.cpp Mon Oct 04 17:49:30 2010 +0300
+++ b/src/hbcore/vkbhosts/hbabstractvkbhost.cpp Mon Oct 18 18:23:13 2010 +0300
@@ -22,158 +22,59 @@
** Nokia at developer.feedback@nokia.com.
**
****************************************************************************/
+
#include "hbabstractvkbhost.h"
#include "hbabstractvkbhost_p.h"
+#include "private/hbvkbgeometrylogic_p.h"
+#include "hbvkbhostcontainerwidget_p.h"
#include "hbinputvirtualkeyboard.h"
#include "hbinputsettingproxy.h"
#include "hbinputvkbhostbridge.h"
+#include "hbvkbconstants_p.h"
+#include "hbwidgetfeedback.h"
#include "hbinputmethod.h"
#include "hbdeviceprofile.h"
+#include "hbscrollarea.h"
#include "hbmainwindow.h"
+#include "hbpopup_p.h"
#include "hbpopup.h"
#include "hbview.h"
-#include "hbwidgetfeedback.h"
#include "hbinstance.h"
#include <QTextEdit>
-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;
const QString KHandWritingName("Handwriting");
// see hbpopup.cpp for this
extern const char* KPositionManagedByVKB;
-/// @cond
-
-HbVkbHostContainerWidget::HbVkbHostContainerWidget(QObject *containterWidget)
- : mContainerWidget(containterWidget)
-{
-}
-
-// sets container widgets position to new position.
-void HbVkbHostContainerWidget::setPos(QPointF newPosition)
-{
- if (mContainerWidget) {
- QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(mContainerWidget);
- if (graphicsObject) {
- graphicsObject->setPos(newPosition);
- return;
- }
+/*!
+@stable
+@hbcore
+\class HbAbstractVkbHost
+\brief The default virtual keyboard host
- QWidget *qWidget = qobject_cast<QWidget *>(mContainerWidget);
- if (qWidget) {
-#ifdef Q_WS_WIN
- QPoint finalPosition = newPosition.toPoint();
- finalPosition -= qWidget->geometry().topLeft() - qWidget->frameGeometry().topLeft();
- qWidget->move(finalPosition);
-#else
- qWidget->move(newPosition.toPoint());
-#endif
- return;
- }
- }
-}
-
-// returns the global position, if container widget is a QGraphicsObject, it returns
-// scene position. In case the widget is QWidget it returns global co-ordinates
-QPointF HbVkbHostContainerWidget::pos()
-{
- if (mContainerWidget) {
- QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(mContainerWidget);
- if (graphicsObject) {
- return graphicsObject->pos();;
- }
-
- QWidget *qWidget = qobject_cast<QWidget *>(mContainerWidget);
- if (qWidget) {
- return qWidget->mapToGlobal(QPoint(0, 0));
- }
- }
-
- return QPointF(0, 0);
-}
-
-// returns the bounding rect in global co-ordinate, if container widget is a QGraphicsObject
-// it returns in scene co-ordinate, incase widget is QWidget it returns in global co-ordinate
-QRectF HbVkbHostContainerWidget::sceneBoundingRect()
-{
- if (mContainerWidget) {
- QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(mContainerWidget);
- if (graphicsObject) {
- return graphicsObject->sceneBoundingRect();;
- }
+This class implements the default virtual keyboard host. A virtual keyboard
+host is responsible for the interaction between application background
+and the virtual keyboard widget when a virtual keyboard becomes visible.
- QWidget *qWidget = qobject_cast<QWidget *>(mContainerWidget);
- if (qWidget) {
- return QRectF(qWidget->mapToGlobal(QPoint(0, 0)), qWidget->size());
- }
- }
-
- return QRectF(0, 0, 0, 0);
-}
+Its main task is to guarantee that editor's cursor line remains visible
+and that the virtual keyboard widget doesn't cover it.
-// connect container specific signals here.
-void HbVkbHostContainerWidget::connectSignals(QObject *receiver)
-{
- if (qobject_cast<QGraphicsObject *> (mContainerWidget)) {
- QObject::connect(mContainerWidget, SIGNAL(yChanged()),
- receiver, SLOT(ensureCursorVisibility()));
- }
-
- HbPopup *popup = qobject_cast<HbPopup *>(mContainerWidget);
- if (popup) {
- QObject::connect(popup, SIGNAL(aboutToHide()), receiver, SLOT(containerAboutToClose()));
- }
-
- HbView *view = qobject_cast<HbView *>(mContainerWidget);
- if (view) {
- QObject::connect(view->mainWindow(), SIGNAL(currentViewChanged(HbView *)),
- receiver, SLOT(currentViewChanged(HbView *)));
- }
-}
+The abstract vkb host does this by moving the editor container around in suitable way.
-// disconnect container specific signals here.
-void HbVkbHostContainerWidget::disconnectSignals(QObject *receiver)
-{
- if (qobject_cast<QGraphicsObject *> (mContainerWidget)) {
- QObject::disconnect(mContainerWidget, SIGNAL(yChanged()),
- receiver, SLOT(ensureCursorVisibility()));
- }
-
- HbPopup *popup = qobject_cast<HbPopup *>(mContainerWidget);
- if (popup) {
- QObject::disconnect(popup, SIGNAL(aboutToHide()), receiver, SLOT(containerAboutToClose()));
- }
+See \ref vkbHandling "virtual keyboard handling guide" for more information
- HbPopup *view = qobject_cast<HbPopup *>(mContainerWidget);
- if (view) {
- QObject::disconnect(view->mainWindow(), SIGNAL(currentViewChanged(HbView *)),
- receiver, SLOT(currentViewChanged(HbView *)));
- }
-}
-
-/// @endcond
-
-/*!
-\proto
-\class HbAbstractVkbHost
-\brief Base class for HbCore's virtual keyboard hosts.
-
-This class contains common code for HbCore's virtual keyboard hosts.
+\sa HbVkbHost
+\sa HbShrinkingVkbHost
+\sa HbStaticVkbHost
*/
-/// @cond
-
HbAbstractVkbHostPrivate::HbAbstractVkbHostPrivate(HbAbstractVkbHost *myHost, QObject *containerWidget)
: q_ptr(myHost),
mCallback(0),
mKeypad(0),
mContainerWidget(new HbVkbHostContainerWidget(containerWidget)),
- mTimeLine(HbAnimationTime),
+ mTimeLine(HbVkbAnimationTime),
mKeypadStatus(HbVkbHost::HbVkbStatusClosed),
mKeypadOperationOngoing(false),
mOriginalContainerPosition(QPointF(0, 0)),
@@ -182,9 +83,13 @@
mKeypadMovementStartingPoint(QPointF(0, 0)),
mKeypadMovementVector(QPointF(0, 0)),
mInputMethod(0),
- mKeypadStatusBeforeOrientationChange(HbVkbHost::HbVkbStatusClosed)
+ mKeypadStatusBeforeOrientationChange(HbVkbHost::HbVkbStatusClosed),
+ mTitleBarHiddenByVkbHost(false),
+ mStatusBarHiddenByVkbHost(false),
+ mMarginInPixels(0)
{
mTimeLine.setUpdateInterval(16);
+ mMarginInPixels = HbDeviceProfile::current().unitValue() * HbVkbHostMargin;
}
HbAbstractVkbHostPrivate::~HbAbstractVkbHostPrivate()
@@ -192,149 +97,164 @@
delete mContainerWidget;
}
+/*!
+\internal
+Initializes starting values to parameters needed for running the keypad and
+container widget animation effects.
+*/
void HbAbstractVkbHostPrivate::prepareAnimationsCommon()
{
- if (mContainerWidget->widgetObject() && mKeypad) {
+ // Initialize movement variables to starting values. These will
+ // be fine tuned later.
+ mKeypadMovementVector = QPointF(0, 0);
+ mContainerMovementVector = QPointF(0, 0);
+ mContainerMovementStartingPoint = QPointF();
+ mKeypadMovementStartingPoint = QPointF();
+ mScrollAreaRect = QRectF();
+
+ if (mContainerWidget && mContainerWidget->widgetObject() && 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();
+
+ // Make sure that the editor is completely visible inside a scroll area.
+ ensureVisibilityInsideScrollArea();
}
+/*!
+\internal
+Sets up view and focus object variables.
+*/
+bool HbAbstractVkbHostPrivate::getViewAndFocusObjects(HbView*& currentView, HbInputFocusObject*& focusObject)
+{
+ if (!mKeypad || !mInputMethod || !mContainerWidget ) {
+ return false;
+ }
+
+ HbMainWindow* window = mainWindow();
+ if (!window) {
+ return false;
+ }
+
+ // Update margin pixel value while you're at it.
+ mMarginInPixels = HbDeviceProfile::profile(window).unitValue() * HbVkbHostMargin;
+
+ currentView = window->currentView();
+ if (!currentView) {
+ return false;
+ }
+
+ focusObject = mInputMethod->focusObject();
+ if (!focusObject) {
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+\internal
+Sets up the container widget animation effect.
+*/
bool HbAbstractVkbHostPrivate::prepareContainerAnimation(HbVkbHost::HbVkbStatus status)
{
- if (!mKeypad || !mContainerWidget->widgetObject() || !mInputMethod || !mInputMethod->focusObject()) {
+ // Init and check main objects
+ HbView* currentView = 0;
+ HbInputFocusObject* focusObject = 0;
+ if (!getViewAndFocusObjects(currentView, 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);
+ bool result = false;
- if (visibleArea.contains(containerArea)) {
- // The whole container is already inside the visible area, nothing to do.
- return false;
- }
+ if (status == HbVkbHost::HbVkbStatusOpened) {
+ // Init parameters before calling.
+ QSizeF keypadSize = mKeypad->size();
+ QRectF viewRect = currentView->sceneBoundingRect();
+ bool isPopupType = qobject_cast<HbPopup *>(mContainerWidget->widgetObject()) != 0;
+ bool vkbOpen = mKeypadStatus == HbVkbHost::HbVkbStatusOpened;
+ QRectF containerRect = mContainerWidget->sceneBoundingRect();
+ QRectF editorRect = findEditorRect(focusObject);
+ QRectF cursorRect = focusObject->microFocus();
+ QPointF fixedMovement = mContainerWidget->fixedContainerMovement();
- 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;
+ // We know that the container will be moved at least the amount of
+ // fixed movement vector (which typically, if non-zero, is the
+ // height of the title bar). So we reduce the keypad area
+ // to make the calculations match (fixed movement points
+ // to negative direction, that's why addition).
+ if (!vkbOpen) {
+ keypadSize.setHeight(keypadSize.height() + fixedMovement.y());
}
- // 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);
+ // Initialize geometry calculation unit to handle all geometry calculations.
+ HbVkbGeometryLogicPrivate unit = HbVkbGeometryLogicPrivate(
+ mScreenSize,
+ keypadSize,
+ viewRect,
+ isPopupType,
+ vkbOpen,
+ containerRect,
+ editorRect,
+ cursorRect,
+ mMarginInPixels);
- // 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());
+ result = unit.calculateContainerMovement(mContainerMovementVector);
+ if (!vkbOpen) {
+ // Apply fixed movement only if the keyboard is not already open.
+ // Fixed movement is used for hiding the title bar.
+ mContainerMovementVector = selectLongestVerticalVector(fixedMovement, mContainerMovementVector);
+ }
+ } else if (status == HbVkbHost::HbVkbStatusClosed) {
+ if (mContainerMovementStartingPoint != mOriginalContainerPosition) {
+ mContainerMovementVector = mOriginalContainerPosition - mContainerMovementStartingPoint;
+ result = true;
+ }
+ }
+
+ return result;
+}
+
+/*!
+\internal
+Sets up the keypad widget animation effect.
+*/
+bool HbAbstractVkbHostPrivate::prepareKeypadAnimation(HbVkbHost::HbVkbStatus status)
+{
+ if (mKeypad) {
+ 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;
}
- }
-
- // 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)) {
- QRectF realEditorGeometry = editorGeometry;
- realEditorGeometry.adjust(0.0, HbCursorLineMargin, 0.0, -HbCursorLineMargin);
- if (!realEditorGeometry.contains(microFocus)) {
- // A sanity check. If the microFocus rectangle is outside the editor
- // bounding rect, don't do anything. The situation in editor widget is not
- // up to date.
- return false;
- }
- // 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()) {
- // First see what would happen if we returned the container to original position.
- // Is the cursor visible then?
- // This is always preferred, use it if possible.
- QPointF toOriginalPos = mOriginalContainerPosition - mContainerWidget->pos();
- QRectF translatedMicroFocus = microFocus.translated(toOriginalPos);
- if (visibleArea.contains(translatedMicroFocus)) {
- mContainerMovementVector = toOriginalPos;
- } else {
- // 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());
- }
-
+ } else {
+ // It is going to be closed.
+ mKeypadMovementVector = QPointF(0, mKeypad->size().height());
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());
- return true;
- } else {
- // It is going to be closed.
- mKeypadMovementVector = QPointF(0, mKeypad->size().height());
- return true;
- }
-
- return false;
-}
-
+/*!
+\internal
+Sets up all the animation effects.
+*/
bool HbAbstractVkbHostPrivate::prepareAnimations(HbVkbHost::HbVkbStatus status)
{
prepareAnimationsCommon();
@@ -353,6 +273,10 @@
return (containerResult | prepareKeypadAnimation(status));
}
+/*!
+\internal
+Connects orientation change, view switching and possible other related signals.
+*/
void HbAbstractVkbHostPrivate::connectSignals()
{
mContainerWidget->connectSignals(q_ptr);
@@ -362,10 +286,14 @@
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)));
- q_ptr->connect(mainWindow, SIGNAL(currentViewChanged(HbView *)), q_ptr, SLOT(currentViewChanged(HbView *)));
+ q_ptr->connect(mainWindow, SIGNAL(aboutToChangeView(HbView *, HbView *)), q_ptr, SLOT(aboutToChangeView(HbView *, HbView *)));
}
}
+/*!
+\internal
+Disconnects orientation change, view switching and possible other related signals.
+*/
void HbAbstractVkbHostPrivate::disconnectSignals()
{
mContainerWidget->disconnectSignals(q_ptr);
@@ -375,10 +303,14 @@
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)));
- q_ptr->disconnect(mainWindow, SIGNAL(currentViewChanged(HbView *)), q_ptr, SLOT(currentViewChanged(HbView *)));
+ q_ptr->disconnect(mainWindow, SIGNAL(aboutToChangeView(HbView *, HbView *)), q_ptr, SLOT(aboutToChangeView(HbView *, HbView *)));
}
}
+/*!
+\internal
+Opens the keypad widget with animation effect.
+*/
void HbAbstractVkbHostPrivate::openKeypad()
{
if (mContainerWidget->widgetObject()) {
@@ -390,7 +322,9 @@
}
if (mKeypadStatus != HbVkbHost::HbVkbStatusOpened) {
- mCallback->aboutToOpen(q_ptr);
+ if (mCallback) {
+ mCallback->aboutToOpen(q_ptr);
+ }
q_ptr->resizeKeyboard(); // Make sure that the keyboard doesn't exceed given boundaries.
}
@@ -403,15 +337,16 @@
}
}
+/*!
+\internal
+Closes the keypad with animation effect.
+*/
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 (mCallback) {
+ mCallback->aboutToClose(q_ptr);
+ }
if (prepareAnimations(HbVkbHost::HbVkbStatusClosed)) {
mKeypadStatus = HbVkbHost::HbVkbStatusClosed;
@@ -420,19 +355,10 @@
}
}
-void HbAbstractVkbHostPrivate::minimizeKeypad()
-{
- if (mCallback && mKeypadStatus != HbVkbHost::HbVkbStatusMinimized) {
- mCallback->aboutToClose(q_ptr);
- if (mContainerWidget->widgetObject()) {
- if (prepareAnimations(HbVkbHost::HbVkbStatusMinimized)) {
- mKeypadStatus = HbVkbHost::HbVkbStatusMinimized;
- mTimeLine.start();
- }
- }
- }
-}
-
+/*!
+\internal
+Opens the keypad widget without animation effect.
+*/
void HbAbstractVkbHostPrivate::openKeypadWithoutAnimation()
{
HbMainWindow *mainWin = mainWindow();
@@ -443,7 +369,9 @@
}
if (mKeypadStatus != HbVkbHost::HbVkbStatusOpened) {
- mCallback->aboutToOpen(q_ptr);
+ if (mCallback) {
+ mCallback->aboutToOpen(q_ptr);
+ }
q_ptr->resizeKeyboard(); // Make sure that the keyboard doesn't exceed given boundaries.
}
if (prepareAnimations(HbVkbHost::HbVkbStatusOpened)) {
@@ -456,48 +384,32 @@
}
mKeypadStatus = HbVkbHost::HbVkbStatusOpened;
- mCallback->keyboardOpened(q_ptr);
+ if (mCallback) {
+ mCallback->keyboardOpened(q_ptr);
+ }
}
}
+
+ ensureVisibilityInsideScrollArea();
+ ensureVisibilityInsideVisibleArea();
}
-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->widgetObject()) {
- 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);
- }
- }
-}
-
+/*!
+\internal
+Closes the keypad widget without animating it.
+*/
void HbAbstractVkbHostPrivate::closeKeypadWithoutAnimation()
{
- if (mKeypadStatus != HbVkbHost::HbVkbStatusClosed && mKeypad) {
+ if (mKeypadStatus != HbVkbHost::HbVkbStatusClosed && mKeypad && mCallback) {
mCallback->aboutToClose(q_ptr);
+
// Set original content widget position
mKeypadStatus = HbVkbHost::HbVkbStatusClosed;
if (!disableCursorShift()) {
// Return the container widget to original position.
mContainerWidget->setPos(mOriginalContainerPosition);
- mContainerWidget->widgetObject()->setProperty(KPositionManagedByVKB, false );
+ mContainerWidget->widgetObject()->setProperty(KPositionManagedByVKB, false);
}
// Hide the keypad
@@ -507,35 +419,18 @@
}
}
-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);
- }
-
- mKeypadStatus = HbVkbHost::HbVkbStatusMinimized;
- 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()));
- }
- }
-}
-
+/*!
+\internal
+Cancels the ongoing keypad animation and resets the timeline timer.
+*/
void HbAbstractVkbHostPrivate::cancelAnimationAndHideVkbWidget()
{
if (mTimeLine.state() == QTimeLine::Running) {
mTimeLine.stop();
- if (!disableCursorShift()) {
+ if (!disableCursorShift() && mContainerWidget && mContainerWidget->widgetObject()) {
mContainerWidget->setPos(mOriginalContainerPosition);
- mContainerWidget->widgetObject()->setProperty(KPositionManagedByVKB, false );
+ mContainerWidget->widgetObject()->setProperty(KPositionManagedByVKB, false);
}
if (mKeypad) {
@@ -551,6 +446,10 @@
}
}
+/*!
+\internal
+Returns pointer to container's main window (if one exists).
+*/
HbMainWindow *HbAbstractVkbHostPrivate::mainWindow() const
{
HbWidget *hbWidget = qobject_cast<HbWidget *>(mContainerWidget->widgetObject());
@@ -568,6 +467,10 @@
return 0;
}
+/*!
+\internal
+Returns screen size.
+*/
QSizeF HbAbstractVkbHostPrivate::screenSize() const
{
HbMainWindow *mainWin = mainWindow();
@@ -592,7 +495,6 @@
bool HbAbstractVkbHostPrivate::disableCursorShift()
{
-
if (!mInputMethod
|| mainWindow()) {
return false;
@@ -607,9 +509,177 @@
return false;
}
+/*!
+\internal
+Closes the keypad. This slot is connected to various signals from
+different container classes.
+*/
+void HbAbstractVkbHostPrivate::_q_containerAboutToClose()
+{
+ Q_Q(HbAbstractVkbHost);
+ q->closeKeypad();
+}
-/// @endcond
+/*!
+\internal
+Finds out if given editor is inside a scroll area and makes sure the cursor position is visible inside the
+scroll area.
+*/
+void HbAbstractVkbHostPrivate::ensureVisibilityInsideScrollArea() const
+{
+ if (mInputMethod && mInputMethod->focusObject()) {
+ HbInputFocusObject *fo = mInputMethod->focusObject();
+ HbScrollArea *scrollArea = 0;
+
+ QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(fo->object());
+ if (graphicsObject) {
+ for (QGraphicsWidget *parent = graphicsObject->parentWidget(); parent; parent = parent->parentWidget()) {
+ scrollArea = qobject_cast<HbScrollArea*>(parent);
+ if (scrollArea) {
+ break;
+ }
+ }
+ }
+
+ if (scrollArea && scrollArea->contentWidget()) {
+ QRectF scrollRect = scrollArea->sceneBoundingRect();
+ mScrollAreaRect = scrollRect;
+ QRectF editorRect = fo->editorGeometry();
+
+ if (!scrollRect.contains(editorRect)) {
+ // The editor is not visible inside a scroll area.
+ // Calculate how much the area needs to be scrolled
+ // to make the cursor line visible inside the scroll
+ // area. The call scroll area's ensure visibility and
+ // return the calculated value (it needs to be factored in
+ // to container animation calculations).
+ if (editorRect.height() < scrollRect.height()) {
+ // Whole editor rect fits into scroll area. Move it there.
+ if (editorRect.bottom() > scrollRect.bottom()) {
+ // Scroll upwards.
+ scrollArea->ensureVisible(scrollArea->contentWidget()->mapFromScene(editorRect.bottomLeft()), 0.0, mMarginInPixels);
+ } else {
+ // Scroll downwards.
+ scrollArea->ensureVisible(scrollArea->contentWidget()->mapFromScene(editorRect.topLeft()), 0.0, mMarginInPixels);
+ }
+ } else {
+ // Whole editor doesn't fit into scroll area. Used micro focus position instead.
+ QRectF microFocus = fo->microFocus();
+ if (microFocus.bottom() > scrollRect.bottom()) {
+ // Scroll upwards.
+ scrollArea->ensureVisible(scrollArea->contentWidget()->mapFromScene(microFocus.bottomLeft()), 0.0, mMarginInPixels);
+ } else {
+ // Scroll downwards.
+ scrollArea->ensureVisible(scrollArea->contentWidget()->mapFromScene(microFocus.topLeft()), 0.0, mMarginInPixels);
+ }
+ }
+ }
+ }
+ }
+}
+
+/*!
+\internal
+Finds out if given editor is inside a scroll area and makes sure the cursor position is visible inside the
+visible area.
+*/
+void HbAbstractVkbHostPrivate::ensureVisibilityInsideVisibleArea() const
+{
+ Q_Q(const HbAbstractVkbHost);
+ if (mInputMethod && mInputMethod->focusObject()) {
+ HbInputFocusObject *fo = mInputMethod->focusObject();
+ HbScrollArea *scrollArea = 0;
+
+ QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(fo->object());
+ if (graphicsObject) {
+ for (QGraphicsWidget *parent = graphicsObject->parentWidget(); parent; parent = parent->parentWidget()) {
+ scrollArea = qobject_cast<HbScrollArea*>(parent);
+ if (scrollArea) {
+ break;
+ }
+ }
+ }
+ if (scrollArea && scrollArea->contentWidget()) {
+ QRectF editorRect = fo->editorGeometry();
+ QRectF visibleArea = q->applicationArea();
+ if (!visibleArea.isValid() && mContainerWidget) {
+ visibleArea = mContainerWidget->sceneBoundingRect();
+ }
+
+ if (!visibleArea.contains(editorRect)) {
+ // Editor is inside scroll area but not on visible area so scroll it to be visible
+ if (editorRect.bottom() > visibleArea.bottom()) {
+ // Scroll upwards.
+ QPointF point = QPointF(0.0, -scrollArea->contentWidget()->pos().y() + (editorRect.bottom() - visibleArea.bottom()) + mMarginInPixels);
+ scrollArea->scrollContentsTo(point);
+ } else {
+ // Scroll downwards.
+ QPointF point = QPointF(0.0, -scrollArea->contentWidget()->pos().y() + editorRect.y() - mMarginInPixels);
+ scrollArea->scrollContentsTo(point);
+ }
+ }
+ }
+ }
+}
+
+/*!
+\internal
+Returns the editor bounding rect. If the editor is inside a scroll area, then we actually
+need to use the intersection of scroll area bounding rect and the editor rect in
+our calculations.
+*/
+QRectF HbAbstractVkbHostPrivate::findEditorRect(HbInputFocusObject* fo) const
+{
+ if (fo) {
+ QRectF editorRect = fo->editorGeometry();
+ if (!mScrollAreaRect.isEmpty()) {
+ QRectF adjustedSrcollArea = mScrollAreaRect;
+ // Cancel out the to-be-added margin
+ adjustedSrcollArea.adjust(0, mMarginInPixels, 0, -mMarginInPixels);
+ return editorRect.intersected(adjustedSrcollArea);
+ }
+ return editorRect;
+ }
+
+ return QRectF();
+}
+
+/*!
+\internal
+Returns true if the container is a popup and it is still running its opening animation
+when the open keypad call comes in.
+*/
+bool HbAbstractVkbHostPrivate::popupAnimationInProgress() const
+{
+ HbPopup *popup = qobject_cast<HbPopup *>(mContainerWidget->widgetObject());
+ if (popup) {
+ HbPopupPrivate *popupPrivate = HbPopupPrivate::d_ptr(popup);
+ return popupPrivate->showingInProgress;
+ }
+
+ return false;
+}
+
+/*!
+\internal
+From two given vector, returns the longest along the y-axis that points to the direction defined
+by v1.
+*/
+QPointF HbAbstractVkbHostPrivate::selectLongestVerticalVector(const QPointF &v1, const QPointF &v2) const
+{
+ if (v1.y() * v2.y() < 0) {
+ // They point to opposite directions.
+ return v1;
+ }
+
+ if (qAbs(v2.y()) > qAbs(v1.y())) {
+ // v2 is longer.
+ return v2;
+ }
+
+ return v1;
+}
HbAbstractVkbHost::HbAbstractVkbHost(HbWidget *containerWidget) : d_ptr(new HbAbstractVkbHostPrivate(this, containerWidget))
{
@@ -617,6 +687,9 @@
setParent(containerWidget);
HbVkbHost::attachHost(this, containerWidget);
+ if (containerWidget) {
+ containerWidget->setFlag(QGraphicsItem::ItemSendsGeometryChanges);
+ }
connect(&d->mTimeLine, SIGNAL(finished()), this, SLOT(animationFinished()));
connect(&d->mTimeLine, SIGNAL(valueChanged(qreal)), this, SLOT(animValueChanged(qreal)));
@@ -639,6 +712,9 @@
setParent(containerWidget);
HbVkbHost::attachHost(this, containerWidget);
+ if (containerWidget) {
+ containerWidget->setFlag(QGraphicsItem::ItemSendsGeometryChanges);
+ }
connect(&d->mTimeLine, SIGNAL(finished()), this, SLOT(animationFinished()));
connect(&d->mTimeLine, SIGNAL(valueChanged(qreal)), this, SLOT(animValueChanged(qreal)));
@@ -650,6 +726,9 @@
setParent(containerWidget);
HbVkbHost::attachHost(this, containerWidget);
+ if (containerWidget) {
+ containerWidget->setFlag(QGraphicsItem::ItemSendsGeometryChanges);
+ }
connect(&d->mTimeLine, SIGNAL(finished()), this, SLOT(animationFinished()));
connect(&d->mTimeLine, SIGNAL(valueChanged(qreal)), this, SLOT(animValueChanged(qreal)));
@@ -701,10 +780,9 @@
d->mInputMethod = owner;
}
- if ((d->mKeypadStatus != HbVkbStatusMinimized) && (!vkb || !owner)) {
+ if (!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.
+ // all the needed parameters.
return;
}
@@ -717,6 +795,16 @@
return;
}
+ if (d->popupAnimationInProgress()) {
+ // The container is a popup and it is still running its opening animation.
+ // delay.
+ connect(d->mContainerWidget->widgetObject(), SIGNAL(popupReady()), this, SLOT(stateTransitionCompleted()));
+ d->mPendingCall.vkb = vkb;
+ d->mPendingCall.animationAllowed = animationAllowed;
+ d->mPendingCall.popupOpening = true;
+ return;
+ }
+
if (!d->mKeypadOperationOngoing) {
d->mKeypadOperationOngoing = true;
@@ -736,7 +824,7 @@
emit aboutToOpen();
if (d->mContainerWidget && d->mContainerWidget->widgetObject()) {
- d->mContainerWidget->widgetObject()->setProperty(KPositionManagedByVKB, true );
+ d->mContainerWidget->widgetObject()->setProperty(KPositionManagedByVKB, true);
}
if (animationAllowed) {
@@ -788,15 +876,16 @@
// Move the container.
if (d->mContainerWidget->widgetObject()) {
d->mContainerWidget->setPos(d->mContainerMovementStartingPoint + (d->mContainerMovementVector * value));
- }
- // Move keypad
- if (d->mKeypad) {
- d->mKeypad->setPos(d->mKeypadMovementStartingPoint + (d->mKeypadMovementVector * value));
+ // Move keypad
+ if (d->mKeypad) {
+ QPointF keypadPos = d->mKeypadMovementStartingPoint + (d->mKeypadMovementVector * value);
+ d->mKeypad->setPos(keypadPos);
+ }
}
}
- if (d->mCallback && d->mKeypad) {
+ if (d->mCallback) {
d->mCallback->keyboardAnimationFrame(HbVirtualKeyboard::HbVkbAnimOpen, value);
}
}
@@ -827,23 +916,28 @@
textEdit->ensureCursorVisible();
}
}
+ d->ensureVisibilityInsideScrollArea();
+ d->ensureVisibilityInsideVisibleArea();
// Make sure the keypad never steals focus.
d->mKeypad->setFlag(QGraphicsItem::ItemIsPanel, true);
- d->mKeypad->setActive(false);
+ if (d->mKeypad->isActive()) {
+ d->mKeypad->setActive(false);
+ }
emit keypadOpened();
- } else if (d->mKeypadStatus == HbVkbHost::HbVkbStatusMinimized) {
- d->mCallback->keyboardMinimized(this);
- emit keypadClosed();
} else {
// It was closed. Hide the keyboard.
d->mKeypad->hide();
// Return the container where it was.
d->mContainerWidget->setPos(d->mOriginalContainerPosition);
- d->mContainerWidget->widgetObject()->setProperty(KPositionManagedByVKB, false );
+ d->mContainerWidget->widgetObject()->setProperty(KPositionManagedByVKB, false);
d->mCallback->keyboardClosed(this);
emit keypadClosed();
- HbVkbHostBridge::instance()->connectHost(0);
+
+ // Keyboard might be opened again due to pending open call
+ if (d->mKeypadStatus == HbVkbHost::HbVkbStatusClosed) {
+ HbVkbHostBridge::instance()->connectHost(0);
+ }
}
}
}
@@ -907,8 +1001,7 @@
Q_D(HbAbstractVkbHost);
if ((d->mTimeLine.state() == QTimeLine::Running) ||
- (d->mKeypadStatus == HbVkbStatusClosed) ||
- (d->mKeypadStatus == HbVkbStatusMinimized) ||
+ (d->mKeypadStatus == HbVkbStatusClosed) ||
!d->mContainerWidget->widgetObject()) {
return;
}
@@ -926,15 +1019,11 @@
Q_D(const HbAbstractVkbHost);
HbMainWindow *mainWindow = d->mainWindow();
- if (d->mContainerWidget->widgetObject() && mainWindow && d->mCallback) {
+ if (d->mContainerWidget && d->mContainerWidget->widgetObject() && mainWindow && d->mCallback) {
QSizeF vpSize = d->screenSize();
QRectF viewport = QRectF(QPointF(0.0, 0.0), QPointF(vpSize.width(), vpSize.height()));
- if (d->mKeypadStatus == HbVkbStatusMinimized) {
- viewport.setHeight(viewport.height() - d->mCallback->minimizedKeyboardSize().height());
- } else {
- viewport.setHeight(viewport.height() - confirmedKeyboardSize().height());
- }
+ viewport.setHeight(viewport.height() - confirmedKeyboardSize().height());
return viewport;
}
@@ -949,7 +1038,7 @@
{
Q_D(const HbAbstractVkbHost);
- if (d->mCallback && d->mKeypad) {
+ if (d->mCallback) {
QSizeF kbArea = keyboardArea();
QSizeF confirmed = d->mCallback->preferredKeyboardSize();
@@ -990,8 +1079,7 @@
{
Q_D(const HbAbstractVkbHost);
- if (d->mKeypadStatus == HbVkbStatusOpened ||
- d->mKeypadStatus == HbVkbStatusMinimized) {
+ if (d->mKeypadStatus == HbVkbStatusOpened) {
return activeViewRect();
}
@@ -1001,55 +1089,6 @@
/*!
\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);
@@ -1057,23 +1096,12 @@
}
/*!
-This slot is called when active HbView changes.
+\deprecated HbAbstractVkbHost::currentViewChanged(HbView *view)
+ is deprecated.
*/
void HbAbstractVkbHost::currentViewChanged(HbView *view)
{
- Q_D(HbAbstractVkbHost);
-
- if (view != d->mContainerWidget->widgetObject()) {
- if (d->mTimeLine.state() == QTimeLine::Running) {
- d->cancelAnimationAndHideVkbWidget();
- if (d->mCallback) {
- d->mCallback->keyboardClosed(this);
- }
- } else if (d->mKeypadStatus != HbVkbStatusClosed) {
- d->closeKeypadWithoutAnimation();
- emit keypadClosed();
- }
- }
+ Q_UNUSED(view);
}
/*!
@@ -1110,7 +1138,11 @@
{
Q_D(HbAbstractVkbHost);
- disconnect(HbVkbHostBridge::instance(), SIGNAL(stateTransitionCompleted()), this, SLOT(stateTransitionCompleted()));
+ if (!d->mPendingCall.popupOpening) {
+ disconnect(HbVkbHostBridge::instance(), SIGNAL(stateTransitionCompleted()), this, SLOT(stateTransitionCompleted()));
+ } else {
+ disconnect(d->mContainerWidget->widgetObject(), SIGNAL(popupReady()), this, SLOT(stateTransitionCompleted()));
+ }
if (d->mPendingCall.vkb) {
// There was an open call pending. Do it now.
@@ -1120,4 +1152,26 @@
}
}
+/*!
+This slot is called when change in active HbView starts.
+*/
+void HbAbstractVkbHost::aboutToChangeView(HbView *oldView, HbView *newView)
+{
+ Q_D(HbAbstractVkbHost);
+
+ if (oldView != newView) {
+ if (d->mTimeLine.state() == QTimeLine::Running) {
+ d->cancelAnimationAndHideVkbWidget();
+ if (d->mCallback) {
+ d->mCallback->keyboardClosed(this);
+ }
+ } else if (d->mKeypadStatus != HbVkbStatusClosed) {
+ d->closeKeypadWithoutAnimation();
+ emit keypadClosed();
+ }
+ }
+}
+
+#include "moc_hbabstractvkbhost.cpp"
+
// End of file