src/hbcore/vkbhosts/hbabstractvkbhost.cpp
changeset 34 ed14f46c0e55
parent 6 c3690ec91ef8
equal deleted inserted replaced
31:7516d6d86cf5 34:ed14f46c0e55
    20 **
    20 **
    21 ** If you have questions regarding the use of this file, please contact
    21 ** If you have questions regarding the use of this file, please contact
    22 ** Nokia at developer.feedback@nokia.com.
    22 ** Nokia at developer.feedback@nokia.com.
    23 **
    23 **
    24 ****************************************************************************/
    24 ****************************************************************************/
       
    25 
    25 #include "hbabstractvkbhost.h"
    26 #include "hbabstractvkbhost.h"
    26 #include "hbabstractvkbhost_p.h"
    27 #include "hbabstractvkbhost_p.h"
       
    28 #include "private/hbvkbgeometrylogic_p.h"
       
    29 #include "hbvkbhostcontainerwidget_p.h"
    27 #include "hbinputvirtualkeyboard.h"
    30 #include "hbinputvirtualkeyboard.h"
    28 #include "hbinputsettingproxy.h"
    31 #include "hbinputsettingproxy.h"
    29 #include "hbinputvkbhostbridge.h"
    32 #include "hbinputvkbhostbridge.h"
       
    33 #include "hbvkbconstants_p.h"
       
    34 #include "hbwidgetfeedback.h"
    30 #include "hbinputmethod.h"
    35 #include "hbinputmethod.h"
    31 #include "hbdeviceprofile.h"
    36 #include "hbdeviceprofile.h"
       
    37 #include "hbscrollarea.h"
    32 #include "hbmainwindow.h"
    38 #include "hbmainwindow.h"
       
    39 #include "hbpopup_p.h"
    33 #include "hbpopup.h"
    40 #include "hbpopup.h"
    34 #include "hbview.h"
    41 #include "hbview.h"
    35 #include "hbwidgetfeedback.h"
       
    36 #include "hbinstance.h"
    42 #include "hbinstance.h"
    37 
    43 
    38 #include <QTextEdit>
    44 #include <QTextEdit>
    39 
    45 
    40 const int HbAnimationTime = 200;
       
    41 const qreal HbEditorExtraMargin = 5.0;
       
    42 const qreal HbCursorLineMargin = 15.0;
       
    43 const qreal HbContainerBorderMargin = 20.0;
       
    44 const qreal HbHeightVerticalFactor = 0.5;
       
    45 const qreal HbHeightHorizFactor = 0.7;
       
    46 const QString KHandWritingName("Handwriting");
    46 const QString KHandWritingName("Handwriting");
    47 // see hbpopup.cpp for this
    47 // see hbpopup.cpp for this
    48 extern const char* KPositionManagedByVKB;
    48 extern const char* KPositionManagedByVKB;
    49 
    49 
    50 /// @cond
    50 /*!
    51 
    51 @stable
    52 HbVkbHostContainerWidget::HbVkbHostContainerWidget(QObject *containterWidget)
    52 @hbcore
    53     : mContainerWidget(containterWidget)
       
    54 {
       
    55 }
       
    56 
       
    57 // sets container widgets position to new position.
       
    58 void HbVkbHostContainerWidget::setPos(QPointF newPosition)
       
    59 {
       
    60     if (mContainerWidget) {
       
    61         QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(mContainerWidget);
       
    62         if (graphicsObject) {
       
    63             graphicsObject->setPos(newPosition);
       
    64             return;
       
    65         }
       
    66 
       
    67         QWidget *qWidget = qobject_cast<QWidget *>(mContainerWidget);
       
    68         if (qWidget) {
       
    69 #ifdef Q_WS_WIN
       
    70             QPoint finalPosition = newPosition.toPoint();
       
    71             finalPosition -= qWidget->geometry().topLeft() - qWidget->frameGeometry().topLeft();
       
    72             qWidget->move(finalPosition);
       
    73 #else
       
    74             qWidget->move(newPosition.toPoint());
       
    75 #endif
       
    76             return;
       
    77         }
       
    78     }
       
    79 }
       
    80 
       
    81 // returns the global position, if container widget is a QGraphicsObject, it returns
       
    82 // scene position. In case the widget is QWidget it returns global co-ordinates
       
    83 QPointF HbVkbHostContainerWidget::pos()
       
    84 {
       
    85     if (mContainerWidget) {
       
    86         QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(mContainerWidget);
       
    87         if (graphicsObject) {
       
    88             return graphicsObject->pos();;
       
    89         }
       
    90 
       
    91         QWidget *qWidget = qobject_cast<QWidget *>(mContainerWidget);
       
    92         if (qWidget) {
       
    93             return qWidget->mapToGlobal(QPoint(0, 0));
       
    94         }
       
    95     }
       
    96 
       
    97     return QPointF(0, 0);
       
    98 }
       
    99 
       
   100 // returns the bounding rect in global co-ordinate, if container widget is a QGraphicsObject
       
   101 // it returns in scene co-ordinate, incase widget is QWidget it returns in global co-ordinate
       
   102 QRectF HbVkbHostContainerWidget::sceneBoundingRect()
       
   103 {
       
   104     if (mContainerWidget) {
       
   105         QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(mContainerWidget);
       
   106         if (graphicsObject) {
       
   107             return graphicsObject->sceneBoundingRect();;
       
   108         }
       
   109 
       
   110         QWidget *qWidget = qobject_cast<QWidget *>(mContainerWidget);
       
   111         if (qWidget) {
       
   112             return QRectF(qWidget->mapToGlobal(QPoint(0, 0)), qWidget->size());
       
   113         }
       
   114     }
       
   115 
       
   116     return QRectF(0, 0, 0, 0);
       
   117 }
       
   118 
       
   119 // connect container specific signals here.
       
   120 void HbVkbHostContainerWidget::connectSignals(QObject *receiver)
       
   121 {
       
   122     if (qobject_cast<QGraphicsObject *> (mContainerWidget)) {
       
   123         QObject::connect(mContainerWidget, SIGNAL(yChanged()),
       
   124                          receiver, SLOT(ensureCursorVisibility()));
       
   125     }
       
   126 
       
   127     HbPopup *popup = qobject_cast<HbPopup *>(mContainerWidget);
       
   128     if (popup) {
       
   129         QObject::connect(popup, SIGNAL(aboutToHide()), receiver, SLOT(containerAboutToClose()));
       
   130     }
       
   131 
       
   132     HbView *view = qobject_cast<HbView *>(mContainerWidget);
       
   133     if (view) {
       
   134         QObject::connect(view->mainWindow(), SIGNAL(currentViewChanged(HbView *)),
       
   135                          receiver, SLOT(currentViewChanged(HbView *)));
       
   136     }
       
   137 }
       
   138 
       
   139 // disconnect container specific signals here.
       
   140 void HbVkbHostContainerWidget::disconnectSignals(QObject *receiver)
       
   141 {
       
   142     if (qobject_cast<QGraphicsObject *> (mContainerWidget)) {
       
   143         QObject::disconnect(mContainerWidget, SIGNAL(yChanged()),
       
   144                             receiver, SLOT(ensureCursorVisibility()));
       
   145     }
       
   146 
       
   147     HbPopup *popup = qobject_cast<HbPopup *>(mContainerWidget);
       
   148     if (popup) {
       
   149         QObject::disconnect(popup, SIGNAL(aboutToHide()), receiver, SLOT(containerAboutToClose()));
       
   150     }
       
   151 
       
   152     HbPopup *view = qobject_cast<HbPopup *>(mContainerWidget);
       
   153     if (view) {
       
   154         QObject::disconnect(view->mainWindow(), SIGNAL(currentViewChanged(HbView *)),
       
   155                             receiver, SLOT(currentViewChanged(HbView *)));
       
   156     }
       
   157 }
       
   158 
       
   159 /// @endcond
       
   160 
       
   161 /*!
       
   162 \proto
       
   163 \class HbAbstractVkbHost
    53 \class HbAbstractVkbHost
   164 \brief Base class for HbCore's virtual keyboard hosts.
    54 \brief The default virtual keyboard host
   165 
    55 
   166 This class contains common code for HbCore's virtual keyboard hosts.
    56 This class implements the default virtual keyboard host. A virtual keyboard
   167 */
    57 host is responsible for the interaction between application background
   168 
    58 and the virtual keyboard widget when a virtual keyboard becomes visible.
   169 /// @cond
    59 
       
    60 Its main task is to guarantee that editor's cursor line remains visible
       
    61 and that the virtual keyboard widget doesn't cover it.
       
    62 
       
    63 The abstract vkb host does this by moving the editor container around in suitable way.
       
    64 
       
    65 See \ref vkbHandling "virtual keyboard handling guide" for more information
       
    66 
       
    67 \sa HbVkbHost
       
    68 \sa HbShrinkingVkbHost
       
    69 \sa HbStaticVkbHost
       
    70 */
   170 
    71 
   171 HbAbstractVkbHostPrivate::HbAbstractVkbHostPrivate(HbAbstractVkbHost *myHost, QObject *containerWidget)
    72 HbAbstractVkbHostPrivate::HbAbstractVkbHostPrivate(HbAbstractVkbHost *myHost, QObject *containerWidget)
   172     : q_ptr(myHost),
    73     : q_ptr(myHost),
   173       mCallback(0),
    74       mCallback(0),
   174       mKeypad(0),
    75       mKeypad(0),
   175       mContainerWidget(new HbVkbHostContainerWidget(containerWidget)),
    76       mContainerWidget(new HbVkbHostContainerWidget(containerWidget)),
   176       mTimeLine(HbAnimationTime),
    77       mTimeLine(HbVkbAnimationTime),
   177       mKeypadStatus(HbVkbHost::HbVkbStatusClosed),
    78       mKeypadStatus(HbVkbHost::HbVkbStatusClosed),
   178       mKeypadOperationOngoing(false),
    79       mKeypadOperationOngoing(false),
   179       mOriginalContainerPosition(QPointF(0, 0)),
    80       mOriginalContainerPosition(QPointF(0, 0)),
   180       mContainerMovementStartingPoint(QPointF(0, 0)),
    81       mContainerMovementStartingPoint(QPointF(0, 0)),
   181       mContainerMovementVector(QPointF(0, 0)),
    82       mContainerMovementVector(QPointF(0, 0)),
   182       mKeypadMovementStartingPoint(QPointF(0, 0)),
    83       mKeypadMovementStartingPoint(QPointF(0, 0)),
   183       mKeypadMovementVector(QPointF(0, 0)),
    84       mKeypadMovementVector(QPointF(0, 0)),
   184       mInputMethod(0),
    85       mInputMethod(0),
   185       mKeypadStatusBeforeOrientationChange(HbVkbHost::HbVkbStatusClosed)
    86       mKeypadStatusBeforeOrientationChange(HbVkbHost::HbVkbStatusClosed),
       
    87       mTitleBarHiddenByVkbHost(false),
       
    88       mStatusBarHiddenByVkbHost(false),
       
    89       mMarginInPixels(0)
   186 {
    90 {
   187     mTimeLine.setUpdateInterval(16);
    91     mTimeLine.setUpdateInterval(16);
       
    92     mMarginInPixels = HbDeviceProfile::current().unitValue() * HbVkbHostMargin;
   188 }
    93 }
   189 
    94 
   190 HbAbstractVkbHostPrivate::~HbAbstractVkbHostPrivate()
    95 HbAbstractVkbHostPrivate::~HbAbstractVkbHostPrivate()
   191 {
    96 {
   192     delete mContainerWidget;
    97     delete mContainerWidget;
   193 }
    98 }
   194 
    99 
       
   100 /*!
       
   101 \internal
       
   102 Initializes starting values to parameters needed for running the keypad and
       
   103 container widget animation effects.
       
   104 */
   195 void HbAbstractVkbHostPrivate::prepareAnimationsCommon()
   105 void HbAbstractVkbHostPrivate::prepareAnimationsCommon()
   196 {
   106 {
   197     if (mContainerWidget->widgetObject() && mKeypad) {
   107     // Initialize movement variables to starting values. These will
       
   108     // be fine tuned later.
       
   109     mKeypadMovementVector = QPointF(0, 0);
       
   110     mContainerMovementVector = QPointF(0, 0);
       
   111     mContainerMovementStartingPoint = QPointF();
       
   112     mKeypadMovementStartingPoint = QPointF();
       
   113     mScrollAreaRect = QRectF();
       
   114 
       
   115     if (mContainerWidget && mContainerWidget->widgetObject() && mKeypad) {
   198         // If the keyboard is not already open, remember the original position.
   116         // If the keyboard is not already open, remember the original position.
   199         // That is where the container will eventually be returned to.
   117         // That is where the container will eventually be returned to.
   200         if (mKeypadStatus == HbVkbHost::HbVkbStatusClosed) {
   118         if (mKeypadStatus == HbVkbHost::HbVkbStatusClosed) {
   201             mOriginalContainerPosition = mContainerWidget->pos();
   119             mOriginalContainerPosition = mContainerWidget->pos();
   202         }
   120         }
   203 
   121 
   204         // Initialize movement variables to starting values. These will
       
   205         // be fine tuned later.
       
   206         mKeypadMovementVector = QPointF(0, 0);
       
   207         mContainerMovementVector = QPointF(0, 0);
       
   208         mContainerMovementStartingPoint = mContainerWidget->pos();
   122         mContainerMovementStartingPoint = mContainerWidget->pos();
   209         mKeypadMovementStartingPoint = mKeypad->pos();
   123         mKeypadMovementStartingPoint = mKeypad->pos();
   210     }
   124     }
   211 
   125 
   212     mScreenSize = screenSize();
   126     mScreenSize = screenSize();
   213 }
   127 
   214 
   128     // Make sure that the editor is completely visible inside a scroll area.
       
   129     ensureVisibilityInsideScrollArea();
       
   130 }
       
   131 
       
   132 /*!
       
   133 \internal
       
   134 Sets up view and focus object variables.
       
   135 */
       
   136 bool HbAbstractVkbHostPrivate::getViewAndFocusObjects(HbView*& currentView, HbInputFocusObject*& focusObject)
       
   137 {
       
   138     if (!mKeypad || !mInputMethod || !mContainerWidget ) {
       
   139         return false;
       
   140     }
       
   141 
       
   142     HbMainWindow* window = mainWindow();
       
   143     if (!window) {
       
   144         return false;
       
   145     }
       
   146 
       
   147     // Update margin pixel value while you're at it.
       
   148     mMarginInPixels = HbDeviceProfile::profile(window).unitValue() * HbVkbHostMargin;
       
   149 
       
   150     currentView = window->currentView();
       
   151     if (!currentView) {
       
   152         return false;
       
   153     }
       
   154 
       
   155     focusObject = mInputMethod->focusObject();
       
   156     if (!focusObject) {
       
   157         return false;
       
   158     }
       
   159 
       
   160     return true;
       
   161 }
       
   162 
       
   163 /*!
       
   164 \internal
       
   165 Sets up the container widget animation effect.
       
   166 */
   215 bool HbAbstractVkbHostPrivate::prepareContainerAnimation(HbVkbHost::HbVkbStatus status)
   167 bool HbAbstractVkbHostPrivate::prepareContainerAnimation(HbVkbHost::HbVkbStatus status)
   216 {
   168 {
   217     if (!mKeypad || !mContainerWidget->widgetObject() || !mInputMethod || !mInputMethod->focusObject()) {
   169     // Init and check main objects
       
   170     HbView* currentView = 0;
       
   171     HbInputFocusObject* focusObject = 0;
       
   172     if (!getViewAndFocusObjects(currentView, focusObject)) {
   218         return false;
   173         return false;
   219     }
   174     }
   220 
   175 
       
   176     bool result = false;
       
   177 
   221     if (status == HbVkbHost::HbVkbStatusOpened) {
   178     if (status == HbVkbHost::HbVkbStatusOpened) {
   222         // Calculate the area that remains visible when the keypad is open.
   179         // Init parameters before calling.
   223         QRectF visibleArea = QRectF(0.0, 0.0, mScreenSize.width(), mScreenSize.height() - mKeypad->size().height());
   180         QSizeF keypadSize = mKeypad->size();
   224 
   181         QRectF viewRect = currentView->sceneBoundingRect();
   225         // Find out the container area.
   182         bool isPopupType = qobject_cast<HbPopup *>(mContainerWidget->widgetObject()) != 0;
   226         QRectF containerArea = mContainerWidget->sceneBoundingRect();
   183         bool vkbOpen = mKeypadStatus == HbVkbHost::HbVkbStatusOpened;
   227         containerArea.adjust(0.0, -HbContainerBorderMargin, 0.0, HbContainerBorderMargin);
   184         QRectF containerRect = mContainerWidget->sceneBoundingRect();
   228 
   185         QRectF editorRect = findEditorRect(focusObject);
   229         if (visibleArea.contains(containerArea)) {
   186         QRectF cursorRect = focusObject->microFocus();
   230             // The whole container is already inside the visible area, nothing to do.
   187         QPointF fixedMovement = mContainerWidget->fixedContainerMovement();
   231             return false;
   188 
   232         }
   189         // We know that the container will be moved at least the amount of
   233 
   190         // fixed movement vector (which typically, if non-zero, is the
   234         if (visibleArea.height() >= containerArea.height()) {
   191         // height of the title bar). So we reduce the keypad area
   235             // It isn't in the visible area yet but fits there. Let's move it there.
   192         // to make the calculations match (fixed movement points
   236             mContainerMovementVector = QPointF(0.0, visibleArea.bottom() - containerArea.bottom());
   193         // to negative direction, that's why addition).
       
   194         if (!vkbOpen) {
       
   195             keypadSize.setHeight(keypadSize.height() + fixedMovement.y());
       
   196         }
       
   197 
       
   198         // Initialize geometry calculation unit to handle all geometry calculations.
       
   199         HbVkbGeometryLogicPrivate unit = HbVkbGeometryLogicPrivate(
       
   200                 mScreenSize,
       
   201                 keypadSize,
       
   202                 viewRect,
       
   203                 isPopupType,
       
   204                 vkbOpen,
       
   205                 containerRect,
       
   206                 editorRect,
       
   207                 cursorRect,
       
   208                 mMarginInPixels);
       
   209 
       
   210         result = unit.calculateContainerMovement(mContainerMovementVector);
       
   211         if (!vkbOpen) {
       
   212             // Apply fixed movement only if the keyboard is not already open.
       
   213             // Fixed movement is used for hiding the title bar.
       
   214             mContainerMovementVector = selectLongestVerticalVector(fixedMovement, mContainerMovementVector);
       
   215         }
       
   216     } else if (status == HbVkbHost::HbVkbStatusClosed) {
       
   217         if (mContainerMovementStartingPoint != mOriginalContainerPosition) {
       
   218            mContainerMovementVector = mOriginalContainerPosition - mContainerMovementStartingPoint;
       
   219            result = true;
       
   220         }
       
   221     }
       
   222 
       
   223     return result;
       
   224 }
       
   225 
       
   226 /*!
       
   227 \internal
       
   228 Sets up the keypad widget animation effect.
       
   229 */
       
   230 bool HbAbstractVkbHostPrivate::prepareKeypadAnimation(HbVkbHost::HbVkbStatus status)
       
   231 {
       
   232     if (mKeypad) {
       
   233         if (status == HbVkbHost::HbVkbStatusOpened) {
       
   234             if (mKeypadStatus == HbVkbHost::HbVkbStatusClosed) {
       
   235                 // Set up keyboard open animation.
       
   236                 mKeypadMovementStartingPoint.setY(mScreenSize.height());
       
   237                 mKeypadMovementVector.setY(-mKeypad->size().height());
       
   238                 if (!disableCursorShift()) {
       
   239                     // Initialize keypad position
       
   240                     mKeypad->setPos(mKeypadMovementStartingPoint);
       
   241                 }
       
   242                 return true;
       
   243             }
       
   244         } else {
       
   245             // It is going to be closed.
       
   246             mKeypadMovementVector = QPointF(0, mKeypad->size().height());
   237             return true;
   247             return true;
   238         }
   248         }
   239 
       
   240         // Find out the editor bounding box and add a small margin to height.
       
   241         QRectF editorGeometry = mInputMethod->focusObject()->editorGeometry();
       
   242         editorGeometry.adjust(0.0, -HbCursorLineMargin, 0.0, HbCursorLineMargin);
       
   243 
       
   244         // Then see if the editor is already inside the visible area.
       
   245         // If it isn't, see if it would fit there.
       
   246         if (!visibleArea.contains(editorGeometry)) {
       
   247             if (editorGeometry.width() <= visibleArea.width() &&
       
   248                 editorGeometry.height() <= visibleArea.height()) {
       
   249                 // Yes, it fits into visible area, let's move it there so that
       
   250                 // the whole editor area is in use right away.
       
   251                 // First check if we want to move it to upper or lower
       
   252                 // part of the visible area.
       
   253                 if (editorGeometry.top() <= visibleArea.top()) {
       
   254                     // It goes to the upper part of the visible area.
       
   255                     mContainerMovementVector = QPointF(0.0, -editorGeometry.top());
       
   256                 } else {
       
   257                     mContainerMovementVector = QPointF(0.0, visibleArea.bottom() - editorGeometry.bottom());
       
   258                 }
       
   259 
       
   260                 return true;
       
   261             }
       
   262         }
       
   263 
       
   264         // The editor is either already inside the visible area or doesn't fit there.
       
   265         // Let's see if the cursor is visble.
       
   266         // First find out micro focus rectangle and increase the height by a small margin.
       
   267         QRectF microFocus = mInputMethod->focusObject()->microFocus();
       
   268         microFocus.setTop(microFocus.top() - HbEditorExtraMargin);
       
   269         microFocus.setBottom(microFocus.bottom() + HbEditorExtraMargin);
       
   270 
       
   271         // Check whether the cursor rectangle is inside visible area.
       
   272         if (!visibleArea.contains(microFocus)) {
       
   273             QRectF realEditorGeometry = editorGeometry;
       
   274             realEditorGeometry.adjust(0.0, HbCursorLineMargin, 0.0, -HbCursorLineMargin);
       
   275             if (!realEditorGeometry.contains(microFocus)) {
       
   276                 // A sanity check. If the microFocus rectangle is outside the editor
       
   277                 // bounding rect, don't do anything. The situation in editor widget is not
       
   278                 // up to date.
       
   279                 return false;
       
   280             }
       
   281             // The cursor is outside the visible area. Figure out how much and
       
   282             // to which direction the container has to be moved.
       
   283             if (microFocus.bottom() <= visibleArea.top()) {
       
   284                 // First see what would happen if we returned the container to original position.
       
   285                 // Is the cursor visible then?
       
   286                 // This is always preferred, use it if possible.
       
   287                 QPointF toOriginalPos = mOriginalContainerPosition - mContainerWidget->pos();
       
   288                 QRectF translatedMicroFocus = microFocus.translated(toOriginalPos);
       
   289                 if (visibleArea.contains(translatedMicroFocus)) {
       
   290                     mContainerMovementVector = toOriginalPos;
       
   291                 } else {
       
   292                     // It goes to the upper part of the visible area.
       
   293                     mContainerMovementVector = QPointF(0.0, HbCursorLineMargin - microFocus.top());
       
   294                 }
       
   295             } else {
       
   296                 mContainerMovementVector = QPointF(0.0, visibleArea.bottom() - HbCursorLineMargin - microFocus.bottom());
       
   297             }
       
   298 
       
   299             return true;
       
   300         }
       
   301     } else {
       
   302         // It is going to be closed or minimized.
       
   303         mContainerMovementVector = mOriginalContainerPosition - mContainerMovementStartingPoint;
       
   304         return true;
       
   305     }
   249     }
   306 
   250 
   307     return false;
   251     return false;
   308 }
   252 }
   309 
   253 
   310 bool HbAbstractVkbHostPrivate::prepareKeypadAnimation(HbVkbHost::HbVkbStatus status)
   254 /*!
   311 {
   255 \internal
   312     if (status == HbVkbHost::HbVkbStatusOpened) {
   256 Sets up all the animation effects.
   313         if (mKeypadStatus == HbVkbHost::HbVkbStatusClosed) {
   257 */
   314             // Set up keyboard open animation.
       
   315             mKeypadMovementStartingPoint.setY(mScreenSize.height());
       
   316             mKeypadMovementVector.setY(-mKeypad->size().height());
       
   317             if (!disableCursorShift()) {
       
   318                 // Initialize keypad position
       
   319                 mKeypad->setPos(mKeypadMovementStartingPoint);
       
   320             }
       
   321             return true;
       
   322         } else if (mKeypadStatus == HbVkbHost::HbVkbStatusMinimized && mCallback) {
       
   323             mKeypadMovementVector.setY(-(mKeypad->size().height() - mCallback->minimizedKeyboardSize().height()));
       
   324             return true;
       
   325         }
       
   326     } else if (status == HbVkbHost::HbVkbStatusMinimized && mCallback) {
       
   327         mKeypadMovementVector = QPointF(0, mKeypad->size().height() - mCallback->minimizedKeyboardSize().height());
       
   328         return true;
       
   329     } else {
       
   330         // It is going to be closed.
       
   331         mKeypadMovementVector = QPointF(0, mKeypad->size().height());
       
   332         return true;
       
   333     }
       
   334 
       
   335     return false;
       
   336 }
       
   337 
       
   338 bool HbAbstractVkbHostPrivate::prepareAnimations(HbVkbHost::HbVkbStatus status)
   258 bool HbAbstractVkbHostPrivate::prepareAnimations(HbVkbHost::HbVkbStatus status)
   339 {
   259 {
   340     prepareAnimationsCommon();
   260     prepareAnimationsCommon();
   341 
   261 
   342     bool containerResult = prepareContainerAnimation(status);
   262     bool containerResult = prepareContainerAnimation(status);
   351     }
   271     }
   352 
   272 
   353     return (containerResult | prepareKeypadAnimation(status));
   273     return (containerResult | prepareKeypadAnimation(status));
   354 }
   274 }
   355 
   275 
       
   276 /*!
       
   277 \internal
       
   278 Connects orientation change, view switching and possible other related signals.
       
   279 */
   356 void HbAbstractVkbHostPrivate::connectSignals()
   280 void HbAbstractVkbHostPrivate::connectSignals()
   357 {
   281 {
   358     mContainerWidget->connectSignals(q_ptr);
   282     mContainerWidget->connectSignals(q_ptr);
   359 
   283 
   360     // global signal not specific to any containter widget, can be connected now.
   284     // global signal not specific to any containter widget, can be connected now.
   361     HbMainWindow *mainWindow = this->mainWindow();
   285     HbMainWindow *mainWindow = this->mainWindow();
   362     if (mainWindow) {
   286     if (mainWindow) {
   363         q_ptr->connect(mainWindow, SIGNAL(aboutToChangeOrientation()), q_ptr, SLOT(orientationAboutToChange()));
   287         q_ptr->connect(mainWindow, SIGNAL(aboutToChangeOrientation()), q_ptr, SLOT(orientationAboutToChange()));
   364         q_ptr->connect(mainWindow, SIGNAL(orientationChanged(Qt::Orientation)), q_ptr, SLOT(orientationChanged(Qt::Orientation)));
   288         q_ptr->connect(mainWindow, SIGNAL(orientationChanged(Qt::Orientation)), q_ptr, SLOT(orientationChanged(Qt::Orientation)));
   365         q_ptr->connect(mainWindow, SIGNAL(currentViewChanged(HbView *)), q_ptr, SLOT(currentViewChanged(HbView *)));
   289         q_ptr->connect(mainWindow, SIGNAL(aboutToChangeView(HbView *, HbView *)), q_ptr, SLOT(aboutToChangeView(HbView *, HbView *)));
   366     }
   290     }
   367 }
   291 }
   368 
   292 
       
   293 /*!
       
   294 \internal
       
   295 Disconnects orientation change, view switching and possible other related signals.
       
   296 */
   369 void HbAbstractVkbHostPrivate::disconnectSignals()
   297 void HbAbstractVkbHostPrivate::disconnectSignals()
   370 {
   298 {
   371     mContainerWidget->disconnectSignals(q_ptr);
   299     mContainerWidget->disconnectSignals(q_ptr);
   372 
   300 
   373     // global signal not specific to any containter widget, can be connected now.
   301     // global signal not specific to any containter widget, can be connected now.
   374     HbMainWindow *mainWindow = this->mainWindow();
   302     HbMainWindow *mainWindow = this->mainWindow();
   375     if (mainWindow) {
   303     if (mainWindow) {
   376         q_ptr->disconnect(mainWindow, SIGNAL(aboutToChangeOrientation()), q_ptr, SLOT(orientationAboutToChange()));
   304         q_ptr->disconnect(mainWindow, SIGNAL(aboutToChangeOrientation()), q_ptr, SLOT(orientationAboutToChange()));
   377         q_ptr->disconnect(mainWindow, SIGNAL(orientationChanged(Qt::Orientation)), q_ptr, SLOT(orientationChanged(Qt::Orientation)));
   305         q_ptr->disconnect(mainWindow, SIGNAL(orientationChanged(Qt::Orientation)), q_ptr, SLOT(orientationChanged(Qt::Orientation)));
   378         q_ptr->disconnect(mainWindow, SIGNAL(currentViewChanged(HbView *)), q_ptr, SLOT(currentViewChanged(HbView *)));
   306         q_ptr->disconnect(mainWindow, SIGNAL(aboutToChangeView(HbView *, HbView *)), q_ptr, SLOT(aboutToChangeView(HbView *, HbView *)));
   379     }
   307     }
   380 }
   308 }
   381 
   309 
       
   310 /*!
       
   311 \internal
       
   312 Opens the keypad widget with animation effect.
       
   313 */
   382 void HbAbstractVkbHostPrivate::openKeypad()
   314 void HbAbstractVkbHostPrivate::openKeypad()
   383 {
   315 {
   384     if (mContainerWidget->widgetObject()) {
   316     if (mContainerWidget->widgetObject()) {
   385         HbMainWindow *mainWin = mainWindow();
   317         HbMainWindow *mainWin = mainWindow();
   386         if (mainWin && mKeypad) {
   318         if (mainWin && mKeypad) {
   388                 // Add keypad to scene if it is not already in there.
   320                 // Add keypad to scene if it is not already in there.
   389                 mainWin->scene()->addItem(mKeypad);
   321                 mainWin->scene()->addItem(mKeypad);
   390             }
   322             }
   391 
   323 
   392             if (mKeypadStatus != HbVkbHost::HbVkbStatusOpened) {
   324             if (mKeypadStatus != HbVkbHost::HbVkbStatusOpened) {
   393                 mCallback->aboutToOpen(q_ptr);
   325                 if (mCallback) {
       
   326                     mCallback->aboutToOpen(q_ptr);
       
   327                 }
   394                 q_ptr->resizeKeyboard(); // Make sure that the keyboard doesn't exceed given boundaries.
   328                 q_ptr->resizeKeyboard(); // Make sure that the keyboard doesn't exceed given boundaries.
   395             }
   329             }
   396 
   330 
   397             if (prepareAnimations(HbVkbHost::HbVkbStatusOpened)) {
   331             if (prepareAnimations(HbVkbHost::HbVkbStatusOpened)) {
   398                 // Run the animation
   332                 // Run the animation
   401             }
   335             }
   402         }
   336         }
   403     }
   337     }
   404 }
   338 }
   405 
   339 
       
   340 /*!
       
   341 \internal
       
   342 Closes the keypad with animation effect.
       
   343 */
   406 void HbAbstractVkbHostPrivate::closeKeypad()
   344 void HbAbstractVkbHostPrivate::closeKeypad()
   407 {
   345 {  
   408     // Since the keypad is already in a minimized state we should not play animation.
       
   409     if (mKeypadStatus == HbVkbHost::HbVkbStatusMinimized) {
       
   410         closeKeypadWithoutAnimation();
       
   411     }
       
   412 
       
   413     if (mKeypadStatus != HbVkbHost::HbVkbStatusClosed) {
   346     if (mKeypadStatus != HbVkbHost::HbVkbStatusClosed) {
   414         mCallback->aboutToClose(q_ptr);
   347         if (mCallback) {
       
   348             mCallback->aboutToClose(q_ptr);
       
   349         }
   415 
   350 
   416         if (prepareAnimations(HbVkbHost::HbVkbStatusClosed)) {
   351         if (prepareAnimations(HbVkbHost::HbVkbStatusClosed)) {
   417             mKeypadStatus = HbVkbHost::HbVkbStatusClosed;
   352             mKeypadStatus = HbVkbHost::HbVkbStatusClosed;
   418             mTimeLine.start();
   353             mTimeLine.start();
   419         }
   354         }
   420     }
   355     }
   421 }
   356 }
   422 
   357 
   423 void HbAbstractVkbHostPrivate::minimizeKeypad()
   358 /*!
   424 {
   359 \internal
   425     if (mCallback && mKeypadStatus != HbVkbHost::HbVkbStatusMinimized) {
   360 Opens the keypad widget without animation effect.
   426         mCallback->aboutToClose(q_ptr);
   361 */
   427         if (mContainerWidget->widgetObject()) {
       
   428             if (prepareAnimations(HbVkbHost::HbVkbStatusMinimized)) {
       
   429                 mKeypadStatus = HbVkbHost::HbVkbStatusMinimized;
       
   430                 mTimeLine.start();
       
   431             }
       
   432         }
       
   433     }
       
   434 }
       
   435 
       
   436 void HbAbstractVkbHostPrivate::openKeypadWithoutAnimation()
   362 void HbAbstractVkbHostPrivate::openKeypadWithoutAnimation()
   437 {
   363 {
   438     HbMainWindow *mainWin = mainWindow();
   364     HbMainWindow *mainWin = mainWindow();
   439     if (mKeypadStatus != HbVkbHost::HbVkbStatusOpened && mKeypad && mContainerWidget->widgetObject() && mainWin) {
   365     if (mKeypadStatus != HbVkbHost::HbVkbStatusOpened && mKeypad && mContainerWidget->widgetObject() && mainWin) {
   440         if (mKeypad->scene() != mainWin->scene()) {
   366         if (mKeypad->scene() != mainWin->scene()) {
   441             // Add item to scene if it is not already in there.
   367             // Add item to scene if it is not already in there.
   442             mainWin->scene()->addItem(mKeypad);
   368             mainWin->scene()->addItem(mKeypad);
   443         }
   369         }
   444 
   370 
   445         if (mKeypadStatus != HbVkbHost::HbVkbStatusOpened) {
   371         if (mKeypadStatus != HbVkbHost::HbVkbStatusOpened) {
   446             mCallback->aboutToOpen(q_ptr);
   372             if (mCallback) {
       
   373                 mCallback->aboutToOpen(q_ptr);
       
   374             }
   447             q_ptr->resizeKeyboard(); // Make sure that the keyboard doesn't exceed given boundaries.
   375             q_ptr->resizeKeyboard(); // Make sure that the keyboard doesn't exceed given boundaries.
   448         }
   376         }
   449         if (prepareAnimations(HbVkbHost::HbVkbStatusOpened)) {
   377         if (prepareAnimations(HbVkbHost::HbVkbStatusOpened)) {
   450             if (!disableCursorShift()) {
   378             if (!disableCursorShift()) {
   451                 // Move the container widget to keep the focused line visible.
   379                 // Move the container widget to keep the focused line visible.
   454                 // Move the keypad
   382                 // Move the keypad
   455                 mKeypad->setPos(mKeypadMovementStartingPoint + mKeypadMovementVector);
   383                 mKeypad->setPos(mKeypadMovementStartingPoint + mKeypadMovementVector);
   456             }
   384             }
   457 
   385 
   458             mKeypadStatus = HbVkbHost::HbVkbStatusOpened;
   386             mKeypadStatus = HbVkbHost::HbVkbStatusOpened;
   459             mCallback->keyboardOpened(q_ptr);
   387             if (mCallback) {
   460         }
   388                 mCallback->keyboardOpened(q_ptr);
   461     }
   389             }
   462 }
   390         }
   463 
   391     }
   464 void HbAbstractVkbHostPrivate::openMinimizedKeypad()
   392 
   465 {
   393     ensureVisibilityInsideScrollArea();
   466     // No need of any animation as this minimized keypad is very small to be a candidate for an
   394     ensureVisibilityInsideVisibleArea();
   467     // animation.
   395 }
   468     HbMainWindow *mainWin = mainWindow();
   396 
   469     if (mainWin && mKeypad && mContainerWidget->widgetObject()) {
   397 /*!
   470         if (mKeypad->scene() != mainWin->scene()) {
   398 \internal
   471             // Add item to scene if it is not already in there.
   399 Closes the keypad widget without animating it.
   472             mainWin->scene()->addItem(mKeypad);
   400 */
   473         }
       
   474 
       
   475         if (mKeypadStatus != HbVkbHost::HbVkbStatusMinimized) {
       
   476             mCallback->aboutToOpen(q_ptr);
       
   477             q_ptr->resizeKeyboard(); // Make sure that the keyboard doesn't exceed given boundaries.
       
   478         }
       
   479 
       
   480         if (prepareAnimations(HbVkbHost::HbVkbStatusMinimized)) {
       
   481             if (!disableCursorShift()) {
       
   482                 mKeypad->setPos(0.0, mScreenSize.height() - mCallback->minimizedKeyboardSize().height());
       
   483             }
       
   484             mKeypadStatus = HbVkbHost::HbVkbStatusMinimized;
       
   485             mCallback->keyboardMinimized(q_ptr);
       
   486         }
       
   487     }
       
   488 }
       
   489 
       
   490 void HbAbstractVkbHostPrivate::closeKeypadWithoutAnimation()
   401 void HbAbstractVkbHostPrivate::closeKeypadWithoutAnimation()
   491 {
   402 {
   492     if (mKeypadStatus != HbVkbHost::HbVkbStatusClosed && mKeypad) {
   403     if (mKeypadStatus != HbVkbHost::HbVkbStatusClosed && mKeypad && mCallback) {
   493         mCallback->aboutToClose(q_ptr);
   404         mCallback->aboutToClose(q_ptr);
       
   405 
   494         // Set original content widget position
   406         // Set original content widget position
   495         mKeypadStatus = HbVkbHost::HbVkbStatusClosed;
   407         mKeypadStatus = HbVkbHost::HbVkbStatusClosed;
   496 
   408 
   497         if (!disableCursorShift()) {
   409         if (!disableCursorShift()) {
   498             // Return the container widget to original position.
   410             // Return the container widget to original position.
   499             mContainerWidget->setPos(mOriginalContainerPosition);
   411             mContainerWidget->setPos(mOriginalContainerPosition);
   500             mContainerWidget->widgetObject()->setProperty(KPositionManagedByVKB, false );
   412             mContainerWidget->widgetObject()->setProperty(KPositionManagedByVKB, false);
   501         }
   413         }
   502 
   414 
   503         // Hide the keypad
   415         // Hide the keypad
   504         mKeypad->hide();
   416         mKeypad->hide();
   505         mCallback->keyboardClosed(q_ptr);
   417         mCallback->keyboardClosed(q_ptr);
   506         mCallback = 0;
   418         mCallback = 0;
   507     }
   419     }
   508 }
   420 }
   509 
   421 
   510 void HbAbstractVkbHostPrivate::minimizeKeypadWithoutAnimation()
   422 /*!
   511 {
   423 \internal
   512     HbMainWindow *mainWin = mainWindow();
   424 Cancels the ongoing keypad animation and resets the timeline timer.
   513     if (mKeypadStatus != HbVkbHost::HbVkbStatusMinimized && mKeypad && mainWin) {
   425 */
   514         mCallback->aboutToClose(q_ptr);
       
   515         if (mKeypad->scene() != mainWin->scene()) {
       
   516             // Add item to scene if it is not already in there.
       
   517             mainWin->scene()->addItem(mKeypad);
       
   518         }
       
   519 
       
   520         mKeypadStatus = HbVkbHost::HbVkbStatusMinimized;
       
   521         if (!disableCursorShift()) {
       
   522             // Return the container widget to original position.
       
   523             mContainerWidget->setPos(mOriginalContainerPosition);
       
   524 
       
   525             // Set the keypad to minimized position.
       
   526             mKeypad->setPos(QPointF(0.0, mScreenSize.height() - mCallback->minimizedKeyboardSize().height()));
       
   527         }
       
   528     }
       
   529 }
       
   530 
       
   531 void HbAbstractVkbHostPrivate::cancelAnimationAndHideVkbWidget()
   426 void HbAbstractVkbHostPrivate::cancelAnimationAndHideVkbWidget()
   532 {
   427 {
   533     if (mTimeLine.state() == QTimeLine::Running) {
   428     if (mTimeLine.state() == QTimeLine::Running) {
   534         mTimeLine.stop();
   429         mTimeLine.stop();
   535 
   430 
   536         if (!disableCursorShift()) {
   431         if (!disableCursorShift() && mContainerWidget && mContainerWidget->widgetObject()) {
   537             mContainerWidget->setPos(mOriginalContainerPosition);
   432             mContainerWidget->setPos(mOriginalContainerPosition);
   538             mContainerWidget->widgetObject()->setProperty(KPositionManagedByVKB, false );
   433             mContainerWidget->widgetObject()->setProperty(KPositionManagedByVKB, false);
   539         }
   434         }
   540 
   435 
   541         if (mKeypad) {
   436         if (mKeypad) {
   542             mKeypad->hide();
   437             mKeypad->hide();
   543         }
   438         }
   549         HbVkbHostBridge::instance()->connectHost(0);
   444         HbVkbHostBridge::instance()->connectHost(0);
   550         mKeypadStatus = HbVkbHost::HbVkbStatusClosed;
   445         mKeypadStatus = HbVkbHost::HbVkbStatusClosed;
   551     }
   446     }
   552 }
   447 }
   553 
   448 
       
   449 /*!
       
   450 \internal
       
   451 Returns pointer to container's main window (if one exists).
       
   452 */
   554 HbMainWindow *HbAbstractVkbHostPrivate::mainWindow() const
   453 HbMainWindow *HbAbstractVkbHostPrivate::mainWindow() const
   555 {
   454 {
   556     HbWidget *hbWidget = qobject_cast<HbWidget *>(mContainerWidget->widgetObject());
   455     HbWidget *hbWidget = qobject_cast<HbWidget *>(mContainerWidget->widgetObject());
   557     if (hbWidget) {
   456     if (hbWidget) {
   558         return hbWidget->mainWindow();
   457         return hbWidget->mainWindow();
   566 
   465 
   567     // no mainwindow.
   466     // no mainwindow.
   568     return 0;
   467     return 0;
   569 }
   468 }
   570 
   469 
       
   470 /*!
       
   471 \internal
       
   472 Returns screen size.
       
   473 */
   571 QSizeF HbAbstractVkbHostPrivate::screenSize() const
   474 QSizeF HbAbstractVkbHostPrivate::screenSize() const
   572 {
   475 {
   573     HbMainWindow *mainWin = mainWindow();
   476     HbMainWindow *mainWin = mainWindow();
   574     QSizeF result = static_cast<QSizeF>(HbDeviceProfile::profile(mainWin).logicalSize());
   477     QSizeF result = static_cast<QSizeF>(HbDeviceProfile::profile(mainWin).logicalSize());
   575 
   478 
   590     return result;
   493     return result;
   591 }
   494 }
   592 
   495 
   593 bool HbAbstractVkbHostPrivate::disableCursorShift()
   496 bool HbAbstractVkbHostPrivate::disableCursorShift()
   594 {
   497 {
   595 
       
   596     if (!mInputMethod
   498     if (!mInputMethod
   597         || mainWindow()) {
   499         || mainWindow()) {
   598         return false;
   500         return false;
   599     }
   501     }
   600 
   502 
   605         return true;
   507         return true;
   606     }
   508     }
   607     return false;
   509     return false;
   608 }
   510 }
   609 
   511 
   610 
   512 /*!
   611 /// @endcond
   513 \internal
   612 
   514 Closes the keypad. This slot is connected to various signals from 
       
   515 different container classes.
       
   516 */
       
   517 void HbAbstractVkbHostPrivate::_q_containerAboutToClose()
       
   518 {
       
   519     Q_Q(HbAbstractVkbHost);
       
   520     q->closeKeypad();
       
   521 }
       
   522 
       
   523 /*!
       
   524 \internal
       
   525 Finds out if given editor is inside a scroll area and makes sure the cursor position is visible inside the
       
   526 scroll area.
       
   527 */
       
   528 void HbAbstractVkbHostPrivate::ensureVisibilityInsideScrollArea() const
       
   529 {
       
   530     if (mInputMethod && mInputMethod->focusObject()) {
       
   531         HbInputFocusObject *fo = mInputMethod->focusObject();
       
   532         HbScrollArea *scrollArea = 0;
       
   533 
       
   534         QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(fo->object());
       
   535         if (graphicsObject) {
       
   536             for (QGraphicsWidget *parent = graphicsObject->parentWidget(); parent; parent = parent->parentWidget()) {
       
   537                 scrollArea = qobject_cast<HbScrollArea*>(parent);
       
   538                 if (scrollArea) {
       
   539                     break;
       
   540                 }
       
   541             }
       
   542         }
       
   543 
       
   544         if (scrollArea && scrollArea->contentWidget()) {
       
   545             QRectF scrollRect = scrollArea->sceneBoundingRect();
       
   546             mScrollAreaRect = scrollRect;
       
   547             QRectF editorRect = fo->editorGeometry();
       
   548 
       
   549             if (!scrollRect.contains(editorRect)) {
       
   550                 // The editor is not visible inside a scroll area.
       
   551                 // Calculate how much the area needs to be scrolled
       
   552                 // to make the cursor line visible inside the scroll
       
   553                 // area. The call scroll area's ensure visibility and
       
   554                 // return the calculated value (it needs to be factored in
       
   555                 // to container animation calculations).                            
       
   556                 if (editorRect.height() < scrollRect.height()) {
       
   557                     // Whole editor rect fits into scroll area. Move it there.
       
   558                     if (editorRect.bottom() > scrollRect.bottom()) {
       
   559                         // Scroll upwards.                    
       
   560                         scrollArea->ensureVisible(scrollArea->contentWidget()->mapFromScene(editorRect.bottomLeft()), 0.0, mMarginInPixels);
       
   561                     } else {
       
   562                         // Scroll downwards.                        
       
   563                         scrollArea->ensureVisible(scrollArea->contentWidget()->mapFromScene(editorRect.topLeft()), 0.0, mMarginInPixels);
       
   564                     }
       
   565                 } else {
       
   566                     // Whole editor doesn't fit into scroll area. Used micro focus position instead.
       
   567                     QRectF microFocus = fo->microFocus();
       
   568                     if (microFocus.bottom() > scrollRect.bottom()) {
       
   569                         // Scroll upwards.
       
   570                         scrollArea->ensureVisible(scrollArea->contentWidget()->mapFromScene(microFocus.bottomLeft()), 0.0, mMarginInPixels);
       
   571                     } else {
       
   572                         // Scroll downwards.
       
   573                         scrollArea->ensureVisible(scrollArea->contentWidget()->mapFromScene(microFocus.topLeft()), 0.0, mMarginInPixels);
       
   574                     }
       
   575                 }
       
   576             }
       
   577         }
       
   578     }
       
   579 }
       
   580 
       
   581 /*!
       
   582 \internal
       
   583 Finds out if given editor is inside a scroll area and makes sure the cursor position is visible inside the
       
   584 visible area.
       
   585 */
       
   586 void HbAbstractVkbHostPrivate::ensureVisibilityInsideVisibleArea() const
       
   587 {
       
   588     Q_Q(const HbAbstractVkbHost);
       
   589     if (mInputMethod && mInputMethod->focusObject()) {
       
   590         HbInputFocusObject *fo = mInputMethod->focusObject();
       
   591         HbScrollArea *scrollArea = 0;
       
   592 
       
   593         QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(fo->object());
       
   594         if (graphicsObject) {
       
   595             for (QGraphicsWidget *parent = graphicsObject->parentWidget(); parent; parent = parent->parentWidget()) {
       
   596                 scrollArea = qobject_cast<HbScrollArea*>(parent);
       
   597                 if (scrollArea) {
       
   598                     break;
       
   599                 }
       
   600             }
       
   601         }
       
   602 
       
   603         if (scrollArea && scrollArea->contentWidget()) {
       
   604             QRectF editorRect = fo->editorGeometry();
       
   605             QRectF visibleArea = q->applicationArea();
       
   606             if (!visibleArea.isValid() && mContainerWidget) {
       
   607                 visibleArea = mContainerWidget->sceneBoundingRect();
       
   608             }
       
   609 
       
   610             if (!visibleArea.contains(editorRect)) {
       
   611                 // Editor is inside scroll area but not on visible area so scroll it to be visible
       
   612                 if (editorRect.bottom() > visibleArea.bottom()) {
       
   613                     // Scroll upwards.
       
   614                     QPointF point = QPointF(0.0, -scrollArea->contentWidget()->pos().y() + (editorRect.bottom() - visibleArea.bottom()) + mMarginInPixels);
       
   615                     scrollArea->scrollContentsTo(point);
       
   616                 } else {
       
   617                     // Scroll downwards.
       
   618                     QPointF point = QPointF(0.0, -scrollArea->contentWidget()->pos().y() + editorRect.y() - mMarginInPixels);
       
   619                     scrollArea->scrollContentsTo(point);
       
   620                 }
       
   621             }
       
   622         }
       
   623     }
       
   624 }
       
   625 
       
   626 /*!
       
   627 \internal
       
   628 Returns the editor bounding rect. If the editor is inside a scroll area, then we actually
       
   629 need to use the intersection of scroll area bounding rect and the editor rect in
       
   630 our calculations.
       
   631 */
       
   632 QRectF HbAbstractVkbHostPrivate::findEditorRect(HbInputFocusObject* fo) const
       
   633 {
       
   634     if (fo) {      
       
   635         QRectF editorRect = fo->editorGeometry();
       
   636         if (!mScrollAreaRect.isEmpty()) {
       
   637             QRectF adjustedSrcollArea = mScrollAreaRect;
       
   638             // Cancel out the to-be-added margin
       
   639             adjustedSrcollArea.adjust(0, mMarginInPixels, 0, -mMarginInPixels);
       
   640             return editorRect.intersected(adjustedSrcollArea);
       
   641         }
       
   642         return editorRect;
       
   643     }
       
   644 
       
   645     return QRectF();
       
   646 }
       
   647 
       
   648 /*!
       
   649 \internal
       
   650 Returns true if the container is a popup and it is still running its opening animation
       
   651 when the open keypad call comes in.
       
   652 */
       
   653 bool HbAbstractVkbHostPrivate::popupAnimationInProgress() const
       
   654 {
       
   655     HbPopup *popup = qobject_cast<HbPopup *>(mContainerWidget->widgetObject());
       
   656     if (popup) {
       
   657         HbPopupPrivate *popupPrivate = HbPopupPrivate::d_ptr(popup);
       
   658         return popupPrivate->showingInProgress;
       
   659     }
       
   660 
       
   661     return false;
       
   662 }
       
   663 
       
   664 /*!
       
   665 \internal
       
   666 From two given vector, returns the longest along the y-axis that points to the direction defined
       
   667 by v1.
       
   668 */
       
   669 QPointF HbAbstractVkbHostPrivate::selectLongestVerticalVector(const QPointF &v1, const QPointF &v2) const
       
   670 {
       
   671     if (v1.y() * v2.y() < 0) {
       
   672         // They point to opposite directions.
       
   673         return v1;
       
   674     }
       
   675 
       
   676     if (qAbs(v2.y()) > qAbs(v1.y())) {
       
   677         // v2 is longer.
       
   678         return v2;
       
   679     }
       
   680 
       
   681     return v1;
       
   682 }
   613 
   683 
   614 HbAbstractVkbHost::HbAbstractVkbHost(HbWidget *containerWidget) : d_ptr(new HbAbstractVkbHostPrivate(this, containerWidget))
   684 HbAbstractVkbHost::HbAbstractVkbHost(HbWidget *containerWidget) : d_ptr(new HbAbstractVkbHostPrivate(this, containerWidget))
   615 {
   685 {
   616     Q_D(HbAbstractVkbHost);
   686     Q_D(HbAbstractVkbHost);
   617 
   687 
   618     setParent(containerWidget);
   688     setParent(containerWidget);
   619     HbVkbHost::attachHost(this, containerWidget);
   689     HbVkbHost::attachHost(this, containerWidget);
       
   690     if (containerWidget) {
       
   691         containerWidget->setFlag(QGraphicsItem::ItemSendsGeometryChanges);
       
   692     }
   620 
   693 
   621     connect(&d->mTimeLine, SIGNAL(finished()), this, SLOT(animationFinished()));
   694     connect(&d->mTimeLine, SIGNAL(finished()), this, SLOT(animationFinished()));
   622     connect(&d->mTimeLine, SIGNAL(valueChanged(qreal)), this, SLOT(animValueChanged(qreal)));
   695     connect(&d->mTimeLine, SIGNAL(valueChanged(qreal)), this, SLOT(animValueChanged(qreal)));
   623 }
   696 }
   624 
   697 
   637 {
   710 {
   638     Q_D(HbAbstractVkbHost);
   711     Q_D(HbAbstractVkbHost);
   639 
   712 
   640     setParent(containerWidget);
   713     setParent(containerWidget);
   641     HbVkbHost::attachHost(this, containerWidget);
   714     HbVkbHost::attachHost(this, containerWidget);
       
   715     if (containerWidget) {
       
   716         containerWidget->setFlag(QGraphicsItem::ItemSendsGeometryChanges);
       
   717     }
   642 
   718 
   643     connect(&d->mTimeLine, SIGNAL(finished()), this, SLOT(animationFinished()));
   719     connect(&d->mTimeLine, SIGNAL(finished()), this, SLOT(animationFinished()));
   644     connect(&d->mTimeLine, SIGNAL(valueChanged(qreal)), this, SLOT(animValueChanged(qreal)));
   720     connect(&d->mTimeLine, SIGNAL(valueChanged(qreal)), this, SLOT(animValueChanged(qreal)));
   645 }
   721 }
   646 
   722 
   648 {
   724 {
   649     Q_D(HbAbstractVkbHost);
   725     Q_D(HbAbstractVkbHost);
   650 
   726 
   651     setParent(containerWidget);
   727     setParent(containerWidget);
   652     HbVkbHost::attachHost(this, containerWidget);
   728     HbVkbHost::attachHost(this, containerWidget);
       
   729     if (containerWidget) {
       
   730         containerWidget->setFlag(QGraphicsItem::ItemSendsGeometryChanges);
       
   731     }
   653 
   732 
   654     connect(&d->mTimeLine, SIGNAL(finished()), this, SLOT(animationFinished()));
   733     connect(&d->mTimeLine, SIGNAL(finished()), this, SLOT(animationFinished()));
   655     connect(&d->mTimeLine, SIGNAL(valueChanged(qreal)), this, SLOT(animValueChanged(qreal)));
   734     connect(&d->mTimeLine, SIGNAL(valueChanged(qreal)), this, SLOT(animValueChanged(qreal)));
   656 }
   735 }
   657 
   736 
   699 
   778 
   700     if (owner) {
   779     if (owner) {
   701         d->mInputMethod = owner;
   780         d->mInputMethod = owner;
   702     }
   781     }
   703 
   782 
   704     if ((d->mKeypadStatus != HbVkbStatusMinimized) && (!vkb || !owner)) {
   783     if (!vkb || !owner) {
   705         // The caller is opening the keypad for the first time but didn't supply
   784         // The caller is opening the keypad for the first time but didn't supply
   706         // all the needed parameters. Null parameters are ok only if minimized
   785         // all the needed parameters.
   707         // keypad is reopened.
       
   708         return;
   786         return;
   709     }
   787     }
   710 
   788 
   711     if (!HbVkbHostBridge::instance()->connectHost(this)) {
   789     if (!HbVkbHostBridge::instance()->connectHost(this)) {
   712         // Do not set open call pending if orientation change is ongoing
   790         // Do not set open call pending if orientation change is ongoing
   715         d->mPendingCall.vkb = vkb;
   793         d->mPendingCall.vkb = vkb;
   716         d->mPendingCall.animationAllowed = animationAllowed;
   794         d->mPendingCall.animationAllowed = animationAllowed;
   717         return;
   795         return;
   718     }
   796     }
   719 
   797 
       
   798     if (d->popupAnimationInProgress()) {
       
   799         // The container is a popup and it is still running its opening animation.
       
   800         // delay.
       
   801         connect(d->mContainerWidget->widgetObject(), SIGNAL(popupReady()), this, SLOT(stateTransitionCompleted()));
       
   802         d->mPendingCall.vkb = vkb;
       
   803         d->mPendingCall.animationAllowed = animationAllowed;
       
   804         d->mPendingCall.popupOpening = true;
       
   805         return;
       
   806     }
       
   807 
   720     if (!d->mKeypadOperationOngoing) {
   808     if (!d->mKeypadOperationOngoing) {
   721         d->mKeypadOperationOngoing = true;
   809         d->mKeypadOperationOngoing = true;
   722 
   810 
   723         if (vkb && (d->mCallback != vkb || !d->mKeypad)) {
   811         if (vkb && (d->mCallback != vkb || !d->mKeypad)) {
   724             // This keypad is opened for the first time or it was opened before but some other keypad
   812             // This keypad is opened for the first time or it was opened before but some other keypad
   734         }
   822         }
   735 
   823 
   736         emit aboutToOpen();
   824         emit aboutToOpen();
   737 
   825 
   738         if (d->mContainerWidget && d->mContainerWidget->widgetObject()) {
   826         if (d->mContainerWidget && d->mContainerWidget->widgetObject()) {
   739             d->mContainerWidget->widgetObject()->setProperty(KPositionManagedByVKB, true );
   827             d->mContainerWidget->widgetObject()->setProperty(KPositionManagedByVKB, true);
   740         }
   828         }
   741 
   829 
   742         if (animationAllowed) {
   830         if (animationAllowed) {
   743             d->openKeypad();
   831             d->openKeypad();
   744         } else {
   832         } else {
   786 
   874 
   787     if (!d->disableCursorShift()) {
   875     if (!d->disableCursorShift()) {
   788         // Move the container.
   876         // Move the container.
   789         if (d->mContainerWidget->widgetObject()) {
   877         if (d->mContainerWidget->widgetObject()) {
   790             d->mContainerWidget->setPos(d->mContainerMovementStartingPoint + (d->mContainerMovementVector * value));
   878             d->mContainerWidget->setPos(d->mContainerMovementStartingPoint + (d->mContainerMovementVector * value));
   791         }
   879 
   792 
   880             // Move keypad
   793         // Move keypad
   881             if (d->mKeypad) {
   794         if (d->mKeypad) {
   882                 QPointF keypadPos = d->mKeypadMovementStartingPoint + (d->mKeypadMovementVector * value);
   795             d->mKeypad->setPos(d->mKeypadMovementStartingPoint + (d->mKeypadMovementVector * value));
   883                 d->mKeypad->setPos(keypadPos);
   796         }
   884             }
   797     }
   885         }
   798 
   886     }
   799     if (d->mCallback && d->mKeypad) {
   887 
       
   888     if (d->mCallback) {
   800         d->mCallback->keyboardAnimationFrame(HbVirtualKeyboard::HbVkbAnimOpen, value);
   889         d->mCallback->keyboardAnimationFrame(HbVirtualKeyboard::HbVkbAnimOpen, value);
   801     }
   890     }
   802 }
   891 }
   803 
   892 
   804 /*!
   893 /*!
   825                 QTextEdit *textEdit = qobject_cast<QTextEdit *>(d->mInputMethod->focusObject()->object());
   914                 QTextEdit *textEdit = qobject_cast<QTextEdit *>(d->mInputMethod->focusObject()->object());
   826                 if (textEdit) {
   915                 if (textEdit) {
   827                     textEdit->ensureCursorVisible();
   916                     textEdit->ensureCursorVisible();
   828                 }
   917                 }
   829             }
   918             }
       
   919             d->ensureVisibilityInsideScrollArea();
       
   920             d->ensureVisibilityInsideVisibleArea();
   830 
   921 
   831             // Make sure the keypad never steals focus.
   922             // Make sure the keypad never steals focus.
   832             d->mKeypad->setFlag(QGraphicsItem::ItemIsPanel, true);
   923             d->mKeypad->setFlag(QGraphicsItem::ItemIsPanel, true);
   833             d->mKeypad->setActive(false);
   924             if (d->mKeypad->isActive()) {
       
   925                 d->mKeypad->setActive(false);
       
   926             }
   834             emit keypadOpened();
   927             emit keypadOpened();
   835         } else if (d->mKeypadStatus == HbVkbHost::HbVkbStatusMinimized) {
       
   836             d->mCallback->keyboardMinimized(this);
       
   837             emit keypadClosed();
       
   838         } else {
   928         } else {
   839             // It was closed. Hide the keyboard.
   929             // It was closed. Hide the keyboard.
   840             d->mKeypad->hide();
   930             d->mKeypad->hide();
   841             // Return the container where it was.
   931             // Return the container where it was.
   842             d->mContainerWidget->setPos(d->mOriginalContainerPosition);
   932             d->mContainerWidget->setPos(d->mOriginalContainerPosition);
   843             d->mContainerWidget->widgetObject()->setProperty(KPositionManagedByVKB, false );
   933             d->mContainerWidget->widgetObject()->setProperty(KPositionManagedByVKB, false);
   844             d->mCallback->keyboardClosed(this);
   934             d->mCallback->keyboardClosed(this);
   845             emit keypadClosed();
   935             emit keypadClosed();
   846             HbVkbHostBridge::instance()->connectHost(0);
   936 
       
   937             // Keyboard might be opened again due to pending open call
       
   938             if (d->mKeypadStatus == HbVkbHost::HbVkbStatusClosed) {
       
   939                 HbVkbHostBridge::instance()->connectHost(0);
       
   940             }
   847         }
   941         }
   848     }
   942     }
   849 }
   943 }
   850 
   944 
   851 /*!
   945 /*!
   905 void HbAbstractVkbHost::ensureCursorVisibility()
   999 void HbAbstractVkbHost::ensureCursorVisibility()
   906 {
  1000 {
   907     Q_D(HbAbstractVkbHost);
  1001     Q_D(HbAbstractVkbHost);
   908 
  1002 
   909     if ((d->mTimeLine.state() == QTimeLine::Running) ||
  1003     if ((d->mTimeLine.state() == QTimeLine::Running) ||
   910         (d->mKeypadStatus == HbVkbStatusClosed) ||
  1004         (d->mKeypadStatus == HbVkbStatusClosed) ||        
   911         (d->mKeypadStatus == HbVkbStatusMinimized) ||
       
   912         !d->mContainerWidget->widgetObject()) {
  1005         !d->mContainerWidget->widgetObject()) {
   913         return;
  1006         return;
   914     }
  1007     }
   915 
  1008 
   916     // This will refresh the situation if needed.
  1009     // This will refresh the situation if needed.
   924 QRectF HbAbstractVkbHost::activeViewRect() const
  1017 QRectF HbAbstractVkbHost::activeViewRect() const
   925 {
  1018 {
   926     Q_D(const HbAbstractVkbHost);
  1019     Q_D(const HbAbstractVkbHost);
   927 
  1020 
   928     HbMainWindow *mainWindow = d->mainWindow();
  1021     HbMainWindow *mainWindow = d->mainWindow();
   929     if (d->mContainerWidget->widgetObject() && mainWindow && d->mCallback) {
  1022     if (d->mContainerWidget && d->mContainerWidget->widgetObject() && mainWindow && d->mCallback) {
   930         QSizeF vpSize = d->screenSize();
  1023         QSizeF vpSize = d->screenSize();
   931         QRectF viewport = QRectF(QPointF(0.0, 0.0), QPointF(vpSize.width(), vpSize.height()));
  1024         QRectF viewport = QRectF(QPointF(0.0, 0.0), QPointF(vpSize.width(), vpSize.height()));
   932 
  1025 
   933         if (d->mKeypadStatus == HbVkbStatusMinimized) {
  1026         viewport.setHeight(viewport.height() - confirmedKeyboardSize().height());
   934             viewport.setHeight(viewport.height() - d->mCallback->minimizedKeyboardSize().height());
       
   935         } else {
       
   936             viewport.setHeight(viewport.height() - confirmedKeyboardSize().height());
       
   937         }
       
   938         return viewport;
  1027         return viewport;
   939     }
  1028     }
   940 
  1029 
   941     return QRectF();
  1030     return QRectF();
   942 }
  1031 }
   947 */
  1036 */
   948 QSizeF HbAbstractVkbHost::confirmedKeyboardSize()const
  1037 QSizeF HbAbstractVkbHost::confirmedKeyboardSize()const
   949 {
  1038 {
   950     Q_D(const HbAbstractVkbHost);
  1039     Q_D(const HbAbstractVkbHost);
   951 
  1040 
   952     if (d->mCallback && d->mKeypad) {
  1041     if (d->mCallback) {
   953         QSizeF kbArea = keyboardArea();
  1042         QSizeF kbArea = keyboardArea();
   954         QSizeF confirmed = d->mCallback->preferredKeyboardSize();
  1043         QSizeF confirmed = d->mCallback->preferredKeyboardSize();
   955 
  1044 
   956         if (confirmed.width() > kbArea.width()) {
  1045         if (confirmed.width() > kbArea.width()) {
   957             confirmed.setWidth(kbArea.width());
  1046             confirmed.setWidth(kbArea.width());
   988 */
  1077 */
   989 QRectF HbAbstractVkbHost::applicationArea() const
  1078 QRectF HbAbstractVkbHost::applicationArea() const
   990 {
  1079 {
   991     Q_D(const HbAbstractVkbHost);
  1080     Q_D(const HbAbstractVkbHost);
   992 
  1081 
   993     if (d->mKeypadStatus == HbVkbStatusOpened ||
  1082     if (d->mKeypadStatus == HbVkbStatusOpened) {
   994         d->mKeypadStatus == HbVkbStatusMinimized) {
       
   995         return activeViewRect();
  1083         return activeViewRect();
   996     }
  1084     }
   997 
  1085 
   998     return QRectF();
  1086     return QRectF();
   999 }
       
  1000 
       
  1001 /*!
       
  1002 \reimp
       
  1003 */
       
  1004 void HbAbstractVkbHost::minimizeKeypad(bool animationAllowed)
       
  1005 {
       
  1006     Q_D(HbAbstractVkbHost);
       
  1007     if (d->mKeypadStatus != HbVkbStatusClosed && !d->mKeypadOperationOngoing) {
       
  1008         d->mKeypadOperationOngoing = true;
       
  1009 
       
  1010         if (animationAllowed) {
       
  1011             d->minimizeKeypad();
       
  1012         } else {
       
  1013             d->minimizeKeypadWithoutAnimation();
       
  1014         }
       
  1015 
       
  1016         d->mKeypadOperationOngoing = false;
       
  1017     }
       
  1018 }
       
  1019 
       
  1020 /*!
       
  1021 \reimp
       
  1022 */
       
  1023 void HbAbstractVkbHost::openMinimizedKeypad(HbVirtualKeyboard *vkb, HbInputMethod *owner)
       
  1024 {
       
  1025     Q_D(HbAbstractVkbHost);
       
  1026     d->mInputMethod = owner;
       
  1027 
       
  1028     if (!d->mKeypadOperationOngoing) {
       
  1029         d->mKeypadOperationOngoing = true;
       
  1030 
       
  1031         if (d->mCallback != vkb || !d->mKeypad) {
       
  1032             // This keypad is opened for the first time or it was opened before but some other keypad
       
  1033             // was opened in between.
       
  1034             d->mCallback = vkb;
       
  1035             d->mKeypad = vkb->asGraphicsWidget();
       
  1036         }
       
  1037 
       
  1038         if (!d->mKeypad) {
       
  1039             // Keyboard widget creation failed for some reason, can't go on.
       
  1040             d->mCallback = 0;
       
  1041             return;
       
  1042         }
       
  1043 
       
  1044         d->openMinimizedKeypad();
       
  1045         d->connectSignals();
       
  1046         d->mKeypadOperationOngoing = false;
       
  1047     }
       
  1048 }
  1087 }
  1049 
  1088 
  1050 /*!
  1089 /*!
  1051 \reimp
  1090 \reimp
  1052 */
  1091 */
  1055     Q_D(const HbAbstractVkbHost);
  1094     Q_D(const HbAbstractVkbHost);
  1056     return d->mKeypadStatusBeforeOrientationChange;
  1095     return d->mKeypadStatusBeforeOrientationChange;
  1057 }
  1096 }
  1058 
  1097 
  1059 /*!
  1098 /*!
  1060 This slot is called when active HbView changes.
  1099 \deprecated HbAbstractVkbHost::currentViewChanged(HbView *view)
       
  1100     is deprecated.
  1061 */
  1101 */
  1062 void HbAbstractVkbHost::currentViewChanged(HbView *view)
  1102 void HbAbstractVkbHost::currentViewChanged(HbView *view)
  1063 {
  1103 {
  1064     Q_D(HbAbstractVkbHost);
  1104     Q_UNUSED(view);
  1065 
       
  1066     if (view != d->mContainerWidget->widgetObject()) {
       
  1067         if (d->mTimeLine.state() == QTimeLine::Running) {
       
  1068             d->cancelAnimationAndHideVkbWidget();
       
  1069             if (d->mCallback) {
       
  1070                 d->mCallback->keyboardClosed(this);
       
  1071             }
       
  1072         } else if (d->mKeypadStatus != HbVkbStatusClosed) {
       
  1073             d->closeKeypadWithoutAnimation();
       
  1074             emit keypadClosed();
       
  1075         }
       
  1076     }
       
  1077 }
  1105 }
  1078 
  1106 
  1079 /*!
  1107 /*!
  1080 \reimp
  1108 \reimp
  1081 */
  1109 */
  1108 */
  1136 */
  1109 void HbAbstractVkbHost::stateTransitionCompleted()
  1137 void HbAbstractVkbHost::stateTransitionCompleted()
  1110 {
  1138 {
  1111     Q_D(HbAbstractVkbHost);
  1139     Q_D(HbAbstractVkbHost);
  1112 
  1140 
  1113     disconnect(HbVkbHostBridge::instance(), SIGNAL(stateTransitionCompleted()), this, SLOT(stateTransitionCompleted()));
  1141     if (!d->mPendingCall.popupOpening) {
       
  1142         disconnect(HbVkbHostBridge::instance(), SIGNAL(stateTransitionCompleted()), this, SLOT(stateTransitionCompleted()));
       
  1143     } else {
       
  1144         disconnect(d->mContainerWidget->widgetObject(), SIGNAL(popupReady()), this, SLOT(stateTransitionCompleted()));
       
  1145     }
  1114 
  1146 
  1115     if (d->mPendingCall.vkb) {
  1147     if (d->mPendingCall.vkb) {
  1116         // There was an open call pending. Do it now.
  1148         // There was an open call pending. Do it now.
  1117         HbVirtualKeyboard *vkb = d->mPendingCall.vkb;
  1149         HbVirtualKeyboard *vkb = d->mPendingCall.vkb;
  1118         d->mPendingCall.vkb = 0;
  1150         d->mPendingCall.vkb = 0;
  1119         openKeypad(vkb, d->mInputMethod, d->mPendingCall.animationAllowed);
  1151         openKeypad(vkb, d->mInputMethod, d->mPendingCall.animationAllowed);
  1120     }
  1152     }
  1121 }
  1153 }
  1122 
  1154 
       
  1155 /*!
       
  1156 This slot is called when change in active HbView starts.
       
  1157 */
       
  1158 void HbAbstractVkbHost::aboutToChangeView(HbView *oldView, HbView *newView)
       
  1159 {
       
  1160     Q_D(HbAbstractVkbHost);
       
  1161 
       
  1162     if (oldView != newView) {
       
  1163         if (d->mTimeLine.state() == QTimeLine::Running) {
       
  1164             d->cancelAnimationAndHideVkbWidget();
       
  1165             if (d->mCallback) {
       
  1166                 d->mCallback->keyboardClosed(this);
       
  1167             }
       
  1168         } else if (d->mKeypadStatus != HbVkbStatusClosed) {
       
  1169             d->closeKeypadWithoutAnimation();
       
  1170             emit keypadClosed();
       
  1171         }
       
  1172     }
       
  1173 }
       
  1174 
       
  1175 #include "moc_hbabstractvkbhost.cpp"
       
  1176 
  1123 // End of file
  1177 // End of file