src/gui/inputmethod/qcoefepinputcontext_s60.cpp
changeset 7 f7bc934e204c
parent 3 41300fa6a67c
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
     1 /****************************************************************************
     1 /****************************************************************************
     2 **
     2 **
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     4 ** All rights reserved.
     4 ** All rights reserved.
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     6 **
     6 **
     7 ** This file is part of the QtGui module of the Qt Toolkit.
     7 ** This file is part of the QtGui module of the Qt Toolkit.
     8 **
     8 **
    69       m_pendingInputCapabilitiesChanged(false),
    69       m_pendingInputCapabilitiesChanged(false),
    70       m_cursorVisibility(1),
    70       m_cursorVisibility(1),
    71       m_inlinePosition(0),
    71       m_inlinePosition(0),
    72       m_formatRetriever(0),
    72       m_formatRetriever(0),
    73       m_pointerHandler(0),
    73       m_pointerHandler(0),
    74       m_longPress(0),
    74       m_cursorPos(0),
    75       m_cursorPos(0)
    75       m_hasTempPreeditString(false)
    76 {
    76 {
    77     m_fepState->SetObjectProvider(this);
    77     m_fepState->SetObjectProvider(this);
    78     m_fepState->SetFlags(EAknEditorFlagDefault);
    78     m_fepState->SetFlags(EAknEditorFlagDefault);
    79     m_fepState->SetDefaultInputMode( EAknEditorTextInputMode );
    79     m_fepState->SetDefaultInputMode( EAknEditorTextInputMode );
    80     m_fepState->SetPermittedInputModes( EAknEditorAllInputModes );
    80     m_fepState->SetPermittedInputModes( EAknEditorAllInputModes );
    98         delete m_fepState;
    98         delete m_fepState;
    99 }
    99 }
   100 
   100 
   101 void QCoeFepInputContext::reset()
   101 void QCoeFepInputContext::reset()
   102 {
   102 {
   103     CCoeFep* fep = CCoeEnv::Static()->Fep();
   103     commitCurrentString(true);
   104     if (fep)
       
   105         fep->CancelTransaction();
       
   106 }
   104 }
   107 
   105 
   108 void QCoeFepInputContext::ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateEvent aEventType)
   106 void QCoeFepInputContext::ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateEvent aEventType)
   109 {
   107 {
   110     QT_TRAP_THROWING(m_fepState->ReportAknEdStateEventL(aEventType));
   108     QT_TRAP_THROWING(m_fepState->ReportAknEdStateEventL(aEventType));
   112 
   110 
   113 void QCoeFepInputContext::update()
   111 void QCoeFepInputContext::update()
   114 {
   112 {
   115     updateHints(false);
   113     updateHints(false);
   116 
   114 
   117 	// :QTP: Always show virtual keyboard - fix needed to use feature manager
       
   118     // For pre-5.0 SDKs, we don't do text updates on S60 side.
   115     // For pre-5.0 SDKs, we don't do text updates on S60 side.
   119     //if (QSysInfo::s60Version() != QSysInfo::SV_S60_5_0) {
   116     if (QSysInfo::s60Version() < QSysInfo::SV_S60_5_0) {
   120     //    return;
   117         return;
   121     //}
   118     }
   122 
   119 
   123     // Don't be fooled (as I was) by the name of this enumeration.
   120     // Don't be fooled (as I was) by the name of this enumeration.
   124     // What it really does is tell the virtual keyboard UI that the text has been
   121     // What it really does is tell the virtual keyboard UI that the text has been
   125     // updated and it should be reflected in the internal display of the VK.
   122     // updated and it should be reflected in the internal display of the VK.
   126     ReportAknEdStateEvent(QT_EAknCursorPositionChanged);
   123     ReportAknEdStateEvent(QT_EAknCursorPositionChanged);
   127 }
   124 }
   128 
   125 
   129 void QCoeFepInputContext::setFocusWidget(QWidget *w)
   126 void QCoeFepInputContext::setFocusWidget(QWidget *w)
   130 {
   127 {
   131     commitCurrentString(false);
   128     commitCurrentString(true);
   132 
   129 
   133     QInputContext::setFocusWidget(w);
   130     QInputContext::setFocusWidget(w);
   134 
   131 
   135     updateHints(true);
   132     updateHints(true);
   136 }
   133 }
   199     // close when it discovers that the underlying widget does not have input capabilities.
   196     // close when it discovers that the underlying widget does not have input capabilities.
   200 
   197 
   201     if (!focusWidget())
   198     if (!focusWidget())
   202         return false;
   199         return false;
   203 
   200 
   204     if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
   201     switch (event->type()) {
       
   202     case QEvent::KeyPress:
       
   203         commitTemporaryPreeditString();
       
   204         // fall through intended
       
   205     case QEvent::KeyRelease:
   205         const QKeyEvent *keyEvent = static_cast<const QKeyEvent *>(event);
   206         const QKeyEvent *keyEvent = static_cast<const QKeyEvent *>(event);
   206         switch (keyEvent->key()) {
   207         switch (keyEvent->key()) {
   207         case Qt::Key_F20:
   208         case Qt::Key_F20:
   208             Q_ASSERT(m_lastImHints == focusWidget()->inputMethodHints());
   209             Q_ASSERT(m_lastImHints == focusWidget()->inputMethodHints());
   209             if (m_lastImHints & Qt::ImhHiddenText) {
   210             if (m_lastImHints & Qt::ImhHiddenText) {
   215                 return true;
   216                 return true;
   216             }
   217             }
   217             break;
   218             break;
   218         case Qt::Key_Select:
   219         case Qt::Key_Select:
   219             if (!m_preeditString.isEmpty()) {
   220             if (!m_preeditString.isEmpty()) {
   220                 commitCurrentString(false);
   221                 commitCurrentString(true);
   221                 return true;
   222                 return true;
   222             }
   223             }
   223             break;
   224             break;
   224         default:
   225         default:
   225             break;
   226             break;
   226         }
   227         }
       
   228 
       
   229         if (keyEvent->type() == QEvent::KeyPress
       
   230             && focusWidget()->inputMethodHints() & Qt::ImhHiddenText
       
   231             && !keyEvent->text().isEmpty()) {
       
   232             // Send some temporary preedit text in order to make text visible for a moment.
       
   233             m_cursorPos = focusWidget()->inputMethodQuery(Qt::ImCursorPosition).toInt();
       
   234             m_preeditString = keyEvent->text();
       
   235             QList<QInputMethodEvent::Attribute> attributes;
       
   236             QInputMethodEvent imEvent(m_preeditString, attributes);
       
   237             sendEvent(imEvent);
       
   238             m_tempPreeditStringTimeout.start(1000, this);
       
   239             m_hasTempPreeditString = true;
       
   240             update();
       
   241             return true;
       
   242         }
       
   243         break;
   227     }
   244     }
   228 
   245 
   229     if (!needsInputPanel())
   246     if (!needsInputPanel())
   230         return false;
   247         return false;
   231 
   248 
   252     }
   269     }
   253 
   270 
   254     return false;
   271     return false;
   255 }
   272 }
   256 
   273 
       
   274 void QCoeFepInputContext::timerEvent(QTimerEvent *timerEvent)
       
   275 {
       
   276     if (timerEvent->timerId() == m_tempPreeditStringTimeout.timerId())
       
   277         commitTemporaryPreeditString();
       
   278 }
       
   279 
       
   280 void QCoeFepInputContext::commitTemporaryPreeditString()
       
   281 {
       
   282     if (m_tempPreeditStringTimeout.isActive())
       
   283         m_tempPreeditStringTimeout.stop();
       
   284 
       
   285     if (!m_hasTempPreeditString)
       
   286         return;
       
   287 
       
   288     commitCurrentString(false);
       
   289 }
       
   290 
   257 void QCoeFepInputContext::mouseHandler( int x, QMouseEvent *event)
   291 void QCoeFepInputContext::mouseHandler( int x, QMouseEvent *event)
   258 {
   292 {
   259     Q_ASSERT(focusWidget());
   293     Q_ASSERT(focusWidget());
   260 
   294 
   261     if (event->type() == QEvent::MouseButtonPress && event->button() == Qt::LeftButton) {
   295     if (event->type() == QEvent::MouseButtonPress && event->button() == Qt::LeftButton) {
   262         commitCurrentString(false);
   296         commitCurrentString(true);
   263         int pos = focusWidget()->inputMethodQuery(Qt::ImCursorPosition).toInt();
   297         int pos = focusWidget()->inputMethodQuery(Qt::ImCursorPosition).toInt();
   264 
   298 
   265         QList<QInputMethodEvent::Attribute> attributes;
   299         QList<QInputMethodEvent::Attribute> attributes;
   266         attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, pos + x, 0, QVariant());
   300         attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, pos + x, 0, QVariant());
   267         QInputMethodEvent event(QLatin1String(""), attributes);
   301         QInputMethodEvent event(QLatin1String(""), attributes);
   308 }
   342 }
   309 
   343 
   310 void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints)
   344 void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints)
   311 {
   345 {
   312     using namespace Qt;
   346     using namespace Qt;
       
   347 
       
   348     commitTemporaryPreeditString();
   313 
   349 
   314     bool numbersOnly = hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly
   350     bool numbersOnly = hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly
   315             || hints & ImhDialableCharactersOnly;
   351             || hints & ImhDialableCharactersOnly;
   316     bool noOnlys = !(numbersOnly || hints & ImhUppercaseOnly
   352     bool noOnlys = !(numbersOnly || hints & ImhUppercaseOnly
   317             || hints & ImhLowercaseOnly);
   353             || hints & ImhLowercaseOnly);
   500 {
   536 {
   501     QWidget *w = focusWidget();
   537     QWidget *w = focusWidget();
   502     if (!w)
   538     if (!w)
   503         return;
   539         return;
   504 
   540 
       
   541     commitTemporaryPreeditString();
       
   542 
   505     m_cursorPos = w->inputMethodQuery(Qt::ImCursorPosition).toInt();
   543     m_cursorPos = w->inputMethodQuery(Qt::ImCursorPosition).toInt();
   506     
   544     
   507     QList<QInputMethodEvent::Attribute> attributes;
   545     QList<QInputMethodEvent::Attribute> attributes;
   508 
   546 
   509     m_cursorVisibility = aCursorVisibility ? 1 : 0;
   547     m_cursorVisibility = aCursorVisibility ? 1 : 0;
   510     m_inlinePosition = aPositionOfInsertionPointInInlineText;
   548     m_inlinePosition = aPositionOfInsertionPointInInlineText;
   511     m_preeditString = qt_TDesC2QString(aInitialInlineText);
   549     m_preeditString = qt_TDesC2QString(aInitialInlineText);
   512 
   550 
   513     m_formatRetriever = &aInlineTextFormatRetriever;
   551     m_formatRetriever = &aInlineTextFormatRetriever;
   514     m_pointerHandler = &aPointerEventHandlerDuringInlineEdit;
   552     m_pointerHandler = &aPointerEventHandlerDuringInlineEdit;
       
   553 
       
   554     // With T9 aInitialInlineText is typically empty when StartFepInlineEditL is called,
       
   555     // but FEP requires that selected text is always removed at StartFepInlineEditL.
       
   556     // Let's remove the selected text if aInitialInlineText is empty and there is selected text
       
   557     if (m_preeditString.isEmpty()) {
       
   558         int anchor = w->inputMethodQuery(Qt::ImAnchorPosition).toInt();
       
   559         int replacementLength = qAbs(m_cursorPos-anchor);
       
   560         if (replacementLength > 0) {
       
   561             int replacementStart = m_cursorPos < anchor ? 0 : -replacementLength;
       
   562             QList<QInputMethodEvent::Attribute> clearSelectionAttributes;
       
   563             QInputMethodEvent clearSelectionEvent(QLatin1String(""), clearSelectionAttributes);
       
   564             clearSelectionEvent.setCommitString(QLatin1String(""), replacementStart, replacementLength);
       
   565             sendEvent(clearSelectionEvent);
       
   566         }
       
   567     }
   515 
   568 
   516     applyFormat(&attributes);
   569     applyFormat(&attributes);
   517 
   570 
   518     attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor,
   571     attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor,
   519                                                    m_inlinePosition,
   572                                                    m_inlinePosition,
   598 void QCoeFepInputContext::SetCursorSelectionForFepL(const TCursorSelection& aCursorSelection)
   651 void QCoeFepInputContext::SetCursorSelectionForFepL(const TCursorSelection& aCursorSelection)
   599 {
   652 {
   600     QWidget *w = focusWidget();
   653     QWidget *w = focusWidget();
   601     if (!w)
   654     if (!w)
   602         return;
   655         return;
       
   656 
       
   657     commitTemporaryPreeditString();
   603 
   658 
   604     int pos = aCursorSelection.iAnchorPos;
   659     int pos = aCursorSelection.iAnchorPos;
   605     int length = aCursorSelection.iCursorPos - pos;
   660     int length = aCursorSelection.iCursorPos - pos;
   606 
   661 
   607     QList<QInputMethodEvent::Attribute> attributes;
   662     QList<QInputMethodEvent::Attribute> attributes;
   697     aAscent = metrics.ascent();
   752     aAscent = metrics.ascent();
   698 }
   753 }
   699 
   754 
   700 void QCoeFepInputContext::DoCommitFepInlineEditL()
   755 void QCoeFepInputContext::DoCommitFepInlineEditL()
   701 {
   756 {
   702     commitCurrentString(true);
   757     commitCurrentString(false);
   703 }
   758     if (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0)
   704 
   759         ReportAknEdStateEvent(QT_EAknCursorPositionChanged);
   705 void QCoeFepInputContext::commitCurrentString(bool triggeredBySymbian)
   760 
   706 {
   761 }
       
   762 
       
   763 void QCoeFepInputContext::commitCurrentString(bool cancelFepTransaction)
       
   764 {
       
   765     int longPress = 0;
       
   766 
   707     if (m_preeditString.size() == 0) {
   767     if (m_preeditString.size() == 0) {
   708         QWidget *w = focusWidget();
   768         QWidget *w = focusWidget();
   709         if (triggeredBySymbian && w) {
   769         if (!cancelFepTransaction && w) {
   710             // We must replace the last character only if the input box has already accepted one 
   770             // We must replace the last character only if the input box has already accepted one 
   711             if (w->inputMethodQuery(Qt::ImCursorPosition).toInt() != m_cursorPos)
   771             if (w->inputMethodQuery(Qt::ImCursorPosition).toInt() != m_cursorPos)
   712                 m_longPress = 1;
   772                 longPress = 1;
   713         }
   773         }
   714         return;
   774         return;
   715     }
   775     }
   716 
   776 
   717     QList<QInputMethodEvent::Attribute> attributes;
   777     QList<QInputMethodEvent::Attribute> attributes;
   718     QInputMethodEvent event(QLatin1String(""), attributes);
   778     QInputMethodEvent event(QLatin1String(""), attributes);
   719     event.setCommitString(m_preeditString, 0-m_longPress, m_longPress);
   779     event.setCommitString(m_preeditString, 0-longPress, longPress);
   720     m_preeditString.clear();
   780     m_preeditString.clear();
   721     sendEvent(event);
   781     sendEvent(event);
   722 
   782 
   723     m_longPress = 0;
   783     m_hasTempPreeditString = false;
   724 
   784     longPress = 0;
   725     if (!triggeredBySymbian) {
   785 
       
   786     if (cancelFepTransaction) {
   726         CCoeFep* fep = CCoeEnv::Static()->Fep();
   787         CCoeFep* fep = CCoeEnv::Static()->Fep();
   727         if (fep)
   788         if (fep)
   728             fep->CancelTransaction();
   789             fep->CancelTransaction();
   729     }
   790     }
   730 }
   791 }