src/hbcore/vkbhosts/hbabstractvkbhost.cpp
changeset 28 b7da29130b0e
parent 23 e6ad4ef83b23
child 30 80e4d18b72f5
--- a/src/hbcore/vkbhosts/hbabstractvkbhost.cpp	Thu Sep 02 20:44:51 2010 +0300
+++ b/src/hbcore/vkbhosts/hbabstractvkbhost.cpp	Fri Sep 17 08:32:10 2010 +0300
@@ -22,8 +22,10 @@
 ** Nokia at developer.feedback@nokia.com.
 **
 ****************************************************************************/
+
 #include "hbabstractvkbhost.h"
 #include "hbabstractvkbhost_p.h"
+#include "private/hbvkbgeometrylogic_p.h"
 #include "hbinputvirtualkeyboard.h"
 #include "hbinputsettingproxy.h"
 #include "hbinputvkbhostbridge.h"
@@ -38,14 +40,8 @@
 #include <QTextEdit>
 
 const int HbAnimationTime = 200;
-const qreal HbEditorExtraMargin = 17.0;
-const qreal HbCursorLineMargin = 5.0;
-const qreal HbContainerBorderMargin = 20.0;
 const qreal HbHeightVerticalFactor = 0.5;
 const qreal HbHeightHorizFactor = 0.7;
-//Marginal value of the keypad height
-const qreal HbHeightMarginFactor = 0.6;
-const qreal HbDeltaHeight = 3.0;
 
 const QString KHandWritingName("Handwriting");
 // see hbpopup.cpp for this
@@ -218,137 +214,64 @@
     mScreenSize = screenSize();
 }
 
-bool HbAbstractVkbHostPrivate::prepareContainerAnimation(HbVkbHost::HbVkbStatus status)
-{
-    if (!mKeypad || !mContainerWidget->widgetObject() || !mInputMethod || !mInputMethod->focusObject()) {
+// TODO: could be in vkb geometry engine
+bool HbAbstractVkbHostPrivate::getViewAndFocusObjects(HbView*& currentView, HbInputFocusObject*& focusObject)
+{    
+    if (!mKeypad || !mInputMethod || !mContainerWidget ) {
+        return false;
+    }
+
+    HbMainWindow* window = mainWindow();
+    if (!window) {
+        return false;
+    }
+
+    currentView = window->currentView();
+    if (!currentView) {
+        return false;
+    }
+
+    focusObject = mInputMethod->focusObject();
+    if (!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());
-        // adjust the container position such that the focused object is always visible. This is required in some cases 
-        // where the actual visible area is very less when the keypad is opened. The cotainer position is automatically adjusted when
-        // the keypad height to screen height ratio exceeds the marginal height value HbHeightMarginFactor. By doing this, we can make
-        // sure that some space available for displaying popups like exactword popup in some input methods        
-        bool adjustContainer = (q_ptr->confirmedKeyboardSize().height() >
-            (mScreenSize.height() * HbHeightMarginFactor))? true : false;
-        // Find out the container area.
-        QRectF containerArea = mContainerWidget->sceneBoundingRect();
-        containerArea.adjust(0.0, -HbContainerBorderMargin, 0.0, HbContainerBorderMargin);
-
-        HbMainWindow *mainWin = mainWindow();
-        HbView *currentView = mainWin ? mainWin->currentView() : 0;
-
-        if (!currentView) {
-            return false;
-        }
-        // check whether the title and status bars are hidden or not
-        bool isTitleOrStatusBarVisible = currentView->isItemVisible(
-            Hb::TitleBarItem) | currentView->isItemVisible(Hb::StatusBarItem);
+    return true;
+}
 
-        // move the container up when hiding the title and status bars
-        if (isTitleOrStatusBarVisible) {
-            mContainerMovementVector.setY(visibleArea.top() - currentView->sceneBoundingRect().top());          
-        }
-
-        if (visibleArea.contains(containerArea)) {
-            // The whole container is already inside the visible area, nothing to do.
-            return false;
-        }
-
-        // If it isn't in the visible area yet but fits there. Let's move it there.
-        if (visibleArea.height() >= containerArea.height()) {
-            // calculate the new container area after hiding the bars
-            containerArea.translate(mContainerMovementVector);
-
-            if (adjustContainer) {
-                adjustContainerPosition();
-            } else {
-                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);
-
-        // calculate the new editor position after hiding the title bars        
-        editorGeometry.translate(mContainerMovementVector);
+bool HbAbstractVkbHostPrivate::prepareContainerAnimation(HbVkbHost::HbVkbStatus status)
+{
+    // Init and check main objects
+    HbView* currentView = NULL;
+    HbInputFocusObject* focusObject = NULL;
+    if (!getViewAndFocusObjects(currentView, focusObject)) {
+        return false;
+    }
 
-        // 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()) {
-                // first check whether the microfocus rectangle is inside the visible area. In case of
-                // text or multiline editors, dont change the editor position if cursor is in visible area                
-                if (adjustContainer) {
-                    if (adjustContainerPosition()) {
-                        return true;
-                    }
-                }
-                // 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);
+    // Init parameters before calling...
+    QSizeF keypadSize = mKeypad->size();
+    QRectF viewRect = currentView->sceneBoundingRect();
+    bool vkbOpen = mKeypadStatus == HbVkbHost::HbVkbStatusOpened;
+    bool titlebarVisible = currentView->isItemVisible(Hb::TitleBarItem);
+    bool statusbarVisible = currentView->isItemVisible(Hb::StatusBarItem);
+    QRectF containerRect = mContainerWidget->sceneBoundingRect();
+    QRectF editorRect = focusObject->editorGeometry();
+    QRectF cursorRect = focusObject->microFocus();
 
-        // calculate the new cursor position after hiding the title bars
-        microFocus.translate(mContainerMovementVector);
-            
-        // 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, visibleArea.top() - microFocus.top());
-                }
-            } else {
-                mContainerMovementVector += QPointF(0.0, visibleArea.bottom() - microFocus.bottom());
-            }       
-            return true;
-        }
-        if (adjustContainer && adjustContainerPosition()) {
-           return true;
-        }          
-    } else {
-        // It is going to be closed or minimized.
-        mContainerMovementVector = mOriginalContainerPosition - mContainerMovementStartingPoint;
-        return true;
+    if (status == HbVkbHost::HbVkbStatusOpened) {
+        // Initialize geometry calculation unit to handle all geometry calculations.
+        HbVkbGeometryLogicPrivate unit = HbVkbGeometryLogicPrivate(
+                mScreenSize,
+                keypadSize,
+                viewRect,
+                vkbOpen,
+                titlebarVisible,
+                statusbarVisible,
+                containerRect,
+                editorRect,
+                cursorRect);
+
+        return unit.calculateContainerMovement( mContainerMovementVector );
     }
 
     return false;
@@ -409,7 +332,7 @@
     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 *)));
     }
 }
 
