src/gui/inputmethod/qcoefepinputcontext_s60.cpp
changeset 7 f7bc934e204c
parent 3 41300fa6a67c
--- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp	Tue Feb 02 00:43:10 2010 +0200
+++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp	Wed Mar 31 11:06:36 2010 +0300
@@ -1,6 +1,6 @@
 /****************************************************************************
 **
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 ** All rights reserved.
 ** Contact: Nokia Corporation (qt-info@nokia.com)
 **
@@ -71,8 +71,8 @@
       m_inlinePosition(0),
       m_formatRetriever(0),
       m_pointerHandler(0),
-      m_longPress(0),
-      m_cursorPos(0)
+      m_cursorPos(0),
+      m_hasTempPreeditString(false)
 {
     m_fepState->SetObjectProvider(this);
     m_fepState->SetFlags(EAknEditorFlagDefault);
@@ -100,9 +100,7 @@
 
 void QCoeFepInputContext::reset()
 {
-    CCoeFep* fep = CCoeEnv::Static()->Fep();
-    if (fep)
-        fep->CancelTransaction();
+    commitCurrentString(true);
 }
 
 void QCoeFepInputContext::ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateEvent aEventType)
@@ -114,11 +112,10 @@
 {
     updateHints(false);
 
-	// :QTP: Always show virtual keyboard - fix needed to use feature manager
     // For pre-5.0 SDKs, we don't do text updates on S60 side.
-    //if (QSysInfo::s60Version() != QSysInfo::SV_S60_5_0) {
-    //    return;
-    //}
+    if (QSysInfo::s60Version() < QSysInfo::SV_S60_5_0) {
+        return;
+    }
 
     // Don't be fooled (as I was) by the name of this enumeration.
     // What it really does is tell the virtual keyboard UI that the text has been
@@ -128,7 +125,7 @@
 
 void QCoeFepInputContext::setFocusWidget(QWidget *w)
 {
-    commitCurrentString(false);
+    commitCurrentString(true);
 
     QInputContext::setFocusWidget(w);
 
@@ -201,7 +198,11 @@
     if (!focusWidget())
         return false;
 
-    if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
+    switch (event->type()) {
+    case QEvent::KeyPress:
+        commitTemporaryPreeditString();
+        // fall through intended
+    case QEvent::KeyRelease:
         const QKeyEvent *keyEvent = static_cast<const QKeyEvent *>(event);
         switch (keyEvent->key()) {
         case Qt::Key_F20:
@@ -217,13 +218,29 @@
             break;
         case Qt::Key_Select:
             if (!m_preeditString.isEmpty()) {
-                commitCurrentString(false);
+                commitCurrentString(true);
                 return true;
             }
             break;
         default:
             break;
         }
+
+        if (keyEvent->type() == QEvent::KeyPress
+            && focusWidget()->inputMethodHints() & Qt::ImhHiddenText
+            && !keyEvent->text().isEmpty()) {
+            // Send some temporary preedit text in order to make text visible for a moment.
+            m_cursorPos = focusWidget()->inputMethodQuery(Qt::ImCursorPosition).toInt();
+            m_preeditString = keyEvent->text();
+            QList<QInputMethodEvent::Attribute> attributes;
+            QInputMethodEvent imEvent(m_preeditString, attributes);
+            sendEvent(imEvent);
+            m_tempPreeditStringTimeout.start(1000, this);
+            m_hasTempPreeditString = true;
+            update();
+            return true;
+        }
+        break;
     }
 
     if (!needsInputPanel())
@@ -254,12 +271,29 @@
     return false;
 }
 
+void QCoeFepInputContext::timerEvent(QTimerEvent *timerEvent)
+{
+    if (timerEvent->timerId() == m_tempPreeditStringTimeout.timerId())
+        commitTemporaryPreeditString();
+}
+
+void QCoeFepInputContext::commitTemporaryPreeditString()
+{
+    if (m_tempPreeditStringTimeout.isActive())
+        m_tempPreeditStringTimeout.stop();
+
+    if (!m_hasTempPreeditString)
+        return;
+
+    commitCurrentString(false);
+}
+
 void QCoeFepInputContext::mouseHandler( int x, QMouseEvent *event)
 {
     Q_ASSERT(focusWidget());
 
     if (event->type() == QEvent::MouseButtonPress && event->button() == Qt::LeftButton) {
-        commitCurrentString(false);
+        commitCurrentString(true);
         int pos = focusWidget()->inputMethodQuery(Qt::ImCursorPosition).toInt();
 
         QList<QInputMethodEvent::Attribute> attributes;
@@ -311,6 +345,8 @@
 {
     using namespace Qt;
 
+    commitTemporaryPreeditString();
+
     bool numbersOnly = hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly
             || hints & ImhDialableCharactersOnly;
     bool noOnlys = !(numbersOnly || hints & ImhUppercaseOnly
@@ -502,6 +538,8 @@
     if (!w)
         return;
 
+    commitTemporaryPreeditString();
+
     m_cursorPos = w->inputMethodQuery(Qt::ImCursorPosition).toInt();
     
     QList<QInputMethodEvent::Attribute> attributes;
@@ -513,6 +551,21 @@
     m_formatRetriever = &aInlineTextFormatRetriever;
     m_pointerHandler = &aPointerEventHandlerDuringInlineEdit;
 
+    // With T9 aInitialInlineText is typically empty when StartFepInlineEditL is called,
+    // but FEP requires that selected text is always removed at StartFepInlineEditL.
+    // Let's remove the selected text if aInitialInlineText is empty and there is selected text
+    if (m_preeditString.isEmpty()) {
+        int anchor = w->inputMethodQuery(Qt::ImAnchorPosition).toInt();
+        int replacementLength = qAbs(m_cursorPos-anchor);
+        if (replacementLength > 0) {
+            int replacementStart = m_cursorPos < anchor ? 0 : -replacementLength;
+            QList<QInputMethodEvent::Attribute> clearSelectionAttributes;
+            QInputMethodEvent clearSelectionEvent(QLatin1String(""), clearSelectionAttributes);
+            clearSelectionEvent.setCommitString(QLatin1String(""), replacementStart, replacementLength);
+            sendEvent(clearSelectionEvent);
+        }
+    }
+
     applyFormat(&attributes);
 
     attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor,
@@ -601,6 +654,8 @@
     if (!w)
         return;
 
+    commitTemporaryPreeditString();
+
     int pos = aCursorSelection.iAnchorPos;
     int length = aCursorSelection.iCursorPos - pos;
 
@@ -699,30 +754,36 @@
 
 void QCoeFepInputContext::DoCommitFepInlineEditL()
 {
-    commitCurrentString(true);
+    commitCurrentString(false);
+    if (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0)
+        ReportAknEdStateEvent(QT_EAknCursorPositionChanged);
+
 }
 
-void QCoeFepInputContext::commitCurrentString(bool triggeredBySymbian)
+void QCoeFepInputContext::commitCurrentString(bool cancelFepTransaction)
 {
+    int longPress = 0;
+
     if (m_preeditString.size() == 0) {
         QWidget *w = focusWidget();
-        if (triggeredBySymbian && w) {
+        if (!cancelFepTransaction && w) {
             // We must replace the last character only if the input box has already accepted one 
             if (w->inputMethodQuery(Qt::ImCursorPosition).toInt() != m_cursorPos)
-                m_longPress = 1;
+                longPress = 1;
         }
         return;
     }
 
     QList<QInputMethodEvent::Attribute> attributes;
     QInputMethodEvent event(QLatin1String(""), attributes);
-    event.setCommitString(m_preeditString, 0-m_longPress, m_longPress);
+    event.setCommitString(m_preeditString, 0-longPress, longPress);
     m_preeditString.clear();
     sendEvent(event);
 
-    m_longPress = 0;
+    m_hasTempPreeditString = false;
+    longPress = 0;
 
-    if (!triggeredBySymbian) {
+    if (cancelFepTransaction) {
         CCoeFep* fep = CCoeEnv::Static()->Fep();
         if (fep)
             fep->CancelTransaction();