diff options
author | Janne Koskinen <janne.p.koskinen@digia.com> | 2009-05-11 12:16:25 (GMT) |
---|---|---|
committer | Janne Koskinen <janne.p.koskinen@digia.com> | 2009-05-11 12:16:25 (GMT) |
commit | f005af3b8c8405219b39bacd348d3861f1243aa8 (patch) | |
tree | a2d1f332de493d3d2cf0e0d1b3ad7c062176fe39 /src/gui/inputmethod | |
parent | 8aaa0cbf3451dee7bc8e8276faad3b2f2954dc1c (diff) | |
parent | 565f2957fb049f2df0330fac72ec5335860b9c7f (diff) | |
download | Qt-f005af3b8c8405219b39bacd348d3861f1243aa8.zip Qt-f005af3b8c8405219b39bacd348d3861f1243aa8.tar.gz Qt-f005af3b8c8405219b39bacd348d3861f1243aa8.tar.bz2 |
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt-s60-public
Conflicts:
src/gui/widgets/qmenu_symbian.cpp
Diffstat (limited to 'src/gui/inputmethod')
-rw-r--r-- | src/gui/inputmethod/qcoefepinputcontext_p.h | 5 | ||||
-rw-r--r-- | src/gui/inputmethod/qcoefepinputcontext_s60.cpp | 210 | ||||
-rw-r--r-- | src/gui/inputmethod/qinputcontext.cpp | 16 | ||||
-rw-r--r-- | src/gui/inputmethod/qwininputcontext_win.cpp | 10 | ||||
-rw-r--r-- | src/gui/inputmethod/qximinputcontext_p.h | 1 | ||||
-rw-r--r-- | src/gui/inputmethod/qximinputcontext_x11.cpp | 13 |
6 files changed, 211 insertions, 44 deletions
diff --git a/src/gui/inputmethod/qcoefepinputcontext_p.h b/src/gui/inputmethod/qcoefepinputcontext_p.h index 7f0a482..9ce9724 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_p.h +++ b/src/gui/inputmethod/qcoefepinputcontext_p.h @@ -63,6 +63,8 @@ public: private: void commitCurrentString(); + void updateHints(); + void applyHints(Qt::InputMethodHints hints); // From MCoeFepAwareTextEditor public: @@ -98,11 +100,12 @@ private: QSymbianControl *m_parent; CAknEdwinState *m_fepState; QString m_preeditString; + Qt::InputMethodHints m_lastImHints; + TUint m_textCapabilities; bool m_isEditing; bool m_inDestruction; int m_cursorVisibility; int m_inlinePosition; - QPoint m_mousePressPos; MFepInlineTextFormatRetriever *m_formatRetriever; MFepPointerEventHandlerDuringInlineEdit *m_pointerHandler; }; diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index b9ea4c7..1ae3d79 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -31,6 +31,8 @@ QT_BEGIN_NAMESPACE QCoeFepInputContext::QCoeFepInputContext(QObject *parent) : QInputContext(parent), m_fepState(new (ELeave) CAknEdwinState), + m_lastImHints(Qt::ImhNone), + m_textCapabilities(TCoeInputCapabilities::EAllText), m_isEditing(false), m_inDestruction(false), m_cursorVisibility(1), @@ -41,12 +43,10 @@ QCoeFepInputContext::QCoeFepInputContext(QObject *parent) m_fepState->SetObjectProvider(this); m_fepState->SetFlags(EAknEditorFlagDefault); m_fepState->SetDefaultInputMode( EAknEditorTextInputMode ); - m_fepState->SetCurrentInputMode( EAknEditorTextInputMode ); m_fepState->SetPermittedInputModes( EAknEditorAllInputModes ); m_fepState->SetLocalLanguage(ELangEnglish); m_fepState->SetDefaultLanguage(ELangEnglish); m_fepState->SetDefaultCase( EAknEditorLowerCase ); - m_fepState->SetCurrentCase( EAknEditorLowerCase ); m_fepState->SetPermittedCases( EAknEditorLowerCase|EAknEditorUpperCase ); m_fepState->SetSpecialCharacterTableResourceId( 0 ); m_fepState->SetNumericKeymap( EAknEditorStandardNumberModeKeymap ); @@ -74,7 +74,9 @@ void QCoeFepInputContext::reset() void QCoeFepInputContext::update() { - // For pre-5.0 SDKs, we don't do any work. + updateHints(); + + // For pre-5.0 SDKs, we don't do text updates on S60 side. if (QSysInfo::s60Version() != QSysInfo::SV_S60_5_0) { return; } @@ -92,6 +94,8 @@ void QCoeFepInputContext::setFocusWidget(QWidget *w) CCoeEnv::Static()->Fep()->CancelTransaction(); QInputContext::setFocusWidget(w); + + updateHints(); } void QCoeFepInputContext::widgetDestroyed(QWidget *w) @@ -203,44 +207,49 @@ QString QCoeFepInputContext::language() bool QCoeFepInputContext::filterEvent(const QEvent *event) { - // For pre-5.0 SDKs, we don't do any work. + // The CloseSoftwareInputPanel event is not handled here, because the VK will automatically + // close when it discovers that the underlying widget does not have input capabilities. + + if (!focusWidget()) + return false; + + if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) { + const QKeyEvent *keyEvent = static_cast<const QKeyEvent *>(event); + Q_ASSERT(m_lastImHints == focusWidget()->inputMethodHints()); + if (keyEvent->key() == Qt::Key_F20 && m_lastImHints & Qt::ImhHiddenText) { + // Special case in Symbian. On editors with secret text, F20 is for some reason + // considered to be a backspace. + QKeyEvent modifiedEvent(keyEvent->type(), Qt::Key_Backspace, keyEvent->modifiers(), + keyEvent->text(), keyEvent->isAutoRepeat(), keyEvent->count()); + QApplication::sendEvent(focusWidget(), &modifiedEvent); + return true; + } + } + + // For pre-5.0 SDKs, we don't launch the keyboard. if (QSysInfo::s60Version() != QSysInfo::SV_S60_5_0) { return false; } - if (event->type() == QEvent::MouseButtonPress) { - const QMouseEvent *mEvent = static_cast<const QMouseEvent *>(event); - m_mousePressPos = mEvent->globalPos(); - } else if (event->type() == QEvent::MouseButtonRelease) { + if (event->type() == QEvent::RequestSoftwareInputPanel) { // Notify S60 that we want the virtual keyboard to show up. - const QMouseEvent *mEvent = static_cast<const QMouseEvent *>(event); - - if (mEvent->modifiers() == Qt::NoModifier - && mEvent->button() == Qt::LeftButton - && focusWidget() // Not set if prior MouseButtonPress was not on this widget - && focusWidget()->rect().contains(focusWidget()->mapFromGlobal(mEvent->globalPos())) - && (m_mousePressPos - mEvent->globalPos()).manhattanLength() < QApplication::startDragDistance()) { - - QSymbianControl *sControl; - sControl = focusWidget()->effectiveWinId()->MopGetObject(sControl); - // The FEP UI temporarily steals focus when it shows up the first time, causing - // all sorts of weird effects on the focused widgets. Since it will immediately give - // back focus to us, we temporarily disable focus handling until the job's done. - if (sControl) { - sControl->setIgnoreFocusChanged(true); - } + QSymbianControl *sControl; + sControl = focusWidget()->effectiveWinId()->MopGetObject(sControl); + Q_ASSERT(sControl); + + // The FEP UI temporarily steals focus when it shows up the first time, causing + // all sorts of weird effects on the focused widgets. Since it will immediately give + // back focus to us, we temporarily disable focus handling until the job's done. + if (sControl) { + sControl->setIgnoreFocusChanged(true); + } - m_fepState->ReportAknEdStateEventL(MAknEdStateObserver::QT_EAknActivatePenInputRequest); + m_fepState->ReportAknEdStateEventL(MAknEdStateObserver::QT_EAknActivatePenInputRequest); - if (sControl) { - sControl->setIgnoreFocusChanged(false); - } - - // Although it is tempting to let the click through by returning false, we have to return - // true because the event might have caused focus switches, which may in turn delete - // widgets. - return true; + if (sControl) { + sControl->setIgnoreFocusChanged(false); } + return true; } return false; @@ -307,7 +316,7 @@ TCoeInputCapabilities QCoeFepInputContext::inputCapabilities() return TCoeInputCapabilities(TCoeInputCapabilities::ENone, 0, 0); } - return TCoeInputCapabilities(TCoeInputCapabilities::EAllText, this, 0); + return TCoeInputCapabilities(m_textCapabilities, this, 0); } static QTextCharFormat qt_TCharFormat2QTextCharFormat(const TCharFormat &cFormat) @@ -323,6 +332,139 @@ static QTextCharFormat qt_TCharFormat2QTextCharFormat(const TCharFormat &cFormat return qFormat; } +void QCoeFepInputContext::updateHints() +{ + QWidget *w = focusWidget(); + if (w) { + Qt::InputMethodHints hints = w->inputMethodHints(); + if (hints != m_lastImHints) { + m_lastImHints = hints; + applyHints(hints); + } + } +} + +void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints) +{ + using namespace Qt; + + bool numbersOnly = hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly + || hints & ImhDialableCharactersOnly; + bool noOnlys = !(numbersOnly || hints & ImhUppercaseOnly + || hints & ImhLowercaseOnly); + TInt flags; + Qt::InputMethodHints oldHints = hints; + + // Some sanity checking. Make sure that only one preference is set. + InputMethodHints prefs = ImhPreferNumbers | ImhPreferUppercase | ImhPreferLowercase; + prefs &= hints; + if (prefs != ImhPreferNumbers && prefs != ImhPreferUppercase && prefs != ImhPreferLowercase) { + hints &= ~prefs; + } + if (!noOnlys) { + // Make sure that the preference is within the permitted set. + if (hints & ImhPreferNumbers && !(hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly + || hints & ImhDialableCharactersOnly)) { + hints &= ~ImhPreferNumbers; + } else if (hints & ImhPreferUppercase && !(hints & ImhUppercaseOnly)) { + hints &= ~ImhPreferUppercase; + } else if (hints & ImhPreferLowercase && !(hints & ImhLowercaseOnly)) { + hints &= ~ImhPreferLowercase; + } + // If there is no preference, set it to something within the permitted set. + if (!(hints & ImhPreferNumbers || hints & ImhPreferUppercase || hints & ImhPreferLowercase)) { + if (hints & ImhLowercaseOnly) { + hints |= ImhPreferLowercase; + } else if (hints & ImhUppercaseOnly) { + hints |= ImhPreferUppercase; + } else if (hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly + || hints & ImhDialableCharactersOnly) { + hints |= ImhPreferNumbers; + } + } + } + + if (hints & ImhPreferNumbers) { + m_fepState->SetDefaultInputMode(EAknEditorNumericInputMode); + m_fepState->SetCurrentInputMode(EAknEditorNumericInputMode); + } else { + m_fepState->SetDefaultInputMode(EAknEditorTextInputMode); + m_fepState->SetCurrentInputMode(EAknEditorTextInputMode); + } + flags = 0; + if (numbersOnly) { + flags |= EAknEditorNumericInputMode; + } + if (hints & ImhUppercaseOnly || hints & ImhLowercaseOnly) { + flags |= EAknEditorTextInputMode; + } + if (flags == 0) { + flags = EAknEditorAllInputModes; + } + m_fepState->SetPermittedInputModes(flags); + m_fepState->ReportAknEdStateEventL(MAknEdStateObserver::EAknEdwinStateInputModeUpdate); + + if (hints & ImhPreferLowercase) { + m_fepState->SetDefaultCase(EAknEditorLowerCase); + m_fepState->SetCurrentCase(EAknEditorLowerCase); + } else if (hints & ImhPreferUppercase) { + m_fepState->SetDefaultCase(EAknEditorUpperCase); + m_fepState->SetCurrentCase(EAknEditorUpperCase); + } else if (hints & ImhNoAutoUppercase) { + m_fepState->SetDefaultCase(EAknEditorLowerCase); + m_fepState->SetCurrentCase(EAknEditorLowerCase); + } else { + m_fepState->SetDefaultCase(EAknEditorTextCase); + m_fepState->SetCurrentCase(EAknEditorTextCase); + } + flags = 0; + if (hints & ImhUppercaseOnly) { + flags |= EAknEditorUpperCase; + } + if (hints & ImhLowercaseOnly) { + flags |= EAknEditorLowerCase; + } + if (flags == 0) { + flags = EAknEditorAllCaseModes; + if (hints & ImhNoAutoUppercase) { + flags &= ~EAknEditorTextCase; + } + } + m_fepState->SetPermittedCases(flags); + m_fepState->ReportAknEdStateEventL(MAknEdStateObserver::EAknEdwinStateCaseModeUpdate); + + flags = 0; + if (hints & ImhUppercaseOnly && !(hints & ImhLowercaseOnly) + || hints & ImhLowercaseOnly && !(hints & ImhUppercaseOnly)) { + flags |= EAknEditorFlagFixedCase; + } + // Using T9 and hidden text together may actually crash the FEP, so check for hidden text too. + if (hints & ImhNoPredictiveText || hints & ImhHiddenText) { + flags |= EAknEditorFlagNoT9; + } + m_fepState->SetFlags(flags); + m_fepState->ReportAknEdStateEventL(MAknEdStateObserver::EAknEdwinStateFlagsUpdate); + + if (hints & ImhFormattedNumbersOnly) { + flags = EAknEditorCalculatorNumberModeKeymap; + } else if (hints & ImhDigitsOnly) { + flags = EAknEditorPlainNumberModeKeymap; + } else { + // ImhDialableCharactersOnly is the fallback as well, so we don't need to check for + // that flag. + flags = EAknEditorStandardNumberModeKeymap; + } + m_fepState->SetNumericKeymap(static_cast<TAknEditorNumericKeymap>(flags)); + + if (hints & ImhHiddenText) { + m_textCapabilities = TCoeInputCapabilities::EAllText | TCoeInputCapabilities::ESecretText; + } else { + m_textCapabilities = TCoeInputCapabilities::EAllText; + } + + CCoeEnv::Static()->InputCapabilitiesChanged(); +} + void QCoeFepInputContext::StartFepInlineEditL(const TDesC& aInitialInlineText, TInt aPositionOfInsertionPointInInlineText, TBool aCursorVisibility, const MFormCustomDraw* /*aCustomDraw*/, MFepInlineTextFormatRetriever& aInlineTextFormatRetriever, diff --git a/src/gui/inputmethod/qinputcontext.cpp b/src/gui/inputmethod/qinputcontext.cpp index 3d6d303..c7d156c 100644 --- a/src/gui/inputmethod/qinputcontext.cpp +++ b/src/gui/inputmethod/qinputcontext.cpp @@ -209,7 +209,19 @@ void QInputContext::setFocusWidget(QWidget *widget) way. Although the input events have accept() and ignore() methods, leave it untouched. - \a event is currently restricted to QKeyEvent and QMouseEvent. + \a event is currently restricted to events of these types: + + \list + \i CloseSoftwareInputPanel + \i KeyPress + \i KeyRelease + \i MouseButtonDblClick + \i MouseButtonPress + \i MouseButtonRelease + \i MouseMove + \i RequestSoftwareInputPanel + \endlist + But some input method related events such as QWheelEvent or QTabletEvent may be added in future. @@ -464,7 +476,7 @@ bool QInputContext::x11FilterEvent(QWidget * /*keywidget*/, XEvent * /*event*/) This function may be overridden only if input method is depending on Symbian and you need raw TWsEvent. Otherwise, this function must not. - This function is designed to filter raw key events for XIM, but + This function is designed to filter raw key events on S60, but other input methods may use this to implement some special features. diff --git a/src/gui/inputmethod/qwininputcontext_win.cpp b/src/gui/inputmethod/qwininputcontext_win.cpp index 720f0b8..e3e8aa4 100644 --- a/src/gui/inputmethod/qwininputcontext_win.cpp +++ b/src/gui/inputmethod/qwininputcontext_win.cpp @@ -57,15 +57,17 @@ #ifdef Q_IME_DEBUG #include "qdebug.h" -#endif - -QT_BEGIN_NAMESPACE +#endif -extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); #if defined(Q_OS_WINCE) extern void qt_wince_show_SIP(bool show); // defined in qguifunctions_wince.cpp #endif +QT_BEGIN_NAMESPACE + +extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); + + DEFINE_GUID(IID_IActiveIMMApp, 0x08c0e040, 0x62d1, 0x11d1, 0x93, 0x26, 0x0, 0x60, 0xb0, 0x67, 0xb8, 0x6e); diff --git a/src/gui/inputmethod/qximinputcontext_p.h b/src/gui/inputmethod/qximinputcontext_p.h index ca2103b..3773122 100644 --- a/src/gui/inputmethod/qximinputcontext_p.h +++ b/src/gui/inputmethod/qximinputcontext_p.h @@ -98,6 +98,7 @@ public: QString text; QBitArray selectedChars; bool composing; + bool preeditEmpty; void clear(); }; diff --git a/src/gui/inputmethod/qximinputcontext_x11.cpp b/src/gui/inputmethod/qximinputcontext_x11.cpp index 48a96b1..c320fb4 100644 --- a/src/gui/inputmethod/qximinputcontext_x11.cpp +++ b/src/gui/inputmethod/qximinputcontext_x11.cpp @@ -264,6 +264,7 @@ extern "C" { qic->standardFormat(QInputContext::PreeditFormat)); attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, cursor, sellen ? 0 : 1, QVariant()); QInputMethodEvent e(data->text, attrs); + data->preeditEmpty = data->text.isEmpty(); qic->sendEvent(e); return 0; @@ -286,6 +287,7 @@ void QXIMInputContext::ICData::clear() text = QString(); selectedChars.clear(); composing = false; + preeditEmpty = true; } QXIMInputContext::ICData *QXIMInputContext::icData() const @@ -435,7 +437,8 @@ void QXIMInputContext::create_xim() // reinitialize input context after the input method // server (like SCIM) has been launched without // requiring the user to manually switch focus. - if (focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) + if (focusWidget->testAttribute(Qt::WA_InputMethodEnabled) + && focusWidget->testAttribute(Qt::WA_WState_Created)) setFocusWidget(focusWidget); } // following code fragment is not required for immodule @@ -537,9 +540,12 @@ void QXIMInputContext::reset() if (mb) { e.setCommitString(QString::fromLocal8Bit(mb)); XFree(mb); + data->preeditEmpty = false; // force sending an event + } + if (!data->preeditEmpty) { + sendEvent(e); + update(); } - sendEvent(e); - update(); } data->clear(); } @@ -686,6 +692,7 @@ QXIMInputContext::ICData *QXIMInputContext::createICData(QWidget *w) { ICData *data = new ICData; data->widget = w; + data->preeditEmpty = true; XVaNestedList preedit_attr = 0; XIMCallback startcallback, drawcallback, donecallback; |