src/gui/inputmethod/qcoefepinputcontext_s60.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #ifndef QT_NO_IM
       
    43 
       
    44 #include "qcoefepinputcontext_p.h"
       
    45 #include <qapplication.h>
       
    46 #include <qtextformat.h>
       
    47 #include <private/qcore_symbian_p.h>
       
    48 
       
    49 #include <fepitfr.h>
       
    50 
       
    51 #include <limits.h>
       
    52 // You only find these enumerations on SDK 5 onwards, so we need to provide our own
       
    53 // to remain compatible with older releases. They won't be called by pre-5.0 SDKs.
       
    54 
       
    55 // MAknEdStateObserver::EAknCursorPositionChanged
       
    56 #define QT_EAknCursorPositionChanged MAknEdStateObserver::EAknEdwinStateEvent(6)
       
    57 // MAknEdStateObserver::EAknActivatePenInputRequest
       
    58 #define QT_EAknActivatePenInputRequest MAknEdStateObserver::EAknEdwinStateEvent(7)
       
    59 
       
    60 QT_BEGIN_NAMESPACE
       
    61 
       
    62 QCoeFepInputContext::QCoeFepInputContext(QObject *parent)
       
    63     : QInputContext(parent),
       
    64       m_fepState(q_check_ptr(new CAknEdwinState)),		// CBase derived object needs check on new
       
    65       m_lastImHints(Qt::ImhNone),
       
    66       m_textCapabilities(TCoeInputCapabilities::EAllText),
       
    67       m_isEditing(false),
       
    68       m_inDestruction(false),
       
    69       m_pendingInputCapabilitiesChanged(false),
       
    70       m_cursorVisibility(1),
       
    71       m_inlinePosition(0),
       
    72       m_formatRetriever(0),
       
    73       m_pointerHandler(0)
       
    74 {
       
    75     m_fepState->SetObjectProvider(this);
       
    76     m_fepState->SetFlags(EAknEditorFlagDefault);
       
    77     m_fepState->SetDefaultInputMode( EAknEditorTextInputMode );
       
    78     m_fepState->SetPermittedInputModes( EAknEditorAllInputModes );
       
    79     m_fepState->SetDefaultCase( EAknEditorLowerCase );
       
    80     m_fepState->SetPermittedCases( EAknEditorLowerCase|EAknEditorUpperCase );
       
    81     m_fepState->SetSpecialCharacterTableResourceId( 0 );
       
    82     m_fepState->SetNumericKeymap( EAknEditorStandardNumberModeKeymap );
       
    83 }
       
    84 
       
    85 QCoeFepInputContext::~QCoeFepInputContext()
       
    86 {
       
    87     m_inDestruction = true;
       
    88 
       
    89     // This is to make sure that the FEP manager "forgets" about us,
       
    90     // otherwise we may get callbacks even after we're destroyed.
       
    91     // The call below is essentially equivalent to InputCapabilitiesChanged(),
       
    92     // but is synchronous, rather than asynchronous.
       
    93     CCoeEnv::Static()->SyncNotifyFocusObserversOfChangeInFocus();
       
    94 
       
    95     if (m_fepState)
       
    96         delete m_fepState;
       
    97 }
       
    98 
       
    99 void QCoeFepInputContext::reset()
       
   100 {
       
   101     CCoeFep* fep = CCoeEnv::Static()->Fep();
       
   102     if (fep)
       
   103         fep->CancelTransaction();
       
   104 }
       
   105 
       
   106 void QCoeFepInputContext::ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateEvent aEventType)
       
   107 {
       
   108     QT_TRAP_THROWING(m_fepState->ReportAknEdStateEventL(aEventType));
       
   109 }
       
   110 
       
   111 void QCoeFepInputContext::update()
       
   112 {
       
   113     updateHints(false);
       
   114 
       
   115 	// :QTP: Always show virtual keyboard - fix needed to use feature manager
       
   116     // For pre-5.0 SDKs, we don't do text updates on S60 side.
       
   117     //if (QSysInfo::s60Version() != QSysInfo::SV_S60_5_0) {
       
   118     //    return;
       
   119     //}
       
   120 
       
   121     // Don't be fooled (as I was) by the name of this enumeration.
       
   122     // What it really does is tell the virtual keyboard UI that the text has been
       
   123     // updated and it should be reflected in the internal display of the VK.
       
   124     ReportAknEdStateEvent(QT_EAknCursorPositionChanged);
       
   125 }
       
   126 
       
   127 void QCoeFepInputContext::setFocusWidget(QWidget *w)
       
   128 {
       
   129     commitCurrentString(false);
       
   130 
       
   131     QInputContext::setFocusWidget(w);
       
   132 
       
   133     updateHints(true);
       
   134 }
       
   135 
       
   136 void QCoeFepInputContext::widgetDestroyed(QWidget *w)
       
   137 {
       
   138     // Make sure that the input capabilities of whatever new widget got focused are queried.
       
   139     CCoeControl *ctrl = w->effectiveWinId();
       
   140     if (ctrl->IsFocused()) {
       
   141         ctrl->SetFocus(false);
       
   142         ctrl->SetFocus(true);
       
   143     }
       
   144 }
       
   145 
       
   146 QString QCoeFepInputContext::language()
       
   147 {
       
   148     TLanguage lang = m_fepState->LocalLanguage();
       
   149     const QByteArray localeName = qt_symbianLocaleName(lang);
       
   150     if (!localeName.isEmpty()) {
       
   151         return QString::fromLatin1(localeName);
       
   152     } else {
       
   153         return QString::fromLatin1("C");
       
   154     }
       
   155 }
       
   156 
       
   157 bool QCoeFepInputContext::filterEvent(const QEvent *event)
       
   158 {
       
   159     // The CloseSoftwareInputPanel event is not handled here, because the VK will automatically
       
   160     // close when it discovers that the underlying widget does not have input capabilities.
       
   161 
       
   162     if (!focusWidget())
       
   163         return false;
       
   164 
       
   165     if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
       
   166         const QKeyEvent *keyEvent = static_cast<const QKeyEvent *>(event);
       
   167         Q_ASSERT(m_lastImHints == focusWidget()->inputMethodHints());
       
   168         if (keyEvent->key() == Qt::Key_F20 && m_lastImHints & Qt::ImhHiddenText) {
       
   169             // Special case in Symbian. On editors with secret text, F20 is for some reason
       
   170             // considered to be a backspace.
       
   171             QKeyEvent modifiedEvent(keyEvent->type(), Qt::Key_Backspace, keyEvent->modifiers(),
       
   172                     keyEvent->text(), keyEvent->isAutoRepeat(), keyEvent->count());
       
   173             QApplication::sendEvent(focusWidget(), &modifiedEvent);
       
   174             return true;
       
   175         }
       
   176     }
       
   177 
       
   178 	// :QTP: Always show virtual keyboard - fix needed to use feature manager
       
   179     // For pre-5.0 SDKs, we don't launch the keyboard.
       
   180 	/*
       
   181     if (QSysInfo::s60Version() != QSysInfo::SV_S60_5_0) {
       
   182         return false;
       
   183     }
       
   184 	*/
       
   185 
       
   186     if (event->type() == QEvent::RequestSoftwareInputPanel) {
       
   187         // Notify S60 that we want the virtual keyboard to show up.
       
   188         QSymbianControl *sControl;
       
   189         sControl = focusWidget()->effectiveWinId()->MopGetObject(sControl);
       
   190         Q_ASSERT(sControl);
       
   191 
       
   192         // The FEP UI temporarily steals focus when it shows up the first time, causing
       
   193         // all sorts of weird effects on the focused widgets. Since it will immediately give
       
   194         // back focus to us, we temporarily disable focus handling until the job's done.
       
   195         if (sControl) {
       
   196             sControl->setIgnoreFocusChanged(true);
       
   197         }
       
   198 
       
   199         ensureInputCapabilitiesChanged();
       
   200         m_fepState->ReportAknEdStateEventL(MAknEdStateObserver::QT_EAknActivatePenInputRequest);
       
   201 
       
   202         if (sControl) {
       
   203             sControl->setIgnoreFocusChanged(false);
       
   204         }
       
   205         return true;
       
   206     }
       
   207 
       
   208     return false;
       
   209 }
       
   210 
       
   211 void QCoeFepInputContext::mouseHandler( int x, QMouseEvent *event)
       
   212 {
       
   213     Q_ASSERT(m_isEditing);
       
   214     Q_ASSERT(focusWidget());
       
   215 
       
   216     if (event->type() == QEvent::MouseButtonPress && event->button() == Qt::LeftButton) {
       
   217         commitCurrentString(false);
       
   218         int pos = focusWidget()->inputMethodQuery(Qt::ImCursorPosition).toInt();
       
   219 
       
   220         QList<QInputMethodEvent::Attribute> attributes;
       
   221         attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, pos + x, 0, QVariant());
       
   222         QInputMethodEvent event(QLatin1String(""), attributes);
       
   223         sendEvent(event);
       
   224     }
       
   225 }
       
   226 
       
   227 TCoeInputCapabilities QCoeFepInputContext::inputCapabilities()
       
   228 {
       
   229     if (m_inDestruction || !focusWidget()) {
       
   230         return TCoeInputCapabilities(TCoeInputCapabilities::ENone, 0, 0);
       
   231     }
       
   232 
       
   233     return TCoeInputCapabilities(m_textCapabilities, this, 0);
       
   234 }
       
   235 
       
   236 static QTextCharFormat qt_TCharFormat2QTextCharFormat(const TCharFormat &cFormat)
       
   237 {
       
   238     QTextCharFormat qFormat;
       
   239 
       
   240     QBrush foreground(QColor(cFormat.iFontPresentation.iTextColor.Internal()));
       
   241     qFormat.setForeground(foreground);
       
   242 
       
   243     qFormat.setFontStrikeOut(cFormat.iFontPresentation.iStrikethrough == EStrikethroughOn);
       
   244     qFormat.setFontUnderline(cFormat.iFontPresentation.iUnderline == EUnderlineOn);
       
   245 
       
   246     return qFormat;
       
   247 }
       
   248 
       
   249 void QCoeFepInputContext::updateHints(bool mustUpdateInputCapabilities)
       
   250 {
       
   251     QWidget *w = focusWidget();
       
   252     if (w) {
       
   253         Qt::InputMethodHints hints = w->inputMethodHints();
       
   254         if (hints != m_lastImHints) {
       
   255             m_lastImHints = hints;
       
   256             applyHints(hints);
       
   257         } else if (!mustUpdateInputCapabilities) {
       
   258             // Optimization. Return immediately if there was no change.
       
   259             return;
       
   260         }
       
   261     }
       
   262     queueInputCapabilitiesChanged();
       
   263 }
       
   264 
       
   265 void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints)
       
   266 {
       
   267     using namespace Qt;
       
   268 
       
   269     bool numbersOnly = hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly
       
   270             || hints & ImhDialableCharactersOnly;
       
   271     bool noOnlys = !(numbersOnly || hints & ImhUppercaseOnly
       
   272             || hints & ImhLowercaseOnly);
       
   273     TInt flags;
       
   274     Qt::InputMethodHints oldHints = hints;
       
   275 
       
   276     // Some sanity checking. Make sure that only one preference is set.
       
   277     InputMethodHints prefs = ImhPreferNumbers | ImhPreferUppercase | ImhPreferLowercase;
       
   278     prefs &= hints;
       
   279     if (prefs != ImhPreferNumbers && prefs != ImhPreferUppercase && prefs != ImhPreferLowercase) {
       
   280         hints &= ~prefs;
       
   281     }
       
   282     if (!noOnlys) {
       
   283         // Make sure that the preference is within the permitted set.
       
   284         if (hints & ImhPreferNumbers && !(hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly
       
   285                 || hints & ImhDialableCharactersOnly)) {
       
   286             hints &= ~ImhPreferNumbers;
       
   287         } else if (hints & ImhPreferUppercase && !(hints & ImhUppercaseOnly)) {
       
   288             hints &= ~ImhPreferUppercase;
       
   289         } else if (hints & ImhPreferLowercase && !(hints & ImhLowercaseOnly)) {
       
   290             hints &= ~ImhPreferLowercase;
       
   291         }
       
   292         // If there is no preference, set it to something within the permitted set.
       
   293         if (!(hints & ImhPreferNumbers || hints & ImhPreferUppercase || hints & ImhPreferLowercase)) {
       
   294             if (hints & ImhLowercaseOnly) {
       
   295                 hints |= ImhPreferLowercase;
       
   296             } else if (hints & ImhUppercaseOnly) {
       
   297                 hints |= ImhPreferUppercase;
       
   298             } else if (hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly
       
   299                     || hints & ImhDialableCharactersOnly) {
       
   300                 hints |= ImhPreferNumbers;
       
   301             }
       
   302         }
       
   303     }
       
   304 
       
   305     if (hints & ImhPreferNumbers) {
       
   306         m_fepState->SetDefaultInputMode(EAknEditorNumericInputMode);
       
   307         m_fepState->SetCurrentInputMode(EAknEditorNumericInputMode);
       
   308     } else {
       
   309         m_fepState->SetDefaultInputMode(EAknEditorTextInputMode);
       
   310         m_fepState->SetCurrentInputMode(EAknEditorTextInputMode);
       
   311     }
       
   312     flags = 0;
       
   313     if (numbersOnly) {
       
   314         flags |= EAknEditorNumericInputMode;
       
   315     }
       
   316     if (hints & ImhUppercaseOnly || hints & ImhLowercaseOnly) {
       
   317         flags |= EAknEditorTextInputMode;
       
   318     }
       
   319     if (flags == 0) {
       
   320         flags = EAknEditorAllInputModes;
       
   321     }
       
   322     m_fepState->SetPermittedInputModes(flags);
       
   323     ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateInputModeUpdate);
       
   324 
       
   325     if (hints & ImhPreferLowercase) {
       
   326         m_fepState->SetDefaultCase(EAknEditorLowerCase);
       
   327         m_fepState->SetCurrentCase(EAknEditorLowerCase);
       
   328     } else if (hints & ImhPreferUppercase) {
       
   329         m_fepState->SetDefaultCase(EAknEditorUpperCase);
       
   330         m_fepState->SetCurrentCase(EAknEditorUpperCase);
       
   331     } else if (hints & ImhNoAutoUppercase) {
       
   332         m_fepState->SetDefaultCase(EAknEditorLowerCase);
       
   333         m_fepState->SetCurrentCase(EAknEditorLowerCase);
       
   334     } else {
       
   335         m_fepState->SetDefaultCase(EAknEditorTextCase);
       
   336         m_fepState->SetCurrentCase(EAknEditorTextCase);
       
   337     }
       
   338     flags = 0;
       
   339     if (hints & ImhUppercaseOnly) {
       
   340         flags |= EAknEditorUpperCase;
       
   341     }
       
   342     if (hints & ImhLowercaseOnly) {
       
   343         flags |= EAknEditorLowerCase;
       
   344     }
       
   345     if (flags == 0) {
       
   346         flags = EAknEditorAllCaseModes;
       
   347         if (hints & ImhNoAutoUppercase) {
       
   348             flags &= ~EAknEditorTextCase;
       
   349         }
       
   350     }
       
   351     m_fepState->SetPermittedCases(flags);
       
   352     ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateCaseModeUpdate);
       
   353 
       
   354     flags = 0;
       
   355     if (hints & ImhUppercaseOnly && !(hints & ImhLowercaseOnly)
       
   356             || hints & ImhLowercaseOnly && !(hints & ImhUppercaseOnly)) {
       
   357         flags |= EAknEditorFlagFixedCase;
       
   358     }
       
   359     // Using T9 and hidden text together may actually crash the FEP, so check for hidden text too.
       
   360     if (hints & ImhNoPredictiveText || hints & ImhHiddenText) {
       
   361         flags |= EAknEditorFlagNoT9;
       
   362     }
       
   363     m_fepState->SetFlags(flags);
       
   364     ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateFlagsUpdate);
       
   365 
       
   366     if (hints & ImhFormattedNumbersOnly) {
       
   367         flags = EAknEditorCalculatorNumberModeKeymap;
       
   368     } else if (hints & ImhDigitsOnly) {
       
   369         flags = EAknEditorPlainNumberModeKeymap;
       
   370     } else {
       
   371         // ImhDialableCharactersOnly is the fallback as well, so we don't need to check for
       
   372         // that flag.
       
   373         flags = EAknEditorStandardNumberModeKeymap;
       
   374     }
       
   375     m_fepState->SetNumericKeymap(static_cast<TAknEditorNumericKeymap>(flags));
       
   376 
       
   377     if (hints & ImhHiddenText) {
       
   378         m_textCapabilities = TCoeInputCapabilities::EAllText | TCoeInputCapabilities::ESecretText;
       
   379     } else {
       
   380         m_textCapabilities = TCoeInputCapabilities::EAllText;
       
   381     }
       
   382 }
       
   383 
       
   384 void QCoeFepInputContext::applyFormat(QList<QInputMethodEvent::Attribute> *attributes)
       
   385 {
       
   386     TCharFormat cFormat;
       
   387     TInt numChars = 0;
       
   388     TInt charPos = 0;
       
   389     int oldSize = attributes->size();
       
   390     while (m_formatRetriever) {
       
   391         m_formatRetriever->GetFormatOfFepInlineText(cFormat, numChars, charPos);
       
   392         if (numChars <= 0) {
       
   393             // This shouldn't happen according to S60 docs, but apparently does sometimes.
       
   394             break;
       
   395         }
       
   396         attributes->append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
       
   397                                                         charPos,
       
   398                                                         numChars,
       
   399                                                         QVariant(qt_TCharFormat2QTextCharFormat(cFormat))));
       
   400         charPos += numChars;
       
   401         if (charPos >= m_preeditString.size()) {
       
   402             break;
       
   403         }
       
   404     }
       
   405 
       
   406     if (attributes->size() == oldSize) {
       
   407         // S60 didn't provide any format, so let's give our own instead.
       
   408         attributes->append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
       
   409                                                         0,
       
   410                                                         m_preeditString.size(),
       
   411                                                         standardFormat(PreeditFormat)));
       
   412     }
       
   413 }
       
   414 
       
   415 void QCoeFepInputContext::queueInputCapabilitiesChanged()
       
   416 {
       
   417     if (m_pendingInputCapabilitiesChanged)
       
   418         return;
       
   419 
       
   420     // Call ensureInputCapabilitiesChanged asynchronously. This is done to improve performance
       
   421     // by not updating input capabilities too often. The reason we don't call the Symbian
       
   422     // asynchronous version of InputCapabilitiesChanged is because we need to ensure that it
       
   423     // is synchronous in some specific cases. Those will call ensureInputCapabilitesChanged.
       
   424     QMetaObject::invokeMethod(this, "ensureInputCapabilitiesChanged", Qt::QueuedConnection);
       
   425     m_pendingInputCapabilitiesChanged = true;
       
   426 }
       
   427 
       
   428 void QCoeFepInputContext::ensureInputCapabilitiesChanged()
       
   429 {
       
   430     if (!m_pendingInputCapabilitiesChanged)
       
   431         return;
       
   432 
       
   433     // The call below is essentially equivalent to InputCapabilitiesChanged(),
       
   434     // but is synchronous, rather than asynchronous.
       
   435     CCoeEnv::Static()->SyncNotifyFocusObserversOfChangeInFocus();
       
   436     m_pendingInputCapabilitiesChanged = false;
       
   437 }
       
   438 
       
   439 void QCoeFepInputContext::StartFepInlineEditL(const TDesC& aInitialInlineText,
       
   440         TInt aPositionOfInsertionPointInInlineText, TBool aCursorVisibility, const MFormCustomDraw* /*aCustomDraw*/,
       
   441         MFepInlineTextFormatRetriever& aInlineTextFormatRetriever,
       
   442         MFepPointerEventHandlerDuringInlineEdit& aPointerEventHandlerDuringInlineEdit)
       
   443 {
       
   444     QWidget *w = focusWidget();
       
   445     if (!w)
       
   446         return;
       
   447 
       
   448     m_isEditing = true;
       
   449 
       
   450     QList<QInputMethodEvent::Attribute> attributes;
       
   451 
       
   452     m_cursorVisibility = aCursorVisibility ? 1 : 0;
       
   453     m_inlinePosition = aPositionOfInsertionPointInInlineText;
       
   454     m_preeditString = qt_TDesC2QString(aInitialInlineText);
       
   455 
       
   456     m_formatRetriever = &aInlineTextFormatRetriever;
       
   457     m_pointerHandler = &aPointerEventHandlerDuringInlineEdit;
       
   458 
       
   459     applyFormat(&attributes);
       
   460 
       
   461     attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor,
       
   462                                                    m_inlinePosition,
       
   463                                                    m_cursorVisibility,
       
   464                                                    QVariant()));
       
   465     QInputMethodEvent event(m_preeditString, attributes);
       
   466     sendEvent(event);
       
   467 }
       
   468 
       
   469 void QCoeFepInputContext::UpdateFepInlineTextL(const TDesC& aNewInlineText,
       
   470         TInt aPositionOfInsertionPointInInlineText)
       
   471 {
       
   472     QWidget *w = focusWidget();
       
   473     if (!w)
       
   474         return;
       
   475 
       
   476     m_inlinePosition = aPositionOfInsertionPointInInlineText;
       
   477 
       
   478     QList<QInputMethodEvent::Attribute> attributes;
       
   479     applyFormat(&attributes);
       
   480     attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor,
       
   481                                                    m_inlinePosition,
       
   482                                                    m_cursorVisibility,
       
   483                                                    QVariant()));
       
   484     m_preeditString = qt_TDesC2QString(aNewInlineText);
       
   485     QInputMethodEvent event(m_preeditString, attributes);
       
   486     sendEvent(event);
       
   487 }
       
   488 
       
   489 void QCoeFepInputContext::SetInlineEditingCursorVisibilityL(TBool aCursorVisibility)
       
   490 {
       
   491     QWidget *w = focusWidget();
       
   492     if (!w)
       
   493         return;
       
   494 
       
   495     m_cursorVisibility = aCursorVisibility ? 1 : 0;
       
   496 
       
   497     QList<QInputMethodEvent::Attribute> attributes;
       
   498     attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor,
       
   499                                                    m_inlinePosition,
       
   500                                                    m_cursorVisibility,
       
   501                                                    QVariant()));
       
   502     QInputMethodEvent event(m_preeditString, attributes);
       
   503     sendEvent(event);
       
   504 }
       
   505 
       
   506 void QCoeFepInputContext::CancelFepInlineEdit()
       
   507 {
       
   508     QList<QInputMethodEvent::Attribute> attributes;
       
   509     QInputMethodEvent event(QLatin1String(""), attributes);
       
   510     event.setCommitString(QLatin1String(""), 0, 0);
       
   511     m_preeditString.clear();
       
   512     sendEvent(event);
       
   513 
       
   514     m_isEditing = false;
       
   515 }
       
   516 
       
   517 TInt QCoeFepInputContext::DocumentLengthForFep() const
       
   518 {
       
   519     QWidget *w = focusWidget();
       
   520     if (!w)
       
   521         return 0;
       
   522 
       
   523     QVariant variant = w->inputMethodQuery(Qt::ImSurroundingText);
       
   524     return variant.value<QString>().size() + m_preeditString.size();
       
   525 }
       
   526 
       
   527 TInt QCoeFepInputContext::DocumentMaximumLengthForFep() const
       
   528 {
       
   529     QWidget *w = focusWidget();
       
   530     if (!w)
       
   531         return 0;
       
   532 
       
   533     QVariant variant = w->inputMethodQuery(Qt::ImMaximumTextLength);
       
   534     int size;
       
   535     if (variant.isValid()) {
       
   536         size = variant.toInt();
       
   537     } else {
       
   538         size = INT_MAX; // Sensible default for S60.
       
   539     }
       
   540     return size;
       
   541 }
       
   542 
       
   543 void QCoeFepInputContext::SetCursorSelectionForFepL(const TCursorSelection& aCursorSelection)
       
   544 {
       
   545     QWidget *w = focusWidget();
       
   546     if (!w)
       
   547         return;
       
   548 
       
   549     int pos = aCursorSelection.iAnchorPos;
       
   550     int length = aCursorSelection.iCursorPos - pos;
       
   551 
       
   552     QList<QInputMethodEvent::Attribute> attributes;
       
   553     attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, pos, length, QVariant());
       
   554     QInputMethodEvent event(m_preeditString, attributes);
       
   555     sendEvent(event);
       
   556 }
       
   557 
       
   558 void QCoeFepInputContext::GetCursorSelectionForFep(TCursorSelection& aCursorSelection) const
       
   559 {
       
   560     QWidget *w = focusWidget();
       
   561     if (!w) {
       
   562         aCursorSelection.SetSelection(0,0);
       
   563         return;
       
   564     }
       
   565 
       
   566     int cursor = w->inputMethodQuery(Qt::ImCursorPosition).toInt() + m_preeditString.size();
       
   567     int anchor = w->inputMethodQuery(Qt::ImAnchorPosition).toInt() + m_preeditString.size();
       
   568     aCursorSelection.iAnchorPos = anchor;
       
   569     aCursorSelection.iCursorPos = cursor;
       
   570 }
       
   571 
       
   572 void QCoeFepInputContext::GetEditorContentForFep(TDes& aEditorContent, TInt aDocumentPosition,
       
   573         TInt aLengthToRetrieve) const
       
   574 {
       
   575     QWidget *w = focusWidget();
       
   576     if (!w) {
       
   577         aEditorContent.FillZ(aLengthToRetrieve);
       
   578         return;
       
   579     }
       
   580 
       
   581     QString text = w->inputMethodQuery(Qt::ImSurroundingText).value<QString>();
       
   582     // FEP expects the preedit string to be part of the editor content, so let's mix it in.
       
   583     int cursor = w->inputMethodQuery(Qt::ImCursorPosition).toInt();
       
   584     text.insert(cursor, m_preeditString);
       
   585     aEditorContent.Copy(qt_QString2TPtrC(text.mid(aDocumentPosition, aLengthToRetrieve)));
       
   586 }
       
   587 
       
   588 void QCoeFepInputContext::GetFormatForFep(TCharFormat& aFormat, TInt /* aDocumentPosition */) const
       
   589 {
       
   590     QWidget *w = focusWidget();
       
   591     if (!w) {
       
   592         aFormat = TCharFormat();
       
   593         return;
       
   594     }
       
   595 
       
   596     QFont font = w->inputMethodQuery(Qt::ImFont).value<QFont>();
       
   597     QFontMetrics metrics(font);
       
   598     //QString name = font.rawName();
       
   599     QString name = font.defaultFamily(); // TODO! FIXME! Should be the above.
       
   600     QHBufC hBufC(name);
       
   601     aFormat = TCharFormat(hBufC->Des(), metrics.height());
       
   602 }
       
   603 
       
   604 void QCoeFepInputContext::GetScreenCoordinatesForFepL(TPoint& aLeftSideOfBaseLine, TInt& aHeight,
       
   605         TInt& aAscent, TInt /* aDocumentPosition */) const
       
   606 {
       
   607     QWidget *w = focusWidget();
       
   608     if (!w) {
       
   609         aLeftSideOfBaseLine = TPoint(0,0);
       
   610         aHeight = 0;
       
   611         aAscent = 0;
       
   612         return;
       
   613     }
       
   614 
       
   615     QRect rect = w->inputMethodQuery(Qt::ImMicroFocus).value<QRect>();
       
   616     aLeftSideOfBaseLine.iX = rect.left();
       
   617     aLeftSideOfBaseLine.iY = rect.bottom();
       
   618 
       
   619     QFont font = w->inputMethodQuery(Qt::ImFont).value<QFont>();
       
   620     QFontMetrics metrics(font);
       
   621     aHeight = metrics.height();
       
   622     aAscent = metrics.ascent();
       
   623 }
       
   624 
       
   625 void QCoeFepInputContext::DoCommitFepInlineEditL()
       
   626 {
       
   627     commitCurrentString(true);
       
   628 }
       
   629 
       
   630 void QCoeFepInputContext::commitCurrentString(bool triggeredBySymbian)
       
   631 {
       
   632     if (m_preeditString.size() == 0) {
       
   633         return;
       
   634     }
       
   635 
       
   636     QList<QInputMethodEvent::Attribute> attributes;
       
   637     QInputMethodEvent event(QLatin1String(""), attributes);
       
   638     event.setCommitString(m_preeditString, 0, 0);//m_preeditString.size());
       
   639     m_preeditString.clear();
       
   640     sendEvent(event);
       
   641 
       
   642     m_isEditing = false;
       
   643 
       
   644     if (!triggeredBySymbian) {
       
   645         CCoeFep* fep = CCoeEnv::Static()->Fep();
       
   646         if (fep)
       
   647             fep->CancelTransaction();
       
   648     }
       
   649 }
       
   650 
       
   651 MCoeFepAwareTextEditor_Extension1* QCoeFepInputContext::Extension1(TBool& aSetToTrue)
       
   652 {
       
   653     aSetToTrue = ETrue;
       
   654     return this;
       
   655 }
       
   656 
       
   657 void QCoeFepInputContext::SetStateTransferingOwnershipL(MCoeFepAwareTextEditor_Extension1::CState* aState,
       
   658         TUid /*aTypeSafetyUid*/)
       
   659 {
       
   660     // Note: The S60 docs are wrong! See the State() function.
       
   661     if (m_fepState)
       
   662         delete m_fepState;
       
   663     m_fepState = static_cast<CAknEdwinState *>(aState);
       
   664 }
       
   665 
       
   666 MCoeFepAwareTextEditor_Extension1::CState* QCoeFepInputContext::State(TUid /*aTypeSafetyUid*/)
       
   667 {
       
   668     // Note: The S60 docs are horribly wrong when describing the
       
   669     // SetStateTransferingOwnershipL function and this function. They say that the former
       
   670     // sets a CState object identified by the TUid, and the latter retrieves it.
       
   671     // In reality, the CState is expected to always be a CAknEdwinState (even if it was not
       
   672     // previously set), and the TUid is ignored. All in all, there is a single CAknEdwinState
       
   673     // per QCoeFepInputContext, which should be deleted if the SetStateTransferingOwnershipL
       
   674     // function is used to set a new one.
       
   675     return m_fepState;
       
   676 }
       
   677 
       
   678 TTypeUid::Ptr QCoeFepInputContext::MopSupplyObject(TTypeUid /*id*/)
       
   679 {
       
   680     return TTypeUid::Null();
       
   681 }
       
   682 
       
   683 QT_END_NAMESPACE
       
   684 
       
   685 #endif // QT_NO_IM