diff options
Diffstat (limited to 'client/qt4')
| -rw-r--r-- | client/qt4/.gitignore | 1 | ||||
| -rw-r--r-- | client/qt4/Makefile.am | 55 | ||||
| -rw-r--r-- | client/qt4/ibus-client.cpp | 548 | ||||
| -rw-r--r-- | client/qt4/ibus-client.h | 87 | ||||
| -rw-r--r-- | client/qt4/ibus-input-context.cpp | 243 | ||||
| -rw-r--r-- | client/qt4/ibus-input-context.h | 69 | ||||
| -rw-r--r-- | client/qt4/ibus.pro | 40 | ||||
| -rw-r--r-- | client/qt4/im-ibus-qt.cpp | 136 |
8 files changed, 1179 insertions, 0 deletions
diff --git a/client/qt4/.gitignore b/client/qt4/.gitignore new file mode 100644 index 0000000..52bae9b --- /dev/null +++ b/client/qt4/.gitignore @@ -0,0 +1 @@ +moc*.cpp diff --git a/client/qt4/Makefile.am b/client/qt4/Makefile.am new file mode 100644 index 0000000..012a6b0 --- /dev/null +++ b/client/qt4/Makefile.am @@ -0,0 +1,55 @@ +# vim:set noet ts=4: +# +# ibus - The Input Bus +# +# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place, Suite 330, +# Boston, MA 02111-1307 USA + +EXTRA_DIST = \ + ibus-client.cpp \ + ibus-client.h \ + ibus-input-context.cpp \ + ibus-input-context.h \ + ibus.pro \ + im-ibus-qt.cpp \ + $(NULL) + +if IBUS_BUILD_QT4 +Makefile.qmake: ibus.pro + $(QMAKE) -makefile -o Makefile.qmake $(srcdir)/ibus.pro + +all-local: Makefile.qmake + $(MAKE) -f Makefile.qmake $(AM_MAKEFLAGS) all + +check-local: Makefile.qmake + +clean-local: Makefile.qmake + $(MAKE) -f Makefile.qmake $(AM_MAKEFLAGS) clean + +distclean-local: Makefile.qmake + $(MAKE) -f Makefile.qmake $(AM_MAKEFLAGS) distclean + +install-exec-local: Makefile.qmake + $(MAKE) -f Makefile.qmake $(AM_MAKEFLAGS) INSTALL_ROOT=$(DESTDIR) install + +uninstall-local: Makefile.qmake + $(MAKE) -f Makefile.qmake $(AM_MAKEFLAGS) INSTALL_ROOT=$(DESTDIR) uninstall + +test: all + QT_IM_MODULE=ibus kwrite +endif + diff --git a/client/qt4/ibus-client.cpp b/client/qt4/ibus-client.cpp new file mode 100644 index 0000000..cb37b1b --- /dev/null +++ b/client/qt4/ibus-client.cpp @@ -0,0 +1,548 @@ +/* vim:set noet ts=4: */ +/* + * ibus - The Input Bus + * + * Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + */ +#include <QtDebug> +#include <QFile> +#include <QDBusConnection> +#include <QCoreApplication> +#include <QDBusMessage> +#include <QDBusArgument> + +#include "ibus-client.h" +#include "ibus-input-context.h" + +#ifdef Q_WS_X11 +# include <QX11Info> +# include <X11/Xlib.h> +# include <X11/keysym.h> +# include <X11/Xutil.h> +#endif + +#define IBUS_NAME "org.freedesktop.IBus" +#define IBUS_PATH "/org/freedesktop/IBus" +#define IBUS_INTERFACE "org.freedesktop.IBus" + + +IBusClient::IBusClient () + : ibus (NULL), focused_context (NULL) +{ + username = getlogin (); + if (username.isNull ()) + username = getenv ("LOGNAME"); + if (username.isNull ()) + username = getenv ("USER"); + if (username.isNull ()) + username = getenv ("LNAME"); + if (username.isNull ()) + username = getenv ("USERNAME"); + + session = getenv ("DISPLAY"); + session.replace (":", "-"); + + ibus_addr = QString("unix:path=/tmp/ibus-%1/ibus-%2").arg (username, session); + connectToBus (); + + QObject::connect ( + &watcher, + SIGNAL(directoryChanged(const QString &)), + this, + SLOT(slotDirectoryChanged(const QString &))); + + QString ibus_dir; + + ibus_dir = QString ("/tmp/ibus-%1/").arg (username); + watcher.addPath (ibus_dir); +} + +IBusClient::~IBusClient () +{ + if (ibus) + delete ibus; +} + +QString +IBusClient::createInputContextRemote () +{ + QString ic; + if (ibus) { + QDBusMessage message = QDBusMessage::createMethodCall ( + IBUS_NAME, + IBUS_PATH, + IBUS_INTERFACE, + "CreateInputContext"); + message << QCoreApplication::applicationName (); + message = ibus->call (message); + + if (message.type () == QDBusMessage::ErrorMessage) { + qWarning() << message.errorMessage (); + } + else if (message.type () == QDBusMessage::ReplyMessage) { + ic = message.arguments () [0].toString (); + } + } + return ic; +} + +QInputContext * +IBusClient::createInputContext () +{ + IBusInputContext *ctx; + QString ic; + + ic = createInputContextRemote (); + + ctx = new IBusInputContext (0, this, ic); + context_list.append (ctx); + + if (! ic.isEmpty ()) { + context_dict[ic] = ctx; + } + + return (QInputContext *) ctx; +} + +void +IBusClient::releaseInputContext (IBusInputContext *ctx) +{ + Q_ASSERT (ctx); + + QString ic = ctx->getIC (); + + if (ibus && !ic.isEmpty ()) { + QDBusMessage message = QDBusMessage::createMethodCall ( + IBUS_NAME, + IBUS_PATH, + IBUS_INTERFACE, + "ReleaseInputContext"); + message << ctx->getIC (); + message = ibus->call (message); + + if (message.type () == QDBusMessage::ErrorMessage) { + qWarning() << message.errorMessage (); + } + context_dict.remove (ic); + } + context_list.removeAll (ctx); +} + +#ifndef Q_WS_X11 +static void +translate_key_event (const QKeyEvent *event, quint32 *keyval, bool *is_press, quint32 *state) +{ + Q_ASSERT (event); + Q_ASSERT (keyval); + Q_ASSERT (is_press); + Q_ASSERT (state); + + *keyval = event->key (); + *is_press = (event->type() == QEvent::KeyPress); + + Qt::KeyboardModifiers modifiers = event->modifiers (); + *state = 0; + if (modifiers & Qt::ShiftModifier) { + *state |= (1<< 0); + } + if (modifiers & Qt::ControlModifier) { + *state |= (1<< 2); + } + if (modifiers & Qt::AltModifier) { + *state |= (1<< 3); + } + if (modifiers & Qt::MetaModifier) { + *state |= (1<< 28); + } + if (modifiers & Qt::KeypadModifier) { + // *state |= (1<< 28); + } + if (modifiers & Qt::GroupSwitchModifier) { + // *state |= (1<< 28); + } +} + +bool +IBusClient::filterEvent (IBusInputContext *ctx, QEvent *event) +{ + return true; +} +#endif + +#ifdef Q_WS_X11 +static inline bool +translate_x_key_event (XEvent *xevent, quint32 *keyval, bool *is_press, quint32 *state) +{ + Q_ASSERT (xevent); + Q_ASSERT (keyval); + Q_ASSERT (state); + Q_ASSERT (is_press); + + if (xevent->type != KeyPress && xevent->type != KeyRelease) + return false; + + *is_press = (xevent->type == KeyPress); + *state = xevent->xkey.state; + + char key_str[64]; + + if (XLookupString (&xevent->xkey, key_str, sizeof (key_str), (KeySym *)keyval, 0) <= 0) { + *keyval = (quint32) XLookupKeysym (&xevent->xkey, 0); + } + + return true; + +} + +bool +IBusClient::x11FilterEvent (IBusInputContext *ctx, QWidget * /* keywidget */, XEvent *xevent) +{ + Q_ASSERT (ctx); + Q_ASSERT (keywidget); + Q_ASSERT (xevent); + + quint32 keyval; + quint32 state; + bool is_press; + + if (focused_context != ctx) { + focusIn (ctx); + } + + if (ibus == NULL || !ibus->isConnected () || ctx->getIC().isEmpty ()) + return false; + + if (!translate_x_key_event (xevent, &keyval, &is_press, &state)) + return false; + QDBusMessage message = QDBusMessage::createMethodCall ( + IBUS_NAME, + IBUS_PATH, + IBUS_INTERFACE, + "ProcessKeyEvent"); + message << ctx->getIC (); + message << keyval; + message << is_press; + message << state; + + message = ibus->call (message); + + if (message.type() == QDBusMessage::ErrorMessage) { + qWarning() << message.errorMessage (); + return false; + } + else + return message.arguments ()[0].toBool (); +} +#endif + +void +IBusClient::mouseHandler (IBusInputContext * /*ctx */, int /* x */, QMouseEvent * /* event */) +{ + return; +} + +void +IBusClient::setCursorLocation (IBusInputContext *ctx, QRect &rect) +{ + Q_ASSERT (ctx); + + if (focused_context != ctx) { + focusIn (ctx); + } + + if (ibus == NULL || !ibus->isConnected () || ctx->getIC().isEmpty ()) + return; + + QDBusMessage message = QDBusMessage::createMethodCall ( + IBUS_NAME, + IBUS_PATH, + IBUS_INTERFACE, + "SetCursorLocation"); + message << ctx->getIC (); + message << rect.x (); + message << rect.y (); + message << rect.width (); + message << rect.height (); + message = ibus->call (message); + if (message.type() == QDBusMessage::ErrorMessage) { + qWarning() << message.errorMessage (); + } +} + +void +IBusClient::reset (IBusInputContext *ctx) +{ + Q_ASSERT (ctx); + + if (ibus == NULL || !ibus->isConnected () || ctx->getIC().isEmpty ()) + return; + QDBusMessage message = QDBusMessage::createMethodCall ( + IBUS_NAME, + IBUS_PATH, + IBUS_INTERFACE, + "Reset"); + message << ctx->getIC (); + message = ibus->call (message); + if (message.type() == QDBusMessage::ErrorMessage) { + qWarning() << message.errorMessage (); + } +} + +void +IBusClient::focusIn (IBusInputContext *ctx) +{ + Q_ASSERT (ctx); + if (focused_context != ctx && focused_context != NULL) + focusOut (focused_context); + focused_context = ctx; + + if (ibus == NULL || !ibus->isConnected () || ctx->getIC().isEmpty ()) + return; + QDBusMessage message = QDBusMessage::createMethodCall ( + IBUS_NAME, + IBUS_PATH, + IBUS_INTERFACE, + "FocusIn"); + message << ctx->getIC (); + message = ibus->call (message); + if (message.type() == QDBusMessage::ErrorMessage) { + qWarning() << message.errorMessage (); + } + +} + +void +IBusClient::focusOut (IBusInputContext *ctx) +{ + Q_ASSERT (ctx); + + if (focused_context != ctx) + return; + + focused_context = NULL; + + if (ibus == NULL || !ibus->isConnected () || ctx->getIC().isEmpty ()) + return; + + QDBusMessage message = QDBusMessage::createMethodCall ( + IBUS_NAME, + IBUS_PATH, + IBUS_INTERFACE, + "FocusOut"); + message << ctx->getIC (); + message = ibus->call (message); + if (message.type() == QDBusMessage::ErrorMessage) { + qWarning() << message.errorMessage (); + } +} +void +IBusClient::widgetDestroyed (IBusInputContext * /* ctx */, QWidget * /* widget */) +{ +} + +bool +IBusClient::connectToBus () +{ + QDBusConnection *connection = NULL; + + if (ibus != NULL) + return false; + + connection = new QDBusConnection ( + QDBusConnection::connectToBus ( + ibus_addr, + QString ("ibus"))); + + if (!connection->isConnected ()) { + delete connection; + QDBusConnection::disconnectFromBus ("ibus"); + return false; + } + + if (!connection->connect ("", + "", + "org.freedesktop.DBus.Local", + "Disconnected", + this, SLOT (slotIBusDisconnected()))) { + qWarning () << "Can not connect Disconnected signal"; + delete connection; + QDBusConnection::disconnectFromBus ("ibus"); + return false; + } + + if (!connection->connect ("", + IBUS_PATH, + IBUS_INTERFACE, + "CommitString", + this, SLOT (slotCommitString(QString, QString)))) { + qWarning () << "Can not connect CommitString signal"; + delete connection; + QDBusConnection::disconnectFromBus ("ibus"); + return false; + } + + if (!connection->connect ("", + IBUS_PATH, + IBUS_INTERFACE, + "UpdatePreedit", + this, SLOT (slotUpdatePreedit(QDBusMessage)))) { + qWarning () << "Can not connect UpdatePreedit signal"; + delete connection; + QDBusConnection::disconnectFromBus ("ibus"); + return false; + } + + if (!connection->connect ("", + IBUS_PATH, + IBUS_INTERFACE, + "ShowPreedit", + this, SLOT (slotShowPreedit(QDBusMessage)))) { + qWarning () << "Can not connect ShowPreedit signal"; + delete connection; + QDBusConnection::disconnectFromBus ("ibus"); + return false; + } + + if (!connection->connect ("", + IBUS_PATH, + IBUS_INTERFACE, + "HidePreedit", + this, SLOT (slotHidePreedit(QDBusMessage)))) { + qWarning () << "Can not connect ShowPreedit signal"; + delete connection; + QDBusConnection::disconnectFromBus ("ibus"); + return false; + } + + ibus = connection; + + QList <IBusInputContext *>::iterator i; + for (i = context_list.begin (); i != context_list.end (); ++i ) { + QString ic = createInputContextRemote (); + (*i)->setIC (ic); + context_dict[ic] = *i; + } + + return true; +} + +void +IBusClient::disconnectFromBus () +{ + if (ibus) { + delete ibus; + ibus = NULL; + QDBusConnection::disconnectFromBus ("ibus"); + QList <IBusInputContext *>::iterator i; + for (i = context_list.begin (); i != context_list.end (); ++i ) { + (*i)->setIC (""); + } + context_dict.clear (); + } +} + +void +IBusClient::slotDirectoryChanged (const QString & /*path*/) +{ + if (ibus && !ibus->isConnected ()) + disconnectFromBus (); + + if (ibus == NULL ) { + if (QFile::exists (ibus_addr)) { + usleep (500); + connectToBus (); + } + } +} + +void +IBusClient::slotIBusDisconnected () +{ + disconnectFromBus (); +} + + +void +IBusClient::slotCommitString (QString ic, QString text) +{ + IBusInputContext *ctx = context_dict[ic]; + ctx->commitString (text); +} + +void +IBusClient::slotUpdatePreedit (QDBusMessage message) +{ + QString ic; + QString text; + QVariant attrs; + int cursor_pos; + bool visible; + + QList<QVariant> args = message.arguments (); + + ic = args[0].toString (); + text = args[1].toString (); + attrs = args[2]; + cursor_pos = args[3].toInt (); + visible = args[4].toBool (); + QList <QList <quint32> > attr_list; + const QDBusArgument arg = attrs.value <QDBusArgument> (); + arg.beginArray (); + while ( !arg.atEnd ()) { + quint32 type, value, start_index, end_index; + + arg.beginArray (); + arg >> type >> value >> start_index >> end_index; + arg.endArray (); + QList <quint32> attr; + attr.append (type); + attr.append (value); + attr.append (start_index); + attr.append (end_index); + attr_list.append (attr); + } + arg.endArray (); + + IBusInputContext *ctx = context_dict[ic]; + ctx->updatePreedit (text, attr_list, cursor_pos, visible); +} + +void +IBusClient::slotShowPreedit (QDBusMessage message) +{ + QString ic; + + QList<QVariant> args = message.arguments (); + + ic = args[0].toString (); + IBusInputContext *ctx = context_dict[ic]; + ctx->showPreedit (); +} + +void +IBusClient::slotHidePreedit (QDBusMessage message) +{ + QString ic; + + QList<QVariant> args = message.arguments (); + + ic = args[0].toString (); + IBusInputContext *ctx = context_dict[ic]; + ctx->hidePreedit (); +} + diff --git a/client/qt4/ibus-client.h b/client/qt4/ibus-client.h new file mode 100644 index 0000000..285d633 --- /dev/null +++ b/client/qt4/ibus-client.h @@ -0,0 +1,87 @@ +/* vim:set noet ts=4: */ +/* + * ibus - The Input Bus + * + * Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + */ +#ifndef __IBUS_CLIENT_H_ +#define __IBUS_CLIENT_H_ +#include <QObject> +#include <QList> +#include <QHash> +#include <QInputContext> +#include <QFileSystemWatcher> +#include <QDBusMessage> + +class QDBusConnection; +class IBusInputContext; + +class IBusClient : public QObject { + Q_OBJECT +public: + IBusClient (); + ~IBusClient (); + +public: + +#ifndef Q_WS_X11 + bool filterEvent (IBusInputContext *ctx, const QEvent *event); +#endif + + bool isComposing (IBusInputContext const *ctx); + void mouseHandler (IBusInputContext *ctx, int x, QMouseEvent *event); + void widgetDestroyed (IBusInputContext *ctx, QWidget *widget); + +#ifdef Q_WS_X11 + bool x11FilterEvent (IBusInputContext *ctx, QWidget *keywidget, XEvent *xevent); +#endif + +public: + QInputContext *createInputContext (); + void releaseInputContext (IBusInputContext *ctx); + void setCursorLocation (IBusInputContext *ctx, QRect &rect); + void focusIn (IBusInputContext *ctx); + void focusOut (IBusInputContext *ctx); + void reset (IBusInputContext *ctx); + +private slots: + void slotDirectoryChanged (const QString &path); + void slotFileChanged (const QString &path); + void slotIBusDisconnected (); + void slotCommitString (QString ic, QString text); + //void slotUpdatePreedit (QString ic, QString text, QVariant attrs, int cursor_pos, bool show); + void slotUpdatePreedit (QDBusMessage message); + void slotShowPreedit (QDBusMessage message); + void slotHidePreedit (QDBusMessage message); + +private: + bool connectToBus (); + void disconnectFromBus (); + QString createInputContextRemote (); + + QDBusConnection *ibus; + QFileSystemWatcher watcher; + QList <IBusInputContext *> context_list; + QHash <QString, IBusInputContext *>context_dict; + IBusInputContext *focused_context; + QString username; + QString session; + QString ibus_addr; +}; + +#endif // __IBUS_CLIENT_H_ diff --git a/client/qt4/ibus-input-context.cpp b/client/qt4/ibus-input-context.cpp new file mode 100644 index 0000000..692fecb --- /dev/null +++ b/client/qt4/ibus-input-context.cpp @@ -0,0 +1,243 @@ +/* vim:set noet ts=4: */ +/* + * ibus - The Input Bus + * + * Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + */ +#include "ibus-input-context.h" +#include "ibus-client.h" +#include <QtDebug> +#include <QInputMethodEvent> +#include <QTextCharFormat> + +typedef QInputMethodEvent::Attribute QAttribute; + +IBusInputContext::IBusInputContext (QObject *parent, IBusClient *client, QString &ic) + : QInputContext (parent), client (client), ic (ic), preedit_visible (false) +{ +} + +IBusInputContext::~IBusInputContext () +{ + client->releaseInputContext (this); +} + +bool +IBusInputContext::filterEvent (const QEvent *event) +{ +#ifndef Q_WS_X11 + if (client->filterEvent (this, event)) + return true; + return QInputContext::filterEvent (event); +#else + return QInputContext::filterEvent (event); +#endif +} + +QFont +IBusInputContext::font () const +{ + return QInputContext::font (); +} + +QString +IBusInputContext::identifierName () +{ + return QString ("ibus"); +} + +QString +IBusInputContext::language() +{ + return QString (""); +} + +void +IBusInputContext::mouseHandler (int x, QMouseEvent *event) +{ + client->mouseHandler (this, x, event); + QInputContext::mouseHandler (x, event); +} + +void +IBusInputContext::reset() +{ + client->reset (this); +} + +void +IBusInputContext::update () +{ + QWidget *widget; + + if ((widget = focusWidget ()) == NULL) + return; + + QRect rect = widget->inputMethodQuery(Qt::ImMicroFocus).toRect (); + +#if 0 + QFont font = widget->inputMethodQuery(Qt::ImFont).value <QFont> (); + qDebug () << rect << preedit_string << preedit_cursor_pos; + + QFontMetrics fm(font); + int textWidth = fm.width (preedit_string.left (preedit_cursor_pos)); + rect.translate (textWidth, 0); +#endif + + QPoint topleft = widget->mapToGlobal(QPoint(0,0)); + rect.translate (topleft); + if (cursor_location != rect ) { + client->setCursorLocation (this, rect); + cursor_location = rect; + } + +#if 0 + QVariant value; + value = widget->inputMethodQuery(Qt::ImMicroFocus); + qDebug () << value; + value = widget->inputMethodQuery(Qt::ImFont); + qDebug () << value; + value = widget->inputMethodQuery(Qt::ImCursorPosition); + qDebug () << value; + value = widget->inputMethodQuery(Qt::ImSurroundingText); + qDebug () << value; + value = widget->inputMethodQuery(Qt::ImCurrentSelection); + qDebug () << value; +#endif +} + +bool +IBusInputContext::isComposing() const +{ + return (!preedit_string.isEmpty ()) && preedit_visible; +} + +void +IBusInputContext::setFocusWidget (QWidget *widget) +{ + // qDebug () << "setFocusWidget (" << widget << ")"; + QInputContext::setFocusWidget (widget); + update (); +} + +void +IBusInputContext::widgetDestroyed (QWidget *widget) +{ + QInputContext::widgetDestroyed (widget); + update (); +} + +#ifdef Q_WS_X11 +bool +IBusInputContext::x11FilterEvent (QWidget *keywidget, XEvent *xevent) +{ + if (client->x11FilterEvent (this, keywidget, xevent)) + return true; + return QInputContext::x11FilterEvent (keywidget, xevent); +} +#endif + +void +IBusInputContext::setIC (QString ic) +{ + this->ic = ic; +} + +QString +IBusInputContext::getIC () +{ + return ic; +} + +void +IBusInputContext::commitString (QString text) +{ + QInputMethodEvent event; + event.setCommitString (text); + sendEvent (event); + update (); +} + +void +IBusInputContext::updatePreedit (QString text, QList <QList <quint32> > attr_list, int cursor_pos, bool visible) +{ + // qDebug () << text << cursor_pos << show; + QList <QAttribute> qattrs; + + if (visible) { + // append cursor pos + qattrs.append (QAttribute (QInputMethodEvent::Cursor, cursor_pos, true, 0)); + + // append attributes + for (QList <QList <quint32> >::iterator it = attr_list.begin (); it != attr_list.end(); ++ it) { + + QList <quint32> attr = *it; + QTextCharFormat format; + + switch (attr[0]) { + case 1: // underline + format.setUnderlineStyle (QTextCharFormat::SingleUnderline); + break; + case 2: // foreground + format.setForeground (QBrush (QColor (attr[1]))); + break; + case 3: // background + format.setBackground (QBrush (QColor (attr[1]))); + break; + default: + break; + } + + qattrs.append (QAttribute (QInputMethodEvent::TextFormat, attr[2], attr[3] - attr[2], QVariant (format))); + // qDebug () << attr[0] << attr[2] << attr[3] - attr[2]; + } + } + else { + qattrs.append (QAttribute (QInputMethodEvent::Cursor, 0, true, 0)); + text = ""; + cursor_pos = 0; + } + + preedit_string = text; + preedit_visible = visible; + preedit_attrs = attr_list; + preedit_cursor_pos = cursor_pos; + + QInputMethodEvent event (text, qattrs); + sendEvent (event); + update (); +} + +void +IBusInputContext::showPreedit () +{ + if (preedit_visible) + return; + + updatePreedit (preedit_string, preedit_attrs, preedit_cursor_pos, TRUE); +} + +void +IBusInputContext::hidePreedit () +{ + if (!preedit_visible) + return; + + updatePreedit (preedit_string, preedit_attrs, preedit_cursor_pos, FALSE); +} + diff --git a/client/qt4/ibus-input-context.h b/client/qt4/ibus-input-context.h new file mode 100644 index 0000000..317c876 --- /dev/null +++ b/client/qt4/ibus-input-context.h @@ -0,0 +1,69 @@ +/* vim:set noet ts=4: */ +/* + * ibus - The Input Bus + * + * Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + */ +#ifndef __IBUS_INPUT_CONTEXT_H_ +#define __IBUS_INPUT_CONTEXT_H_ +#include <QInputContext> +#include <QList> +#include "ibus-client.h" + +class IBusClient; + +class IBusInputContext : public QInputContext { + Q_OBJECT +public: + IBusInputContext (QObject *parent, IBusClient *client, QString &ic); + ~IBusInputContext (); + +public: + bool filterEvent (const QEvent *event); + QFont font () const; + QString identifierName (); + bool isComposing() const; + QString language(); + void mouseHandler (int x, QMouseEvent *event); + void reset(); + void update (); + void setFocusWidget (QWidget *widget ); + void widgetDestroyed (QWidget *widget); +#ifdef Q_WS_X11 + bool x11FilterEvent (QWidget *keywidget, XEvent *event); +#endif + void setIC (QString ic); + QString getIC (); + + void commitString (QString text); + void updatePreedit (QString text, QList <QList <quint32> > attr_list, int cursor_pos, bool visible); + void showPreedit (); + void hidePreedit (); + + +private: + IBusClient *client; + QString ic; + QString preedit_string; + bool preedit_visible; + int preedit_cursor_pos; + QList <QList <quint32> > preedit_attrs; + QRect cursor_location; +}; + +#endif //__IBUS_INPUT_CONTEXT_H_ diff --git a/client/qt4/ibus.pro b/client/qt4/ibus.pro new file mode 100644 index 0000000..1c308a2 --- /dev/null +++ b/client/qt4/ibus.pro @@ -0,0 +1,40 @@ +# vim:set noet ts=4: +# +# ibus - The Input Bus +# +# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place, Suite 330, +# Boston, MA 02111-1307 USA + +TEMPLATE = lib +TARGET = ibus +DEPENDPATH += . +INCLUDEPATH += . + +CONFIG += qt qdbus plugin + +# Input +HEADERS += \ + ibus-client.h \ + ibus-input-context.h + +SOURCES += \ + ibus-client.cpp \ + ibus-input-context.cpp \ + im-ibus-qt.cpp + +target.path += $$[QT_INSTALL_PLUGINS]/inputmethods +INSTALLS += target diff --git a/client/qt4/im-ibus-qt.cpp b/client/qt4/im-ibus-qt.cpp new file mode 100644 index 0000000..0d6944b --- /dev/null +++ b/client/qt4/im-ibus-qt.cpp @@ -0,0 +1,136 @@ +/* vim:set noet ts=4: */ +/* + * ibus - The Input Bus + * + * Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + */ +#include <cassert> +#include <Qt> +#include <QInputContextPlugin> +#include "ibus-client.h" + +using namespace Qt; + +#define IBUS_IDENTIFIER_NAME "ibus" + +static IBusClient *client; + +/* The class Definition */ +class IBusInputContextPlugin: public QInputContextPlugin +{ + + private: + + /** + * The language list for SCIM. + */ + static QStringList ibus_languages; + + public: + + IBusInputContextPlugin (QObject *parent = 0); + + ~IBusInputContextPlugin (); + + QStringList keys () const; + + QStringList languages (const QString &key); + + QString description (const QString &key); + + QInputContext *create (const QString &key); + + QString displayName (const QString &key); + +}; + + +/* Implementations */ +QStringList IBusInputContextPlugin::ibus_languages; + + +IBusInputContextPlugin::IBusInputContextPlugin (QObject *parent) + :QInputContextPlugin (parent) +{ +} + + +IBusInputContextPlugin::~IBusInputContextPlugin () +{ + if (client != NULL) { + delete client; + client = NULL; + } +} + +QStringList +IBusInputContextPlugin::keys () const +{ + QStringList identifiers; + identifiers.push_back (IBUS_IDENTIFIER_NAME); + return identifiers; +} + + +QStringList +IBusInputContextPlugin::languages (const QString & key) +{ + if (key.toLower () != IBUS_IDENTIFIER_NAME) + return QStringList (); + + if (ibus_languages.empty ()) { + ibus_languages.push_back ("zh_CN"); + ibus_languages.push_back ("zh_TW"); + ibus_languages.push_back ("zh_HK"); + ibus_languages.push_back ("ja"); + ibus_languages.push_back ("ko"); + } + return ibus_languages; +} + + +QString +IBusInputContextPlugin::description (const QString &key) +{ + if (key.toLower () != IBUS_IDENTIFIER_NAME) + return QString (""); + + return QString::fromUtf8 ("Qt immodule plugin for IBus"); +} + + +QInputContext * +IBusInputContextPlugin::create (const QString &key) +{ + if (key.toLower () != IBUS_IDENTIFIER_NAME) { + return NULL; + } else { + if (client == NULL) { + client = new IBusClient (); + } + return client->createInputContext (); + } +} + + +QString IBusInputContextPlugin::displayName (const QString &key) +{ + return key; +} + +Q_EXPORT_PLUGIN2 (IBusInputContextPlugin, IBusInputContextPlugin) |
