Ticket #40: ime.diff

File ime.diff, 28.7 KB (added by KO Myung-Hun, 11 years ago)

Implementation of QInputContext

  • configure.cmd

     
    902902
    903903    G.QCONFIG_FLAGS = Join(G.QCONFIG_FLAGS,,
    904904        "QT_NO_TABLET QT_NO_SYSTEMSEMAPHORE QT_NO_SHAREDMEMORY",
    905         "QT_NO_IM QT_NO_LPR")
     905        "QT_NO_LPR")
    906906
    907907    G.CFG_PHONON = "no"
    908908    G.CFG_MULTIMEDIA = "no"
  • src/gui/kernel/qapplication_pm.cpp

     
    6565#include "qcursor_p.h"
    6666#include "qdnd_p.h"
    6767
     68#ifndef QT_NO_IM
     69#include "private/qos2inputcontext_p.h"
     70#include <os2im.h>
     71#endif
     72
    6873#define WM_KBDLAYERCHANGED   0x0BD4 // defined in OS2TK45/h/pmbidi.h
    6974
    7075//#define QT_DEBUGMSGFLOW
     
    394399
    395400    if (QApplication::desktopSettingsAware())
    396401        qt_set_pm_resources();
     402
     403#ifndef QT_NO_IM
     404    QApplicationPrivate::inputContext = new QOS2InputContext();
     405#endif
    397406}
    398407
    399408/*****************************************************************************
     
    422431           qt_total_blit_ms, qt_total_blit_pixels,
    423432           qt_total_blit_pixels / qt_total_blit_ms);
    424433#endif
     434
     435#ifndef QT_NO_IM
     436    delete QApplicationPrivate::inputContext;
     437    QApplicationPrivate::inputContext = 0;
     438#endif
    425439}
    426440
    427441/*****************************************************************************
     
    10341048            }
    10351049
    10361050            case WM_QUERYCONVERTPOS: { // IME input box position request
    1037                 // @todo the proper detection of the caret position in the
    1038                 // current widget requires implementing QInputContext. For now,
    1039                 // just send the IME box to the lower left corner of the
    1040                 // top-level window
    10411051                PRECTL pcp = (PRECTL)mp1;
    10421052                memset(pcp, 0xFF, sizeof(RECTL));
    10431053                pcp->xLeft = 0;
    10441054                pcp->yBottom = 0;
     1055
     1056                QWidget *w = QApplication::focusWidget();
     1057                if(w) {
     1058                    QRect r = w->inputMethodQuery(Qt::ImMicroFocus).toRect();
     1059
     1060                    // The ime window positions are based on the WinId with active focus.
     1061                    QWidget *imeWnd = QWidget::find(WinQueryFocus(HWND_DESKTOP));
     1062                    if (imeWnd) {
     1063                        QPoint pt (r.bottomLeft());
     1064                        pt = w->mapToGlobal(pt);
     1065                        pt = imeWnd->mapFromGlobal(pt);
     1066
     1067                        pcp->xLeft = pt.x();
     1068                        pcp->xRight = pt.x() + r.width();
     1069                        // invert Y
     1070                        // bottom is exclusive and top is inclusive on Qt
     1071                        // bottom is inclusive and top is exclusive on OS/2
     1072                        pcp->yBottom = imeWnd->height() - pt.y();
     1073                        pcp->yTop = pcp->yBottom + r.height();
     1074                    }
     1075                }
     1076
    10451077                return (MRESULT)QCP_CONVERT;
    10461078            }
    10471079
     1080#ifndef QT_NO_IM
     1081            case WM_IMENOTIFY: {
     1082                QWidget *fw = QApplication::focusWidget();
     1083                QOS2InputContext *im = fw ? qobject_cast<QOS2InputContext *>(fw->inputContext()) : 0;
     1084                if (fw && im) {
     1085                    if (LONGFROMMP(mp1) == IMN_STARTCONVERSION)
     1086                        im->startComposition();
     1087                    else if (LONGFROMMP(mp1) == IMN_ENDCONVERSION)
     1088                        im->endComposition();
     1089                }
     1090
     1091                // do not consume WM_IMENOTIFY, especially IMN_STARTCONVERSION.
     1092                // otherwise, WM_QUERYCONVERTPOS does not work
     1093                break;
     1094            }
     1095
     1096            case WM_IMEREQUEST: {
     1097                QWidget *fw = QApplication::focusWidget();
     1098                QOS2InputContext *im = fw ? qobject_cast<QOS2InputContext *>(fw->inputContext()) : 0;
     1099                if (fw && im && LONGFROMMP(mp1) == IMR_CONVRESULT) {
     1100                    if (im->composition(LONGFROMMP(mp2)))
     1101                        return (MRESULT)TRUE;
     1102                }
     1103
     1104                break;
     1105            }
     1106#endif
     1107
    10481108            case WM_PAINT: { // paint event
    10491109                if (widget->translatePaintEvent(qmsg))
    10501110                    return (MRESULT)TRUE;
  • src/gui/inputmethod/qos2inputcontext_pm.cpp

     
     1/****************************************************************************
     2**
     3** Copyright (C) 2011 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 module of the Qt Toolkit.
     8**
     9** $QT_BEGIN_LICENSE:LGPL$
     10** Commercial Usage
     11** Licensees holding valid Qt Commercial licenses may use this file in
     12** accordance with the Qt Commercial License Agreement provided with the
     13** Software or, alternatively, in accordance with the terms contained in
     14** a written agreement between you and Nokia.
     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** GNU General Public License Usage
     29** Alternatively, this file may be used under the terms of the GNU
     30** General Public License version 3.0 as published by the Free Software
     31** Foundation and appearing in the file LICENSE.GPL included in the
     32** packaging of this file.  Please review the following information to
     33** ensure the GNU General Public License version 3.0 requirements will be
     34** met: http://www.gnu.org/copyleft/gpl.html.
     35**
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
     38** $QT_END_LICENSE$
     39**
     40****************************************************************************/
     41
     42#include "qos2inputcontext_p.h"
     43#include "qinputcontext_p.h"
     44
     45#include "qfont.h"
     46#include "qwidget.h"
     47#include "qapplication.h"
     48#include "qevent.h"
     49#include "qtextformat.h"
     50#include "qtextboundaryfinder.h"
     51
     52//#define Q_IME_DEBUG
     53
     54#ifdef Q_IME_DEBUG
     55#include "qdebug.h"
     56#endif
     57
     58#include <os2im.h>
     59
     60QT_BEGIN_NAMESPACE
     61
     62bool qt_sendSpontaneousEvent(QObject*, QEvent*);
     63
     64static QString *imeComposition = 0;
     65static int      imePosition    = -1;
     66static bool     haveCursor     = false;
     67
     68static HMODULE im32Mod = NULLHANDLE;
     69static APIRET (APIENTRY *im32AssociateInstance)(HWND, HIMI, PHIMI);
     70static APIRET (APIENTRY *im32GetInstance)(HWND, PHIMI);
     71static APIRET (APIENTRY *im32ReleaseInstance)(HWND, HIMI);
     72static APIRET (APIENTRY *im32GetConversionString)(HIMI, ULONG, PVOID, PULONG);
     73static APIRET (APIENTRY *im32GetResultString)(HIMI, ULONG, PVOID, PULONG);
     74static APIRET (APIENTRY *im32RequestIme)(HIMI, ULONG, ULONG, ULONG);
     75
     76static void loadIme()
     77{
     78    if (im32Mod)
     79        return;
     80
     81    CHAR  szName[CCHMAXPATH];
     82    ULONG rc;
     83
     84    rc = DosLoadModule(szName, sizeof(szName), "os2im", &im32Mod);
     85
     86    if (!rc)
     87        rc = DosQueryProcAddr(im32Mod, 101, NULL,
     88                              (PFN *)&im32AssociateInstance);
     89
     90    if (!rc)
     91        rc = DosQueryProcAddr(im32Mod, 104, NULL, (PFN *)&im32GetInstance);
     92
     93    if (!rc)
     94        rc = DosQueryProcAddr(im32Mod, 106, NULL, (PFN *)&im32ReleaseInstance);
     95
     96    if (!rc)
     97        rc = DosQueryProcAddr(im32Mod, 118, NULL,
     98                              (PFN *)&im32GetConversionString);
     99
     100    if (!rc)
     101        rc = DosQueryProcAddr(im32Mod, 122, NULL, (PFN *)&im32GetResultString);
     102
     103    if (!rc)
     104        rc = DosQueryProcAddr(im32Mod, 131, NULL, (PFN *)&im32RequestIme);
     105
     106    if (rc) {
     107      DosFreeModule(im32Mod);
     108
     109      im32Mod = NULLHANDLE;
     110    }
     111}
     112
     113static int getCursorPosition(HIMI himi)
     114{
     115    ULONG len = 256;
     116    CHAR  buffer[len];
     117
     118    if (im32GetConversionString(himi, IMR_CONV_CONVERSIONSTRING, buffer, &len))
     119        return 0;
     120
     121    ULONG cursorPos;
     122    ULONG cursorPosLen = sizeof(cursorPos);
     123
     124    if (im32GetConversionString(himi, IMR_CONV_CURSORPOS, &cursorPos,
     125                                &cursorPosLen))
     126        return 0;
     127
     128    return QString::fromLocal8Bit(buffer, cursorPos).length();
     129}
     130
     131static QString getString(HIMI himi, ULONG ulIndex, int *selStart = 0,
     132                         int *selLength = 0)
     133{
     134    const int bufferSize = 256;
     135    ULONG len = bufferSize;
     136    CHAR  buffer[len];
     137
     138    if (ulIndex == IMR_CONV_CONVERSIONSTRING) {
     139        if (im32GetConversionString(himi, ulIndex, buffer, &len))
     140            len = 0;
     141    } else if (ulIndex == IMR_RESULT_RESULTSTRING) {
     142        if (im32GetResultString(himi, ulIndex, buffer, &len))
     143            len = 0;
     144    } else
     145        len = 0;
     146
     147    if (ulIndex == IMR_CONV_CONVERSIONSTRING && selStart) {
     148        ULONG attrLen = bufferSize;
     149        CHAR  attrBuffer[attrLen];
     150        if (im32GetConversionString(himi, IMR_CONV_CONVERSIONATTR, attrBuffer,
     151                                    &attrLen))
     152            attrLen = 0;
     153
     154        *selStart  = QString::fromLocal8Bit(buffer, attrLen).length() + 1;
     155        *selLength = -1;
     156        for (int i = 0; i < (LONG)attrLen; i++) {
     157            if (attrBuffer[i] & CP_ATTR_TARGET_CONVERTED) {
     158                int index = QString::fromLocal8Bit(buffer, i).length();
     159
     160                *selStart  = qMin(*selStart, index);
     161                *selLength = qMax(*selLength, index);
     162            }
     163        }
     164
     165        *selLength = qMax(0, *selLength - *selStart + 1);
     166    }
     167
     168    if (len <= 0)
     169        return QString();
     170
     171    return QString::fromLocal8Bit(buffer, len);
     172}
     173
     174QOS2InputContext::QOS2InputContext(QObject *parent)
     175    : QInputContext(parent), recursionGuard(false)
     176{
     177    loadIme();
     178}
     179
     180QOS2InputContext::~QOS2InputContext()
     181{
     182    delete imeComposition;
     183    imeComposition = 0;
     184}
     185
     186void QOS2InputContext::update()
     187{
     188    if (!im32Mod)
     189        return;
     190
     191    QWidget *w = focusWidget();
     192    if(!w)
     193        return;
     194
     195    Q_ASSERT(w->testAttribute(Qt::WA_WState_Created));
     196
     197    HIMI himi;
     198
     199    if (im32GetInstance(w->effectiveWinId(), &himi))
     200        return;
     201
     202    QRect r = w->inputMethodQuery(Qt::ImMicroFocus).toRect();
     203
     204    // The ime window positions are based on the WinId with active focus.
     205    QWidget *imeWnd = QWidget::find(::WinQueryFocus(HWND_DESKTOP));
     206    if (imeWnd) {
     207        QPoint pt (r.bottomLeft());
     208        pt = w->mapToGlobal(pt);
     209        pt = imeWnd->mapFromGlobal(pt);
     210
     211        // invert Y
     212        // bottom is exclusive on Qt
     213        pt.setY(imeWnd->height() - pt.y());
     214
     215        if(haveCursor)
     216            WinCreateCursor(imeWnd->effectiveWinId(), pt.x(), pt.y(), 0, 0,
     217                            CURSOR_SETPOS, NULL);
     218    }
     219
     220    // todo : set composition font, composition window
     221    // BTW is this really needed ?
     222
     223    im32ReleaseInstance(w->effectiveWinId(), himi);
     224}
     225
     226
     227bool QOS2InputContext::endComposition()
     228{
     229    QWidget *fw = focusWidget();
     230#ifdef Q_IME_DEBUG
     231    qDebug("endComposition! fw = %s",
     232           fw ? qPrintable(fw->objectName()) : "(null)");
     233#endif
     234
     235    if (!im32Mod)
     236        return false;
     237
     238    bool result = true;
     239    if(imePosition == -1 || recursionGuard)
     240        return result;
     241
     242    // Googles Pinyin Input Method likes to call endComposition again
     243    // when we call notifyIME with CPS_CANCEL, so protect ourselves
     244    // against that.
     245    recursionGuard = true;
     246
     247    if (fw) {
     248        Q_ASSERT(fw->testAttribute(Qt::WA_WState_Created));
     249        HIMI himi;
     250        im32GetInstance(fw->effectiveWinId(), &himi);
     251        im32RequestIme(himi, REQ_CONVERSIONSTRING, CNV_CANCEL, 0);
     252        im32ReleaseInstance(fw->effectiveWinId(), himi);
     253        if(haveCursor) {
     254            WinDestroyCursor(fw->effectiveWinId());
     255            haveCursor = false;
     256        }
     257    }
     258
     259    if (!fw)
     260        fw = QApplication::focusWidget();
     261
     262    if (fw) {
     263        QInputMethodEvent e;
     264        result = qt_sendSpontaneousEvent(fw, &e);
     265    }
     266
     267    if (imeComposition)
     268        imeComposition->clear();
     269    imePosition = -1;
     270
     271    recursionGuard = false;
     272
     273    return result;
     274}
     275
     276void QOS2InputContext::reset()
     277{
     278    QWidget *fw = focusWidget();
     279
     280#ifdef Q_IME_DEBUG
     281    qDebug("sending accept to focus widget %s",
     282           fw ? qPrintable(fw->objectName()) : "(null)");
     283#endif
     284
     285    if (!im32Mod)
     286        return;
     287
     288    if (fw && imePosition != -1) {
     289        QInputMethodEvent e;
     290        if (imeComposition)
     291            e.setCommitString(*imeComposition);
     292         qt_sendSpontaneousEvent(fw, &e);
     293    }
     294
     295    if (imeComposition)
     296        imeComposition->clear();
     297    imePosition = -1;
     298
     299    if (fw) {
     300        Q_ASSERT(fw->testAttribute(Qt::WA_WState_Created));
     301        HIMI himi;
     302        im32GetInstance(fw->effectiveWinId(), &himi);
     303        im32RequestIme(himi, REQ_CONVERSIONSTRING, CNV_CANCEL, 0);
     304        im32ReleaseInstance(fw->effectiveWinId(), himi);
     305    }
     306}
     307
     308
     309bool QOS2InputContext::startComposition()
     310{
     311#ifdef Q_IME_DEBUG
     312    qDebug("startComposition");
     313#endif
     314
     315    if (!im32Mod)
     316        return false;
     317
     318    if (!imeComposition)
     319        imeComposition = new QString();
     320
     321    QWidget *fw = focusWidget();
     322    if (fw) {
     323        Q_ASSERT(fw->testAttribute(Qt::WA_WState_Created));
     324        imePosition = 0;
     325        haveCursor = WinCreateCursor(fw->effectiveWinId(), 0, 0, 1, 1,
     326                                     CURSOR_SOLID, NULL);
     327        WinShowCursor(fw->effectiveWinId(), FALSE);
     328        update();
     329    }
     330    return fw != 0;
     331}
     332
     333enum StandardFormat {
     334    PreeditFormat,
     335    SelectionFormat
     336};
     337
     338bool QOS2InputContext::composition(ULONG mp2)
     339{
     340#ifdef Q_IME_DEBUG
     341    QString str;
     342    if (mp2 & IMR_RESULT_RESULTSTRING)
     343        str += QLatin1String("RESULTSTRING ");
     344    if (mp2 & IMR_CONV_CONVERSIONSTRING)
     345        str += QLatin1String("CONVERSIONSTRING ");
     346    if (mp2 & IMR_CONV_CONVERSIONATTR)
     347        str += QLatin1String("CONVERSIONATTR ");
     348    if (mp2 & IMR_CONV_CURSORPOS)
     349        str += QLatin1String("CURSORPOS ");
     350    if (mp2 & IMR_CONV_CONVERSIONCLAUSE)
     351        str += QLatin1String("CONVERSIONCLAUSE ");
     352    if (mp2 & IMR_CONV_INSERTCHAR)
     353       str += QLatin1String("INSERTCHAR ");
     354    if (mp2 & IMR_CONV_NOMOVECARET)
     355       str += QLatin1String("NOMOVECARET ");
     356    if (mp2 & IMR_CONV_CONVERSIONPOS)
     357       str += QLatin1String("CONVERSIONPOS ");
     358    qDebug("composition, mp2=(%lx) %s imePosition=%d",
     359           mp2, qPrintable(str), imePosition);
     360#endif
     361
     362    if (!im32Mod)
     363        return false;
     364
     365    bool result = true;
     366
     367    QWidget *fw = QApplication::focusWidget();
     368    if (fw) {
     369        Q_ASSERT(fw->testAttribute(Qt::WA_WState_Created));
     370        HIMI himi;
     371        im32GetInstance(fw->effectiveWinId(), &himi);
     372        QInputMethodEvent e;
     373        if (mp2 & (IMR_CONV_CONVERSIONSTRING |
     374                   IMR_CONV_CONVERSIONATTR |
     375                   IMR_CONV_CURSORPOS)) {
     376            if (imePosition == -1)
     377                // need to send a start event
     378                startComposition();
     379
     380            // some intermediate composition result
     381            int selStart, selLength;
     382            *imeComposition = getString(himi, IMR_CONV_CONVERSIONSTRING,
     383                                        &selStart, &selLength);
     384            imePosition = getCursorPosition(himi);
     385            if ((mp2 & IMR_CONV_INSERTCHAR) && (mp2 & IMR_CONV_NOMOVECARET)) {
     386                // make korean work correctly. Hope this is correct for all IMEs
     387                selStart = 0;
     388                selLength = imeComposition->length();
     389            }
     390            if(selLength == 0)
     391                selStart = 0;
     392
     393           QList<QInputMethodEvent::Attribute> attrs;
     394           if (selStart > 0)
     395               attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, selStart,
     396                                            standardFormat(PreeditFormat));
     397           if (selLength)
     398               attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, selStart, selLength,
     399                                            standardFormat(SelectionFormat));
     400           if (selStart + selLength < imeComposition->length())
     401               attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, selStart + selLength,
     402                                            imeComposition->length() - selStart - selLength,
     403                                            standardFormat(PreeditFormat));
     404           if(imePosition >= 0)
     405               attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, imePosition, selLength ? 0 : 1, QVariant());
     406
     407           e = QInputMethodEvent(*imeComposition, attrs);
     408        }
     409
     410        if (mp2 & IMR_RESULT_RESULTSTRING) {
     411            if(imePosition == -1)
     412                startComposition();
     413            // a fixed result, return the converted string
     414            *imeComposition = getString(himi, IMR_RESULT_RESULTSTRING);
     415            imePosition = -1;
     416            e.setCommitString(*imeComposition);
     417            imeComposition->clear();
     418        }
     419
     420        if (!e.preeditString().isEmpty() || !e.commitString().isEmpty())
     421            result = qt_sendSpontaneousEvent(fw, &e);
     422
     423        update();
     424        im32ReleaseInstance(fw->effectiveWinId(), himi);
     425    }
     426#ifdef Q_IME_DEBUG
     427    qDebug("imecomposition: cursor pos at %d, result=%d", imePosition, result);
     428#endif
     429    return result;
     430}
     431
     432static HIMI defaultInstance = 0;
     433
     434// checks whether widget is a popup
     435inline bool isPopup(QWidget *w)
     436{
     437    if (w && (w->windowFlags() & Qt::Popup) == Qt::Popup)
     438        return true;
     439    else
     440        return false;
     441}
     442// checks whether widget is in a popup
     443inline bool isInPopup(QWidget *w)
     444{
     445    if (w && (isPopup(w) ||  isPopup(w->window())))
     446        return true;
     447    else
     448        return false;
     449}
     450
     451// find the parent widget, which is a non popup toplevel
     452// this is valid only if the widget is/in a popup
     453inline QWidget *findParentforPopup(QWidget *w)
     454{
     455    QWidget *e = QWidget::find(w->effectiveWinId());
     456    // check if this or its parent is a popup
     457    while (isInPopup(e)) {
     458        e = e->window()->parentWidget();
     459        if (!e)
     460            break;
     461        e = QWidget::find(e->effectiveWinId());
     462    }
     463    if (e)
     464        return e->window();
     465    else
     466        return 0;
     467}
     468
     469// enables or disables the ime
     470inline void enableIme(QWidget *w,  bool value)
     471{
     472    if (!im32Mod)
     473        return;
     474
     475    HIMI oldInstance;
     476    if (value) {
     477        // enable ime
     478        if (defaultInstance)
     479            im32AssociateInstance(w->effectiveWinId(), defaultInstance,
     480                                  &oldInstance);
     481    } else {
     482        // disable ime
     483        im32AssociateInstance(w->effectiveWinId(), NULL, &oldInstance);
     484        if (!defaultInstance)
     485            defaultInstance = oldInstance;
     486    }
     487}
     488
     489
     490void QOS2InputContext::updateImeStatus(QWidget *w, bool hasFocus)
     491{
     492    if (!w)
     493        return;
     494    // It's always the proxy that carries the hints.
     495    QWidget *focusProxyWidget = w->focusProxy();
     496    if (!focusProxyWidget)
     497        focusProxyWidget = w;
     498    bool e = w->testAttribute(Qt::WA_InputMethodEnabled) && w->isEnabled()
     499            && !(focusProxyWidget->inputMethodHints() & (Qt::ImhExclusiveInputMask | Qt::ImhHiddenText));
     500    bool hasIme = e && hasFocus;
     501#ifdef Q_IME_DEBUG
     502    qDebug("%s HasFocus = %d hasIme = %d e = %d ",
     503           qPrintable(w->objectName()), hasFocus, hasIme, e);
     504#endif
     505    if (hasFocus || e) {
     506        if (isInPopup(w))
     507            QOS2InputContext::enablePopupChild(w, hasIme);
     508        else
     509            QOS2InputContext::enable(w, hasIme);
     510    }
     511}
     512
     513void QOS2InputContext::enablePopupChild(QWidget *w, bool e)
     514{
     515    if (!w || !isInPopup(w))
     516        return;
     517#ifdef Q_IME_DEBUG
     518    qDebug("enablePopupChild: w=%s, enable = %s",
     519           w ? qPrintable(w->objectName()) : "(null)" , e ? "true" : "false");
     520#endif
     521    QWidget *parent = findParentforPopup(w);
     522    if (parent) {
     523        // update ime status of the normal toplevel parent of the popup
     524        enableIme(parent, e);
     525    }
     526    QWidget *toplevel = w->window();
     527    if (toplevel) {
     528        // update ime status of the toplevel popup
     529        enableIme(toplevel, e);
     530    }
     531}
     532
     533void QOS2InputContext::enable(QWidget *w, bool e)
     534{
     535    if(w) {
     536#ifdef Q_IME_DEBUG
     537        qDebug("enable: w=%s, enable = %s",
     538               w ? qPrintable(w->objectName()) : "(null)",
     539               e ? "true" : "false");
     540#endif
     541        if (!w->testAttribute(Qt::WA_WState_Created))
     542            return;
     543
     544        // update ime status on the widget
     545        QWidget *p = QWidget::find(w->effectiveWinId());
     546        if (p)
     547            enableIme(p, e);
     548    }
     549}
     550
     551void QOS2InputContext::setFocusWidget(QWidget *w)
     552{
     553    QWidget *oldFocus = focusWidget();
     554    if (oldFocus == w)
     555        return;
     556    if (w) {
     557        QOS2InputContext::updateImeStatus(w, true);
     558    } else {
     559        if (oldFocus)
     560            QOS2InputContext::updateImeStatus(oldFocus , false);
     561    }
     562    QInputContext::setFocusWidget(w);
     563    update();
     564}
     565
     566bool QOS2InputContext::isComposing() const
     567{
     568    return imeComposition && !imeComposition->isEmpty();
     569}
     570
     571void QOS2InputContext::mouseHandler(int pos, QMouseEvent *e)
     572{
     573    if(e->type() != QEvent::MouseButtonPress)
     574        return;
     575
     576#ifdef Q_IME_DEBUG
     577    qDebug("mouseHandler: pos=%d, length = %d", pos, imeComposition->length());
     578#endif
     579
     580    if (1 || pos < 0 || pos > imeComposition->length())
     581        reset();
     582}
     583
     584QString QOS2InputContext::language()
     585{
     586    return QString();
     587}
     588
     589QT_END_NAMESPACE
  • src/gui/inputmethod/inputmethod.pri

     
    1515    HEADERS += inputmethod/qwininputcontext_p.h
    1616    SOURCES += inputmethod/qwininputcontext_win.cpp
    1717}
     18os2 {
     19    HEADERS += inputmethod/qos2inputcontext_p.h
     20    SOURCES += inputmethod/qos2inputcontext_pm.cpp
     21}
    1822embedded {
    1923    HEADERS += inputmethod/qwsinputcontext_p.h
    2024    SOURCES += inputmethod/qwsinputcontext_qws.cpp
  • src/gui/inputmethod/qinputcontextfactory.cpp

     
    6868#ifdef Q_WS_WIN
    6969#include "qwininputcontext_p.h"
    7070#endif
     71#ifdef Q_WS_PM
     72#include "qos2inputcontext_p.h"
     73#endif
    7174#ifdef Q_WS_MAC
    7275#include "qmacinputcontext_p.h"
    7376#endif
     
    143146        result = new QWinInputContext;
    144147    }
    145148#endif
     149#if defined(Q_WS_PM)
     150    if (key == QLatin1String("os2")) {
     151        result = new QOS2InputContext;
     152    }
     153#endif
    146154#if defined(Q_WS_MAC)
    147155    if (key == QLatin1String("mac")) {
    148156        result = new QMacInputContext;
     
    187195#if defined(Q_WS_WIN) && !defined(QT_NO_XIM)
    188196    result << QLatin1String("win");
    189197#endif
     198#if defined(Q_WS_PM) && !defined(QT_NO_XIM)
     199    result << QLatin1String("os2");
     200#endif
    190201#if defined(Q_WS_MAC)
    191202    result << QLatin1String("mac");
    192203#endif
     
    260271    if (key == QLatin1String("win"))
    261272        return QStringList(QString());
    262273#endif
     274#if defined(Q_WS_PM)
     275    if (key == QLatin1String("os2"))
     276        return QStringList(QString());
     277#endif
    263278#if defined(Q_WS_MAC)
    264279    if (key == QLatin1String("mac"))
    265280        return QStringList(QString());
     
    331346    if (key == QLatin1String("win"))
    332347        return QInputContext::tr( "Windows input method" );
    333348#endif
     349#if defined(Q_WS_PM) && !defined(QT_NO_XIM)
     350    if (key == QLatin1String("os2"))
     351        return QInputContext::tr( "OS/2 input method" );
     352#endif
    334353#if defined(Q_WS_MAC)
    335354    if (key == QLatin1String("mac"))
    336355        return QInputContext::tr( "Mac OS X input method" );
  • src/gui/inputmethod/qos2inputcontext_p.h

     
     1/****************************************************************************
     2**
     3** Copyright (C) 2011 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 module of the Qt Toolkit.
     8**
     9** $QT_BEGIN_LICENSE:LGPL$
     10** Commercial Usage
     11** Licensees holding valid Qt Commercial licenses may use this file in
     12** accordance with the Qt Commercial License Agreement provided with the
     13** Software or, alternatively, in accordance with the terms contained in
     14** a written agreement between you and Nokia.
     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** GNU General Public License Usage
     29** Alternatively, this file may be used under the terms of the GNU
     30** General Public License version 3.0 as published by the Free Software
     31** Foundation and appearing in the file LICENSE.GPL included in the
     32** packaging of this file.  Please review the following information to
     33** ensure the GNU General Public License version 3.0 requirements will be
     34** met: http://www.gnu.org/copyleft/gpl.html.
     35**
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
     38** $QT_END_LICENSE$
     39**
     40****************************************************************************/
     41
     42#ifndef QOS2INPUTCONTEXT_P_H
     43#define QOS2INPUTCONTEXT_P_H
     44
     45//
     46//  W A R N I N G
     47//  -------------
     48//
     49// This file is not part of the Qt API.  It exists for the convenience
     50// of qinputcontext.cpp.  This header file may change from version to
     51// version without notice, or even be removed.
     52//
     53// We mean it.
     54//
     55
     56#include "QtGui/qinputcontext.h"
     57#include "QtCore/qt_os2.h"
     58
     59QT_BEGIN_NAMESPACE
     60
     61class QOS2InputContext : public QInputContext
     62{
     63    Q_OBJECT
     64public:
     65    explicit QOS2InputContext(QObject* parent = 0);
     66    virtual ~QOS2InputContext();
     67
     68    virtual QString identifierName() { return QLatin1String("os2"); }
     69    virtual QString language();
     70
     71    virtual void reset();
     72    virtual void update();
     73
     74    virtual void mouseHandler(int x, QMouseEvent *event);
     75    virtual bool isComposing() const;
     76
     77    virtual void setFocusWidget(QWidget *w);
     78
     79    bool startComposition();
     80    bool endComposition();
     81    bool composition(ULONG mp2);
     82
     83    static void updateImeStatus(QWidget *w, bool hasFocus);
     84    static void enablePopupChild(QWidget *w, bool e);
     85    static void enable(QWidget *w, bool e);
     86
     87private:
     88    bool recursionGuard;
     89};
     90
     91QT_END_NAMESPACE
     92
     93#endif // QOS2INPUTCONTEXT_P_H
  • include/QtGui/private/qos2inputcontext_p.h

     
     1#include "../../../src/gui/inputmethod/qos2inputcontext_p.h"