summaryrefslogtreecommitdiffstats
path: root/src/gui/inputmethod
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2009-03-23 09:34:13 (GMT)
committerSimon Hausmann <simon.hausmann@nokia.com>2009-03-23 09:34:13 (GMT)
commit67ad0519fd165acee4a4d2a94fa502e9e4847bd0 (patch)
tree1dbf50b3dff8d5ca7e9344733968c72704eb15ff /src/gui/inputmethod
downloadQt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.zip
Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.tar.gz
Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.tar.bz2
Long live Qt!
Diffstat (limited to 'src/gui/inputmethod')
-rw-r--r--src/gui/inputmethod/inputmethod.pri26
-rw-r--r--src/gui/inputmethod/qinputcontext.cpp464
-rw-r--r--src/gui/inputmethod/qinputcontext.h134
-rw-r--r--src/gui/inputmethod/qinputcontext_p.h98
-rw-r--r--src/gui/inputmethod/qinputcontextfactory.cpp287
-rw-r--r--src/gui/inputmethod/qinputcontextfactory.h88
-rw-r--r--src/gui/inputmethod/qinputcontextplugin.cpp178
-rw-r--r--src/gui/inputmethod/qinputcontextplugin.h106
-rw-r--r--src/gui/inputmethod/qmacinputcontext_mac.cpp349
-rw-r--r--src/gui/inputmethod/qmacinputcontext_p.h92
-rw-r--r--src/gui/inputmethod/qwininputcontext_p.h96
-rw-r--r--src/gui/inputmethod/qwininputcontext_win.cpp861
-rw-r--r--src/gui/inputmethod/qwsinputcontext_p.h96
-rw-r--r--src/gui/inputmethod/qwsinputcontext_qws.cpp239
-rw-r--r--src/gui/inputmethod/qximinputcontext_p.h141
-rw-r--r--src/gui/inputmethod/qximinputcontext_x11.cpp832
16 files changed, 4087 insertions, 0 deletions
diff --git a/src/gui/inputmethod/inputmethod.pri b/src/gui/inputmethod/inputmethod.pri
new file mode 100644
index 0000000..d321cd4
--- /dev/null
+++ b/src/gui/inputmethod/inputmethod.pri
@@ -0,0 +1,26 @@
+# Qt inputmethod module
+
+HEADERS +=inputmethod/qinputcontextfactory.h \
+ inputmethod/qinputcontextplugin.h \
+ inputmethod/qinputcontext_p.h \
+ inputmethod/qinputcontext.h
+SOURCES +=inputmethod/qinputcontextfactory.cpp \
+ inputmethod/qinputcontextplugin.cpp \
+ inputmethod/qinputcontext.cpp
+x11 {
+ HEADERS += inputmethod/qximinputcontext_p.h
+ SOURCES += inputmethod/qximinputcontext_x11.cpp
+}
+win32 {
+ HEADERS += inputmethod/qwininputcontext_p.h
+ SOURCES += inputmethod/qwininputcontext_win.cpp
+}
+embedded {
+ HEADERS += inputmethod/qwsinputcontext_p.h
+ SOURCES += inputmethod/qwsinputcontext_qws.cpp
+}
+mac:!embedded {
+ HEADERS += inputmethod/qmacinputcontext_p.h
+ SOURCES += inputmethod/qmacinputcontext_mac.cpp
+}
+
diff --git a/src/gui/inputmethod/qinputcontext.cpp b/src/gui/inputmethod/qinputcontext.cpp
new file mode 100644
index 0000000..f78b86a
--- /dev/null
+++ b/src/gui/inputmethod/qinputcontext.cpp
@@ -0,0 +1,464 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/****************************************************************************
+**
+** Implementation of QInputContext class
+**
+** Copyright (C) 2003-2004 immodule for Qt Project. All rights reserved.
+**
+** This file is written to contribute to Nokia Corporation and/or its subsidiary(-ies) under their own
+** license. You may use this file under your Qt license. Following
+** description is copied from their original file headers. Contact
+** immodule-qt@freedesktop.org if any conditions of this licensing are
+** not clear to you.
+**
+****************************************************************************/
+
+//#define QT_NO_IM_PREEDIT_RELOCATION
+
+#include "qinputcontext.h"
+#include "qinputcontext_p.h"
+
+#ifndef QT_NO_IM
+
+#include "qplatformdefs.h"
+
+#include "qapplication.h"
+#include "qmenu.h"
+#include "qtextformat.h"
+#include "qpalette.h"
+
+#include <stdlib.h>
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QInputContext
+ \brief The QInputContext class abstracts the input method dependent data and composing state.
+
+ \ingroup i18n
+
+ An input method is responsible to input complex text that cannot
+ be inputted via simple keymap. It converts a sequence of input
+ events (typically key events) into a text string through the input
+ method specific converting process. The class of the processes are
+ widely ranging from simple finite state machine to complex text
+ translator that pools a whole paragraph of a text with text
+ editing capability to perform grammar and semantic analysis.
+
+ To abstract such different input method specific intermediate
+ information, Qt offers the QInputContext as base class. The
+ concept is well known as 'input context' in the input method
+ domain. an input context is created for a text widget in response
+ to a demand. It is ensured that an input context is prepared for
+ an input method before input to a text widget.
+
+ Multiple input contexts that is belonging to a single input method
+ may concurrently coexist. Suppose multi-window text editor. Each
+ text widget of window A and B holds different QInputContext
+ instance which contains different state information such as
+ partially composed text.
+
+ \section1 Groups of Functions
+
+ \table
+ \header \o Context \o Functions
+
+ \row \o Receiving information \o
+ x11FilterEvent(),
+ filterEvent(),
+ mouseHandler()
+
+ \row \o Sending back composed text \o
+ sendEvent()
+
+ \row \o State change notification \o
+ setFocusWidget(),
+ reset()
+
+ \row \o Context information \o
+ identifierName(),
+ language(),
+ font(),
+ isComposing()
+
+ \endtable
+
+ \legalese
+ Copyright (C) 2003-2004 immodule for Qt Project. All rights reserved.
+
+ This file is written to contribute to Nokia Corporation and/or its subsidiary(-ies) under their own
+ license. You may use this file under your Qt license. Following
+ description is copied from their original file headers. Contact
+ immodule-qt@freedesktop.org if any conditions of this licensing are
+ not clear to you.
+ \endlegalese
+
+ \sa QInputContextPlugin, QInputContextFactory, QApplication::setInputContext()
+*/
+
+/*!
+ Constructs an input context with the given \a parent.
+*/
+QInputContext::QInputContext(QObject* parent)
+ : QObject(*new QInputContextPrivate, parent)
+{
+}
+
+
+/*!
+ Destroys the input context.
+*/
+QInputContext::~QInputContext()
+{
+}
+
+/*!
+ \internal
+ Returns the widget that has an input focus for this input
+ context. Ordinary input methods should not call this function
+ directly to keep platform independence and flexible configuration
+ possibility.
+
+ The return value may differ from holderWidget() if the input
+ context is shared between several text widgets.
+
+ \sa setFocusWidget(), holderWidget()
+*/
+QWidget *QInputContext::focusWidget() const
+{
+ Q_D(const QInputContext);
+ return d->focusWidget;
+}
+
+
+/*!
+ \internal
+ Sets the widget that has an input focus for this input
+ context. Ordinary input methods must not call this function
+ directly.
+
+ \sa focusWidget()
+*/
+void QInputContext::setFocusWidget(QWidget *widget)
+{
+ Q_ASSERT(!widget || widget->testAttribute(Qt::WA_InputMethodEnabled));
+ Q_D(QInputContext);
+ d->focusWidget = widget;
+}
+
+/*!
+ \fn bool QInputContext::isComposing() const
+
+ This function indicates whether InputMethodStart event had been
+ sent to the current focus widget. It is ensured that an input
+ context can send InputMethodCompose or InputMethodEnd event safely
+ if this function returned true.
+
+ The state is automatically being tracked through sendEvent().
+
+ \sa sendEvent()
+*/
+
+/*!
+ This function can be reimplemented in a subclass to filter input
+ events.
+
+ Return true if the \a event has been consumed. Otherwise, the
+ unfiltered \a event will be forwarded to widgets as ordinary
+ way. Although the input events have accept() and ignore()
+ methods, leave it untouched.
+
+ \a event is currently restricted to QKeyEvent. But some input
+ method related events such as QWheelEvent or QTabletEvent may be
+ added in future.
+
+ The filtering opportunity is always given to the input context as
+ soon as possible. It has to be taken place before any other key
+ event consumers such as eventfilters and accelerators because some
+ input methods require quite various key combination and
+ sequences. It often conflicts with accelerators and so on, so we
+ must give the input context the filtering opportunity first to
+ ensure all input methods work properly regardless of application
+ design.
+
+ Ordinary input methods require discrete key events to work
+ properly, so Qt's key compression is always disabled for any input
+ contexts.
+
+ \sa QKeyEvent, x11FilterEvent()
+*/
+bool QInputContext::filterEvent(const QEvent * /*event*/)
+{
+ return false;
+}
+
+/*!
+ Sends an input method event specified by \a event to the current focus
+ widget. Implementations of QInputContext should call this method to
+ send the generated input method events and not
+ QApplication::sendEvent(), as the events might have to get dispatched
+ to a different application on some platforms.
+
+ Some complex input methods route the handling to several child
+ contexts (e.g. to enable language switching). To account for this,
+ QInputContext will check if the parent object is a QInputContext. If
+ yes, it will call the parents sendEvent() implementation instead of
+ sending the event directly.
+
+ \sa QInputMethodEvent
+*/
+void QInputContext::sendEvent(const QInputMethodEvent &event)
+{
+ // route events over input context parents to make chaining possible.
+ QInputContext *p = qobject_cast<QInputContext *>(parent());
+ if (p) {
+ p->sendEvent(event);
+ return;
+ }
+
+ QWidget *focus = focusWidget();
+ if (!focus)
+ return;
+
+ QInputMethodEvent e(event);
+ qApp->sendEvent(focus, &e);
+}
+
+
+/*!
+ This function can be reimplemented in a subclass to handle mouse
+ press, release, double-click, and move events within the preedit
+ text. You can use the function to implement mouse-oriented user
+ interface such as text selection or popup menu for candidate
+ selection.
+
+ The \a x parameter is the offset within the string that was sent
+ with the InputMethodCompose event. The alteration boundary of \a
+ x is ensured as character boundary of preedit string accurately.
+
+ The \a event parameter is the event that was sent to the editor
+ widget. The event type is QEvent::MouseButtonPress,
+ QEvent::MouseButtonRelease, QEvent::MouseButtonDblClick or
+ QEvent::MouseButtonMove. The event's button and state indicate
+ the kind of operation that was performed.
+*/
+void QInputContext::mouseHandler(int /*x*/, QMouseEvent *event)
+{
+ // Default behavior for simple ephemeral input contexts. Some
+ // complex input contexts should not be reset here.
+ if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick)
+ reset();
+}
+
+
+/*!
+ Returns the font of the current input widget
+*/
+QFont QInputContext::font() const
+{
+ Q_D(const QInputContext);
+ if (!d->focusWidget)
+ return QApplication::font();
+
+ return qvariant_cast<QFont>(d->focusWidget->inputMethodQuery(Qt::ImFont));
+}
+
+/*!
+ This virtual function is called when a state in the focus widget
+ has changed. QInputContext can then use
+ QWidget::inputMethodQuery() to query the new state of the widget.
+*/
+void QInputContext::update()
+{
+}
+
+/*!
+ This virtual function is called when the specified \a widget is
+ destroyed. The \a widget is a widget on which this input context
+ is installed.
+*/
+void QInputContext::widgetDestroyed(QWidget *widget)
+{
+ Q_D(QInputContext);
+ if (widget == d->focusWidget)
+ setFocusWidget(0);
+}
+
+/*!
+ \fn void QInputContext::reset()
+
+ This function can be reimplemented in a subclass to reset the
+ state of the input method.
+
+ This function is called by several widgets to reset input
+ state. For example, a text widget call this function before
+ inserting a text to make widget ready to accept a text.
+
+ Default implementation is sufficient for simple input method. You
+ can override this function to reset external input method engines
+ in complex input method. In the case, call QInputContext::reset()
+ to ensure proper termination of inputting.
+
+ You must not send any QInputMethodEvent except empty InputMethodEnd event using
+ QInputContext::reset() at reimplemented reset(). It will break
+ input state consistency.
+*/
+
+
+/*!
+ \fn QString QInputContext::identifierName()
+
+ This function must be implemented in any subclasses to return the
+ identifier name of the input method.
+
+ Return value is the name to identify and specify input methods for
+ the input method switching mechanism and so on. The name has to be
+ consistent with QInputContextPlugin::keys(). The name has to
+ consist of ASCII characters only.
+
+ There are two different names with different responsibility in the
+ input method domain. This function returns one of them. Another
+ name is called 'display name' that stands for the name for
+ endusers appeared in a menu and so on.
+
+ \sa QInputContextPlugin::keys(), QInputContextPlugin::displayName()
+*/
+
+
+/*!
+ \fn QString QInputContext::language()
+
+ This function must be implemented in any subclasses to return a
+ language code (e.g. "zh_CN", "zh_TW", "zh_HK", "ja", "ko", ...)
+ of the input context. If the input context can handle multiple
+ languages, return the currently used one. The name has to be
+ consistent with QInputContextPlugin::language().
+
+ This information will be used by language tagging feature in
+ QInputMethodEvent. It is required to distinguish unified han characters
+ correctly. It enables proper font and character code
+ handling. Suppose CJK-awared multilingual web browser
+ (that automatically modifies fonts in CJK-mixed text) and XML editor
+ (that automatically inserts lang attr).
+*/
+
+
+/*!
+ This is a preliminary interface for Qt 4.
+*/
+QList<QAction *> QInputContext::actions()
+{
+ return QList<QAction *>();
+}
+
+/*!
+ \enum QInputContext::StandardFormat
+
+ \value PreeditFormat The preedit text.
+ \value SelectionFormat The selection text.
+
+ \sa standardFormat()
+*/
+
+/*!
+ Returns a QTextFormat object that specifies the format for
+ component \a s.
+*/
+QTextFormat QInputContext::standardFormat(StandardFormat s) const
+{
+ QWidget *focus = focusWidget();
+ const QPalette &pal = focus ? focus->palette() : qApp->palette();
+
+ QTextCharFormat fmt;
+ QColor bg;
+ switch (s) {
+ case QInputContext::PreeditFormat: {
+ fmt.setUnderlineStyle(QTextCharFormat::DashUnderline);
+#ifndef Q_WS_WIN
+ int h1, s1, v1, h2, s2, v2;
+ pal.color(QPalette::Base).getHsv(&h1, &s1, &v1);
+ pal.color(QPalette::Background).getHsv(&h2, &s2, &v2);
+ bg.setHsv(h1, s1, (v1 + v2) / 2);
+ fmt.setBackground(QBrush(bg));
+#endif
+ break;
+ }
+ case QInputContext::SelectionFormat: {
+ bg = pal.text().color();
+ fmt.setBackground(QBrush(bg));
+ fmt.setForeground(pal.background());
+ break;
+ }
+ }
+ return fmt;
+}
+
+#ifdef Q_WS_X11
+/*!
+ This function may be overridden only if input method is depending
+ on X11 and you need raw XEvent. Otherwise, this function must not.
+
+ This function is designed to filter raw key events for XIM, but
+ other input methods may use this to implement some special
+ features such as distinguishing Shift_L and Shift_R.
+
+ Return true if the \a event has been consumed. Otherwise, the
+ unfiltered \a event will be translated into QEvent and forwarded
+ to filterEvent(). Filtering at both x11FilterEvent() and
+ filterEvent() in single input method is allowed.
+
+ \a keywidget is a client widget into which a text is inputted. \a
+ event is inputted XEvent.
+
+ \sa filterEvent()
+*/
+bool QInputContext::x11FilterEvent(QWidget * /*keywidget*/, XEvent * /*event*/)
+{
+ return false;
+}
+#endif // Q_WS_X11
+
+QT_END_NAMESPACE
+
+#endif //Q_NO_IM
diff --git a/src/gui/inputmethod/qinputcontext.h b/src/gui/inputmethod/qinputcontext.h
new file mode 100644
index 0000000..bcaa7fe
--- /dev/null
+++ b/src/gui/inputmethod/qinputcontext.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/****************************************************************************
+**
+** Definition of QInputContext class
+**
+** Copyright (C) 2003-2004 immodule for Qt Project. All rights reserved.
+**
+** This file is written to contribute to Nokia Corporation and/or its subsidiary(-ies) under their own
+** license. You may use this file under your Qt license. Following
+** description is copied from their original file headers. Contact
+** immodule-qt@freedesktop.org if any conditions of this licensing are
+** not clear to you.
+**
+****************************************************************************/
+
+#ifndef QINPUTCONTEXT_H
+#define QINPUTCONTEXT_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qglobal.h>
+#include <QtGui/qevent.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qlist.h>
+#include <QtGui/qaction.h>
+
+#ifndef QT_NO_IM
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QWidget;
+class QFont;
+class QPopupMenu;
+class QInputContextPrivate;
+
+
+class Q_GUI_EXPORT QInputContext : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QInputContext)
+public:
+ explicit QInputContext(QObject* parent = 0);
+ virtual ~QInputContext();
+
+ virtual QString identifierName() = 0;
+ virtual QString language() = 0;
+
+ virtual void reset() = 0;
+ virtual void update();
+
+ virtual void mouseHandler( int x, QMouseEvent *event);
+ virtual QFont font() const;
+ virtual bool isComposing() const = 0;
+
+ QWidget *focusWidget() const;
+ virtual void setFocusWidget( QWidget *w );
+
+ virtual void widgetDestroyed(QWidget *w);
+
+ virtual QList<QAction *> actions();
+
+#if defined(Q_WS_X11)
+ virtual bool x11FilterEvent( QWidget *keywidget, XEvent *event );
+#endif // Q_WS_X11
+ virtual bool filterEvent( const QEvent *event );
+
+ void sendEvent(const QInputMethodEvent &event);
+
+ enum StandardFormat {
+ PreeditFormat,
+ SelectionFormat
+ };
+ QTextFormat standardFormat(StandardFormat s) const;
+private:
+ friend class QWidget;
+ friend class QWidgetPrivate;
+ friend class QInputContextFactory;
+ friend class QApplication;
+private: // Disabled copy constructor and operator=
+ QInputContext( const QInputContext & );
+ QInputContext &operator=( const QInputContext & );
+
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //Q_NO_IM
+
+#endif // QINPUTCONTEXT_H
diff --git a/src/gui/inputmethod/qinputcontext_p.h b/src/gui/inputmethod/qinputcontext_p.h
new file mode 100644
index 0000000..8c1b8de
--- /dev/null
+++ b/src/gui/inputmethod/qinputcontext_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+/****************************************************************************
+**
+** Implementation of QInputContext class
+**
+** Copyright (C) 2003-2004 immodule for Qt Project. All rights reserved.
+**
+** This file is written to contribute to Nokia Corporation and/or its subsidiary(-ies) under their own
+** license. You may use this file under your Qt license. Following
+** description is copied from their original file headers. Contact
+** immodule-qt@freedesktop.org if any conditions of this licensing are
+** not clear to you.
+**
+****************************************************************************/
+
+#ifndef QINPUTCONTEXT_P_H
+#define QINPUTCONTEXT_P_H
+
+#include "private/qobject_p.h"
+#include "qwidget.h"
+#include "qinputcontext.h"
+
+#ifndef QT_NO_IM
+
+QT_BEGIN_NAMESPACE
+
+class QInputContextPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QInputContext)
+public:
+ QInputContextPrivate()
+ : focusWidget(0)
+ {}
+
+ QWidget *focusWidget;
+
+#if defined(Q_WS_WIN) || defined(Q_WS_QWS)
+ static void updateImeStatus(QWidget *w, bool hasFocus);
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif
+
+#endif
+
diff --git a/src/gui/inputmethod/qinputcontextfactory.cpp b/src/gui/inputmethod/qinputcontextfactory.cpp
new file mode 100644
index 0000000..06625f9
--- /dev/null
+++ b/src/gui/inputmethod/qinputcontextfactory.cpp
@@ -0,0 +1,287 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/****************************************************************************
+**
+** Implementation of QInputContextFactory class
+**
+** Copyright (C) 2003-2004 immodule for Qt Project. All rights reserved.
+**
+** This file is written to contribute to Nokia Corporation and/or its subsidiary(-ies) under their own
+** license. You may use this file under your Qt license. Following
+** description is copied from their original file headers. Contact
+** immodule-qt@freedesktop.org if any conditions of this licensing are
+** not clear to you.
+**
+****************************************************************************/
+
+#include "qinputcontextfactory.h"
+
+#ifndef QT_NO_IM
+
+#include "qcoreapplication.h"
+#include "qinputcontext.h"
+#include "qinputcontextplugin.h"
+
+#ifdef Q_WS_X11
+#include "private/qt_x11_p.h"
+#include "qximinputcontext_p.h"
+#endif
+#ifdef Q_WS_WIN
+#include "qwininputcontext_p.h"
+#endif
+#ifdef Q_WS_MAC
+#include "qmacinputcontext_p.h"
+#endif
+
+#include "private/qfactoryloader_p.h"
+#include "qmutex.h"
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+ (QInputContextFactoryInterface_iid, QLatin1String("/inputmethods")))
+#endif
+
+/*!
+ \class QInputContextFactory
+ \brief The QInputContextFactory class creates QInputContext objects.
+
+ \ingroup appearance
+
+ The input context factory creates a QInputContext object for a
+ given key with QInputContextFactory::create().
+
+ The input contexts are either built-in or dynamically loaded from
+ an input context plugin (see QInputContextPlugin).
+
+ keys() returns a list of valid keys. The
+ keys are the names used, for example, to identify and specify
+ input methods for the input method switching mechanism. The names
+ have to be consistent with QInputContext::identifierName(), and
+ may only contain ASCII characters.
+
+ A key can be used to retrieve the associated input context's
+ supported languages using languages(). You
+ can retrieve the input context's description using
+ description() and finally you can get a user
+ friendly internationalized name of the QInputContext object
+ specified by the key using displayName().
+
+ \legalese
+ Copyright (C) 2003-2004 immodule for Qt Project. All rights reserved.
+
+ This file is written to contribute to Nokia Corporation and/or its subsidiary(-ies) under their own
+ license. You may use this file under your Qt license. Following
+ description is copied from their original file headers. Contact
+ immodule-qt@freedesktop.org if any conditions of this licensing are
+ not clear to you.
+ \endlegalese
+
+ \sa QInputContext, QInputContextPlugin
+*/
+
+/*!
+ Creates and returns a QInputContext object for the input context
+ specified by \a key with the given \a parent. Keys are case
+ sensitive.
+
+ \sa keys()
+*/
+QInputContext *QInputContextFactory::create( const QString& key, QObject *parent )
+{
+ QInputContext *result = 0;
+#if defined(Q_WS_X11) && !defined(QT_NO_XIM)
+ if (key == QLatin1String("xim")) {
+ result = new QXIMInputContext;
+ }
+#endif
+#if defined(Q_WS_WIN)
+ if (key == QLatin1String("win")) {
+ result = new QWinInputContext;
+ }
+#endif
+#if defined(Q_WS_MAC)
+ if (key == QLatin1String("mac")) {
+ result = new QMacInputContext;
+ }
+#endif
+#if defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
+ Q_UNUSED(key);
+#else
+ if (QInputContextFactoryInterface *factory =
+ qobject_cast<QInputContextFactoryInterface*>(loader()->instance(key))) {
+ result = factory->create(key);
+ }
+#endif
+ if (result)
+ result->setParent(parent);
+ return result;
+}
+
+
+/*!
+ Returns the list of keys this factory can create input contexts
+ for.
+
+ The keys are the names used, for example, to identify and specify
+ input methods for the input method switching mechanism. The names
+ have to be consistent with QInputContext::identifierName(), and
+ may only contain ASCII characters.
+
+ \sa create(), displayName(), QInputContext::identifierName()
+*/
+QStringList QInputContextFactory::keys()
+{
+ QStringList result;
+#if defined(Q_WS_X11) && !defined(QT_NO_XIM)
+ result << QLatin1String("xim");
+#endif
+#if defined(Q_WS_WIN) && !defined(QT_NO_XIM)
+ result << QLatin1String("win");
+#endif
+#if defined(Q_WS_MAC)
+ result << QLatin1String("mac");
+#endif
+#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
+ result += loader()->keys();
+#endif // QT_NO_LIBRARY
+ return result;
+}
+
+/*!
+ Returns the languages supported by the QInputContext object
+ specified by \a key.
+
+ The languages are expressed as language code (e.g. "zh_CN",
+ "zh_TW", "zh_HK", "ja", "ko", ...). An input context that supports
+ multiple languages can return all supported languages as a
+ QStringList. The name has to be consistent with
+ QInputContext::language().
+
+ This information may be used to optimize a user interface.
+
+ \sa keys(), QInputContext::language(), QLocale
+*/
+QStringList QInputContextFactory::languages( const QString &key )
+{
+ QStringList result;
+#if defined(Q_WS_X11) && !defined(QT_NO_XIM)
+ if (key == QLatin1String("xim"))
+ return QStringList(QString());
+#endif
+#if defined(Q_WS_WIN)
+ if (key == QLatin1String("win"))
+ return QStringList(QString());
+#endif
+#if defined(Q_WS_MAC)
+ if (key == QLatin1String("mac"))
+ return QStringList(QString());
+#endif
+#if defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
+ Q_UNUSED(key);
+#else
+ if (QInputContextFactoryInterface *factory =
+ qobject_cast<QInputContextFactoryInterface*>(loader()->instance(key)))
+ result = factory->languages(key);
+#endif // QT_NO_LIBRARY
+ return result;
+}
+
+/*!
+ Returns a user friendly internationalized name of the
+ QInputContext object specified by \a key. You can, for example,
+ use this name in a menu.
+
+ \sa keys(), QInputContext::identifierName()
+*/
+QString QInputContextFactory::displayName( const QString &key )
+{
+ QString result;
+#if defined(Q_WS_X11) && !defined(QT_NO_XIM)
+ if (key == QLatin1String("xim"))
+ return QInputContext::tr( "XIM" );
+#endif
+#if defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
+ Q_UNUSED(key);
+#else
+ if (QInputContextFactoryInterface *factory =
+ qobject_cast<QInputContextFactoryInterface*>(loader()->instance(key)))
+ return factory->displayName(key);
+#endif // QT_NO_LIBRARY
+ return QString();
+}
+
+/*!
+ Returns an internationalized brief description of the QInputContext
+ object specified by \a key. You can, for example, use this
+ description in a user interface.
+
+ \sa keys(), displayName()
+*/
+QString QInputContextFactory::description( const QString &key )
+{
+#if defined(Q_WS_X11) && !defined(QT_NO_XIM)
+ if (key == QLatin1String("xim"))
+ return QInputContext::tr( "XIM input method" );
+#endif
+#if defined(Q_WS_WIN) && !defined(QT_NO_XIM)
+ if (key == QLatin1String("win"))
+ return QInputContext::tr( "Windows input method" );
+#endif
+#if defined(Q_WS_MAC)
+ if (key == QLatin1String("mac"))
+ return QInputContext::tr( "Mac OS X input method" );
+#endif
+#if defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
+ Q_UNUSED(key);
+#else
+ if (QInputContextFactoryInterface *factory =
+ qobject_cast<QInputContextFactoryInterface*>(loader()->instance(key)))
+ return factory->description(key);
+#endif // QT_NO_LIBRARY
+ return QString();
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_IM
diff --git a/src/gui/inputmethod/qinputcontextfactory.h b/src/gui/inputmethod/qinputcontextfactory.h
new file mode 100644
index 0000000..bc17fd3
--- /dev/null
+++ b/src/gui/inputmethod/qinputcontextfactory.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/****************************************************************************
+**
+** Definition of QInputContextFactory class
+**
+** Copyright (C) 2003-2004 immodule for Qt Project. All rights reserved.
+**
+** This file is written to contribute to Nokia Corporation and/or its subsidiary(-ies) under their own
+** license. You may use this file under your Qt license. Following
+** description is copied from their original file headers. Contact
+** immodule-qt@freedesktop.org if any conditions of this licensing are
+** not clear to you.
+**
+****************************************************************************/
+
+#ifndef QINPUTCONTEXTFACTORY_H
+#define QINPUTCONTEXTFACTORY_H
+
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_IM
+
+class QInputContext;
+class QWidget;
+
+class Q_GUI_EXPORT QInputContextFactory
+{
+public:
+ static QStringList keys();
+ static QInputContext *create( const QString &key, QObject *parent ); // should be a toplevel widget
+ static QStringList languages( const QString &key );
+ static QString displayName( const QString &key );
+ static QString description( const QString &key );
+};
+
+#endif // QT_NO_IM
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QINPUTCONTEXTFACTORY_H
diff --git a/src/gui/inputmethod/qinputcontextplugin.cpp b/src/gui/inputmethod/qinputcontextplugin.cpp
new file mode 100644
index 0000000..69b4800
--- /dev/null
+++ b/src/gui/inputmethod/qinputcontextplugin.cpp
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/****************************************************************************
+**
+** Implementation of QInputContext class
+**
+** Copyright (C) 2003-2004 immodule for Qt Project. All rights reserved.
+**
+** This file is written to contribute to Nokia Corporation and/or its subsidiary(-ies) under their own
+** license. You may use this file under your Qt license. Following
+** description is copied from their original file headers. Contact
+** immodule-qt@freedesktop.org if any conditions of this licensing are
+** not clear to you.
+**
+****************************************************************************/
+
+#include "qinputcontextplugin.h"
+
+#ifndef QT_NO_IM
+#ifndef QT_NO_LIBRARY
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QInputContextPlugin
+ \brief The QInputContextPlugin class provides an abstract base for custom QInputContext plugins.
+
+ \reentrant
+ \ingroup plugins
+
+ The input context plugin is a simple plugin interface that makes it
+ easy to create custom input contexts that can be loaded dynamically
+ into applications.
+
+ To create an input context plugin you subclass this base class,
+ reimplement the pure virtual functions keys(), create(),
+ languages(), displayName(), and description(), and export the
+ class with the Q_EXPORT_PLUGIN2() macro.
+
+ \legalese
+ Copyright (C) 2003-2004 immodule for Qt Project. All rights reserved.
+
+ This file is written to contribute to Nokia Corporation and/or its subsidiary(-ies) under their own
+ license. You may use this file under your Qt license. Following
+ description is copied from their original file headers. Contact
+ immodule-qt@freedesktop.org if any conditions of this licensing are
+ not clear to you.
+ \endlegalese
+
+ \sa QInputContext, {How to Create Qt Plugins}
+*/
+
+/*!
+ \fn QStringList QInputContextPlugin::keys() const
+
+ Returns the list of QInputContext keys this plugin provides.
+
+ These keys are usually the class names of the custom input context
+ that are implemented in the plugin. The names are used, for
+ example, to identify and specify input methods for the input
+ method switching mechanism. They have to be consistent with
+ QInputContext::identifierName(), and may only contain ASCII
+ characters.
+
+ \sa create(), displayName(), QInputContext::identifierName()
+*/
+
+/*!
+ \fn QInputContext* QInputContextPlugin::create( const QString& key )
+
+ Creates and returns a QInputContext object for the input context
+ key \a key. The input context key is usually the class name of
+ the required input method.
+
+ \sa keys()
+*/
+
+/*!
+ \fn QStringList QInputContextPlugin::languages(const QString &key)
+
+ Returns the languages supported by the QInputContext object
+ specified by \a key.
+
+ The languages are expressed as language code (e.g. "zh_CN",
+ "zh_TW", "zh_HK", "ja", "ko", ...). An input context that supports
+ multiple languages can return all supported languages as
+ QStringList. The name has to be consistent with
+ QInputContext::language().
+
+ This information may be used to optimize user interface.
+
+ \sa keys(), QInputContext::language(), QLocale
+*/
+
+/*!
+ \fn QString QInputContextPlugin::displayName(const QString &key)
+
+ Returns a user friendly internationalized name of the
+ QInputContext object specified by \a key. You can, for example,
+ use this name in a menu.
+
+ \sa keys(), QInputContext::identifierName()
+*/
+
+/*!
+ \fn QString QInputContextPlugin::description(const QString &key)
+
+ Returns an internationalized brief description of the QInputContext
+ object specified by \a key. You can, for example, use this
+ description in a user interface.
+
+ \sa keys(), displayName()
+*/
+
+
+/*!
+ Constructs a input context plugin with the given \a parent. This
+ is invoked automatically by the Q_EXPORT_PLUGIN2() macro.
+*/
+QInputContextPlugin::QInputContextPlugin(QObject *parent)
+ :QObject(parent)
+{
+}
+
+/*!
+ Destroys the input context plugin.
+
+ You never have to call this explicitly. Qt destroys a plugin
+ automatically when it's no longer used.
+*/
+QInputContextPlugin::~QInputContextPlugin()
+{
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_LIBRARY
+
+#endif // QT_NO_IM
diff --git a/src/gui/inputmethod/qinputcontextplugin.h b/src/gui/inputmethod/qinputcontextplugin.h
new file mode 100644
index 0000000..6c57284
--- /dev/null
+++ b/src/gui/inputmethod/qinputcontextplugin.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/****************************************************************************
+**
+** Definition of QInputContextPlugin class
+**
+** Copyright (C) 2003-2004 immodule for Qt Project. All rights reserved.
+**
+** This file is written to contribute to Nokia Corporation and/or its subsidiary(-ies) under their own
+** license. You may use this file under your Qt license. Following
+** description is copied from their original file headers. Contact
+** immodule-qt@freedesktop.org if any conditions of this licensing are
+** not clear to you.
+**
+****************************************************************************/
+
+#ifndef QINPUTCONTEXTPLUGIN_H
+#define QINPUTCONTEXTPLUGIN_H
+
+#include <QtCore/qplugin.h>
+#include <QtCore/qfactoryinterface.h>
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#if !defined(QT_NO_IM) && !defined(QT_NO_LIBRARY)
+
+class QInputContext;
+class QInputContextPluginPrivate;
+
+struct Q_GUI_EXPORT QInputContextFactoryInterface : public QFactoryInterface
+{
+ virtual QInputContext *create( const QString &key ) = 0;
+ virtual QStringList languages( const QString &key ) = 0;
+ virtual QString displayName( const QString &key ) = 0;
+ virtual QString description( const QString &key ) = 0;
+};
+
+#define QInputContextFactoryInterface_iid "com.trolltech.Qt.QInputContextFactoryInterface"
+Q_DECLARE_INTERFACE(QInputContextFactoryInterface, QInputContextFactoryInterface_iid)
+
+class Q_GUI_EXPORT QInputContextPlugin : public QObject, public QInputContextFactoryInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QInputContextFactoryInterface:QFactoryInterface)
+public:
+ explicit QInputContextPlugin(QObject *parent = 0);
+ ~QInputContextPlugin();
+
+ virtual QStringList keys() const = 0;
+ virtual QInputContext *create( const QString &key ) = 0;
+ virtual QStringList languages( const QString &key ) = 0;
+ virtual QString displayName( const QString &key ) = 0;
+ virtual QString description( const QString &key ) = 0;
+};
+
+#endif // QT_NO_IM
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QINPUTCONTEXTPLUGIN_H
diff --git a/src/gui/inputmethod/qmacinputcontext_mac.cpp b/src/gui/inputmethod/qmacinputcontext_mac.cpp
new file mode 100644
index 0000000..f0e7ea9
--- /dev/null
+++ b/src/gui/inputmethod/qmacinputcontext_mac.cpp
@@ -0,0 +1,349 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qvarlengtharray.h>
+#include <qwidget.h>
+#include <private/qmacinputcontext_p.h>
+#include "qtextformat.h"
+#include <qdebug.h>
+#include <private/qapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+extern bool qt_sendSpontaneousEvent(QObject*, QEvent*);
+
+#if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5)
+# define typeRefCon typeSInt32
+# define typeByteCount typeSInt32
+#endif
+
+static QTextFormat qt_mac_compose_format()
+{
+ QTextCharFormat ret;
+ ret.setFontUnderline(true);
+ return ret;
+}
+
+QMacInputContext::QMacInputContext(QObject *parent)
+ : QInputContext(parent), composing(false), recursionGuard(false), textDocument(0)
+{
+// createTextDocument();
+}
+
+QMacInputContext::~QMacInputContext()
+{
+#ifdef Q_WS_MAC32
+ if(textDocument)
+ DeleteTSMDocument(textDocument);
+#endif
+}
+
+void
+QMacInputContext::createTextDocument()
+{
+#ifdef Q_WS_MAC32
+ if(!textDocument) {
+ InterfaceTypeList itl = { kUnicodeDocument };
+ NewTSMDocument(1, itl, &textDocument, SRefCon(this));
+ }
+#endif
+}
+
+
+QString QMacInputContext::language()
+{
+ return QString();
+}
+
+
+void QMacInputContext::mouseHandler(int pos, QMouseEvent *e)
+{
+#ifdef Q_WS_MAC32
+ if(e->type() != QEvent::MouseButtonPress)
+ return;
+
+ if (!composing)
+ return;
+ if (pos < 0 || pos > currentText.length())
+ reset();
+ // ##### handle mouse position
+#endif
+}
+
+#if !defined QT_MAC_USE_COCOA
+
+void QMacInputContext::reset()
+{
+ if (recursionGuard)
+ return;
+ if (!currentText.isEmpty()){
+ QInputMethodEvent e;
+ e.setCommitString(currentText);
+ qt_sendSpontaneousEvent(focusWidget(), &e);
+ currentText = QString();
+ }
+ recursionGuard = true;
+ createTextDocument();
+ composing = false;
+ ActivateTSMDocument(textDocument);
+ FixTSMDocument(textDocument);
+ recursionGuard = false;
+}
+
+bool QMacInputContext::isComposing() const
+{
+ return composing;
+}
+#endif
+
+void QMacInputContext::setFocusWidget(QWidget *w)
+{
+ createTextDocument();
+#ifdef Q_WS_MAC32
+ if(w)
+ ActivateTSMDocument(textDocument);
+ else
+ DeactivateTSMDocument(textDocument);
+#endif
+ QInputContext::setFocusWidget(w);
+}
+
+
+static EventTypeSpec input_events[] = {
+ { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent },
+ { kEventClassTextInput, kEventTextInputOffsetToPos },
+ { kEventClassTextInput, kEventTextInputUpdateActiveInputArea }
+};
+static EventHandlerUPP input_proc_handlerUPP = 0;
+static EventHandlerRef input_proc_handler = 0;
+
+void
+QMacInputContext::initialize()
+{
+#ifdef Q_WS_MAC32
+ if(!input_proc_handler) {
+ input_proc_handlerUPP = NewEventHandlerUPP(QMacInputContext::globalEventProcessor);
+ InstallEventHandler(GetApplicationEventTarget(), input_proc_handlerUPP,
+ GetEventTypeCount(input_events), input_events,
+ 0, &input_proc_handler);
+ }
+#endif
+}
+
+void
+QMacInputContext::cleanup()
+{
+#ifdef Q_WS_MAC32
+ if(input_proc_handler) {
+ RemoveEventHandler(input_proc_handler);
+ input_proc_handler = 0;
+ }
+ if(input_proc_handlerUPP) {
+ DisposeEventHandlerUPP(input_proc_handlerUPP);
+ input_proc_handlerUPP = 0;
+ }
+#endif
+}
+
+OSStatus
+QMacInputContext::globalEventProcessor(EventHandlerCallRef, EventRef event, void *)
+{
+#ifdef Q_WS_MAC32
+ QScopedLoopLevelCounter loopLevelCounter(QApplicationPrivate::instance()->threadData);
+
+ SRefCon refcon = 0;
+ GetEventParameter(event, kEventParamTextInputSendRefCon, typeRefCon, 0,
+ sizeof(refcon), 0, &refcon);
+ QMacInputContext *context = reinterpret_cast<QMacInputContext*>(refcon);
+
+ bool handled_event=true;
+ UInt32 ekind = GetEventKind(event), eclass = GetEventClass(event);
+ switch(eclass) {
+ case kEventClassTextInput: {
+ handled_event = false;
+ QWidget *widget = QApplicationPrivate::focus_widget;
+ if(!widget || (context && widget->inputContext() != context)) {
+ handled_event = false;
+ } else if(ekind == kEventTextInputOffsetToPos) {
+ if(!widget->testAttribute(Qt::WA_InputMethodEnabled)) {
+ handled_event = false;
+ break;
+ }
+
+ QRect mr(widget->inputMethodQuery(Qt::ImMicroFocus).toRect());
+ QPoint mp(widget->mapToGlobal(QPoint(mr.topLeft())));
+ Point pt;
+ pt.h = mp.x();
+ pt.v = mp.y() + mr.height();
+ SetEventParameter(event, kEventParamTextInputReplyPoint, typeQDPoint,
+ sizeof(pt), &pt);
+ handled_event = true;
+ } else if(ekind == kEventTextInputUpdateActiveInputArea) {
+ if(!widget->testAttribute(Qt::WA_InputMethodEnabled)) {
+ handled_event = false;
+ break;
+ }
+
+ if (context->recursionGuard)
+ break;
+
+ ByteCount unilen = 0;
+ GetEventParameter(event, kEventParamTextInputSendText, typeUnicodeText,
+ 0, 0, &unilen, 0);
+ UniChar *unicode = (UniChar*)NewPtr(unilen);
+ GetEventParameter(event, kEventParamTextInputSendText, typeUnicodeText,
+ 0, unilen, 0, unicode);
+ QString text((QChar*)unicode, unilen / sizeof(UniChar));
+ DisposePtr((char*)unicode);
+
+ ByteCount fixed_length = 0;
+ GetEventParameter(event, kEventParamTextInputSendFixLen, typeByteCount, 0,
+ sizeof(fixed_length), 0, &fixed_length);
+ if(fixed_length == ULONG_MAX || fixed_length == unilen) {
+ QInputMethodEvent e;
+ e.setCommitString(text);
+ context->currentText = QString();
+ qt_sendSpontaneousEvent(context->focusWidget(), &e);
+ handled_event = true;
+ context->reset();
+ } else {
+ ByteCount rngSize = 0;
+ OSStatus err = GetEventParameter(event, kEventParamTextInputSendHiliteRng, typeTextRangeArray, 0,
+ 0, &rngSize, 0);
+ QVarLengthArray<TextRangeArray> highlight(rngSize);
+ if (noErr == err) {
+ err = GetEventParameter(event, kEventParamTextInputSendHiliteRng, typeTextRangeArray, 0,
+ rngSize, &rngSize, highlight.data());
+ }
+ context->composing = true;
+ if(fixed_length > 0) {
+ const int qFixedLength = fixed_length / sizeof(UniChar);
+ QList<QInputMethodEvent::Attribute> attrs;
+ attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
+ qFixedLength, text.length()-qFixedLength,
+ qt_mac_compose_format());
+ QInputMethodEvent e(text, attrs);
+ context->currentText = text;
+ e.setCommitString(text.left(qFixedLength), 0, qFixedLength);
+ qt_sendSpontaneousEvent(widget, &e);
+ handled_event = true;
+ } else {
+ /* Apple's enums that they have removed from Tiger :(
+ enum {
+ kCaretPosition = 1,
+ kRawText = 2,
+ kSelectedRawText = 3,
+ kConvertedText = 4,
+ kSelectedConvertedText = 5,
+ kBlockFillText = 6,
+ kOutlineText = 7,
+ kSelectedText = 8
+ };
+ */
+#ifndef kConvertedText
+#define kConvertedText 4
+#endif
+#ifndef kCaretPosition
+#define kCaretPosition 1
+#endif
+ QList<QInputMethodEvent::Attribute> attrs;
+ if (!highlight.isEmpty()) {
+ TextRangeArray *data = highlight.data();
+ for (int i = 0; i < data->fNumOfRanges; ++i) {
+ int start = data->fRange[i].fStart / sizeof(UniChar);
+ int len = (data->fRange[i].fEnd - data->fRange[i].fStart) / sizeof(UniChar);
+ if (data->fRange[i].fHiliteStyle == kCaretPosition) {
+ attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, start, 0, QVariant());
+ continue;
+ }
+ QTextCharFormat format;
+ format.setFontUnderline(true);
+ if (data->fRange[i].fHiliteStyle == kConvertedText)
+ format.setUnderlineColor(Qt::gray);
+ else
+ format.setUnderlineColor(Qt::black);
+ attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, start, len, format);
+ }
+ } else {
+ attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
+ 0, text.length(), qt_mac_compose_format());
+ }
+ context->currentText = text;
+ QInputMethodEvent e(text, attrs);
+ qt_sendSpontaneousEvent(widget, &e);
+ handled_event = true;
+ }
+ }
+#if 0
+ if(!context->composing)
+ handled_event = false;
+#endif
+
+ extern bool qt_mac_eat_unicode_key; //qapplication_mac.cpp
+ qt_mac_eat_unicode_key = handled_event;
+ } else if(ekind == kEventTextInputUnicodeForKeyEvent) {
+ EventRef key_ev = 0;
+ GetEventParameter(event, kEventParamTextInputSendKeyboardEvent, typeEventRef, 0,
+ sizeof(key_ev), 0, &key_ev);
+ QString text;
+ ByteCount unilen = 0;
+ if(GetEventParameter(key_ev, kEventParamKeyUnicodes, typeUnicodeText, 0, 0, &unilen, 0) == noErr) {
+ UniChar *unicode = (UniChar*)NewPtr(unilen);
+ GetEventParameter(key_ev, kEventParamKeyUnicodes, typeUnicodeText, 0, unilen, 0, unicode);
+ text = QString((QChar*)unicode, unilen / sizeof(UniChar));
+ DisposePtr((char*)unicode);
+ }
+ unsigned char chr = 0;
+ GetEventParameter(key_ev, kEventParamKeyMacCharCodes, typeChar, 0, sizeof(chr), 0, &chr);
+ if(!chr || chr >= 128 || (text.length() > 0 && (text.length() > 1 || text.at(0) != QLatin1Char(chr))))
+ handled_event = !widget->testAttribute(Qt::WA_InputMethodEnabled);
+ }
+ break; }
+ default:
+ break;
+ }
+ if(!handled_event) //let the event go through
+ return eventNotHandledErr;
+#endif
+ return noErr; //we eat the event
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/inputmethod/qmacinputcontext_p.h b/src/gui/inputmethod/qmacinputcontext_p.h
new file mode 100644
index 0000000..f708040
--- /dev/null
+++ b/src/gui/inputmethod/qmacinputcontext_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMACINPUTCONTEXT_P_H
+#define QMACINPUTCONTEXT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtGui/qinputcontext.h"
+#include "private/qt_mac_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QMacInputContext : public QInputContext
+{
+ Q_OBJECT
+ //Q_DECLARE_PRIVATE(QMacInputContext)
+ void createTextDocument();
+public:
+ explicit QMacInputContext(QObject* parent = 0);
+ virtual ~QMacInputContext();
+
+ virtual void setFocusWidget(QWidget *w);
+ virtual QString identifierName() { return QLatin1String("mac"); }
+ virtual QString language();
+
+ virtual void reset();
+
+ virtual bool isComposing() const;
+
+ static OSStatus globalEventProcessor(EventHandlerCallRef, EventRef, void *);
+ static void initialize();
+ static void cleanup();
+protected:
+ void mouseHandler(int pos, QMouseEvent *);
+private:
+ bool composing;
+ bool recursionGuard;
+ TSMDocumentID textDocument;
+ QString currentText;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMACINPUTCONTEXT_P_H
diff --git a/src/gui/inputmethod/qwininputcontext_p.h b/src/gui/inputmethod/qwininputcontext_p.h
new file mode 100644
index 0000000..38d7e32
--- /dev/null
+++ b/src/gui/inputmethod/qwininputcontext_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWININPUTCONTEXT_P_H
+#define QWININPUTCONTEXT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qinputcontext.cpp. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtGui/qinputcontext.h"
+#include "QtCore/qt_windows.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWinInputContext : public QInputContext
+{
+ Q_OBJECT
+public:
+ explicit QWinInputContext(QObject* parent = 0);
+ virtual ~QWinInputContext();
+
+ virtual QString identifierName() { return QLatin1String("win"); }
+ virtual QString language();
+
+ virtual void reset();
+ virtual void update();
+
+ virtual void mouseHandler(int x, QMouseEvent *event);
+ virtual bool isComposing() const;
+
+ virtual void setFocusWidget(QWidget *w);
+
+ bool startComposition();
+ bool endComposition();
+ bool composition(LPARAM lparam);
+
+ static void TranslateMessage(const MSG *msg);
+ static LRESULT DefWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+ static void enablePopupChild(QWidget *w, bool e);
+ static void enable(QWidget *w, bool e);
+
+private:
+ void init();
+ bool recursionGuard;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWININPUTCONTEXT_P_H
diff --git a/src/gui/inputmethod/qwininputcontext_win.cpp b/src/gui/inputmethod/qwininputcontext_win.cpp
new file mode 100644
index 0000000..720f0b8
--- /dev/null
+++ b/src/gui/inputmethod/qwininputcontext_win.cpp
@@ -0,0 +1,861 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwininputcontext_p.h"
+#include "qinputcontext_p.h"
+
+#include "qfont.h"
+#include "qwidget.h"
+#include "qapplication.h"
+#include "qlibrary.h"
+#include "qevent.h"
+#include "qtextformat.h"
+
+//#define Q_IME_DEBUG
+
+/* Active Input method support on Win95/98/NT */
+#include <objbase.h>
+#include <initguid.h>
+
+#ifdef Q_IME_DEBUG
+#include "qdebug.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+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
+
+DEFINE_GUID(IID_IActiveIMMApp,
+0x08c0e040, 0x62d1, 0x11d1, 0x93, 0x26, 0x0, 0x60, 0xb0, 0x67, 0xb8, 0x6e);
+
+
+
+DEFINE_GUID(CLSID_CActiveIMM,
+0x4955DD33, 0xB159, 0x11d0, 0x8F, 0xCF, 0x0, 0xAA, 0x00, 0x6B, 0xCC, 0x59);
+
+
+
+DEFINE_GUID(IID_IActiveIMMMessagePumpOwner,
+0xb5cf2cfa, 0x8aeb, 0x11d1, 0x93, 0x64, 0x0, 0x60, 0xb0, 0x67, 0xb8, 0x6e);
+
+
+
+interface IEnumRegisterWordW;
+interface IEnumInputContext;
+
+
+bool qt_sendSpontaneousEvent(QObject*, QEvent*);
+
+
+#define IFMETHOD HRESULT STDMETHODCALLTYPE
+
+interface IActiveIMMApp : public IUnknown
+{
+public:
+ virtual IFMETHOD AssociateContext(HWND hWnd, HIMC hIME, HIMC __RPC_FAR *phPrev) = 0;
+ virtual IFMETHOD dummy_ConfigureIMEA() = 0;
+ virtual IFMETHOD ConfigureIMEW(HKL hKL, HWND hWnd, DWORD dwMode, REGISTERWORDW __RPC_FAR *pData) = 0;
+ virtual IFMETHOD CreateContext(HIMC __RPC_FAR *phIMC) = 0;
+ virtual IFMETHOD DestroyContext(HIMC hIME) = 0;
+ virtual IFMETHOD dummy_EnumRegisterWordA() = 0;
+ virtual IFMETHOD EnumRegisterWordW(HKL hKL, LPWSTR szReading, DWORD dwStyle, LPWSTR szRegister, LPVOID pData,
+ IEnumRegisterWordW __RPC_FAR *__RPC_FAR *pEnum) = 0;
+ virtual IFMETHOD dummy_EscapeA() = 0;
+ virtual IFMETHOD EscapeW(HKL hKL, HIMC hIMC, UINT uEscape, LPVOID pData, LRESULT __RPC_FAR *plResult) = 0;
+ virtual IFMETHOD dummy_GetCandidateListA() = 0;
+ virtual IFMETHOD GetCandidateListW(HIMC hIMC, DWORD dwIndex, UINT uBufLen, CANDIDATELIST __RPC_FAR *pCandList,
+ UINT __RPC_FAR *puCopied) = 0;
+ virtual IFMETHOD dummy_GetCandidateListCountA() = 0;
+ virtual IFMETHOD GetCandidateListCountW(HIMC hIMC, DWORD __RPC_FAR *pdwListSize, DWORD __RPC_FAR *pdwBufLen) = 0;
+ virtual IFMETHOD GetCandidateWindow(HIMC hIMC, DWORD dwIndex, CANDIDATEFORM __RPC_FAR *pCandidate) = 0;
+ virtual IFMETHOD dummy_GetCompositionFontA() = 0;
+ virtual IFMETHOD GetCompositionFontW(HIMC hIMC, LOGFONTW __RPC_FAR *plf) = 0;
+ virtual IFMETHOD dummy_GetCompositionStringA() = 0;
+ virtual IFMETHOD GetCompositionStringW(HIMC hIMC, DWORD dwIndex, DWORD dwBufLen, LONG __RPC_FAR *plCopied, LPVOID pBuf) = 0;
+ virtual IFMETHOD GetCompositionWindow(HIMC hIMC, COMPOSITIONFORM __RPC_FAR *pCompForm) = 0;
+ virtual IFMETHOD GetContext(HWND hWnd, HIMC __RPC_FAR *phIMC) = 0;
+ virtual IFMETHOD dummy_GetConversionListA() = 0;
+ virtual IFMETHOD GetConversionListW(HKL hKL, HIMC hIMC, LPWSTR pSrc, UINT uBufLen, UINT uFlag,
+ CANDIDATELIST __RPC_FAR *pDst, UINT __RPC_FAR *puCopied) = 0;
+ virtual IFMETHOD GetConversionStatus(HIMC hIMC, DWORD __RPC_FAR *pfdwConversion, DWORD __RPC_FAR *pfdwSentence) = 0;
+ virtual IFMETHOD GetDefaultIMEWnd(HWND hWnd, HWND __RPC_FAR *phDefWnd) = 0;
+ virtual IFMETHOD dummy_GetDescriptionA() = 0;
+ virtual IFMETHOD GetDescriptionW(HKL hKL, UINT uBufLen, LPWSTR szDescription, UINT __RPC_FAR *puCopied) = 0;
+ virtual IFMETHOD dummy_GetGuideLineA() = 0;
+ virtual IFMETHOD GetGuideLineW(HIMC hIMC, DWORD dwIndex, DWORD dwBufLen, LPWSTR pBuf, DWORD __RPC_FAR *pdwResult) = 0;
+ virtual IFMETHOD dummy_GetIMEFileNameA() = 0;
+ virtual IFMETHOD GetIMEFileNameW(HKL hKL, UINT uBufLen, LPWSTR szFileName, UINT __RPC_FAR *puCopied) = 0;
+ virtual IFMETHOD GetOpenStatus(HIMC hIMC) = 0;
+ virtual IFMETHOD GetProperty(HKL hKL, DWORD fdwIndex, DWORD __RPC_FAR *pdwProperty) = 0;
+ virtual IFMETHOD dummy_GetRegisterWordStyleA() = 0;
+ virtual IFMETHOD GetRegisterWordStyleW(HKL hKL, UINT nItem, STYLEBUFW __RPC_FAR *pStyleBuf, UINT __RPC_FAR *puCopied) = 0;
+ virtual IFMETHOD GetStatusWindowPos(HIMC hIMC, POINT __RPC_FAR *pptPos) = 0;
+ virtual IFMETHOD GetVirtualKey(HWND hWnd, UINT __RPC_FAR *puVirtualKey) = 0;
+ virtual IFMETHOD dummy_InstallIMEA() = 0;
+ virtual IFMETHOD InstallIMEW(LPWSTR szIMEFileName, LPWSTR szLayoutText, HKL __RPC_FAR *phKL) = 0;
+ virtual IFMETHOD IsIME(HKL hKL) = 0;
+ virtual IFMETHOD dummy_IsUIMessageA() = 0;
+ virtual IFMETHOD IsUIMessageW(HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam) = 0;
+ virtual IFMETHOD NotifyIME(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue) = 0;
+ virtual IFMETHOD dummy_RegisterWordA() = 0;
+ virtual IFMETHOD RegisterWordW(HKL hKL, LPWSTR szReading, DWORD dwStyle, LPWSTR szRegister) = 0;
+ virtual IFMETHOD ReleaseContext(HWND hWnd, HIMC hIMC) = 0;
+ virtual IFMETHOD SetCandidateWindow(HIMC hIMC, CANDIDATEFORM __RPC_FAR *pCandidate) = 0;
+ virtual IFMETHOD SetCompositionFontA(HIMC hIMC, LOGFONTA __RPC_FAR *plf) = 0;
+ virtual IFMETHOD SetCompositionFontW(HIMC hIMC, LOGFONTW __RPC_FAR *plf) = 0;
+ virtual IFMETHOD dummy_SetCompositionStringA() = 0;
+ virtual IFMETHOD SetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPVOID pComp, DWORD dwCompLen,
+ LPVOID pRead, DWORD dwReadLen) = 0;
+ virtual IFMETHOD SetCompositionWindow(HIMC hIMC, COMPOSITIONFORM __RPC_FAR *pCompForm) = 0;
+ virtual IFMETHOD SetConversionStatus(HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence) = 0;
+ virtual IFMETHOD SetOpenStatus(HIMC hIMC, BOOL fOpen) = 0;
+ virtual IFMETHOD SetStatusWindowPos(HIMC hIMC, POINT __RPC_FAR *pptPos) = 0;
+ virtual IFMETHOD SimulateHotKey(HWND hWnd, DWORD dwHotKeyID) = 0;
+ virtual IFMETHOD dummy_UnregisterWordA() = 0;
+ virtual IFMETHOD UnregisterWordW(HKL hKL, LPWSTR szReading, DWORD dwStyle, LPWSTR szUnregister) = 0;
+ virtual IFMETHOD Activate(BOOL fRestoreLayout) = 0;
+ virtual IFMETHOD Deactivate(void) = 0;
+ virtual IFMETHOD OnDefWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT __RPC_FAR *plResult) = 0;
+ virtual IFMETHOD FilterClientWindows(ATOM __RPC_FAR *aaClassList, UINT uSize) = 0;
+ virtual IFMETHOD dummy_GetCodePageA() = 0;
+ virtual IFMETHOD GetLangId(HKL hKL, LANGID __RPC_FAR *plid) = 0;
+ virtual IFMETHOD AssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags) = 0;
+ virtual IFMETHOD DisableIME(DWORD idThread) = 0;
+ virtual IFMETHOD dummy_GetImeMenuItemsA() = 0;
+ virtual IFMETHOD GetImeMenuItemsW(HIMC hIMC, DWORD dwFlags, DWORD dwType, /*IMEMENUITEMINFOW*/ void __RPC_FAR *pImeParentMenu,
+ /*IMEMENUITEMINFOW*/ void __RPC_FAR *pImeMenu, DWORD dwSize, DWORD __RPC_FAR *pdwResult) = 0;
+ virtual IFMETHOD EnumInputContext(DWORD idThread, IEnumInputContext __RPC_FAR *__RPC_FAR *ppEnum) = 0;
+};
+
+interface IActiveIMMMessagePumpOwner : public IUnknown
+{
+public:
+ virtual IFMETHOD Start(void) = 0;
+ virtual IFMETHOD End(void) = 0;
+ virtual IFMETHOD OnTranslateMessage(const MSG __RPC_FAR *pMsg) = 0;
+ virtual IFMETHOD Pause(DWORD __RPC_FAR *pdwCookie) = 0;
+ virtual IFMETHOD Resume(DWORD dwCookie) = 0;
+};
+
+
+static IActiveIMMApp *aimm = 0;
+static IActiveIMMMessagePumpOwner *aimmpump = 0;
+static QString *imeComposition = 0;
+static int imePosition = -1;
+bool qt_use_rtl_extensions = false;
+static bool haveCaret = false;
+
+#ifndef LGRPID_INSTALLED
+#define LGRPID_INSTALLED 0x00000001 // installed language group ids
+#define LGRPID_SUPPORTED 0x00000002 // supported language group ids
+#endif
+
+#ifndef LGRPID_ARABIC
+#define LGRPID_WESTERN_EUROPE 0x0001 // Western Europe & U.S.
+#define LGRPID_CENTRAL_EUROPE 0x0002 // Central Europe
+#define LGRPID_BALTIC 0x0003 // Baltic
+#define LGRPID_GREEK 0x0004 // Greek
+#define LGRPID_CYRILLIC 0x0005 // Cyrillic
+#define LGRPID_TURKISH 0x0006 // Turkish
+#define LGRPID_JAPANESE 0x0007 // Japanese
+#define LGRPID_KOREAN 0x0008 // Korean
+#define LGRPID_TRADITIONAL_CHINESE 0x0009 // Traditional Chinese
+#define LGRPID_SIMPLIFIED_CHINESE 0x000a // Simplified Chinese
+#define LGRPID_THAI 0x000b // Thai
+#define LGRPID_HEBREW 0x000c // Hebrew
+#define LGRPID_ARABIC 0x000d // Arabic
+#define LGRPID_VIETNAMESE 0x000e // Vietnamese
+#define LGRPID_INDIC 0x000f // Indic
+#define LGRPID_GEORGIAN 0x0010 // Georgian
+#define LGRPID_ARMENIAN 0x0011 // Armenian
+#endif
+
+static DWORD WM_MSIME_MOUSE = 0;
+
+QWinInputContext::QWinInputContext(QObject *parent)
+ : QInputContext(parent), recursionGuard(false)
+{
+ if (QSysInfo::WindowsVersion < QSysInfo::WV_2000) {
+ // try to get the Active IMM COM object on Win95/98/NT, where english versions don't
+ // support the regular Windows input methods.
+ if (CoCreateInstance(CLSID_CActiveIMM, NULL, CLSCTX_INPROC_SERVER,
+ IID_IActiveIMMApp, (LPVOID *)&aimm) != S_OK) {
+ aimm = 0;
+ }
+ if (aimm && (aimm->QueryInterface(IID_IActiveIMMMessagePumpOwner, (LPVOID *)&aimmpump) != S_OK ||
+ aimm->Activate(true) != S_OK)) {
+ aimm->Release();
+ aimm = 0;
+ if (aimmpump)
+ aimmpump->Release();
+ aimmpump = 0;
+ }
+ if (aimmpump)
+ aimmpump->Start();
+ }
+
+#ifndef Q_OS_WINCE
+ QSysInfo::WinVersion ver = QSysInfo::windowsVersion();
+ if (ver & QSysInfo::WV_NT_based && ver >= QSysInfo::WV_VISTA) {
+ // Since the IsValidLanguageGroup/IsValidLocale functions always return true on
+ // Vista, check the Keyboard Layouts for enabling RTL.
+ UINT nLayouts = GetKeyboardLayoutList(0, 0);
+ if (nLayouts) {
+ HKL *lpList = new HKL[nLayouts];
+ GetKeyboardLayoutList(nLayouts, lpList);
+ for (int i = 0; i<(int)nLayouts; i++) {
+ WORD plangid = PRIMARYLANGID((quintptr)lpList[i]);
+ if (plangid == LANG_ARABIC
+ || plangid == LANG_HEBREW
+ || plangid == LANG_FARSI
+#ifdef LANG_SYRIAC
+ || plangid == LANG_SYRIAC
+#endif
+ ) {
+ qt_use_rtl_extensions = true;
+ break;
+ }
+ }
+ delete []lpList;
+ }
+ } else {
+ // figure out whether a RTL language is installed
+ typedef BOOL(WINAPI *PtrIsValidLanguageGroup)(DWORD,DWORD);
+ PtrIsValidLanguageGroup isValidLanguageGroup = (PtrIsValidLanguageGroup)QLibrary::resolve(QLatin1String("kernel32"), "IsValidLanguageGroup");
+ if (isValidLanguageGroup) {
+ qt_use_rtl_extensions = isValidLanguageGroup(LGRPID_ARABIC, LGRPID_INSTALLED)
+ || isValidLanguageGroup(LGRPID_HEBREW, LGRPID_INSTALLED);
+ }
+ qt_use_rtl_extensions |= IsValidLocale(MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED)
+ || IsValidLocale(MAKELCID(MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED)
+#ifdef LANG_SYRIAC
+ || IsValidLocale(MAKELCID(MAKELANGID(LANG_SYRIAC, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED)
+#endif
+ || IsValidLocale(MAKELCID(MAKELANGID(LANG_FARSI, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED);
+ }
+#else
+ qt_use_rtl_extensions = false;
+#endif
+
+ WM_MSIME_MOUSE = QT_WA_INLINE(RegisterWindowMessage(L"MSIMEMouseOperation"), RegisterWindowMessageA("MSIMEMouseOperation"));
+}
+
+QWinInputContext::~QWinInputContext()
+{
+ // release active input method if we have one
+ if (aimm) {
+ aimmpump->End();
+ aimmpump->Release();
+ aimm->Deactivate();
+ aimm->Release();
+ aimm = 0;
+ aimmpump = 0;
+ }
+ delete imeComposition;
+ imeComposition = 0;
+}
+
+static HWND getDefaultIMEWnd(HWND wnd)
+{
+ HWND ime_wnd;
+ if(aimm)
+ aimm->GetDefaultIMEWnd(wnd, &ime_wnd);
+ else
+ ime_wnd = ImmGetDefaultIMEWnd(wnd);
+ return ime_wnd;
+}
+
+static HIMC getContext(HWND wnd)
+{
+ HIMC imc;
+ if (aimm)
+ aimm->GetContext(wnd, &imc);
+ else
+ imc = ImmGetContext(wnd);
+
+ return imc;
+}
+
+static void releaseContext(HWND wnd, HIMC imc)
+{
+ if (aimm)
+ aimm->ReleaseContext(wnd, imc);
+ else
+ ImmReleaseContext(wnd, imc);
+}
+
+static void notifyIME(HIMC imc, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
+{
+ if (!imc)
+ return;
+ if (aimm)
+ aimm->NotifyIME(imc, dwAction, dwIndex, dwValue);
+ else
+ ImmNotifyIME(imc, dwAction, dwIndex, dwValue);
+}
+
+static LONG getCompositionString(HIMC himc, DWORD dwIndex, LPVOID lpbuf, DWORD dBufLen, bool *unicode = 0)
+{
+ LONG len = 0;
+ if (unicode)
+ *unicode = true;
+ if (aimm)
+ aimm->GetCompositionStringW(himc, dwIndex, dBufLen, &len, lpbuf);
+ else
+ {
+ if(QSysInfo::WindowsVersion != QSysInfo::WV_95) {
+ len = ImmGetCompositionStringW(himc, dwIndex, lpbuf, dBufLen);
+ }
+#if !defined(Q_OS_WINCE)
+ else {
+ len = ImmGetCompositionStringA(himc, dwIndex, lpbuf, dBufLen);
+ if (unicode)
+ *unicode = false;
+ }
+#endif
+ }
+ return len;
+}
+
+static int getCursorPosition(HIMC himc)
+{
+ return getCompositionString(himc, GCS_CURSORPOS, 0, 0);
+}
+
+static QString getString(HIMC himc, DWORD dwindex, int *selStart = 0, int *selLength = 0)
+{
+ static char *buffer = 0;
+ static int buflen = 0;
+
+ int len = getCompositionString(himc, dwindex, 0, 0) + 1;
+ if (!buffer || len > buflen) {
+ delete [] buffer;
+ buflen = qMin(len, 256);
+ buffer = new char[buflen];
+ }
+
+ bool unicode = true;
+ len = getCompositionString(himc, dwindex, buffer, buflen, &unicode);
+
+ if (selStart) {
+ static char *attrbuffer = 0;
+ static int attrbuflen = 0;
+ int attrlen = getCompositionString(himc, dwindex, 0, 0) + 1;
+ if (!attrbuffer || attrlen> attrbuflen) {
+ delete [] attrbuffer;
+ attrbuflen = qMin(attrlen, 256);
+ attrbuffer = new char[attrbuflen];
+ }
+ attrlen = getCompositionString(himc, GCS_COMPATTR, attrbuffer, attrbuflen);
+ *selStart = attrlen+1;
+ *selLength = -1;
+ for (int i = 0; i < attrlen; i++) {
+ if (attrbuffer[i] & ATTR_TARGET_CONVERTED) {
+ *selStart = qMin(*selStart, i);
+ *selLength = qMax(*selLength, i);
+ }
+ }
+ *selLength = qMax(0, *selLength - *selStart + 1);
+ }
+
+ if (len <= 0)
+ return QString();
+ if (unicode) {
+ return QString((QChar *)buffer, len/sizeof(QChar));
+ }
+ else {
+ buffer[len] = 0;
+ WCHAR *wc = new WCHAR[len+1];
+ int l = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
+ buffer, len, wc, len+1);
+ QString res = QString((QChar *)wc, l);
+ delete [] wc;
+ return res;
+ }
+}
+
+void QWinInputContext::TranslateMessage(const MSG *msg)
+{
+ if (!aimmpump || aimmpump->OnTranslateMessage(msg) != S_OK)
+ ::TranslateMessage(msg);
+}
+
+LRESULT QWinInputContext::DefWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ LRESULT retval;
+ if (!aimm || aimm->OnDefWindowProc(hwnd, msg, wParam, lParam, &retval) != S_OK)
+ {
+ QT_WA({
+ retval = ::DefWindowProc(hwnd, msg, wParam, lParam);
+ } , {
+ retval = ::DefWindowProcA(hwnd,msg, wParam, lParam);
+ });
+ }
+ return retval;
+}
+
+
+void QWinInputContext::update()
+{
+ QWidget *w = focusWidget();
+ if(!w)
+ return;
+
+ Q_ASSERT(w->testAttribute(Qt::WA_WState_Created));
+ HIMC imc = getContext(w->effectiveWinId());
+
+ if (!imc)
+ return;
+
+ QFont f = qvariant_cast<QFont>(w->inputMethodQuery(Qt::ImFont));
+ HFONT hf;
+ hf = f.handle();
+
+ QT_WA({
+ LOGFONT lf;
+ if (GetObject(hf, sizeof(lf), &lf))
+ if (aimm)
+ aimm->SetCompositionFontW(imc, &lf);
+ else
+ ImmSetCompositionFont(imc, &lf);
+ } , {
+ LOGFONTA lf;
+ if (GetObjectA(hf, sizeof(lf), &lf))
+ if (aimm)
+ aimm->SetCompositionFontA(imc, &lf);
+ else
+ ImmSetCompositionFontA(imc, &lf);
+ });
+
+ QRect r = w->inputMethodQuery(Qt::ImMicroFocus).toRect();
+
+ // The ime window positions are based on the WinId with active focus.
+ QWidget *imeWnd = QWidget::find(::GetFocus());
+ if (imeWnd && !aimm) {
+ QPoint pt (r.topLeft());
+ pt = w->mapToGlobal(pt);
+ pt = imeWnd->mapFromGlobal(pt);
+ r.moveTo(pt);
+ }
+
+ COMPOSITIONFORM cf;
+ // ### need X-like inputStyle config settings
+ cf.dwStyle = CFS_FORCE_POSITION;
+ cf.ptCurrentPos.x = r.x();
+ cf.ptCurrentPos.y = r.y();
+
+ CANDIDATEFORM candf;
+ candf.dwIndex = 0;
+ candf.dwStyle = CFS_EXCLUDE;
+ candf.ptCurrentPos.x = r.x();
+ candf.ptCurrentPos.y = r.y() + r.height();
+ candf.rcArea.left = r.x();
+ candf.rcArea.top = r.y();
+ candf.rcArea.right = r.x() + r.width();
+ candf.rcArea.bottom = r.y() + r.height();
+
+ if(haveCaret)
+ SetCaretPos(r.x(), r.y());
+
+ if (aimm) {
+ aimm->SetCompositionWindow(imc, &cf);
+ aimm->SetCandidateWindow(imc, &candf);
+ } else {
+ ImmSetCompositionWindow(imc, &cf);
+ ImmSetCandidateWindow(imc, &candf);
+ }
+
+ releaseContext(w->effectiveWinId(), imc);
+}
+
+
+bool QWinInputContext::endComposition()
+{
+ QWidget *fw = focusWidget();
+#ifdef Q_IME_DEBUG
+ qDebug("endComposition! fw = %s", fw ? fw->className() : "(null)");
+#endif
+ bool result = true;
+ if(imePosition == -1 || recursionGuard)
+ return result;
+
+ // Googles Pinyin Input Method likes to call endComposition again
+ // when we call notifyIME with CPS_CANCEL, so protect ourselves
+ // against that.
+ recursionGuard = true;
+
+ if (fw) {
+ Q_ASSERT(fw->testAttribute(Qt::WA_WState_Created));
+ HIMC imc = getContext(fw->effectiveWinId());
+ notifyIME(imc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
+ releaseContext(fw->effectiveWinId(), imc);
+ if(haveCaret) {
+ DestroyCaret();
+ haveCaret = false;
+ }
+ }
+
+ if (!fw)
+ fw = qApp->focusWidget();
+
+ if (fw) {
+ QInputMethodEvent e;
+ result = qt_sendSpontaneousEvent(fw, &e);
+ }
+
+ if (imeComposition)
+ imeComposition->clear();
+ imePosition = -1;
+
+ recursionGuard = false;
+
+ return result;
+}
+
+void QWinInputContext::reset()
+{
+ QWidget *fw = focusWidget();
+
+#ifdef Q_IME_DEBUG
+ qDebug("sending accept to focus widget %s", fw ? fw->className() : "(null)");
+#endif
+
+ if (fw && imePosition != -1) {
+ QInputMethodEvent e;
+ if (imeComposition)
+ e.setCommitString(*imeComposition);
+ imePosition = -1;
+ qt_sendSpontaneousEvent(fw, &e);
+ }
+
+ if (imeComposition)
+ imeComposition->clear();
+ imePosition = -1;
+
+ if (fw) {
+ Q_ASSERT(fw->testAttribute(Qt::WA_WState_Created));
+ HIMC imc = getContext(fw->effectiveWinId());
+ notifyIME(imc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
+ releaseContext(fw->effectiveWinId(), imc);
+ }
+
+}
+
+
+bool QWinInputContext::startComposition()
+{
+#ifdef Q_IME_DEBUG
+ qDebug("startComposition");
+#endif
+
+ if (!imeComposition)
+ imeComposition = new QString();
+
+ QWidget *fw = focusWidget();
+ if (fw) {
+ Q_ASSERT(fw->testAttribute(Qt::WA_WState_Created));
+ imePosition = 0;
+ haveCaret = CreateCaret(fw->effectiveWinId(), 0, 1, 1);
+ HideCaret(fw->effectiveWinId());
+ update();
+ }
+ return fw != 0;
+}
+
+enum StandardFormat {
+ PreeditFormat,
+ SelectionFormat
+};
+
+bool QWinInputContext::composition(LPARAM lParam)
+{
+#ifdef Q_IME_DEBUG
+ QString str;
+ if (lParam & GCS_RESULTSTR)
+ str += "RESULTSTR ";
+ if (lParam & GCS_COMPSTR)
+ str += "COMPSTR ";
+ if (lParam & GCS_COMPATTR)
+ str += "COMPATTR ";
+ if (lParam & GCS_CURSORPOS)
+ str += "CURSORPOS ";
+ if (lParam & GCS_COMPCLAUSE)
+ str += "COMPCLAUSE ";
+ if (lParam & CS_INSERTCHAR)
+ str += "INSERTCHAR ";
+ if (lParam & CS_NOMOVECARET)
+ str += "NOMOVECARET ";
+ qDebug("composition, lParam=(%x) %s imePosition=%d", lParam, str.latin1(), imePosition);
+#endif
+
+ bool result = true;
+
+ if(!lParam)
+ // bogus event
+ return true;
+
+ QWidget *fw = qApp->focusWidget();
+ if (fw) {
+ Q_ASSERT(fw->testAttribute(Qt::WA_WState_Created));
+ HIMC imc = getContext(fw->effectiveWinId());
+ QInputMethodEvent e;
+ if (lParam & (GCS_COMPSTR | GCS_COMPATTR | GCS_CURSORPOS)) {
+ if (imePosition == -1)
+ // need to send a start event
+ startComposition();
+
+ // some intermediate composition result
+ int selStart, selLength;
+ *imeComposition = getString(imc, GCS_COMPSTR, &selStart, &selLength);
+ imePosition = getCursorPosition(imc);
+ if (lParam & CS_INSERTCHAR && lParam & CS_NOMOVECARET) {
+ // make korean work correctly. Hope this is correct for all IMEs
+ selStart = 0;
+ selLength = imeComposition->length();
+ }
+ if(selLength == 0)
+ selStart = 0;
+
+ QList<QInputMethodEvent::Attribute> attrs;
+ if (selStart > 0)
+ attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, selStart,
+ standardFormat(PreeditFormat));
+ if (selLength)
+ attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, selStart, selLength,
+ standardFormat(SelectionFormat));
+ if (selStart + selLength < imeComposition->length())
+ attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, selStart + selLength,
+ imeComposition->length() - selStart - selLength,
+ standardFormat(PreeditFormat));
+ if(imePosition >= 0)
+ attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, imePosition, selLength ? 0 : 1, QVariant());
+
+ e = QInputMethodEvent(*imeComposition, attrs);
+ }
+ if (lParam & GCS_RESULTSTR) {
+ if(imePosition == -1)
+ startComposition();
+ // a fixed result, return the converted string
+ *imeComposition = getString(imc, GCS_RESULTSTR);
+ imePosition = -1;
+ e.setCommitString(*imeComposition);
+ imeComposition->clear();
+ }
+ result = qt_sendSpontaneousEvent(fw, &e);
+ update();
+ releaseContext(fw->effectiveWinId(), imc);
+ }
+#ifdef Q_IME_DEBUG
+ qDebug("imecomposition: cursor pos at %d, str=%x", imePosition, str[0].unicode());
+#endif
+ return result;
+}
+
+static HIMC defaultContext = 0;
+
+// checks whether widget is a popup
+inline bool isPopup(QWidget *w)
+{
+ if (w && (w->windowFlags() & Qt::Popup) == Qt::Popup)
+ return true;
+ else
+ return false;
+}
+// checks whether widget is in a popup
+inline bool isInPopup(QWidget *w)
+{
+ if (w && (isPopup(w) || isPopup(w->window())))
+ return true;
+ else
+ return false;
+}
+
+// find the parent widget, which is a non popup toplevel
+// this is valid only if the widget is/in a popup
+inline QWidget *findParentforPopup(QWidget *w)
+{
+ QWidget *e = QWidget::find(w->effectiveWinId());
+ // check if this or its parent is a popup
+ while (isInPopup(e)) {
+ e = e->window()->parentWidget();
+ if (!e)
+ break;
+ e = QWidget::find(e->effectiveWinId());
+ }
+ if (e)
+ return e->window();
+ else
+ return 0;
+}
+
+// enables or disables the ime
+inline void enableIme(QWidget *w, bool value)
+{
+ if (value) {
+ // enable ime
+ if (defaultContext)
+ ImmAssociateContext(w->effectiveWinId(), defaultContext);
+#ifdef Q_OS_WINCE
+ if (qApp->autoSipEnabled())
+ qt_wince_show_SIP(true);
+#endif
+ } else {
+ // disable ime
+ HIMC oldimc = ImmAssociateContext(w->effectiveWinId(), 0);
+ if (!defaultContext)
+ defaultContext = oldimc;
+#ifdef Q_OS_WINCE
+ if (qApp->autoSipEnabled())
+ qt_wince_show_SIP(false);
+#endif
+ }
+}
+
+
+void QInputContextPrivate::updateImeStatus(QWidget *w, bool hasFocus)
+{
+ if (!w)
+ return;
+ bool e = w->testAttribute(Qt::WA_InputMethodEnabled) && w->isEnabled();
+ bool hasIme = e && hasFocus;
+#ifdef Q_IME_DEBUG
+ qDebug("%s HasFocus = %d hasIme = %d e = %d ", w->className(), hasFocus, hasIme, e);
+#endif
+ if (hasFocus || e) {
+ if (isInPopup(w))
+ QWinInputContext::enablePopupChild(w, hasIme);
+ else
+ QWinInputContext::enable(w, hasIme);
+ }
+}
+
+void QWinInputContext::enablePopupChild(QWidget *w, bool e)
+{
+ if (aimm) {
+ enable(w, e);
+ return;
+ }
+
+ if (!w || !isInPopup(w))
+ return;
+#ifdef Q_IME_DEBUG
+ qDebug("enablePopupChild: w=%s, enable = %s", w ? w->className() : "(null)" , e ? "true" : "false");
+#endif
+ QWidget *parent = findParentforPopup(w);
+ if (parent) {
+ // update ime status of the normal toplevel parent of the popup
+ enableIme(parent, e);
+ }
+ QWidget *toplevel = w->window();
+ if (toplevel) {
+ // update ime status of the toplevel popup
+ enableIme(toplevel, e);
+ }
+}
+
+void QWinInputContext::enable(QWidget *w, bool e)
+{
+ if(w) {
+#ifdef Q_IME_DEBUG
+ qDebug("enable: w=%s, enable = %s", w ? w->className() : "(null)" , e ? "true" : "false");
+#endif
+ if (!w->testAttribute(Qt::WA_WState_Created))
+ return;
+ if(aimm) {
+ HIMC oldimc;
+ if (!e) {
+ aimm->AssociateContext(w->effectiveWinId(), 0, &oldimc);
+ if (!defaultContext)
+ defaultContext = oldimc;
+ } else if (defaultContext) {
+ aimm->AssociateContext(w->effectiveWinId(), defaultContext, &oldimc);
+ }
+ } else {
+ // update ime status on the widget
+ QWidget *p = QWidget::find(w->effectiveWinId());
+ if (p)
+ enableIme(p, e);
+ }
+ }
+}
+
+void QWinInputContext::setFocusWidget(QWidget *w)
+{
+ QInputContext::setFocusWidget(w);
+ update();
+}
+
+bool QWinInputContext::isComposing() const
+{
+ return imeComposition && !imeComposition->isEmpty();
+}
+
+void QWinInputContext::mouseHandler(int pos, QMouseEvent *e)
+{
+ if(e->type() != QEvent::MouseButtonPress)
+ return;
+
+ if (pos < 0 || pos > imeComposition->length())
+ reset();
+
+ // Probably should pass the correct button, but it seems to work fine like this.
+ DWORD button = MK_LBUTTON;
+
+ QWidget *fw = focusWidget();
+ if (fw) {
+ Q_ASSERT(fw->testAttribute(Qt::WA_WState_Created));
+ HIMC himc = getContext(fw->effectiveWinId());
+ HWND ime_wnd = getDefaultIMEWnd(fw->effectiveWinId());
+ SendMessage(ime_wnd, WM_MSIME_MOUSE, MAKELONG(MAKEWORD(button, pos == 0 ? 2 : 1), pos), (LPARAM)himc);
+ releaseContext(fw->effectiveWinId(), himc);
+ }
+ //qDebug("mouseHandler: got value %d pos=%d", ret,pos);
+}
+
+QString QWinInputContext::language()
+{
+ return QString();
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/inputmethod/qwsinputcontext_p.h b/src/gui/inputmethod/qwsinputcontext_p.h
new file mode 100644
index 0000000..20811da
--- /dev/null
+++ b/src/gui/inputmethod/qwsinputcontext_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWSINPUTCONTEXT_P_H
+#define QWSINPUTCONTEXT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtGui/qinputcontext.h"
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+
+QT_BEGIN_NAMESPACE
+
+class QWSIMEvent;
+class QWSIMQueryEvent;
+class QWSIMInitEvent;
+
+class QWSInputContext : public QInputContext
+{
+ Q_OBJECT
+public:
+ explicit QWSInputContext(QObject* parent = 0);
+ ~QWSInputContext() {}
+
+
+ QString identifierName() { return QString(); }
+ QString language() { return QString(); }
+
+ void reset();
+ void update();
+ void mouseHandler( int x, QMouseEvent *event);
+
+ void setFocusWidget( QWidget *w );
+ void widgetDestroyed(QWidget *w);
+
+ bool isComposing() const;
+
+ static QWidget *activeWidget();
+ static bool translateIMEvent(QWidget *w, const QWSIMEvent *e);
+ static bool translateIMQueryEvent(QWidget *w, const QWSIMQueryEvent *e);
+ static bool translateIMInitEvent(const QWSIMInitEvent *e);
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_QWS_INPUTMETHODS
+
+#endif // QWSINPUTCONTEXT_P_H
diff --git a/src/gui/inputmethod/qwsinputcontext_qws.cpp b/src/gui/inputmethod/qwsinputcontext_qws.cpp
new file mode 100644
index 0000000..46ac13d
--- /dev/null
+++ b/src/gui/inputmethod/qwsinputcontext_qws.cpp
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwsinputcontext_p.h"
+#include "qinputcontext_p.h"
+#include "qwsdisplay_qws.h"
+#include "qwsevent_qws.h"
+#include "private/qwscommand_qws_p.h"
+#include "qwindowsystem_qws.h"
+#include "qevent.h"
+#include "qtextformat.h"
+
+#include <qbuffer.h>
+
+#include <qdebug.h>
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+
+QT_BEGIN_NAMESPACE
+
+static QWidget* activeWidget = 0;
+
+//#define EXTRA_DEBUG
+
+QWSInputContext::QWSInputContext(QObject *parent)
+ :QInputContext(parent)
+{
+}
+
+void QWSInputContext::reset()
+{
+ QPaintDevice::qwsDisplay()->resetIM();
+}
+
+
+void QWSInputContext::setFocusWidget( QWidget *w )
+{
+ QWidget *oldFocus = focusWidget();
+ if (oldFocus == w)
+ return;
+
+ if (oldFocus) {
+ QWidget *tlw = oldFocus->window();
+ int winid = tlw->internalWinId();
+
+ int widgetid = oldFocus->internalWinId();
+ QPaintDevice::qwsDisplay()->sendIMUpdate(QWSInputMethod::FocusOut, winid, widgetid);
+ }
+
+ QInputContext::setFocusWidget(w);
+
+ if (!w)
+ return;
+
+ QWidget *tlw = w->window();
+ int winid = tlw->winId();
+
+ int widgetid = w->winId();
+ QPaintDevice::qwsDisplay()->sendIMUpdate(QWSInputMethod::FocusIn, winid, widgetid);
+
+ //setfocus ???
+
+ update();
+}
+
+
+void QWSInputContext::widgetDestroyed(QWidget *w)
+{
+ if (w == ::activeWidget)
+ ::activeWidget = 0;
+ QInputContext::widgetDestroyed(w);
+}
+
+void QWSInputContext::update()
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return;
+
+ QWidget *tlw = w->window();
+ int winid = tlw->winId();
+
+ int widgetid = w->winId();
+ QPaintDevice::qwsDisplay()->sendIMUpdate(QWSInputMethod::Update, winid, widgetid);
+
+}
+
+void QWSInputContext::mouseHandler( int x, QMouseEvent *event)
+{
+ if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease)
+ QPaintDevice::qwsDisplay()->sendIMMouseEvent( x, event->type() == QEvent::MouseButtonPress );
+}
+
+QWidget *QWSInputContext::activeWidget()
+{
+ return ::activeWidget;
+}
+
+
+bool QWSInputContext::isComposing() const
+{
+ return ::activeWidget != 0;
+}
+
+bool QWSInputContext::translateIMQueryEvent(QWidget *w, const QWSIMQueryEvent *e)
+{
+ Qt::InputMethodQuery type = static_cast<Qt::InputMethodQuery>(e->simpleData.property);
+ QVariant result = w->inputMethodQuery(type);
+ QWidget *tlw = w->window();
+ int winId = tlw->winId();
+
+ if ( type == Qt::ImMicroFocus ) {
+ // translate to relative to tlw
+ QRect mf = result.toRect();
+ mf.moveTopLeft(w->mapTo(tlw,mf.topLeft()));
+ result = mf;
+ }
+
+ QPaintDevice::qwsDisplay()->sendIMResponse(winId, e->simpleData.property, result);
+
+ return false;
+}
+
+bool QWSInputContext::translateIMInitEvent(const QWSIMInitEvent *e)
+{
+ Q_UNUSED(e);
+ qDebug("### QWSInputContext::translateIMInitEvent not implemented ###");
+ return false;
+}
+
+bool QWSInputContext::translateIMEvent(QWidget *w, const QWSIMEvent *e)
+{
+ QDataStream stream(e->streamingData);
+ QString preedit;
+ QString commit;
+
+ stream >> preedit;
+ stream >> commit;
+
+ if (preedit.isEmpty() && ::activeWidget)
+ w = ::activeWidget;
+
+ QInputContext *qic = w->inputContext();
+ if (!qic)
+ return false;
+
+ QList<QInputMethodEvent::Attribute> attrs;
+
+
+ while (!stream.atEnd()) {
+ int type = -1;
+ int start = -1;
+ int length = -1;
+ QVariant data;
+ stream >> type >> start >> length >> data;
+ if (stream.status() != QDataStream::Ok) {
+ qWarning("corrupted QWSIMEvent");
+ //qic->reset(); //???
+ return false;
+ }
+ if (type == QInputMethodEvent::TextFormat)
+ data = qic->standardFormat(static_cast<QInputContext::StandardFormat>(data.toInt()));
+ attrs << QInputMethodEvent::Attribute(static_cast<QInputMethodEvent::AttributeType>(type), start, length, data);
+ }
+#ifdef EXTRA_DEBUG
+ qDebug() << "preedit" << preedit << "len" << preedit.length() <<"commit" << commit << "len" << commit.length()
+ << "n attr" << attrs.count();
+#endif
+
+ if (preedit.isEmpty())
+ ::activeWidget = 0;
+ else
+ ::activeWidget = w;
+
+
+ QInputMethodEvent ime(preedit, attrs);
+ if (!commit.isEmpty() || e->simpleData.replaceLength > 0)
+ ime.setCommitString(commit, e->simpleData.replaceFrom, e->simpleData.replaceLength);
+
+
+ extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); //qapplication_qws.cpp
+ qt_sendSpontaneousEvent(w, &ime);
+
+ return true;
+}
+
+Q_GUI_EXPORT void (*qt_qws_inputMethodStatusChanged)(QWidget*) = 0;
+
+void QInputContextPrivate::updateImeStatus(QWidget *w, bool hasFocus)
+{
+ Q_UNUSED(hasFocus);
+
+ if (!w || !qt_qws_inputMethodStatusChanged)
+ return;
+ qt_qws_inputMethodStatusChanged(w);
+}
+
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_QWS_INPUTMETHODS
diff --git a/src/gui/inputmethod/qximinputcontext_p.h b/src/gui/inputmethod/qximinputcontext_p.h
new file mode 100644
index 0000000..ca2103b
--- /dev/null
+++ b/src/gui/inputmethod/qximinputcontext_p.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/****************************************************************************
+**
+** Definition of QXIMInputContext class
+**
+** Copyright (C) 2003-2004 immodule for Qt Project. All rights reserved.
+**
+** This file is written to contribute to Nokia Corporation and/or its subsidiary(-ies) under their own
+** license. You may use this file under your Qt license. Following
+** description is copied from their original file headers. Contact
+** immodule-qt@freedesktop.org if any conditions of this licensing are
+** not clear to you.
+**
+****************************************************************************/
+
+#ifndef QXIMINPUTCONTEXT_P_H
+#define QXIMINPUTCONTEXT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#if !defined(Q_NO_IM)
+
+#include "QtCore/qglobal.h"
+#include "QtGui/qinputcontext.h"
+#include "QtGui/qfont.h"
+#include "QtCore/qhash.h"
+#ifdef Q_WS_X11
+#include "QtCore/qlist.h"
+#include "QtCore/qbitarray.h"
+#include "QtGui/qwindowdefs.h"
+#include "private/qt_x11_p.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QKeyEvent;
+class QWidget;
+class QFont;
+class QString;
+
+class QXIMInputContext : public QInputContext
+{
+ Q_OBJECT
+public:
+ struct ICData {
+ XIC ic;
+ XFontSet fontset;
+ QWidget *widget;
+ QString text;
+ QBitArray selectedChars;
+ bool composing;
+ void clear();
+ };
+
+ QXIMInputContext();
+ ~QXIMInputContext();
+
+ QString identifierName();
+ QString language();
+
+ void reset();
+
+ void mouseHandler( int x, QMouseEvent *event);
+ bool isComposing() const;
+
+ void setFocusWidget( QWidget *w );
+ void widgetDestroyed(QWidget *w);
+
+ void create_xim();
+ void close_xim();
+
+ void update();
+
+ ICData *icData() const;
+protected:
+ bool x11FilterEvent( QWidget *keywidget, XEvent *event );
+
+private:
+ static XIMStyle xim_style;
+
+ QString _language;
+ XIM xim;
+ QHash<WId, ICData *> ximData;
+
+ ICData *createICData(QWidget *w);
+};
+
+QT_END_NAMESPACE
+
+#endif // Q_NO_IM
+
+#endif // QXIMINPUTCONTEXT_P_H
diff --git a/src/gui/inputmethod/qximinputcontext_x11.cpp b/src/gui/inputmethod/qximinputcontext_x11.cpp
new file mode 100644
index 0000000..48a96b1
--- /dev/null
+++ b/src/gui/inputmethod/qximinputcontext_x11.cpp
@@ -0,0 +1,832 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/****************************************************************************
+**
+** Implementation of QXIMInputContext class
+**
+** Copyright (C) 2003-2004 immodule for Qt Project. All rights reserved.
+**
+** This file is written to contribute to Nokia Corporation and/or its subsidiary(-ies) under their own
+** license. You may use this file under your Qt license. Following
+** description is copied from their original file headers. Contact
+** immodule-qt@freedesktop.org if any conditions of this licensing are
+** not clear to you.
+**
+****************************************************************************/
+
+#include "qdebug.h"
+#include "qximinputcontext_p.h"
+
+#if !defined(QT_NO_IM)
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_NO_XIM)
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "qplatformdefs.h"
+
+#include "qapplication.h"
+#include "qwidget.h"
+#include "qstring.h"
+#include "qlist.h"
+#include "qtextcodec.h"
+#include "qevent.h"
+#include "qtextformat.h"
+
+#include "qx11info_x11.h"
+
+#include <stdlib.h>
+#include <limits.h>
+QT_END_INCLUDE_NAMESPACE
+
+// #define QT_XIM_DEBUG
+#ifdef QT_XIM_DEBUG
+#define XIM_DEBUG qDebug
+#else
+#define XIM_DEBUG if (0) qDebug
+#endif
+
+// from qapplication_x11.cpp
+// #### move to X11 struct
+extern XIMStyle qt_xim_preferred_style;
+extern char *qt_ximServer;
+extern int qt_ximComposingKeycode;
+extern QTextCodec * qt_input_mapper;
+
+XIMStyle QXIMInputContext::xim_style = 0;
+// moved from qapplication_x11.cpp
+static const XIMStyle xim_default_style = XIMPreeditCallbacks | XIMStatusNothing;
+
+
+extern "C" {
+#ifdef USE_X11R6_XIM
+ static void xim_create_callback(XIM /*im*/,
+ XPointer client_data,
+ XPointer /*call_data*/)
+ {
+ QXIMInputContext *qic = reinterpret_cast<QXIMInputContext *>(client_data);
+ // qDebug("xim_create_callback");
+ qic->create_xim();
+ }
+
+ static void xim_destroy_callback(XIM /*im*/,
+ XPointer client_data,
+ XPointer /*call_data*/)
+ {
+ QXIMInputContext *qic = reinterpret_cast<QXIMInputContext *>(client_data);
+ // qDebug("xim_destroy_callback");
+ qic->close_xim();
+ XRegisterIMInstantiateCallback(X11->display, 0, 0, 0,
+ (XIMProc) xim_create_callback, reinterpret_cast<char *>(qic));
+ }
+#endif // USE_X11R6_XIM
+
+ static int xic_start_callback(XIC, XPointer client_data, XPointer) {
+ QXIMInputContext *qic = (QXIMInputContext *) client_data;
+ if (!qic) {
+ XIM_DEBUG("xic_start_callback: no qic");
+ return 0;
+ }
+ QXIMInputContext::ICData *data = qic->icData();
+ if (!data) {
+ XIM_DEBUG("xic_start_callback: no ic data");
+ return 0;
+ }
+ XIM_DEBUG("xic_start_callback");
+
+ data->clear();
+ data->composing = true;
+
+ return 0;
+ }
+
+ static int xic_draw_callback(XIC, XPointer client_data, XPointer call_data) {
+ QXIMInputContext *qic = (QXIMInputContext *) client_data;
+ if (!qic) {
+ XIM_DEBUG("xic_draw_callback: no qic");
+ return 0;
+ }
+ QXIMInputContext::ICData *data = qic->icData();
+ if (!data) {
+ XIM_DEBUG("xic_draw_callback: no ic data");
+ return 0;
+ }
+ XIM_DEBUG("xic_draw_callback");
+
+
+ if(!data->composing) {
+ data->clear();
+ data->composing = true;
+ }
+
+ XIMPreeditDrawCallbackStruct *drawstruct = (XIMPreeditDrawCallbackStruct *) call_data;
+ XIMText *text = (XIMText *) drawstruct->text;
+ int cursor = drawstruct->caret, sellen = 0, selstart = 0;
+
+ if (!drawstruct->caret && !drawstruct->chg_first && !drawstruct->chg_length && !text) {
+ if(data->text.isEmpty()) {
+ XIM_DEBUG("compose emptied");
+ // if the composition string has been emptied, we need
+ // to send an InputMethodEnd event
+ QInputMethodEvent e;
+ qic->sendEvent(e);
+ data->clear();
+
+ // if the commit string has coming after here, InputMethodStart
+ // will be sent dynamically
+ }
+ return 0;
+ }
+
+ if (text) {
+ char *str = 0;
+ if (text->encoding_is_wchar) {
+ int l = wcstombs(NULL, text->string.wide_char, text->length);
+ if (l != -1) {
+ str = new char[l + 1];
+ wcstombs(str, text->string.wide_char, l);
+ str[l] = 0;
+ }
+ } else
+ str = text->string.multi_byte;
+
+ if (!str)
+ return 0;
+
+ QString s = QString::fromLocal8Bit(str);
+
+ if (text->encoding_is_wchar)
+ delete [] str;
+
+ if (drawstruct->chg_length < 0)
+ data->text.replace(drawstruct->chg_first, INT_MAX, s);
+ else
+ data->text.replace(drawstruct->chg_first, drawstruct->chg_length, s);
+
+ if (data->selectedChars.size() < data->text.length()) {
+ // expand the selectedChars array if the compose string is longer
+ int from = data->selectedChars.size();
+ data->selectedChars.resize(data->text.length());
+ for (int x = from; x < data->selectedChars.size(); ++x)
+ data->selectedChars.clearBit(x);
+ }
+
+ // determine if the changed chars are selected based on text->feedback
+ for (int x = 0; x < text->length; ++x)
+ data->selectedChars.setBit(x + drawstruct->chg_first,
+ (text->feedback ? (text->feedback[x] & XIMReverse) : 0));
+
+ // figure out where the selection starts, and how long it is
+ bool started = false;
+ for (int x = 0; x < qMin(data->selectedChars.size(), data->text.length()); ++x) {
+ if (started) {
+ if (data->selectedChars.testBit(x)) ++sellen;
+ else break;
+ } else {
+ if (data->selectedChars.testBit(x)) {
+ selstart = x;
+ started = true;
+ sellen = 1;
+ }
+ }
+ }
+ } else {
+ if (drawstruct->chg_length == 0)
+ drawstruct->chg_length = -1;
+
+ data->text.remove(drawstruct->chg_first, drawstruct->chg_length);
+ bool qt_compose_emptied = data->text.isEmpty();
+ if (qt_compose_emptied) {
+ XIM_DEBUG("compose emptied 2 text=%s", data->text.toUtf8().constData());
+ // if the composition string has been emptied, we need
+ // to send an InputMethodEnd event
+ QInputMethodEvent e;
+ qic->sendEvent(e);
+ data->clear();
+ // if the commit string has coming after here, InputMethodStart
+ // will be sent dynamically
+ return 0;
+ }
+ }
+
+ XIM_DEBUG("sending compose: '%s', cursor=%d, sellen=%d",
+ data->text.toUtf8().constData(), cursor, sellen);
+ QList<QInputMethodEvent::Attribute> attrs;
+ if (selstart > 0)
+ attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, selstart,
+ qic->standardFormat(QInputContext::PreeditFormat));
+ if (sellen)
+ attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, selstart, sellen,
+ qic->standardFormat(QInputContext::SelectionFormat));
+ if (selstart + sellen < data->text.length())
+ attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
+ selstart + sellen, data->text.length() - selstart - sellen,
+ qic->standardFormat(QInputContext::PreeditFormat));
+ attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, cursor, sellen ? 0 : 1, QVariant());
+ QInputMethodEvent e(data->text, attrs);
+ qic->sendEvent(e);
+
+ return 0;
+ }
+
+ static int xic_done_callback(XIC, XPointer client_data, XPointer) {
+ QXIMInputContext *qic = (QXIMInputContext *) client_data;
+ if (!qic)
+ return 0;
+
+ XIM_DEBUG("xic_done_callback");
+ // Don't send InputMethodEnd here. QXIMInputContext::x11FilterEvent()
+ // handles InputMethodEnd with commit string.
+ return 0;
+ }
+}
+
+void QXIMInputContext::ICData::clear()
+{
+ text = QString();
+ selectedChars.clear();
+ composing = false;
+}
+
+QXIMInputContext::ICData *QXIMInputContext::icData() const
+{
+ if (QWidget *w = focusWidget())
+ return ximData.value(w->effectiveWinId());
+ return 0;
+}
+/* The cache here is needed, as X11 leaks a few kb for every
+ XFreeFontSet call, so we avoid creating and deletion of fontsets as
+ much as possible
+*/
+static XFontSet fontsetCache[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+static int fontsetRefCount = 0;
+
+static const char * const fontsetnames[] = {
+ "-*-fixed-medium-r-*-*-16-*,-*-*-medium-r-*-*-16-*",
+ "-*-fixed-medium-i-*-*-16-*,-*-*-medium-i-*-*-16-*",
+ "-*-fixed-bold-r-*-*-16-*,-*-*-bold-r-*-*-16-*",
+ "-*-fixed-bold-i-*-*-16-*,-*-*-bold-i-*-*-16-*",
+ "-*-fixed-medium-r-*-*-24-*,-*-*-medium-r-*-*-24-*",
+ "-*-fixed-medium-i-*-*-24-*,-*-*-medium-i-*-*-24-*",
+ "-*-fixed-bold-r-*-*-24-*,-*-*-bold-r-*-*-24-*",
+ "-*-fixed-bold-i-*-*-24-*,-*-*-bold-i-*-*-24-*"
+};
+
+static XFontSet getFontSet(const QFont &f)
+{
+ int i = 0;
+ if (f.italic())
+ i |= 1;
+ if (f.bold())
+ i |= 2;
+
+ if (f.pointSize() > 20)
+ i += 4;
+
+ if (!fontsetCache[i]) {
+ Display* dpy = X11->display;
+ int missCount;
+ char** missList;
+ fontsetCache[i] = XCreateFontSet(dpy, fontsetnames[i], &missList, &missCount, 0);
+ if(missCount > 0)
+ XFreeStringList(missList);
+ if (!fontsetCache[i]) {
+ fontsetCache[i] = XCreateFontSet(dpy, "-*-fixed-*-*-*-*-16-*", &missList, &missCount, 0);
+ if(missCount > 0)
+ XFreeStringList(missList);
+ if (!fontsetCache[i])
+ fontsetCache[i] = (XFontSet)-1;
+ }
+ }
+ return (fontsetCache[i] == (XFontSet)-1) ? 0 : fontsetCache[i];
+}
+
+
+
+QXIMInputContext::QXIMInputContext()
+{
+ if (!qt_xim_preferred_style) // no configured input style, use the default
+ qt_xim_preferred_style = xim_default_style;
+
+ xim = 0;
+ QByteArray ximServerName(qt_ximServer);
+ if (qt_ximServer)
+ ximServerName.prepend("@im=");
+ else
+ ximServerName = "";
+
+ if (!XSupportsLocale())
+#ifndef QT_NO_DEBUG
+ qWarning("Qt: Locale not supported on X server")
+#endif
+ ;
+#ifdef USE_X11R6_XIM
+ else if (XSetLocaleModifiers (ximServerName.constData()) == 0)
+ qWarning("Qt: Cannot set locale modifiers: %s", ximServerName.constData());
+ else
+ XRegisterIMInstantiateCallback(X11->display, 0, 0, 0,
+ (XIMProc) xim_create_callback, reinterpret_cast<char *>(this));
+#else // !USE_X11R6_XIM
+ else if (XSetLocaleModifiers ("") == 0)
+ qWarning("Qt: Cannot set locale modifiers");
+ else
+ QXIMInputContext::create_xim();
+#endif // USE_X11R6_XIM
+}
+
+
+/*!\internal
+ Creates the application input method.
+*/
+void QXIMInputContext::create_xim()
+{
+ ++fontsetRefCount;
+#ifndef QT_NO_XIM
+ xim = XOpenIM(X11->display, 0, 0, 0);
+ if (xim) {
+
+#ifdef USE_X11R6_XIM
+ XIMCallback destroy;
+ destroy.callback = (XIMProc) xim_destroy_callback;
+ destroy.client_data = XPointer(this);
+ if (XSetIMValues(xim, XNDestroyCallback, &destroy, (char *) 0) != 0)
+ qWarning("Xlib doesn't support destroy callback");
+#endif // USE_X11R6_XIM
+
+ XIMStyles *styles = 0;
+ XGetIMValues(xim, XNQueryInputStyle, &styles, (char *) 0, (char *) 0);
+ if (styles) {
+ int i;
+ for (i = 0; !xim_style && i < styles->count_styles; i++) {
+ if (styles->supported_styles[i] == qt_xim_preferred_style) {
+ xim_style = qt_xim_preferred_style;
+ break;
+ }
+ }
+ // if the preferred input style couldn't be found, look for
+ // Nothing
+ for (i = 0; !xim_style && i < styles->count_styles; i++) {
+ if (styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing)) {
+ xim_style = XIMPreeditNothing | XIMStatusNothing;
+ break;
+ }
+ }
+ // ... and failing that, None.
+ for (i = 0; !xim_style && i < styles->count_styles; i++) {
+ if (styles->supported_styles[i] == (XIMPreeditNone |
+ XIMStatusNone)) {
+ xim_style = XIMPreeditNone | XIMStatusNone;
+ break;
+ }
+ }
+
+ // qDebug("QApplication: using im style %lx", xim_style);
+ XFree((char *)styles);
+ }
+
+ if (xim_style) {
+
+#ifdef USE_X11R6_XIM
+ XUnregisterIMInstantiateCallback(X11->display, 0, 0, 0,
+ (XIMProc) xim_create_callback, reinterpret_cast<char *>(this));
+#endif // USE_X11R6_XIM
+
+ if (QWidget *focusWidget = QApplication::focusWidget()) {
+ // 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))
+ setFocusWidget(focusWidget);
+ }
+ // following code fragment is not required for immodule
+ // version of XIM
+#if 0
+ QWidgetList list = qApp->topLevelWidgets();
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = list.at(i);
+ w->d->createTLSysExtra();
+ }
+#endif
+ } else {
+ // Give up
+ qWarning("No supported input style found."
+ " See InputMethod documentation.");
+ close_xim();
+ }
+ }
+#endif // QT_NO_XIM
+}
+
+/*!\internal
+ Closes the application input method.
+*/
+void QXIMInputContext::close_xim()
+{
+ for(QHash<WId, ICData *>::const_iterator i = ximData.constBegin(),
+ e = ximData.constEnd(); i != e; ++i) {
+ ICData *data = i.value();
+ if (data->ic)
+ XDestroyIC(data->ic);
+ delete data;
+ }
+ ximData.clear();
+
+ if ( --fontsetRefCount == 0 ) {
+ Display *dpy = X11->display;
+ for ( int i = 0; i < 8; i++ ) {
+ if ( fontsetCache[i] && fontsetCache[i] != (XFontSet)-1 ) {
+ XFreeFontSet(dpy, fontsetCache[i]);
+ fontsetCache[i] = 0;
+ }
+ }
+ }
+
+ setFocusWidget(0);
+ xim = 0;
+}
+
+
+
+QXIMInputContext::~QXIMInputContext()
+{
+ XIM old_xim = xim; // close_xim clears xim pointer.
+ close_xim();
+ if (old_xim)
+ XCloseIM(old_xim);
+}
+
+
+QString QXIMInputContext::identifierName()
+{
+ // the name should be "xim" rather than "XIM" to be consistent
+ // with corresponding immodule of GTK+
+ return QLatin1String("xim");
+}
+
+
+QString QXIMInputContext::language()
+{
+ QString language;
+ if (xim) {
+ QByteArray locale(XLocaleOfIM(xim));
+
+ if (locale.startsWith("zh")) {
+ // Chinese language should be formed as "zh_CN", "zh_TW", "zh_HK"
+ language = QLatin1String(locale.left(5));
+ } else {
+ // other languages should be two-letter ISO 639 language code
+ language = QLatin1String(locale.left(2));
+ }
+ }
+ return language;
+}
+
+void QXIMInputContext::reset()
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return;
+
+ ICData *data = ximData.value(w->effectiveWinId());
+ if (!data)
+ return;
+
+ if (data->ic) {
+ char *mb = XmbResetIC(data->ic);
+ QInputMethodEvent e;
+ if (mb) {
+ e.setCommitString(QString::fromLocal8Bit(mb));
+ XFree(mb);
+ }
+ sendEvent(e);
+ update();
+ }
+ data->clear();
+}
+
+void QXIMInputContext::widgetDestroyed(QWidget *w)
+{
+ QInputContext::widgetDestroyed(w);
+ ICData *data = ximData.take(w->effectiveWinId());
+ if (!data)
+ return;
+
+ data->clear();
+ if (data->ic)
+ XDestroyIC(data->ic);
+ delete data;
+}
+
+void QXIMInputContext::mouseHandler(int pos, QMouseEvent *e)
+{
+ if(e->type() != QEvent::MouseButtonPress)
+ return;
+
+ XIM_DEBUG("QXIMInputContext::mouseHandler pos=%d", pos);
+ if (QWidget *w = focusWidget()) {
+ ICData *data = ximData.value(w->effectiveWinId());
+ if (!data)
+ return;
+ if (pos < 0 || pos > data->text.length())
+ reset();
+ // ##### handle mouse position
+ }
+}
+
+bool QXIMInputContext::isComposing() const
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return false;
+
+ ICData *data = ximData.value(w->effectiveWinId());
+ if (!data)
+ return false;
+ return data->composing;
+}
+
+void QXIMInputContext::setFocusWidget(QWidget *w)
+{
+ if (!xim)
+ return;
+ QWidget *oldFocus = focusWidget();
+ if (oldFocus == w)
+ return;
+
+ if (language() != QLatin1String("ja"))
+ reset();
+
+ if (oldFocus) {
+ ICData *data = ximData.value(oldFocus->effectiveWinId());
+ if (data && data->ic)
+ XUnsetICFocus(data->ic);
+ }
+
+ QInputContext::setFocusWidget(w);
+
+ if (!w)
+ return;
+
+ ICData *data = ximData.value(w->effectiveWinId());
+ if (!data)
+ data = createICData(w);
+
+ if (data->ic)
+ XSetICFocus(data->ic);
+
+ update();
+}
+
+
+bool QXIMInputContext::x11FilterEvent(QWidget *keywidget, XEvent *event)
+{
+ int xkey_keycode = event->xkey.keycode;
+ if (!keywidget->testAttribute(Qt::WA_WState_Created))
+ return false;
+ if (XFilterEvent(event, keywidget->effectiveWinId())) {
+ qt_ximComposingKeycode = xkey_keycode; // ### not documented in xlib
+
+ update();
+
+ return true;
+ }
+ if (event->type != XKeyPress || event->xkey.keycode != 0)
+ return false;
+
+ QWidget *w = focusWidget();
+ if (keywidget != w)
+ return false;
+ ICData *data = ximData.value(w->effectiveWinId());
+ if (!data)
+ return false;
+
+ // input method has sent us a commit string
+ QByteArray string;
+ string.resize(513);
+ KeySym key; // unused
+ Status status; // unused
+ QString text;
+ int count = XmbLookupString(data->ic, &event->xkey, string.data(), string.size(),
+ &key, &status);
+
+ if (status == XBufferOverflow) {
+ string.resize(count + 1);
+ count = XmbLookupString(data->ic, &event->xkey, string.data(), string.size(),
+ &key, &status);
+ }
+ if (count > 0) {
+ // XmbLookupString() gave us some text, convert it to unicode
+ text = qt_input_mapper->toUnicode(string.constData() , count);
+ if (text.isEmpty()) {
+ // codec couldn't convert to unicode? this can happen when running in the
+ // C locale (or with no LANG set). try converting from latin-1
+ text = QString::fromLatin1(string.constData(), count);
+ }
+ }
+
+#if 0
+ if (!(xim_style & XIMPreeditCallbacks) || !isComposing()) {
+ // ############### send a regular key event here!
+ ;
+ }
+#endif
+
+ QInputMethodEvent e;
+ e.setCommitString(text);
+ sendEvent(e);
+ data->clear();
+
+ update();
+
+ return true;
+}
+
+
+QXIMInputContext::ICData *QXIMInputContext::createICData(QWidget *w)
+{
+ ICData *data = new ICData;
+ data->widget = w;
+
+ XVaNestedList preedit_attr = 0;
+ XIMCallback startcallback, drawcallback, donecallback;
+
+ QFont font = w->font();
+ data->fontset = getFontSet(font);
+
+ if (xim_style & XIMPreeditArea) {
+ XRectangle rect;
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = w->width();
+ rect.height = w->height();
+
+ preedit_attr = XVaCreateNestedList(0,
+ XNArea, &rect,
+ XNFontSet, data->fontset,
+ (char *) 0);
+ } else if (xim_style & XIMPreeditPosition) {
+ XPoint spot;
+ spot.x = 1;
+ spot.y = 1;
+
+ preedit_attr = XVaCreateNestedList(0,
+ XNSpotLocation, &spot,
+ XNFontSet, data->fontset,
+ (char *) 0);
+ } else if (xim_style & XIMPreeditCallbacks) {
+ startcallback.client_data = (XPointer) this;
+ startcallback.callback = (XIMProc) xic_start_callback;
+ drawcallback.client_data = (XPointer) this;
+ drawcallback.callback = (XIMProc)xic_draw_callback;
+ donecallback.client_data = (XPointer) this;
+ donecallback.callback = (XIMProc) xic_done_callback;
+
+ preedit_attr = XVaCreateNestedList(0,
+ XNPreeditStartCallback, &startcallback,
+ XNPreeditDrawCallback, &drawcallback,
+ XNPreeditDoneCallback, &donecallback,
+ (char *) 0);
+ }
+
+ if (preedit_attr) {
+ data->ic = XCreateIC(xim,
+ XNInputStyle, xim_style,
+ XNClientWindow, w->effectiveWinId(),
+ XNPreeditAttributes, preedit_attr,
+ (char *) 0);
+ XFree(preedit_attr);
+ } else {
+ data->ic = XCreateIC(xim,
+ XNInputStyle, xim_style,
+ XNClientWindow, w->effectiveWinId(),
+ (char *) 0);
+ }
+
+ if (data->ic) {
+ // when resetting the input context, preserve the input state
+ (void) XSetICValues(data->ic, XNResetState, XIMPreserveState, (char *) 0);
+ } else {
+ qWarning("Failed to create XIC");
+ }
+
+ ximData[w->effectiveWinId()] = data;
+ return data;
+}
+
+void QXIMInputContext::update()
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return;
+
+ ICData *data = ximData.value(w->effectiveWinId());
+ if (!data || !data->ic)
+ return;
+
+ QRect r = w->inputMethodQuery(Qt::ImMicroFocus).toRect();
+ QPoint p;
+ if (w->nativeParentWidget())
+ p = w->mapTo(w->nativeParentWidget(), QPoint((r.left() + r.right() + 1)/2, r.bottom()));
+ else
+ p = QPoint((r.left() + r.right() + 1)/2, r.bottom());
+ XPoint spot;
+ spot.x = p.x();
+ spot.y = p.y();
+
+ r = w->rect();
+ XRectangle area;
+ area.x = r.x();
+ area.y = r.y();
+ area.width = r.width();
+ area.height = r.height();
+
+ XFontSet fontset = getFontSet(qvariant_cast<QFont>(w->inputMethodQuery(Qt::ImFont)));
+ if (data->fontset == fontset)
+ fontset = 0;
+ else
+ data->fontset = fontset;
+
+ XVaNestedList preedit_attr;
+ if (fontset)
+ preedit_attr = XVaCreateNestedList(0,
+ XNSpotLocation, &spot,
+ XNArea, &area,
+ XNFontSet, fontset,
+ (char *) 0);
+ else
+ preedit_attr = XVaCreateNestedList(0,
+ XNSpotLocation, &spot,
+ XNArea, &area,
+ (char *) 0);
+
+ XSetICValues(data->ic, XNPreeditAttributes, preedit_attr, (char *) 0);
+ XFree(preedit_attr);
+}
+
+
+#else
+/*
+ When QT_NO_XIM is defined, we provide a dummy implementation for
+ this class. The reason for this is that the header file is moc'ed
+ regardless of QT_NO_XIM. The best would be to remove the file
+ completely from the pri file is QT_NO_XIM was defined, or for moc
+ to understand this preprocessor directive. Since the header does
+ not declare this class when QT_NO_XIM is defined, this is dead
+ code.
+*/
+bool QXIMInputContext::isComposing() const { return false; }
+QString QXIMInputContext::identifierName() { return QString(); }
+void QXIMInputContext::mouseHandler(int, QMouseEvent *) {}
+void QXIMInputContext::setFocusWidget(QWidget *) {}
+void QXIMInputContext::reset() {}
+void QXIMInputContext::update() {}
+QXIMInputContext::~QXIMInputContext() {}
+void QXIMInputContext::widgetDestroyed(QWidget *) {}
+QString QXIMInputContext::language() { return QString(); }
+bool QXIMInputContext::x11FilterEvent(QWidget *, XEvent *) { return true; }
+
+#endif //QT_NO_XIM
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_IM