@@ -422,7 +345,7 @@
     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 *)));
     }
 }
 
@@ -679,9 +602,12 @@
     }
 
     HbMainWindow *mainWin = mainWindow();
-    HbView *currentView;
+    if (!mainWin) {
+        return;
+    }
 
-    if (mainWin && (currentView = mainWin->currentView())) {
+    HbView *currentView = mainWin->currentView();
+    if (currentView) {
         HbView::HbViewFlags flags = currentView->viewFlags();
 
         HbView::HbViewFlags setFlags = HbView::ViewFlagNone;
@@ -716,34 +642,6 @@
     }
 }
 
-bool HbAbstractVkbHostPrivate::adjustContainerPosition()
-{
-    bool result = false;
-    if (!mInputMethod || !mInputMethod->focusObject()) {
-        return result;
-    }
-    // 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());
-    QRectF microFocus = mInputMethod->focusObject()->microFocus();
-    microFocus.adjust(0.0, -HbEditorExtraMargin, 0.0, HbEditorExtraMargin);
-
-    // calculate the new cursor position after moving it to the visible area
-    QRectF newCursorRect = microFocus.translated(mContainerMovementVector);
-    if (visibleArea.contains(newCursorRect)) {
-        qreal topArea = newCursorRect.top() - visibleArea.top() - HbDeltaHeight;
-        qreal bottomArea = visibleArea.bottom() - newCursorRect.bottom() - HbDeltaHeight;
-        if (topArea > 0 && bottomArea > 0) {
-            if (topArea >= bottomArea) {
-                mContainerMovementVector += QPointF(0.0, bottomArea);
-            } else {
-                mContainerMovementVector += QPointF(0.0, -topArea);
-            }
-        }
-        result = true;  
-    }
-    return result;
-}
-
 /// @endcond
 
 
@@ -753,6 +651,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)));
@@ -775,6 +676,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)));
@@ -786,6 +690,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)));
@@ -966,7 +873,9 @@
 
             // 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);
@@ -979,7 +888,11 @@
             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);
+            }
         }
     }
 }
@@ -1199,19 +1112,8 @@
 */
 void HbAbstractVkbHost::currentViewChanged(HbView *view)
 {
-    Q_D(HbAbstractVkbHost);
+    Q_UNUSED(view);
 
-    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();
-        }
-    }
 }
 
 /*!
@@ -1257,5 +1159,23 @@
         openKeypad(vkb, d->mInputMethod, d->mPendingCall.animationAllowed);
     }
 }
+/*!
+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();
+        }
+    }
+}
 // End of file