diff options
author | Huang Peng <shawn.p.huang@gmail.com> | 2009-02-05 10:39:56 +0800 |
---|---|---|
committer | Huang Peng <shawn.p.huang@gmail.com> | 2009-02-05 10:39:56 +0800 |
commit | aedad1ea0a7fef604aa27f4b58433fd8f2ece29e (patch) | |
tree | ffcb531d8474bde18b90341bcd4eb639edd74525 | |
parent | 41ad46305a88637dd99f00a2d2a3f455505d357b (diff) | |
download | ibus-aedad1ea0a7fef604aa27f4b58433fd8f2ece29e.tar.gz ibus-aedad1ea0a7fef604aa27f4b58433fd8f2ece29e.tar.xz ibus-aedad1ea0a7fef604aa27f4b58433fd8f2ece29e.zip |
re-implement ibus in c language.
226 files changed, 33580 insertions, 10515 deletions
@@ -6,6 +6,7 @@ *.so *~ tags +TAGS Makefile.qmake Makefile Makefile.in @@ -34,3 +35,4 @@ stamp-h1 py-compile ibus-*.tar.* ibus.spec +ibus-1.0.pc diff --git a/Makefile.am b/Makefile.am index 7f99b46..47a21d0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,25 +19,30 @@ # Free Software Foundation, Inc., 59 Temple Place, Suite 330, # Boston, MA 02111-1307 USA -SUBDIRS = \ - daemon \ - gconf \ - ibus \ - launcher \ - ui \ - lib \ - util \ - client \ - setup \ - icons \ - m4 \ - po \ +SUBDIRS = \ + src \ + bindings \ + gconf \ + ibus \ + ui \ + util \ + client \ + setup \ + bus \ + icons \ + m4 \ + po \ + docs \ $(NULL) ACLOCAL_AMFLAGS = -I m4 +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = ibus-1.0.pc + EXTRA_DIST = \ autogen.sh \ + ibus-1.0.pc.in \ ibus.spec.in \ python-config.py \ $(NULL) @@ -55,6 +60,7 @@ install-data-hook: DISTCHECK_CONFIGURE_FLAGS = \ --enable-pygconf \ + --enable-gtk-doc \ $(NULL) rpm: dist @PACKAGE_NAME@.spec @@ -4,6 +4,7 @@ set -x autopoint --force libtoolize --automake --copy --force +gtkdocize #--flavour=no-tmpl aclocal -I m4 --force autoheader --force automake --add-missing --copy --force diff --git a/lib/Makefile.am b/bindings/Makefile.am index 19d7bc3..59fb9f4 100644 --- a/lib/Makefile.am +++ b/bindings/Makefile.am @@ -20,5 +20,5 @@ # Boston, MA 02111-1307 USA SUBDIRS = \ - gtk2 \ + python \ $(NULL) diff --git a/bindings/python/Makefile.am b/bindings/python/Makefile.am new file mode 100644 index 0000000..75a2e49 --- /dev/null +++ b/bindings/python/Makefile.am @@ -0,0 +1,80 @@ +# 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 + +# pyexec_PYTHON = +# pyexec_LTLIBRARIES = ibus.la +# +# INCLUDES = \ +# -I$(top_srcdir)/src \ +# -I$(top_builddir)/src \ +# $(NULL) +# +# ibus_la_SOURCES = ibus.c ibusmodule.c +# ibus_la_CFLAGS = \ +# @PYTHON_CFLAGS@ \ +# @GLIB2_CFLAGS@ \ +# @GOBJECT2_CFLAGS@ \ +# @PYGOBJECT2_CFLAGS@ \ +# @DBUS_CFLAGS@ \ +# $(NULL) +# ibus_la_LDFLAGS = \ +# @PYTHON_LIBS@ \ +# @GLIB2_LIBS@ \ +# @GOBJECT2_LIBS@ \ +# @DBUS_LIBS@ \ +# $(top_builddir)/src/libibus.la \ +# -avoid-version \ +# -module \ +# -export-symbols-regex "initibus" \ +# $(NULL) +# +# ibus-codegen.defs: +# (cd $(srcdir); \ +# ./gendefs.sh; ) > ibus-codegen.defs +# +# IBUS_DEFS = \ +# ibus.defs \ +# ibus-types.defs \ +# ibus-func.defs \ +# ibus-virtual-methods.defs \ +# ibus.override \ +# $(NULL) +# +# ibus.c: $(IBUS_DEFS) ibus.override ibus-codegen.defs +# +# CLEANFILES = ibus.c ibus-codegen.defs +# EXTRA_DIST = \ +# gendefs.sh \ +# common.h \ +# $(GIK_DEFS) \ +# $(NULL) +# +# PYGOBJECT_CODEGEN = pygobject-codegen-2.0 +# +# .defs.c: +# (cd $(srcdir)\ +# && $(PYGOBJECT_CODEGEN) \ +# -o $*.override \ +# -I $(abs_builddir) \ +# -p py$* $*.defs) > gen-$*.c \ +# && cp gen-$*.c $*.c \ +# && rm -f gen-$*.c +# diff --git a/bindings/python/common.h b/bindings/python/common.h new file mode 100644 index 0000000..f3267ee --- /dev/null +++ b/bindings/python/common.h @@ -0,0 +1,7 @@ +#ifndef __PY_COMMON_H_ +#define __PY_COMMON_H_ + +#include <pygobject.h> +#include <ibus.h> + +#endif //__PY_COMMON_H_ diff --git a/bindings/python/gendefs.sh b/bindings/python/gendefs.sh new file mode 100755 index 0000000..bc92257 --- /dev/null +++ b/bindings/python/gendefs.sh @@ -0,0 +1,3 @@ +#!/bin/sh +codegendir=`pkg-config pygobject-2.0 --variable=codegendir` +python $codegendir/h2def.py -m ibus ../../src/*.h diff --git a/bindings/python/ibus-types.defs b/bindings/python/ibus-types.defs new file mode 100644 index 0000000..a077851 --- /dev/null +++ b/bindings/python/ibus-types.defs @@ -0,0 +1,27 @@ +;; (define-boxed EventKey +;; (in-module "Gik") +;; (c-name "GikEventKey") +;; (gtype-id "GIK_TYPE_EVENT_KEY") +;; (copy-func "gik_event_copy") +;; (release-func "gik_event_free") +;; (fields +;; '("gint" "type") +;; '("guint" "state") +;; '("guint" "keyval") +;; '("guint16" "hardware_keycode") +;; '("guint" "is_modifier") +;; ) +;; ) +;; +;; (define-boxed Event +;; (in-module "Gik") +;; (c-name "GikEvent") +;; (gtype-id "GIK_TYPE_EVENT") +;; (copy-func "gik_event_copy") +;; (release-func "gik_event_free") +;; (fields +;; '("gint" "type") +;; '("GikEventKey" "key") +;; ) +;; ) +;; diff --git a/bindings/python/ibus-virtual-methods.defs b/bindings/python/ibus-virtual-methods.defs new file mode 100644 index 0000000..542f0b4 --- /dev/null +++ b/bindings/python/ibus-virtual-methods.defs @@ -0,0 +1,23 @@ +;; For GikEngine class +;; (define-virtual filter_keypress +;; (of-object "GikEngine") +;; (return-type "gboolean") +;; (parameters +;; '("GikEventKey*" "key") +;; ) +;; ) +;; +;; (define-virtual focus_in +;; (of-object "GikEngine") +;; (return-type "none") +;; ) +;; +;; (define-virtual focus_out +;; (of-object "GikEngine") +;; (return-type "none") +;; ) +;; +;; (define-virtual reset +;; (of-object "GikEngine") +;; (return-type "none") +;; ) diff --git a/bindings/python/ibus.defs b/bindings/python/ibus.defs new file mode 100644 index 0000000..eada9c8 --- /dev/null +++ b/bindings/python/ibus.defs @@ -0,0 +1,5 @@ +(include "ibus-types.defs") +(include "ibus-func.defs") +(include "ibus-virtual-methods.defs") +(include "ibus-codegen.defs") + diff --git a/bindings/python/ibus.override b/bindings/python/ibus.override new file mode 100644 index 0000000..a00771c --- /dev/null +++ b/bindings/python/ibus.override @@ -0,0 +1,11 @@ +%% +headers +#include "common.h" +%% +modulename ibus +%% +import gobject.GObject as PyGObject_Type +%% +ignore-glob + *_get_type +%% diff --git a/bindings/python/ibusmodule.c b/bindings/python/ibusmodule.c new file mode 100644 index 0000000..875ff88 --- /dev/null +++ b/bindings/python/ibusmodule.c @@ -0,0 +1,29 @@ +#include <Python.h> +#include <pygobject.h> + +void pyibus_register_classes (PyObject *d); +void pyibus_add_constants (PyObject *module, const gchar *strip_prefix); +extern PyMethodDef pyibus_functions[]; + + +DL_EXPORT(void) +initibus (void) +{ + PyObject *m, *d; + + init_pygobject (); + + m = Py_InitModule ("ibus", pyibus_functions); + d = PyModule_GetDict (m); + + pyibus_register_classes (d); + + if (PyErr_Occurred ()) { + Py_FatalError ("unable to initialise ibus module"); + } + pyibus_add_constants (m, "GIK_"); + if (PyErr_Occurred ()) { + Py_FatalError ("unable to initialise ibus module"); + } +} + diff --git a/bus/.gitignore b/bus/.gitignore new file mode 100644 index 0000000..847558d --- /dev/null +++ b/bus/.gitignore @@ -0,0 +1,2 @@ +ibus-daemon +test-matchrule diff --git a/bus/Makefile.am b/bus/Makefile.am new file mode 100644 index 0000000..d0f883a --- /dev/null +++ b/bus/Makefile.am @@ -0,0 +1,99 @@ +# 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 + +libibus = $(top_builddir)/src/libibus.la + +INCLUDES = \ + -I$(top_srcdir)/src \ + $(NULL) + +AM_CFLAGS = \ + @GLIB2_CFLAGS@ \ + @DBUS_CFLAGS@ \ + -DG_LOG_DOMAIN=\"IBUS\" \ + -DPKGDATADIR=\"$(pkgdatadir)\" \ + -DLIBEXECDIR=\"$(libexecdir)\" \ + $(INCLUDES) \ + $(NULL) +AM_LDFLAGS = \ + @GLIB2_LIBS@ \ + @DBUS_LIBS@ \ + $(libibus) \ + $(NULL) + +TESTS = \ + test-matchrule \ + $(NULL) + +noinst_PROGRAMS = $(TESTS) +bin_PROGRAMS = ibus-daemon +ibus_daemon_DEPENDENCIES = \ + $(libibus) \ + $(NULL) +ibus_daemon_SOURCES = \ + main.c \ + dbusimpl.c \ + dbusimpl.h \ + ibusimpl.c \ + ibusimpl.h \ + inputcontext.c \ + inputcontext.h \ + engineproxy.c \ + engineproxy.h \ + panelproxy.c \ + panelproxy.h \ + factoryproxy.c \ + factoryproxy.h \ + server.c \ + server.h \ + connection.c \ + connection.h \ + matchrule.c \ + matchrule.h \ + registry.c \ + registry.h \ + $(NULL) +ibus_daemon_CFLAGS = \ + $(AM_CFLAGS) \ + $(NULL) +ibus_daemon_LDADD = \ + $(AM_LDFLAGS) \ + $(NULL) + +test_registry_SOURCES = \ + registry.c \ + registry.h \ + factoryproxy.c \ + factoryproxy.h \ + test-registry.c \ + $(NULL) + +test_matchrule_SOURCES = \ + connection.c \ + matchrule.c \ + test-matchrule.c \ + $(NULL) + +$(libibus): + $(MAKE) -C $(top_builddir)/src + +test: ibus-daemon + $(builddir)/ibus-daemon diff --git a/bus/connection.c b/bus/connection.c new file mode 100644 index 0000000..fd05ab1 --- /dev/null +++ b/bus/connection.c @@ -0,0 +1,261 @@ +/* vim:set et sts=4: */ +/* bus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "connection.h" +#include "matchrule.h" + +#define BUS_CONNECTION_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), BUS_TYPE_CONNECTION, BusConnectionPrivate)) + +/* BusConnectionPriv */ +struct _BusConnectionPrivate { + gchar *unique_name; + /* list for well known names */ + GList *names; + GList *rules; +}; +typedef struct _BusConnectionPrivate BusConnectionPrivate; + +// static guint _signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void bus_connection_class_init (BusConnectionClass *klass); +static void bus_connection_init (BusConnection *connection); +static void bus_connection_destroy (BusConnection *connection); +static gboolean bus_connection_ibus_message (BusConnection *connection, + IBusMessage *message); +#if 0 +static gboolean bus_connection_dbus_signal (BusConnection *connection, + DBusMessage *message); +#endif + +static IBusObjectClass *parent_class = NULL; + +GType +bus_connection_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (BusConnectionClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) bus_connection_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusConnection), + 0, + (GInstanceInitFunc) bus_connection_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_CONNECTION, + "BusConnection", + &type_info, + (GTypeFlags)0); + } + + return type; +} + +BusConnection * +bus_connection_new (void) +{ + BusConnection *connection = BUS_CONNECTION (g_object_new (BUS_TYPE_CONNECTION, NULL)); + return connection; +} + +static void +bus_connection_class_init (BusConnectionClass *klass) +{ + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + IBusConnectionClass *ibus_connection_class = IBUS_CONNECTION_CLASS (klass); + + parent_class = (IBusObjectClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (BusConnectionPrivate)); + + ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_connection_destroy; + + ibus_connection_class->ibus_message = + (IBusIBusMessageFunc) bus_connection_ibus_message; + +} + +static void +bus_connection_init (BusConnection *connection) +{ + BusConnectionPrivate *priv; + + priv = BUS_CONNECTION_GET_PRIVATE (connection); + + priv->unique_name = NULL; + priv->names = NULL; +} + +static void +bus_connection_destroy (BusConnection *connection) +{ + GList *name; + BusConnectionPrivate *priv; + + IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (connection)); + + priv = BUS_CONNECTION_GET_PRIVATE (connection); + + if (priv->unique_name) { + g_free (priv->unique_name); + priv->unique_name = NULL; + } + + for (name = priv->names; name != NULL; name = name->next) { + g_free (name->data); + } + g_list_free (priv->names); + priv->names = NULL; +} + +static gboolean +bus_connection_ibus_message (BusConnection *connection, + IBusMessage *message) +{ + gboolean retval; + +#if 0 + gchar *str = ibus_message_to_string (message); + g_debug ("%s", str); + g_free(str); +#endif + + retval = IBUS_CONNECTION_CLASS (parent_class)->ibus_message ( + (IBusConnection *)connection, + message); + return retval; +} + +#if 0 +static gboolean +bus_connection_dbus_signal (BusConnection *connection, + DBusMessage *message) +{ + gboolean retval; + retval = IBUS_CONNECTION_CLASS (parent_class)->dbus_signal ( + IBUS_CONNECTION (connection), message); + return retval; +} +#endif + +const gchar * +bus_connection_get_unique_name (BusConnection *connection) +{ + BusConnectionPrivate *priv; + + priv = BUS_CONNECTION_GET_PRIVATE (connection); + return priv->unique_name; +} + +void +bus_connection_set_unique_name (BusConnection *connection, + const gchar *name) +{ + BusConnectionPrivate *priv; + priv = BUS_CONNECTION_GET_PRIVATE (connection); + g_assert (priv->unique_name == NULL); + priv->unique_name = g_strdup (name); +} + +const GList * +bus_connection_get_names (BusConnection *connection) +{ + BusConnectionPrivate *priv; + + priv = BUS_CONNECTION_GET_PRIVATE (connection); + return priv->names; +} + +const gchar * +bus_connection_add_name (BusConnection *connection, + const gchar *name) +{ + gchar *new_name; + BusConnectionPrivate *priv; + + priv = BUS_CONNECTION_GET_PRIVATE (connection); + new_name = g_strdup (name); + priv->names = g_list_append (priv->names, new_name); + + return new_name; +} + +gboolean +bus_connection_remove_name (BusConnection *connection, + const gchar *name) +{ + BusConnectionPrivate *priv; + GList *link; + + priv = BUS_CONNECTION_GET_PRIVATE (connection); + + link = g_list_find_custom (priv->names, name, (GCompareFunc) g_strcmp0); + + if (link) { + g_free (link->data); + priv->names = g_list_delete_link (priv->names, link); + return TRUE; + } + return FALSE; +} + +gboolean +bus_connection_add_match (BusConnection *connection, + const gchar *rule) +{ + g_assert (BUS_IS_CONNECTION (connection)); + g_assert (rule != NULL); + + BusMatchRule *p; + GList *link; + BusConnectionPrivate *priv; + + priv = BUS_CONNECTION_GET_PRIVATE (connection); + + p = bus_match_rule_new (rule); + if (p == NULL) + return FALSE; + + for (link = priv->rules; link != NULL; link = link->next) { + if (bus_match_rule_is_equal (p, (BusMatchRule *)link->data)) { + g_object_unref (p); + return TRUE; + } + } + + priv->rules = g_list_append (priv->rules, p); + return TRUE; + +} + +gboolean +bus_connection_remove_match (BusConnection *connection, + const gchar *rule) +{ + return FALSE; +} + diff --git a/bus/connection.h b/bus/connection.h new file mode 100644 index 0000000..1c0624d --- /dev/null +++ b/bus/connection.h @@ -0,0 +1,71 @@ +/* vim:set et sts=4: */ +/* bus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __CONNECTION_H_ +#define __CONNECTION_H_ + +#include <ibus.h> + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define BUS_TYPE_CONNECTION \ + (bus_connection_get_type ()) +#define BUS_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUS_TYPE_CONNECTION, BusConnection)) +#define BUS_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), BUS_TYPE_CONNECTION, BusConnectionClass)) +#define BUS_IS_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUS_TYPE_CONNECTION)) +#define BUS_IS_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), BUS_TYPE_CONNECTION)) +#define BUS_CONNECTION_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), BUS_TYPE_CONNECTION, BusConnectionClass)) + +G_BEGIN_DECLS + +typedef struct _BusConnection BusConnection; +typedef struct _BusConnectionClass BusConnectionClass; + +struct _BusConnection { + IBusConnection parent; + /* instance members */ +}; + +struct _BusConnectionClass { + IBusConnectionClass parent; + + /* class members */ +}; + +GType bus_connection_get_type (void); +BusConnection *bus_connection_new (void); +const gchar *bus_connection_get_unique_name (BusConnection *connection); +void bus_connection_set_unique_name (BusConnection *connection, + const gchar *name); +const GList *bus_connection_get_names (BusConnection *connection); +const gchar *bus_connection_add_name (BusConnection *connection, + const gchar *name); +gboolean bus_connection_remove_name (BusConnection *connection, + const gchar *name); +G_END_DECLS +#endif + diff --git a/bus/dbusimpl.c b/bus/dbusimpl.c new file mode 100644 index 0000000..6a70f89 --- /dev/null +++ b/bus/dbusimpl.c @@ -0,0 +1,1174 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <string.h> +#include <ibusinternal.h> +#include <ibusmarshalers.h> +#include "dbusimpl.h" +#include "connection.h" +#include "matchrule.h" + +#define BUS_DBUS_IMPL_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), BUS_TYPE_DBUS_IMPL, BusDBusImplPrivate)) + +enum { + NAME_ACQUIRED, + NAME_LOST, + NAME_OWNER_CHANGED, + LAST_SIGNAL, +}; + +enum { + PROP_0, +}; + + +/* IBusDBusImplPriv */ +struct _BusDBusImplPrivate { + GHashTable *unique_names; + GHashTable *names; + GHashTable *objects; + GList *connections; + GList *rules; + gint id; +}; + +typedef struct _BusDBusImplPrivate BusDBusImplPrivate; + +static guint dbus_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void bus_dbus_impl_class_init (BusDBusImplClass *klass); +static void bus_dbus_impl_init (BusDBusImpl *dbus); +static void bus_dbus_impl_dispose (BusDBusImpl *dbus); +static gboolean bus_dbus_impl_ibus_message (BusDBusImpl *dbus, + BusConnection *connection, + IBusMessage *message); +static void bus_dbus_impl_name_owner_changed + (BusDBusImpl *dbus, + gchar *name, + gchar *old_name, + gchar *new_name); + +static IBusServiceClass *parent_class = NULL; + +GType +bus_dbus_impl_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (BusDBusImplClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) bus_dbus_impl_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (BusDBusImpl), + 0, + (GInstanceInitFunc) bus_dbus_impl_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERVICE, + "BusDBusImpl", + &type_info, + (GTypeFlags) 0); + } + return type; +} + +BusDBusImpl * +bus_dbus_impl_get_default (void) +{ + // BusDBusImplPrivate *priv; + static BusDBusImpl *dbus = NULL; + + if (dbus == NULL) { + dbus = (BusDBusImpl *) g_object_new (BUS_TYPE_DBUS_IMPL, + "path", DBUS_PATH_DBUS, + NULL); + } + + return dbus; +} + +static void +bus_dbus_impl_class_init (BusDBusImplClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + IBusServiceClass *service_class = IBUS_SERVICE_CLASS (klass); + + parent_class = (IBusServiceClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (BusDBusImplPrivate)); + + gobject_class->dispose = (GObjectFinalizeFunc) bus_dbus_impl_dispose; + + service_class->ibus_message = (ServiceIBusMessageFunc) bus_dbus_impl_ibus_message; + + klass->name_owner_changed = bus_dbus_impl_name_owner_changed; + + /* install signals */ + dbus_signals[NAME_OWNER_CHANGED] = + g_signal_new (I_("name-owner-changed"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (BusDBusImplClass, name_owner_changed), + NULL, NULL, + ibus_marshal_VOID__STRING_STRING_STRING, + G_TYPE_NONE, + 3, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING); + +} + +static void +bus_dbus_impl_init (BusDBusImpl *dbus) +{ + BusDBusImplPrivate *priv; + priv = BUS_DBUS_IMPL_GET_PRIVATE (dbus); + + priv->unique_names = g_hash_table_new (g_str_hash, g_str_equal); + priv->names = g_hash_table_new (g_str_hash, g_str_equal); + priv->objects = g_hash_table_new (g_str_hash, g_str_equal); + priv->connections = NULL; + priv->rules = NULL; + priv->id = 1; + + g_object_ref (dbus); + g_hash_table_insert (priv->objects, DBUS_PATH_DBUS, dbus); +} + +static void +bus_dbus_impl_dispose (BusDBusImpl *dbus) +{ + BusDBusImplPrivate *priv; + priv = BUS_DBUS_IMPL_GET_PRIVATE (dbus); + + G_OBJECT_CLASS(parent_class)->dispose (G_OBJECT (dbus)); +} + + +/* introspectable interface */ +static IBusMessage * +_dbus_introspect (BusDBusImpl *dbus, + IBusMessage *message, + BusConnection *connection) +{ + static const gchar *introspect = + DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE + "<node>\n" + " <interface name=\"org.freedesktop.DBus.Introspectable\">\n" + " <method name=\"Introspect\">\n" + " <arg name=\"data\" direction=\"out\" type=\"s\"/>\n" + " </method>\n" + " </interface>\n" + " <interface name=\"org.freedesktop.DBus\">\n" + " <method name=\"Hello\">\n" + " <arg direction=\"out\" type=\"s\"/>\n" + " </method>\n" + " <method name=\"RequestName\">\n" + " <arg direction=\"in\" type=\"s\"/>\n" + " <arg direction=\"in\" type=\"u\"/>\n" + " <arg direction=\"out\" type=\"u\"/>\n" + " </method>\n" + " <method name=\"ReleaseName\">\n" + " <arg direction=\"in\" type=\"s\"/>\n" + " <arg direction=\"out\" type=\"u\"/>\n" + " </method>\n" + " <method name=\"StartServiceByName\">\n" + " <arg direction=\"in\" type=\"s\"/>\n" + " <arg direction=\"in\" type=\"u\"/>\n" + " <arg direction=\"out\" type=\"u\"/>\n" + " </method>\n" + " <method name=\"UpdateActivationEnvironment\">\n" + " <arg direction=\"in\" type=\"a{ss}\"/>\n" + " </method>\n" + " <method name=\"NameHasOwner\">\n" + " <arg direction=\"in\" type=\"s\"/>\n" + " <arg direction=\"out\" type=\"b\"/>\n" + " </method>\n" + " <method name=\"ListNames\">\n" + " <arg direction=\"out\" type=\"as\"/>\n" + " </method>\n" + " <method name=\"ListActivatableNames\">\n" + " <arg direction=\"out\" type=\"as\"/>\n" + " </method>\n" + " <method name=\"AddMatch\">\n" + " <arg direction=\"in\" type=\"s\"/>\n" + " </method>\n" + " <method name=\"RemoveMatch\">\n" + " <arg direction=\"in\" type=\"s\"/>\n" + " </method>\n" + " <method name=\"GetNameOwner\">\n" + " <arg direction=\"in\" type=\"s\"/>\n" + " <arg direction=\"out\" type=\"s\"/>\n" + " </method>\n" + " <method name=\"ListQueuedOwners\">\n" + " <arg direction=\"in\" type=\"s\"/>\n" + " <arg direction=\"out\" type=\"as\"/>\n" + " </method>\n" + " <method name=\"GetConnectionUnixUser\">\n" + " <arg direction=\"in\" type=\"s\"/>\n" + " <arg direction=\"out\" type=\"u\"/>\n" + " </method>\n" + " <method name=\"GetConnectionUnixProcessID\">\n" + " <arg direction=\"in\" type=\"s\"/>\n" + " <arg direction=\"out\" type=\"u\"/>\n" + " </method>\n" + " <method name=\"GetAdtAuditSessionData\">\n" + " <arg direction=\"in\" type=\"s\"/>\n" + " <arg direction=\"out\" type=\"ay\"/>\n" + " </method>\n" + " <method name=\"GetConnectionSELinuxSecurityContext\">\n" + " <arg direction=\"in\" type=\"s\"/>\n" + " <arg direction=\"out\" type=\"ay\"/>\n" + " </method>\n" + " <method name=\"ReloadConfig\">\n" + " </method>\n" + " <method name=\"GetId\">\n" + " <arg direction=\"out\" type=\"s\"/>\n" + " </method>\n" + " <signal name=\"NameOwnerChanged\">\n" + " <arg type=\"s\"/>\n" + " <arg type=\"s\"/>\n" + " <arg type=\"s\"/>\n" + " </signal>\n" + " <signal name=\"NameLost\">\n" + " <arg type=\"s\"/>\n" + " </signal>\n" + " <signal name=\"NameAcquired\">\n" + " <arg type=\"s\"/>\n" + " </signal>\n" + " </interface>\n" + "</node>\n"; + + IBusMessage *reply_message; + reply_message = ibus_message_new_method_return (message); + ibus_message_append_args (reply_message, + G_TYPE_STRING, &introspect, + G_TYPE_INVALID); + + return reply_message; +} + + +/* dbus interface */ +static IBusMessage * +_dbus_no_implement (BusDBusImpl *dbus, + IBusMessage *message, + BusConnection *connection) +{ + IBusMessage *reply_message; + reply_message = ibus_message_new_error_printf (message, + DBUS_ERROR_UNKNOWN_METHOD, + "IBus does not support %s.", + ibus_message_get_member (message)); + return reply_message; +} + + +static IBusMessage * +_dbus_hello (BusDBusImpl *dbus, + IBusMessage *message, + BusConnection *connection) +{ + BusDBusImplPrivate *priv; + priv = BUS_DBUS_IMPL_GET_PRIVATE (dbus); + + IBusMessage *reply_message; + + if (bus_connection_get_unique_name (connection) != NULL) { + reply_message = ibus_message_new_error (message, + DBUS_ERROR_FAILED, + "Already handled an Hello message"); + } + else { + gchar *name; + + name = g_strdup_printf (":1.%d", priv->id ++); + bus_connection_set_unique_name (connection, name); + g_free (name); + + name = (gchar *) bus_connection_get_unique_name (connection); + g_hash_table_insert (priv->unique_names, name, connection); + + reply_message = ibus_message_new_method_return (message); + ibus_message_append_args (reply_message, + G_TYPE_STRING, &name, + G_TYPE_INVALID); + + ibus_connection_send ((IBusConnection *) connection, reply_message); + ibus_message_unref (reply_message); + ibus_connection_flush ((IBusConnection *) connection); + reply_message = NULL; + + g_signal_emit (dbus, + dbus_signals[NAME_OWNER_CHANGED], + 0, + name, + "", + name); + + } + + return reply_message; +} + +static IBusMessage * +_dbus_list_names (BusDBusImpl *dbus, + IBusMessage *message, + BusConnection *connection) +{ + BusDBusImplPrivate *priv; + priv = BUS_DBUS_IMPL_GET_PRIVATE (dbus); + + IBusMessage *reply_message; + IBusMessageIter iter, sub_iter; + GList *name, *names; + + reply_message = ibus_message_new_method_return (message); + + ibus_message_iter_init_append (message, &iter); + ibus_message_iter_open_container (&iter, IBUS_TYPE_ARRAY, "s", &sub_iter); + + // append unique names + names = g_hash_table_get_keys (priv->unique_names); + + names = g_list_sort (names, (GCompareFunc) g_strcmp0); + for (name = names; name != NULL; name = name->next) { + ibus_message_iter_append (&sub_iter, G_TYPE_STRING, &(name->data)); + } + g_list_free (names); + + // append well-known names + names = g_hash_table_get_keys (priv->names); + names = g_list_sort (names, (GCompareFunc) g_strcmp0); + for (name = names; name != NULL; name = name->next) { + ibus_message_iter_append (&sub_iter, G_TYPE_STRING, &(name->data)); + } + g_list_free (names); + + ibus_message_iter_close_container (&iter, &sub_iter); + + return reply_message; +} + +static IBusMessage * +_dbus_name_has_owner (BusDBusImpl *dbus, + IBusMessage *message, + BusConnection *connection) +{ + BusDBusImplPrivate *priv; + priv = BUS_DBUS_IMPL_GET_PRIVATE (dbus); + + gchar *name; + gboolean retval; + gboolean has_owner; + IBusMessage *reply_message; + IBusError *error; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_STRING, &name, + G_TYPE_INVALID); + + if (! retval) { + reply_message = ibus_message_new_error (message, + error->name, + error->message); + ibus_error_free (error); + return reply_message; + } + + if (name[0] == ':') { + has_owner = g_hash_table_lookup (priv->unique_names, name) != NULL; + } + else { + has_owner = g_hash_table_lookup (priv->names, name) != NULL; + } + + reply_message = ibus_message_new_method_return (message); + ibus_message_append_args (reply_message, + G_TYPE_BOOLEAN, &has_owner, + G_TYPE_INVALID); + + return reply_message; +} + + +static IBusMessage * +_dbus_get_name_owner (BusDBusImpl *dbus, + IBusMessage *message, + BusConnection *connection) +{ + BusDBusImplPrivate *priv; + priv = BUS_DBUS_IMPL_GET_PRIVATE (dbus); + + gchar *name; + BusConnection *owner; + gboolean retval; + const gchar *owner_name = NULL; + IBusMessage *reply_message; + IBusError *error; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_STRING, &name, + G_TYPE_INVALID); + + if (! retval) { + reply_message = ibus_message_new_error (message, + error->name, + error->message); + ibus_error_free (error); + return reply_message; + } + + if (g_strcmp0 (name, DBUS_SERVICE_DBUS) == 0 || + g_strcmp0 (name, IBUS_SERVICE_IBUS) == 0) { + owner_name = name; + } + else { + owner = bus_dbus_impl_get_connection_by_name (dbus, name); + if (owner != NULL) { + owner_name = bus_connection_get_unique_name (owner); + } + } + + if (owner_name != NULL) { + reply_message = ibus_message_new_method_return (message); + ibus_message_append_args (reply_message, + G_TYPE_STRING, &owner_name, + G_TYPE_INVALID); + } + else { + reply_message = ibus_message_new_error_printf (message, + DBUS_ERROR_NAME_HAS_NO_OWNER, + "Name '%s' does have owner", + name); + } + + return reply_message; +} + +static IBusMessage * +_dbus_get_id (BusDBusImpl *dbus, + IBusMessage *message, + BusConnection *connection) +{ + BusDBusImplPrivate *priv; + priv = BUS_DBUS_IMPL_GET_PRIVATE (dbus); + + IBusMessage *reply_message; + const gchar *name; + + name = bus_connection_get_unique_name (connection); + + if (name == NULL) { + reply_message = ibus_message_new_error (message, + DBUS_ERROR_FAILED, + "Can not GetId before Hello"); + return reply_message; + } + + reply_message = ibus_message_new_method_return (message); + ibus_message_append_args (reply_message, + G_TYPE_STRING, &name, + G_TYPE_INVALID); + return reply_message; +} + +static void +_rule_destroy_cb (BusMatchRule *rule, + BusDBusImpl *dbus) +{ + g_assert (BUS_IS_MATCH_RULE (rule)); + g_assert (BUS_IS_DBUS_IMPL (dbus)); + + BusDBusImplPrivate *priv; + priv = BUS_DBUS_IMPL_GET_PRIVATE (dbus); + + priv->rules = g_list_remove (priv->rules, rule); + g_object_unref (rule); +} + +static IBusMessage * +_dbus_add_match (BusDBusImpl *dbus, + IBusMessage *message, + BusConnection *connection) +{ + BusDBusImplPrivate *priv; + priv = BUS_DBUS_IMPL_GET_PRIVATE (dbus); + + IBusMessage *reply_message; + IBusError *error; + gboolean retval; + gchar *rule_text; + BusMatchRule *rule; + GList *link; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_STRING, &rule_text, + G_TYPE_INVALID); + + if (!retval) { + reply_message = ibus_message_new_error (message, + error->name, + error->message); + ibus_error_free (error); + return reply_message; + } + + rule = bus_match_rule_new (rule_text); + + if (rule == NULL) { + reply_message = ibus_message_new_error_printf (message, + DBUS_ERROR_MATCH_RULE_INVALID, + "Parse rule [%s] failed", + rule_text); + return reply_message; + } + + for (link = priv->rules; link != NULL; link = link->next) { + if (bus_match_rule_is_equal (rule, BUS_MATCH_RULE (link->data))) { + bus_match_rule_add_recipient (BUS_MATCH_RULE (link->data), connection); + g_object_unref (rule); + rule = NULL; + break; + } + } + + if (rule) { + bus_match_rule_add_recipient (rule, connection); + priv->rules = g_list_append (priv->rules, rule); + g_signal_connect (rule, "destroy", G_CALLBACK (_rule_destroy_cb), dbus); + } + + reply_message = ibus_message_new_method_return (message); + return reply_message; +} + +static IBusMessage * +_dbus_remove_match (BusDBusImpl *dbus, + IBusMessage *message, + BusConnection *connection) +{ + BusDBusImplPrivate *priv; + priv = BUS_DBUS_IMPL_GET_PRIVATE (dbus); + + IBusMessage *reply_message; + IBusError *error; + gchar *rule_text; + BusMatchRule *rule; + GList *link; + + if (!ibus_message_get_args (message, + &error, + G_TYPE_STRING, &rule_text, + G_TYPE_INVALID)) { + reply_message = ibus_message_new_error (message, + error->name, + error->message); + ibus_error_free (error); + return reply_message; + } + + rule = bus_match_rule_new (rule_text); + + if (rule == NULL ) { + reply_message = ibus_message_new_error_printf (message, + DBUS_ERROR_MATCH_RULE_INVALID, + "Parse rule [%s] failed", + rule_text); + return reply_message; + } + + for (link = priv->rules; link != NULL; link = link->next) { + if (bus_match_rule_is_equal (rule, BUS_MATCH_RULE (link->data))) { + bus_match_rule_remove_recipient (BUS_MATCH_RULE (link->data), connection); + break; + } + } + + g_object_unref (rule); + + reply_message = ibus_message_new_method_return (message); + return reply_message; +} + +static IBusMessage * +_dbus_request_name (BusDBusImpl *dbus, + IBusMessage *message, + BusConnection *connection) +{ + BusDBusImplPrivate *priv; + priv = BUS_DBUS_IMPL_GET_PRIVATE (dbus); + + IBusMessage *reply_message; + IBusError *error; + gchar *name; + guint flags; + guint retval; + + if (!ibus_message_get_args (message, + &error, + G_TYPE_STRING, &name, + G_TYPE_UINT, &flags, + G_TYPE_INVALID)) { + reply_message = ibus_message_new_error (message, + error->name, + error->message); + ibus_error_free (error); + return reply_message; + } + + if (g_hash_table_lookup (priv->names, name) != NULL) { + reply_message = ibus_message_new_error_printf (message, + DBUS_ERROR_FAILED, + "Name %s has owner", + name); + return reply_message; + } + + retval = 1; + g_hash_table_insert (priv->names, + (gpointer )bus_connection_add_name (connection, name), + connection); + reply_message = ibus_message_new_method_return (message); + ibus_message_append_args (reply_message, + G_TYPE_UINT, &retval, + G_TYPE_INVALID); + + ibus_connection_send ((IBusConnection *) connection, reply_message); + ibus_message_unref (reply_message); + ibus_connection_flush ((IBusConnection *) connection); + + g_signal_emit (dbus, + dbus_signals[NAME_OWNER_CHANGED], + 0, + name, + "", + bus_connection_get_unique_name (connection)); + + return NULL; +} + +static IBusMessage * +_dbus_release_name (BusDBusImpl *dbus, + IBusMessage *message, + BusConnection *connection) +{ + BusDBusImplPrivate *priv; + priv = BUS_DBUS_IMPL_GET_PRIVATE (dbus); + + IBusMessage *reply_message; + IBusError *error; + gchar *name; + guint retval; + + if (!ibus_message_get_args (message, + &error, + G_TYPE_STRING, &name, + G_TYPE_INVALID)) { + reply_message = ibus_message_new_error (message, + error->name, + error->message); + ibus_error_free (error); + return reply_message; + } + + reply_message = ibus_message_new_method_return (message); + if (bus_connection_remove_name (connection, name)) { + retval = 1; + } + else { + retval = 2; + } + + ibus_message_append_args (message, + G_TYPE_UINT, &retval, + G_TYPE_INVALID); + + return reply_message; +} + + +static gboolean +bus_dbus_impl_ibus_message (BusDBusImpl *dbus, + BusConnection *connection, + IBusMessage *message) +{ + g_assert (BUS_IS_DBUS_IMPL (dbus)); + g_assert (BUS_IS_CONNECTION (connection)); + g_assert (message != NULL); + + gint i; + IBusMessage *reply_message = NULL; + + static const struct { + const gchar *interface; + const gchar *name; + IBusMessage *(* handler) (BusDBusImpl *, IBusMessage *, BusConnection *); + } handlers[] = { + /* Introspectable interface */ + { DBUS_INTERFACE_INTROSPECTABLE, + "Introspect", _dbus_introspect }, + /* DBus interface */ + { DBUS_INTERFACE_DBUS, "Hello", _dbus_hello }, + { DBUS_INTERFACE_DBUS, "ListNames", _dbus_list_names }, + { DBUS_INTERFACE_DBUS, "ListActivatableNames", + _dbus_no_implement }, + { DBUS_INTERFACE_DBUS, "NameHasOwner", + _dbus_name_has_owner }, + { DBUS_INTERFACE_DBUS, "StartServiceByName", + _dbus_no_implement }, + { DBUS_INTERFACE_DBUS, "GetNameOwner", + _dbus_get_name_owner }, + { DBUS_INTERFACE_DBUS, "GetConnectionUnixUser", + _dbus_no_implement }, + { DBUS_INTERFACE_DBUS, "AddMatch", _dbus_add_match }, + { DBUS_INTERFACE_DBUS, "RemoveMatch", + _dbus_remove_match }, + { DBUS_INTERFACE_DBUS, "GetId", _dbus_get_id }, + { DBUS_INTERFACE_DBUS, "RequestName", _dbus_request_name }, + { DBUS_INTERFACE_DBUS, "ReleaseName", _dbus_release_name }, + { NULL, NULL, NULL } + }; + + ibus_message_set_destination (message, DBUS_SERVICE_DBUS); + + for (i = 0; handlers[i].interface != NULL; i++) { + if (ibus_message_is_method_call (message, + handlers[i].interface, + handlers[i].name)) { + + reply_message = handlers[i].handler (dbus, message, connection); + if (reply_message) { + + ibus_message_set_sender (reply_message, DBUS_SERVICE_DBUS); + ibus_message_set_destination (reply_message, + bus_connection_get_unique_name (connection)); + ibus_message_set_no_reply (reply_message, TRUE); + + ibus_connection_send (IBUS_CONNECTION (connection), reply_message); + ibus_message_unref (reply_message); + } + + g_signal_stop_emission_by_name (dbus, "ibus-message"); + return TRUE; + } + } + + return parent_class->ibus_message ((IBusService *) dbus, + (IBusConnection *) connection, + message); +} + +static void +bus_dbus_impl_name_owner_changed (BusDBusImpl *dbus, + gchar *name, + gchar *old_name, + gchar *new_name) +{ + g_assert (BUS_IS_DBUS_IMPL (dbus)); + g_assert (name != NULL); + g_assert (old_name != NULL); + g_assert (new_name != NULL); + + IBusMessage *message; + + message = ibus_message_new_signal (DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "NameOwnerChanged"); + ibus_message_append_args (message, + G_TYPE_STRING, &name, + G_TYPE_STRING, &old_name, + G_TYPE_STRING, &new_name, + G_TYPE_INVALID); + ibus_message_set_sender (message, DBUS_SERVICE_DBUS); + + bus_dbus_impl_dispatch_message_by_rule (dbus, message, NULL); + + ibus_message_unref (message); + +} + +static gboolean +_connection_ibus_message_cb (BusConnection *connection, + IBusMessage *message, + BusDBusImpl *dbus) +{ + g_assert (BUS_IS_CONNECTION (connection)); + g_assert (message != NULL); + g_assert (BUS_IS_DBUS_IMPL (dbus)); + + const gchar *dest; + + if (ibus_message_is_signal (message, + DBUS_INTERFACE_LOCAL, + "Disconnected")) { + /* ignore signal from local interface */ + return FALSE; + } + + ibus_message_set_sender (message, bus_connection_get_unique_name (connection)); + + switch (ibus_message_get_type (message)) { + case DBUS_MESSAGE_TYPE_ERROR: + g_debug ("From :%s to %s, Error: %s : %s", + ibus_message_get_sender (message), + ibus_message_get_destination (message), + ibus_message_get_error_name (message), + ibus_message_get_error_message (message)); + break; +#if 0 + case DBUS_MESSAGE_TYPE_METHOD_CALL: + g_debug("From %s to %s, Method %s on %s", + ibus_message_get_sender (message), + ibus_message_get_destination (message), + ibus_message_get_path (message), + ibus_message_get_member (message)); + break; +#endif + } + + dest = ibus_message_get_destination (message); + + if (dest == NULL || + strcmp ((gchar *)dest, IBUS_SERVICE_IBUS) == 0 || + strcmp ((gchar *)dest, DBUS_SERVICE_DBUS) == 0) { + /* this message is sent to ibus-daemon */ + + switch (ibus_message_get_type (message)) { + case DBUS_MESSAGE_TYPE_SIGNAL: + case DBUS_MESSAGE_TYPE_METHOD_RETURN: + case DBUS_MESSAGE_TYPE_ERROR: + bus_dbus_impl_dispatch_message_by_rule (dbus, message, NULL); + return FALSE; + case DBUS_MESSAGE_TYPE_METHOD_CALL: + { + const gchar *path; + IBusService *object; + + BusDBusImplPrivate *priv; + priv = BUS_DBUS_IMPL_GET_PRIVATE (dbus); + + path = ibus_message_get_path (message); + + object = g_hash_table_lookup (priv->objects, path); + + if (object == NULL || + ibus_service_handle_message (object, + (IBusConnection *) connection, + message) == FALSE) { + IBusMessage *error; + error = ibus_message_new_error_printf (message, + DBUS_ERROR_UNKNOWN_METHOD, + "Unknown method %s on %s", + ibus_message_get_member (message), + path); + ibus_connection_send ((IBusConnection *) connection, error); + ibus_message_unref (error); + } + + /* dispatch message */ + bus_dbus_impl_dispatch_message_by_rule (dbus, message, NULL); + } + break; + default: + g_assert (FALSE); + } + } + else { + /* If the destination is not IBus or DBus, the message will be forwanded. */ + bus_dbus_impl_dispatch_message (dbus, message); + } + + g_signal_stop_emission_by_name (connection, "ibus-message"); + return TRUE; +} + +static void +_connection_ibus_message_sent_cb (BusConnection *connection, + IBusMessage *message, + BusDBusImpl *dbus) +{ + g_assert (BUS_IS_CONNECTION (connection)); + g_assert (message != NULL); + g_assert (BUS_IS_DBUS_IMPL (dbus)); + + bus_dbus_impl_dispatch_message_by_rule (dbus, message, connection); +} + +static void +_connection_destroy_cb (BusConnection *connection, + BusDBusImpl *dbus) +{ + g_assert (BUS_IS_CONNECTION (connection)); + g_assert (BUS_IS_DBUS_IMPL (dbus)); + + BusDBusImplPrivate *priv; + priv = BUS_DBUS_IMPL_GET_PRIVATE (dbus); + + /* + ibus_service_remove_from_connection ( + IBUS_SERVICE (dbus), + IBUS_CONNECTION (connection)); + */ + + const gchar *unique_name = bus_connection_get_unique_name (connection); + if (unique_name != NULL) { + g_hash_table_remove (priv->unique_names, unique_name); + g_signal_emit (dbus, + dbus_signals[NAME_OWNER_CHANGED], + 0, + unique_name, + unique_name, + ""); + } + + const GList *name = bus_connection_get_names (connection); + + while (name != NULL) { + g_hash_table_remove (priv->names, name->data); + g_signal_emit (dbus, + dbus_signals[NAME_OWNER_CHANGED], + 0, + name->data, + unique_name, + ""); + name = name->next; + } + + priv->connections = g_list_remove (priv->connections, connection); + g_object_unref (connection); +} + + +gboolean +bus_dbus_impl_new_connection (BusDBusImpl *dbus, + BusConnection *connection) +{ + g_assert (BUS_IS_DBUS_IMPL (dbus)); + g_assert (BUS_IS_CONNECTION (connection)); + + BusDBusImplPrivate *priv; + priv = BUS_DBUS_IMPL_GET_PRIVATE (dbus); + + g_assert (g_list_find (priv->connections, connection) == NULL); + + g_object_ref (connection); + priv->connections = g_list_append (priv->connections, connection); + + g_signal_connect (connection, + "ibus-message", + G_CALLBACK (_connection_ibus_message_cb), + dbus); + + g_signal_connect (connection, + "ibus-message-sent", + G_CALLBACK (_connection_ibus_message_sent_cb), + dbus); + + + g_signal_connect (connection, + "destroy", + G_CALLBACK (_connection_destroy_cb), + dbus); + return TRUE; +} + + +BusConnection * +bus_dbus_impl_get_connection_by_name (BusDBusImpl *dbus, + const gchar *name) +{ + g_assert (BUS_IS_DBUS_IMPL (dbus)); + g_assert (name != NULL); + + BusConnection *connection = NULL; + + BusDBusImplPrivate *priv; + priv = BUS_DBUS_IMPL_GET_PRIVATE (dbus); + + if (name[0] == ':') { + connection = BUS_CONNECTION (g_hash_table_lookup ( + priv->unique_names, + name)); + } + else { + connection = BUS_CONNECTION (g_hash_table_lookup ( + priv->names, + name)); + } + + return connection; +} + + +void +bus_dbus_impl_dispatch_message (BusDBusImpl *dbus, + IBusMessage *message) +{ + g_assert (BUS_IS_DBUS_IMPL (dbus)); + g_assert (message != NULL); + + const gchar *destination; + BusConnection *dest_connection = NULL; + + destination = ibus_message_get_destination (message); + + if (destination != NULL) { + dest_connection = bus_dbus_impl_get_connection_by_name (dbus, destination); + + if (dest_connection != NULL) { + ibus_connection_send (IBUS_CONNECTION (dest_connection), message); + } + else { + IBusMessage *reply_message; + reply_message = ibus_message_new_error_printf (message, + DBUS_ERROR_SERVICE_UNKNOWN, + "Can not find service %s", + destination); + bus_dbus_impl_dispatch_message (dbus, reply_message); + ibus_message_unref (reply_message); + } + } + + bus_dbus_impl_dispatch_message_by_rule (dbus, message, dest_connection); +} + +void +bus_dbus_impl_dispatch_message_by_rule (BusDBusImpl *dbus, + IBusMessage *message, + BusConnection *skip_connection) +{ + g_assert (BUS_IS_DBUS_IMPL (dbus)); + g_assert (message != NULL); + g_assert (BUS_IS_CONNECTION (skip_connection) || skip_connection == NULL); + + GList *recipients = NULL; + GList *link = NULL; + + static gint32 data_slot = -1; + + BusDBusImplPrivate *priv; + priv = BUS_DBUS_IMPL_GET_PRIVATE (dbus); + + if (data_slot == -1) { + dbus_message_allocate_data_slot (&data_slot); + } + + /* If this message has been dispatched by rule, it will be ignored. */ + if (dbus_message_get_data (message, data_slot) != NULL) + return; + + dbus_message_set_data (message, data_slot, (gpointer) TRUE, NULL); + +#if 0 + if (g_strcmp0 (ibus_message_get_member (message), "ValueChanged") == 0) { + g_debug ("Dispatch ValueChanged"); + } +#endif + + for (link = priv->rules; link != NULL; link = link->next) { + if (bus_match_rule_get_recipients (BUS_MATCH_RULE (link->data), + message, + &recipients)) { + break; + } + } + + for (link = recipients; link != NULL; link = link->next) { + BusConnection *connection = BUS_CONNECTION (link->data); + if (connection != skip_connection) { + ibus_connection_send (IBUS_CONNECTION (connection), message); + } + g_object_unref (link->data); + } + g_list_free (recipients); +} + + +static void +_object_destroy_cb (IBusService *object, + BusDBusImpl *dbus) +{ + gboolean retval; + + retval = bus_dbus_impl_unregister_object (dbus, object); + + g_assert (retval); +} + +gboolean +bus_dbus_impl_register_object (BusDBusImpl *dbus, + IBusService *object) +{ + g_assert (BUS_IS_DBUS_IMPL (dbus)); + g_assert (IBUS_IS_SERVICE (object)); + + const gchar *path; + BusDBusImplPrivate *priv; + priv = BUS_DBUS_IMPL_GET_PRIVATE (dbus); + + path = ibus_service_get_path (object); + + g_return_val_if_fail (path, FALSE); + + g_return_val_if_fail (g_hash_table_lookup (priv->objects, path) == NULL, FALSE); + + g_object_ref (object); + g_hash_table_insert (priv->objects, (gpointer)path, object); + + g_signal_connect (object, "destroy", G_CALLBACK (_object_destroy_cb), dbus); + + return TRUE; +} + +gboolean +bus_dbus_impl_unregister_object (BusDBusImpl *dbus, + IBusService *object) +{ + g_assert (BUS_IS_DBUS_IMPL (dbus)); + g_assert (IBUS_IS_SERVICE (object)); + + const gchar *path; + BusDBusImplPrivate *priv; + priv = BUS_DBUS_IMPL_GET_PRIVATE (dbus); + + path = ibus_service_get_path (object); + g_return_val_if_fail (path, FALSE); + + g_return_val_if_fail (g_hash_table_lookup (priv->objects, path) == object, FALSE); + + g_signal_handlers_disconnect_by_func (object, G_CALLBACK (_object_destroy_cb), dbus); + + g_hash_table_remove (priv->objects, path); + g_object_unref (object); + + return TRUE; +} + diff --git a/bus/dbusimpl.h b/bus/dbusimpl.h new file mode 100644 index 0000000..d04326e --- /dev/null +++ b/bus/dbusimpl.h @@ -0,0 +1,87 @@ +/* vim:set et sts=4: */ +/* bus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __DBUS_IMPL_H_ +#define __DBUS_IMPL_H_ + +#include <ibus.h> +#include "connection.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define BUS_TYPE_DBUS_IMPL \ + (bus_dbus_impl_get_type ()) +#define BUS_DBUS_IMPL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUS_TYPE_DBUS_IMPL, BusDBusImpl)) +#define BUS_DBUS_IMPL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), BUS_TYPE_DBUS_IMPL, BusDBusImplClass)) +#define BUS_IS_DBUS_IMPL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUS_TYPE_DBUS_IMPL)) +#define BUS_IS_DBUS_IMPL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), BUS_TYPE_DBUS_IMPL)) +#define BUS_DBUS_IMPL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), BUS_TYPE_DBUS_IMPL, BusDBusImplClass)) + +#define BUS_DEFAULT_DBUS \ + (bus_dbus_impl_get_default ()) + +G_BEGIN_DECLS + +typedef struct _BusDBusImpl BusDBusImpl; +typedef struct _BusDBusImplClass BusDBusImplClass; + +struct _BusDBusImpl { + IBusService parent; + /* instance members */ +}; + +struct _BusDBusImplClass { + IBusServiceClass parent; + + /* class members */ + void (* name_owner_changed) (BusDBusImpl *dbus, + gchar *name, + gchar *old_name, + gchar *new_name); +}; + +GType bus_dbus_impl_get_type (void); +BusDBusImpl *bus_dbus_impl_get_default (void); +gboolean bus_dbus_impl_new_connection (BusDBusImpl *dbus, + BusConnection *connection); +BusConnection *bus_dbus_impl_get_connection_by_name + (BusDBusImpl *dbus, + const gchar *name); +void bus_dbus_impl_dispatch_message (BusDBusImpl *dbus, + DBusMessage *message); +void bus_dbus_impl_dispatch_message_by_rule + (BusDBusImpl *dbus, + DBusMessage *message, + BusConnection *skip_connection); +gboolean bus_dbus_impl_register_object (BusDBusImpl *dbus, + IBusService *object); +gboolean bus_dbus_impl_unregister_object(BusDBusImpl *dbus, + IBusService *object); + +G_END_DECLS +#endif + diff --git a/bus/engineproxy.c b/bus/engineproxy.c new file mode 100644 index 0000000..963dfe2 --- /dev/null +++ b/bus/engineproxy.c @@ -0,0 +1,716 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <ibusinternal.h> +#include <ibusmarshalers.h> +#include "engineproxy.h" + +#define BUS_ENGINE_PROXY_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), BUS_TYPE_ENGINE_PROXY, BusEngineProxyPrivate)) + +enum { + COMMIT_TEXT, + FORWARD_KEY_EVENT, + UPDATE_PREEDIT_TEXT, + SHOW_PREEDIT_TEXT, + HIDE_PREEDIT_TEXT, + UPDATE_AUXILIARY_TEXT, + SHOW_AUXILIARY_TEXT, + HIDE_AUXILIARY_TEXT, + UPDATE_LOOKUP_TABLE, + SHOW_LOOKUP_TABLE, + HIDE_LOOKUP_TABLE, + PAGE_UP_LOOKUP_TABLE, + PAGE_DOWN_LOOKUP_TABLE, + CURSOR_UP_LOOKUP_TABLE, + CURSOR_DOWN_LOOKUP_TABLE, + REGISTER_PROPERTIES, + UPDATE_PROPERTY, + LAST_SIGNAL, +}; + + +/* BusEngineProxyPriv */ +struct _BusEngineProxyPrivate { + gboolean enabled; + IBusEngineDesc *desc; + + IBusPropList *prop_list; +}; +typedef struct _BusEngineProxyPrivate BusEngineProxyPrivate; + +static guint engine_signals[LAST_SIGNAL] = { 0 }; +// static guint engine_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void bus_engine_proxy_class_init (BusEngineProxyClass *klass); +static void bus_engine_proxy_init (BusEngineProxy *engine); +static void bus_engine_proxy_real_destroy (BusEngineProxy *engine); + +static gboolean bus_engine_proxy_ibus_signal (IBusProxy *proxy, + IBusMessage *message); + +static IBusProxyClass *parent_class = NULL; + +GType +bus_engine_proxy_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (BusEngineProxyClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) bus_engine_proxy_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (BusEngineProxy), + 0, + (GInstanceInitFunc) bus_engine_proxy_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_PROXY, + "BusEngineProxy", + &type_info, + (GTypeFlags)0); + } + return type; +} + +BusEngineProxy * +bus_engine_proxy_new (const gchar *path, + IBusEngineDesc *desc, + BusConnection *connection) +{ + g_assert (path); + g_assert (IBUS_IS_ENGINE_DESC (desc)); + g_assert (BUS_IS_CONNECTION (connection)); + + BusEngineProxy *engine; + + engine = (BusEngineProxy *) g_object_new (BUS_TYPE_ENGINE_PROXY, + "name", NULL, + "path", path, + "connection", connection, + NULL); + + BusEngineProxyPrivate *priv; + priv = BUS_ENGINE_PROXY_GET_PRIVATE (engine); + priv->desc = desc; + g_object_ref (desc); + + return engine; +} + +static void +bus_engine_proxy_class_init (BusEngineProxyClass *klass) +{ + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + IBusProxyClass *proxy_class = IBUS_PROXY_CLASS (klass); + + + parent_class = (IBusProxyClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (BusEngineProxyPrivate)); + + ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_engine_proxy_real_destroy; + + proxy_class->ibus_signal = bus_engine_proxy_ibus_signal; + + /* install signals */ + engine_signals[COMMIT_TEXT] = + g_signal_new (I_("commit-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + IBUS_TYPE_TEXT); + + engine_signals[FORWARD_KEY_EVENT] = + g_signal_new (I_("forward-key-event"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__UINT_UINT, + G_TYPE_NONE, + 2, + G_TYPE_UINT, + G_TYPE_UINT); + + engine_signals[UPDATE_PREEDIT_TEXT] = + g_signal_new (I_("update-preedit-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT_UINT_BOOLEAN, + G_TYPE_NONE, + 3, + IBUS_TYPE_TEXT, + G_TYPE_UINT, + G_TYPE_BOOLEAN); + + engine_signals[SHOW_PREEDIT_TEXT] = + g_signal_new (I_("show-preedit-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + engine_signals[HIDE_PREEDIT_TEXT] = + g_signal_new (I_("hide-preedit-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + engine_signals[UPDATE_AUXILIARY_TEXT] = + g_signal_new (I_("update-auxiliary-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT_BOOLEAN, + G_TYPE_NONE, + 2, + IBUS_TYPE_TEXT, + G_TYPE_BOOLEAN); + + engine_signals[SHOW_AUXILIARY_TEXT] = + g_signal_new (I_("show-auxiliary-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + engine_signals[HIDE_AUXILIARY_TEXT] = + g_signal_new (I_("hide-auxiliary-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + engine_signals[UPDATE_LOOKUP_TABLE] = + g_signal_new (I_("update-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__BOXED_BOOLEAN, + G_TYPE_NONE, + 2, + IBUS_TYPE_LOOKUP_TABLE, + G_TYPE_BOOLEAN); + + engine_signals[SHOW_LOOKUP_TABLE] = + g_signal_new (I_("show-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + engine_signals[HIDE_LOOKUP_TABLE] = + g_signal_new (I_("hide-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + engine_signals[PAGE_UP_LOOKUP_TABLE] = + g_signal_new (I_("page-up-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + engine_signals[PAGE_DOWN_LOOKUP_TABLE] = + g_signal_new (I_("page-down-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + engine_signals[CURSOR_UP_LOOKUP_TABLE] = + g_signal_new (I_("cursor-up-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + engine_signals[CURSOR_DOWN_LOOKUP_TABLE] = + g_signal_new (I_("cursor-down-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + engine_signals[REGISTER_PROPERTIES] = + g_signal_new (I_("register-properties"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + IBUS_TYPE_PROP_LIST); + + engine_signals[UPDATE_PROPERTY] = + g_signal_new (I_("update-property"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + IBUS_TYPE_PROPERTY); + +} + +static void +bus_engine_proxy_init (BusEngineProxy *engine) +{ + BusEngineProxyPrivate *priv; + priv = BUS_ENGINE_PROXY_GET_PRIVATE (engine); + + priv->enabled = FALSE; + priv->prop_list = NULL; + priv->desc = NULL; +} + +static void +bus_engine_proxy_real_destroy (BusEngineProxy *engine) +{ + BusEngineProxyPrivate *priv; + priv = BUS_ENGINE_PROXY_GET_PRIVATE (engine); + + if (priv->prop_list) { + g_object_unref (priv->prop_list); + priv->prop_list = NULL; + } + + if (ibus_proxy_get_connection ((IBusProxy *) engine)) { + ibus_proxy_call ((IBusProxy *) engine, + "Destroy", + DBUS_TYPE_INVALID); + } + + if (priv->desc) { + g_object_unref (priv->desc); + priv->desc = NULL; + } + + IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (engine)); +} + +static gboolean +bus_engine_proxy_ibus_signal (IBusProxy *proxy, + IBusMessage *message) +{ + g_assert (BUS_IS_ENGINE_PROXY (proxy)); + g_assert (message != NULL); + + BusEngineProxy *engine; + BusEngineProxyPrivate *priv; + IBusError *error; + gint i; + + static const struct { + const gchar *member; + const guint signal_id; + } signals [] = { + { "ShowPreeditText", SHOW_PREEDIT_TEXT }, + { "HidePreeditText", HIDE_PREEDIT_TEXT }, + { "ShowAuxiliaryText", SHOW_AUXILIARY_TEXT }, + { "HideAuxiliaryText", HIDE_AUXILIARY_TEXT }, + { "ShowLookupTable", SHOW_LOOKUP_TABLE }, + { "HideLookupTable", HIDE_LOOKUP_TABLE }, + { "PageUpLookupTable", PAGE_UP_LOOKUP_TABLE }, + { "PageDownLookupTable", PAGE_DOWN_LOOKUP_TABLE }, + { "CursorUpLookupTable", CURSOR_UP_LOOKUP_TABLE }, + { "CursorDownLookupTable", CURSOR_DOWN_LOOKUP_TABLE }, + { NULL, 0}, + }; + + engine = BUS_ENGINE_PROXY (proxy); + priv = BUS_ENGINE_PROXY_GET_PRIVATE (engine); + + for (i = 0; ; i++) { + if (signals[i].member == NULL) + break; + if (ibus_message_is_signal (message, IBUS_INTERFACE_ENGINE, signals[i].member)) { + g_signal_emit (engine, engine_signals[signals[i].signal_id], 0); + goto handled; + } + } + + if (ibus_message_is_signal (message, IBUS_INTERFACE_ENGINE, "CommitText")) { + IBusText *text; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_TEXT, &text, + G_TYPE_INVALID); + if (!retval) + goto failed; + g_signal_emit (engine, engine_signals[COMMIT_TEXT], 0, text); + g_object_unref (text); + } + else if (ibus_message_is_signal (message, IBUS_INTERFACE_ENGINE, "ForwardKeyEvent")) { + guint keyval; + guint states; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_UINT, &keyval, + G_TYPE_UINT, &states, + G_TYPE_INVALID); + + if (!retval) + goto failed; + g_signal_emit (engine, engine_signals[FORWARD_KEY_EVENT], keyval, states); + } + else if (ibus_message_is_signal (message, IBUS_INTERFACE_ENGINE, "UpdatePreeditText")) { + IBusText *text; + gint cursor_pos; + gboolean visible; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_TEXT, &text, + G_TYPE_UINT, &cursor_pos, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); + + if (!retval) + goto failed; + + g_signal_emit (engine, engine_signals[UPDATE_PREEDIT_TEXT], 0, + text, cursor_pos, visible); + g_object_unref (text); + } + else if (ibus_message_is_signal (message, IBUS_INTERFACE_ENGINE, "UpdateAuxiliaryText")) { + IBusText *text; + gboolean visible; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_TEXT, &text, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); + + if (!retval) + goto failed; + + g_signal_emit (engine, engine_signals[UPDATE_AUXILIARY_TEXT], 0, text, visible); + g_object_unref (text); + } + else if (ibus_message_is_signal (message, IBUS_INTERFACE_ENGINE, "UpdateLookupTable")) { + IBusLookupTable *table; + gboolean visible; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_LOOKUP_TABLE, &table, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); + + if (!retval) + goto failed; + + g_signal_emit (engine, engine_signals[UPDATE_LOOKUP_TABLE], 0, table, visible); + g_object_unref (table); + } + else if (ibus_message_is_signal (message, IBUS_INTERFACE_ENGINE, "RegisterProperties")) { + gboolean retval; + + if (priv->prop_list) { + g_object_unref (priv->prop_list); + priv->prop_list = NULL; + } + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_PROP_LIST, &priv->prop_list, + G_TYPE_INVALID); + if (!retval) { + priv->prop_list = NULL; + goto failed; + } + g_signal_emit (engine, engine_signals[REGISTER_PROPERTIES], 0, priv->prop_list); + } + else if (ibus_message_is_signal (message, IBUS_INTERFACE_ENGINE, "UpdateProperty")) { + IBusProperty *prop; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_PROPERTY, &prop, + G_TYPE_INVALID); + + if (!retval) + goto failed; + + g_signal_emit (engine, engine_signals[UPDATE_PROPERTY], 0, prop); + g_object_unref (prop); + } + else { + return FALSE; + } + +handled: + g_signal_stop_emission_by_name (engine, "ibus-signal"); + return TRUE; + +failed: + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + return FALSE; +} + +typedef struct { + GFunc func; + gpointer user_data; +}CallData; + +static void +bus_engine_proxy_process_key_event_reply_cb (IBusPendingCall *pending, + CallData *call_data) +{ + IBusMessage *reply_message; + IBusError *error; + gboolean retval; + + reply_message = dbus_pending_call_steal_reply (pending); + + if ((error = ibus_error_new_from_message (reply_message)) != NULL) { + g_warning ("%s: %s", error->name, error->message); + ibus_message_unref (reply_message); + ibus_error_free (error); + call_data->func(FALSE, call_data->user_data); + return; + } + + if (!ibus_message_get_args (reply_message, + &error, + G_TYPE_BOOLEAN, &retval, + G_TYPE_INVALID)) { + g_warning ("%s: %s", error->name, error->message); + ibus_message_unref (reply_message); + ibus_error_free (error); + call_data->func(FALSE, call_data->user_data); + return; + } + + call_data->func((gpointer *)retval, call_data->user_data); + g_slice_free (CallData, call_data); +} + +void +bus_engine_proxy_process_key_event (BusEngineProxy *engine, + guint keyval, + guint state, + GFunc return_cb, + gpointer user_data) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + g_assert (return_cb); + + IBusPendingCall *pending = NULL; + CallData *call_data; + IBusError *error; + gboolean retval; + + retval = ibus_proxy_call_with_reply ((IBusProxy *) engine, + "ProcessKeyEvent", + &pending, + -1, + &error, + G_TYPE_UINT, &keyval, + G_TYPE_UINT, &state, + G_TYPE_INVALID); + if (!retval) { + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + return_cb (FALSE, user_data); + return; + } + + call_data = g_slice_new0 (CallData); + call_data->func = return_cb; + call_data->user_data = user_data; + + retval = ibus_pending_call_set_notify (pending, + (IBusPendingCallNotifyFunction) bus_engine_proxy_process_key_event_reply_cb, + call_data, + NULL); + ibus_pending_call_unref (pending); + + if (!retval) { + g_warning ("%s : ProcessKeyEvent", DBUS_ERROR_NO_MEMORY); + return_cb (FALSE, user_data); + return; + } +} + +void +bus_engine_proxy_set_cursor_location (BusEngineProxy *engine, + gint x, + gint y, + gint w, + gint h) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + + ibus_proxy_call ((IBusProxy *) engine, + "SetCursorLocation", + G_TYPE_INT, &x, + G_TYPE_INT, &y, + G_TYPE_INT, &w, + G_TYPE_INT, &h, + G_TYPE_INVALID); +} + +void +bus_engine_proxy_set_capabilities (BusEngineProxy *engine, + guint caps) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + + ibus_proxy_call ((IBusProxy *) engine, + "SetCapabilites", + G_TYPE_UINT, &caps, + G_TYPE_INVALID); + +} + +void +bus_engine_proxy_property_activate (BusEngineProxy *engine, + const gchar *prop_name, + guint prop_state) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + g_assert (prop_name != NULL); + + ibus_proxy_call ((IBusProxy *) engine, + "PropertyActivate", + G_TYPE_STRING, &prop_name, + G_TYPE_UINT, &prop_state, + G_TYPE_INVALID); +} + +void +bus_engine_proxy_property_show (BusEngineProxy *engine, + const gchar *prop_name) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + g_assert (prop_name != NULL); + + ibus_proxy_call ((IBusProxy *) engine, + "PropertyShow", + G_TYPE_STRING, &prop_name, + G_TYPE_INVALID); +} + +void bus_engine_proxy_property_hide (BusEngineProxy *engine, + const gchar *prop_name) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + g_assert (prop_name != NULL); + + ibus_proxy_call ((IBusProxy *) engine, + "PropertyHide", + G_TYPE_STRING, &prop_name, + G_TYPE_INVALID); +} + +#define DEFINE_FUNCTION(Name, name) \ + void bus_engine_proxy_##name (BusEngineProxy *engine) \ + { \ + g_assert (BUS_IS_ENGINE_PROXY (engine)); \ + ibus_proxy_call ((IBusProxy *) engine, \ + #Name, \ + DBUS_TYPE_INVALID); \ + } + +DEFINE_FUNCTION (FocusIn, focus_in) +DEFINE_FUNCTION (FocusOut, focus_out) +DEFINE_FUNCTION (Reset, reset) +DEFINE_FUNCTION (PageUp, page_up) +DEFINE_FUNCTION (PageDown, page_down) +DEFINE_FUNCTION (CursorUp, cursor_up) +DEFINE_FUNCTION (CursorDown, cursor_down) +DEFINE_FUNCTION (Enable, enable) +DEFINE_FUNCTION (Disable, disable) + +#undef DEFINE_FUNCTION + + +IBusEngineDesc * +bus_engine_proxy_get_desc (BusEngineProxy *engine) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + + BusEngineProxyPrivate *priv; + priv = BUS_ENGINE_PROXY_GET_PRIVATE (engine); + + return priv->desc; +} diff --git a/bus/engineproxy.h b/bus/engineproxy.h new file mode 100644 index 0000000..2206c9a --- /dev/null +++ b/bus/engineproxy.h @@ -0,0 +1,95 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __ENGINE_PROXY_H_ +#define __ENGINE_PROXY_H_ + +#include <ibus.h> +#include "connection.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define BUS_TYPE_ENGINE_PROXY \ + (bus_engine_proxy_get_type ()) +#define BUS_ENGINE_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUS_TYPE_ENGINE_PROXY, BusEngineProxy)) +#define BUS_ENGINE_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), BUS_TYPE_ENGINE_PROXY, BusEngineProxyClass)) +#define BUS_IS_ENGINE_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUS_TYPE_ENGINE_PROXY)) +#define BUS_IS_ENGINE_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), BUS_TYPE_ENGINE_PROXY)) +#define BUS_ENGINE_PROXY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), BUS_TYPE_ENGINE_PROXY, BusEngineProxyClass)) + +G_BEGIN_DECLS + +typedef struct _BusEngineProxy BusEngineProxy; +typedef struct _BusEngineProxyClass BusEngineProxyClass; + +struct _BusEngineProxy { + IBusProxy parent; + /* instance members */ +}; + +struct _BusEngineProxyClass { + IBusProxyClass parent; + /* class members */ +}; + +GType bus_engine_proxy_get_type (void); +BusEngineProxy *bus_engine_proxy_new (const gchar *path, + IBusEngineDesc *desc, + BusConnection *connection); +IBusEngineDesc *bus_engine_proxy_get_desc (BusEngineProxy *engine); +void bus_engine_proxy_process_key_event (BusEngineProxy *engine, + guint keyval, + guint state, + GFunc return_cn, + gpointer user_data); +void bus_engine_proxy_set_cursor_location + (BusEngineProxy *engine, + gint x, + gint y, + gint w, + gint h); +void bus_engine_proxy_focus_in (BusEngineProxy *engine); +void bus_engine_proxy_focus_out (BusEngineProxy *engine); +void bus_engine_proxy_reset (BusEngineProxy *engine); +void bus_engine_proxy_set_capabilities (BusEngineProxy *engine, + guint caps); +void bus_engine_proxy_page_up (BusEngineProxy *engine); +void bus_engine_proxy_page_down (BusEngineProxy *engine); +void bus_engine_proxy_cursor_up (BusEngineProxy *engine); +void bus_engine_proxy_cursor_down (BusEngineProxy *engine); +void bus_engine_proxy_enable (BusEngineProxy *engine); +void bus_engine_proxy_disable (BusEngineProxy *engine); +void bus_engine_proxy_property_activate (BusEngineProxy *engine, + const gchar *prop_name, + guint state); +void bus_engine_proxy_property_show (BusEngineProxy *engine, + const gchar *prop_name); +void bus_engine_proxy_property_hide (BusEngineProxy *engine, + const gchar *prop_name); +G_END_DECLS +#endif + diff --git a/bus/factoryproxy.c b/bus/factoryproxy.c new file mode 100644 index 0000000..38357b4 --- /dev/null +++ b/bus/factoryproxy.c @@ -0,0 +1,220 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <ibusinternal.h> +#include <ibusmarshalers.h> +#include "dbusimpl.h" +#include "factoryproxy.h" + +/* functions prototype */ +static void bus_factory_proxy_class_init (BusFactoryProxyClass *klass); +static void bus_factory_proxy_init (BusFactoryProxy *factory); +static void bus_factory_proxy_destroy (BusFactoryProxy *factory); + + +static IBusProxyClass *parent_class = NULL; + +GType +bus_factory_proxy_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (BusFactoryProxyClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) bus_factory_proxy_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (BusFactoryProxy), + 0, + (GInstanceInitFunc) bus_factory_proxy_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_PROXY, + "BusFactoryProxy", + &type_info, + (GTypeFlags)0); + } + return type; +} + +BusFactoryProxy * +bus_factory_proxy_new (IBusComponent *component, + BusConnection *connection) +{ + g_assert (IBUS_IS_COMPONENT (component)); + + BusFactoryProxy *factory; + GList *p; + + if (connection == NULL) { + connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, component->name); + } + + if (connection == NULL) { + return NULL; + } + + factory = g_object_new (BUS_TYPE_FACTORY_PROXY, + "name", NULL, + "path", "/org/freedesktop/IBus/Factory", + "connection", connection, + NULL); + + g_object_ref (component); + factory->component = component; + g_object_set_data ((GObject *)factory->component, "factory", factory); + + factory->engine_list = ibus_component_get_engines (factory->component); + + for (p = factory->engine_list; p != NULL; p = p->next) { + IBusEngineDesc *desc = (IBusEngineDesc *)p->data; + g_object_ref (desc); + g_object_set_data ((GObject *)desc, "factory", factory); + } + + return factory; +} + +static void +bus_factory_proxy_class_init (BusFactoryProxyClass *klass) +{ + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + + parent_class = (IBusProxyClass *) g_type_class_peek_parent (klass); + + ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_factory_proxy_destroy; + +} + +static void +bus_factory_proxy_init (BusFactoryProxy *factory) +{ + factory->component = NULL; +} + +static void +bus_factory_proxy_destroy (BusFactoryProxy *factory) +{ + GList *p; + + for (p = factory->engine_list; p != NULL ; p = p->next) { + IBusEngineDesc *desc = (IBusEngineDesc *)p->data; + g_object_steal_data ((GObject *)desc, "factory"); + g_object_unref (desc); + } + g_list_free (factory->engine_list); + factory->engine_list = NULL; + + if (factory->component) { + g_object_steal_data ((GObject *)factory->component, "factory"); + g_object_unref (factory->component); + factory->component = NULL; + } + + IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (factory)); +} + +IBusComponent * +bus_factory_proxy_get_component (BusFactoryProxy *factory) +{ + return factory->component; +} + +BusFactoryProxy * +bus_factory_proxy_get_from_component (IBusComponent *component) +{ + IBUS_IS_COMPONENT (component); + + BusFactoryProxy *factory; + + factory = (BusFactoryProxy *) g_object_get_data ((GObject *)component, "factory"); + + return factory; +} + +BusFactoryProxy * +bus_factory_proxy_get_from_engine (IBusEngineDesc *desc) +{ + + IBUS_IS_ENGINE_DESC (desc); + + BusFactoryProxy *factory; + + factory = (BusFactoryProxy *) g_object_get_data ((GObject *)desc, "factory"); + + return factory; +} + +BusEngineProxy * +bus_factory_proxy_create_engine (BusFactoryProxy *factory, + IBusEngineDesc *desc) +{ + g_assert (BUS_IS_FACTORY_PROXY (factory)); + g_assert (IBUS_IS_ENGINE_DESC (desc)); + + IBusMessage *reply_message; + IBusError *error; + BusEngineProxy *engine; + gchar *object_path; + + if (g_list_find (factory->component->engines, desc) == NULL) { + return NULL; + } + + reply_message = ibus_proxy_call_with_reply_and_block ((IBusProxy *) factory, + "CreateEngine", + -1, + &error, + G_TYPE_STRING, &(desc->name), + DBUS_TYPE_INVALID); + if (reply_message == NULL) { + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + return NULL; + } + + if ((error = ibus_error_new_from_message (reply_message)) != NULL) { + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + ibus_message_unref (reply_message); + return NULL; + } + + if (!ibus_message_get_args (reply_message, + &error, + IBUS_TYPE_OBJECT_PATH, &object_path, + G_TYPE_INVALID)) { + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + ibus_message_unref (reply_message); + + return NULL; + } + + IBusConnection *connection = ibus_proxy_get_connection ((IBusProxy *) factory); + engine = bus_engine_proxy_new (object_path, desc, (BusConnection *) connection); + ibus_message_unref (reply_message); + + return engine; +} + diff --git a/bus/factoryproxy.h b/bus/factoryproxy.h new file mode 100644 index 0000000..198b458 --- /dev/null +++ b/bus/factoryproxy.h @@ -0,0 +1,84 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __FACTORY_PROXY_H_ +#define __FACTORY_PROXY_H_ + +#include <ibus.h> +#include "connection.h" +#include "engineproxy.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define BUS_TYPE_FACTORY_PROXY \ + (bus_factory_proxy_get_type ()) +#define BUS_FACTORY_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUS_TYPE_FACTORY_PROXY, BusFactoryProxy)) +#define BUS_FACTORY_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), BUS_TYPE_FACTORY_PROXY, BusFactoryProxyClass)) +#define BUS_IS_FACTORY_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUS_TYPE_FACTORY_PROXY)) +#define BUS_IS_FACTORY_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), BUS_TYPE_FACTORY_PROXY)) +#define BUS_FACTORY_PROXY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), BUS_TYPE_FACTORY_PROXY, BusFactoryProxyClass)) + +G_BEGIN_DECLS + +typedef struct _BusFactoryProxy BusFactoryProxy; +typedef struct _BusFactoryProxyClass BusFactoryProxyClass; + +struct _BusFactoryProxy { + IBusProxy parent; + /* instance members */ + + IBusComponent *component; + GList *engine_list; +}; + +struct _BusFactoryProxyClass { + IBusProxyClass parent; + /* class members */ +}; + +GType bus_factory_proxy_get_type (void); +BusFactoryProxy *bus_factory_proxy_new (IBusComponent *component, + BusConnection *connection); +IBusComponent *bus_factory_proxy_get_component(BusFactoryProxy *factory); +BusEngineProxy *bus_factory_proxy_create_engine(BusFactoryProxy *factory, + IBusEngineDesc *desc); +BusFactoryProxy *bus_factory_proxy_get_from_component + (IBusComponent *component); +BusFactoryProxy *bus_factory_proxy_get_from_engine + (IBusEngineDesc *desc); + +#if 0 +const gchar *bus_factory_proxy_get_name (BusFactoryProxy *factory); +const gchar *bus_factory_proxy_get_lang (BusFactoryProxy *factory); +const gchar *bus_factory_proxy_get_icon (BusFactoryProxy *factory); +const gchar *bus_factory_proxy_get_authors (BusFactoryProxy *factory); +const gchar *bus_factory_proxy_get_credits (BusFactoryProxy *factory); +#endif + +G_END_DECLS +#endif + diff --git a/bus/ibusimpl.c b/bus/ibusimpl.c new file mode 100644 index 0000000..31799d6 --- /dev/null +++ b/bus/ibusimpl.c @@ -0,0 +1,935 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "ibusimpl.h" +#include "dbusimpl.h" +#include "server.h" +#include "connection.h" +#include "registry.h" +#include "factoryproxy.h" +#include "panelproxy.h" +#include "inputcontext.h" + + +enum { + LAST_SIGNAL, +}; + +enum { + PROP_0, +}; + +// static guint _signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void bus_ibus_impl_class_init (BusIBusImplClass *klass); +static void bus_ibus_impl_init (BusIBusImpl *ibus); +static void bus_ibus_impl_destroy (BusIBusImpl *ibus); +static gboolean bus_ibus_impl_ibus_message (BusIBusImpl *ibus, + BusConnection *connection, + IBusMessage *message); +static void bus_ibus_impl_add_factory (BusIBusImpl *ibus, + BusFactoryProxy *factory); +static void bus_ibus_impl_set_trigger (BusIBusImpl *ibus, + GValue *value); +static void bus_ibus_impl_set_preload_engines + (BusIBusImpl *ibus, + GValue *value); +static void _factory_destroy_cb (BusFactoryProxy *factory, + BusIBusImpl *ibus); + +static IBusServiceClass *parent_class = NULL; + +GType +bus_ibus_impl_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (BusIBusImplClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) bus_ibus_impl_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (BusIBusImpl), + 0, + (GInstanceInitFunc) bus_ibus_impl_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERVICE, + "BusIBusImpl", + &type_info, + (GTypeFlags) 0); + } + return type; +} + +BusIBusImpl * +bus_ibus_impl_get_default (void) +{ + static BusIBusImpl *ibus = NULL; + + if (ibus == NULL) { + ibus = (BusIBusImpl *) g_object_new (BUS_TYPE_IBUS_IMPL, + "path", IBUS_PATH_IBUS, + NULL); + bus_dbus_impl_register_object (BUS_DEFAULT_DBUS, + (IBusService *)ibus); + } + return ibus; +} + +static void +bus_ibus_impl_class_init (BusIBusImplClass *klass) +{ + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + + parent_class = (IBusServiceClass *) g_type_class_peek_parent (klass); + + ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_ibus_impl_destroy; + + IBUS_SERVICE_CLASS (klass)->ibus_message = (ServiceIBusMessageFunc) bus_ibus_impl_ibus_message; + +} + +static void +_panel_destroy_cb (BusPanelProxy *panel, + BusIBusImpl *ibus) +{ + g_assert (BUS_IS_PANEL_PROXY (panel)); + g_assert (BUS_IS_IBUS_IMPL (ibus)); + + g_return_if_fail (ibus->panel == panel); + + ibus->panel = NULL; + g_object_unref (panel); +} + +static void +bus_ibus_impl_set_trigger (BusIBusImpl *ibus, + GValue *value) +{ + g_assert (BUS_IS_IBUS_IMPL (ibus)); + + GValueArray *array; + gint i; + + ibus_hotkey_profile_remove_hotkey_by_event (ibus->hotkey_profile, + g_quark_from_static_string ("trigger")); + + if (value == NULL) { + ibus_hotkey_profile_add_hotkey (ibus->hotkey_profile, + IBUS_space, + IBUS_CONTROL_MASK, + g_quark_from_static_string ("trigger")); + return; + } + + g_return_if_fail (G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY); + array = g_value_get_boxed (value); + + for (i = 0; i < array->n_values; i++) { + GValue *str; + + str = g_value_array_get_nth (array, i); + g_return_if_fail (G_VALUE_TYPE (str) == G_TYPE_STRING); + + ibus_hotkey_profile_add_hotkey_from_string (ibus->hotkey_profile, + g_value_get_string (str), + g_quark_from_static_string ("trigger")); + } +} + +static void +bus_ibus_impl_set_preload_engines (BusIBusImpl *ibus, + GValue *value) +{ + GList *engine_list = NULL; + + g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL); + g_list_free (ibus->engine_list); + + if (value != NULL && G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY) { + GValueArray *array; + gint i; + + array = (GValueArray *) g_value_get_boxed (value); + for (i = 0; array && i < array->n_values; i++) { + const gchar *engine_name; + IBusEngineDesc *engine; + + if (G_VALUE_TYPE (&array->values[i]) != G_TYPE_STRING) + continue; + + engine_name = g_value_get_string (&array->values[i]); + + engine = bus_registry_find_engine_by_name (ibus->registry, engine_name); + + if (engine == NULL || g_list_find (engine_list, engine) != NULL) + continue; + + engine_list = g_list_append (engine_list, engine); + } + } + + g_list_foreach (engine_list, (GFunc) g_object_ref, NULL); + ibus->engine_list = engine_list; +} + +static void +bus_ibus_impl_reload_config (BusIBusImpl *ibus) +{ + g_assert (BUS_IS_IBUS_IMPL (ibus)); + + gint i; + GValue value = { 0 }; + + const static struct { + gchar *section; + gchar *key; + void ( *func) (BusIBusImpl *, GValue *); + } entries [] = { + { "general/hotkey", "trigger", bus_ibus_impl_set_trigger }, + { "general", "preload_engines", bus_ibus_impl_set_preload_engines }, + { NULL, NULL, NULL }, + }; + + for (i = 0; entries[i].section != NULL; i++) { + if (ibus->config != NULL && + ibus_config_get_value (ibus->config, + entries[i].section, + entries[i].key, + &value)) { + entries[i].func (ibus, &value); + g_value_unset (&value); + } + else { + entries[i].func (ibus, NULL); + } + } +} + +static void +_config_value_changed_cb (IBusConfig *config, + gchar *section, + gchar *key, + GValue *value, + BusIBusImpl *ibus) +{ + g_assert (IBUS_IS_CONFIG (config)); + g_assert (section); + g_assert (key); + g_assert (value); + g_assert (BUS_IS_IBUS_IMPL (ibus)); + + gint i; + + const static struct { + gchar *section; + gchar *key; + void ( *func) (BusIBusImpl *, GValue *); + } entries [] = { + { "general/hotkey", "trigger", bus_ibus_impl_set_trigger }, + { "general", "preload_engines", bus_ibus_impl_set_preload_engines }, + { NULL, NULL, NULL }, + }; + + for (i = 0; entries[i].section != NULL; i++) { + if (g_strcmp0 (entries[i].section, section) == 0 && + g_strcmp0 (entries[i].key, key) == 0) { + entries[i].func (ibus, value); + break; + } + } +} + +static void +_config_destroy_cb (IBusConfig *config, + BusIBusImpl *ibus) +{ + g_assert (IBUS_IS_CONFIG (config)); + g_assert (BUS_IS_IBUS_IMPL (ibus)); + + g_assert (ibus->config == config); + + ibus->config = NULL; + g_object_unref (config); +} + +static void +_dbus_name_owner_changed_cb (BusDBusImpl *dbus, + const gchar *name, + const gchar *old_name, + const gchar *new_name, + BusIBusImpl *ibus) +{ + g_assert (BUS_IS_DBUS_IMPL (dbus)); + g_assert (name != NULL); + g_assert (old_name != NULL); + g_assert (new_name != NULL); + g_assert (BUS_IS_IBUS_IMPL (ibus)); + + BusFactoryProxy *factory; + + if (g_strcmp0 (name, IBUS_SERVICE_PANEL) == 0) { + if (g_strcmp0 (new_name, "") != 0) { + BusConnection *connection; + + if (ibus->panel != NULL) { + ibus_object_destroy (IBUS_OBJECT (ibus->panel)); + ibus->panel = NULL; + } + + connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name); + g_return_if_fail (connection != NULL); + + ibus->panel = bus_panel_proxy_new (connection); + + g_signal_connect (ibus->panel, + "destroy", + G_CALLBACK (_panel_destroy_cb), + ibus); + + if (ibus->focused_context != NULL) { + bus_panel_proxy_focus_in (ibus->panel, ibus->focused_context); + } + } + } + else if (g_strcmp0 (name, IBUS_SERVICE_CONFIG) == 0) { + if (g_strcmp0 (new_name, "") != 0) { + BusConnection *connection; + + if (ibus->config != NULL) { + ibus_object_destroy (IBUS_OBJECT (ibus->config)); + ibus->config = NULL; + } + + connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name); + g_return_if_fail (connection != NULL); + + ibus->config = g_object_new (IBUS_TYPE_CONFIG, + "name", NULL, + "path", IBUS_PATH_CONFIG, + "connection", connection, + NULL); + + g_signal_connect (ibus->config, + "value-changed", + G_CALLBACK (_config_value_changed_cb), + ibus); + + g_signal_connect (ibus->config, + "destroy", + G_CALLBACK (_config_destroy_cb), + ibus); + + bus_ibus_impl_reload_config (ibus); + } + } + + factory = bus_registry_name_owner_changed (ibus->registry, name, old_name, new_name); + + if (factory) { + bus_ibus_impl_add_factory (ibus, factory); + g_object_unref (factory); + } +} + +static void +bus_ibus_impl_init (BusIBusImpl *ibus) +{ + ibus->factory_dict = g_hash_table_new_full ( + g_str_hash, + g_str_equal, + NULL, + (GDestroyNotify) g_object_unref); + + ibus->registry = bus_registry_new (); + ibus->engine_list = NULL; + ibus->register_engine_list = NULL; + ibus->contexts = NULL; + ibus->focused_context = NULL; + ibus->panel = NULL; + ibus->config = NULL; + + ibus->hotkey_profile = ibus_hotkey_profile_new (); + + bus_ibus_impl_reload_config (ibus); + + g_signal_connect (BUS_DEFAULT_DBUS, + "name-owner-changed", + G_CALLBACK (_dbus_name_owner_changed_cb), + ibus); +} + +static void +bus_ibus_impl_destroy (BusIBusImpl *ibus) +{ + g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL); + g_list_free (ibus->engine_list); + ibus->engine_list = NULL; + + g_list_foreach (ibus->register_engine_list, (GFunc) g_object_unref, NULL); + g_list_free (ibus->register_engine_list); + ibus->register_engine_list = NULL; + + if (ibus->factory_dict != NULL) { + g_hash_table_destroy (ibus->factory_dict); + ibus->factory_dict = NULL; + } + + if (ibus->hotkey_profile != NULL) { + g_object_unref (ibus->hotkey_profile); + ibus->hotkey_profile = NULL; + } + + bus_server_quit (BUS_DEFAULT_SERVER); + + IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (ibus)); +} + +/* introspectable interface */ +static IBusMessage * +_ibus_introspect (BusIBusImpl *ibus, + IBusMessage *message, + BusConnection *connection) +{ + static const gchar *introspect = + DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE + "<node>\n" + " <interface name=\"org.freedesktop.DBus.Introspectable\">\n" + " <method name=\"Introspect\">\n" + " <arg name=\"data\" direction=\"out\" type=\"s\"/>\n" + " </method>\n" + " </interface>\n" + " <interface name=\"org.freedesktop.DBus\">\n" + " <method name=\"RequestName\">\n" + " <arg direction=\"in\" type=\"s\"/>\n" + " <arg direction=\"in\" type=\"u\"/>\n" + " <arg direction=\"out\" type=\"u\"/>\n" + " </method>\n" + " <signal name=\"NameOwnerChanged\">\n" + " <arg type=\"s\"/>\n" + " <arg type=\"s\"/>\n" + " <arg type=\"s\"/>\n" + " </signal>\n" + " </interface>\n" + "</node>\n"; + + IBusMessage *reply_message; + reply_message = ibus_message_new_method_return (message); + ibus_message_append_args (reply_message, + G_TYPE_STRING, &introspect, + G_TYPE_INVALID); + + return reply_message; +} + + + +static IBusMessage * +_ibus_get_address (BusIBusImpl *ibus, + IBusMessage *message, + BusConnection *connection) +{ + const gchar *address; + IBusMessage *reply; + + address = ibus_server_get_address (IBUS_SERVER (BUS_DEFAULT_SERVER)); + + reply = ibus_message_new_method_return (message); + ibus_message_append_args (message, + G_TYPE_STRING, &address, + G_TYPE_INVALID); + + return reply; +} + +static void +_context_request_engine_cb (BusInputContext *context, + gchar *engine_name, + BusIBusImpl *ibus) +{ + IBusEngineDesc *engine_desc = NULL; + IBusComponent *comp; + BusFactoryProxy *factory; + BusEngineProxy *engine; + + if (engine_name == NULL || engine_name[0] == '\0') { + /* request default engine */ + if (ibus->register_engine_list) { + engine_desc = (IBusEngineDesc *)ibus->register_engine_list->data; + } + else if (ibus->engine_list) { + engine_desc = (IBusEngineDesc *)ibus->engine_list->data; + } + } + else { + /* request engine by name */ + GList *p; + gboolean found = FALSE; + + /* find engine in registered engine list */ + for (p = ibus->register_engine_list; p != NULL; p = p->next) { + engine_desc = (IBusEngineDesc *)p->data; + if (g_strcmp0 (engine_desc->name, engine_name) == 0) { + found = TRUE; + break; + } + } + + if (!found) { + /* find engine in preload engine list */ + for (p = ibus->engine_list; p != NULL; p = p->next) { + engine_desc = (IBusEngineDesc *)p->data; + if (g_strcmp0 (engine_desc->name, engine_name) == 0) { + found = TRUE; + break; + } + } + } + + if (!found) { + engine_desc = NULL; + } + } + + if (engine_desc == NULL) + return; + + factory = bus_factory_proxy_get_from_engine (engine_desc); + + if (factory == NULL) { + /* try to execute the engine */ + comp = ibus_component_get_from_engine (engine_desc); + g_assert (comp); + + if (!ibus_component_is_running (comp)) { + ibus_component_start (comp); + + gint time = 0; + while (time < G_USEC_PER_SEC * 3) { + if (g_main_context_pending (NULL)) { + g_main_context_iteration (NULL, FALSE); + } + else { + g_usleep (50 * 1000); + time += 50 * 1000; + } + factory = bus_factory_proxy_get_from_engine (engine_desc); + if (factory != NULL) { + break; + } + } + } + factory = bus_factory_proxy_get_from_engine (engine_desc); + } + + if (factory == NULL) + return; + + engine = bus_factory_proxy_create_engine (factory, engine_desc); + + if (engine == NULL) + return; + + bus_input_context_set_engine (context, engine); +} + +static void +_context_request_next_engine_cb (BusInputContext *context, + BusIBusImpl *ibus) +{ + +} + +static void +_context_request_prev_engine_cb (BusInputContext *context, + BusIBusImpl *ibus) +{ + +} + +static void +_context_focus_out_cb (BusInputContext *context, + BusIBusImpl *ibus) +{ + g_assert (BUS_IS_IBUS_IMPL (ibus)); + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + if (ibus->focused_context != context) + return; + + if (ibus->panel != NULL) { + bus_panel_proxy_focus_out (ibus->panel, context); + } + + if (context) { + g_object_unref (context); + ibus->focused_context = NULL; + } +} + +static void +_context_focus_in_cb (BusInputContext *context, + BusIBusImpl *ibus) +{ + g_assert (BUS_IS_IBUS_IMPL (ibus)); + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + if (ibus->focused_context) { + /* focus out context */ + bus_input_context_focus_out (ibus->focused_context); + g_assert (ibus->focused_context == NULL); + } + + g_object_ref (context); + ibus->focused_context = context; + + if (ibus->panel != NULL) { + bus_panel_proxy_focus_in (ibus->panel, ibus->focused_context); + } + +} + +static void +_context_destroy_cb (BusInputContext *context, + BusIBusImpl *ibus) +{ + g_assert (BUS_IS_IBUS_IMPL (ibus)); + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + if (context == ibus->focused_context) { + /* focus out context */ + bus_input_context_focus_out (ibus->focused_context); + g_assert (ibus->focused_context == NULL); + } + + ibus->contexts = g_list_remove (ibus->contexts, context); + g_object_unref (context); +} + +static IBusMessage * +_ibus_create_input_context (BusIBusImpl *ibus, + IBusMessage *message, + BusConnection *connection) +{ + g_assert (BUS_IS_IBUS_IMPL (ibus)); + g_assert (message != NULL); + g_assert (BUS_IS_CONNECTION (connection)); + + gint i; + gchar *client; + IBusError *error; + IBusMessage *reply; + BusInputContext *context; + const gchar *path; + + if (!ibus_message_get_args (message, + &error, + G_TYPE_STRING, &client, + G_TYPE_INVALID)) { + reply = ibus_message_new_error (message, + DBUS_ERROR_INVALID_ARGS, + "Argument 1 of CreateInputContext should be an string"); + ibus_error_free (error); + return reply; + } + + context = bus_input_context_new (connection, client); + ibus->contexts = g_list_append (ibus->contexts, context); + + static const struct { + gchar *name; + GCallback callback; + } signals [] = { + { "request-engine", G_CALLBACK (_context_request_engine_cb) }, + { "request-next-engine", G_CALLBACK (_context_request_next_engine_cb) }, + { "request-prev-engine", G_CALLBACK (_context_request_prev_engine_cb) }, + { "focus-in", G_CALLBACK (_context_focus_in_cb) }, + { "focus-out", G_CALLBACK (_context_focus_out_cb) }, + { "destroy", G_CALLBACK (_context_destroy_cb) }, + { NULL, NULL } + }; + + for (i = 0; signals[i].name != NULL; i++) { + g_signal_connect (context, + signals[i].name, + signals[i].callback, + ibus); + } + + path = ibus_service_get_path ((IBusService *) context); + reply = ibus_message_new_method_return (message); + ibus_message_append_args (reply, + IBUS_TYPE_OBJECT_PATH, &path, + G_TYPE_INVALID); + + bus_dbus_impl_register_object (BUS_DEFAULT_DBUS, + (IBusService *)context); + return reply; +} + +static void +_factory_destroy_cb (BusFactoryProxy *factory, + BusIBusImpl *ibus) +{ + g_assert (BUS_IS_IBUS_IMPL (ibus)); + g_assert (BUS_IS_FACTORY_PROXY (factory)); + + IBusComponent *component; + GList *engines, *p; + + ibus->factory_list = g_list_remove (ibus->factory_list, factory); + + component = bus_factory_proxy_get_component (factory); + + if (component != NULL) { + p = engines = ibus_component_get_engines (component); + for (; p != NULL; p = p->next) { + if (g_list_find (ibus->register_engine_list, p->data)) { + ibus->register_engine_list = g_list_remove (ibus->register_engine_list, p->data); + g_object_unref (p->data); + } + } + g_list_free (engines); + } + + g_object_unref (factory); +} + +static void +bus_ibus_impl_add_factory (BusIBusImpl *ibus, + BusFactoryProxy *factory) +{ + g_assert (BUS_IS_IBUS_IMPL (ibus)); + g_assert (BUS_IS_FACTORY_PROXY (factory)); + + g_object_ref (factory); + ibus->factory_list = g_list_append (ibus->factory_list, factory); + + g_signal_connect (factory, "destroy", G_CALLBACK (_factory_destroy_cb), ibus); +} + + +static IBusMessage * +_ibus_register_component (BusIBusImpl *ibus, + IBusMessage *message, + BusConnection *connection) +{ + IBusMessage *reply; + IBusError *error; + gboolean retval; + GList *engines; + IBusComponent *component; + BusFactoryProxy *factory; + + retval = ibus_message_get_args (message, &error, + IBUS_TYPE_COMPONENT, &component, + G_TYPE_INVALID); + + if (!retval) { + reply = ibus_message_new_error_printf (message, + DBUS_ERROR_INVALID_ARGS, + "1st Argument must be IBusComponent: %s", + error->message); + ibus_error_free (error); + return reply; + } + + factory = bus_factory_proxy_new (component, connection); + + if (factory == NULL) { + reply = ibus_message_new_error (message, + DBUS_ERROR_FAILED, + "Can not create factory"); + return reply; + } + + bus_ibus_impl_add_factory (ibus, factory); + g_object_unref (factory); + + engines = ibus_component_get_engines (component); + + g_list_foreach (engines, (GFunc) g_object_ref, NULL); + ibus->register_engine_list = g_list_concat (ibus->register_engine_list, engines); + g_object_unref (component); + + reply = ibus_message_new_method_return (message); + return reply; +} + +static IBusMessage * +_ibus_list_engines (BusIBusImpl *ibus, + IBusMessage *message, + BusConnection *connection) +{ + IBusMessage *reply; + IBusMessageIter iter, sub_iter; + GList *engines, *p; + + reply = ibus_message_new_method_return (message); + + ibus_message_iter_init_append (reply, &iter); + ibus_message_iter_open_container (&iter, IBUS_TYPE_ARRAY, "v", &sub_iter); + + engines = bus_registry_get_engines (ibus->registry); + for (p = engines; p != NULL; p = p->next) { + ibus_message_iter_append (&sub_iter, IBUS_TYPE_ENGINE_DESC, &(p->data)); + } + g_list_free (engines); + ibus_message_iter_close_container (&iter, &sub_iter); + + return reply; +} + +static IBusMessage * +_ibus_list_active_engines (BusIBusImpl *ibus, + IBusMessage *message, + BusConnection *connection) +{ + IBusMessage *reply; + IBusMessageIter iter, sub_iter; + GList *p; + + reply = ibus_message_new_method_return (message); + + ibus_message_iter_init_append (reply, &iter); + ibus_message_iter_open_container (&iter, IBUS_TYPE_ARRAY, "v", &sub_iter); + + for (p = ibus->engine_list; p != NULL; p = p->next) { + ibus_message_iter_append (&sub_iter, IBUS_TYPE_ENGINE_DESC, &(p->data)); + } + + for (p = ibus->register_engine_list; p != NULL; p = p->next) { + ibus_message_iter_append (&sub_iter, IBUS_TYPE_ENGINE_DESC, &(p->data)); + } + ibus_message_iter_close_container (&iter, &sub_iter); + + return reply; +} + +static IBusMessage * +_ibus_kill (BusIBusImpl *ibus, + IBusMessage *message, + BusConnection *connection) +{ + IBusMessage *reply; + + reply = ibus_message_new_method_return (message); + ibus_connection_send ((IBusConnection *) connection, reply); + ibus_connection_flush ((IBusConnection *) connection); + ibus_message_unref (reply); + + ibus_object_destroy (IBUS_OBJECT (ibus)); + return NULL; +} + +static gboolean +bus_ibus_impl_ibus_message (BusIBusImpl *ibus, + BusConnection *connection, + IBusMessage *message) +{ + g_assert (BUS_IS_IBUS_IMPL (ibus)); + g_assert (BUS_IS_CONNECTION (connection)); + g_assert (message != NULL); + + gint i; + IBusMessage *reply_message = NULL; + + static const struct { + const gchar *interface; + const gchar *name; + IBusMessage *(* handler) (BusIBusImpl *, IBusMessage *, BusConnection *); + } handlers[] = { + /* Introspectable interface */ + { DBUS_INTERFACE_INTROSPECTABLE, + "Introspect", _ibus_introspect }, + /* IBus interface */ + { IBUS_INTERFACE_IBUS, "GetAddress", _ibus_get_address }, + { IBUS_INTERFACE_IBUS, "CreateInputContext", _ibus_create_input_context }, + { IBUS_INTERFACE_IBUS, "RegisterComponent", _ibus_register_component }, + { IBUS_INTERFACE_IBUS, "ListEngines", _ibus_list_engines }, + { IBUS_INTERFACE_IBUS, "ListActiveEngines", _ibus_list_active_engines }, + { IBUS_INTERFACE_IBUS, "Kill", _ibus_kill }, + { NULL, NULL, NULL } + }; + + ibus_message_set_sender (message, bus_connection_get_unique_name (connection)); + ibus_message_set_destination (message, DBUS_SERVICE_DBUS); + + for (i = 0; handlers[i].interface != NULL; i++) { + if (ibus_message_is_method_call (message, + handlers[i].interface, + handlers[i].name)) { + + reply_message = handlers[i].handler (ibus, message, connection); + if (reply_message) { + + ibus_message_set_sender (reply_message, DBUS_SERVICE_DBUS); + ibus_message_set_destination (reply_message, bus_connection_get_unique_name (connection)); + ibus_message_set_no_reply (reply_message, TRUE); + + ibus_connection_send ((IBusConnection *) connection, reply_message); + ibus_message_unref (reply_message); + } + + g_signal_stop_emission_by_name (ibus, "ibus-message"); + return TRUE; + } + } + + return parent_class->ibus_message ((IBusService *) ibus, + (IBusConnection *) connection, + message); +} + +BusFactoryProxy * +bus_ibus_impl_lookup_factory (BusIBusImpl *ibus, + const gchar *path) +{ + g_assert (BUS_IS_IBUS_IMPL (ibus)); + + BusFactoryProxy *factory; + + factory = (BusFactoryProxy *) g_hash_table_lookup (ibus->factory_dict, path); + + return factory; +} + +IBusHotkeyProfile * +bus_ibus_impl_get_hotkey_profile (BusIBusImpl *ibus) +{ + g_assert (BUS_IS_IBUS_IMPL (ibus)); + + return ibus->hotkey_profile; +} + +BusRegistry * +bus_ibus_impl_get_registry (BusIBusImpl *ibus) +{ + + g_assert (BUS_IS_IBUS_IMPL (ibus)); + + return ibus->registry; +} + diff --git a/bus/ibusimpl.h b/bus/ibusimpl.h new file mode 100644 index 0000000..fd85138 --- /dev/null +++ b/bus/ibusimpl.h @@ -0,0 +1,102 @@ +/* vim:set et sts=4: */ +/* bus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_IMPL_H_ +#define __IBUS_IMPL_H_ + +#include <ibus.h> +#include "connection.h" +#include "inputcontext.h" +#include "registry.h" +#include "factoryproxy.h" +#include "panelproxy.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define BUS_TYPE_IBUS_IMPL \ + (bus_ibus_impl_get_type ()) +#define BUS_IBUS_IMPL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUS_TYPE_IBUS_IMPL, BusIBusImpl)) +#define BUS_IBUS_IMPL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), BUS_TYPE_IBUS_IMPL, BusIBusImplClass)) +#define BUS_IS_IBUS_IMPL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUS_TYPE_IBUS_IMPL)) +#define BUS_IS_IBUS_IMPL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), BUS_TYPE_IBUS_IMPL)) +#define BUS_IBUS_IMPL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), BUS_TYPE_IBUS_IMPL, BusIBusImplClass)) + +#define BUS_DEFAULT_IBUS \ + (bus_ibus_impl_get_default ()) +#define BUS_DEFAULT_HOTKEY_PROFILE \ + (bus_ibus_impl_get_hotkey_profile (BUS_DEFAULT_IBUS)) +#define BUS_DEFAULT_REGISTRY \ + (bus_ibus_impl_get_registry (BUS_DEFAULT_IBUS)) + +G_BEGIN_DECLS + +typedef struct _BusIBusImpl BusIBusImpl; +typedef struct _BusIBusImplClass BusIBusImplClass; + +struct _BusIBusImpl { + IBusService parent; + /* instance members */ + + GHashTable *factory_dict; + GList *factory_list; + GList *contexts; + + GList *engine_list; + GList *register_engine_list; + GList *component_list; + + BusRegistry *registry; + + BusInputContext *focused_context; + BusPanelProxy *panel; + IBusConfig *config; + IBusHotkeyProfile *hotkey_profile; + +}; + +struct _BusIBusImplClass { + IBusServiceClass parent; + + /* class members */ +}; + +GType bus_ibus_impl_get_type (void); +BusIBusImpl *bus_ibus_impl_get_default (void); +BusFactoryProxy *bus_ibus_impl_get_default_factory (BusIBusImpl *ibus); +BusFactoryProxy *bus_ibus_impl_get_next_factory (BusIBusImpl *ibus, + BusFactoryProxy *factory); +BusFactoryProxy *bus_ibus_impl_get_previous_factory (BusIBusImpl *ibus, + BusFactoryProxy *factory); +BusFactoryProxy *bus_ibus_impl_lookup_factory (BusIBusImpl *ibus, + const gchar *path); +IBusHotkeyProfile + *bus_ibus_impl_get_hotkey_profile (BusIBusImpl *ibus); +BusRegistry *bus_ibus_impl_get_registry (BusIBusImpl *ibus); + +G_END_DECLS +#endif + diff --git a/bus/inputcontext.c b/bus/inputcontext.c new file mode 100644 index 0000000..a4e3359 --- /dev/null +++ b/bus/inputcontext.c @@ -0,0 +1,1559 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <ibusinternal.h> +#include <ibusmarshalers.h> +#include "ibusimpl.h" +#include "inputcontext.h" +#include "engineproxy.h" +#include "factoryproxy.h" + +#define BUS_INPUT_CONTEXT_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), BUS_TYPE_INPUT_CONTEXT, BusInputContextPrivate)) + +enum { + PROCESS_KEY_EVENT, + SET_CURSOR_LOCATION, + FOCUS_IN, + FOCUS_OUT, + UPDATE_PREEDIT_TEXT, + SHOW_PREEDIT_TEXT, + HIDE_PREEDIT_TEXT, + UPDATE_AUXILIARY_TEXT, + SHOW_AUXILIARY_TEXT, + HIDE_AUXILIARY_TEXT, + UPDATE_LOOKUP_TABLE, + SHOW_LOOKUP_TABLE, + HIDE_LOOKUP_TABLE, + PAGE_UP_LOOKUP_TABLE, + PAGE_DOWN_LOOKUP_TABLE, + CURSOR_UP_LOOKUP_TABLE, + CURSOR_DOWN_LOOKUP_TABLE, + REGISTER_PROPERTIES, + UPDATE_PROPERTY, + ENABLED, + DISABLED, + ENGINE_CHANGED, + REQUEST_ENGINE, + REQUEST_NEXT_ENGINE, + REQUEST_PREV_ENGINE, + LAST_SIGNAL, +}; + +enum { + PROP_0, +}; + + +/* IBusInputContextPriv */ +struct _BusInputContextPrivate { + BusConnection *connection; + BusEngineProxy *engine; + gchar *client; + + gboolean has_focus; + gboolean enabled; + + /* capabilities */ + guint capabilities; + + /* cursor location */ + gint x; + gint y; + gint w; + gint h; +}; + +typedef struct _BusInputContextPrivate BusInputContextPrivate; + +static guint context_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void bus_input_context_class_init (BusInputContextClass *klass); +static void bus_input_context_init (BusInputContext *context); +static void bus_input_context_destroy (BusInputContext *context); +static gboolean bus_input_context_ibus_message (BusInputContext *context, + BusConnection *connection, + IBusMessage *message); +static gboolean bus_input_context_filter_keyboard_shortcuts + (BusInputContext *context, + guint keyval, + guint modifiers); +static gboolean bus_input_context_send_signal (BusInputContext *context, + const gchar *signal_name, + GType first_arg_type, + ...); +static void _engine_destroy_cb (BusEngineProxy *factory, + BusInputContext *context); + +static IBusServiceClass *parent_class = NULL; +static guint id = 0; + +GType +bus_input_context_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (BusInputContextClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) bus_input_context_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (BusInputContext), + 0, + (GInstanceInitFunc) bus_input_context_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERVICE, + "BusInputContext", + &type_info, + (GTypeFlags) 0); + } + return type; +} + +static void +_connection_destroy_cb (BusConnection *connection, + BusInputContext *context) +{ + BUS_IS_CONNECTION (connection); + BUS_IS_INPUT_CONTEXT (context); + + ibus_object_destroy (IBUS_OBJECT (context)); +} + + +BusInputContext * +bus_input_context_new (BusConnection *connection, + const gchar *client) +{ + g_assert (BUS_IS_CONNECTION (connection)); + g_assert (client != NULL); + + BusInputContext *context; + gchar *path; + BusInputContextPrivate *priv; + + path = g_strdup_printf (IBUS_PATH_INPUT_CONTEXT, ++id); + + context = (BusInputContext *) g_object_new (BUS_TYPE_INPUT_CONTEXT, + "path", path, + NULL); + g_free (path); + + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + +#if 0 + ibus_service_add_to_connection (IBUS_SERVICE (context), + IBUS_CONNECTION (connection)); +#endif + + g_object_ref (connection); + priv->connection = connection; + priv->client = g_strdup (client); + + g_signal_connect (priv->connection, + "destroy", + (GCallback) _connection_destroy_cb, + context); + + return context; +} + +static void +bus_input_context_class_init (BusInputContextClass *klass) +{ + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + + parent_class = (IBusServiceClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (BusInputContextPrivate)); + + ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_input_context_destroy; + + IBUS_SERVICE_CLASS (klass)->ibus_message = (ServiceIBusMessageFunc) bus_input_context_ibus_message; + + /* install signals */ + context_signals[PROCESS_KEY_EVENT] = + g_signal_new (I_("process-key-event"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_BOOL__UINT_UINT, + G_TYPE_BOOLEAN, + 2, + G_TYPE_UINT, + G_TYPE_UINT); + + context_signals[SET_CURSOR_LOCATION] = + g_signal_new (I_("set-cursor-location"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__INT_INT_INT_INT, + G_TYPE_NONE, + 4, + G_TYPE_INT, + G_TYPE_INT, + G_TYPE_INT, + G_TYPE_INT); + + context_signals[FOCUS_IN] = + g_signal_new (I_("focus-in"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[FOCUS_OUT] = + g_signal_new (I_("focus-out"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[UPDATE_PREEDIT_TEXT] = + g_signal_new (I_("update-preedit-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT_UINT_BOOLEAN, + G_TYPE_NONE, + 3, + IBUS_TYPE_TEXT, + G_TYPE_UINT, + G_TYPE_BOOLEAN); + + context_signals[SHOW_PREEDIT_TEXT] = + g_signal_new (I_("show-preedit-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + context_signals[HIDE_PREEDIT_TEXT] = + g_signal_new (I_("hide-preedit-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + context_signals[UPDATE_AUXILIARY_TEXT] = + g_signal_new (I_("update-auxiliary-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT_BOOLEAN, + G_TYPE_NONE, + 2, + IBUS_TYPE_TEXT, + G_TYPE_BOOLEAN); + + context_signals[SHOW_AUXILIARY_TEXT] = + g_signal_new (I_("show-auxiliary-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + context_signals[HIDE_AUXILIARY_TEXT] = + g_signal_new (I_("hide-auxiliary-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + context_signals[UPDATE_LOOKUP_TABLE] = + g_signal_new (I_("update-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT_BOOLEAN, + G_TYPE_NONE, + 2, + IBUS_TYPE_LOOKUP_TABLE, + G_TYPE_BOOLEAN); + + context_signals[SHOW_LOOKUP_TABLE] = + g_signal_new (I_("show-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[HIDE_LOOKUP_TABLE] = + g_signal_new (I_("hide-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[PAGE_UP_LOOKUP_TABLE] = + g_signal_new (I_("page-up-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[PAGE_DOWN_LOOKUP_TABLE] = + g_signal_new (I_("page-down-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[CURSOR_UP_LOOKUP_TABLE] = + g_signal_new (I_("cursor-up-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[CURSOR_DOWN_LOOKUP_TABLE] = + g_signal_new (I_("cursor-down-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[REGISTER_PROPERTIES] = + g_signal_new (I_("register-properties"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + IBUS_TYPE_PROP_LIST); + + context_signals[UPDATE_PROPERTY] = + g_signal_new (I_("update-property"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + IBUS_TYPE_PROPERTY); + + context_signals[ENABLED] = + g_signal_new (I_("enabled"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + context_signals[DISABLED] = + g_signal_new (I_("disabled"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + context_signals[ENGINE_CHANGED] = + g_signal_new (I_("factory-changed"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + context_signals[REQUEST_ENGINE] = + g_signal_new (I_("request-engine"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); + + context_signals[REQUEST_NEXT_ENGINE] = + g_signal_new (I_("request-next-engine"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + context_signals[REQUEST_PREV_ENGINE] = + g_signal_new (I_("request-prev-engine"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); +} + +static void +bus_input_context_init (BusInputContext *context) +{ + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + priv->connection = NULL; + priv->client = NULL; + priv->engine = NULL; + priv->has_focus = FALSE; + priv->enabled = FALSE; + + priv->capabilities = 0; + + priv->x = 0; + priv->y = 0; + priv->w = 0; + priv->h = 0; + +} + +static void +bus_input_context_destroy (BusInputContext *context) +{ + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + if (priv->has_focus) { + bus_input_context_focus_out (context); + priv->has_focus = FALSE; + } + + if (priv->engine) { + g_signal_handlers_disconnect_by_func (priv->engine, + G_CALLBACK (_engine_destroy_cb), + context); + g_object_unref (priv->engine); + priv->engine = NULL; + } + + if (priv->connection) { + g_signal_handlers_disconnect_by_func (priv->connection, + (GCallback) _connection_destroy_cb, + context); + g_object_unref (priv->connection); + priv->connection = NULL; + } + + if (priv->client) { + g_free (priv->client); + priv->client = NULL; + } + + IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (context)); +} + +/* introspectable interface */ +static IBusMessage * +_ibus_introspect (BusInputContext *context, + IBusMessage *message, + BusConnection *connection) +{ + static const gchar *introspect = + "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n" + "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n" + "<node>\n" + " <interface name=\"org.freedesktop.DBus.Introspectable\">\n" + " <method name=\"Introspect\">\n" + " <arg name=\"data\" direction=\"out\" type=\"s\"/>\n" + " </method>\n" + " </interface>\n" + " <interface name=\"org.freedesktop.IBus\">\n" + " <method name=\"RequestName\">\n" + " <arg direction=\"in\" type=\"s\"/>\n" + " <arg direction=\"in\" type=\"u\"/>\n" + " <arg direction=\"out\" type=\"u\"/>\n" + " </method>\n" + " <signal name=\"NameOwnerChanged\">\n" + " <arg type=\"s\"/>\n" + " <arg type=\"s\"/>\n" + " <arg type=\"s\"/>\n" + " </signal>\n" + " </interface>\n" + "</node>\n"; + + IBusMessage *reply_message; + reply_message = ibus_message_new_method_return (message); + ibus_message_append_args (reply_message, + G_TYPE_STRING, &introspect, + G_TYPE_INVALID); + + return reply_message; +} + +typedef struct { + BusInputContext *context; + IBusMessage *message; +}CallData; + +static void +_ic_process_key_event_reply_cb (gboolean retval, + CallData *call_data) +{ + IBusMessage *reply; + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (call_data->context); + + reply = ibus_message_new_method_return (call_data->message); + ibus_message_append_args (reply, + G_TYPE_BOOLEAN, &retval, + G_TYPE_INVALID); + ibus_connection_send ((IBusConnection *)priv->connection, reply); + + g_object_unref (call_data->context); + ibus_message_unref (call_data->message); + ibus_message_unref (reply); + g_slice_free (CallData, call_data); +} + +static IBusMessage * +_ic_process_key_event (BusInputContext *context, + IBusMessage *message, + BusConnection *connection) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + g_assert (message != NULL); + g_assert (BUS_IS_CONNECTION (connection)); + + IBusMessage *reply = NULL; + guint keyval, modifiers; + gboolean retval; + IBusError *error; + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + + error = ibus_error_new (); + retval = ibus_message_get_args (message, + &error, + G_TYPE_UINT, &keyval, + G_TYPE_UINT, &modifiers, + G_TYPE_INVALID); + + if (!retval) { + reply = ibus_message_new_error (message, + error->name, + error->message); + ibus_error_free (error); + return reply; + } + + ibus_error_free (error); + + retval = bus_input_context_filter_keyboard_shortcuts (context, keyval, modifiers); + + if (retval) { + reply = ibus_message_new_method_return (message); + ibus_message_append_args (reply, + G_TYPE_BOOLEAN, &retval, + G_TYPE_INVALID); + } + else if (priv->enabled && priv->engine) { + CallData *call_data = g_slice_new (CallData); + call_data->context = context; + call_data->message = message; + g_object_ref (context); + ibus_message_ref (message); + + bus_engine_proxy_process_key_event (priv->engine, + keyval, + modifiers, + (GFunc) _ic_process_key_event_reply_cb, + call_data); + } + else { + reply = ibus_message_new_method_return (message); + ibus_message_append_args (reply, + G_TYPE_BOOLEAN, &retval, + G_TYPE_INVALID); + } + return reply; +} + +static IBusMessage * +_ic_set_cursor_location (BusInputContext *context, + IBusMessage *message, + BusConnection *connection) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + g_assert (message != NULL); + g_assert (BUS_IS_CONNECTION (connection)); + + IBusMessage *reply; + guint x, y, w, h; + gboolean retval; + IBusError *error; + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + retval = ibus_message_get_args (message, &error, + G_TYPE_INT, &x, + G_TYPE_INT, &y, + G_TYPE_INT, &w, + G_TYPE_INT, &h, + G_TYPE_INVALID); + + if (!retval) { + reply = ibus_message_new_error (message, + error->name, + error->message); + ibus_error_free (error); + return reply; + } + + priv->x = x; + priv->y = y; + priv->h = h; + priv->w = w; + + if (priv->engine) { + bus_engine_proxy_set_cursor_location (priv->engine, x, y, w, h); + } + + if (priv->capabilities & IBUS_CAP_FOCUS) { + g_signal_emit (context, + context_signals[SET_CURSOR_LOCATION], + 0, + x, + y, + w, + h); + } + + reply = ibus_message_new_method_return (message); + return reply; +} + +static IBusMessage * +_ic_focus_in (BusInputContext *context, + IBusMessage *message, + BusConnection *connection) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + g_assert (message != NULL); + g_assert (BUS_IS_CONNECTION (connection)); + + IBusMessage *reply; + + bus_input_context_focus_in (context); + + reply = ibus_message_new_method_return (message); + + return reply; +} + +static IBusMessage * +_ic_focus_out (BusInputContext *context, + IBusMessage *message, + BusConnection *connection) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + g_assert (message != NULL); + g_assert (BUS_IS_CONNECTION (connection)); + + IBusMessage *reply; + + bus_input_context_focus_out (context); + + reply = ibus_message_new_method_return (message); + + return reply; +} + +static IBusMessage * +_ic_reset (BusInputContext *context, + IBusMessage *message, + BusConnection *connection) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + g_assert (message != NULL); + g_assert (BUS_IS_CONNECTION (connection)); + + IBusMessage *reply; + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + + if (priv->engine) { + bus_engine_proxy_reset (priv->engine); + } + + reply = ibus_message_new_method_return (message); + return reply; +} + +static IBusMessage * +_ic_set_capabilities (BusInputContext *context, + IBusMessage *message, + BusConnection *connection) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + g_assert (message != NULL); + g_assert (BUS_IS_CONNECTION (connection)); + + IBusMessage *reply; + guint caps; + gboolean retval; + IBusError *error; + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + + retval = ibus_message_get_args (message, + &error, + G_TYPE_UINT, &caps, + G_TYPE_INVALID); + + if (!retval) { + reply = ibus_message_new_error (message, + error->name, + error->message); + ibus_error_free (error); + return reply; + } + + if (priv->capabilities != caps) { + priv->capabilities = caps; + + if (priv->engine) { + bus_engine_proxy_set_capabilities (priv->engine, caps); + } + } + + reply = ibus_message_new_method_return (message); + return reply; +} + +static IBusMessage * +_ic_is_enabled (BusInputContext *context, + IBusMessage *message, + BusConnection *connection) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + g_assert (message != NULL); + g_assert (BUS_IS_CONNECTION (connection)); + + IBusMessage *reply; + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + reply = ibus_message_new_method_return (message); + ibus_message_append_args (reply, + G_TYPE_BOOLEAN, &priv->enabled, + G_TYPE_INVALID); + + return reply; +} + +static IBusMessage * +_ic_set_engine (BusInputContext *context, + IBusMessage *message, + BusConnection *connection) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + g_assert (message != NULL); + g_assert (BUS_IS_CONNECTION (connection)); + + gboolean retval; + IBusMessage *reply; + IBusError *error; + gchar *engine_name; + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + retval = ibus_message_get_args (message, + &error, + G_TYPE_STRING, &engine_name, + G_TYPE_INVALID); + if (!retval) { + reply = ibus_message_new_error (message, + error->name, + error->message); + ibus_error_free (error); + return reply; + } + + g_signal_emit (context, context_signals[REQUEST_ENGINE], 0, engine_name); + + if (priv->engine == NULL) { + reply = ibus_message_new_error_printf (message, + "org.freedesktop.IBus.NoEngine", + "can not find engine with name %s", + engine_name); + return reply; + } + + bus_input_context_enable (context); + + reply = ibus_message_new_method_return (message); + return reply; +} + +static IBusMessage * +_ic_get_engine (BusInputContext *context, + IBusMessage *message, + BusConnection *connection) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + g_assert (message != NULL); + g_assert (BUS_IS_CONNECTION (connection)); + + IBusMessage *reply; + IBusEngineDesc *desc; + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + if (priv->engine) { + desc = bus_engine_proxy_get_desc (priv->engine); + if (desc != NULL) { + reply = ibus_message_new_method_return (message); + ibus_message_append_args (reply, + IBUS_TYPE_ENGINE_DESC, &desc, + G_TYPE_INVALID); + return reply; + } + } + + reply = ibus_message_new_error (message, + DBUS_ERROR_FAILED, + "InputContext does not have factory."); + return reply; +} + +static IBusMessage * +_ic_destroy (BusInputContext *context, + IBusMessage *message, + BusConnection *connection) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + g_assert (message != NULL); + g_assert (BUS_IS_CONNECTION (connection)); + + IBusMessage *reply; + reply = ibus_message_new_method_return (message); + + ibus_connection_send ((IBusConnection *) connection, reply); + ibus_connection_flush ((IBusConnection *) connection); + ibus_message_unref (reply); + + ibus_object_destroy ((IBusObject *) context); + + return NULL; +} + +static gboolean +bus_input_context_ibus_message (BusInputContext *context, + BusConnection *connection, + IBusMessage *message) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + g_assert (BUS_IS_CONNECTION (connection)); + g_assert (message != NULL); + + gint i; + IBusMessage *reply_message = NULL; + + static const struct { + const gchar *interface; + const gchar *name; + IBusMessage *(* handler) (BusInputContext *, IBusMessage *, BusConnection *); + } handlers[] = { + /* Introspectable interface */ + { DBUS_INTERFACE_INTROSPECTABLE, + "Introspect", _ibus_introspect }, + /* IBus interface */ + { IBUS_INTERFACE_INPUT_CONTEXT, "ProcessKeyEvent", _ic_process_key_event }, + { IBUS_INTERFACE_INPUT_CONTEXT, "SetCursorLocation", _ic_set_cursor_location }, + { IBUS_INTERFACE_INPUT_CONTEXT, "FocusIn", _ic_focus_in }, + { IBUS_INTERFACE_INPUT_CONTEXT, "FocusOut", _ic_focus_out }, + { IBUS_INTERFACE_INPUT_CONTEXT, "Reset", _ic_reset }, + { IBUS_INTERFACE_INPUT_CONTEXT, "SetCapabilities", _ic_set_capabilities }, + { IBUS_INTERFACE_INPUT_CONTEXT, "IsEnabled", _ic_is_enabled }, + { IBUS_INTERFACE_INPUT_CONTEXT, "SetEngine", _ic_set_engine }, + { IBUS_INTERFACE_INPUT_CONTEXT, "GetEngine", _ic_get_engine }, + { IBUS_INTERFACE_INPUT_CONTEXT, "Destroy", _ic_destroy }, + + { NULL, NULL, NULL } + }; + + ibus_message_set_sender (message, bus_connection_get_unique_name (connection)); + ibus_message_set_destination (message, DBUS_SERVICE_DBUS); + + for (i = 0; handlers[i].interface != NULL; i++) { + if (ibus_message_is_method_call (message, + handlers[i].interface, + handlers[i].name)) { + + reply_message = handlers[i].handler (context, message, connection); + if (reply_message) { + + ibus_message_set_sender (reply_message, + DBUS_SERVICE_DBUS); + ibus_message_set_destination (reply_message, + bus_connection_get_unique_name (connection)); + ibus_message_set_no_reply (reply_message, TRUE); + + ibus_connection_send (IBUS_CONNECTION (connection), reply_message); + ibus_message_unref (reply_message); + } + + g_signal_stop_emission_by_name (context, "ibus-message"); + return TRUE; + } + } + + return parent_class->ibus_message ((IBusService *)context, + (IBusConnection *)connection, + message); +} + + +gboolean +bus_input_context_is_focus (BusInputContext *context) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + return priv->has_focus; +} + +void +bus_input_context_focus_in (BusInputContext *context) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + if (priv->has_focus) + return; + + priv->has_focus = TRUE; + + if (priv->engine) { + bus_engine_proxy_focus_in (priv->engine); + } + + if (priv->capabilities & IBUS_CAP_FOCUS) { + g_signal_emit (context, context_signals[FOCUS_IN], 0); + } +} + +void +bus_input_context_focus_out (BusInputContext *context) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + if (!priv->has_focus) + return; + + priv->has_focus = FALSE; + + if (priv->engine) { + bus_engine_proxy_focus_out (priv->engine); + } + + if (priv->capabilities & IBUS_CAP_FOCUS) { + g_signal_emit (context, context_signals[FOCUS_OUT], 0); + } +} + +void +bus_input_context_page_up (BusInputContext *context) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + if (priv->engine) { + bus_engine_proxy_page_up (priv->engine); + } +} + +void +bus_input_context_page_down (BusInputContext *context) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + if (priv->engine) { + bus_engine_proxy_page_down (priv->engine); + } +} + +void +bus_input_context_cursor_up (BusInputContext *context) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + if (priv->engine) { + bus_engine_proxy_cursor_up (priv->engine); + } +} + +void +bus_input_context_cursor_down (BusInputContext *context) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + if (priv->engine) { + bus_engine_proxy_cursor_down (priv->engine); + } +} + +void +bus_input_context_property_activate (BusInputContext *context, + const gchar *prop_name, + gint prop_state) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + if (priv->engine) { + bus_engine_proxy_property_activate (priv->engine, prop_name, prop_state); + } +} + +static void +_engine_destroy_cb (BusEngineProxy *engine, + BusInputContext *context) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + g_assert (priv->engine == engine); + + bus_input_context_set_engine (context, NULL); +} + +static void +_engine_commit_text_cb (BusEngineProxy *engine, + IBusText *text, + BusInputContext *context) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + g_assert (text != NULL); + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + g_assert (priv->engine == engine); + + bus_input_context_send_signal (context, + "CommitText", + IBUS_TYPE_TEXT, &text, + G_TYPE_INVALID); + +} + +static void +_engine_forward_key_event_cb (BusEngineProxy *engine, + guint keyval, + guint state, + BusInputContext *context) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + g_assert (priv->engine == engine); + + bus_input_context_send_signal (context, + "ForwardKeyEvent", + G_TYPE_UINT, &keyval, + G_TYPE_UINT, &state, + G_TYPE_INVALID); + +} + +static void +_engine_update_preedit_text_cb (BusEngineProxy *engine, + IBusText *text, + guint cursor_pos, + gboolean visible, + BusInputContext *context) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + g_assert (IBUS_IS_TEXT (text)); + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + g_assert (priv->engine == engine); + + if (priv->capabilities & IBUS_CAP_PREEDIT_TEXT) { + bus_input_context_send_signal (context, + "UpdatePreeditText", + IBUS_TYPE_TEXT, &text, + G_TYPE_UINT, &cursor_pos, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); + } + else { + g_signal_emit (context, + context_signals[UPDATE_PREEDIT_TEXT], + 0, + text, + cursor_pos, + visible); + } +} + +static void +_engine_update_auxiliary_text_cb (BusEngineProxy *engine, + IBusText *text, + gboolean visible, + BusInputContext *context) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + g_assert (IBUS_IS_TEXT (text)); + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + g_assert (priv->engine == engine); + + if (priv->capabilities & IBUS_CAP_AUXILIARY_TEXT) { + bus_input_context_send_signal (context, + "UpdateAuxiliaryText", + IBUS_TYPE_TEXT, &text, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); + } + else { + g_signal_emit (context, + context_signals[UPDATE_AUXILIARY_TEXT], + 0, + text, + visible); + } +} + +static void +_engine_update_lookup_table_cb (BusEngineProxy *engine, + IBusLookupTable *table, + gboolean visible, + BusInputContext *context) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + g_assert (IBUS_IS_LOOKUP_TABLE (table)); + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + g_assert (priv->engine == engine); + + if (priv->capabilities & IBUS_CAP_LOOKUP_TABLE) { + bus_input_context_send_signal (context, + "UpdateLookupTable", + IBUS_TYPE_LOOKUP_TABLE, &table, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); + } + else { + g_signal_emit (context, + context_signals[UPDATE_LOOKUP_TABLE], + 0, + table, + visible); + } +} + +static void +_engine_register_properties_cb (BusEngineProxy *engine, + IBusPropList *prop_list, + BusInputContext *context) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + g_assert (IBUS_IS_PROP_LIST (prop_list)); + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + g_assert (priv->engine == engine); + + if (priv->capabilities & IBUS_CAP_PROPERTY) { + bus_input_context_send_signal (context, + "RegisterProperties", + IBUS_TYPE_PROP_LIST, &prop_list, + G_TYPE_INVALID); + } + else { + g_signal_emit (context, + context_signals[REGISTER_PROPERTIES], + 0, + prop_list); + } +} + +static void +_engine_update_property_cb (BusEngineProxy *engine, + IBusProperty *prop, + BusInputContext *context) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + g_assert (IBUS_IS_PROPERTY (prop)); + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + g_assert (priv->engine == engine); + + if (priv->capabilities & IBUS_CAP_PROPERTY) { + bus_input_context_send_signal (context, + "UpdateProperty", + IBUS_TYPE_PROPERTY, &prop, + G_TYPE_INVALID); + } + else { + g_signal_emit (context, + context_signals[UPDATE_PROPERTY], + 0, + prop); + } +} + +#define DEFINE_FUNCTION(name, Name, signal_name, cap) \ + static void \ + _engine_##name##_cb (BusEngineProxy *engine, \ + BusInputContext *context) \ + { \ + g_assert (BUS_IS_ENGINE_PROXY (engine)); \ + g_assert (BUS_IS_INPUT_CONTEXT (context)); \ + \ + BusInputContextPrivate *priv; \ + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); \ + \ + g_assert (priv->engine == engine); \ + \ + if ((priv->capabilities & (cap)) == (cap)) { \ + bus_input_context_send_signal (context, \ + #Name, \ + G_TYPE_INVALID); \ + } \ + else { \ + g_signal_emit (context, \ + context_signals[signal_name], \ + 0); \ + } \ +} + +DEFINE_FUNCTION (show_preedit_text, ShowPreeditText, SHOW_PREEDIT_TEXT, IBUS_CAP_PREEDIT_TEXT) +DEFINE_FUNCTION (hide_preedit_text, HidePreeditText, HIDE_PREEDIT_TEXT, IBUS_CAP_PREEDIT_TEXT) +DEFINE_FUNCTION (show_auxiliary_text, ShowAuxiliaryText, SHOW_AUXILIARY_TEXT, IBUS_CAP_AUXILIARY_TEXT) +DEFINE_FUNCTION (hide_auxiliary_text, HideAuxiliaryText, HIDE_AUXILIARY_TEXT, IBUS_CAP_AUXILIARY_TEXT) +DEFINE_FUNCTION (show_lookup_table, ShowLookupTable, SHOW_LOOKUP_TABLE, IBUS_CAP_LOOKUP_TABLE) +DEFINE_FUNCTION (hide_lookup_table, HideLookupTable, HIDE_LOOKUP_TABLE, IBUS_CAP_LOOKUP_TABLE) +DEFINE_FUNCTION (page_up_lookup_table, PageUpLookupTable, PAGE_UP_LOOKUP_TABLE, IBUS_CAP_LOOKUP_TABLE) +DEFINE_FUNCTION (page_down_lookup_table, PageDownLookupTable, PAGE_DOWN_LOOKUP_TABLE, IBUS_CAP_LOOKUP_TABLE) +DEFINE_FUNCTION (cursor_up_lookup_table, CursorUpLookupTable, CURSOR_UP_LOOKUP_TABLE, IBUS_CAP_LOOKUP_TABLE) +DEFINE_FUNCTION (cursor_down_lookup_table, CursorDownLookupTable, CURSOR_DOWN_LOOKUP_TABLE, IBUS_CAP_LOOKUP_TABLE) + +#undef DEFINE_FUNCTION + +void +bus_input_context_enable (BusInputContext *context) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + if (priv->engine == NULL) + return; + + priv->enabled = TRUE; + + bus_engine_proxy_enable (priv->engine); + bus_input_context_send_signal (context, + "Enabled", + G_TYPE_INVALID); + g_signal_emit (context, + context_signals[ENABLED], + 0); + if (priv->has_focus) { + bus_engine_proxy_focus_in (priv->engine); + } +} + +void +bus_input_context_disable (BusInputContext *context) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + priv->enabled = FALSE; + + if (priv->engine) { + if (priv->has_focus) { + bus_engine_proxy_focus_out (priv->engine); + } + bus_engine_proxy_disable (priv->engine); + } + + bus_input_context_send_signal (context, + "Disabled", + G_TYPE_INVALID); + g_signal_emit (context, + context_signals[DISABLED], + 0); +} + + +void +bus_input_context_set_engine (BusInputContext *context, + BusEngineProxy *engine) +{ + + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + if (priv->engine != NULL) { + g_signal_handlers_disconnect_by_func (priv->engine, _engine_destroy_cb, context); + ibus_object_destroy ((IBusObject *) priv->engine); + g_object_unref (priv->engine); + priv->engine = NULL; + } + + if (engine == NULL) { + bus_input_context_disable (context); + g_signal_emit (context, + context_signals[ENGINE_CHANGED], + 0); + return; + } + + priv->engine = engine; + g_object_ref (priv->engine); + + gint i; + const static struct { + const gchar *name; + GCallback callback; + } signals [] = { + { "commit-text", G_CALLBACK (_engine_commit_text_cb) }, + { "forward-key-event", G_CALLBACK (_engine_forward_key_event_cb) }, + { "update-preedit-text", G_CALLBACK (_engine_update_preedit_text_cb) }, + { "show-preedit-text", G_CALLBACK (_engine_show_preedit_text_cb) }, + { "hide-preedit-text", G_CALLBACK (_engine_hide_preedit_text_cb) }, + { "update-auxiliary-text", G_CALLBACK (_engine_update_auxiliary_text_cb) }, + { "show-auxiliary-text", G_CALLBACK (_engine_show_auxiliary_text_cb) }, + { "hide-auxiliary-text", G_CALLBACK (_engine_hide_auxiliary_text_cb) }, + { "update-lookup-table", G_CALLBACK (_engine_update_lookup_table_cb) }, + { "show-lookup-table", G_CALLBACK (_engine_show_lookup_table_cb) }, + { "hide-lookup-table", G_CALLBACK (_engine_hide_lookup_table_cb) }, + { "page-up-lookup-table", G_CALLBACK (_engine_page_up_lookup_table_cb) }, + { "page-down-lookup-table", G_CALLBACK (_engine_page_down_lookup_table_cb) }, + { "cursor-up-lookup-table", G_CALLBACK (_engine_cursor_up_lookup_table_cb) }, + { "cursor-down-lookup-table", G_CALLBACK (_engine_cursor_down_lookup_table_cb) }, + { "register-properties", G_CALLBACK (_engine_register_properties_cb) }, + { "update-property", G_CALLBACK (_engine_update_property_cb) }, + { "destroy", G_CALLBACK (_engine_destroy_cb) }, + { NULL, 0 } + }; + + for (i = 0; signals[i].name != NULL; i++) { + g_signal_connect (priv->engine, + signals[i].name, + signals[i].callback, + context); + } + + g_signal_emit (context, + context_signals[ENGINE_CHANGED], + 0); +} + +static gboolean +bus_input_context_filter_keyboard_shortcuts (BusInputContext *context, + guint keyval, + guint modifiers) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + static GQuark trigger; + static GQuark next_factory; + static GQuark prev_factory; + + GQuark event; + + if (trigger == 0) { + trigger = g_quark_from_static_string ("trigger"); + next_factory = g_quark_from_static_string ("next-engine"); + prev_factory = g_quark_from_static_string ("prev-engine"); + } + + event = ibus_hotkey_profile_filter_key_event (BUS_DEFAULT_HOTKEY_PROFILE, + keyval, + modifiers, + 0); + + if (event == trigger) { + if (priv->engine == NULL) { + g_signal_emit (context, context_signals[REQUEST_ENGINE], 0, NULL); + } + + if (priv->engine == NULL) { + return FALSE; + } + + if (priv->enabled) { + bus_input_context_disable (context); + } + else { + bus_input_context_enable (context); + } + + return TRUE; + } + else if (event == next_factory) { + return TRUE; + } + else if (event == prev_factory) { + return TRUE; + } + else + return FALSE; +} + + +static gboolean +bus_input_context_send_signal (BusInputContext *context, + const gchar *signal_name, + GType first_arg_type, + ...) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + g_assert (signal_name != NULL); + + va_list args; + gboolean retval; + IBusMessage *message; + BusInputContextPrivate *priv; + + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + g_assert (priv->connection != NULL); + + message = ibus_message_new_signal (ibus_service_get_path ((IBusService *)context), + IBUS_INTERFACE_INPUT_CONTEXT, + signal_name); + + ibus_message_set_sender (message, IBUS_SERVICE_IBUS); + + va_start (args, first_arg_type); + ibus_message_append_args_valist (message, first_arg_type, args); + va_end (args); + + retval = ibus_connection_send ((IBusConnection *)priv->connection, message); + ibus_message_unref (message); + + return retval; +} diff --git a/bus/inputcontext.h b/bus/inputcontext.h new file mode 100644 index 0000000..edebdc0 --- /dev/null +++ b/bus/inputcontext.h @@ -0,0 +1,82 @@ +/* vim:set et sts=4: */ +/* bus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __INPUT_CONTEXT_H_ +#define __INPUT_CONTEXT_H_ + +#include <ibus.h> +#include "connection.h" +#include "factoryproxy.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define BUS_TYPE_INPUT_CONTEXT \ + (bus_input_context_get_type ()) +#define BUS_INPUT_CONTEXT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUS_TYPE_INPUT_CONTEXT, BusInputContext)) +#define BUS_INPUT_CONTEXT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), BUS_TYPE_INPUT_CONTEXT, BusInputContextClass)) +#define BUS_IS_INPUT_CONTEXT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUS_TYPE_INPUT_CONTEXT)) +#define BUS_IS_INPUT_CONTEXT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), BUS_TYPE_INPUT_CONTEXT)) +#define BUS_INPUT_CONTEXT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), BUS_TYPE_INPUT_CONTEXT, BusInputContextClass)) + +G_BEGIN_DECLS + +typedef struct _BusInputContext BusInputContext; +typedef struct _BusInputContextClass BusInputContextClass; + +struct _BusInputContext { + IBusService parent; + /* instance members */ +}; + +struct _BusInputContextClass { + IBusServiceClass parent; + + /* class members */ +}; + +GType bus_input_context_get_type (void); +BusInputContext *bus_input_context_new (BusConnection *connection, + const gchar *client); +gboolean bus_input_context_is_focus (BusInputContext *context); +void bus_input_context_focus_in (BusInputContext *context); +void bus_input_context_focus_out (BusInputContext *context); +void bus_input_context_enable_or_disable(BusInputContext *context); +void bus_input_context_enable (BusInputContext *context); +void bus_input_context_disable (BusInputContext *context); +void bus_input_context_page_up (BusInputContext *context); +void bus_input_context_page_down (BusInputContext *context); +void bus_input_context_cursor_up (BusInputContext *context); +void bus_input_context_cursor_down (BusInputContext *context); +void bus_input_context_set_engine (BusInputContext *context, + BusEngineProxy *factory); +void bus_input_context_property_activate(BusInputContext *context, + const gchar *prop_name, + gint prop_state); + +G_END_DECLS +#endif + diff --git a/bus/main.c b/bus/main.c new file mode 100644 index 0000000..74e05d8 --- /dev/null +++ b/bus/main.c @@ -0,0 +1,148 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <unistd.h> +#include <stdlib.h> +#include <locale.h> +#include "server.h" +#include "ibusimpl.h" + +static gboolean daemonize = FALSE; +static gboolean single = FALSE; +static gboolean xim = FALSE; +static gchar *panel = "default"; +static gchar *config = "default"; +static gchar *desktop = "gnome"; +static gboolean verbose = FALSE; + +static const GOptionEntry entries[] = +{ + { "daemonize", 'd', 0, G_OPTION_ARG_NONE, &daemonize, "run ibus as background process.", NULL }, + { "single", 's', 0, G_OPTION_ARG_NONE, &single, "do not execute panel and config module.", NULL }, + { "xim", 'x', 0, G_OPTION_ARG_NONE, &xim, "execute ibus XIM server.", NULL }, + { "desktop", 'n', 0, G_OPTION_ARG_STRING, &desktop, "specify the name of desktop session. [default=gnome]", "name" }, + { "panel", 'p', 0, G_OPTION_ARG_STRING, &panel, "specify the cmdline of panel program.", "cmdline" }, + { "config", 'c', 0, G_OPTION_ARG_STRING, &config, "specify the cmdline of config program.", "cmdline" }, + { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "verbose.", NULL }, + { NULL }, +}; + +static gboolean +execute_cmdline (const gchar *cmdline) +{ + g_assert (cmdline); + + gint argc; + gchar **argv; + gboolean retval; + GError *error; + + error = NULL; + if (!g_shell_parse_argv (cmdline, &argc, &argv, &error)) { + g_warning ("Can not parse cmdline `%s` exec: %s", cmdline, error->message); + g_error_free (error); + return FALSE; + } + + error = NULL; + retval = g_spawn_async (NULL, argv, NULL, + G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, + NULL, &error); + g_strfreev (argv); + + if (!retval) { + g_warning ("Can not execute cmdline `%s`: %s", cmdline, error->message); + g_error_free (error); + return FALSE; + } + + return TRUE; +} + +gint +main (gint argc, gchar **argv) +{ + GOptionContext *context; + BusServer *server; + + GError *error = NULL; + + setlocale (LC_ALL, ""); + + context = g_option_context_new ("- ibus daemon"); + + g_option_context_add_main_entries (context, entries, "ibus-daemon"); + + if (!g_option_context_parse (context, &argc, &argv, &error)) { + g_printerr ("Option parsing failed: %s\n", error->message); + exit (-1); + } + + if (daemonize) { + if (daemon (1, 0) != 0) { + g_printerr ("Can not daemonize ibus.\n"); + exit (-1); + } + } + + g_type_init (); + + server = bus_server_get_default (); + bus_server_listen (server); + + if (!single) { + /* execute config component */ + if (g_strcmp0 (config, "default") == 0) { + IBusComponent *component; + component = bus_registry_lookup_component_by_name (BUS_DEFAULT_REGISTRY, IBUS_SERVICE_CONFIG); + if (component == NULL || !ibus_component_start (component)) { + g_printerr ("Can not execute default config program\n"); + exit (-1); + } + } else if (g_strcmp0 (config, "disable") != 0 && g_strcmp0 (config, "") != 0) { + if (!execute_cmdline (config)) + exit (-1); + } + + /* execut panel component */ + if (g_strcmp0 (panel, "default") == 0) { + IBusComponent *component; + component = bus_registry_lookup_component_by_name (BUS_DEFAULT_REGISTRY, IBUS_SERVICE_PANEL); + if (component == NULL || !ibus_component_start (component)) { + g_printerr ("Can not execute default panel program\n"); + exit (-1); + } + } else if (g_strcmp0 (panel, "disable") != 0 && g_strcmp0 (panel, "") != 0) { + if (!execute_cmdline (panel)) + exit (-1); + } + } + + /* execute ibus xim server */ + if (xim) { + if (!execute_cmdline (LIBEXECDIR"/ibus-x11 --kill-daemon")) + exit (-1); + } + + bus_server_run (server); + + return 0; +} diff --git a/bus/matchrule.c b/bus/matchrule.c new file mode 100644 index 0000000..6884fd6 --- /dev/null +++ b/bus/matchrule.c @@ -0,0 +1,672 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include <string.h> +#include "matchrule.h" + +#define BUS_CONFIG_PROXY_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), BUS_TYPE_CONFIG_PROXY, BusMatchRulePrivate)) + + +static void bus_match_rule_class_init (BusMatchRuleClass *klass); +static void bus_match_rule_init (BusMatchRule *rule); +static void bus_match_rule_destroy (BusMatchRule *rule); + +static IBusObjectClass *parent_class = NULL; + +GType +bus_match_rule_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (BusMatchRuleClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) bus_match_rule_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (BusMatchRule), + 0, + (GInstanceInitFunc) bus_match_rule_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_OBJECT, + "BusMatchRule", + &type_info, + (GTypeFlags)0); + } + return type; +} + +static void +bus_match_rule_class_init (BusMatchRuleClass *klass) +{ + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + + parent_class = (IBusObjectClass *) g_type_class_peek_parent (klass); + + ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_match_rule_destroy; +} + +static void +bus_match_rule_init (BusMatchRule *rule) +{ + rule->flags = 0; + rule->message_type = DBUS_MESSAGE_TYPE_INVALID; + rule->interface = NULL; + rule->member = NULL; + rule->sender = NULL; + rule->destination = NULL; + rule->path = NULL; + rule->args = g_array_new (TRUE, TRUE, sizeof (gchar *)); +} + +static void +bus_match_rule_destroy (BusMatchRule *rule) +{ + g_free (rule->interface); + g_free (rule->member); + g_free (rule->sender); + g_free (rule->destination); + g_free (rule->path); + + gint i; + GList *link; + + for (i = 0; i < rule->args->len; i++) { + g_free (g_array_index (rule->args, gchar *, i)); + } + g_array_free (rule->args, TRUE); + + for (link = rule->recipients; link != NULL; link = link->next) { + BusRecipient *recipient = (BusRecipient *) link->data; + g_object_unref (recipient->connection); + g_slice_free (BusRecipient, recipient); + } + g_list_free (rule->recipients); + + IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (rule)); +} + + +typedef struct _Token { + gchar *key; + gchar *value; +} Token; + +#define SKIP_WHITE(a) \ + while (*(a) == ' ' || *(a) == '\t') { (a)++; } +#define IS_ALPHA(a) \ + ((*(a) >= 'a' && *(a) <= 'z') || (*(a) >= 'A' && *(a) <= 'Z')) +#define IS_NUMBER(a) \ + (*(a) >= '0' && *(a) <= '9') + +static gchar * +find_key (const gchar **p) +{ + GString *text; + + text = g_string_new (""); + + SKIP_WHITE(*p) + if (!IS_ALPHA (*p)) + goto failed; + + g_string_append_c (text, **p); + (*p) ++; + + while (IS_ALPHA (*p) || IS_NUMBER (*p)) { + g_string_append_c (text, **p); + (*p) ++; + } + + return g_string_free (text, FALSE); + +failed: + g_string_free (text, TRUE); + return NULL; + +} + +static gchar * +find_value (const gchar **p) +{ + GString *text; + + text = g_string_new (""); + + SKIP_WHITE (*p); + + if (**p != '\'') + goto failed; + (*p) ++; + + while (**p != '\'') { + if (**p == '\0') + goto failed; + if (**p == '\\') + (*p) ++; + g_string_append_c (text, **p); + (*p) ++; + } + (*p) ++; + + return g_string_free (text, FALSE); + +failed: + g_string_free (text, TRUE); + return NULL; +} + +static Token * +tokenize_rule (const gchar *text) +{ + GArray *tokens; + Token token; + const gchar *p; + gint i; + + tokens = g_array_new (TRUE, TRUE, sizeof (Token)); + + p = text; + + while (*p != '\0') { + gchar *key; + gchar *value; + + SKIP_WHITE (p); + key = find_key (&p); + if (key == NULL) + goto failed; + SKIP_WHITE (p); + if (*p != '=') + goto failed; + p ++; + SKIP_WHITE (p); + value = find_value (&p); + if (value == NULL) { + g_free (key); + goto failed; + } + SKIP_WHITE (p); + if (*p != ',' && *p != '\0') { + g_free (key); + g_free (value); + goto failed; + } + + if (*p == ',') + p ++; + token.key = key; + token.value = value; + g_array_append_val (tokens, token); + } + + return (Token *)g_array_free (tokens, FALSE); + +failed: + + for (i = 0; i < tokens->len; i++) { + Token *p = &g_array_index (tokens, Token, i); + g_free (p->key); + g_free (p->value); + } + + g_array_free (tokens, TRUE); + return NULL; +} + +static void +tokens_free (Token *tokens) +{ + Token *p; + p = tokens; + + while (p != NULL && p->key != NULL) { + g_free (p->key); + g_free (p->value); + p ++; + } + g_free (tokens); +} + +static gboolean +_atoi (const gchar *text, gint *i) +{ + const gchar *p = text; + *i = 0; + while (*p != '\0') { + if (!IS_NUMBER(p)) + return FALSE; + *i = (*i) * 10 - '0' + *p; + p ++; + } + return TRUE; +} + +BusMatchRule * +bus_match_rule_new (const gchar *text) +{ + g_assert (text != NULL); + + Token *tokens, *p; + BusMatchRule *rule; + + rule = BUS_MATCH_RULE (g_object_new (BUS_TYPE_MATCH_RULE, NULL)); + + /* parse rule */ + tokens = tokenize_rule (text); + + for (p = tokens; p != NULL && p->key != 0; p++) { + if (g_strcmp0 (p->key, "type") == 0) { + if (g_strcmp0 (p->value, "signal") == 0) { + bus_match_rule_set_message_type (rule, DBUS_MESSAGE_TYPE_SIGNAL); + } + else if (g_strcmp0 (p->value, "method_call") == 0) { + bus_match_rule_set_message_type (rule, DBUS_MESSAGE_TYPE_METHOD_CALL); + } + else if (g_strcmp0 (p->value, "method_return") == 0) { + bus_match_rule_set_message_type (rule, DBUS_MESSAGE_TYPE_METHOD_RETURN); + } + else if (g_strcmp0 (p->value, "error") == 0) { + bus_match_rule_set_message_type (rule, DBUS_MESSAGE_TYPE_ERROR); + } + else + goto failed; + } + else if (g_strcmp0 (p->key, "sender") == 0) { + bus_match_rule_set_sender (rule, p->value); + } + else if (g_strcmp0 (p->key, "interface") == 0) { + bus_match_rule_set_interface (rule, p->value); + } + else if (g_strcmp0 (p->key, "member") == 0) { + bus_match_rule_set_member (rule, p->value); + } + else if (g_strcmp0 (p->key, "path") == 0) { + bus_match_rule_set_path (rule, p->value); + } + else if (g_strcmp0 (p->key, "destination") == 0) { + bus_match_rule_set_destination (rule, p->value); + } + else if (strncmp (p->key, "arg", 3) == 0) { + gint i; + if (! _atoi (p->key + 3, &i)) + goto failed; + bus_match_rule_set_arg (rule, i, p->value); + } + else + goto failed; + } + + tokens_free (tokens); + return rule; + +failed: + tokens_free (tokens); + g_object_unref (rule); + return NULL; +} + +gboolean +bus_match_rule_set_message_type (BusMatchRule *rule, + gint type) +{ + g_assert (rule != NULL); + g_assert (type == DBUS_MESSAGE_TYPE_SIGNAL || + type == DBUS_MESSAGE_TYPE_METHOD_CALL || + type == DBUS_MESSAGE_TYPE_METHOD_RETURN || + type == DBUS_MESSAGE_TYPE_ERROR); + + rule->flags |= MATCH_TYPE; + rule->message_type = type; + + return TRUE; +} + +gboolean +bus_match_rule_set_sender (BusMatchRule *rule, + const gchar *sender) +{ + g_assert (rule != NULL); + g_assert (sender != NULL); + + rule->flags |= MATCH_SENDER; + + g_free (rule->sender); + rule->sender = g_strdup (sender); + + return TRUE; +} + +gboolean +bus_match_rule_set_interface (BusMatchRule *rule, + const gchar *interface) +{ + g_assert (rule != NULL); + g_assert (interface != NULL); + + rule->flags |= MATCH_INTERFACE; + + g_free (rule->interface); + rule->interface = g_strdup (interface); + return TRUE; +} + +gboolean +bus_match_rule_set_member (BusMatchRule *rule, + const gchar *member) +{ + g_assert (rule != NULL); + g_assert (member != NULL); + + rule->flags |= MATCH_MEMBER; + + g_free (rule->member); + rule->member = g_strdup (member); + + return TRUE; +} + +gboolean +bus_match_rule_set_path (BusMatchRule *rule, + const gchar *path) +{ + g_assert (rule != NULL); + g_assert (path != NULL); + + rule->flags |= MATCH_PATH; + + g_free (rule->path); + rule->path = g_strdup (path); + + return TRUE; +} + +gboolean +bus_match_rule_set_destination (BusMatchRule *rule, + const gchar *dest) +{ + g_assert (rule != NULL); + g_assert (dest != NULL); + + rule->flags |= MATCH_DESTINATION; + + g_free (rule->destination); + rule->destination = g_strdup (dest); + + return TRUE; +} + +gboolean +bus_match_rule_set_arg (BusMatchRule *rule, + guint arg_i, + const gchar *arg) +{ + g_assert (rule != NULL); + g_assert (arg != NULL); + + rule->flags |= MATCH_ARGS; + + if (arg_i >= rule->args->len) { + g_array_set_size (rule->args, arg_i + 1); + } + + g_free (g_array_index (rule->args, gchar *, arg_i)); + g_array_index (rule->args, gchar *, arg_i) = g_strdup (arg); + return TRUE; +} + +gboolean +bus_match_rule_match (BusMatchRule *rule, + DBusMessage *message) +{ + g_assert (rule != NULL); + g_assert (message != NULL); + + if (rule->flags & MATCH_TYPE) { + if (ibus_message_get_type (message) != rule->message_type) + return FALSE; + } + + if (rule->flags & MATCH_INTERFACE) { + if (g_strcmp0 (ibus_message_get_interface (message), rule->interface) != 0) + return FALSE; + } + + if (rule->flags & MATCH_MEMBER) { + if (g_strcmp0 (ibus_message_get_member (message), rule->member) != 0) + return FALSE; + } + + if (rule->flags & MATCH_SENDER) { + if (g_strcmp0 (ibus_message_get_sender (message), rule->sender) != 0) + return FALSE; + } + + if (rule->flags & MATCH_DESTINATION) { + if (g_strcmp0 (ibus_message_get_destination (message), rule->destination) != 0) + return FALSE; + } + + if (rule->flags & MATCH_PATH) { + if (g_strcmp0 (ibus_message_get_path (message), rule->path) != 0) + return FALSE; + } + + if (rule->flags & MATCH_ARGS) { + guint i; + DBusMessageIter iter; + + ibus_message_iter_init (message, &iter); + + for (i = 0; i < rule->args->len; i++) { + gchar *arg = g_array_index (rule->args, gchar *, i); + if (arg != NULL) { + gint type; + gchar *value; + + type = ibus_message_iter_get_arg_type (&iter); + if (type != G_TYPE_STRING && type != IBUS_TYPE_OBJECT_PATH) + return FALSE; + + ibus_message_iter_get_basic (&iter, &value); + + if (g_strcmp0 (arg, value) != 0) + return FALSE; + } + ibus_message_iter_next (&iter); + } + } + return TRUE; +} + +gboolean +bus_match_rule_is_equal (BusMatchRule *a, + BusMatchRule *b) +{ + g_assert (a != NULL); + g_assert (b != NULL); + + if (a->flags != b->flags) + return FALSE; + + if (a->flags & MATCH_TYPE) { + if (a->message_type != b->message_type) + return FALSE; + } + + if (a->flags & MATCH_INTERFACE) { + if (g_strcmp0 (a->interface, b->interface) != 0) + return FALSE; + } + + if (a->flags & MATCH_MEMBER) { + if (g_strcmp0 (a->member, b->member) != 0) + return FALSE; + } + + if (a->flags & MATCH_SENDER) { + if (g_strcmp0 (a->sender, b->sender) != 0) + return FALSE; + } + + if (a->flags & MATCH_DESTINATION) { + if (g_strcmp0 (a->destination, b->destination) != 0) + return FALSE; + } + + if (a->flags & MATCH_PATH) { + if (g_strcmp0 (a->path, b->path) != 0) + return FALSE; + } + + if (a->flags & MATCH_ARGS) { + if (a->args->len != b->args->len) + return FALSE; + + gint i; + + for (i = 0; i < a->args->len; i++) { + if (g_strcmp0 (g_array_index (a->args, gchar *, i), + g_array_index (b->args, gchar *, i)) != 0) + return FALSE; + } + } + + return TRUE; +} + +static void +_connection_destroy_cb (BusConnection *connection, + BusMatchRule *rule) +{ + g_assert (BUS_IS_MATCH_RULE (rule)); + g_assert (BUS_IS_CONNECTION (connection)); + + GList *link; + BusRecipient *recipient; + + for (link = rule->recipients; link != NULL; link = link->next) { + recipient = (BusRecipient *)link->data; + + if (recipient->connection == connection) { + rule->recipients = g_list_remove_link (rule->recipients, link); + g_object_unref (connection); + g_slice_free (BusRecipient, recipient); + return; + } + + if (rule->recipients == NULL) { + ibus_object_destroy (IBUS_OBJECT (rule)); + } + } + g_assert_not_reached (); +} + +void +bus_match_rule_add_recipient (BusMatchRule *rule, + BusConnection *connection) +{ + g_assert (BUS_IS_MATCH_RULE (rule)); + g_assert (BUS_IS_CONNECTION (connection)); + + GList *link; + BusRecipient *recipient; + + for (link = rule->recipients; link != NULL; link = link->next) { + recipient = (BusRecipient *) link->data; + if (connection == recipient->connection) { + recipient->refcount ++; + return; + } + } + + recipient = g_slice_new (BusRecipient); + + g_object_ref (connection); + recipient->connection = connection; + recipient->refcount = 1; + + rule->recipients = g_list_append (rule->recipients, recipient); + g_signal_connect (connection, + "destroy", + G_CALLBACK (_connection_destroy_cb), + rule); +} + +void +bus_match_rule_remove_recipient (BusMatchRule *rule, + BusConnection *connection) +{ + g_assert (BUS_IS_MATCH_RULE (rule)); + g_assert (BUS_IS_CONNECTION (connection)); + + GList *link; + BusRecipient *recipient; + + for (link = rule->recipients; link != NULL; link = link->next) { + recipient = (BusRecipient *) link->data; + if (connection == recipient->connection) { + recipient->refcount --; + if (recipient->refcount == 0) { + rule->recipients = g_list_remove_link (rule->recipients, link); + g_slice_free (BusRecipient, recipient); + g_signal_handlers_disconnect_by_func (connection, + G_CALLBACK (_connection_destroy_cb), + rule); + g_object_unref (connection); + } + + if (rule->recipients == NULL ) { + ibus_object_destroy (IBUS_OBJECT(rule)); + } + return; + } + } + + g_warning ("Remove recipient failed"); +} + +gboolean +bus_match_rule_get_recipients (BusMatchRule *rule, + DBusMessage *message, + GList **recipients) +{ + g_assert (BUS_IS_MATCH_RULE (rule)); + g_assert (message != NULL); + g_assert (recipients != NULL); + + GList *link; + + if (!bus_match_rule_match (rule, message)) + return FALSE; + + for (link = rule->recipients; link != NULL; link = link->next) { + BusRecipient *recipient = (BusRecipient *) link->data; + + g_object_ref (recipient->connection); + *recipients = g_list_append (*recipients, recipient->connection); + } + + return TRUE; +} + diff --git a/bus/matchrule.h b/bus/matchrule.h new file mode 100644 index 0000000..e8aaf39 --- /dev/null +++ b/bus/matchrule.h @@ -0,0 +1,124 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __MATCH_RULE_H_ +#define __MATCH_RULE_H_ + +#include <ibus.h> +#include "connection.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define BUS_TYPE_MATCH_RULE \ + (bus_match_rule_get_type ()) +#define BUS_MATCH_RULE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUS_TYPE_MATCH_RULE, BusMatchRule)) +#define BUS_MATCH_RULE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), BUS_TYPE_MATCH_RULE, BusMatchRuleClass)) +#define BUS_IS_MATCH_RULE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUS_TYPE_MATCH_RULE)) +#define BUS_IS_MATCH_RULE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), BUS_TYPE_MATCH_RULE)) +#define BUS_MATCH_RULE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), BUS_TYPE_MATCH_RULE, BusMatchRuleClass)) + +G_BEGIN_DECLS + +typedef struct _BusMatchRule BusMatchRule; +typedef struct _BusMatchRuleClass BusMatchRuleClass; + +typedef enum { + MATCH_TYPE = 1 << 0, + MATCH_INTERFACE = 1 << 1, + MATCH_MEMBER = 1 << 2, + MATCH_SENDER = 1 << 3, + MATCH_DESTINATION = 1 << 4, + MATCH_PATH = 1 << 5, + MATCH_ARGS = 1 << 6, +} BusMatchFlags; + +typedef struct _BusRecipient BusRecipient; +struct _BusRecipient { + BusConnection *connection; + gint refcount; +}; + +struct _BusMatchRule { + IBusProxy parent; + /* instance members */ + gint flags; + gint message_type; + gchar *interface; + gchar *member; + gchar *sender; + gchar *destination; + gchar *path; + GArray *args; + GList *recipients; +}; + +struct _BusMatchRuleClass { + IBusProxyClass parent; + /* class members */ +}; + +GType bus_match_rule_get_type (void); +BusMatchRule *bus_match_rule_new (const gchar *text); +BusMatchRule *bus_match_rule_ref (BusMatchRule *rule); +void bus_match_rule_unref (BusMatchRule *rule); +void bus_match_rule_free (BusMatchRule *rule); +gboolean bus_match_rule_set_message_type + (BusMatchRule *rule, + gint type); +gboolean bus_match_rule_set_sender (BusMatchRule *rule, + const gchar *sender); +gboolean bus_match_rule_set_interface + (BusMatchRule *rule, + const gchar *interface); +gboolean bus_match_rule_set_member (BusMatchRule *rule, + const gchar *member); +gboolean bus_match_rule_set_path (BusMatchRule *rule, + const gchar *path); +gboolean bus_match_rule_set_destination + (BusMatchRule *rule, + const gchar *dest); +gboolean bus_match_rule_set_arg (BusMatchRule *rule, + guint arg_i, + const gchar *arg); +gboolean bus_match_rule_match (BusMatchRule *rule, + DBusMessage *message); +gboolean bus_match_rule_is_equal (BusMatchRule *a, + BusMatchRule *b); +void bus_match_rule_add_recipient + (BusMatchRule *rule, + BusConnection *connection); +void bus_match_rule_remove_recipient + (BusMatchRule *rule, + BusConnection *connection); +gboolean bus_match_rule_get_recipients + (BusMatchRule *rule, + DBusMessage *message, + GList **recipients); + +G_END_DECLS +#endif + diff --git a/bus/panelproxy.c b/bus/panelproxy.c new file mode 100644 index 0000000..7d99f67 --- /dev/null +++ b/bus/panelproxy.c @@ -0,0 +1,757 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <ibusinternal.h> +#include <ibusmarshalers.h> +#include "panelproxy.h" + +#define BUS_PANEL_PROXY_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), BUS_TYPE_PANEL_PROXY, BusPanelProxyPrivate)) + +enum { + PAGE_UP, + PAGE_DOWN, + CURSOR_UP, + CURSOR_DOWN, + PROPERTY_ACTIVATE, + PROPERTY_SHOW, + PROPERTY_HIDE, + LAST_SIGNAL, +}; + + +/* BusPanelProxyPriv */ +struct _BusPanelProxyPrivate { + BusInputContext *focused_context; +}; +typedef struct _BusPanelProxyPrivate BusPanelProxyPrivate; + +static guint panel_signals[LAST_SIGNAL] = { 0 }; +// static guint engine_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void bus_panel_proxy_class_init (BusPanelProxyClass *klass); +static void bus_panel_proxy_init (BusPanelProxy *panel); +static void bus_panel_proxy_real_destroy (BusPanelProxy *panel); + +static gboolean bus_panel_proxy_ibus_signal (IBusProxy *proxy, + IBusMessage *message); +static void bus_panel_proxy_page_up (BusPanelProxy *panel); +static void bus_panel_proxy_page_down (BusPanelProxy *panel); +static void bus_panel_proxy_cursor_up (BusPanelProxy *panel); +static void bus_panel_proxy_cursor_down (BusPanelProxy *panel); +static void bus_panel_proxy_property_activate + (BusPanelProxy *panel, + const gchar *prop_name, + gint prop_state); + +static IBusProxyClass *parent_class = NULL; + +struct _SignalCallbackTable { + gchar *name; + GCallback callback; +} ; + +static const struct _SignalCallbackTable __signals[]; + +GType +bus_panel_proxy_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (BusPanelProxyClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) bus_panel_proxy_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (BusPanelProxy), + 0, + (GInstanceInitFunc) bus_panel_proxy_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_PROXY, + "BusPanelProxy", + &type_info, + (GTypeFlags)0); + } + return type; +} + +BusPanelProxy * +bus_panel_proxy_new (BusConnection *connection) +{ + g_assert (BUS_IS_CONNECTION (connection)); + + GObject *obj; + obj = g_object_new (BUS_TYPE_PANEL_PROXY, + "name", NULL, + "path", IBUS_PATH_PANEL, + "connection", connection, + NULL); + + return BUS_PANEL_PROXY (obj); +} + +static void +bus_panel_proxy_class_init (BusPanelProxyClass *klass) +{ + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + IBusProxyClass *proxy_class = IBUS_PROXY_CLASS (klass); + + + parent_class = (IBusProxyClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (BusPanelProxyPrivate)); + + klass->page_up = bus_panel_proxy_page_up; + klass->page_down = bus_panel_proxy_page_down; + klass->cursor_up = bus_panel_proxy_cursor_up; + klass->cursor_down = bus_panel_proxy_cursor_down; + + klass->property_activate = bus_panel_proxy_property_activate; + + ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_panel_proxy_real_destroy; + + proxy_class->ibus_signal = bus_panel_proxy_ibus_signal; + + /* install signals */ + panel_signals[PAGE_UP] = + g_signal_new (I_("page-up"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(BusPanelProxyClass, page_up), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + panel_signals[PAGE_DOWN] = + g_signal_new (I_("page-down"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(BusPanelProxyClass, page_down), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + panel_signals[CURSOR_UP] = + g_signal_new (I_("cursor-up"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(BusPanelProxyClass, cursor_up), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + panel_signals[CURSOR_DOWN] = + g_signal_new (I_("cursor-down"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(BusPanelProxyClass, cursor_down), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + panel_signals[PROPERTY_ACTIVATE] = + g_signal_new (I_("property-activate"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(BusPanelProxyClass, property_activate), + NULL, NULL, + ibus_marshal_VOID__STRING_INT, + G_TYPE_NONE, 2, + G_TYPE_STRING, + G_TYPE_INT); + + panel_signals[PROPERTY_SHOW] = + g_signal_new (I_("property-show"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + panel_signals[PROPERTY_HIDE] = + g_signal_new (I_("property-hide"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + +} + +static void +bus_panel_proxy_init (BusPanelProxy *panel) +{ + BusPanelProxyPrivate *priv; + priv = BUS_PANEL_PROXY_GET_PRIVATE (panel); + + priv->focused_context = NULL; +} + +static void +bus_panel_proxy_real_destroy (BusPanelProxy *panel) +{ + BusPanelProxyPrivate *priv; + priv = BUS_PANEL_PROXY_GET_PRIVATE (panel); + + if (ibus_proxy_get_connection ((IBusProxy *)panel) != NULL) { + ibus_proxy_call ((IBusProxy *) panel, + "Destroy", + DBUS_TYPE_INVALID); + } + + if (priv->focused_context) { + bus_panel_proxy_focus_out (panel, priv->focused_context); + priv->focused_context = NULL; + } + + IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (panel)); +} + +static gboolean +bus_panel_proxy_ibus_signal (IBusProxy *proxy, + IBusMessage *message) +{ + g_assert (BUS_IS_PANEL_PROXY (proxy)); + g_assert (message != NULL); + + BusPanelProxy *panel; + IBusError *error; + gint i; + + static const struct { + const gchar *member; + const guint signal_id; + } signals [] = { + { "PageUp", PAGE_UP }, + { "PageDown", PAGE_DOWN }, + { "CursorUp", CURSOR_UP }, + { "CursorDown", CURSOR_DOWN }, + { NULL, 0}, + }; + + panel = BUS_PANEL_PROXY (proxy); + + for (i = 0; ; i++) { + if (signals[i].member == NULL) + break; + if (ibus_message_is_signal (message, IBUS_INTERFACE_PANEL, signals[i].member)) { + g_signal_emit (panel, panel_signals[signals[i].signal_id], 0); + goto handled; + } + } + + if (ibus_message_is_signal (message, IBUS_INTERFACE_PANEL, "PropertyActivate")) { + gchar *prop_name; + gint prop_state; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_STRING, &prop_name, + G_TYPE_INT, &prop_state, + G_TYPE_INVALID); + if (!retval) + goto failed; + + g_signal_emit (panel, panel_signals[PROPERTY_ACTIVATE], 0, prop_name, prop_state); + } + else if (ibus_message_is_signal (message, IBUS_INTERFACE_PANEL, "PropertyShow")) { + gchar *prop_name; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_STRING, &prop_name, + G_TYPE_INVALID); + if (!retval) + goto failed; + g_signal_emit (panel, panel_signals[PROPERTY_SHOW], 0, prop_name); + } + else if (ibus_message_is_signal (message, IBUS_INTERFACE_PANEL, "PropertyHide")) { + gchar *prop_name; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_STRING, &prop_name, + G_TYPE_INVALID); + if (!retval) + goto failed; + g_signal_emit (panel, panel_signals[PROPERTY_HIDE], 0, prop_name); + } + +handled: + g_signal_stop_emission_by_name (panel, "ibus-signal"); + return TRUE; + +failed: + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + return FALSE; +} + + +void +bus_panel_proxy_focus_in (BusPanelProxy *panel, + BusInputContext *context) +{ + g_assert (BUS_IS_PANEL_PROXY (panel)); + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusPanelProxyPrivate *priv; + priv = BUS_PANEL_PROXY_GET_PRIVATE (panel); + + if (priv->focused_context == context) + return; + + if (priv->focused_context != NULL) + bus_panel_proxy_focus_out (panel, priv->focused_context); + + g_object_ref (context); + priv->focused_context = context; + + const gchar *path = ibus_service_get_path ((IBusService *)context); + + ibus_proxy_call ((IBusProxy *) panel, + "FocusIn", + IBUS_TYPE_OBJECT_PATH, &path, + G_TYPE_INVALID); + + /* install signal handlers */ + gint i; + for (i = 0; __signals[i].name != NULL; i++) { + g_signal_connect (context, + __signals[i].name, + __signals[i].callback, + panel); + } +} + +void +bus_panel_proxy_focus_out (BusPanelProxy *panel, + BusInputContext *context) +{ + g_assert (BUS_IS_PANEL_PROXY (panel)); + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusPanelProxyPrivate *priv; + priv = BUS_PANEL_PROXY_GET_PRIVATE (panel); + + g_assert (priv->focused_context == context); + + /* uninstall signal handlers */ + gint i; + for (i = 0; __signals[i].name != NULL; i++) { + g_signal_handlers_disconnect_by_func (context, + __signals[i].callback, + panel); + } + + const gchar *path = ibus_service_get_path ((IBusService *)context); + + ibus_proxy_call ((IBusProxy *) panel, + "FocusOut", + IBUS_TYPE_OBJECT_PATH, &path, + G_TYPE_INVALID); + + g_object_unref (priv->focused_context); + priv->focused_context = NULL; +} + +void +bus_panel_proxy_set_cursor_location (BusPanelProxy *panel, + gint x, + gint y, + gint w, + gint h) +{ + g_assert (BUS_IS_PANEL_PROXY (panel)); + + ibus_proxy_call ((IBusProxy *) panel, + "SetCursorLocation", + G_TYPE_INT, &x, + G_TYPE_INT, &y, + G_TYPE_INT, &w, + G_TYPE_INT, &h, + G_TYPE_INVALID); +} + +void +bus_panel_proxy_update_preedit_text (BusPanelProxy *panel, + IBusText *text, + guint cursor_pos, + gboolean visible) +{ + g_assert (BUS_IS_PANEL_PROXY (panel)); + g_assert (text != NULL); + + ibus_proxy_call ((IBusProxy *) panel, + "UpdatePreeditText", + IBUS_TYPE_TEXT, &text, + G_TYPE_UINT, &cursor_pos, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); +} + +void +bus_panel_proxy_update_auxiliary_text (BusPanelProxy *panel, + IBusText *text, + gboolean visible) +{ + g_assert (BUS_IS_PANEL_PROXY (panel)); + g_assert (text != NULL); + + ibus_proxy_call ((IBusProxy *) panel, + "UpdateAuxiliaryText", + IBUS_TYPE_TEXT, &text, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); +} + +void +bus_panel_proxy_update_lookup_table (BusPanelProxy *panel, + IBusLookupTable *table, + gboolean visible) +{ + g_assert (BUS_IS_PANEL_PROXY (panel)); + g_assert (table != NULL); + + ibus_proxy_call ((IBusProxy *) panel, + "UpdateLookupTable", + IBUS_TYPE_LOOKUP_TABLE, &table, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); +} + +void +bus_panel_proxy_register_properties (BusPanelProxy *panel, + IBusPropList *prop_list) +{ + g_assert (BUS_IS_PANEL_PROXY (panel)); + g_assert (prop_list != NULL); + + ibus_proxy_call ((IBusProxy *) panel, + "RegisterProperties", + IBUS_TYPE_PROP_LIST, &prop_list, + G_TYPE_INVALID); + ibus_connection_flush (ibus_proxy_get_connection((IBusProxy *)panel)); +} + +void +bus_panel_proxy_update_property (BusPanelProxy *panel, + IBusProperty *prop) +{ + g_assert (BUS_IS_PANEL_PROXY (panel)); + g_assert (prop != NULL); + + ibus_proxy_call ((IBusProxy *) panel, + "UpdateProperty", + IBUS_TYPE_PROPERTY, &prop, + G_TYPE_INVALID); +} + +static void +bus_panel_proxy_page_up (BusPanelProxy *panel) +{ + g_assert (BUS_IS_PANEL_PROXY (panel)); + + BusPanelProxyPrivate *priv; + priv = BUS_PANEL_PROXY_GET_PRIVATE (panel); + + if (priv->focused_context) { + bus_input_context_page_up (priv->focused_context); + } +} + +static void +bus_panel_proxy_page_down (BusPanelProxy *panel) +{ + g_assert (BUS_IS_PANEL_PROXY (panel)); + + BusPanelProxyPrivate *priv; + priv = BUS_PANEL_PROXY_GET_PRIVATE (panel); + + if (priv->focused_context) { + bus_input_context_page_down (priv->focused_context); + } +} +static void +bus_panel_proxy_cursor_up (BusPanelProxy *panel) +{ + g_assert (BUS_IS_PANEL_PROXY (panel)); + + BusPanelProxyPrivate *priv; + priv = BUS_PANEL_PROXY_GET_PRIVATE (panel); + + if (priv->focused_context) { + bus_input_context_cursor_up (priv->focused_context); + } +} + +static void +bus_panel_proxy_cursor_down (BusPanelProxy *panel) +{ + g_assert (BUS_IS_PANEL_PROXY (panel)); + + BusPanelProxyPrivate *priv; + priv = BUS_PANEL_PROXY_GET_PRIVATE (panel); + + if (priv->focused_context) { + bus_input_context_cursor_down (priv->focused_context); + } +} + +static void +bus_panel_proxy_property_activate (BusPanelProxy *panel, + const gchar *prop_name, + gint prop_state) +{ + g_assert (BUS_IS_PANEL_PROXY (panel)); + + BusPanelProxyPrivate *priv; + priv = BUS_PANEL_PROXY_GET_PRIVATE (panel); + + if (priv->focused_context) { + bus_input_context_property_activate (priv->focused_context, prop_name, prop_state); + } +} + +#define DEFINE_FUNCTION(Name, name) \ + void bus_panel_proxy_##name (BusPanelProxy *panel) \ + { \ + g_assert (BUS_IS_PANEL_PROXY (panel)); \ + ibus_proxy_call ((IBusProxy *) panel, \ + #Name, \ + G_TYPE_INVALID); \ + } + +DEFINE_FUNCTION (ShowPreeditText, show_preedit_text) +DEFINE_FUNCTION (HidePreeditText, hide_preedit_text) +DEFINE_FUNCTION (ShowAuxiliaryText, show_auxiliary_text) +DEFINE_FUNCTION (HideAuxiliaryText, hide_auxiliary_text) +DEFINE_FUNCTION (ShowLookupTable, show_lookup_table) +DEFINE_FUNCTION (HideLookupTable, hide_lookup_table) +DEFINE_FUNCTION (PageUpLookupTable, page_up_lookup_table) +DEFINE_FUNCTION (PageDownLookupTable, page_down_lookup_table) +DEFINE_FUNCTION (CursorUpLookupTable, cursor_up_lookup_table) +DEFINE_FUNCTION (CursorDownLookupTable, cursor_down_lookup_table) +DEFINE_FUNCTION (StateChanged, state_changed) + +#undef DEFINE_FUNCTION + +static void +_context_set_cursor_location_cb (BusInputContext *context, + gint x, + gint y, + gint w, + gint h, + BusPanelProxy *panel) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + g_assert (BUS_IS_PANEL_PROXY (panel)); + + BusPanelProxyPrivate *priv; + priv = BUS_PANEL_PROXY_GET_PRIVATE (panel); + + g_return_if_fail (priv->focused_context == context); + + bus_panel_proxy_set_cursor_location (panel, x, y, w, h); +} + +static void +_context_update_preedit_text_cb (BusInputContext *context, + IBusText *text, + guint cursor_pos, + gboolean visible, + BusPanelProxy *panel) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + g_assert (text != NULL); + g_assert (BUS_IS_PANEL_PROXY (panel)); + + BusPanelProxyPrivate *priv; + priv = BUS_PANEL_PROXY_GET_PRIVATE (panel); + + g_return_if_fail (priv->focused_context == context); + + bus_panel_proxy_update_preedit_text (panel, + text, + cursor_pos, + visible); +} + +static void +_context_update_auxiliary_text_cb (BusInputContext *context, + IBusText *text, + gboolean visible, + BusPanelProxy *panel) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + g_assert (BUS_IS_PANEL_PROXY (panel)); + + BusPanelProxyPrivate *priv; + priv = BUS_PANEL_PROXY_GET_PRIVATE (panel); + + g_return_if_fail (priv->focused_context == context); + + bus_panel_proxy_update_auxiliary_text (panel, + text, + visible); +} + +static void +_context_update_lookup_table_cb (BusInputContext *context, + IBusLookupTable *table, + gboolean visible, + BusPanelProxy *panel) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + g_assert (BUS_IS_PANEL_PROXY (panel)); + + BusPanelProxyPrivate *priv; + priv = BUS_PANEL_PROXY_GET_PRIVATE (panel); + + g_return_if_fail (priv->focused_context == context); + + bus_panel_proxy_update_lookup_table (panel, + table, + visible); +} + +static void +_context_register_properties_cb (BusInputContext *context, + IBusPropList *prop_list, + BusPanelProxy *panel) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + g_assert (BUS_IS_PANEL_PROXY (panel)); + + BusPanelProxyPrivate *priv; + priv = BUS_PANEL_PROXY_GET_PRIVATE (panel); + + g_return_if_fail (priv->focused_context == context); + + bus_panel_proxy_register_properties (panel, + prop_list); +} + +static void +_context_update_property_cb (BusInputContext *context, + IBusProperty *prop, + BusPanelProxy *panel) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + g_assert (BUS_IS_PANEL_PROXY (panel)); + + BusPanelProxyPrivate *priv; + priv = BUS_PANEL_PROXY_GET_PRIVATE (panel); + + g_return_if_fail (priv->focused_context == context); + + bus_panel_proxy_update_property (panel, + prop); +} + +#if 0 +static void +_context_destroy_cb (BusInputContext *context, + BusPanelProxy *panel) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + g_assert (BUS_IS_PANEL_PROXY (panel)); + + BusPanelProxyPrivate *priv; + priv = BUS_PANEL_PROXY_GET_PRIVATE (panel); + + g_assert (context == priv->focused_context); + + bus_panel_proxy_focus_out (panel, context); +} +#endif + +#define DEFINE_FUNCTION(name) \ + static void _context_##name##_cb (BusInputContext *context, \ + BusPanelProxy *panel) \ + { \ + g_assert (BUS_IS_INPUT_CONTEXT (context)); \ + g_assert (BUS_IS_PANEL_PROXY (panel)); \ + \ + BusPanelProxyPrivate *priv; \ + priv = BUS_PANEL_PROXY_GET_PRIVATE (panel); \ + \ + g_return_if_fail (priv->focused_context == context); \ + \ + bus_panel_proxy_##name (panel); \ + } + +DEFINE_FUNCTION (show_preedit_text) +DEFINE_FUNCTION (hide_preedit_text) +DEFINE_FUNCTION (show_auxiliary_text) +DEFINE_FUNCTION (hide_auxiliary_text) +DEFINE_FUNCTION (show_lookup_table) +DEFINE_FUNCTION (hide_lookup_table) +DEFINE_FUNCTION (page_up_lookup_table) +DEFINE_FUNCTION (page_down_lookup_table) +DEFINE_FUNCTION (cursor_up_lookup_table) +DEFINE_FUNCTION (cursor_down_lookup_table) +DEFINE_FUNCTION (state_changed) + +#undef DEFINE_FUNCTION + +static const struct _SignalCallbackTable +__signals[] = { + { "set-cursor-location", G_CALLBACK (_context_set_cursor_location_cb) }, + + { "update-preedit-text", G_CALLBACK (_context_update_preedit_text_cb) }, + { "show-preedit-text", G_CALLBACK (_context_show_preedit_text_cb) }, + { "hide-preedit-text", G_CALLBACK (_context_hide_preedit_text_cb) }, + + { "update-auxiliary-text", G_CALLBACK (_context_update_auxiliary_text_cb) }, + { "show-auxiliary-text", G_CALLBACK (_context_show_auxiliary_text_cb) }, + { "hide-auxiliary-text", G_CALLBACK (_context_hide_auxiliary_text_cb) }, + + { "update-lookup-table", G_CALLBACK (_context_update_lookup_table_cb) }, + { "show-lookup-table", G_CALLBACK (_context_show_lookup_table_cb) }, + { "hide-lookup-table", G_CALLBACK (_context_hide_lookup_table_cb) }, + { "page-up-lookup-table", G_CALLBACK (_context_page_up_lookup_table_cb) }, + { "page-down-lookup-table", G_CALLBACK (_context_page_down_lookup_table_cb) }, + { "cursor-up-lookup-table", G_CALLBACK (_context_cursor_up_lookup_table_cb) }, + { "cursor-down-lookup-table", G_CALLBACK (_context_cursor_down_lookup_table_cb) }, + + { "register-properties", G_CALLBACK (_context_register_properties_cb) }, + { "update-property", G_CALLBACK (_context_update_property_cb) }, + + { "enabled", G_CALLBACK (_context_state_changed_cb) }, + { "disabled", G_CALLBACK (_context_state_changed_cb) }, + { "factory-changed", G_CALLBACK (_context_state_changed_cb) }, + + // { "destroy", G_CALLBACK (_context_destroy_cb) }, + { NULL, NULL} +}; + diff --git a/bus/panelproxy.h b/bus/panelproxy.h new file mode 100644 index 0000000..0ecc4a7 --- /dev/null +++ b/bus/panelproxy.h @@ -0,0 +1,112 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __PANEL_PROXY_H_ +#define __PANEL_PROXY_H_ + +#include <ibus.h> +#include "connection.h" +#include "inputcontext.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define BUS_TYPE_PANEL_PROXY \ + (bus_panel_proxy_get_type ()) +#define BUS_PANEL_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUS_TYPE_PANEL_PROXY, BusPanelProxy)) +#define BUS_PANEL_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), BUS_TYPE_PANEL_PROXY, BusPanelProxyClass)) +#define BUS_IS_PANEL_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUS_TYPE_PANEL_PROXY)) +#define BUS_IS_PANEL_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), BUS_TYPE_PANEL_PROXY)) +#define BUS_PANEL_PROXY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), BUS_TYPE_PANEL_PROXY, BusPanelProxyClass)) + +G_BEGIN_DECLS + +typedef struct _BusPanelProxy BusPanelProxy; +typedef struct _BusPanelProxyClass BusPanelProxyClass; + +struct _BusPanelProxy { + IBusProxy parent; + /* instance members */ +}; + +struct _BusPanelProxyClass { + IBusProxyClass parent; + /* class members */ + + void (* page_up) (BusPanelProxy *panel); + void (* page_down) (BusPanelProxy *panel); + void (* cursor_up) (BusPanelProxy *panel); + void (* cursor_down) (BusPanelProxy *panel); + + void (* property_activate) (BusPanelProxy *panel, + const gchar *prop_name, + gint prop_state); +}; + +GType bus_panel_proxy_get_type (void); +BusPanelProxy *bus_panel_proxy_new (BusConnection *connection); +void bus_panel_proxy_focus_in (BusPanelProxy *panel, + BusInputContext *context); +void bus_panel_proxy_focus_out (BusPanelProxy *panel, + BusInputContext *context); +void bus_panel_proxy_set_cursor_location + (BusPanelProxy *panel, + gint32 x, + gint32 y, + gint32 w, + gint32 h); +void bus_panel_proxy_update_preedit_text(BusPanelProxy *panel, + IBusText *text, + guint cursor_pos, + gboolean visible); +void bus_panel_proxy_show_preedit_text (BusPanelProxy *panel); +void bus_panel_proxy_hide_preedit_text (BusPanelProxy *panel); +void bus_panel_proxy_update_auxiliary_text + (BusPanelProxy *panel, + IBusText *text, + gboolean visible); +void bus_panel_proxy_show_auxiliary_text(BusPanelProxy *panel); +void bus_panel_proxy_hide_auxiliary_text(BusPanelProxy *panel); +void bus_panel_proxy_update_lookup_table(BusPanelProxy *panel, + IBusLookupTable *table, + gboolean visible); +void bus_panel_proxy_show_lookup_table (BusPanelProxy *panel); +void bus_panel_proxy_hide_lookup_table (BusPanelProxy *panel); +void bus_panel_proxy_page_up_lookup_table + (BusPanelProxy *panel); +void bus_panel_proxy_page_down_lookup_table + (BusPanelProxy *panel); +void bus_panel_proxy_cursor_up_lookup_table + (BusPanelProxy *panel); +void bus_panel_proxy_cursor_down_lookup_table + (BusPanelProxy *panel); +void bus_panel_proxy_register_properties(BusPanelProxy *panel, + IBusPropList *prop_list); +void bus_panel_proxy_update_property (BusPanelProxy *panel, + IBusProperty *prop); +G_END_DECLS +#endif + diff --git a/bus/registry.c b/bus/registry.c new file mode 100644 index 0000000..cdc1aa7 --- /dev/null +++ b/bus/registry.c @@ -0,0 +1,447 @@ +/* vim:set et sts=4: */ +/* bus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include <glib/gstdio.h> +#include <gio/gio.h> +#include <stdlib.h> +#include "registry.h" + +enum { + LAST_SIGNAL, +}; + +// static guint _signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void bus_registry_class_init (BusRegistryClass *klass); +static void bus_registry_init (BusRegistry *registry); +static void bus_registry_destroy (BusRegistry *registry); +static void bus_registry_load (BusRegistry *registry); +static void bus_registry_load_in_dir (BusRegistry *registry, + const gchar *dirname); +static gboolean bus_registry_save_cache (BusRegistry *registry); +static gboolean bus_registry_load_cache (BusRegistry *registry); +static gboolean bus_registry_check_modification(BusRegistry *registry); +static void bus_registry_remove_all (BusRegistry *registry); + +static IBusObjectClass *parent_class = NULL; + +GType +bus_registry_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (BusRegistryClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) bus_registry_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (BusRegistry), + 0, + (GInstanceInitFunc) bus_registry_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_OBJECT, + "BusRegistry", + &type_info, + (GTypeFlags)0); + } + + return type; +} + + +static void +bus_registry_class_init (BusRegistryClass *klass) +{ + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + + parent_class = (IBusObjectClass *) g_type_class_peek_parent (klass); + + ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_registry_destroy; +} + +static void +bus_registry_init (BusRegistry *registry) +{ + GList *p; + registry->observed_paths = NULL; + registry->components = NULL; + registry->engine_table = g_hash_table_new (g_str_hash, g_str_equal); + + if (bus_registry_load_cache (registry) == FALSE || bus_registry_check_modification (registry)) { + bus_registry_remove_all (registry); + bus_registry_load (registry); + bus_registry_save_cache (registry); + } + + for (p = registry->components; p != NULL; p = p->next) { + IBusComponent *comp = (IBusComponent *)p->data; + GList *p1; + + for (p1 = comp->engines; p1 != NULL; p1 = p1->next) { + IBusEngineDesc *desc = (IBusEngineDesc *)p1->data; + g_hash_table_insert (registry->engine_table, desc->name, desc); + g_object_set_data ((GObject *)desc, "component", comp); + } + } +} + +static void +bus_registry_remove_all (BusRegistry *registry) +{ + g_list_foreach (registry->observed_paths, (GFunc) g_object_unref, NULL); + g_list_free (registry->observed_paths); + registry->observed_paths = NULL; + + g_list_foreach (registry->components, (GFunc) g_object_unref, NULL); + g_list_free (registry->components); + registry->components = NULL; + + g_hash_table_remove_all (registry->engine_table); +} + +static void +bus_registry_destroy (BusRegistry *registry) +{ + bus_registry_remove_all (registry); + + g_hash_table_destroy (registry->engine_table); + registry->engine_table = NULL; + + IBUS_OBJECT_CLASS (parent_class)->destroy (IBUS_OBJECT (registry)); +} + + +static void +bus_registry_load (BusRegistry *registry) +{ + g_assert (BUS_IS_REGISTRY (registry)); + + gchar *dirname; + gchar *homedir; + IBusObservedPath *path; + + dirname = g_build_filename (PKGDATADIR, "component", NULL); + + path = ibus_observed_path_new (dirname, TRUE); + registry->observed_paths = g_list_append (registry->observed_paths, path); + + bus_registry_load_in_dir (registry, dirname); + + g_free (dirname); + + homedir = (gchar *) g_getenv ("HOME"); + if (!homedir) + homedir = (gchar *) g_get_home_dir (); + dirname = g_build_filename (homedir, ".ibus", "component", NULL); + + path = ibus_observed_path_new (dirname, TRUE); + registry->observed_paths = g_list_append (registry->observed_paths, path); + + if (g_file_test(dirname, G_FILE_TEST_EXISTS)) { + bus_registry_load_in_dir (registry, dirname); + } + + g_free (dirname); +} + + +#define g_string_append_indent(string, indent) \ + { \ + gint i; \ + for (i = 0; i < (indent); i++) { \ + g_string_append (string, " "); \ + } \ + } + +static gboolean +bus_registry_load_cache (BusRegistry *registry) +{ + g_assert (BUS_IS_REGISTRY (registry)); + + gchar *filename; + XMLNode *node; + GList *p; + + filename = g_build_filename (g_get_user_cache_dir (), "ibus", "registry.xml", NULL); + node = ibus_xml_parse_file (filename); + g_free (filename); + + if (node == NULL) { + return FALSE; + } + + if (g_strcmp0 (node->name, "ibus-registry") != 0) { + ibus_xml_free (node); + return FALSE; + } + + for (p = node->sub_nodes; p != NULL; p = p->next) { + XMLNode *sub_node = (XMLNode *) p->data; + + if (g_strcmp0 (sub_node->name, "observed-paths") == 0) { + GList *pp; + for (pp = sub_node->sub_nodes; pp != NULL; pp = pp->next) { + IBusObservedPath *path; + path = ibus_observed_path_new_from_xml_node (pp->data, FALSE); + if (path) { + registry->observed_paths = g_list_append (registry->observed_paths, path); + } + } + continue; + } + if (g_strcmp0 (sub_node->name, "components") == 0) { + GList *pp; + for (pp = sub_node->sub_nodes; pp != NULL; pp = pp->next) { + IBusComponent *component; + component = ibus_component_new_from_xml_node (pp->data); + if (component) { + registry->components = g_list_append (registry->components, component); + } + } + + continue; + } + g_warning ("Unknown element <%s>", sub_node->name); + } + + ibus_xml_free (node); + return TRUE; +} + +static gboolean +bus_registry_check_modification (BusRegistry *registry) +{ + GList *p; + + for (p = registry->observed_paths; p != NULL; p = p->next) { + if (ibus_observed_path_check_modification ((IBusObservedPath *)p->data)) + return TRUE; + } + + for (p = registry->components; p != NULL; p = p->next) { + if (ibus_component_check_modification ((IBusComponent *)p->data)) + return TRUE; + } + + return FALSE; +} + +static gboolean +bus_registry_save_cache (BusRegistry *registry) +{ + g_assert (BUS_IS_REGISTRY (registry)); + + gchar *cachedir; + gchar *filename; + GString *output; + GList *p; + FILE *pf; + + cachedir = g_build_filename (g_get_user_cache_dir (), "ibus", NULL); + filename = g_build_filename (cachedir, "registry.xml", NULL); + g_mkdir_with_parents (cachedir, 0775); + pf = g_fopen (filename, "w"); + g_free (filename); + g_free (cachedir); + + if (pf == NULL) { + g_warning ("create registry.xml failed"); + return FALSE; + } + + output = g_string_new (""); + g_string_append (output, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); + g_string_append (output, "<!-- \n" + " This file was generated by ibus-daemon. Please don't modify it.\n" + " -->\n"); + g_string_append (output, "<ibus-registry>\n"); + + if (registry->observed_paths) { + g_string_append_indent (output, 1); + g_string_append (output, "<observed-paths>\n"); + for (p = registry->observed_paths; p != NULL; p = p->next) { + ibus_observed_path_output ((IBusObservedPath *)p->data, + output, 2); + } + g_string_append_indent (output, 1); + g_string_append (output, "</observed-paths>\n"); + } + + if (registry->components) { + g_string_append_indent (output, 1); + g_string_append (output, "<components>\n"); + for (p = registry->components; p != NULL; p = p->next) { + ibus_component_output ((IBusComponent *)p->data, + output, 2); + } + g_string_append_indent (output, 1); + g_string_append (output, "</components>\n"); + } + + g_string_append (output, "</ibus-registry>\n"); + fwrite (output->str, output->len, 1, pf); + g_string_free (output, TRUE); + fclose (pf); + return TRUE; +} + +static void +bus_registry_load_in_dir (BusRegistry *registry, + const gchar *dirname) +{ + g_assert (BUS_IS_REGISTRY (registry)); + g_assert (dirname); + + GError *error = NULL; + GDir *dir; + const gchar *filename; + + dir = g_dir_open (dirname, 0, &error); + + if (dir == NULL) { + g_warning ("Unable open directory %s : %s", dirname, error->message); + g_error_free (error); + return; + } + + while ((filename = g_dir_read_name (dir)) != NULL) { + glong size; + gchar *path; + IBusComponent *component; + + size = g_utf8_strlen (filename, -1); + if (g_strcmp0 (MAX (filename, filename + size -4), ".xml" ) != 0) + continue; + + path = g_build_filename (dirname, filename, NULL); + component = ibus_component_new_from_file (path); + registry->components = g_list_append (registry->components, component); + + g_free (path); + } + + g_dir_close (dir); +} + + +BusRegistry * +bus_registry_new (void) +{ + BusRegistry *registry; + registry = (BusRegistry *)g_object_new (BUS_TYPE_REGISTRY, NULL); + return registry; +} + +static gint +_component_is_name (IBusComponent *component, + const gchar *name) +{ + g_assert (IBUS_IS_COMPONENT (component)); + g_assert (name); + + return g_strcmp0 (component->name, name); +} + +IBusComponent * +bus_registry_lookup_component_by_name (BusRegistry *registry, + const gchar *name) +{ + g_assert (BUS_IS_REGISTRY (registry)); + g_assert (name); + + GList *p; + p = g_list_find_custom (registry->components, + name, + (GCompareFunc)_component_is_name); + if (p) { + return (IBusComponent *)p->data; + } + else { + return NULL; + } +} + +GList * +bus_registry_get_components (BusRegistry *registry) +{ + g_assert (BUS_IS_REGISTRY (registry)); + + return g_list_copy (registry->components); +} + +GList * +bus_registry_get_engines (BusRegistry *registry) +{ + g_assert (BUS_IS_REGISTRY (registry)); + + return g_hash_table_get_values (registry->engine_table); +} + + +IBusEngineDesc * +bus_registry_find_engine_by_name (BusRegistry *registry, + const gchar *name) +{ + g_assert (BUS_IS_REGISTRY (registry)); + g_assert (name); + + return (IBusEngineDesc *) g_hash_table_lookup (registry->engine_table, name); +} + + +BusFactoryProxy * +bus_registry_name_owner_changed (BusRegistry *registry, + const gchar *name, + const gchar *old_name, + const gchar *new_name) +{ + g_assert (BUS_IS_REGISTRY (registry)); + g_assert (name); + g_assert (old_name); + g_assert (new_name); + + IBusComponent *component; + BusFactoryProxy *factory; + + component = bus_registry_lookup_component_by_name (registry, name); + + if (component == NULL) { + return NULL; + } + + if (g_strcmp0 (old_name, "") != 0) { + factory = bus_factory_proxy_get_from_component (component); + + if (factory != NULL) { + ibus_object_destroy ((IBusObject *)factory); + } + } + + if (g_strcmp0 (new_name, "") != 0) { + factory = bus_factory_proxy_new (component, NULL); + return factory; + } + + return NULL; +} diff --git a/bus/registry.h b/bus/registry.h new file mode 100644 index 0000000..9dadda6 --- /dev/null +++ b/bus/registry.h @@ -0,0 +1,88 @@ +/* vim:set et sts=4: */ +/* bus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __REGISTRY_H_ +#define __REGISTRY_H_ + +#include <ibus.h> +#include "factoryproxy.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define BUS_TYPE_REGISTRY \ + (bus_registry_get_type ()) +#define BUS_REGISTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUS_TYPE_REGISTRY, BusRegistry)) +#define BUS_REGISTRY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), BUS_TYPE_REGISTRY, BusRegistryClass)) +#define BUS_IS_REGISTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUS_TYPE_REGISTRY)) +#define BUS_IS_REGISTRY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), BUS_TYPE_REGISTRY)) +#define BUS_REGISTRY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), BUS_TYPE_REGISTRY, BusRegistryClass)) + +G_BEGIN_DECLS + +typedef struct _BusRegistry BusRegistry; +typedef struct _BusRegistryClass BusRegistryClass; + +struct _BusRegistry { + IBusObject parent; + + /* instance members */ + GList *observed_paths; + GList *components; + + GHashTable *engine_table; + GList *active_engines; +}; + +struct _BusRegistryClass { + IBusObjectClass parent; + + /* class members */ +}; + +GType bus_registry_get_type (void); +BusRegistry *bus_registry_new (void); +GList *bus_registry_get_components (BusRegistry *registry); +GList *bus_registry_get_engines (BusRegistry *registry); +gboolean bus_registry_exec_component (BusRegistry *registry, + const gchar *name); +gboolean bus_registry_kill_component (BusRegistry *registry, + const gchar *name); + +IBusComponent *bus_registry_lookup_component_by_name + (BusRegistry *registry, + const gchar *name); +IBusEngineDesc *bus_registry_find_engine_by_name + (BusRegistry *registry, + const gchar *name); +BusFactoryProxy *bus_registry_name_owner_changed(BusRegistry *registry, + const gchar *name, + const gchar *old_name, + const gchar *new_name); + +G_END_DECLS +#endif + diff --git a/bus/server.c b/bus/server.c new file mode 100644 index 0000000..2ae36bf --- /dev/null +++ b/bus/server.c @@ -0,0 +1,152 @@ +/* vim:set et sts=4: */ +/* bus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <sys/stat.h> +#include <sys/types.h> +#include <libgen.h> + +#include "server.h" +#include "connection.h" +#include "dbusimpl.h" +#include "ibusimpl.h" + +/* functions prototype */ +static void bus_server_class_init (BusServerClass *klass); +static void bus_server_init (BusServer *server); +static void bus_server_destroy (BusServer *server); +static void bus_server_new_connection + (BusServer *server, + BusConnection *connection); + +static IBusObjectClass *parent_class = NULL; + +GType +bus_server_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (BusServerClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) bus_server_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (BusServer), + 0, + (GInstanceInitFunc) bus_server_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERVER, + "BusServer", + &type_info, + (GTypeFlags)0); + } + + return type; +} + +BusServer * +bus_server_get_default (void) +{ + static BusServer *server = NULL; + + if (server == NULL) { + server = (BusServer *) g_object_new (BUS_TYPE_SERVER, + "connection-type", BUS_TYPE_CONNECTION, + NULL); + bus_dbus_impl_get_default (); + bus_ibus_impl_get_default (); + } + return server; +} + +gboolean +bus_server_listen (BusServer *server) +{ + g_assert (BUS_IS_SERVER (server)); + + // const gchar *address = "unix:abstract=/tmp/ibus-c" + const gchar *address; + gchar *path; + + path = g_strdup_printf("/tmp/ibus-%s", ibus_get_user_name ()); + mkdir (path, 0775); + g_free(path); + address = ibus_get_address (); + + return ibus_server_listen (IBUS_SERVER (server), address); +} + +void +bus_server_run (BusServer *server) +{ + g_assert (BUS_IS_SERVER (server)); + + g_main_loop_run (server->loop); +} + +void +bus_server_quit (BusServer *server) +{ + g_assert (BUS_IS_SERVER (server)); + + g_main_loop_quit (server->loop); +} + +static void +bus_server_class_init (BusServerClass *klass) +{ + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + + parent_class = (IBusObjectClass *) g_type_class_peek_parent (klass); + + ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_server_destroy; + + IBUS_SERVER_CLASS (klass)->new_connection = (IBusNewConnectionFunc) bus_server_new_connection; +} + +static void +bus_server_init (BusServer *server) +{ + server->loop = g_main_loop_new (NULL, FALSE); +} + +static void +bus_server_new_connection (BusServer *server, + BusConnection *connection) +{ + g_assert (BUS_IS_SERVER (server)); + bus_dbus_impl_new_connection (BUS_DEFAULT_DBUS, connection); +} + +static void +bus_server_destroy (BusServer *server) +{ + g_assert (BUS_IS_SERVER (server)); + + while (g_main_loop_is_running (server->loop)) { + g_main_loop_quit (server->loop); + } + g_main_loop_unref (server->loop); + + IBUS_OBJECT_CLASS (parent_class)->destroy (IBUS_OBJECT (server)); +} diff --git a/bus/server.h b/bus/server.h new file mode 100644 index 0000000..9ea5794 --- /dev/null +++ b/bus/server.h @@ -0,0 +1,72 @@ +/* vim:set et sts=4: */ +/* bus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __SERVER_H_ +#define __SERVER_H_ + +#include <ibus.h> + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define BUS_TYPE_SERVER \ + (bus_server_get_type ()) +#define BUS_SERVER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUS_TYPE_SERVER, BusServer)) +#define BUS_SERVER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), BUS_TYPE_SERVER, BusServerClass)) +#define BUS_IS_SERVER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUS_TYPE_SERVER)) +#define BUS_IS_SERVER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), BUS_TYPE_SERVER)) +#define BUS_SERVER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), BUS_TYPE_SERVER, BusServerClass)) +#define BUS_DEFAULT_SERVER \ + (bus_server_get_default ()) + +G_BEGIN_DECLS + +typedef struct _BusServer BusServer; +typedef struct _BusServerClass BusServerClass; + +struct _BusServer { + IBusServer parent; + + /* instance members */ + GMainLoop *loop; + +}; + +struct _BusServerClass { + IBusServerClass parent; + + /* class members */ +}; + +GType bus_server_get_type (void); +BusServer *bus_server_get_default (void); +gboolean bus_server_listen (BusServer *server); +void bus_server_run (BusServer *server); +void bus_server_quit (BusServer *server); + +G_END_DECLS +#endif + diff --git a/bus/test-matchrule.c b/bus/test-matchrule.c new file mode 100644 index 0000000..63110fd --- /dev/null +++ b/bus/test-matchrule.c @@ -0,0 +1,40 @@ +#include "matchrule.h" + +int +main(gint argc, gchar **argv) +{ + BusMatchRule *rule, *rule1; + g_type_init (); + + rule = bus_match_rule_new (" type='signal' , interface = 'org.freedesktop.IBus' "); + g_assert (rule->message_type == DBUS_MESSAGE_TYPE_SIGNAL); + g_assert (g_strcmp0 (rule->interface, "org.freedesktop.IBus") == 0 ); + g_object_unref (rule); + + rule = bus_match_rule_new ("type='method_call', interface='org.freedesktop.IBus' "); + g_assert (rule->message_type == DBUS_MESSAGE_TYPE_METHOD_CALL); + g_assert (g_strcmp0 (rule->interface, "org.freedesktop.IBus") == 0 ); + g_object_unref (rule); + + rule = bus_match_rule_new ("type='signal'," + "interface='org.freedesktop.DBus'," + "member='NameOwnerChanged'," + "arg0='ibus.freedesktop.IBus.config'," + "arg0='ibus.freedesktop.IBus.config'," + "arg2='ibus.freedesktop.IBus.config'"); + g_assert (rule->message_type == DBUS_MESSAGE_TYPE_SIGNAL); + g_assert (g_strcmp0 (rule->interface, "org.freedesktop.DBus") == 0 ); + rule1 = bus_match_rule_new ("type='signal'," + "interface='org.freedesktop.DBus'," + "member='NameOwnerChanged'," + "arg0='ibus.freedesktop.IBus.config'," + "arg0='ibus.freedesktop.IBus.config'," + "arg2='ibus.freedesktop.IBus.config'"); + + g_assert (bus_match_rule_is_equal (rule, rule1)); + + g_object_unref (rule); + g_object_unref (rule1); + + return 0; +} diff --git a/bus/test-registry.c b/bus/test-registry.c new file mode 100644 index 0000000..fdcbba8 --- /dev/null +++ b/bus/test-registry.c @@ -0,0 +1,9 @@ +#include "registry.h" + +int main() +{ + g_type_init (); + BusRegistry *registry = bus_registry_new (); + g_object_unref (registry); + return 0; +} diff --git a/client/Makefile.am b/client/Makefile.am index c7bd313..0eaf3dc 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -21,6 +21,6 @@ SUBDIRS = \ gtk2 \ - qt4 \ x11 \ + qt4 \ $(NULL) diff --git a/client/gtk2/Makefile.am b/client/gtk2/Makefile.am index b5c251b..2a4eb8b 100644 --- a/client/gtk2/Makefile.am +++ b/client/gtk2/Makefile.am @@ -19,10 +19,10 @@ # Free Software Foundation, Inc., 59 Temple Place, Suite 330, # Boston, MA 02111-1307 USA -libibus_gtk = $(top_builddir)/lib/gtk2/libibus-gtk.la +libibus = $(top_builddir)/src/libibus.la INCLUDES = \ - -I$(top_srcdir)/lib/gtk2 \ + -I$(top_srcdir)/src \ $(NULL) immoduledir = @GTK_IM_MODULEDIR@ @@ -34,8 +34,8 @@ im_ibus_la_SOURCES = \ ibusimcontext.h \ $(NULL) -im_ibus_la_DEPENDENCIES = $(libibus_gtk) -im_ibus_la_LIBADD = $(libibus_gtk) +im_ibus_la_DEPENDENCIES = $(libibus) +im_ibus_la_LIBADD = $(libibus) im_ibus_la_CFLAGS = \ @GTK2_CFLAGS@ \ @@ -50,8 +50,8 @@ im_ibus_la_LDFLAGS = \ -module \ $(NULL) -$(libibus_gtk): - (cd $(top_builddir)/lib/gtk2; make ) +$(libibus): + (cd $(top_builddir)/src; make ) EXTRA_DIST = \ $(NULL) diff --git a/client/gtk2/ibusim.c b/client/gtk2/ibusim.c index 30d84b8..c2951ca 100644 --- a/client/gtk2/ibusim.c +++ b/client/gtk2/ibusim.c @@ -21,7 +21,7 @@ #include <glib/gprintf.h> #include <gtk/gtk.h> #include <gtk/gtkimmodule.h> -#include "ibusimclient.h" +#include <ibus.h> #include "ibusimcontext.h" #define IBUS_LOCALDIR "" @@ -38,19 +38,22 @@ static const GtkIMContextInfo * info_list[] = { }; +G_MODULE_EXPORT const gchar* g_module_check_init (GModule *module); +const gchar* +g_module_check_init (GModule *module) +{ + return glib_check_version (GLIB_MAJOR_VERSION, + GLIB_MINOR_VERSION, + GLIB_MICRO_VERSION); +} + void im_module_init (GTypeModule *type_module) { - ibus_im_client_register_type(type_module); - ibus_im_context_register_type(type_module); -#if 0 - gchar **p = environ; - extern gchar **environ; - while (*p != NULL) { - g_fprintf (stderr, "%s\n", *p); - p ++; - } -#endif + /* make module resident */ + g_type_module_use (type_module); + + ibus_im_context_register_type (type_module); } void diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c index 195c9d9..640d0ea 100644 --- a/client/gtk2/ibusimcontext.c +++ b/client/gtk2/ibusimcontext.c @@ -23,9 +23,8 @@ #include <sys/socket.h> #include <sys/time.h> #include <sys/un.h> +#include <ibus.h> #include "ibusimcontext.h" -#include "ibusattribute.h" -#include "ibusimclient.h" /* IBusIMContextPriv */ struct _IBusIMContextPrivate { @@ -34,7 +33,7 @@ struct _IBusIMContextPrivate { /* enabled */ gboolean enable; - gchar *ic; + IBusInputContext *ibus_context; /* preedit status */ gchar *preedit_string; @@ -56,35 +55,37 @@ static guint _signal_delete_surrounding_id = 0; static guint _signal_retrieve_surrounding_id = 0; /* functions prototype */ -static void ibus_im_context_class_init (IBusIMContextClass *klass); -static void ibus_im_context_init (IBusIMContext *obj); -static void ibus_im_context_finalize (GObject *obj); -static void ibus_im_context_reset (GtkIMContext *context); +static void ibus_im_context_class_init (IBusIMContextClass *klass); +static void ibus_im_context_init (GObject *obj); +static void ibus_im_context_finalize (GObject *obj); +static void ibus_im_context_reset (GtkIMContext *context); static gboolean ibus_im_context_filter_keypress - (GtkIMContext *context, - GdkEventKey *key); -static void ibus_im_context_focus_in (GtkIMContext *context); -static void ibus_im_context_focus_out (GtkIMContext *context); + (GtkIMContext *context, + GdkEventKey *key); +static void ibus_im_context_focus_in (GtkIMContext *context); +static void ibus_im_context_focus_out (GtkIMContext *context); static void ibus_im_context_get_preedit_string - (GtkIMContext *context, - gchar **str, - PangoAttrList **attrs, - gint *cursor_pos); + (GtkIMContext *context, + gchar **str, + PangoAttrList **attrs, + gint *cursor_pos); static void ibus_im_context_set_client_window - (GtkIMContext *context, - GdkWindow *client); + (GtkIMContext *context, + GdkWindow *client); static void ibus_im_context_set_cursor_location - (GtkIMContext *context, - GdkRectangle *area); + (GtkIMContext *context, + GdkRectangle *area); static void ibus_im_context_set_use_preedit - (GtkIMContext *context, - gboolean use_preedit); + (GtkIMContext *context, + gboolean use_preedit); /* static methods*/ -static void _init_ibus_client (void); -static void _set_cursor_location_internal +static void _create_input_context (IBusIMContext *context); +static void _set_cursor_location_internal (GtkIMContext *context); +static void _bus_connected_cb (IBusBus *bus, + IBusIMContext *context); /* callback functions for slave context */ static void _slave_commit_cb (GtkIMContext *slave, gchar *string, @@ -109,9 +110,7 @@ static void _slave_delete_surrounding_cb static GType _ibus_type_im_context = 0; static GtkIMContextClass *parent_class = NULL; -static IBusIMClient *_client = NULL; -static GHashTable *_ic_table = NULL; -static GArray *_im_context_array = NULL; +static IBusBus *_bus = NULL; void ibus_im_context_register_type (GTypeModule *type_module) @@ -210,16 +209,16 @@ ibus_im_context_class_init (IBusIMContextClass *klass) _signal_retrieve_surrounding_id = g_signal_lookup ("retrieve-surrounding", G_TYPE_FROM_CLASS (klass)); g_assert (_signal_retrieve_surrounding_id != 0); + } static void -ibus_im_context_init (IBusIMContext *obj) +ibus_im_context_init (GObject *obj) { - _init_ibus_client (); - IBusIMContext *ibus = IBUS_IM_CONTEXT (obj); - IBusIMContextPrivate *priv = ibus->priv = - G_TYPE_INSTANCE_GET_PRIVATE (ibus, IBUS_TYPE_IM_CONTEXT, IBusIMContextPrivate); + IBusIMContext *ibuscontext = IBUS_IM_CONTEXT (obj); + IBusIMContextPrivate *priv = ibuscontext->priv = + G_TYPE_INSTANCE_GET_PRIVATE (ibuscontext, IBUS_TYPE_IM_CONTEXT, IBusIMContextPrivate); priv->client_window = NULL; @@ -238,34 +237,47 @@ ibus_im_context_init (IBusIMContext *obj) priv->cursor_area.width = 0; priv->cursor_area.height = 0; - priv->ic = NULL; + priv->ibus_context = NULL; priv->has_focus = FALSE; - priv->caps = IBUS_CAP_PREEDIT | IBUS_CAP_FOCUS; + priv->caps = IBUS_CAP_PREEDIT_TEXT | IBUS_CAP_FOCUS; // Create slave im context - ibus->priv->slave = gtk_im_context_simple_new (); - g_signal_connect (ibus->priv->slave, - "commit", G_CALLBACK (_slave_commit_cb), obj); - g_signal_connect (ibus->priv->slave, - "preedit-start", G_CALLBACK (_slave_preedit_start_cb), obj); - g_signal_connect (ibus->priv->slave, - "preedit-end", G_CALLBACK (_slave_preedit_end_cb), obj); - g_signal_connect (ibus->priv->slave, - "preedit-changed", G_CALLBACK (_slave_preedit_changed_cb), obj); - g_signal_connect (ibus->priv->slave, - "retrieve-surrounding", G_CALLBACK (_slave_retrieve_surrounding_cb), obj); - g_signal_connect (ibus->priv->slave, - "delete-surrounding", G_CALLBACK (_slave_delete_surrounding_cb), obj); - - g_array_append_val (_im_context_array, obj); - - if (ibus_im_client_get_connected (_client)) { - const gchar *ic = ibus_im_client_create_input_context (_client); - ibus_im_context_set_ic (ibus, ic); - g_hash_table_insert (_ic_table, - (gpointer) ibus_im_context_get_ic (ibus), (gpointer) ibus); - } + priv->slave = gtk_im_context_simple_new (); + g_signal_connect (priv->slave, + "commit", + G_CALLBACK (_slave_commit_cb), + ibuscontext); + g_signal_connect (priv->slave, + "preedit-start", + G_CALLBACK (_slave_preedit_start_cb), + ibuscontext); + g_signal_connect (priv->slave, + "preedit-end", + G_CALLBACK (_slave_preedit_end_cb), + ibuscontext); + g_signal_connect (priv->slave, + "preedit-changed", + G_CALLBACK (_slave_preedit_changed_cb), + ibuscontext); + g_signal_connect (priv->slave, + "retrieve-surrounding", + G_CALLBACK (_slave_retrieve_surrounding_cb), + ibuscontext); + g_signal_connect (priv->slave, + "delete-surrounding", + G_CALLBACK (_slave_delete_surrounding_cb), + ibuscontext); + + /* init bus object */ + if (_bus == NULL) + _bus = ibus_bus_new(); + + if (ibus_bus_is_connected (_bus)) { + _create_input_context (ibuscontext); + } + + g_signal_connect (_bus, "connected", G_CALLBACK (_bus_connected_cb), obj); } static void @@ -277,18 +289,10 @@ ibus_im_context_finalize (GObject *obj) IBusIMContext *ibus = IBUS_IM_CONTEXT (obj); IBusIMContextPrivate *priv = ibus->priv; - gint i; - for (i = 0; i < _im_context_array->len; i++) { - if (obj == g_array_index (_im_context_array, GObject *, i)) { - g_array_remove_index_fast (_im_context_array, i); - break; - } - } + g_signal_handlers_disconnect_by_func (_bus, G_CALLBACK (_bus_connected_cb), obj); - if (priv->ic) { - ibus_im_client_release_input_context (_client, priv->ic); - g_hash_table_remove (_ic_table, priv->ic); - g_free (priv->ic); + if (priv->ibus_context) { + ibus_object_destroy (priv->ibus_context); } g_object_unref (priv->slave); @@ -318,12 +322,26 @@ ibus_im_context_filter_keypress (GtkIMContext *context, IBusIMContext *ibus = IBUS_IM_CONTEXT (context); IBusIMContextPrivate *priv = ibus->priv; - if (priv->ic && priv->has_focus) { + if (priv->ibus_context && priv->has_focus) { /* If context does not have focus, ibus will process key event in sync mode. * It is a workaround for increase search in treeview. */ - gboolean retval = ibus_im_client_filter_keypress (_client, - priv->ic, event, FALSE); + gboolean retval; + switch (event->type) { + case GDK_KEY_RELEASE: + retval = ibus_input_context_process_key_event (priv->ibus_context, + event->keyval, + event->state | IBUS_RELEASE_MASK); + break; + case GDK_KEY_PRESS: + retval = ibus_input_context_process_key_event (priv->ibus_context, + event->keyval, + event->state); + break; + default: + retval = FALSE; + } + if (retval) { return TRUE; } @@ -337,15 +355,17 @@ ibus_im_context_filter_keypress (GtkIMContext *context, static void ibus_im_context_focus_in (GtkIMContext *context) { - g_return_if_fail (context != NULL); - g_return_if_fail (IBUS_IS_IM_CONTEXT (context)); + g_assert (IBUS_IS_IM_CONTEXT (context)); - IBusIMContext *ibus = IBUS_IM_CONTEXT (context); - IBusIMContextPrivate *priv = ibus->priv; + IBusIMContext *ibuscontext; + IBusIMContextPrivate *priv; + + ibuscontext = IBUS_IM_CONTEXT (context); + priv = ibuscontext->priv; priv->has_focus = TRUE; - if (priv->ic) { - ibus_im_client_focus_in (_client, priv->ic); + if (priv->ibus_context) { + ibus_input_context_focus_in (priv->ibus_context); } gtk_im_context_focus_in (priv->slave); @@ -356,15 +376,18 @@ ibus_im_context_focus_in (GtkIMContext *context) static void ibus_im_context_focus_out (GtkIMContext *context) { - g_return_if_fail (context != NULL); - g_return_if_fail (IBUS_IS_IM_CONTEXT (context)); - IBusIMContext *ibus = IBUS_IM_CONTEXT (context); - IBusIMContextPrivate *priv = ibus->priv; + g_assert (IBUS_IS_IM_CONTEXT (context)); + + IBusIMContext *ibuscontext; + IBusIMContextPrivate *priv; + + ibuscontext = IBUS_IM_CONTEXT (context); + priv = ibuscontext->priv; priv->has_focus = FALSE; - if (priv->ic) { - ibus_im_client_focus_out (_client, priv->ic); + if (priv->ibus_context) { + ibus_input_context_focus_out (priv->ibus_context); } gtk_im_context_focus_out (priv->slave); } @@ -372,14 +395,16 @@ ibus_im_context_focus_out (GtkIMContext *context) static void ibus_im_context_reset (GtkIMContext *context) { - g_return_if_fail (context != NULL); - g_return_if_fail (IBUS_IS_IM_CONTEXT (context)); + g_assert (IBUS_IS_IM_CONTEXT (context)); - IBusIMContext *ibus = IBUS_IM_CONTEXT (context); - IBusIMContextPrivate *priv = ibus->priv; + IBusIMContext *ibuscontext; + IBusIMContextPrivate *priv; - if (priv->ic) { - ibus_im_client_reset (_client, priv->ic); + ibuscontext = IBUS_IM_CONTEXT (context); + priv = ibuscontext->priv; + + if (priv->ibus_context) { + ibus_input_context_reset (priv->ibus_context); } gtk_im_context_reset (priv->slave); } @@ -387,15 +412,17 @@ ibus_im_context_reset (GtkIMContext *context) static void ibus_im_context_get_preedit_string (GtkIMContext *context, - gchar **str, - PangoAttrList **attrs, - gint *cursor_pos) + gchar **str, + PangoAttrList **attrs, + gint *cursor_pos) { - g_return_if_fail (context != NULL); - g_return_if_fail (IBUS_IS_IM_CONTEXT (context)); + g_assert (IBUS_IS_IM_CONTEXT (context)); - IBusIMContext *ibus = IBUS_IM_CONTEXT (context); - IBusIMContextPrivate *priv = ibus->priv; + IBusIMContext *ibuscontext; + IBusIMContextPrivate *priv; + + ibuscontext = IBUS_IM_CONTEXT (context); + priv = ibuscontext->priv; if (priv->enable) { if (priv->preedit_visible) { @@ -460,7 +487,7 @@ _set_cursor_location_internal (GtkIMContext *context) GdkRectangle area; gint x, y; - if(priv->client_window == NULL || priv->ic == NULL) { + if(priv->client_window == NULL || priv->ibus_context == NULL) { return; } @@ -475,7 +502,11 @@ _set_cursor_location_internal (GtkIMContext *context) gdk_window_get_origin (priv->client_window, &x, &y); area.x += x; area.y += y; - ibus_im_client_set_cursor_location (_client, priv->ic, &area); + ibus_input_context_set_cursor_location (priv->ibus_context, + area.x, + area.y, + area.width, + area.height); } static void @@ -501,96 +532,84 @@ ibus_im_context_set_use_preedit (GtkIMContext *context, gboolean use_preedit) IBusIMContext *ibus = IBUS_IM_CONTEXT (context); IBusIMContextPrivate *priv = ibus->priv; - if(priv->ic) { + if(priv->ibus_context) { if (use_preedit) { - priv->caps |= IBUS_CAP_PREEDIT; + priv->caps |= IBUS_CAP_PREEDIT_TEXT; } else { - priv->caps &= ~IBUS_CAP_PREEDIT; + priv->caps &= ~IBUS_CAP_PREEDIT_TEXT; } - ibus_im_client_set_capabilities (_client, priv->ic, priv->caps); + ibus_input_context_set_capabilities (priv->ibus_context, priv->caps); } gtk_im_context_set_use_preedit (priv->slave, use_preedit); } static void -_client_connected_cb (IBusIMClient *client, gpointer user_data) -{ - gint i; - const gchar *ic; - IBusIMContext *context; - - for (i = 0; i < _im_context_array->len; i++) { - context = g_array_index (_im_context_array, IBusIMContext *, i); - ic = ibus_im_client_create_input_context (client); - ibus_im_context_set_ic (context, ic); - if (ic == NULL) { - continue; - } - g_hash_table_insert (_ic_table, - (gpointer) ibus_im_context_get_ic (context), (gpointer) context); - } -} - -static void -_client_disconnected_cb (IBusIMClient *client, gpointer user_data) +_bus_connected_cb (IBusBus *bus, + IBusIMContext *context) { - gint i; - IBusIMContext *context; - - g_hash_table_remove_all (_ic_table); - for (i = 0; i < _im_context_array->len; i++) { - context = g_array_index (_im_context_array, IBusIMContext *, i); - ibus_im_context_set_ic (context, NULL); - } + g_assert (IBUS_IS_IM_CONTEXT (context)); + g_assert (context->priv->ibus_context == NULL); + _create_input_context (context); } static void -_client_commit_string_cb (IBusIMClient *client, const gchar *ic, const gchar *string, gpointer user_data) +_ibus_context_commit_text_cb (IBusInputContext *ibus_context, + IBusText *text, + IBusIMContext *context) { - IBusIMContext *context = g_hash_table_lookup (_ic_table, ic); - g_return_if_fail (context != NULL); - - g_signal_emit (context, _signal_commit_id, 0, string); + g_assert (IBUS_IS_INPUT_CONTEXT (ibus_context)); + g_assert (IBUS_IS_TEXT (text)); + g_assert (IBUS_IS_IM_CONTEXT (context)); + g_signal_emit (context, _signal_commit_id, 0, text->text); } static void -_client_forward_event_cb (IBusIMClient *client, const gchar *ic, GdkEvent *event, gpointer user_data) +_ibus_context_forward_key_event_cb (IBusInputContext *ibus_context, + guint keyval, + gboolean is_press, + guint state, + IBusIMContext *context) { - IBusIMContext *context = g_hash_table_lookup (_ic_table, ic); - g_return_if_fail (context != NULL); + g_assert (IBUS_IS_IM_CONTEXT (context)); - if (event->type == GDK_KEY_PRESS || - event->type == GDK_KEY_RELEASE) { - /* - GTimeVal time; - event->key.time = time.tv_sec * 1000 + time.tv_usec / 1000; - */ - event->key.time = GDK_CURRENT_TIME; - } + GdkEventKey *event; + IBusIMContextPrivate *priv; -#if 0 - if (event->any.window != context->priv->client_window) { - GdkWindow *old_window = event->any.window; - event->any.window = context->priv->client_window; - gdk_event_put (event); - event->any.window = old_window; - } - else -#endif - gdk_event_put (event); + priv = context->priv; + event = (GdkEventKey *)gdk_event_new (is_press ? GDK_KEY_PRESS : GDK_KEY_RELEASE); + + event->time = GDK_CURRENT_TIME; + event->window = g_object_ref (priv->client_window); + event->send_event = FALSE; + event->state = state; + event->keyval = keyval; + event->string = gdk_keyval_name (keyval); + event->length = strlen (event->string); + event->hardware_keycode = 0; + event->group = 0; + event->is_modifier = 0; + + gdk_event_put ((GdkEvent *)event); + gdk_event_free ((GdkEvent *)event); } static void -_client_update_preedit_cb (IBusIMClient *client, const gchar *ic, const gchar *string, - IBusAttrList *attr_list, gint cursor_pos, gboolean visible, gpointer user_data) +_ibus_context_update_preedit_text_cb (IBusInputContext *ibus_context, + IBusText *text, + gint cursor_pos, + gboolean visible, + IBusIMContext *context) { - IBusIMContext *context = g_hash_table_lookup (_ic_table, ic); - g_return_if_fail (context != NULL); + g_assert (IBUS_IS_INPUT_CONTEXT (ibus_context)); + g_assert (IBUS_IS_TEXT (text)); + g_assert (IBUS_IS_IM_CONTEXT (context)); - IBusIMContextPrivate *priv = context->priv; + IBusIMContextPrivate *priv; + priv = context->priv; + const gchar *str; if (priv->preedit_string) { g_free (priv->preedit_string); @@ -600,12 +619,13 @@ _client_update_preedit_cb (IBusIMClient *client, const gchar *ic, const gchar *s priv->preedit_attrs = NULL; } - priv->preedit_string = g_strdup (string); - if (attr_list) { + str = text->text; + priv->preedit_string = g_strdup (str); + if (text->attrs) { guint i; priv->preedit_attrs = pango_attr_list_new (); for (i = 0; ; i++) { - IBusAttribute *attr = ibus_attr_list_get (attr_list, i); + IBusAttribute *attr = ibus_attr_list_get (text->attrs, i); if (attr == NULL) { break; } @@ -630,8 +650,8 @@ _client_update_preedit_cb (IBusIMClient *client, const gchar *ic, const gchar *s default: continue; } - pango_attr->start_index = g_utf8_offset_to_pointer (string, attr->start_index) - string; - pango_attr->end_index = g_utf8_offset_to_pointer (string, attr->end_index) - string; + pango_attr->start_index = g_utf8_offset_to_pointer (str, attr->start_index) - str; + pango_attr->end_index = g_utf8_offset_to_pointer (str, attr->end_index) - str; pango_attr_list_insert (priv->preedit_attrs, pango_attr); } } @@ -641,11 +661,10 @@ _client_update_preedit_cb (IBusIMClient *client, const gchar *ic, const gchar *s } static void -_client_show_preedit_cb (IBusIMClient *client, const gchar *ic, gpointer user_data) +_ibus_context_show_preedit_text_cb (IBusInputContext *ibus_context, + IBusIMContext *context) { - IBusIMContext *context = g_hash_table_lookup (_ic_table, ic); - g_return_if_fail (context != NULL); - + g_assert (IBUS_IS_IM_CONTEXT (context)); IBusIMContextPrivate *priv = context->priv; if (priv->preedit_visible == FALSE) { @@ -655,11 +674,10 @@ _client_show_preedit_cb (IBusIMClient *client, const gchar *ic, gpointer user_da } static void -_client_hide_preedit_cb (IBusIMClient *client, const gchar *ic, gpointer user_data) +_ibus_context_hide_preedit_text_cb (IBusInputContext *ibus_context, + IBusIMContext *context) { - IBusIMContext *context = g_hash_table_lookup (_ic_table, ic); - g_return_if_fail (context != NULL); - + g_assert (IBUS_IS_IM_CONTEXT (context)); IBusIMContextPrivate *priv = context->priv; if (priv->preedit_visible == TRUE) { @@ -669,62 +687,88 @@ _client_hide_preedit_cb (IBusIMClient *client, const gchar *ic, gpointer user_da } static void -_client_enabled_cb (IBusIMClient *client, const gchar *ic, gpointer user_data) +_ibus_context_enabled_cb (IBusInputContext *ibus_context, + IBusIMContext *context) { - IBusIMContext *context = g_hash_table_lookup (_ic_table, ic); - g_return_if_fail (context != NULL); - + g_assert (IBUS_IS_IM_CONTEXT (context)); IBusIMContextPrivate *priv = context->priv; - if (priv->enable == FALSE) { - priv->enable = TRUE; - } + priv->enable = TRUE; } static void -_client_disabled_cb (IBusIMClient *client, const gchar *ic, gpointer user_data) +_ibus_context_disabled_cb (IBusInputContext *ibus_context, + IBusIMContext *context) { - IBusIMContext *context = g_hash_table_lookup (_ic_table, ic); - g_return_if_fail (context != NULL); - + g_assert (IBUS_IS_IM_CONTEXT (context)); IBusIMContextPrivate *priv = context->priv; - if (priv->enable == TRUE) { - priv->enable = FALSE; - } + priv->enable = FALSE; } static void -_init_ibus_client (void) +_ibus_context_destroy_cb (IBusInputContext *ibus_context, + IBusIMContext *context) { - if (_client != NULL) { - return; - } + g_assert (IBUS_IS_IM_CONTEXT (context)); - _im_context_array = g_array_new (TRUE, TRUE, sizeof (IBusIMContext *)); - _ic_table = g_hash_table_new (g_str_hash, g_str_equal); + IBusIMContextPrivate *priv = context->priv; - _client = ibus_im_client_new (); + g_assert (priv->ibus_context == ibus_context); - g_signal_connect (_client, "connected", - G_CALLBACK (_client_connected_cb), NULL); - g_signal_connect (_client, "disconnected", - G_CALLBACK (_client_disconnected_cb), NULL); - g_signal_connect (_client, "commit-string", - G_CALLBACK (_client_commit_string_cb), NULL); - g_signal_connect (_client, "forward-event", - G_CALLBACK (_client_forward_event_cb), NULL); - g_signal_connect (_client, "update-preedit", - G_CALLBACK (_client_update_preedit_cb), NULL); - g_signal_connect (_client, "show-preedit", - G_CALLBACK (_client_show_preedit_cb), NULL); - g_signal_connect (_client, "hide-preedit", - G_CALLBACK (_client_hide_preedit_cb), NULL); - g_signal_connect (_client, "enabled", - G_CALLBACK (_client_enabled_cb), NULL); - g_signal_connect (_client, "disabled", - G_CALLBACK (_client_disabled_cb), NULL); + g_object_unref (priv->ibus_context); + priv->ibus_context = NULL; + priv->enable = FALSE; +} +static void +_create_input_context (IBusIMContext *context) +{ + g_assert (IBUS_IS_IM_CONTEXT (context)); + g_assert (context->priv->ibus_context == NULL); + + IBusIMContextPrivate *priv; + priv = context->priv; + + priv->ibus_context = ibus_bus_create_input_context (_bus, "test"); + + g_signal_connect (priv->ibus_context, + "commit-text", + G_CALLBACK (_ibus_context_commit_text_cb), + context); + g_signal_connect (priv->ibus_context, + "forward-key-event", + G_CALLBACK (_ibus_context_forward_key_event_cb), + context); + g_signal_connect (priv->ibus_context, + "update-preedit-text", + G_CALLBACK (_ibus_context_update_preedit_text_cb), + context); + g_signal_connect (priv->ibus_context, + "show-preedit-text", + G_CALLBACK (_ibus_context_show_preedit_text_cb), + context); + g_signal_connect (priv->ibus_context, + "hide-preedit-text", + G_CALLBACK (_ibus_context_hide_preedit_text_cb), + context); + g_signal_connect (priv->ibus_context, + "enabled", + G_CALLBACK (_ibus_context_enabled_cb), + context); + g_signal_connect (priv->ibus_context, + "disabled", + G_CALLBACK (_ibus_context_disabled_cb), + context); + g_signal_connect (priv->ibus_context, "destroy", + G_CALLBACK (_ibus_context_destroy_cb), + context); + + ibus_input_context_set_capabilities (priv->ibus_context, priv->caps); + + if (priv->has_focus) { + ibus_input_context_focus_in (priv->ibus_context); + } } /* Callback functions for slave context */ @@ -750,7 +794,7 @@ _slave_preedit_changed_cb (GtkIMContext *slave, IBusIMContext *context) IBusIMContextPrivate *priv = context->priv; - if (priv->enable && priv->ic) { + if (priv->enable && priv->ibus_context) { return; } @@ -765,7 +809,7 @@ _slave_preedit_start_cb (GtkIMContext *slave, IBusIMContext *context) IBusIMContextPrivate *priv = context->priv; - if (priv->enable && priv->ic) { + if (priv->enable && priv->ibus_context) { return; } g_signal_emit (context, _signal_preedit_start_id, 0); @@ -779,7 +823,7 @@ _slave_preedit_end_cb (GtkIMContext *slave, IBusIMContext *context) IBusIMContextPrivate *priv = context->priv; - if (priv->enable && priv->ic) { + if (priv->enable && priv->ibus_context) { return; } g_signal_emit (context, _signal_preedit_end_id, 0); @@ -793,7 +837,7 @@ _slave_retrieve_surrounding_cb (GtkIMContext *slave, IBusIMContext *context) IBusIMContextPrivate *priv = context->priv; - if (priv->enable && priv->ic) { + if (priv->enable && priv->ibus_context) { return; } g_signal_emit (context, _signal_retrieve_surrounding_id, 0); @@ -807,44 +851,12 @@ _slave_delete_surrounding_cb (GtkIMContext *slave, gint a1, gint a2, IBusIMConte IBusIMContextPrivate *priv = context->priv; - if (priv->enable && priv->ic) { + if (priv->enable && priv->ibus_context) { return; } g_signal_emit (context, _signal_delete_surrounding_id, 0, a1, a2); } -const gchar * -ibus_im_context_get_ic (IBusIMContext *context) -{ - g_return_val_if_fail (context != NULL, NULL); - g_return_val_if_fail (IBUS_IS_IM_CONTEXT (context), NULL); - - IBusIMContextPrivate *priv = context->priv; - return priv->ic; -} - -void -ibus_im_context_set_ic (IBusIMContext *context, const gchar *ic) -{ - g_return_if_fail (context != NULL); - g_return_if_fail (IBUS_IS_IM_CONTEXT (context)); - - IBusIMContextPrivate *priv = context->priv; - - g_free (priv->ic); - priv->ic = g_strdup (ic); - - if (priv->ic == NULL) { - priv->enable = FALSE; - } - else { - ibus_im_client_set_capabilities (_client, priv->ic, priv->caps); - if (priv->has_focus) { - ibus_im_context_focus_in (GTK_IM_CONTEXT (context)); - } - } -} - void ibus_im_context_show_preedit (IBusIMContext *context) { diff --git a/client/x11/.gitignore b/client/x11/.gitignore new file mode 100644 index 0000000..bdff9a1 --- /dev/null +++ b/client/x11/.gitignore @@ -0,0 +1 @@ +ibus-x11 diff --git a/client/x11/Makefile.am b/client/x11/Makefile.am index c50cf7d..bd2efab 100644 --- a/client/x11/Makefile.am +++ b/client/x11/Makefile.am @@ -21,9 +21,9 @@ libIMdkit = $(top_builddir)/util/IMdkit/libIMdkit.la -libibus_gtk = $(top_builddir)/lib/gtk2/libibus-gtk.la +libibus = $(top_builddir)/src/libibus.la -bin_PROGRAMS = ibus-x11 +libexec_PROGRAMS = ibus-x11 ibus_x11_SOURCES = \ main.c \ @@ -32,12 +32,12 @@ ibus_x11_SOURCES = \ ibus_x11_DEPENDENCIES = \ $(libIMdkit) \ - $(libibus_gtk) \ + $(libibus) \ $(NULL) ibus_x11_LDADD = \ $(libIMdkit) \ - $(libibus_gtk) \ + $(libibus) \ $(NULL) ibus_x11_LDFLAGS = \ @@ -48,7 +48,7 @@ ibus_x11_CFLAGS = \ @GTK2_CFLAGS@ \ @DBUS_CFLAGS@ \ -I$(top_srcdir)/util/IMdkit \ - -I$(top_srcdir)/lib/gtk2 \ + -I$(top_srcdir)/src \ $(NULL) noinst_HEADERS = \ @@ -58,6 +58,6 @@ noinst_HEADERS = \ $(IMdkit): (cd $(top_builddir)/util/IMdkit; make) -$(libibus_gtk): - (cd $(top_builddir)/lib/gtk2; make) +$(libibus): + (cd $(top_builddir)/src; make) diff --git a/client/x11/main.c b/client/x11/main.c index 30b5ad8..734c898 100644 --- a/client/x11/main.c +++ b/client/x11/main.c @@ -44,8 +44,7 @@ g_debug (fmt_args); \ } -#include <ibusattribute.h> -#include <ibusimclient.h> +#include <ibus.h> #include "gdk-private.h" struct _X11ICONN { @@ -53,32 +52,53 @@ struct _X11ICONN { }; typedef struct _X11ICONN X11ICONN; +typedef struct _X11IC X11IC; struct _X11IC { - gchar *ibus_ic; - Window client_window; - Window focus_window; - gint32 input_style; - X11ICONN *conn; - gint icid; - gint connect_id; - gchar *lang; - gboolean has_preedit_area; - GdkRectangle preedit_area; + IBusInputContext *context; + Window client_window; + Window focus_window; + gint32 input_style; + X11ICONN *conn; + gint icid; + gint connect_id; + gchar *lang; + gboolean has_preedit_area; + GdkRectangle preedit_area; gchar *preedit_string; IBusAttrList *preedit_attrs; - gint preedit_cursor; - gboolean preedit_visible; - gboolean preedit_started; - gint onspot_preedit_length; + gint preedit_cursor; + gboolean preedit_visible; + gboolean preedit_started; + gint onspot_preedit_length; }; -typedef struct _X11IC X11IC; - -static void _xim_set_cursor_location (X11IC *x11ic); +static void _xim_set_cursor_location (X11IC *x11ic); +static void _context_commit_text_cb (IBusInputContext *context, + IBusText *text, + X11IC *x11ic); +static void _context_forward_key_event_cb + (IBusInputContext *context, + X11IC *x11ic); + +static void _context_update_preedit_text_cb + (IBusInputContext *context, + IBusText *text, + gint cursor_pos, + gboolean visible, + X11IC *x11ic); +static void _context_show_preedit_text_cb + (IBusInputContext *context, + X11IC *x11ic); +static void _context_hide_preedit_text_cb + (IBusInputContext *context, + X11IC *x11ic); +static void _context_enabled_cb (IBusInputContext *context, + X11IC *x11ic); +static void _context_disabled_cb (IBusInputContext *context, + X11IC *x11ic); static GHashTable *_x11_ic_table = NULL; -static GHashTable *_ibus_ic_table = NULL; static GHashTable *_connections = NULL; static XIMS _xims = NULL; static gchar _server_name[128] = "ibus"; @@ -95,9 +115,9 @@ static gchar _locale[1024] = "uk,ur,uz,ve,vi,wa,xh,yi,zh,zu"; static gboolean _kill_daemon = FALSE; -static gint g_debug_level = 0; +static gint g_debug_level = 0; -static IBusIMClient *_client = NULL; +static IBusBus *_bus = NULL; static void _xim_preedit_start (XIMS xims, const X11IC *x11ic) @@ -315,21 +335,35 @@ xim_create_ic (XIMS xims, IMChangeICStruct *call_data) i = _xim_store_ic_values (x11ic, call_data); - x11ic->ibus_ic = g_strdup (ibus_im_client_create_input_context (_client)); - if (x11ic->ibus_ic == NULL) { + x11ic->context = ibus_bus_create_input_context (_bus, "xim"); + + if (x11ic->context == NULL) { g_slice_free (X11IC, x11ic); g_return_val_if_reached (0); } - g_hash_table_insert (_ibus_ic_table, x11ic->ibus_ic, (gpointer)x11ic); + g_signal_connect (x11ic->context, "commit-text", + G_CALLBACK (_context_commit_text_cb), x11ic); + g_signal_connect (x11ic->context, "forward-key-event", + G_CALLBACK (_context_forward_key_event_cb), x11ic); + + g_signal_connect (x11ic->context, "update-preedit-text", + G_CALLBACK (_context_update_preedit_text_cb), x11ic); + g_signal_connect (x11ic->context, "show-preedit-text", + G_CALLBACK (_context_show_preedit_text_cb), x11ic); + g_signal_connect (x11ic->context, "hide-preedit-text", + G_CALLBACK (_context_hide_preedit_text_cb), x11ic); + g_signal_connect (x11ic->context, "enabled", + G_CALLBACK (_context_enabled_cb), x11ic); + g_signal_connect (x11ic->context, "disabled", + G_CALLBACK (_context_disabled_cb), x11ic); + if (x11ic->input_style & XIMPreeditCallbacks) { - ibus_im_client_set_capabilities (_client, x11ic->ibus_ic, - IBUS_CAP_FOCUS | IBUS_CAP_PREEDIT); + ibus_input_context_set_capabilities (x11ic->context, IBUS_CAP_FOCUS | IBUS_CAP_PREEDIT_TEXT); } else { - ibus_im_client_set_capabilities (_client, x11ic->ibus_ic, - IBUS_CAP_FOCUS); + ibus_input_context_set_capabilities (x11ic->context, IBUS_CAP_FOCUS); } g_hash_table_insert (_x11_ic_table, @@ -352,16 +386,23 @@ xim_destroy_ic (XIMS xims, IMChangeICStruct *call_data) (gconstpointer)(unsigned long)call_data->icid); g_return_val_if_fail (x11ic != NULL, 0); - ibus_im_client_release_input_context (_client, x11ic->ibus_ic); + if (x11ic->context) { + ibus_object_destroy ((IBusObject *)x11ic->context); + g_object_unref (x11ic->context); + x11ic->context = NULL; + } - g_hash_table_remove (_ibus_ic_table, x11ic->ibus_ic); g_hash_table_remove (_x11_ic_table, (gconstpointer)(unsigned long)call_data->icid); x11ic->conn->clients = g_list_remove (x11ic->conn->clients, (gconstpointer)x11ic); g_free (x11ic->preedit_string); - ibus_attr_list_unref (x11ic->preedit_attrs); - g_free (x11ic->ibus_ic); + x11ic->preedit_string = NULL; + + if (x11ic->preedit_attrs) { + g_object_unref (x11ic->preedit_attrs); + x11ic->preedit_attrs = NULL; + } g_slice_free (X11IC, x11ic); @@ -380,7 +421,7 @@ xim_set_ic_focus (XIMS xims, IMChangeFocusStruct *call_data) (gconstpointer)(unsigned long)call_data->icid); g_return_val_if_fail (x11ic != NULL, 0); - ibus_im_client_focus_in (_client, x11ic->ibus_ic); + ibus_input_context_focus_in (x11ic->context); _xim_set_cursor_location (x11ic); return 1; @@ -398,7 +439,7 @@ xim_unset_ic_focus (XIMS xims, IMChangeFocusStruct *call_data) (gconstpointer)(unsigned long)call_data->icid); g_return_val_if_fail (x11ic != NULL, 0); - ibus_im_client_focus_out (_client, x11ic->ibus_ic); + ibus_input_context_focus_out (x11ic->context); return 1; @@ -426,8 +467,12 @@ xim_forward_event (XIMS xims, IMForwardEventStruct *call_data) event.send_event = xevent->send_event; event.window = NULL; - if (ibus_im_client_filter_keypress (_client, - x11ic->ibus_ic, &event, False)) { + if (event.type == GDK_KEY_RELEASE) { + event.state |= IBUS_RELEASE_MASK; + } + + if (ibus_input_context_process_key_event (x11ic->context, + event.keyval, event.state)) { if (! x11ic->has_preedit_area) { _xim_set_cursor_location (x11ic); } @@ -479,12 +524,19 @@ _free_ic (gpointer data, gpointer user_data) g_return_if_fail (x11ic != NULL); g_free (x11ic->preedit_string); - ibus_attr_list_unref (x11ic->preedit_attrs); - g_free (x11ic->ibus_ic); + + if (x11ic->preedit_attrs) { + g_object_unref (x11ic->preedit_attrs); + x11ic->preedit_attrs = NULL; + } + + if (x11ic->context) { + ibus_object_destroy ((IBusObject *)x11ic->context); + g_object_unref (x11ic->context); + x11ic->context = NULL; + } /* Remove the IC from g_client dictionary */ - g_hash_table_remove (_ibus_ic_table, - (gconstpointer)(unsigned long)x11ic->ibus_ic); g_hash_table_remove (_x11_ic_table, (gconstpointer)(unsigned long)x11ic->icid); @@ -551,8 +603,11 @@ _xim_set_cursor_location (X11IC *x11ic) } } - ibus_im_client_set_cursor_location (_client, - x11ic->ibus_ic, &preedit_area); + ibus_input_context_set_cursor_location (x11ic->context, + preedit_area.x, + preedit_area.y, + preedit_area.width, + preedit_area.height); } @@ -618,7 +673,7 @@ xim_reset_ic (XIMS xims, IMResetICStruct *call_data) (gconstpointer)(unsigned long)call_data->icid); g_return_val_if_fail (x11ic != NULL, 0); - ibus_im_client_reset (_client, x11ic->ibus_ic); + ibus_input_context_reset (x11ic->context); return 1; } @@ -702,23 +757,29 @@ _xim_forward_gdk_event (GdkEventKey *event, X11IC *x11ic) } static void -_client_disconnected_cb (IBusIMClient *client, gpointer user_data) +_bus_disconnected_cb (IBusBus *bus, + gpointer user_data) { g_warning ("Connection closed by ibus-daemon"); + g_object_unref (_bus); + _bus = NULL; exit(EXIT_SUCCESS); } static void -_client_commit_string_cb (IBusIMClient *client, const gchar *ic, const gchar *string, gpointer user_data) +_context_commit_text_cb (IBusInputContext *context, + IBusText *text, + X11IC *x11ic) { - X11IC *x11ic = g_hash_table_lookup (_ibus_ic_table, ic); - g_return_if_fail (x11ic != NULL); + g_assert (IBUS_IS_INPUT_CONTEXT (context)); + g_assert (IBUS_IS_TEXT (text)); + g_assert (x11ic != NULL); XTextProperty tp; IMCommitStruct cms = {0}; Xutf8TextListToTextProperty (GDK_DISPLAY (), - (gchar **)&string, 1, XCompoundTextStyle, &tp); + (gchar **)&(text->text), 1, XCompoundTextStyle, &tp); cms.major_code = XIM_COMMIT; cms.icid = x11ic->icid; @@ -731,12 +792,12 @@ _client_commit_string_cb (IBusIMClient *client, const gchar *ic, const gchar *st } static void -_client_forward_event_cb (IBusIMClient *client, const gchar *ic, GdkEvent *event, gpointer user_data) +_context_forward_key_event_cb (IBusInputContext *context, + X11IC *x11ic) { - X11IC *x11ic = g_hash_table_lookup (_ibus_ic_table, ic); - g_return_if_fail (x11ic != NULL); + g_assert (x11ic); - _xim_forward_gdk_event (&(event->key), x11ic); + // _xim_forward_gdk_event (&(event->key), x11ic); } static void @@ -759,21 +820,27 @@ _update_preedit (X11IC *x11ic) } static void -_client_update_preedit_cb (IBusIMClient *client, const gchar *ic, const gchar *string, - IBusAttrList *attrs, gint cursor_pos, gboolean visible, gpointer user_data) +_context_update_preedit_text_cb (IBusInputContext *context, + IBusText *text, + gint cursor_pos, + gboolean visible, + X11IC *x11ic) { - X11IC *x11ic = g_hash_table_lookup (_ibus_ic_table, ic); - g_return_if_fail (x11ic != NULL); + g_assert (IBUS_IS_INPUT_CONTEXT (context)); + g_assert (IBUS_IS_TEXT (text)); + g_assert (x11ic); if (x11ic->preedit_string) { g_free(x11ic->preedit_string); } - x11ic->preedit_string = g_strdup(string); + x11ic->preedit_string = g_strdup(text->text); if (x11ic->preedit_attrs) { - ibus_attr_list_unref (x11ic->preedit_attrs); + g_object_unref (x11ic->preedit_attrs); } - x11ic->preedit_attrs = ibus_attr_list_ref(attrs); + + g_object_ref(text->attrs); + x11ic->preedit_attrs = text->attrs; x11ic->preedit_cursor = cursor_pos; x11ic->preedit_visible = visible; @@ -782,74 +849,62 @@ _client_update_preedit_cb (IBusIMClient *client, const gchar *ic, const gchar *s } static void -_client_show_preedit_cb (IBusIMClient *client, const gchar *ic, gpointer user_data) +_context_show_preedit_text_cb (IBusInputContext *context, + X11IC *x11ic) { - X11IC *x11ic = g_hash_table_lookup (_ibus_ic_table, ic); - g_return_if_fail (x11ic != NULL); + g_assert (IBUS_IS_INPUT_CONTEXT (context)); + g_assert (x11ic); x11ic->preedit_visible = TRUE; _update_preedit (x11ic); } static void -_client_hide_preedit_cb (IBusIMClient *client, const gchar *ic, gpointer user_data) +_context_hide_preedit_text_cb (IBusInputContext *context, + X11IC *x11ic) { - X11IC *x11ic = g_hash_table_lookup (_ibus_ic_table, ic); - g_return_if_fail (x11ic != NULL); + g_assert (IBUS_IS_INPUT_CONTEXT (context)); + g_assert (x11ic); x11ic->preedit_visible = FALSE; _update_preedit (x11ic); } static void -_client_enabled_cb (IBusIMClient *client, const gchar *ic, gpointer user_data) +_context_enabled_cb (IBusInputContext *context, + X11IC *x11ic) { - X11IC *x11ic = g_hash_table_lookup (_ibus_ic_table, ic); - g_return_if_fail (x11ic != NULL); + g_assert (IBUS_IS_INPUT_CONTEXT (context)); + g_assert (x11ic); _xim_preedit_start (_xims, x11ic); } static void -_client_disabled_cb (IBusIMClient *client, const gchar *ic, gpointer user_data) +_context_disabled_cb (IBusInputContext *context, + X11IC *x11ic) { - X11IC *x11ic = g_hash_table_lookup (_ibus_ic_table, ic); - g_return_if_fail (x11ic != NULL); + g_assert (IBUS_IS_INPUT_CONTEXT (context)); + g_assert (x11ic); _xim_preedit_end (_xims, x11ic); } static void -_init_ibus_client (void) +_init_ibus (void) { - if (_client != NULL) + if (_bus != NULL) return; + ibus_init (); - ibus_im_client_register_type (NULL); - - _client = ibus_im_client_new (); + _bus = ibus_bus_new (); - if (!ibus_im_client_get_connected (_client)) { + if (!ibus_bus_is_connected (_bus)) { g_error ("Can not connect to ibus-daemon!"); } - g_signal_connect (_client, "disconnected", - G_CALLBACK (_client_disconnected_cb), NULL); - g_signal_connect (_client, "commit-string", - G_CALLBACK (_client_commit_string_cb), NULL); - g_signal_connect (_client, "forward-event", - G_CALLBACK (_client_forward_event_cb), NULL); - - g_signal_connect (_client, "update-preedit", - G_CALLBACK (_client_update_preedit_cb), NULL); - g_signal_connect (_client, "show-preedit", - G_CALLBACK (_client_show_preedit_cb), NULL); - g_signal_connect (_client, "hide-preedit", - G_CALLBACK (_client_hide_preedit_cb), NULL); - g_signal_connect (_client, "enabled", - G_CALLBACK (_client_enabled_cb), NULL); - g_signal_connect (_client, "disabled", - G_CALLBACK (_client_disabled_cb), NULL); + g_signal_connect (_bus, "disconnected", + G_CALLBACK (_bus_disconnected_cb), NULL); } static void @@ -915,9 +970,9 @@ _xim_init_IMdkit () IMFilterEventMask, KeyPressMask | KeyReleaseMask, NULL); - _init_ibus_client (); + _init_ibus (); - if (!ibus_im_client_get_connected (_client)) { + if (!ibus_bus_is_connected (_bus)) { g_warning ("Can not connect to ibus daemon"); exit (1); } @@ -926,7 +981,9 @@ _xim_init_IMdkit () static void _atexit_cb () { - ibus_im_client_kill_daemon(_client); + if (_bus) { + ibus_bus_kill(_bus); + } } static void @@ -1021,7 +1078,6 @@ main (int argc, char **argv) } _x11_ic_table = g_hash_table_new (g_direct_hash, g_direct_equal); - _ibus_ic_table = g_hash_table_new (g_str_hash, g_str_equal); _connections = g_hash_table_new (g_direct_hash, g_direct_equal); signal (SIGINT, _sighandler); diff --git a/configure.ac b/configure.ac index d978fb2..a2087a3 100644 --- a/configure.ac +++ b/configure.ac @@ -21,9 +21,9 @@ # if not 1, append datestamp to the version number. m4_define([ibus_released], [0]) -m4_define([ibus_major_version], [0]) +m4_define([ibus_major_version], [1]) m4_define([ibus_minor_version], [1]) -m4_define([ibus_micro_version], [1]) +m4_define([ibus_micro_version], [0]) m4_define(ibus_maybe_datestamp, m4_esyscmd([if test x]ibus_released[ != x1; then date +.%Y%m%d | tr -d '\n\r'; fi])) @@ -49,20 +49,34 @@ AC_ISC_POSIX AC_HEADER_STDC AM_PROG_LIBTOOL +# If only source code changed, lt_revision + 1 +# If any interface added, lt_age + 1 +# If any interfaces changed or removed, lt_current + 1 +m4_define([lt_current], [0]) +m4_define([lt_revision], [0]) +m4_define([lt_age], [0]) +LT_VERSION_INFO="lt_current:lt_revision:lt_age" +AC_SUBST(LT_VERSION_INFO) + # check inotify AC_CHECK_HEADERS([sys/inotify.h]) # check glib2 AM_PATH_GLIB_2_0 PKG_CHECK_MODULES(GLIB2, [ - glib-2.0 >= 2.16 + glib-2.0 >= 2.18 ]) PKG_CHECK_MODULES(GOBJECT2, [ - gobject-2.0 + gobject-2.0 >= 2.18 +]) +PKG_CHECK_MODULES(GIO2, [ + gio-2.0 >= 2.18 +]) +PKG_CHECK_MODULES(PYGOBJECT2, [ + pygobject-2.0 >= 2.15 ]) - -# check gtk, gdk & pygtk +# check for gtk, gdk & pygtk PKG_CHECK_MODULES(GTK2, [ gtk+-2.0 ]) @@ -74,9 +88,11 @@ PKG_CHECK_MODULES(GDK2, [ gdk-2.0 ]) -# check dbus-glib +# check for gtk-doc +GTK_DOC_CHECK(1.9) +# check for dbus-glib PKG_CHECK_MODULES(DBUS, [ - dbus-glib-1 + dbus-1 ]) # Check for Qt4 @@ -131,6 +147,9 @@ AC_SUBST(PYTHON_CFLAGS) AC_SUBST(PYTHON_INCLUDES) AC_SUBST(PYTHON_LIBS) +# +REBUILD = # +AC_SUBST(REBUILD) # define GETTEXT_* variables GETTEXT_PACKAGE=ibus @@ -158,32 +177,9 @@ AC_ARG_ENABLE(qt4-immodule, if test x"$IBUS_HAS_QT4" != x"yes"; then enable_qt4=no fi +enable_qt=no AM_CONDITIONAL(IBUS_BUILD_QT4, [test x"$enable_qt4" = x"yes" ]) -# check pygtk gconf for pygconf -AC_ARG_ENABLE(pygconf, - AS_HELP_STRING([--enable-pygconf], - [Build python gconf binding, with it ibus will not depend on gnome-python]), - [enable_pygconf=$enableval], - [enable_pygconf=no], -) - -PKG_CHECK_MODULES(PYGTK, - pygtk-2.0 >= 2.10.3, - [IBUS_HAS_PYGTK=yes], - [IBUS_HAS_PYGTK=no] -) -AC_SUBST(PYGTK_CFLAGS) -AC_SUBST(PYGTK_LIBS) -if test x"$IBUS_HAS_PYGTK" != x"yes" -a x"$enable_pygconf" = x"yes"; then - AC_MSG_ERROR(can not build python gconf binding without pygtk-2.0) -fi - -AC_PATH_PROG(PYGTK_CODEGEN, pygtk-codegen-2.0, no) -if test x"$PYGTK_CODEGEN" = x"no" -a x"$enable_pygconf" = x"yes"; then - AC_MSG_ERROR(can not build python gconf binding without pygtk-codegen-2.0) -fi - PKG_CHECK_MODULES(GCONF, [gconf-2.0 >= 2.11.1], [IBUS_HAS_GCONF=yes], @@ -191,11 +187,6 @@ PKG_CHECK_MODULES(GCONF, ) AC_SUBST(GCONF_CFLAGS) AC_SUBST(GCONF_LIBS) -if test x"$IBUS_HAS_GCONF" != x"yes" -a x"$enable_pygconf" = x"yes"; then - AC_MSG_ERROR(can not build python gconf binding without gconf-2.0) -fi - -AM_CONDITIONAL(IBUS_BUILD_PYGCONF, [test x"$enable_pygconf" = x"yes" ]) # check iso-codes AC_ARG_ENABLE(iso-codes-check, @@ -220,22 +211,17 @@ fi # OUTPUT files AC_CONFIG_FILES([ po/Makefile.in Makefile +ibus-1.0.pc ibus.spec ibus/_config.py ibus/Makefile ibus/interface/Makefile -daemon/Makefile -daemon/ibus-daemon -launcher/ibus -launcher/ibus.desktop -launcher/Makefile ui/Makefile ui/gtk/Makefile ui/gtk/ibus-ui-gtk +ui/gtk/gtkpanel.xml gconf/Makefile -gconf/ibus-gconf -lib/Makefile -lib/gtk2/Makefile +gconf/gconf.xml client/Makefile client/gtk2/Makefile client/qt4/Makefile @@ -243,10 +229,16 @@ client/x11/Makefile setup/Makefile setup/ibus-setup setup/ibus-setup.desktop +src/Makefile +bus/Makefile +bindings/Makefile +bindings/python/Makefile util/Makefile util/IMdkit/Makefile -util/gconf/Makefile icons/Makefile +docs/Makefile +docs/reference/Makefile +docs/reference/ibus/Makefile m4/Makefile ]) @@ -259,6 +251,6 @@ Build options: Build static libs $enable_static Gtk immodule dir $GTK_IM_MODULEDIR Enable Qt4 IM module $enable_qt4 - Build pygconf $enable_pygconf + Build document $enable_gtk_doc ]) diff --git a/daemon/.gitignore b/daemon/.gitignore deleted file mode 100644 index 76a720d..0000000 --- a/daemon/.gitignore +++ /dev/null @@ -1 +0,0 @@ -ibus-daemon diff --git a/daemon/Makefile.am b/daemon/Makefile.am deleted file mode 100644 index 0d32443..0000000 --- a/daemon/Makefile.am +++ /dev/null @@ -1,55 +0,0 @@ -# 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 -ibusdaemon_PYTHON = \ - bus.py \ - _dbus.py \ - config.py \ - connection.py \ - contextmanager.py \ - enginefactory.py \ - engine.py \ - factorymanager.py \ - ibusdaemon.py \ - inputcontext.py \ - lookuptable.py \ - panel.py \ - notifications.py \ - register.py \ - $(NULL) - -bin_SCRIPTS = ibus-daemon - -ibusdaemondir = $(pkgdatadir)/daemon - -CLEANFILES = \ - *.pyc \ - $(NULL) - -EXTRA_DIST = \ - ibus-daemon.in \ - $(NULL) - -test: - $(ENV) \ - DBUS_DEBUG=true \ - PYTHONPATH=$${PYTHONPATH}:$(top_srcdir) \ - IBUS_DATAROOTDIR=${datarootdir} \ - $(PYTHON) $(srcdir)/ibusdaemon.py diff --git a/daemon/_dbus.py b/daemon/_dbus.py deleted file mode 100644 index 1b007a0..0000000 --- a/daemon/_dbus.py +++ /dev/null @@ -1,319 +0,0 @@ -# vim:set et sts=4 sw=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 - -import gobject -import dbus -import dbus.service -import ibus - -class MatchRule: - def __init__(self, rule): - m = self.__eval_rule(rule) - self.__type = m.get('type', None) - self.__sender = m.get('sender', None) - self.__interface = m.get('interface', None) - self.__member = m.get('member', None) - self.__path = m.get('path', None) - self.__destination = m.get('destination', None) - self.__args = [] - for i in range(64): - arg = m.get('arg%d'%i, None) - if arg == None: - continue - self.__args.append((i, arg)) - - def __eval_rule(self, rule): - _fn = lambda **kargs: kargs - try: - return eval("_fn(%s)" % rule) - except: - raise ibus.IBusException("Parse match rule failed\n%s" % rule) - - def __cmp_bus_name(self, dbusobj, a, b): - if a == None or b == None: - return a == b - a_is_unique = a.startswith(":") - b_is_unique = b.startswith(":") - if a_is_unique == b_is_unique: - return a == b - else: - try: - if not a_is_unique: - a = dbusobj.get_name_owner(a).get_unique_name() - if not b_is_unique: - b = dbusobj.get_name_owner(b).get_unique_name() - return a == b - except: - return False - - def match_message(self, dbusobj, message): - if self.__type == 'signal' and message.get_type() != 4: - return False - - if self.__sender: - if not self.__cmp_bus_name(dbusobj, self.__sender, message.get_sender()): - return False - - if self.__interface and self.__interface != message.get_interface(): - return False - - if self.__member and self.__member != message.get_member(): - return False - - if self.__path and self.__path != message.get_path(): - return False - - if self.__destination: - if not self.__cmp_bus_name(dbusobj, self.__destination, message.get_destination()): - return False - args = message.get_args_list() - for i, arg in self.__args: - if i >= len(args): - return False - if arg != args[i]: - return False - return True - -class DBusReal(ibus.Object): - __gsignals__ = { - "name-owner-changed" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)), - } - - def __init__(self): - super(DBusReal, self).__init__() - self.__connections = dict() - self.__unique_name_dict = dict() - self.__name_dict = dict() - self.__id = 0 - - def add_connection(self, ibusconn): - self.__connections[ibusconn] = list() - ibusconn.connect("dbus-message", self.__dbus_message_cb) - ibusconn.connect("destroy", self.__ibusconn_destroy_cb) - - def register_connection(self, ibusconn): - name = ibusconn.get_unique_name() - if name: - raise ibus.IBusException("Already handled an Hello message") - self.__id += 1 - name = ":1.%d" % self.__id - self.__unique_name_dict[name] = ibusconn - ibusconn.set_unique_name(name) - return name - - def list_names(self): - return self.__name_dict.keys() + self.__unique_name_dict.keys() - - def list_activatable_names(self): - return self.__name_dict.keys() + self.__unique_name_dict.keys() - - def name_has_owner(self, name): - if name.startswith(":"): - return name in self.__unique_name_dict - return name in self.__name_dict - - def get_name_owner(self, name): - if name == dbus.BUS_DAEMON_NAME or \ - name == ibus.IBUS_NAME: - return name - if name.startswith(":"): - if name in self.__unique_name_dict: - return name - elif name in self.__name_dict: - ibusconn = self.__name_dict[name] - return ibusconn.get_unique_name() - - raise ibus.IBusException( - "org.freedesktop.DBus.Error.NameHasNoOwner:\n" - "\tCould not get owner of name '%s': no such name" % name) - - def start_service_by_name(self, name, flags): - return 0 - - def get_connection_unix_user(self, connection_name): - return 0 - - def add_match(self, ibusconn, rule): - self.__connections[ibusconn].append(MatchRule(rule)) - - def remove_match(self, ibusconn, rule): - pass - - def request_name(self, ibusconn, name, flags): - if name.startswith(":"): - raise ibus.IBusException("Only unique name can start with ':'") - if not ibusconn.get_unique_name(): - raise ibus.IBusException("Can not call any method before Hello.") - if name in ibusconn.get_names(): - return 0 - if name in self.__name_dict: - raise ibus.IBusException("Name has been registered") - self.__name_dict[name] = ibusconn - self.emit("name-owner-changed", name, "", ibusconn.get_unique_name()) - ibusconn.add_name(name) - return 1 - - def release_name(self, ibusconn, name): - if name.startswith(":"): - raise ibus.IBusException("Only unique name can start with ':'") - if name not in ibusconn.get_names(): - return 2 - del self.__name_dict[name] - self.emit("name-owner-changed", name, ibusconn.get_unique_name(), "") - ibusconn.remove_name(name) - return 1 - - def dispatch_dbus_signal(self, message): - for conn, rules in self.__connections.items(): - for rule in rules: - if rule.match_message(self, message): - conn.send_message(message) - break - def get_connection_by_name(self, name): - if not name.startswith(":"): - return None - return self.__unique_name_dict.get(name, None) - - def do_name_owner_changed(self, name, old_name, new_name): - message = dbus.lowlevel.SignalMessage(dbus.BUS_DAEMON_PATH, - dbus.BUS_DAEMON_IFACE, "NameOwnerChanged") - # message.set_sender(dbus.BUS_DAEMON_NAME) - message.append(name) - message.append(old_name) - message.append(new_name) - self.dispatch_dbus_signal(message) - - def __dbus_message_cb(self, ibusconn, message): - dest = message.get_destination() - message.set_sender(ibusconn.get_unique_name()) - if (not dest): - if message.get_type() != 4: # Is not signal - raise ibus.IBusException("Message without destination") - self.dispatch_dbus_signal(message) - return True - - if not dest.startswith(":"): - raise ibus.IBusException("Destination of message must be an unique name") - - destconn = self.__unique_name_dict.get(dest, None) - if destconn == None: - raise ibus.IBusException("Can not find the destination(%s)" % dest) - - destconn.send_message(message) - return True - - def __ibusconn_destroy_cb(self, ibusconn): - name = ibusconn.get_unique_name() - for name in ibusconn.get_names(): - del self.__name_dict[name] - self.emit("name-owner-changed", name, ibusconn.get_unique_name(), "") - if name: - del self.__unique_name_dict[name] - self.emit("name-owner-changed", name, name, "") - - del self.__connections[ibusconn] - -bus = DBusReal() - -class DBus(dbus.service.Object): - - method = lambda **args: \ - dbus.service.method(dbus_interface = dbus.BUS_DAEMON_IFACE, \ - **args) - - signal = lambda **args: \ - dbus.service.signal(dbus_interface = dbus.BUS_DAEMON_IFACE, \ - **args) - - __bus = bus - - def __init__(self, ibusconn): - super(DBus, self).__init__(ibusconn.get_dbusconn(), dbus.BUS_DAEMON_PATH) - self.__ibusconn = ibusconn - self.__name = DBus.__bus.register_connection(self.__ibusconn) - self.__active = False - self.__bus.add_connection(ibusconn) - - @method(out_signature="s") - def Hello(self): - if not self.__active: - self.__active = True - return self.__name - raise ibus.IBusException("Already handled an Hello message") - - @method(out_signature="as") - def ListNames(self): - return DBus.__bus.list_names() - - @method(out_signature="as") - def ListActivatableNames(self): - return DBus.__bus.list_activatable_names() - - @method(in_signature="s", out_signature="as") - def NameHasOwner(self, name): - return DBus.__bus.name_has_owner(name) - - @method(in_signature="si", out_signature="i") - def StartServiceByName(self, name, flags): - return DBus.__bus.start_service_by_name(name, flags) - - @method(in_signature="s", out_signature="s") - def GetNameOwner(self, name): - return DBus.__bus.get_name_owner(name) - - @method(in_signature="s", out_signature="i") - def GetConnectionUnixUser(self, connection_name): - return DBus.__bus.get_connection_unix_user(connection_name) - - @method(in_signature="s") - def AddMatch(self, rule): - return DBus.__bus.add_match(self.__ibusconn, rule) - - @method(in_signature="s") - def RemoveMatch(self, rule): - return DBus.__bus.remove_match(self.__ibusconn, rule) - - @method(out_signature="s") - def GetId(self): - return self.__name - - @method(in_signature="su", out_signature="u") - def RequestName(self, name, flags): - return self.__bus.request_name(self.__ibusconn, name, flags) - - @method(in_signature="s", out_signature="u") - def ReleaseName(self, name): - return self.__bus.release_name(self.__ibusconn, name) - - @signal(signature="sss") - def NameOwnerChanged(self, name, old_owner, new_owner): - pass - - @signal(signature="s") - def NameLost(self, name): - pass - - @signal(signature="s") - def NameAcquired(self, name): - pass diff --git a/daemon/bus.py b/daemon/bus.py deleted file mode 100644 index 5c5cb3a..0000000 --- a/daemon/bus.py +++ /dev/null @@ -1,714 +0,0 @@ -# vim:set et sts=4 sw=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 - -import sys -import ibus -import gobject -from ibus import keysyms -from ibus import modifier -from contextmanager import ContextManager -from factorymanager import FactoryManager -from panel import Panel, DummyPanel -from notifications import Notifications, DummyNotifications -from config import Config, DummyConfig -from register import Register -import _dbus - -from gettext import dgettext -_ = lambda a : dgettext("ibus", a) -N_ = lambda a : a - -class IBus(ibus.Object): - def __init__(self): - super(IBus, self).__init__() - _dbus.bus.connect("name-owner-changed", self.__dbus_name_owner_changed_cb) - self.__context_manager = ContextManager() - self.__factory_manager = FactoryManager() - self.__factory_manager.connect("default-factory-changed", - self.__factory_manager_default_factory_changed_cb) - - self.__panel = DummyPanel() - self.__panel_handlers = list() - self.__install_panel_handlers() - - self.__notifications = DummyNotifications() - self.__notifications_handlers = list() - self.__install_notifications_handlers() - - self.__no_engine_notification_id = 0 - self.__no_engine_notification_show = True - - self.__config = DummyConfig() - self.__config_handlers = list() - self.__install_config_handlers() - - self.__register = Register() - - self.__focused_context = None - self.__last_focused_context = None - self.__context_handlers = list() - - self.__connections = list() - - self.__prev_key = None - self.__config_load_settings () - - def __config_load_settings (self): - self.__shortcut_trigger = self.__load_config_shortcut( - "general", "keyboard_shortcut_trigger", - ibus.CONFIG_GENERAL_SHORTCUT_TRIGGER_DEFAULT) - self.__shortcut_next_engine = self.__load_config_shortcut( - "general", "keyboard_shortcut_next_engine", - ibus.CONFIG_GENERAL_SHORTCUT_NEXT_ENGINE_DEFAULT) - self.__shortcut_prev_engine = self.__load_config_shortcut( - "general", "keyboard_shortcut_next_engine", - ibus.CONFIG_GENERAL_SHORTCUT_NEXT_ENGINE_DEFAULT) - self.__default_factory = None - - def __dbus_name_owner_changed_cb(self, bus, name, old_name, new_name): - if name == ibus.IBUS_PANEL_NAME: - self.__panel_changed(new_name) - elif name == ibus.IBUS_CONFIG_NAME: - self.__config_changed(new_name) - elif name == ibus.IBUS_NOTIFICATIONS_NAME: - self.__notifications_changed(new_name) - - def __factory_manager_default_factory_changed_cb(self, manager, factory): - if self.__default_factory != factory: - self.__default_factory = factory - if factory == None: - return - self.__config.set_value("general", "default_factory", factory.get_object_path()) - - def __load_config_shortcut(self, section, name, default_value): - - # load trigger - shortcut_strings = default_value - try: - shortcut_strings = self.__config.get_value(section, name) - except: - pass - shortcuts = [] - for s in shortcut_strings: - keyval, keymask = self.__parse_shortcut_string(s) - if keyval != 0: - shortcuts.append((keyval, keymask)) - return shortcuts - - def new_connection(self, conn): - IBusProxy(self, conn) - conn.connect("destroy", self.__conn_destroy_cb) - self.__connections.append(conn) - - def __conn_destroy_cb(self, conn): - self.__connections.remove(conn) - - ########################################################## - # methods for im context - ########################################################## - def __load_default_factory(self): - if self.__default_factory != None: - return - try: - factory_path = self.__config.get_value("general", "default_factory") - self.__default_factory = self.__factory_manager.get_factory(factory_path) - except: - pass - if self.__default_factory != None: - self.__factory_manager.set_default_factory(self.__default_factory) - return - - def create_input_context(self, name, conn): - context = self.__context_manager.create_input_context(name, conn) - self.__load_default_factory() - if self.__default_factory != None: - engine = self.__default_factory.create_engine() - context.set_engine(engine) - return context.get_id() - - def release_input_context(self, ic, conn): - self.__context_manager.release_input_context(ic, conn) - - def focus_in(self, ic, conn): - context = self.__lookup_context(ic, conn) - if not context.get_support_focus(): - return - if self.__focused_context != context and self.__focused_context != None: - self.__remove_focused_context_handlers() - self.__focused_context.focus_out() - - self.__focused_context = context - self.__install_focused_context_handlers() - - self.__panel.focus_in(context.get_id()) - self.__last_focused_context = context - context.focus_in() - self.__prev_key = None - - def focus_out(self, ic, conn): - context = self.__lookup_context(ic, conn) - - if context == self.__focused_context: - self.__remove_focused_context_handlers() - self.__focused_context = None - self.__panel.focus_out(context.get_id()) - - context.focus_out() - - def reset(self, ic, conn): - context = self.__lookup_context(ic, conn) - context.reset() - - def is_enabled(self, ic, conn): - context = self.__lookup_context(ic, conn) - return context.is_enabled() - - def set_capabilities(self, ic, caps, conn): - context = self.__lookup_context(ic, conn) - return context.set_capabilities(caps) - - def process_key_event(self, ic, keyval, is_press, state, - conn, reply_cb, error_cb): - context = self.__lookup_context(ic, conn) - - # focus in the context, if context supports focus - if context != self.__focused_context and context.get_support_focus(): - self.focus_in(ic, conn) - - if self.__filter_keyboard_shortcuts(context, keyval, is_press, state): - reply_cb(True) - return - else: - context.process_key_event(keyval, is_press, state, reply_cb, error_cb) - - def set_cursor_location(self, ic, x, y, w, h, conn): - context = self.__lookup_context(ic, conn) - context.set_cursor_location(x, y, w, h) - if context == self.__focused_context: - self.__panel.set_cursor_location(x, y, w, h) - - def __context_enable(self, context): - if context.get_engine() == None: - self.__load_default_factory() - if self.__default_factory == None: - self.__default_factory = self.__factory_manager.get_default_factory() - if self.__default_factory: - engine = self.__default_factory.create_engine() - engine.focus_in() - context.set_engine(engine) - else: - if self.__no_engine_notification_show: - self.__no_engine_notification_id = self.__notifications.notify( - self.__no_engine_notification_id, - "ibus", _("Cannot enable input engine"), - _("IBus can not enable input engine, because IBus does not load any input engines!\n" - "Please use ibus-setup program to load some input engines."), - ["Setup", _("Setup"), "NoAgain", _("Don't show this again")], - 15000) - - if context.get_engine() != None: - context.set_enable(True) - self.__panel.states_changed() - - def __context_disable(self, context): - context.set_enable(False) - self.__panel.reset() - self.__panel.states_changed() - - def __context_next_factory(self, context): - old_factory = context.get_factory() - new_factory = self.__factory_manager.get_next_factory(old_factory) - self.__factory_manager.set_default_factory(new_factory) - engine = new_factory.create_engine() - self.__panel.reset() - engine.focus_in() - context.set_engine(engine) - self.__panel.states_changed() - - def __match_keyboard_shortcuts(self, keyval, is_press, state, shortcuts): - for sc in shortcuts: - if state == sc[1] and keyval == sc[0]: - if state & modifier.RELEASE_MASK == 0: - return True - if self.__prev_key[0] == keyval and \ - self.__prev_key[1] == True: - return True - return False - - def __filter_keyboard_shortcuts(self, context, keyval, is_press, state): - state = state & (modifier.CONTROL_MASK | \ - modifier.SHIFT_MASK | \ - modifier.MOD1_MASK | \ - modifier.SUPER_MASK | \ - modifier.HYPER_MASK | \ - modifier.META_MASK) - if not is_press: - state = state | modifier.RELEASE_MASK - - retval = True - if self.__match_keyboard_shortcuts(keyval, - is_press, state, self.__shortcut_trigger): - if context.is_enabled(): - self.__context_disable(context) - else: - self.__context_enable(context) - retval = True - elif self.__match_keyboard_shortcuts(keyval, - is_press, state, self.__shortcut_next_engine): - if not context.is_enabled(): - self.__context_enable(context) - else: - self.__context_next_factory(context) - else: - retval = False - - self.__prev_key = (keyval, is_press, state) - return retval - - def __lookup_context(self, ic, conn): - return self.__context_manager.lookup_context(ic, conn) - - def __install_focused_context_handlers(self): - # Install all callback functions - if self.__focused_context == None: - return - signals = ( - ("update-preedit", self.__update_preedit_cb), - ("show-preedit", self.__show_preedit_cb), - ("hide-preedit", self.__hide_preedit_cb), - ("update-aux-string", self.__update_aux_string_cb), - ("show-aux-string", self.__show_aux_string_cb), - ("hide-aux-string", self.__hide_aux_string_cb), - ("update-lookup-table", self.__update_lookup_table_cb), - ("show-lookup-table", self.__show_lookup_table_cb), - ("hide-lookup-table", self.__hide_lookup_table_cb), - ("page-up-lookup-table", self.__page_up_lookup_table_cb), - ("page-down-lookup-table", self.__page_down_lookup_table_cb), - ("cursor-up-lookup-table", self.__cursor_up_lookup_table_cb), - ("cursor-down-lookup-table", self.__cursor_down_lookup_table_cb), - ("register-properties", self.__register_properties_cb), - ("update-property", self.__update_property_cb), - ("engine-lost", self.__engine_lost_cb), - ("destroy", self.__context_destroy_cb) - ) - for name, handler in signals: - id = self.__focused_context.connect(name, handler) - self.__context_handlers.append(id) - - def __remove_focused_context_handlers(self): - if self.__focused_context == None: - return - map(self.__focused_context.disconnect, self.__context_handlers) - self.__context_handlers = [] - - def __update_preedit_cb(self, context, text, attrs, cursor_pos, visible): - assert self.__focused_context == context - self.__panel.update_preedit(text, attrs, cursor_pos, visible) - - def __show_preedit_cb(self, context): - assert self.__focused_context == context - self.__panel.show_preedit() - - def __hide_preedit_cb(self, context): - assert self.__focused_context == context - self.__panel.hide_preedit() - - def __update_aux_string_cb(self, context, text, attrs, visible): - assert self.__focused_context == context - self.__panel.update_aux_string(text, attrs, visible) - - def __show_aux_string_cb(self, context): - assert self.__focused_context == context - self.__panel.show_aux_string() - - def __hide_aux_string_cb(self, context): - assert self.__focused_context == context - self.__panel.hide_aux_string() - - def __update_lookup_table_cb(self, context, lookup_table, visible): - assert self.__focused_context == context - self.__panel.update_lookup_table(lookup_table, visible) - - def __show_lookup_table_cb(self, context): - assert self.__focused_context == context - self.__panel.show_lookup_table() - - def __hide_lookup_table_cb(self, context): - assert self.__focused_context == context - self.__panel.hide_lookup_table() - - def __page_up_lookup_table_cb(self, context): - assert self.__focused_context == context - self.__panel.page_up_lookup_table() - - def __page_down_lookup_table_cb(self, context): - assert self.__focused_context == context - self.__panel.page_down_lookup_table() - - def __cursor_up_lookup_table_cb(self, context): - assert self.__focused_context == context - self.__panel.cursor_up_lookup_table() - - def __cursor_down_lookup_table_cb(self, context): - assert self.__focused_context == context - self.__panel.cursor_down_lookup_table() - - def __register_properties_cb(self, context, props): - assert self.__focused_context == context - self.__panel.register_properties(props) - - - def __update_property_cb(self, context, prop): - assert self.__focused_context == context - self.__panel.update_property(prop) - - def __engine_lost_cb(self, context): - assert self.__focused_context == context - self.__panel.reset() - - def __context_destroy_cb(self, context): - assert context == self.__focused_context - self.__remove_focused_context_handlers() - self.__panel.focus_out(context.get_id()) - self.__focused_context = None - - ########################################################## - # methods for im engines - ########################################################## - def register_factories(self, object_paths, conn): - self.__factory_manager.register_factories(object_paths, conn) - - - ########################################################## - # methods for panel - ########################################################## - def __panel_changed(self, bus_name): - if not isinstance(self.__panel, DummyPanel): - self.__uninstall_panel_handlers() - self.__panel.destroy() - ibusconn = _dbus.bus.get_connection_by_name(bus_name) - if ibusconn == None: - self.__panel = DummyPanel() - else: - self.__panel = Panel(ibusconn) - self.__install_panel_handlers() - if self.__focused_context: - self.__panel.focus_in(self.__focused_context.get_id()) - - def __install_panel_handlers(self): - signals = ( - ("page-up", self.__panel_page_up_cb), - ("page-down", self.__panel_page_down_cb), - ("cursor-up", self.__panel_cursor_up_cb), - ("cursor-down", self.__panel_cursor_down_cb), - ("property-activate", self.__panel_property_active_cb), - ("property-show", self.__panel_property_show_cb), - ("property-hide", self.__panel_property_hide_cb), - ("destroy", self.__panel_destroy_cb) - ) - - for signal, handler in signals: - id = self.__panel.connect(signal, handler) - self.__panel_handlers.append(id) - - def __uninstall_panel_handlers(self): - map(lambda id:self.__panel.disconnect(id), self.__panel_handlers) - self.__panel_handlers = list() - - - def __panel_page_up_cb(self, panel): - assert panel == self.__panel - if self.__focused_context: - self.__focused_context.page_up() - - def __panel_page_down_cb(self, panel): - assert panel == self.__panel - if self.__focused_context: - self.__focused_context.page_down() - - def __panel_cursor_up_cb(self, panel): - assert panel == self.__panel - if self.__focused_context: - self.__focused_context.cursor_up() - - def __panel_cursor_down_cb(self, panel): - assert panel == self.__panel - if self.__focused_context: - self.__focused_context.cursor_down() - - def __panel_property_active_cb(self, panel, prop_name, prop_state): - assert panel == self.__panel - if self.__focused_context: - self.__focused_context.property_activate(prop_name, prop_state) - - def __panel_property_show_cb(self, panel, prop_name): - assert panel == self.__panel - if self.__focused_context: - self.__focused_context.property_show(prop_name) - - def __panel_property_hide_cb(self, panel, prop_name): - assert panel == self.__panel - if self.__focused_context: - self.__focused_context.property_hide(prop_name) - - def __panel_destroy_cb(self, panel): - if panel == self.__panel: - self.__uninstall_panel_handlers() - self.__panel = DummyPanel() - - ########################################################## - # methods for notifications - ########################################################## - def __notifications_changed(self, bus_name): - if not isinstance(self.__notifications, DummyNotifications): - self.__uninstall_notifications_handlers() - self.__notifications.destroy() - ibusconn = _dbus.bus.get_connection_by_name(bus_name) - if ibusconn == None: - self.__notifications = DummyNotifications() - else: - self.__notifications = Notifications(ibusconn) - self.__install_notifications_handlers() - - def __install_notifications_handlers(self): - signals = ( - ("notification-closed", self.__notifications_notification_closed_cb), - ("action-invoked", self.__notifications_action_invoked_cb), - ("destroy", self.__notifications_destroy_cb) - ) - - for signal, handler in signals: - id = self.__notifications.connect(signal, handler) - self.__notifications_handlers.append(id) - - def __uninstall_notifications_handlers(self): - map(lambda id:self.__notifications.disconnect(id), self.__notifications_handlers) - self.__notifications_handlers = list() - - def __notifications_notification_closed_cb(self, notifications, id, reason): - pass - - def __notifications_action_invoked_cb(self, notifications, id, action_key): - if id == self.__no_engine_notification_id: - if action_key == "NoAgain": - self.__no_engine_notification_show = False - elif action_key == "Setup": - self.__panel.start_setup() - - - def __notifications_destroy_cb(self, notifications): - if notifications == self.__notifications: - self.__uninstall_notifications_handlers() - self.__notifications = DummyNotifications() - - - ########################################################## - # methods for config - ########################################################## - def __config_changed(self, bus_name): - ibusconn = _dbus.bus.get_connection_by_name(bus_name) - self.__uninstall_config_handlers() - self.__config.destroy() - self.__config = Config(ibusconn) - self.__install_config_handlers() - gobject.idle_add (self.__config_load_settings) - - def __install_config_handlers(self): - signals = ( - ("value-changed", self.__config_value_changed_cb), - ("destroy", self.__config_destroy_cb), - ) - for signal, handler in signals: - id = self.__config.connect(signal, handler) - self.__config_handlers.append(id) - - def __uninstall_config_handlers(self): - map(lambda id:self.__config.disconnect(id), self.__config_handlers) - self.__config_handlers = list() - - def __parse_shortcut_string(self, string): - keys = string.split("+") - keymask = 0 - for name, mask in modifier.MODIFIER_NAME_TABLE: - if name in keys[:-1]: - keymask |= mask - keyname = keys[-1] - keyval = keysyms.name_to_keycode(keyname) - if keyval == None: - keyval = 0 - - return keyval, keymask - - def __config_value_changed_cb (self, config, section, name, value): - if section == "general": - if name == "keyboard_shortcut_trigger": - self.__shortcut_trigger = self.__load_config_shortcut( - "general", "keyboard_shortcut_trigger", - ibus.CONFIG_GENERAL_SHORTCUT_TRIGGER_DEFAULT) - elif name =="keyboard_shortcut_next_engine": - self.__shortcut_next_engine = self.__load_config_shortcut( - "general", "keyboard_shortcut_next_engine", - ibus.CONFIG_GENERAL_SHORTCUT_NEXT_ENGINE_DEFAULT) - - def __config_destroy_cb(self, config): - if config == self.__config: - self.__config = DefaultConfig() - - ########################################################## - # engine register methods - ########################################################## - def register_list_engines(self, conn): - return self.__register.list_engines() - - def register_reload_engines(self, conn): - return self.__register.reload_engines() - - def register_start_engine(self, lang, name, conn): - return self.__register.start_engine(lang, name) - - def register_restart_engine(self, lang, name, conn): - return self.__register.restart_engine(lang, name) - - def register_stop_engine(self, lang, name, conn): - return self.__register.stop_engine(lang, name) - - ########################################################## - # general methods - ########################################################## - def get_factories(self): - return self.__factory_manager.get_factories() - - def get_factory_info(self, factory_path): - return self.__factory_manager.get_factory_info(factory_path) - - def set_factory(self, factory_path): - if self.__focused_context == None: - return - self.__panel.reset() - factory = self.__factory_manager.get_factory(factory_path) - self.__factory_manager.set_default_factory(factory) - engine = factory.create_engine() - self.__focused_context.set_engine(engine) - self.__focused_context.set_enable(True) - engine.focus_in() - self.__panel.states_changed() - - def get_input_context_states(self, ic, conn): - factory_path = "" - context = self.__lookup_context(ic, conn) - if context.get_factory() != None: - factory_path = context.get_factory().get_object_path() - return factory_path, context.is_enabled() - - def kill(self, conn): - print "be killed" - sys.exit(0) - - -class IBusProxy(ibus.IIBus): - def __init__(self, bus, conn): - super(IBusProxy, self).__init__(conn.get_dbusconn(), ibus.IBUS_PATH) - self.__ibus = bus - self.__conn = conn - self.__conn.connect("destroy", self.__conn_destroy_cb) - - def __conn_destroy_cb(self, conn): - self.__conn = None - self.__ibus = None - - def GetIBusAddress(self, dbusconn): - return self.__ibus_addr - - def CreateInputContext(self, context_name, dbusconn): - return self.__ibus.create_input_context(context_name, self.__conn) - - def ReleaseInputContext(self, ic, dbusconn): - self.__ibus.release_input_context(ic, self.__conn) - - def RegisterFactories(self, object_paths, dbusconn): - self.__ibus.register_factories(object_paths, self.__conn) - - def UnregisterEngines(self, object_paths, dbusconn): - self.__ibus.unregister_engines(object_paths, self.__conn) - - def RegisterPanel(self, object_path, replace, dbusconn): - self.__ibus.register_panel(object_path, replace, self.__conn) - - def RegisterConfig(self, object_path, replace, dbusconn): - self.__ibus.register_config(object_path, replace, self.__conn) - - def ProcessKeyEvent(self, ic, keyval, is_press, state, \ - dbusconn, reply_cb, error_cb): - try: - self.__ibus.process_key_event(ic, keyval, is_press, state, - self.__conn, reply_cb, error_cb) - except Exception, e: - error_cb(e) - - def SetCursorLocation(self, ic, x, y, w, h, dbusconn): - self.__ibus.set_cursor_location(ic, x, y, w, h, self.__conn) - - def FocusIn(self, ic, dbusconn): - self.__ibus.focus_in(ic, self.__conn) - - def FocusOut(self, ic, dbusconn): - self.__ibus.focus_out(ic, self.__conn) - - def Reset(self, ic, dbusconn): - self.__ibus.reset(ic, self.__conn) - - def IsEnabled(self, ic, dbusconn): - return self.__ibus.is_enabled(ic, self.__conn) - - def SetCapabilities(self, ic, caps, dbusconn): - return self.__ibus.set_capabilities(ic, caps, self.__conn) - - def GetFactories(self, dbusconn): - return self.__ibus.get_factories() - - def GetFactoryInfo(self, factory_path, dbusconn): - return self.__ibus.get_factory_info(factory_path) - - def SetFactory(self, factory_path, dbusconn): - return self.__ibus.set_factory(factory_path) - - def GetInputContextStates(self, ic, dbusconn): - return self.__ibus.get_input_context_states(ic, self.__conn) - - def RegisterListEngines(self, dbusconn): - return self.__ibus.register_list_engines(self.__conn) - - def RegisterReloadEngines(self, dbusconn): - return self.__ibus.register_reload_engines(self.__conn) - - def RegisterStartEngine(self, lang, name, dbusconn): - return self.__ibus.register_start_engine(lang, name, self.__conn) - - def RegisterRestartEngine(self, lang, name, dbusconn): - return self.__ibus.register_restart_engine(lang, name, self.__conn) - - def RegisterStopEngine(self, lang, name, dbusconn): - return self.__ibus.register_stop_engine(lang, name, self.__conn) - - def Kill(self, dbusconn, reply_cb, error_cb): - reply_cb() - self.__ibus.kill(self.__conn) - diff --git a/daemon/config.py b/daemon/config.py deleted file mode 100644 index 3a41c9c..0000000 --- a/daemon/config.py +++ /dev/null @@ -1,101 +0,0 @@ -# vim:set et sts=4 sw=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 - -__all__ = ( - "Config", - "DefaultConfig" -) - -import gobject -import ibus - -class Config(ibus.Object): - __gsignals__ = { - "value-changed" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)), - } - - def __init__(self, ibusconn): - super(Config, self).__init__() - self.__ibusconn = ibusconn - self.__config = self.__ibusconn.get_object(ibus.IBUS_CONFIG_PATH) - - self.__ibusconn.connect("destroy", self.__ibusconn_destroy_cb) - self.__ibusconn.connect("dbus-signal", self.__dbus_signal_cb) - - def get_value(self, section, name, **kargs): - return self.__config.GetValue(section, name, **kargs) - - def set_value(self, section, name, value, **kargs): - return self.__config.SetValue(section, name, value, **kargs) - - def destroy(self): - if self.__ibusconn != None: - self.__config.Destroy(**ibus.DEFAULT_ASYNC_HANDLERS) - - self.__ibusconn = None - self.__config = None - ibus.Object.destroy(self) - - # signal callbacks - def __ibusconn_destroy_cb(self, ibusconn): - self.__ibusconn = None - self.destroy() - - def __dbus_signal_cb(self, ibusconn, message): - if message.is_signal(ibus.IBUS_CONFIG_IFACE, "ValueChanged"): - args = message.get_args_list() - self.emit("value-changed", args[0], args[1], args[2]) - return False - -gobject.type_register(Config) - -class DummyConfig(ibus.Object): - __gsignals__ = { - "value-changed" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)), - } - - def __init__(self): - super(DummyConfig, self).__init__() - self.__values = dict() - - def get_value(self, section, name, **kargs): - value = self.__values.get((section, name), None) - if value == None: - raise ibus.IBusException("Can not get config section=%s name=%s" % (section, name)) - return value - - def set_value(self, section, name, value, **kargs): - old_value = self.__values.get((section, name), None) - if value == old_value: - return - if value == None: - del self.__values[(section, name)] - else: - self.__values[(section, name)] = value - self.emit("value-changed", section, name, value) - -gobject.type_register(DummyConfig) diff --git a/daemon/connection.py b/daemon/connection.py deleted file mode 100644 index f897e08..0000000 --- a/daemon/connection.py +++ /dev/null @@ -1,98 +0,0 @@ -# vim:set et sts=4 sw=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 - -import dbus.lowlevel -import ibus -import gobject - -class Connection(ibus.Object): - __gsignals__ = { - "dbus-signal" : ( - gobject.SIGNAL_RUN_LAST, - gobject.TYPE_BOOLEAN, - (gobject.TYPE_PYOBJECT, ) - ), - "dbus-message" : ( - gobject.SIGNAL_RUN_LAST, - gobject.TYPE_BOOLEAN, - (gobject.TYPE_PYOBJECT, ) - ) - } - def __init__(self, dbusconn): - super(Connection, self).__init__() - self.__dbusconn = dbusconn - self.__unique_name = "" - self.__names = set() - dbusconn.add_message_filter(self.message_filter_cb) - - def message_filter_cb(self, dbusconn, message): - if message.is_signal(dbus.LOCAL_IFACE, "Disconnected"): - self.destroy() - return dbus.lowlevel.HANDLER_RESULT_HANDLED - - if message.get_destination() in set(["org.freedesktop.IBus", "org.freedesktop.DBus"]): - return dbus.lowlevel.HANDLER_RESULT_NOT_YET_HANDLED - - if message.get_type() == 4: # is signal - if self.emit("dbus-signal", message): - return dbus.lowlevel.HANDLER_RESULT_HANDLED - if self.emit("dbus-message", message): - return dbus.lowlevel.HANDLER_RESULT_HANDLED - return dbus.lowlevel.HANDLER_RESULT_NOT_YET_HANDLED - - def get_object(self, path): - return self.__dbusconn.get_object("no.name", path) - - def emit_dbus_signal(self, name, *args): - message = dbus.lowlevel.SignalMessage(ibus.IBUS_PATH, ibus.IBUS_IFACE, name) - message.append(*args) - self.send_message(message) - - def send_message(self, message): - self.__dbusconn.send_message(message) - self.__dbusconn.flush() - - def do_destroy(self): - self.__dbusconn = None - - def get_dbusconn(self): - return self.__dbusconn - - def get_unique_name(self): - return self.__unique_name - - def set_unique_name(self, name): - assert name - assert not self.__unique_name - self.__unique_name = name - - def get_names(self): - return self.__names - - def add_name(self, name): - if name not in self.__names: - self.__names.add(name) - - def remove_name(self, name): - if name in self.__names: - self.__names.remove(name) - -gobject.type_register(Connection) diff --git a/daemon/contextmanager.py b/daemon/contextmanager.py deleted file mode 100644 index 44b4bdb..0000000 --- a/daemon/contextmanager.py +++ /dev/null @@ -1,45 +0,0 @@ -# vim:set et sts=4 sw=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 - -import ibus -from inputcontext import InputContext - -class ContextManager(ibus.Object): - def __init__(self): - super(ContextManager, self).__init__() - self._contexts = {} - - def create_input_context(self, name, ibusconn): - context = InputContext(name, ibusconn) - self._contexts[context.get_id()] = context - context.connect("destroy", self._context_destroy_cb) - return context - - def release_input_context(self, ic, ibusconn): - context = self._contexts[ic] - context.destroy() - - def lookup_context(self, ic, ibusconn): - return self._contexts[ic] - - def _context_destroy_cb(self, context): - del self._contexts[context.get_id()] - diff --git a/daemon/engine.py b/daemon/engine.py deleted file mode 100644 index e4bc048..0000000 --- a/daemon/engine.py +++ /dev/null @@ -1,221 +0,0 @@ -# vim:set et sts=4 sw=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 - -import gobject -import ibus - -class Engine(ibus.Object): - __gsignals__ = { - "commit-string" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_PYOBJECT, )), - "forward-key-event" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_UINT, gobject.TYPE_BOOLEAN, gobject.TYPE_UINT )), - "update-preedit" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_INT, gobject.TYPE_BOOLEAN)), - "show-preedit" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "hide-preedit" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "update-aux-string" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_BOOLEAN)), - "show-aux-string" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "hide-aux-string" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "update-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_PYOBJECT, gobject.TYPE_BOOLEAN)), - "show-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "hide-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "page-up-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "page-down-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "cursor-up-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "cursor-down-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "register-properties" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_PYOBJECT, )), - "update-property" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_PYOBJECT, )), - } - - def __init__(self, factory, ibusconn, object_path): - super(Engine, self).__init__() - self.__factory = factory - self.__ibusconn = ibusconn - self.__object_path = object_path - self.__engine = ibusconn.get_object(self.__object_path) - self.__lookup_table = ibus.LookupTable() - self.__ibusconn.connect("destroy", self.__ibusconn_destroy_cb) - - def get_factory(self): - return self.__factory - - def get_object_path(self): - return self.__object_path - - def handle_dbus_signal(self, message): - if message.is_signal(ibus.IBUS_ENGINE_IFACE, "CommitString"): - args = message.get_args_list() - self.emit("commit-string", args[0]) - elif message.is_signal(ibus.IBUS_ENGINE_IFACE, "ForwardKeyEvent"): - args = message.get_args_list() - self.emit("forward-key-event", args[0], bool(arg[1]), arg[2]) - elif message.is_signal(ibus.IBUS_ENGINE_IFACE, "UpdatePreedit"): - args = message.get_args_list() - self.emit("update-preedit", args[0], args[1], args[2], args[3]) - elif message.is_signal(ibus.IBUS_ENGINE_IFACE, "ShowPreedit"): - self.emit("show-preedit") - elif message.is_signal(ibus.IBUS_ENGINE_IFACE, "HidePreedit"): - self.emit("hide-preedit") - elif message.is_signal(ibus.IBUS_ENGINE_IFACE, "UpdateAuxString"): - args = message.get_args_list() - self.emit("update-aux-string", args[0], args[1], args[2]) - elif message.is_signal(ibus.IBUS_ENGINE_IFACE, "ShowAuxString"): - self.emit("show-aux-string") - elif message.is_signal(ibus.IBUS_ENGINE_IFACE, "HideAuxString"): - self.emit("hide-aux-string") - elif message.is_signal(ibus.IBUS_ENGINE_IFACE, "UpdateLookupTable"): - args = message.get_args_list() - self.emit("update-lookup-table", args[0], args[1]) - elif message.is_signal(ibus.IBUS_ENGINE_IFACE, "ShowLookupTable"): - self.emit("show-lookup-table") - elif message.is_signal(ibus.IBUS_ENGINE_IFACE, "HideLookupTable"): - self.emit("hide-lookup-table") - elif message.is_signal(ibus.IBUS_ENGINE_IFACE, "PageUpLookupTable"): - self.emit("page-up-lookup-table") - elif message.is_signal(ibus.IBUS_ENGINE_IFACE, "PageDownLookupTable"): - self.emit("page-down-lookup-table") - elif message.is_signal(ibus.IBUS_ENGINE_IFACE, "CursorUpLookupTable"): - self.emit("cursor-up-lookup-table") - elif message.is_signal(ibus.IBUS_ENGINE_IFACE, "CursorDownLookupTable"): - self.emit("cursor-down-lookup-table") - elif message.is_signal(ibus.IBUS_ENGINE_IFACE, "RegisterProperties"): - args = message.get_args_list() - self.emit("register-properties", args[0]) - elif message.is_signal(ibus.IBUS_ENGINE_IFACE, "UpdateProperty"): - args = message.get_args_list() - self.emit("update-property", args[0]) - else: - return False - - return True - - def focus_in(self): - self.__engine.FocusIn(**ibus.DEFAULT_ASYNC_HANDLERS) - - def focus_out(self): - self.__engine.FocusOut(**ibus.DEFAULT_ASYNC_HANDLERS) - - def reset(self): - self.__engine.Reset(**ibus.DEFAULT_ASYNC_HANDLERS) - - def process_key_event(self, keyval, is_press, state, reply_cb, error_cb): - self.__engine.ProcessKeyEvent(keyval, is_press, state, - reply_handler = reply_cb, - error_handler = error_cb) - - def set_cursor_location(self, x, y, w, h): - self.__engine.SetCursorLocation(x, y, w, h, - **ibus.DEFAULT_ASYNC_HANDLERS) - - def enable(self): - self.__engine.Enable(**ibus.DEFAULT_ASYNC_HANDLERS) - - def disable(self): - self.__engine.Disable(**ibus.DEFAULT_ASYNC_HANDLERS) - - # cursor for lookup table - - def page_up(self): - self.__engine.PageUp(**ibus.DEFAULT_ASYNC_HANDLERS) - - def page_down(self): - self.__engine.PageDown(**ibus.DEFAULT_ASYNC_HANDLERS) - - def cursor_up(self): - self.__engine.CursorUp(**ibus.DEFAULT_ASYNC_HANDLERS) - - def cursor_down(self): - self.__engine.CursorDown(**ibus.DEFAULT_ASYNC_HANDLERS) - - def property_activate(self, prop_name, prop_state): - self.__engine.PropertyActivate(prop_name, prop_state, - **ibus.DEFAULT_ASYNC_HANDLERS) - - def property_show(self, prop_name): - self.__engine.PropertyShow(prop_name, - **ibus.DEFAULT_ASYNC_HANDLERS) - - def property_hide(self, prop_name): - self.__engine.PropertyHide(prop_name, - **ibus.DEFAULT_ASYNC_HANDLERS) - - def destroy(self): - ibus.Object.destroy(self) - if self.__engine: - self.__engine.Destroy(**ibus.DEFAULT_ASYNC_HANDLERS) - self.__engine = None - self.__ibusconn = None - - def __ibusconn_destroy_cb(self, ibusconn): - self.__engine = None - self.destroy() - -gobject.type_register(Engine) - diff --git a/daemon/enginefactory.py b/daemon/enginefactory.py deleted file mode 100644 index 5ef6cc6..0000000 --- a/daemon/enginefactory.py +++ /dev/null @@ -1,83 +0,0 @@ -# vim:set et sts=4 sw=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 - -import weakref -import gobject -import ibus -from engine import Engine - -class EngineFactory(ibus.Object): - def __init__(self, ibusconn, object_path): - super(EngineFactory, self).__init__() - self._ibusconn = ibusconn - self._object_path = object_path - self._factory = self._ibusconn.get_object(self._object_path) - - self._ibusconn.connect("destroy", self.__ibusconn_destroy_cb) - - self._ibusconn.connect("dbus-signal", self.__dbus_signal_cb) - self._engines = weakref.WeakValueDictionary() - - self._info = None - - def get_object_path(self): - return self._object_path - - def get_info(self): - if self._info == None: - self._info = self._factory.GetInfo() - return self._info - - def create_engine(self): - object_path = self._factory.CreateEngine() - engine = Engine(self, self._ibusconn, object_path) - self._engines[object_path] = engine - return engine - - def destroy(self): - ibus.Object.destroy(self) - self._ibusconn = None - self._factory = None - - def __ibusconn_destroy_cb(self, ibusconn): - self.destroy() - - def __dbus_signal_cb(self, ibusconn, message): - object_path = message.get_path() - if object_path in self._engines: - if self._engines[object_path].handle_dbus_signal(message): - ibusconn.stop_emission("dbus-signal") - return True - return False - - # methods for cmp - def __lt__(self, other): - x = self.get_info() - y = other.get_info() - if x[1] < y[1]: return True - if x[1] == y[1]: return x[0] < y[0] - - def __gt__(self, other): - x = self.get_info() - y = other.get_info() - if x[1] > y[1]: return True - if x[1] == y[1]: return x[0] > y[0] - diff --git a/daemon/factorymanager.py b/daemon/factorymanager.py deleted file mode 100644 index 351f40c..0000000 --- a/daemon/factorymanager.py +++ /dev/null @@ -1,123 +0,0 @@ -# vim:set et sts=4 sw=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 - -import gobject -import ibus -from enginefactory import EngineFactory - -class FactoryManager(ibus.Object): - __gsignals__ = { - 'new-factories-added' : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_PYOBJECT, ) - ), - 'default-factory-changed' : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_PYOBJECT, ) - ) - } - - def __init__(self): - super(FactoryManager, self).__init__() - self.__factories = {} - self.__ibusconn_factory_dict = {} - self.__default_factory = None - self.__sorted_factories = None - - def register_factories(self, object_paths, ibusconn): - if ibusconn in self.__factories: - raise ibus.IBusException("this conn has registered factories!") - - self.__ibusconn_factory_dict[ibusconn] = [] - - for object_path in object_paths: - if object_path in self.__factories: - raise ibus.IBusException( - "Factory [%s] has been registered!" % object_path) - - factory = EngineFactory(ibusconn, object_path) - self.__factories[object_path] = factory - self.__ibusconn_factory_dict[ibusconn].append(object_path) - self.__sorted_factories = None - - ibusconn.connect("destroy", self.__ibusconn_destroy_cb) - - self.emit("new-factories-added", - self.__ibusconn_factory_dict[ibusconn][:]) - - def get_default_factory(self): - if self.__default_factory == None: - factories = self.__get_sorted_factories() - if factories: - self.set_default_factory(factories[0]) - - return self.__default_factory - - def set_default_factory(self, factory): - if factory in self.__get_sorted_factories() or factory == None: - if self.__default_factory != factory: - self.__default_factory = factory - self.emit("default-factory-changed", self.__default_factory) - else: - print "unknown factory" - - def get_next_factory(self, factory): - factories = self.__get_sorted_factories() - i = factories.index(factory) + 1 - if i >= len(factories): - i = 0 - - return factories[i] - - def get_factories(self): - return self.__factories.keys() - - def get_factory_info(self, factory_path): - factory = self.__factories[factory_path] - return factory.get_info() - - def get_factory(self, factory_path): - factory = self.__factories.get(factory_path, None) - return factory - - def __get_sorted_factories(self, resort = False): - if not self.__sorted_factories or resort: - factories = self.__factories.values() - factories.sort() - self.__sorted_factories = factories - return self.__sorted_factories - - def __ibusconn_destroy_cb(self, ibusconn): - assert ibusconn in self.__ibusconn_factory_dict - - for object_path in self.__ibusconn_factory_dict[ibusconn]: - factory = self.__factories[object_path] - if factory == self.__default_factory: - self.set_default_factory(None) - del self.__factories[object_path] - - del self.__ibusconn_factory_dict[ibusconn] - self.__sorted_factories = None - -gobject.type_register(FactoryManager) - diff --git a/daemon/ibusdaemon.py b/daemon/ibusdaemon.py deleted file mode 100644 index b2f44c8..0000000 --- a/daemon/ibusdaemon.py +++ /dev/null @@ -1,112 +0,0 @@ -# vim:set et sts=4 sw=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 - -import os -import sys -import getopt -import getpass -import gobject -import dbus.server -import dbus.mainloop.glib -import ibus -from _dbus import DBus -from bus import IBus -from connection import Connection - - -class IBusServer(dbus.server.Server): - def __init__(self, *args, **kargs): - super(IBusServer, self).__init__() - - self.__ibus = IBus() - # self.__launch_auto_load_engines() - - # def __launch_auto_load_engines(self): - # engines = [] - # try: - # engines = self.__ibus.config_get_value("general", "preload_engines", None) - # if not engines: - # engines = [] - # except: - # pass - # for e in engines: - # try: - # lang, name = e.split(":") - # self.__ibus.register_start_engine(lang, name, None) - # except: - # pass - - def connection_added(self, dbusconn): - conn = Connection(dbusconn) - self.__ibus.new_connection(conn) - DBus(conn) - - def connection_removed(self, dbusconn): - # do nothing. - pass - -def launch_ibus(): - dbus.mainloop.glib.DBusGMainLoop(set_as_default = True) - loop = gobject.MainLoop() - try: - os.mkdir("/tmp/ibus-%s" % getpass.getuser()) - except: - pass - bus = IBusServer(ibus.IBUS_ADDR) - try: - loop.run() - except KeyboardInterrupt, e: - print "daemon exits" - sys.exit() - - -def print_help(out, v = 0): - print >> out, "-h, --help show this message." - print >> out, "-d, --daemonize daemonize ibus" - sys.exit(v) - -def main(): - daemonize = False - shortopt = "hd" - longopt = ["help", "daemonize"] - try: - opts, args = getopt.getopt(sys.argv[1:], shortopt, longopt) - except getopt.GetoptError, err: - print_help(sys.stderr, 1) - - for o, a in opts: - if o in ("-h", "--help"): - print_help(sys.stdout) - elif o in ("-d", "--daemonize"): - daemonize = True - else: - print >> sys.stderr, "Unknown argument: %s" % o - print_help(sys.stderr, 1) - - if daemonize: - if os.fork(): - sys.exit() - - launch_ibus() - - -if __name__ == "__main__": - main() diff --git a/daemon/inputcontext.py b/daemon/inputcontext.py deleted file mode 100644 index 8e433a2..0000000 --- a/daemon/inputcontext.py +++ /dev/null @@ -1,449 +0,0 @@ -# vim:set et sts=4 sw=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 - -import gobject -import ibus - -IBUS_CAP_PREEDIT = 1 -IBUS_CAP_AUX_STRING = 1 << 1 -IBUS_CAP_LOOKUP_TABLE = 1 << 2 -IBUS_CAP_FOCUS = 1 << 3 - -class InputContext(ibus.Object): - id = 1 - __gsignals__ = { - "update-preedit" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_INT, gobject.TYPE_BOOLEAN)), - "show-preedit" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "hide-preedit" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "update-aux-string" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_BOOLEAN)), - "show-aux-string" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "hide-aux-string" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "update-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_PYOBJECT, gobject.TYPE_BOOLEAN)), - "show-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "hide-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "page-up-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "page-down-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "cursor-up-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "cursor-down-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "register-properties" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_PYOBJECT, )), - "update-property" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_PYOBJECT, )), - "engine-lost" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - } - - def __init__(self, name, ibusconn): - super(InputContext, self).__init__() - self.__id = "%d" % InputContext.id - InputContext.id += 1 - self.__ibusconn = ibusconn - self.__ibusconn.connect("destroy", self.__ibusconn_destroy_cb) - - # init default values - self.__enable = False - self.__engine = None - self.__engine_handlers = [] - - # client state - self.__aux_string = None - self.__aux_attrs = None - self.__aux_visible = False - - # capabitlies - self.__support_preedit = True - self.__support_aux_string = False - self.__support_lookup_table = False - self.__support_focus = True - - self.__preedit_string = None - self.__preedit_attrs = None - self.__cursor_pos = 0 - self.__preedit_visible = False - - self.__lookup_table = None - self.__lookup_table_visible = False - - def get_id(self): - return self.__id; - - def get_preedit_string(self): - return self.__preedit_string, self.__preedit_attrs, self.__cursor_pos - - def get_aux_string(self): - return self.__aux_string, self.__aux_attrs - - def process_key_event(self, keyval, is_press, state, - reply_cb, error_cb): - if self.__engine != None and self.__enable: - self.__engine.process_key_event(keyval, is_press, state, - reply_cb, error_cb) - else: - reply_cb(False) - - def set_cursor_location(self, x, y, w, h): - if self.__engine: - self.__engine.set_cursor_location(x, y, w, h) - - def focus_in(self): - if self.__engine and self.__enable: - self.__engine.focus_in() - - def focus_out(self): - if self.__engine and self.__enable: - self.__engine.focus_out() - - def reset(self): - if self.__engine and self.__enable: - self.__engine.reset() - - def page_up(self): - if self.__engine and self.__enable: - self.__engine.page_up() - - def page_down(self): - if self.__engine and self.__enable: - self.__engine.page_down() - - def cursor_up(self): - if self.__engine and self.__enable: - self.__engine.cursor_up() - - def cursor_down(self): - if self.__engine and self.__enable: - self.__engine.cursor_down() - - def property_activate(self, prop_name, prop_state): - if self.__engine and self.__enable: - self.__engine.property_activate(prop_name, prop_state) - - def property_show(self, prop_name): - if self.__engine and self.__enable: - self.__engine.property_show(prop_name) - - def property_hide(self, prop_name): - if self.__engine and self.__enable: - self.__engine.property_hide(prop_name) - - def is_enabled(self): - return self.__enable - - def set_capabilities(self, caps): - self.__support_preedit = bool(caps & IBUS_CAP_PREEDIT) - self.__support_aux_string = bool(caps & IBUS_CAP_AUX_STRING) - self.__support_lookup_table = bool(caps & IBUS_CAP_LOOKUP_TABLE) - self.__support_focus = bool(caps & IBUS_CAP_FOCUS) - - def get_support_focus(self): - return self.__support_focus - - def set_enable(self, enable): - if self.__enable != enable: - self.__enable = enable - if self.__enable: - self.__ibusconn.emit_dbus_signal("Enabled", self.__id) - if self.__engine: - self.__engine.enable() - self.__engine.focus_in() - else: - self.hide_preedit() - self.__ibusconn.emit_dbus_signal("Disabled", self.__id) - if self.__engine: - self.__engine.disable() - - def commit_string(self, text): - self.__ibusconn.emit_dbus_signal("CommitString", self.__id, text) - - def update_preedit(self, text, attrs, cursor_pos, visible): - self.__preedit_string = text - self.__preedit_attrs = attrs - self.__cursor_pos = cursor_pos - self.__preedit_visible = visible - if self.__support_preedit: - self.__ibusconn.emit_dbus_signal("UpdatePreedit", self.__id, text, attrs, cursor_pos, visible) - else: - # show preedit on panel - self.emit("update-preedit", text, attrs, cursor_pos, visible) - - def show_preedit(self): - self.__preedit_visible = True - if self.__support_preedit: - self.__ibusconn.emit_dbus_signal("ShowPreedit", self.__id) - else: - # show preedit on panel - self.emit("show-preedit") - - def hide_preedit(self): - self.__preedit_visible = False - if self.__support_preedit: - self.__ibusconn.emit_dbus_signal("HidePreedit", self.__id) - else: - # show preedit on panel - self.emit("hide-preedit") - - def set_engine(self, engine): - if self.__engine == engine: - return - - if self.__engine != None: - self.__remove_engine_handlers() - self.__engine.destroy() - self.__engine = None - - self.__engine = engine - self.__install_engine_handlers() - - def get_engine(self): - return self.__engine - - def get_factory(self): - if self.__engine: - return self.__engine.get_factory() - return None - - def __engine_destroy_cb(self, engine): - if self.__engine == engine: - self.__remove_engine_handlers() - self.__engine = None - self.__enable = False - if self.__support_preedit: - self.__ibusconn.emit_dbus_signal("UpdatePreedit", - self.__id, - u"", - ibus.AttrList().to_dbus_value(), - 0, - False) - self.__ibusconn.emit_dbus_signal("Disabled", self.__id) - self.emit("engine-lost") - - def __ibusconn_destroy_cb(self, ibusconn): - if self.__engine != None: - self.__remove_engine_handlers() - self.__engine.destroy() - self.__engine = None - self.destroy() - - def __commit_string_cb(self, engine, text): - if not self.__enable: - return - self.commit_string(text) - - def __update_preedit_cb(self, engine, text, attrs, cursor_pos, visible): - if not self.__enable: - return - self.update_preedit(text, attrs, cursor_pos, visible) - - def __show_preedit_cb(self, engine): - if not self.__enable: - return - self.show_preedit() - - def __hide_preedit_cb(self, engine): - if not self.__enable: - return - self.hide_preedit() - - def __update_aux_string_cb(self, engine, text, attrs, visible): - if not self.__enable: - return - self.__aux_string = text - self.__aux_attrs = attrs - self.__aux_visible = visible - - if self.__support_aux_string: - self.__ibusconn.emit_dbus_signal("UpdateAuxString", self.__id, text, attrs, visible) - else: - self.emit("update-aux-string", text, attrs, visible) - - def __show_aux_string_cb(self, engine): - if not self.__enable: - return - self.__aux_visible = True - - if self.__support_aux_string: - self.__ibusconn.emit_dbus_signal("ShowAuxString", self.__id) - else: - self.emit("show-aux-string") - - def __hide_aux_string_cb(self, engine): - if not self.__enable: - return - self.__aux_visible = False - - if self.__support_aux_string: - self.__ibusconn.emit_dbus_signal("HideAuxString", self.__id) - else: - self.emit("hide-aux-string") - - def __update_lookup_table_cb(self, engine, lookup_table, visible): - if not self.__enable: - return - self.__lookup_table = lookup_table - self.__lookup_table_visible = visible - - if self.__support_lookup_table: - self.__ibusconn.emit_dbus_signal("UpdateLookupTable", self.__id, lookup_table, visible) - else: - self.emit("update-lookup-table", lookup_table, visible) - - def __show_lookup_table_cb(self, engine): - if not self.__enable: - return - self.__lookup_table_visible = True - - if self.__support_lookup_table: - self.__ibusconn.emit_dbus_signal("ShowLookupTable", self.__id) - else: - self.emit("show-lookup-table") - - def __hide_lookup_table_cb(self, engine): - if not self.__enable: - return - self.__lookup_table_visible = False - - if self.__support_lookup_table: - self.__ibusconn.emit_dbus_signal("HideLookupTable", self.__id) - else: - self.emit("hide-lookup-table") - - def __page_up_lookup_table_cb(self, engine): - if not self.__enable: - return - - if self.__support_lookup_table: - self.__ibusconn.emit_dbus_signal("PageUpLookupTable", self.__id) - else: - self.emit("page-up-lookup-table") - - def __page_down_lookup_table_cb(self, engine): - if not self.__enable: - return - - if self.__support_lookup_table: - self.__ibusconn.emit_dbus_signal("PageDownLookupTable", self.__id) - else: - self.emit("page-down-lookup-table") - - def __cursor_up_lookup_table_cb(self, engine): - if not self.__enable: - return - - if self.__support_lookup_table: - self.__ibusconn.emit_dbus_signal("CursorUpLookupTable", self.__id) - else: - self.emit("cursor-up-lookup-table") - - def __cursor_down_lookup_table_cb(self, engine): - if not self.__enable: - return - - if self.__support_lookup_table: - self.__ibusconn.emit_dbus_signal("CursorDownLookupTable", self.__id) - else: - self.emit("cursor-down-lookup-table") - - def __register_properties_cb(self, engine, props): - if not self.__enable: - return - self.emit("register-properties", props) - - def __update_property_cb(self, engine, prop): - if not self.__enable: - return - self.emit("update-property", prop) - - def __remove_engine_handlers(self): - assert self.__engine != None - - map(self.__engine.disconnect, self.__engine_handlers) - del self.__engine_handlers[:] - - def __install_engine_handlers(self): - signals = ( - ("destroy", self.__engine_destroy_cb), - ("commit-string", self.__commit_string_cb), - ("update-preedit", self.__update_preedit_cb), - ("show-preedit", self.__show_preedit_cb), - ("hide-preedit", self.__hide_preedit_cb), - ("update-aux-string", self.__update_aux_string_cb), - ("show-aux-string", self.__show_aux_string_cb), - ("hide-aux-string", self.__hide_aux_string_cb), - ("update-lookup-table", self.__update_lookup_table_cb), - ("show-lookup-table", self.__show_lookup_table_cb), - ("hide-lookup-table", self.__hide_lookup_table_cb), - ("page-up-lookup-table", self.__page_up_lookup_table_cb), - ("page-down-lookup-table", self.__page_down_lookup_table_cb), - ("cursor-up-lookup-table", self.__cursor_up_lookup_table_cb), - ("cursor-down-lookup-table", self.__cursor_down_lookup_table_cb), - ("register-properties", self.__register_properties_cb), - ("update-property", self.__update_property_cb) - ) - - for signal, handler in signals: - id = self.__engine.connect(signal, handler) - self.__engine_handlers.append(id) - -gobject.type_register(InputContext) diff --git a/daemon/lookuptable.py b/daemon/lookuptable.py deleted file mode 100644 index 02d2cbc..0000000 --- a/daemon/lookuptable.py +++ /dev/null @@ -1,95 +0,0 @@ -# vim:set et sts=4 sw=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 - -import dbus - -class Candidates(list): - SIGNATURE = "a(saau)" - def to_dbus_value(self): - value = dbus.Array(signature = "(saau)") - for text, attrs in self: - value.append((text, attrs.to_dbus_value()), "(s%s)" % attrs.SIGNATURE) - - def from_dbus_value(self): - pass - -class LookupTable(object): - SIGNATURE = "(ibia(saau))" - - def __init__(self, page_size = 5): - self._page_size = page_size - self._cursor_visible = False - self._cursor_pos = 0 - self._candidates = [] - - def set_page_size(self, page_size): - self._page_size = page_size - - def get_page_size(self): - return self._page_size - - def show_cursor(self): - self._cursor_visible = True - - def hide_cursor(self): - self._cursor_visible = False - - def is_cursor_visible(self): - return self._cursor_visible - - def get_current_page_start(self): - return(self._cursor_pos / self._page_size) * self._page_size - - def set_cursor_pos(self, pos): - self._current_pos = pos - - def get_cursor_pos(self): - return self._current_pos - - def get_cursor_pos_in_current_page(self): - return self._current_pos % self._page_size - - def page_up(self): - pass - - def page_down(self): - pass - - def cursor_up(self): - pass - - def cursor_down(self): - pass - - def clear(self): - self._candidates = [] - - def append_candidate(self, candidate, attrs = None): - self._candidates.append((candidates, attrs)) - - def get_candidate(self, index): - return self._candidates[index] - - def to_dbus_struct(self): - pass - - def from_dbus_struct(self, value): - pass diff --git a/daemon/notifications.py b/daemon/notifications.py deleted file mode 100644 index 370bdac..0000000 --- a/daemon/notifications.py +++ /dev/null @@ -1,92 +0,0 @@ -# vim:set et sts=4 sw=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 - -import gobject -import ibus - -class Notifications(ibus.Object): - __gsignals__ = { - "notification-closed" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_UINT, gobject.TYPE_UINT)), - "action-invoked" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_UINT, gobject.TYPE_STRING)), - } - - def __init__(self, ibusconn): - super(Notifications, self).__init__() - self.__ibusconn = ibusconn - self.__notifications = self.__ibusconn.get_object(ibus.IBUS_NOTIFICATIONS_PATH) - - self.__ibusconn.connect("destroy", self.__ibusconn_destroy_cb) - self.__ibusconn.connect("dbus-signal", self.__dbus_signal_cb) - - def notify(self, replaces_id, app_icon, summary, body, actions, expire_timeout): - id = self.__notifications.Notify( - replaces_id, app_icon, summary, body, actions, expire_timeout) - return id - - def close_notification(self, id): - return self.__notifications.CloseNotifications(id) - - def __dbus_signal_cb(self, ibusconn, message): - if message.is_signal(ibus.IBUS_NOTIFICATIONS_IFACE, "NotificationsClosed"): - args = message.get_args_list() - self.emit("notifications-closed", args[0], args[1]) - elif message.is_signal(ibus.IBUS_NOTIFICATIONS_IFACE, "ActionInvoked"): - args = message.get_args_list() - self.emit("action-invoked", args[0], args[1]) - else: - return False - ibusconn.stop_emission("dbus-signal") - return False - - def __ibusconn_destroy_cb(self, ibusconn): - self.__ibusconn = None - self.destroy() - -gobject.type_register(Notifications) - - -class DummyNotifications(ibus.Object): - __gsignals__ = { - "notification-closed" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_UINT, gobject.TYPE_UINT)), - "action-invoked" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_UINT, gobject.TYPE_STRING)), - } - - def notify(self, replaces_id, app_icon, summary, body, actions, expire_timeout): - return 0 - - def close_notification(self, id): - pass - -gobject.type_register(DummyNotifications) - - diff --git a/daemon/panel.py b/daemon/panel.py deleted file mode 100644 index aee1185..0000000 --- a/daemon/panel.py +++ /dev/null @@ -1,262 +0,0 @@ -# vim:set et sts=4 sw=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 - -import gobject -import ibus - -class Panel(ibus.Object): - __gsignals__ = { - "page-up" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "page-down" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "cursor-up" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "cursor-down" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "property-activate" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, gobject.TYPE_INT)), - "property-show" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, )), - "property-hide" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, )), - } - - def __init__(self, ibusconn): - super(Panel, self).__init__() - self.__ibusconn = ibusconn - self.__panel = self.__ibusconn.get_object(ibus.IBUS_PANEL_PATH) - - self.__ibusconn.connect("destroy", self.__ibusconn_destroy_cb) - self.__ibusconn.connect("dbus-signal", self.__dbus_signal_cb) - - def set_cursor_location(self, x, y, w, h): - self.__panel.SetCursorLocation(x, y, w, h, - **ibus.DEFAULT_ASYNC_HANDLERS) - - def update_preedit(self, text, attrs, cursor_pos, visible): - self.__panel.UpdatePreedit(text, attrs, cursor_pos, visible, - **ibus.DEFAULT_ASYNC_HANDLERS) - - def show_preedit(self): - self.__panel.ShowPreedit(**ibus.DEFAULT_ASYNC_HANDLERS) - - def hide_preedit(self): - self.__panel.HidePreedit(**ibus.DEFAULT_ASYNC_HANDLERS) - - def update_aux_string(self, text, attrs, visible): - self.__panel.UpdateAuxString(text, attrs, visible, - **ibus.DEFAULT_ASYNC_HANDLERS) - - def show_aux_string(self): - self.__panel.ShowAuxString(**ibus.DEFAULT_ASYNC_HANDLERS) - - def hide_aux_string(self): - self.__panel.HideAuxString(**ibus.DEFAULT_ASYNC_HANDLERS) - - def update_lookup_table(self, lookup_table, visible): - self.__panel.UpdateLookupTable(lookup_table, visible, - **ibus.DEFAULT_ASYNC_HANDLERS) - - def show_lookup_table(self): - self.__panel.ShowLookupTable(**ibus.DEFAULT_ASYNC_HANDLERS) - - def hide_lookup_table(self): - self.__panel.HideLookupTable(**ibus.DEFAULT_ASYNC_HANDLERS) - - def page_up_lookup_table(self): - self.__panel.PageUpLookupTable(**ibus.DEFAULT_ASYNC_HANDLERS) - - def page_down_lookup_table(self): - self.__panel.PageDownLookupTable(**ibus.DEFAULT_ASYNC_HANDLERS) - - def cursor_up_lookup_table(self): - self.__panel.CursorUpLookupTable(**ibus.DEFAULT_ASYNC_HANDLERS) - - def cursor_down_lookup_table(self): - self.__panel.CursorDownLookupTable(**ibus.DEFAULT_ASYNC_HANDLERS) - - def register_properties(self, props): - self.__panel.RegisterProperties(props, - **ibus.DEFAULT_ASYNC_HANDLERS) - - def update_property(self, prop): - self.__panel.UpdateProperty(prop, - **ibus.DEFAULT_ASYNC_HANDLERS) - - def show_language_bar(self): - self.__panel.ShowLanguageBar(**ibus.DEFAULT_ASYNC_HANDLERS) - - def hide_language_bar(self): - self.__panel.HideLanguageBar(**ibus.DEFAULT_ASYNC_HANDLERS) - - def focus_in(self, ic): - self.__panel.FocusIn(ic, **ibus.DEFAULT_ASYNC_HANDLERS) - - def focus_out(self, ic): - self.__panel.FocusOut(ic, **ibus.DEFAULT_ASYNC_HANDLERS) - - def states_changed(self): - self.__panel.StatesChanged(**ibus.DEFAULT_ASYNC_HANDLERS) - - def reset(self): - self.__panel.Reset(**ibus.DEFAULT_ASYNC_HANDLERS) - - def start_setup(self): - self.__panel.StartSetup(**ibus.DEFAULT_ASYNC_HANDLERS) - - def destroy(self): - if self.__ibusconn != None: - self.__panel.Destroy(**ibus.DEFAULT_ASYNC_HANDLERS) - - self.__ibusconn = None - self.__panel = None - ibus.Object.destroy(self) - - # signal callbacks - def __ibusconn_destroy_cb(self, ibusconn): - self.__ibusconn = None - self.destroy() - - def __dbus_signal_cb(self, ibusconn, message): - if message.is_signal(ibus.IBUS_PANEL_IFACE, "PageUp"): - self.emit("page-up") - elif message.is_signal(ibus.IBUS_PANEL_IFACE, "PageDown"): - self.emit("page-down") - elif message.is_signal(ibus.IBUS_PANEL_IFACE, "CursorUp"): - self.emit("cursor-up") - elif message.is_signal(ibus.IBUS_PANEL_IFACE, "CursorDown"): - self.emit("cursor-down") - elif message.is_signal(ibus.IBUS_PANEL_IFACE, "PropertyActivate"): - args = message.get_args_list() - self.emit("property-activate", args[0], args[1]) - elif message.is_signal(ibus.IBUS_PANEL_IFACE, "PropertyShow"): - args = message.get_args_list() - self.emit("property-show", args[0]) - elif message.is_signal(ibus.IBUS_PANEL_IFACE, "PropertyHide"): - args = message.get_args_list() - self.emit("property-hide", args[0]) - else: - return False - ibusconn.stop_emission("dbus-signal") - return True - - # methods for cmp - # def __lt__(self, other): - # x = self.get_info() - # y = other.get_info() - # if x[1] < y[1]: return True - # if x[1] == y[1]: return x[0] < y[0] - # - # def __gt__(self, other): - # x = self.get_info() - # y = other.get_info() - # if x[1] > y[1]: return True - # if x[1] == y[1]: return x[0] > y[0] - -gobject.type_register(Panel) - -class DummyPanel(ibus.Object): - __gsignals__ = { - "page-up" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "page-down" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "cursor-up" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "cursor-down" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), - "property-activate" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, )), - "property-show" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, )), - "property-hide" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, )), - } - - def set_cursor_location(self, x, y, w, h): - pass - - def update_preedit(self, text, attrs, cursor_pos, visible): - pass - - def update_aux_string(self, text, attrs, visible): - pass - - def update_lookup_table(self, lookup_table, visible): - pass - - def register_properties(self, props): - pass - - def update_property(self, prop): - pass - - def show_language_bar(self): - pass - - def hide_language_bar(self): - pass - - def focus_in(self, ic): - pass - - def focus_out(self, ic): - pass - - def states_changed(self): - pass - - def reset(self): - pass - - def start_setup(self): - pass - -gobject.type_register(DummyPanel) diff --git a/daemon/register.py b/daemon/register.py deleted file mode 100644 index bfef2b3..0000000 --- a/daemon/register.py +++ /dev/null @@ -1,205 +0,0 @@ -# vim:set et sts=4 sw=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 - -import os -from os import path -import signal -import glob -import ibus -import locale - -locale.setlocale(locale.LC_ALL, "") - -LANG = tuple() -try: - LANG = locale.getlocale()[0], locale.getlocale()[0].split("_")[0] -except: - pass - -IBUS_DATAROOTDIR = os.getenv("IBUS_DATAROOTDIR") - -class Engine(ibus.Object): - def __init__(self, name, local_name, lang = "other", icon = "", author = "", credits = "", _exec = "", pid = 0): - super(Engine, self).__init__() - self.name = name - self.local_name = local_name - self.lang = lang - self.icon = icon - self.author = author - self.credits = credits - self._exec = _exec - self.pid = pid - - def start(self): - if self.pid != 0: - return - pid = os.fork() - if pid > 0: # parent - self.pid = pid - elif pid == 0: # child - os.setpgrp() - args = self._exec.split() - os.execv(args[0], args) - sys.exit(1) - - def stop(self, force = False): - if self.pid == 0: - return - try: - if force: - os.kill(-self.pid, signal.SIGKILL) - else: - os.kill(-self.pid, signal.SIGTERM) - except: - pass - - def engine_exit(self, pid): - if self.pid == pid: - self.pid = 0 - return True - return False - - def __eq__(self, o): - # We don't test icon author & credits - return self.name == o.name and \ - self.lang == o.lang and \ - self._exec == o._exec - - def __str__(self): - return "Engine('%s', '%s', '%s', '%s', '%s', '%s', '%s', %d" % (self.name, self.local_name, self.lang, \ - self.icon, self.author, \ - self.credits, self._exec, \ - self.pid) - -class Register(ibus.Object): - def __init__(self): - super(Register, self).__init__() - self.__engines = dict() - self.__load() - signal.signal(signal.SIGCHLD, self.__sigchld_cb) - - def start_engine(self, lang, name): - key = (lang, name) - if key not in self.__engines: - raise ibus.IBusException("Can not find engine(%s, %s)" % (lang, name)) - - engine = self.__engines[(lang, name)] - engine.start() - - def stop_engine(self, lang, name): - key = (lang, name) - if key not in self.__engines: - raise ibus.IBusException("Can not find engine(%s, %s)" % (lang, name)) - - engine = self.__engines[(lang, name)] - engine.stop() - - def restart_engine(self, lang, name): - key = (lang, name) - if key not in self.__engines: - raise ibus.IBusException("Can not find engine (%s, %s)" % (lang, name)) - - engine = self.__engines[(lang, name)] - engine.stop() - engine.start() - - def list_engines(self): - engines = [] - for key, e in self.__engines.items(): - engines.append((e.name, e.local_name, e.lang, e.icon, e.author, e.credits, e._exec, e.pid != 0)) - return engines - - def reload_engines(self): - self.__load() - - def __sigchld_cb(self, sig, f): - pid, state = os.wait() - for key, engine in self.__engines.items(): - if engine.engine_exit(pid): - break - - def __load(self): - _dir = path.join(IBUS_DATAROOTDIR, "ibus/engine") - for _file in glob.glob(_dir + "/*.engine"): - engine = self.__load_engine(_file) - if (engine.lang, engine.name) in self.__engines: - old_engine = self.__engines[(engine.lang, engine.name)] - if old_engine == engine: - engine.pid = old_engine.pid - self.__engines[(engine.lang, engine.name)] = engine - else: - self.__engines[(engine.lang, engine.name + " (old)")] = old_engine - self.__engines[(engine.lang, engine.name)] = engine - else: - self.__engines[(engine.lang, engine.name)] = engine - - - - def __load_engine(self, _file): - f = file(_file) - name = None - local_name = None - lang = "other" - icon = "" - author = "" - credits = "" - _exec = None - line = 0 - for l in f: - line += 1 - l = l.strip() - if l.startswith("#"): - continue - n, v = l.split("=") - if n == "Name": - name = v - if local_name == None: - local_name = name - elif n.startswith("Name."): - if n[5:] in LANG: - local_name = v - elif n == "Lang": - lang = v - elif n == "Icon": - icon = v - elif n == "Author": - author = v - elif n == "Credits": - credits = v - elif n == "Exec": - _exec = v - else: - raise Exception("%s:%d\nUnknown value name = %s" % (_file, line, n)) - - if name == None: - raise Exception("%s: no name" % _file) - if _exec == None: - raise Exception("%s: no exec" % _file) - - return Engine(name, local_name, lang, icon, author, credits, _exec) - -if __name__ == "__main__": - import time - reg = Register() - reg.start_engine("zh", "py") - time.sleep(3) - reg.stop_engine("zh", "py") - diff --git a/gconf/ibus-gconf.in b/docs/Makefile.am index c1fcf8b..c23ca9e 100644 --- a/gconf/ibus-gconf.in +++ b/docs/Makefile.am @@ -1,4 +1,4 @@ -#!/bin/sh +# vim:set noet ts=4: # # ibus - The Input Bus # @@ -19,6 +19,6 @@ # Free Software Foundation, Inc., 59 Temple Place, Suite 330, # Boston, MA 02111-1307 USA -export IBUS_PREFIX=@prefix@ -exec python @prefix@/share/ibus/gconf/main.py $@ - +SUBDIRS = \ + reference \ + $(NULL) diff --git a/daemon/ibus-daemon.in b/docs/reference/Makefile.am index a572c8b..70fe792 100644 --- a/daemon/ibus-daemon.in +++ b/docs/reference/Makefile.am @@ -1,4 +1,4 @@ -#!/bin/sh +# vim:set noet ts=4: # # ibus - The Input Bus # @@ -19,7 +19,6 @@ # Free Software Foundation, Inc., 59 Temple Place, Suite 330, # Boston, MA 02111-1307 USA -prefix=@prefix@ -export IBUS_DATAROOTDIR=@datarootdir@ -exec python @prefix@/share/@PACKAGE@/daemon/ibusdaemon.py $@ - +SUBDIRS = \ + ibus \ + $(NULL) diff --git a/docs/reference/ibus/.gitignore b/docs/reference/ibus/.gitignore new file mode 100644 index 0000000..00b86a9 --- /dev/null +++ b/docs/reference/ibus/.gitignore @@ -0,0 +1,24 @@ +ibus-decl-list.txt +ibus-decl.txt +ibus-overrides.txt +ibus-sections.txt +ibus-undeclared.txt +ibus-undocumented.txt +ibus-unused.txt +html +tmpl +xml +html-build.stamp +html.stamp +ibus-docs.sgml +ibus.args +ibus.hierarchy +ibus.interfaces +ibus.prerequisites +ibus.signals +scan-build.stamp +sgml-build.stamp +sgml.stamp +tmpl-build.stamp +tmpl.stamp + diff --git a/docs/reference/ibus/Makefile.am b/docs/reference/ibus/Makefile.am new file mode 100644 index 0000000..65065c9 --- /dev/null +++ b/docs/reference/ibus/Makefile.am @@ -0,0 +1,101 @@ +## Process this file with automake to produce Makefile.in + +# We require automake 1.6 at least. +AUTOMAKE_OPTIONS = 1.6 + +# This is a blank Makefile.am for using gtk-doc. +# Copy this to your project's API docs directory and modify the variables to +# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples +# of using the various options. + +# The name of the module, e.g. 'glib'. +DOC_MODULE=ibus + +# The top-level SGML file. You can change this if you want to. +DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml + +# The directory containing the source code. Relative to $(srcdir). +# gtk-doc will search all .c & .h files beneath here for inline comments +# documenting the functions and macros. +# e.g. DOC_SOURCE_DIR=../../../gtk +DOC_SOURCE_DIR=$(top_srcdir)/src + +# Extra options to pass to gtkdoc-scangobj. Not normally needed. +SCANGOBJ_OPTIONS= + +# Extra options to supply to gtkdoc-scan. +# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" +SCAN_OPTIONS=--rebuild-sections + +# Extra options to supply to gtkdoc-mkdb. +# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml +MKDB_OPTIONS=--sgml-mode --output-format=xml + +# Extra options to supply to gtkdoc-mktmpl +# e.g. MKTMPL_OPTIONS=--only-section-tmpl +MKTMPL_OPTIONS= + +# Extra options to supply to gtkdoc-fixref. Not normally needed. +# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html +FIXXREF_OPTIONS= + +# Used for dependencies. The docs will be rebuilt if any of these change. +# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h +# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c +HFILE_GLOB= +CFILE_GLOB= + +# Header files to ignore when scanning. +# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h +IGNORE_HFILES= + +# Images to copy into HTML directory. +# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png +HTML_IMAGES= + +# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). +# e.g. content_files=running.sgml building.sgml changes-2.0.sgml +content_files= + +# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded +# These files must be listed here *and* in content_files +# e.g. expand_content_files=running.sgml +expand_content_files= + +CFLAGS = \ + @GLIB2_CFLAGS@ \ + @GOBJECT2_CFLAGS@ \ + @GIO2_CFLAGS@ \ + @DBUS_CFLAGS@ \ + $(NULL) +LDFLAGS = \ + @GLIB2_LIBS@ \ + @GOBJECT2_LIBS@ \ + @GIO2_LIBS@ \ + @DBUS_LIBS@ \ + $(NULL) + +# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. +# Only needed if you are using gtkdoc-scangobj to dynamically query widget +# signals and properties. +# e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) +# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) +INCLUDES=-I$(top_srcdir)/src +GTKDOC_LIBS=$(top_builddir)/src/libibus.la + +# This includes the standard gtk-doc make rules, copied by gtkdocize. +include $(top_srcdir)/gtk-doc.make + +# Other files to distribute +# e.g. EXTRA_DIST += version.xml.in +EXTRA_DIST += + +# Files not to distribute +# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types +# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt +#DISTCLEANFILES += + +# Comment this out if you want your docs-status tested during 'make check' +#TESTS = $(GTKDOC_CHECK) + +CLEANFILES += ibus* diff --git a/docs/reference/ibus/ibus.types b/docs/reference/ibus/ibus.types new file mode 100644 index 0000000..130545b --- /dev/null +++ b/docs/reference/ibus/ibus.types @@ -0,0 +1,29 @@ +ibus_factory_get_type +ibus_factory_info_get_type +ibus_attribute_get_type +ibus_attr_list_get_type +ibus_input_context_get_type +ibus_observed_path_get_type +ibus_engine_get_type +ibus_service_get_type +ibus_lookup_table_get_type +ibus_proxy_get_type +ibus_server_get_type +ibus_object_flags_get_type +ibus_attr_type_get_type +ibus_attr_underline_get_type +ibus_prop_type_get_type +ibus_prop_state_get_type +ibus_modifier_type_get_type +ibus_capabilite_get_type +ibus_component_get_type +ibus_connection_get_type +ibus_property_get_type +ibus_prop_list_get_type +ibus_text_get_type +ibus_serializable_get_type +ibus_hotkey_profile_get_type +ibus_bus_get_type +ibus_engine_desc_get_type +ibus_object_get_type +ibus_config_get_type diff --git a/gconf/.gitignore b/gconf/.gitignore new file mode 100644 index 0000000..9459c62 --- /dev/null +++ b/gconf/.gitignore @@ -0,0 +1,2 @@ +ibus-gconf +gconf.xml diff --git a/gconf/Makefile.am b/gconf/Makefile.am index 3175bf2..c0cd889 100644 --- a/gconf/Makefile.am +++ b/gconf/Makefile.am @@ -19,22 +19,54 @@ # Free Software Foundation, Inc., 59 Temple Place, Suite 330, # Boston, MA 02111-1307 USA -gconf_PYTHON = \ - config.py \ - main.py \ +libibus = $(top_builddir)/src/libibus.la + +INCLUDES = \ + -I$(top_srcdir)/src \ + $(NULL) + +AM_CFLAGS = \ + @GLIB2_CFLAGS@ \ + @GCONF_CFLAGS@ \ + @DBUS_CFLAGS@ \ + -DG_LOG_DOMAIN=\"IBUS\" \ + $(INCLUDES) \ + $(NULL) +AM_LDFLAGS = \ + @GLIB2_LIBS@ \ + @GCONF_LIBS@ \ + @DBUS_LIBS@ \ + $(libibus) \ + $(NULL) + +libexec_PROGRAMS = \ + ibus-gconf \ $(NULL) -gconfdir = $(pkgdatadir)/gconf +ibus_gconf_SOURCES = \ + main.c \ + config.c \ + config.h \ + $(NULL) +ibus_gconf_CFLAGS = \ + $(AM_CFLAGS) \ + $(NULL) +ibus_gconf_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(NULL) -bin_SCRIPTS = ibus-gconf +component_DATA = \ + gconf.xml \ + $(NULL) +componentdir = $(pkgdatadir)/component CLEANFILES = \ *.pyc \ $(NULL) EXTRA_DIST = \ - ibus-gconf.in \ + gconf.xml.in \ $(NULL) -test: - $(ENV) PYTHONPATH=$(top_srcdir) $(PYTHON) $(srcdir)/main.py +$(libibus): + $(MAKE) -C $(top_builddir)/src diff --git a/gconf/config.c b/gconf/config.c new file mode 100644 index 0000000..a7fa394 --- /dev/null +++ b/gconf/config.c @@ -0,0 +1,312 @@ +/* vim:set et sts=4: */ + +#include <string.h> +#include <ibus.h> +#include "config.h" + +#define GCONF_PREFIX "/desktop/ibus" + +/* functions prototype */ +static void ibus_config_gconf_class_init (IBusConfigGConfClass *klass); +static void ibus_config_gconf_init (IBusConfigGConf *config); +static void ibus_config_gconf_destroy (IBusConfigGConf *config); +static gboolean ibus_config_gconf_set_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + const GValue *value, + IBusError **error); +static gboolean ibus_config_gconf_get_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GValue *value, + IBusError **error); + +static GConfValue *_to_gconf_value (const GValue *value); +static void _from_gconf_value (GValue *value, + const GConfValue *gvalue); + +static IBusConfigServiceClass *parent_class = NULL; + +GType +ibus_config_gconf_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusConfigGConfClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_config_gconf_class_init, + NULL, + NULL, + sizeof (IBusConfigGConf), + 0, + (GInstanceInitFunc) ibus_config_gconf_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_CONFIG_SERVICE, + "IBusConfigGConf", + &type_info, + (GTypeFlags) 0); + } + + return type; +} + +static void +ibus_config_gconf_class_init (IBusConfigGConfClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = (IBusConfigServiceClass *) g_type_class_peek_parent (klass); + + IBUS_OBJECT_CLASS (object_class)->destroy = (IBusObjectDestroyFunc) ibus_config_gconf_destroy; + IBUS_CONFIG_SERVICE_CLASS (object_class)->set_value = ibus_config_gconf_set_value; + IBUS_CONFIG_SERVICE_CLASS (object_class)->get_value = ibus_config_gconf_get_value; +} + +static void +_value_changed_cb (GConfClient *client, + const gchar *key, + GConfValue *value, + IBusConfigGConf *config) +{ + gchar *p, *section, *name; + GValue v = { 0 }; + + p = g_strdup (key); + section = p + sizeof (GCONF_PREFIX); + name = rindex (p, '/') + 1; + *(name - 1) = '\0'; + + + _from_gconf_value (&v, value); + ibus_config_service_value_changed ((IBusConfigService *) config, + section, + name, + &v); + g_free (p); + g_value_unset (&v); +} + +static void +ibus_config_gconf_init (IBusConfigGConf *config) +{ + config->client = gconf_client_get_default (); + gconf_client_add_dir (config->client, GCONF_PREFIX, GCONF_CLIENT_PRELOAD_NONE, NULL); + g_signal_connect (config->client, "value-changed", G_CALLBACK (_value_changed_cb), config); +} + +static void +ibus_config_gconf_destroy (IBusConfigGConf *config) +{ + if (config->client) { + g_object_unref (config->client); + config->client = NULL; + } + + IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *)config); +} + +static GConfValue * +_to_gconf_value (const GValue *value) +{ + GConfValue *gv; + GType type = G_VALUE_TYPE (value); + + switch (type) { + case G_TYPE_STRING: + { + gv = gconf_value_new (GCONF_VALUE_STRING); + gconf_value_set_string (gv, g_value_get_string (value)); + } + break; + case G_TYPE_INT: + { + gv = gconf_value_new (GCONF_VALUE_INT); + gconf_value_set_int (gv, g_value_get_int (value)); + } + break; + case G_TYPE_UINT: + { + gv = gconf_value_new (GCONF_VALUE_INT); + gconf_value_set_int (gv, g_value_get_uint (value)); + } + break; + case G_TYPE_BOOLEAN: + { + gv = gconf_value_new (GCONF_VALUE_BOOL); + gconf_value_set_bool (gv, g_value_get_boolean (value)); + } + break; + case G_TYPE_DOUBLE: + { + gv = gconf_value_new (GCONF_VALUE_FLOAT); + gconf_value_set_float (gv, g_value_get_double (value)); + } + break; + case G_TYPE_FLOAT: + { + gv = gconf_value_new (GCONF_VALUE_FLOAT); + gconf_value_set_float (gv, g_value_get_float (value)); + } + break; + default: + if (type == G_TYPE_VALUE_ARRAY) { + + GSList *l = NULL; + GType list_type = G_TYPE_STRING; + GValueArray *array = g_value_get_boxed (value); + gint i; + + if (array && array->n_values > 0) { + list_type = G_VALUE_TYPE (&(array->values[0])); + } + + gv = gconf_value_new (GCONF_VALUE_LIST); + + switch (list_type) { + case G_TYPE_STRING: + gconf_value_set_list_type (gv, GCONF_VALUE_STRING); break; + case G_TYPE_INT: + case G_TYPE_UINT: + gconf_value_set_list_type (gv, GCONF_VALUE_INT); break; + case G_TYPE_BOOLEAN: + gconf_value_set_list_type (gv, GCONF_VALUE_BOOL); break; + case G_TYPE_FLOAT: + case G_TYPE_DOUBLE: + gconf_value_set_list_type (gv, GCONF_VALUE_FLOAT); break; + default: + g_assert_not_reached (); + } + + for (i = 0; array && i < array->n_values; i++) { + GConfValue *tmp; + g_assert (G_VALUE_TYPE (&(array->values[i])) == list_type); + tmp = _to_gconf_value (&(array->values[i])); + l = g_slist_append (l, tmp); + } + gconf_value_set_list_nocopy (gv, l); + } + else + g_assert_not_reached (); + } + return gv; +} + +static void +_from_gconf_value (GValue *value, + const GConfValue *gv) +{ + g_assert (value); + g_assert (gv); + + switch (gv->type) { + case GCONF_VALUE_STRING: + g_value_init (value, G_TYPE_STRING); + g_value_set_string (value, gconf_value_get_string (gv)); + return; + case GCONF_VALUE_INT: + g_value_init (value, G_TYPE_INT); + g_value_set_int (value, gconf_value_get_int (gv)); + return; + case GCONF_VALUE_FLOAT: + g_value_init (value, G_TYPE_DOUBLE); + g_value_set_double (value, gconf_value_get_float (gv)); + return; + case GCONF_VALUE_BOOL: + g_value_init (value, G_TYPE_BOOLEAN); + g_value_set_boolean (value, gconf_value_get_bool (gv)); + return; + case GCONF_VALUE_LIST: + { + g_value_init (value, G_TYPE_VALUE_ARRAY); + + GSList *list, *p; + GValueArray *va; + + list = gconf_value_get_list (gv); + va = g_value_array_new (g_slist_length (list)); + for (p = list; p != NULL; p = p->next) { + GValue tmp = {0}; + _from_gconf_value (&tmp, (GConfValue *) p->data); + g_value_array_append (va, &tmp); + } + + g_value_take_boxed (value, va); + } + return; + default: + g_assert_not_reached (); + break; + } +} + + +static gboolean +ibus_config_gconf_set_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + const GValue *value, + IBusError **error) +{ + gchar *key; + GConfValue *gv; + GError *gerror = NULL; + + gv = _to_gconf_value (value); + + key = g_strdup_printf (GCONF_PREFIX"/%s/%s", section, name); + + gconf_client_set (((IBusConfigGConf *)config)->client, key, gv, &gerror); + g_free (key); + gconf_value_free (gv); + + if (gerror != NULL) { + if (error) { + *error = ibus_error_new_from_text (DBUS_ERROR_FAILED, gerror->message); + g_error_free (gerror); + } + return FALSE; + } + + return TRUE; +} +static gboolean +ibus_config_gconf_get_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GValue *value, + IBusError **error) +{ + gchar *key; + GConfValue *gv; + + key = g_strdup_printf (GCONF_PREFIX"/%s/%s", section, name); + + gv = gconf_client_get (((IBusConfigGConf *) config)->client, key, NULL); + g_free (key); + + if (gv == NULL) { + *error = ibus_error_new_from_printf (DBUS_ERROR_FAILED, + "Can not get value [%s->%s]", section, name); + return FALSE; + } + + _from_gconf_value (value, gv); + gconf_value_free (gv); + return TRUE; +} + +IBusConfigGConf * +ibus_config_gconf_new (IBusConnection *connection) +{ + IBusConfigGConf *config; + + config = (IBusConfigGConf *) g_object_new (IBUS_TYPE_CONFIG_GCONF, + "path", IBUS_PATH_CONFIG, + "connection", connection, + NULL); + return config; +} diff --git a/gconf/config.py b/gconf/config.py deleted file mode 100644 index e0a3af8..0000000 --- a/gconf/config.py +++ /dev/null @@ -1,151 +0,0 @@ -# vim:set et sts=4 sw=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 - -__all__ = ( - "Config", -) - -import gobject -try: - import gconf -except: - from ibus import gconf -import dbus -import ibus - -GCONF_IBUS_PATH = "/desktop/ibus" - -class Config(ibus.ConfigBase): - __gsignals__ = { - "value-changed" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)), - } - - def __init__ (self, bus): - super(Config, self).__init__(bus) - self.__client = gconf.Client() - self.__handler_id = self.__client.connect("value-changed", self.__value_changed_cb) - self.__client.add_dir(GCONF_IBUS_PATH, gconf.CLIENT_PRELOAD_NONE) - - def get_value(self, section, name): - key = "/".join([GCONF_IBUS_PATH, section, name]) - value = self.__client.get(key) - if value == None: - raise ibus.IBusException("key = \"%s\" does not exist" % key) - return self.__to_py_value(value) - - def set_value(self, section, name, value): - key = "/".join([GCONF_IBUS_PATH, section, name]) - value = self.__to_gconf_value(value) - self.__client.set(key, value) - - def do_destroy(self): - if self.__client: - self.__client.disconnect(self.__handler_id) - self.__client = None - super(Config, self).do_destroy() - - def __to_py_value(self, value): - if value == None: - return None - if value.type == gconf.VALUE_STRING: - return unicode(value.get_string(), "utf-8") - if value.type == gconf.VALUE_INT: - return value.get_int() - if value.type == gconf.VALUE_FLOAT: - return value.get_float() - if value.type == gconf.VALUE_BOOL: - return value.get_bool() - if value.type == gconf.VALUE_PAIR: - return (self.__to_py_value(value.get_car()), self.__to_py_value(value.get_cdr())) - if value.type == gconf.VALUE_LIST: - signatures = { - gconf.VALUE_STRING: "s", - gconf.VALUE_INT: "i", - gconf.VALUE_FLOAT: "d", - gconf.VALUE_BOOL: "b", - } - return dbus.Array(map(self.__to_py_value, value.get_list()), signature=signatures.get(value.get_list_type(), "v")) - raise ibus.IBusException("Do not support type == %s" % str(value.type)) - - def __to_gconf_value(self, value): - if isinstance(value, str): - ret = gconf.Value(gconf.VALUE_STRING) - ret.set_string(value) - elif isinstance(value, unicode): - ret = gconf.Value(gconf.VALUE_STRING) - ret.set_string(value.encode("utf-8")) - elif isinstance(value, bool): - ret = gconf.Value(gconf.VALUE_BOOL) - ret.set_bool(value) - elif isinstance(value, int): - ret = gconf.Value(gconf.VALUE_INT) - ret.set_int(value) - elif isinstance(value, float): - ret = gconf.Value(gconf.VALUE_FLOAT) - ret.set_float(value) - elif isinstance(value, tuple): - if len(value) != 2: - raise ibus.IBusException("Pair must have two value") - ret = gconf.Value(gconf.VALUE_PAIR) - ret.set_car(self.__to_gconf_value(value[0])) - ret.set_cdr(self.__to_gconf_value(value[1])) - elif isinstance(value, list): - ret = gconf.Value(gconf.VALUE_LIST) - if len(value) > 0: - value = map(self.__to_gconf_value, value) - _type = value[0].type - if any(map(lambda x: x.type != _type, value)): - raise ibus.IBusException("Items of a list must be in same type") - ret.set_list_type(_type) - ret.set_list(value) - elif len(value) == 0 and isinstance(value, dbus.Array): - if value.signature == "i": - ret.set_list_type(gconf.VALUE_INT) - elif value.signature == "s": - ret.set_list_type(gconf.VALUE_STRING) - elif value.signature == "d": - ret.set_list_type(gconf.VALUE_FLOAT) - elif value.signature == "b": - ret.set_list_type(gconf.VALUE_BOOL) - else: - pass - else: - raise ibus.IBusException("Do not support type of %s." % type(value)) - return ret - - def __value_changed_cb(self, gconf, key, value): - value = self.__client.get(key) - value = self.__to_py_value(value) - if value == None: - value = 0 - elif isinstance(value, list) and len(value) == 0: - value = dbus.Array(signature="v") - section_name = key.replace(GCONF_IBUS_PATH + "/", "") - section_name = section_name.rsplit("/", 1) - if len(section_name) == 1: - self.value_changed("", section_name[0], value) - elif len(section_name) == 2: - self.value_changed(section_name[0], section_name[1], value) - else: - print "Can not process %s" % key diff --git a/gconf/gconf.xml.in b/gconf/gconf.xml.in new file mode 100644 index 0000000..e399230 --- /dev/null +++ b/gconf/gconf.xml.in @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- filename: pinyin.xml --> +<component> + <name>org.freedesktop.IBus.Config</name> + <description>GConf Config Component</description> + <exec>@prefix@/libexec/ibus-gconf</exec> + <version>@VERSION@</version> + <author>Peng Huang <shawn.p.huang@gmail.com></author> + <license>GPL</license> + <homepage>http://code.google.com/p/ibus</homepage> + <textdomain>ibus</textdomain> +</component> diff --git a/gconf/main.c b/gconf/main.c new file mode 100644 index 0000000..b2c6c83 --- /dev/null +++ b/gconf/main.c @@ -0,0 +1,65 @@ +/* vim:set et sts=4: */ + +#include <ibus.h> +#include <stdlib.h> +#include <locale.h> +#include "config.h" + +static IBusBus *bus = NULL; +static IBusConfigGConf *config = NULL; + +/* options */ +static gboolean ibus = FALSE; +static gboolean verbose = FALSE; + +static const GOptionEntry entries[] = +{ + { "ibus", 'i', 0, G_OPTION_ARG_NONE, &ibus, "component is executed by ibus", NULL }, + { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "verbose", NULL }, + { NULL }, +}; + + +static void +ibus_disconnected_cb (IBusBus *bus, + gpointer user_data) +{ + g_debug ("bus disconnected"); + ibus_quit (); +} + +static void +ibus_gconf_start (void) +{ + ibus_init (); + bus = ibus_bus_new (); + if (!ibus_bus_is_connected (bus)) { + exit (-1); + } + g_signal_connect (bus, "disconnected", G_CALLBACK (ibus_disconnected_cb), NULL); + config = ibus_config_gconf_new (ibus_bus_get_connection (bus)); + ibus_bus_request_name (bus, IBUS_SERVICE_CONFIG, 0); + ibus_main (); +} + +int +main (gint argc, gchar **argv) +{ + GError *error = NULL; + GOptionContext *context; + + setlocale (LC_ALL, ""); + + context = g_option_context_new ("- ibus gconf component"); + + g_option_context_add_main_entries (context, entries, "ibus-gconf"); + + if (!g_option_context_parse (context, &argc, &argv, &error)) { + g_print ("Option parsing failed: %s\n", error->message); + exit (-1); + } + + ibus_gconf_start (); + + return 0; +} diff --git a/gconf/main.py b/gconf/main.py deleted file mode 100644 index ee8f6eb..0000000 --- a/gconf/main.py +++ /dev/null @@ -1,84 +0,0 @@ -# vim:set et sts=4 sw=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 - -import os -import sys -import getopt -import ibus -import config -import gobject - -class GconfApplication: - def __init__(self): - self.__mainloop = gobject.MainLoop() - self.__bus = ibus.Bus() - self.__bus.connect("destroy", self.__bus_destroy_cb) - - self.__config = config.Config(self.__bus) - self.__config.connect("destroy", self.__config_destroy_cb) - self.__bus.request_name(ibus.IBUS_CONFIG_NAME, 0) - - def run(self): - self.__mainloop.run() - - def __config_destroy_cb(self, config): - self.__mainloop.quit() - - def __bus_destroy_cb(self, _ibus): - print "disconnected" - self.__mainloop.quit() - - - -def launch_gconf(): - GconfApplication().run() - -def print_help(out, v = 0): - print >> out, "-h, --help show this message." - print >> out, "-d, --daemonize daemonize ibus" - sys.exit(v) - -def main(): - daemonize = False - shortopt = "hd" - longopt = ["help", "daemonize"] - try: - opts, args = getopt.getopt(sys.argv[1:], shortopt, longopt) - except getopt.GetoptError, err: - print_help(sys.stderr, 1) - - for o, a in opts: - if o in ("-h", "--help"): - print_help(sys.stdout) - elif o in ("-d", "--daemonize"): - daemonize = True - else: - print >> sys.stderr, "Unknown argument: %s" % o - print_help(sys.stderr, 1) - - if daemonize: - if os.fork(): - sys.exit() - - launch_gconf() - -if __name__ == "__main__": - main() diff --git a/ibus-1.0.pc.in b/ibus-1.0.pc.in new file mode 100644 index 0000000..9793018 --- /dev/null +++ b/ibus-1.0.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: IBus +Description: IBus Library +Version: @VERSION@ +Requires: gobject-2.0 dbus-1 +Libs: -L${libdir} -libus +Cflags: -I${includedir}/ibus-1.0 diff --git a/ibus.spec.in b/ibus.spec.in index b567c46..65dfced 100644 --- a/ibus.spec.in +++ b/ibus.spec.in @@ -13,10 +13,13 @@ Source1: xinput-ibus BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) +%define glib_ver %([ -a %{_libdir}/pkgconfig/glib-2.0.pc ] && pkg-config --modversion glib-2.0 | cut -d. -f 1,2 || echo -n "999") + BuildRequires: gettext-devel BuildRequires: libtool BuildRequires: python BuildRequires: gtk2-devel +BuildRequires: dbus-devel BuildRequires: qt-devel BuildRequires: dbus-glib-devel BuildRequires: desktop-file-utils @@ -26,6 +29,7 @@ Requires(post): %{_sbindir}/alternatives Requires(postun): desktop-file-utils Requires(postun): %{_sbindir}/alternatives +Requires: glib2 >= %{glib_ver} Requires: pygtk2 Requires: dbus-python >= 0.83.0 Requires: gnome-python2-gconf @@ -33,6 +37,8 @@ Requires: notification-daemon Requires: pyxdg Requires: iso-codes +%define _xinputconf %{_sysconfdir}/X11/xinit/xinput.d/ibus.conf + %description IBus means Intelligent Input Bus. It is a new input framework for Linux OS. It provides full featured and user friendly input method user interface. It also may help @@ -55,7 +61,16 @@ Requires: qt >= 4.4.2 %description qt This package contains ibus im module for qt4 -%define _xinputconf %{_sysconfdir}/X11/xinit/xinput.d/ibus.conf +%package devel +Summary: Development tools for ibus +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} +Requires: glib2-devel +Requires: dbus-devel + +%description devel +The ibus-devel package contains the header files and developer +docs for ibus. %prep %setup -q @@ -68,8 +83,7 @@ make %{?_smp_mflags} %install rm -rf $RPM_BUILD_ROOT make DESTDIR=${RPM_BUILD_ROOT} install -rm -f $RPM_BUILD_ROOT%{_libdir}/libibus-gtk.la -rm -f $RPM_BUILD_ROOT%{_libdir}/libibus-gtk.so +rm -f $RPM_BUILD_ROOT%{_libdir}/libibus.la rm -f $RPM_BUILD_ROOT%{_libdir}/gtk-2.0/%{gtk_binary_version}/immodules/im-ibus.la # install xinput config file @@ -112,26 +126,15 @@ fi %dir %{python_sitelib}/ibus %{python_sitelib}/ibus/* %dir %{_datadir}/ibus/ -%dir %{_datadir}/ibus/daemon/ -%dir %{_datadir}/ibus/gconf/ -%dir %{_datadir}/ibus/ui -%dir %{_datadir}/ibus/setup/ -%dir %{_datadir}/ibus/engine/ -%dir %{_datadir}/ibus/icons/ -%{_bindir}/ibus +%{_bindir}/ibus-daemon %{_bindir}/ibus-setup -%{_libdir}/libibus-gtk.so* -%{_datadir}/ibus/daemon/* -%{_datadir}/ibus/gconf/* -%{_datadir}/ibus/ui/* -%{_datadir}/ibus/setup/* -%{_datadir}/ibus/icons/* +%{_libdir}/libibus.so* +%{_datadir}/ibus/* %{_datadir}/applications/* %{_datadir}/pixmaps/* -%{_bindir}/ibus-daemon -%{_bindir}/ibus-gconf -%{_bindir}/ibus-ui-gtk -%{_bindir}/ibus-x11 +%{_libexecdir}/ibus-gconf +%{_libexecdir}/ibus-ui-gtk +%{_libexecdir}/ibus-x11 %config %{_xinputconf} %files gtk @@ -142,6 +145,13 @@ fi %defattr(-,root,root,-) %{_libdir}/qt4/plugins/inputmethods/libibus.so +%files devel +%defattr(-,root,root,-) +%{_libdir}/lib*.so +%{_includedir}/* +%{_datadir}/gtk-doc/html/* +%{_libdir}/pkgconfig/* + %changelog * Thu Aug 07 2008 Huang Peng <shawn.p.huang@gmail.com> - @VERSION@-1 - The first version. diff --git a/ibus/.gitignore b/ibus/.gitignore new file mode 100644 index 0000000..56b6ff1 --- /dev/null +++ b/ibus/.gitignore @@ -0,0 +1 @@ +_config.py diff --git a/ibus/Makefile.am b/ibus/Makefile.am index 43b9121..fba01c6 100644 --- a/ibus/Makefile.am +++ b/ibus/Makefile.am @@ -28,10 +28,11 @@ ibus_PYTHON = \ attribute.py \ common.py \ bus.py \ + inputcontext.py \ engine.py \ exception.py \ factory.py \ - gtk.py \ + _gtk.py \ __init__.py \ keysyms.py \ lang.py \ @@ -41,6 +42,11 @@ ibus_PYTHON = \ panel.py \ notifications.py \ property.py \ + serializable.py \ + text.py \ + component.py \ + enginedesc.py \ + observedpath.py \ utility.py \ config.py \ _config.py \ diff --git a/ibus/__init__.py b/ibus/__init__.py index 401d31b..08432a3 100644 --- a/ibus/__init__.py +++ b/ibus/__init__.py @@ -27,6 +27,7 @@ from interface import * from exception import * from lookuptable import * from bus import * +from inputcontext import * from lang import * from utility import * from engine import * @@ -34,4 +35,9 @@ from factory import * from panel import * from notifications import * from config import * +from serializable import * +from text import * +from observedpath import * +from enginedesc import * +from component import * from _config import * diff --git a/ibus/gtk.py b/ibus/_gtk.py index eb82929..b9874a6 100644 --- a/ibus/gtk.py +++ b/ibus/_gtk.py @@ -47,13 +47,13 @@ class PangoAttrList(pango.AttrList): r = (attr.value & 0x00ff0000) >> 8 g = (attr.value & 0x0000ff00) b = (attr.value & 0x000000ff) << 8 - pango_attr = pango.AttrForeground(r, g, b, + pango_attr = pango.AttrForeground(r, g, b, start_index, end_index) elif attr.type == ibus.ATTR_TYPE_BACKGROUND: r = (attr.value & 0x00ff0000) >> 8 g = (attr.value & 0x0000ff00) b = (attr.value & 0x000000ff) << 8 - pango_attr = pango.AttrBackground(r, g, b, + pango_attr = pango.AttrBackground(r, g, b, start_index, end_index) elif attr.type == ibus.ATTR_TYPE_UNDERLINE: pango_attr = pango.AttrUnderline(int(attr.value), diff --git a/ibus/attribute.py b/ibus/attribute.py index 144133a..ef4b6a4 100644 --- a/ibus/attribute.py +++ b/ibus/attribute.py @@ -32,12 +32,12 @@ __all__ = ( "AttributeForeground", "AttributeBackground", "AttrList", - "attribute_from_dbus_value", - "attr_list_from_dbus_value", "ARGB", "RGB" ) import dbus +from exception import IBusException +from serializable import * ATTR_TYPE_UNDERLINE = 1 ATTR_TYPE_FOREGROUND = 2 @@ -48,8 +48,10 @@ ATTR_UNDERLINE_SINGLE = 1 ATTR_UNDERLINE_DOUBLE = 2 ATTR_UNDERLINE_LOW = 3 -class Attribute: - def __init__ (self, type, value, start_index, end_index): +class Attribute(Serializable): + __NAME__ = "IBusAttribute" + def __init__ (self, type=0, value=0, start_index=0, end_index=0): + super(Attribute, self).__init__() self.__type = type self.__value = value self.__start_index = start_index @@ -72,30 +74,25 @@ class Attribute: start_index = property(get_start_index) end_index = property(get_end_index) - def to_dbus_value (self): - values = [dbus.UInt32 (self.__type), - dbus.UInt32 (self.__value), - dbus.UInt32 (self.__start_index), - dbus.UInt32 (self.__end_index)] - return dbus.Struct (values, signature="uuuu") - - def from_dbus_value (self, value): - if not isinstance (value, dbus.Struct): - raise dbus.Exception ("Attribute must be dbus.Struct uuuu") - - if len (value) != 4 or not all (map (lambda x: isinstance (x, dbus.UInt32), value)): - raise dbus.Exception ("Attribute must be dbus.Struct uuuu") - - self.__type = value[0] - self.__value = value[1] - self.__start_index = value[2] - self.__end_index = value[3] - -def attribute_from_dbus_value (value): - attribute = Attribute (0, 0, 0, 0) - attribute.from_dbus_value (value) - return attribute - + def serialize(self, struct): + super(Attribute, self).serialize(struct) + struct.append (dbus.UInt32(self.__type)) + struct.append (dbus.UInt32(self.__value)) + struct.append (dbus.UInt32(self.__start_index)) + struct.append (dbus.UInt32(self.__end_index)) + + def deserialize(self, struct): + super(Attribute, self).deserialize(struct) + if len(struct) < 4: + raise IBusException ("Can not deserialize IBusAttribute") + + self.__type = struct.pop(0) + self.__value = struct.pop(0) + self.__start_index = struct.pop(0) + self.__end_index = struct.pop(0) + +serializable_register(Attribute) + class AttributeUnderline (Attribute): def __init__(self, value, start_index, end_index): Attribute.__init__ (self, ATTR_TYPE_UNDERLINE, value, start_index, end_index) @@ -114,8 +111,10 @@ def ARGB (a, r, g, b): def RGB (r, g, b): return ARGB (255, r, g, b) -class AttrList: +class AttrList(Serializable): + __NAME__ = "IBusAttrList" def __init__ (self, attrs = []): + super(AttrList, self).__init__() self._attrs = [] for attr in attrs: self.append (attr) @@ -124,29 +123,31 @@ class AttrList: assert isinstance (attr, Attribute) self._attrs.append (attr) - def to_dbus_value (self): - array = dbus.Array (signature = "v") - for attr in self._attrs: - array.append (attr.to_dbus_value ()) - return array - - def from_dbus_value (self, value): - attrs = [] - if not isinstance (value, dbus.Array): - raise IBusException ("AttrList must from dbus.Array (uuuu)") - - for v in value: - attr = attribute_from_dbus_value (v) - attrs.append (attr) + def serialize (self, struct): + super(AttrList, self).serialize (struct) + array = map (lambda a: serialize_object(a), self._attrs) + array = dbus.Array (array, signature = "v") + struct.append(array) + def deserialize (self, struct): + super(AttrList, self).deserialize(struct) + attrs = map(lambda v: deserialize_object(v), struct.pop(0)) self._attrs = attrs def __iter__ (self): return self._attrs.__iter__ () -def attr_list_from_dbus_value (value): - if len(value) == 0: - return None - attrs = AttrList () - attrs.from_dbus_value (value) - return attrs +serializable_register(AttrList) + +def test(): + attr_list = AttrList() + attr_list.append (Attribute()) + attr_list.append (Attribute()) + attr_list.append (Attribute()) + attr_list.append (Attribute()) + attr_list.append (Attribute()) + value = serialize_object(attr_list) + attr_list = deserialize_object(value) + +if __name__ == "__main__": + test() diff --git a/ibus/bus.py b/ibus/bus.py index eb708a6..6ca5f7d 100644 --- a/ibus/bus.py +++ b/ibus/bus.py @@ -23,95 +23,27 @@ __all__ = ( "Bus", ) -import sys -import gobject import dbus import dbus.lowlevel import dbus.connection import dbus.mainloop.glib -import ibus +import gobject +import common +import object +import serializable +import config dbus.mainloop.glib.DBusGMainLoop(set_as_default = True) -class Bus(ibus.Object): +class Bus(object.Object): __gsignals__ = { - "commit-string" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, gobject.TYPE_STRING) - ), - "update-preedit" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT, gobject.TYPE_INT, gobject.TYPE_BOOLEAN) - ), - "show-preedit" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, ) - ), - "hide-preedit" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, ) - ), - "update-aux-string" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT, gobject.TYPE_BOOLEAN) - ), - "show-aux-string" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, ) - ), - "hide-aux-string" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, ) - ), - "update-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, gobject.TYPE_PYOBJECT, gobject.TYPE_BOOLEAN) - ), - "show-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, ) - ), - "hide-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, ) - ), - "page-up-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, ) - ), - "page-down-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, ) - ), - "cursor-up-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, ) - ), - "cursor-down-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, ) - ), - "config-value-changed" : ( - gobject.SIGNAL_RUN_FIRST, + "disconnected" : ( + gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, - (gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT) + () ), "config-reloaded" : ( - gobject.SIGNAL_RUN_FIRST, + gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, () ), @@ -119,29 +51,36 @@ class Bus(ibus.Object): def __init__(self): super(Bus, self).__init__() - self.__dbusconn = dbus.connection.Connection(ibus.IBUS_ADDR) - self.__ibus = self.__dbusconn.get_object(ibus.IBUS_NAME, - ibus.IBUS_PATH) + self.__dbusconn = dbus.connection.Connection(common.IBUS_ADDR) self.__dbus = self.__dbusconn.get_object(dbus.BUS_DAEMON_NAME, - dbus.BUS_DAEMON_PATH) - self.__dbusconn.add_message_filter(self.__dbus_message_cb) + dbus.BUS_DAEMON_PATH) self.__unique_name = self.hello() + self.__ibus = self.__dbusconn.get_object(common.IBUS_SERVICE_IBUS, + common.IBUS_PATH_IBUS) - try: - unique_name = self.get_name_owner(ibus.IBUS_CONFIG_NAME) - self.__config = self.__dbusconn.get_object(unique_name, - ibus.IBUS_CONFIG_PATH) - except: - self.__config = None - self.add_match( - "type='signal'," - "interface='" + dbus.BUS_DAEMON_IFACE + "'," - "member='NameOwnerChanged'," - "arg0='" + ibus.IBUS_CONFIG_NAME + "'") + self.__dbusconn.call_on_disconnection(self.__dbusconn_disconnected_cb) + # self.__dbusconn.add_message_filter(self.__filter_cb) + + def __filter_cb(self, conn, message): + if message.get_type() == 4: + print "Signal %s" % message.get_member() + print " sender = %s" % message.get_sender() + print " path = %s" % message.get_path() + return dbus.lowlevel.HANDLER_RESULT_NOT_YET_HANDLED + + def __dbusconn_disconnected_cb(self, dbusconn): + assert self.__dbusconn == dbusconn + self.__dbusconn = None + self.emit("disconnected") def get_name(self): return self.__unique_name + def get_is_connected(self): + if self.__dbusconn == None: + return False + return self.__dbusconn.get_is_connected() + # define dbus methods def get_dbus(self): return self.__dbus @@ -150,7 +89,7 @@ class Bus(ibus.Object): return self.__dbus.Hello() def request_name(self, name, flags): - return self.__dbus.RequestName(name, flags) + return self.__dbus.RequestName(name, dbus.UInt32 (flags)) def release_name(self, name): return self.__dbus.ReleaseName(name) @@ -168,209 +107,56 @@ class Bus(ibus.Object): return self.__dbusconn def get_address(self): - return ibus.IBUS_ADDR - - def create_input_context(self, client_name): - return self.__ibus.CreateInputContext(client_name) - - def release_input_context(self, ic): - return self.__ibus.ReleaseInputContext(ic) - - def process_key_event(self, ic, keyval, is_press, state): - return self.__ibus.ProcessKeyEvent(ic, keyval, is_press, state) - - def set_cursor_location(self, ic, x, y, w, h): - return self.__ibus.SetCursorLocation(ic, x, y, w, h) - - def foucs_in(self, ic): - return self.__ibus.FocusIn(ic) - - def foucs_out(self, ic): - return self.__ibus.FocusOut(ic) - - def reset(self, ic): - return self.__ibus.Reset(ic) + return common.IBUS_ADDR - def is_enabled(self, ic): - return self.__ibus.IsEnabled(ic) + # define ibus methods + def register_component(self, component): + component = serializable.serialize_object(component) + return self.__ibus.RegisterComponent(component) - def set_capabilities(self, ic, caps): - return self.__ibus.SetCapabilities(ic, caps) + def list_engines(self): + engines = self.__ibus.ListEngines() + return map(serializable.deserialize_object, engines) - def register_factories(self, object_paths): - object_paths = dbus.Array(object_paths, signature="o") - return self.__ibus.RegisterFactories(object_paths, **ibus.DEFAULT_ASYNC_HANDLERS) + def list_active_engines(self): + engines = self.__ibus.ListActiveEngines() + return map(serializable.deserialize_object, engines) - def unregister_factories(self, object_paths): - return self.__ibus.UnregisterFactories(object_paths) - - def register_config(self, object_path, replace = False): - return self.__ibus.RegisterConfig(object_path, replace) - - def get_factories(self): - return self.__ibus.GetFactories() - - def get_factory_info(self, factory_path): - return self.__ibus.GetFactoryInfo(factory_path) - - def set_factory(self, factory_path): - return self.__ibus.SetFactory(factory_path) - - def get_input_context_states(self, ic): - return self.__ibus.GetInputContextStates(ic) - - def config_add_watch(self, section): - return self.add_match( - "type='signal'," - "interface='" + ibus.IBUS_CONFIG_NAME + "'," - "member='ValueChanged'," - "arg0='" + section + "'" - ) + def create_input_context(self, client_name): + return self.__ibus.CreateInputContext(client_name) - def config_remove_watch(self, section): - return self.remove_match( - "type='signal'," - "interface='" + ibus.IBUS_CONFIG_NAME + "'," - "member='ValueChanged'," - "arg0='" + section + "'" - ) + def kill(self): + return self.__ibus.Kill() - def config_set_value(self, section, name, value): - return self.__config.SetValue(section, name, value) + def get_config(self): + try: + return self.__config + except: + self.__config = config.Config(self) + return self.__config - def config_set_list(self, section, name, value, list_type): - value = dbus.Array(value, signature = list_type) - return self.__config.SetValue(section, name, value) +def test(): + import glib + import factory + import text - def config_get_value(self, section, name, default_value = None): - try: - return self.__config.GetValue(section, name) - except Exception, e: - return default_value + mainloop = glib.MainLoop() - def register_list_engines(self): - return self.__ibus.RegisterListEngines() + def __disconnected_cb(*args): + print "Disconnected", args + mainloop.quit() - def register_reload_engines(self): - return self.__ibus.RegisterReloadEngines() + b = Bus() + b.connect("disconnected", __disconnected_cb) - def register_start_engine(self, lang, name): - return self.__ibus.RegisterStartEngine(lang, name) + print "unique_name =", b.get_name() - def register_restart_engine(self, lang, name): - return self.__ibus.RegisterRestartEngine(lang, name) + for i in b.list_factories(): + print i.name - def register_stop_engine(self, lang, name): - return self.__ibus.RegisterStopEngine(lang, name) + mainloop.run() + print "Exit" - def kill(self): - return self.__ibus.Kill() - def __dbus_message_cb(self, conn, message): - # name owner changed signal - if message.is_signal(dbus.BUS_DAEMON_IFACE, "NameOwnerChanged"): - args = message.get_args_list() - if args[0] == ibus.IBUS_CONFIG_NAME: - if args[2] != "": - self.__config = self.__dbusconn.get_object(args[2], ibus.IBUS_CONFIG_PATH) - else: - self.__config = None - self.emit("config-reloaded") - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - # commit string signal - elif message.is_signal(ibus.IBUS_IFACE, "CommitString"): - args = message.get_args_list() - ic, string = args[0:2] - self.emit("commit-string", ic, string.encode("utf-8")) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - - # preedit signals - elif message.is_signal(ibus.IBUS_IFACE, "UpdatePreedit"): - args = message.get_args_list() - ic, preedit, attrs, cursor_pos, visible = args[0:5] - attrs = ibus.attr_list_from_dbus_value(attrs) - self.emit("update-preedit", ic, preedit.encode("utf-8"), - attrs, cursor_pos, visible) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - elif message.is_signal(ibus.IBUS_IFACE, "ShowPreedit"): - args = message.get_args_list() - ic = args[0] - self.emit("show-preedit", ic) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - elif message.is_signal(ibus.IBUS_IFACE, "HidePreedit"): - args = message.get_args_list() - ic = args[0] - self.emit("hide-preedit", ic) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - - # aux string signals - elif message.is_signal(ibus.IBUS_IFACE, "UpdateAuxString"): - args = message.get_args_list() - ic, aux_string, attrs, visible = args[0:4] - attrs = ibus.attr_list_from_dbus_value(attrs) - self.emit("update-aux-string", ic, aux_string.encode("utf-8"), - attrs, visible) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - elif message.is_signal(ibus.IBUS_IFACE, "ShowAuxString"): - args = message.get_args_list() - ic = args[0] - self.emit("show-aux-string", ic) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - elif message.is_signal(ibus.IBUS_IFACE, "HideAuxString"): - args = message.get_args_list() - ic = args[0] - self.emit("hide-aux-string", ic) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - - # lookup table signals - elif message.is_signal(ibus.IBUS_IFACE, "UpdateLookupTable"): - args = message.get_args_list() - ic, lookup_table, visible = args[0:3] - lookup_table = ibus.lookup_table_from_dbus_value(lookup_table) - self.emit("update-lookup-table", ic, lookup_table, visible) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - elif message.is_signal(ibus.IBUS_IFACE, "ShowLookupTable"): - args = message.get_args_list() - ic = args[0] - self.emit("show-lookup-table", ic) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - elif message.is_signal(ibus.IBUS_IFACE, "HideLookupTable"): - args = message.get_args_list() - ic = args[0] - self.emit("hide-lookup-table", ic) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - elif message.is_signal(ibus.IBUS_IFACE, "PageUpLookupTable"): - args = message.get_args_list() - ic = args[0] - self.emit("page-up-lookup-table", ic) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - elif message.is_signal(ibus.IBUS_IFACE, "PageDownLookupTable"): - args = message.get_args_list() - ic = args[0] - self.emit("page-down-lookup-table", ic) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - elif message.is_signal(ibus.IBUS_IFACE, "CursorUpLookupTable"): - args = message.get_args_list() - ic = args[0] - self.emit("cursor-up-lookup-table", ic) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - elif message.is_signal(ibus.IBUS_IFACE, "CursorDownLookupTable"): - args = message.get_args_list() - ic = args[0] - self.emit("cursor-down-lookup-table", ic) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - - # Config signals - elif message.is_signal(ibus.IBUS_CONFIG_IFACE, "ValueChanged"): - args = message.get_args_list() - section, name, value = args[0:3] - self.emit("config-value-changed", section, name, value) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - - # DBUS Disconnected signal - elif message.is_signal(dbus.LOCAL_IFACE, "Disconnected"): - self.destroy() - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - else: - retval = dbus.lowlevel.HANDLER_RESULT_NOT_YET_HANDLED - return retval +if __name__ == "__main__": + test() diff --git a/ibus/common.py b/ibus/common.py index 60323e4..e9868ee 100644 --- a/ibus/common.py +++ b/ibus/common.py @@ -21,14 +21,15 @@ __all__ = ( "IBUS_ADDR", - "IBUS_IFACE", - "IBUS_NAME", - "IBUS_PATH", - "IBUS_CONFIG_IFACE", - "IBUS_ENGINE_FACTORY_IFACE", - "IBUS_ENGINE_IFACE", - "IBUS_PANEL_IFACE", - "IBUS_NOTIFICATIONS_IFACE", + "IBUS_IFACE_IBUS", + "IBUS_SERVICE_IBUS", + "IBUS_PATH_IBUS", + "IBUS_IFACE_CONFIG", + "IBUS_IFACE_PANEL", + "IBUS_IFACE_ENGINE", + "IBUS_IFACE_ENGINE_FACTORY", + "IBUS_IFACE_INPUT_CONTEXT", + "IBUS_IFACE_NOTIFICATIONS", "default_reply_handler", "default_error_handler", "DEFAULT_ASYNC_HANDLERS", @@ -67,15 +68,16 @@ if not __username: IBUS_ADDR = "unix:path=/tmp/ibus-%s/ibus-%s" % (__username, display.replace(":", "-")) # IBUS_ADDR = "tcp:host=localhost,port=7799" -IBUS_IFACE = "org.freedesktop.IBus" -IBUS_PATH = "/org/freedesktop/IBus" -IBUS_NAME = "org.freedesktop.IBus" +IBUS_IFACE_IBUS = "org.freedesktop.IBus" +IBUS_PATH_IBUS = "/org/freedesktop/IBus" +IBUS_SERVICE_IBUS = "org.freedesktop.IBus" -IBUS_CONFIG_IFACE = "org.freedesktop.ibus.Config" -IBUS_ENGINE_FACTORY_IFACE = "org.freedesktop.ibus.EngineFactory" -IBUS_ENGINE_IFACE = "org.freedesktop.ibus.Engine" -IBUS_PANEL_IFACE = "org.freedesktop.ibus.Panel" -IBUS_NOTIFICATIONS_IFACE = "org.freedesktop.ibus.Notifications" +IBUS_IFACE_PANEL = "org.freedesktop.IBus.Panel" +IBUS_IFACE_CONFIG = "org.freedesktop.IBus.Config" +IBUS_IFACE_ENGINE = "org.freedesktop.IBus.Engine" +IBUS_IFACE_ENGINE_FACTORY = "org.freedesktop.IBus.EngineFactory" +IBUS_IFACE_INPUT_CONTEXT = "org.freedesktop.IBus.InputContext" +IBUS_IFACE_NOTIFICATIONS = "org.freedesktop.IBus.Notifications" def default_reply_handler( *args): pass diff --git a/ibus/component.py b/ibus/component.py new file mode 100644 index 0000000..afdc152 --- /dev/null +++ b/ibus/component.py @@ -0,0 +1,131 @@ +# vim:set et sts=4 sw=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 + +__all__ = ( + "Component", + ) + +import dbus +from exception import IBusException +from serializable import * +from enginedesc import * +from observedpath import * + +class Component(Serializable): + __NAME__ = "IBusComponent" + def __init__ (self, name="", description="", version="", license="", author="", homepage="", _exec="", textdomain=""): + super(Component, self).__init__() + self.__name = name + self.__description = description + self.__version = version + self.__license = license + self.__author = author + self.__homepage = homepage + self.__exec = _exec + self.__textdomain = textdomain + self.__observed_paths = [] + self.__engines = [] + + def get_name(self): + return self.__name + + def get_description(self): + return self.__description + + def get_version(self): + return self.__version + + def get_license(self): + return self.__license + + def get_author(self): + return self.__author + + def get_homepage(self): + return self.__homepage + + def get_exec(self): + return self.__exec + + def get_textdomain(self): + return self.__textdomain + + def get_observed_paths(self): + return self.__observed_paths[:] + + def get_engines(self): + return self.__engines[:] + + name = property(get_name) + description = property(get_description) + version = property(get_version) + license = property(get_license) + author = property(get_author) + homepage = property(get_homepage) + _exec = property(get_exec) + textdomain = property(get_textdomain) + observed_paths = property(get_observed_paths) + engines = property(get_engines) + + def add_observed_path(self, path): + self.__observed_paths.append(ObservedPath(path)) + + def add_engine(self, name="", longname="", description="", language="", license="", author="", icon="", layout=""): + engine = EngineDesc(name, longname, description, language, license, author, icon, layout) + self.__engines.append(engine) + + def serialize(self, struct): + super(Component, self).serialize(struct) + struct.append (dbus.String(self.__name)) + struct.append (dbus.String(self.__description)) + struct.append (dbus.String(self.__version)) + struct.append (dbus.String(self.__license)) + struct.append (dbus.String(self.__author)) + struct.append (dbus.String(self.__homepage)) + struct.append (dbus.String(self.__exec)) + struct.append (dbus.String(self.__textdomain)) + struct.append (dbus.Array(map(serialize_object,self.__observed_paths), signature="v")) + struct.append (dbus.Array(map(serialize_object,self.__engines), signature="v")) + + def deserialize(self, struct): + super(Component, self).deserialize(struct) + + self.__name = struct.pop(0) + self.__description = struct.pop(0) + self.__version = struct.pop(0) + self.__license = struct.pop(0) + self.__author = struct.pop(0) + self.__homepage = struct.pop(0) + self.__exec = struct.pop(0) + self.__textdomain = struct.pop(0) + + self.__observed_paths = map(deserialize_object, struct.pop(0)) + self.__engines = map(deserialize_object, struct.pop(0)) + +serializable_register(Component) + +def test(): + text = Component("Hello", "", "", "", "", "", "", "") + value = serialize_object(text) + text= deserialize_object(value) + +if __name__ == "__main__": + test() diff --git a/ibus/config.py b/ibus/config.py index 24b4edc..70bc89a 100644 --- a/ibus/config.py +++ b/ibus/config.py @@ -21,17 +21,20 @@ __all__ = ( "ConfigBase", - "IBUS_CONFIG_NAME", - "IBUS_CONFIG_PATH" + "IBUS_SERVICE_CONFIG", + "IBUS_PATH_CONFIG" ) -IBUS_CONFIG_NAME = "org.freedesktop.ibus.Config" -IBUS_CONFIG_PATH = "/org/freedesktop/ibus/Config" +IBUS_SERVICE_CONFIG = "org.freedesktop.IBus.Config" +IBUS_PATH_CONFIG = "/org/freedesktop/IBus/Config" -import ibus -from ibus import interface +import gobject +import object +import interface +import dbus +from dbus.proxies import ProxyObject -class ConfigBase(ibus.Object): +class ConfigBase(object.Object): def __init__(self, bus): super(ConfigBase, self).__init__() self.__proxy = ConfigProxy(self, bus.get_dbusconn()) @@ -48,7 +51,7 @@ class ConfigBase(ibus.Object): class ConfigProxy(interface.IConfig): def __init__ (self, config, dbusconn): - super(ConfigProxy, self).__init__(dbusconn, IBUS_CONFIG_PATH) + super(ConfigProxy, self).__init__(dbusconn, IBUS_PATH_CONFIG) self.__dbusconn = dbusconn self.__config = config @@ -60,3 +63,80 @@ class ConfigProxy(interface.IConfig): def Destroy(self): self.__config.destroy() + +class Config(object.Object): + __gsignals__ = { + "reloaded" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "value-changed" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + (gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT) + ), + } + + def __init__(self, bus): + super(Config, self).__init__() + self.__bus = bus + self.__bus_name = None + + self.__bus.add_match("type='signal',\ + sender='org.freedesktop.DBus',\ + member='NameOwnerChanged',\ + arg0='org.freedesktop.IBus.Config'") + self.__bus.get_dbusconn().add_signal_receiver(self.__name_owner_changed_cb, signal_name="NameOwnerChanged") + + try: + self.__init_config() + except: + self.__config = None + + def __name_owner_changed_cb(self, name, old_name, new_name): + if name == "org.freedesktop.IBus.Config": + if new_name == "": + self.__config = None + else: + self.__init_config(new_name) + + def __init_config(self, bus_name=None): + if bus_name == None: + bus_name = self.__bus.get_name_owner(IBUS_SERVICE_CONFIG) + + match_rule = "type='signal',\ + sender='%s',\ + member='ValueChanged',\ + path='/org/freedesktop/IBus/Config'" + + if self.__bus_name: + self.__bus.remove_match(match_rule % self.__bus_name) + self.__bus_name = None + + self.__config = self.__bus.get_dbusconn().get_object(bus_name, IBUS_PATH_CONFIG) + self.__config.connect_to_signal("ValueChanged", self.__value_changed_cb) + + self.__bus_name = bus_name + self.__bus.add_match(match_rule % self.__bus_name) + self.emit("reloaded") + + def __value_changed_cb(self, section, name, value): + self.emit("value-changed", section, name, value) + + def get_value(self, section, name, default_value): + try: + return self.__config.GetValue(section, name) + except: + return default_value + + def set_value(self, section, name, value): + try: + return self.__config.SetValue(section, name, value) + except: + return + + def set_list(self, section, name, value, signature): + return self.set_value(section, name, dbus.Array(value, signature=signature)) + +gobject.type_register(Config) diff --git a/ibus/engine.py b/ibus/engine.py index 9a6a332..d52c97e 100644 --- a/ibus/engine.py +++ b/ibus/engine.py @@ -23,15 +23,16 @@ __all__ = ( "EngineBase", ) -import ibus -from ibus import interface +import object +import serializable +import interface -class EngineBase(ibus.Object): +class EngineBase(object.Object): def __init__(self, bus, object_path): super(EngineBase, self).__init__() self.__proxy = EngineProxy (self, bus.get_dbusconn(), object_path) - def process_key_event(self, keyval, is_press, state): + def process_key_event(self, keyval, state): return False def focus_in(self): @@ -73,39 +74,37 @@ class EngineBase(ibus.Object): def property_hide(self, prop_name): pass - def commit_string(self, text): - return self.__proxy.CommitString(text) + def commit_text(self, text): + text = serializable.serialize_object(text) + return self.__proxy.CommitText(text) - def forward_key_event(self, keyval, is_press, state): - return self.__proxy.ForwardKeyEvent(keyval, is_press, state) + def forward_key_event(self, keyval, state): + return self.__proxy.ForwardKeyEvent(keyval, state) - def update_preedit(self, text, attrs, cursor_pos, visible): - if attrs == None: - attrs = ibus.AttrList() - return self.__proxy.UpdatePreedit(text, attrs.to_dbus_value(), cursor_pos, visible) + def update_preedit_text(self, text, cursor_pos, visible): + text = serializable.serialize_object(text) + return self.__proxy.UpdatePreeditText(text, cursor_pos, visible) - def show_preedit(self): - return self.__proxy.ShowPreedit() + def show_preedit_text(self): + return self.__proxy.ShowPreeditText() - def hide_preedit(self): - return self.__proxy.HidePreedit() + def hide_preedit_text(self): + return self.__proxy.HidePreeditText() - def update_aux_string(self, text, attrs, visible): - if attrs == None: - attrs = ibus.AttrList() - return self.__proxy.UpdateAuxString(text, attrs.to_dbus_value(), visible) + def update_auxiliary_text(self, text, visible): + text = serializable.serialize_object(text) + return self.__proxy.UpdateAuxiliaryText(text, visible) - def show_aux_string(self): - return self.__proxy.ShowAuxString() + def show_auxiliary_text(self): + return self.__proxy.ShowAuxiliaryText() - def hide_aux_string(self): - return self.__proxy.HideAuxString() + def hide_auxiliary_text(self): + return self.__proxy.HideAuxiliaryText() def update_lookup_table(self, lookup_table, visible, just_current_page = False): if just_current_page: - dbus_values = lookup_table.current_page_to_dbus_value() - else: - dbus_values = lookup_table.to_dbus_value() + lookup_table = lookup_table.get_current_page_as_lookup_table() + dbus_values = serializable.serialize_object(lookup_table) return self.__proxy.UpdateLookupTable(dbus_values, visible) def show_lookup_table(self): @@ -127,10 +126,12 @@ class EngineBase(ibus.Object): return self.__proxy.CursorDownLookupTable() def register_properties(self, props): - return self.__proxy.RegisterProperties(props.to_dbus_value()) + dbus_values = serializable.serialize_object(props) + return self.__proxy.RegisterProperties(dbus_values) def update_property(self, prop): - return self.__proxy.UpdateProperty(prop.to_dbus_value()) + dbus_values = serializable.serialize_object(prop) + return self.__proxy.UpdateProperty(dbus_values) def get_dbus_object(self): return self.__proxy @@ -145,8 +146,8 @@ class EngineProxy(interface.IEngine): super(EngineProxy, self).__init__(conn, object_path) self.__engine = engine - def ProcessKeyEvent(self, keyval, is_press, state): - return self.__engine.process_key_event(keyval, is_press, state) + def ProcessKeyEvent(self, keyval, state): + return self.__engine.process_key_event(keyval, state) def FocusIn(self): return self.__engine.focus_in() diff --git a/ibus/enginedesc.py b/ibus/enginedesc.py new file mode 100644 index 0000000..430072c --- /dev/null +++ b/ibus/enginedesc.py @@ -0,0 +1,106 @@ +# vim:set et sts=4 sw=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 + +__all__ = ( + "EngineDesc", + ) + +import dbus +from exception import IBusException +from serializable import * + +class EngineDesc(Serializable): + __NAME__ = "IBusEngineDesc" + def __init__ (self, name="", longname="", description="", language="", license="", author="", icon="", layout=""): + super(EngineDesc, self).__init__() + self.__name = name + self.__longname = longname + self.__description = description + self.__language = language + self.__license = license + self.__author = author + self.__icon = icon + self.__layout = layout + + def get_name(self): + return self.__name + + def get_longname(self): + return self.__longname + + def get_description(self): + return self.__description + + def get_language(self): + return self.__language + + def get_license(self): + return self.__license + + def get_author(self): + return self.__author + + def get_icon(self): + return self.__icon + + def get_layout(self): + return self.__layout + + name = property(get_name) + longname = property(get_longname) + description = property(get_description) + language = property(get_language) + license = property(get_license) + author = property(get_author) + icon = property(get_icon) + layout = property(get_layout) + + def serialize(self, struct): + super(EngineDesc, self).serialize(struct) + struct.append (dbus.String(self.__name)) + struct.append (dbus.String(self.__longname)) + struct.append (dbus.String(self.__description)) + struct.append (dbus.String(self.__language)) + struct.append (dbus.String(self.__license)) + struct.append (dbus.String(self.__author)) + struct.append (dbus.String(self.__icon)) + struct.append (dbus.String(self.__layout)) + + def deserialize(self, struct): + super(EngineDesc, self).deserialize(struct) + self.__name = struct.pop(0) + self.__longname = struct.pop(0) + self.__description = struct.pop(0) + self.__language = struct.pop(0) + self.__license = struct.pop(0) + self.__author = struct.pop(0) + self.__icon = struct.pop(0) + self.__layout = struct.pop(0) + +serializable_register(EngineDesc) + +def test(): + engine = EngineDesc("Hello", "", "", "", "", "", "", "") + value = serialize_object(engine) + engine = deserialize_object(value) + +if __name__ == "__main__": + test() diff --git a/ibus/factory.py b/ibus/factory.py index 18deebf..82751ba 100644 --- a/ibus/factory.py +++ b/ibus/factory.py @@ -21,24 +21,19 @@ __all__ = ( "EngineFactoryBase", + "FactoryInfo" ) - -import ibus -from ibus import interface - -class EngineFactoryBase(ibus.Object): - def __init__(self, info, engine_class, engine_path, bus, object_path): +import dbus +import object +import interface +from serializable import * +from exception import * + +class EngineFactoryBase(object.Object): + def __init__(self, bus): super(EngineFactoryBase, self).__init__() - self.__proxy = EngineFactoryProxy (self, bus.get_dbusconn(), object_path) - self.__info = info + self.__proxy = EngineFactoryProxy (self, bus.get_dbusconn(), "/org/freedesktop/IBus/Factory") self.__bus = bus - self.__engine_class = engine_class - self.__engine_path = engine_path - self.__engine_id = 1 - self.__object_path = object_path - - def get_info(self): - return self.__info def initialize(self): pass @@ -46,21 +41,13 @@ class EngineFactoryBase(ibus.Object): def uninitialize(self): pass - def register(self): - self.__bus.register_factories([self.__object_path]) - - def create_engine(self): - engine = self.__engine_class(self.__bus, self.__engine_path + str(self.__engine_id)) - self.__engine_id += 1 - return engine.get_dbus_object() + def create_engine(self, engine_name): + raise IBusException("Can not create engine %s" % engine_name) def do_destroy(self): self.__proxy = None self.__bus = None - self.__info = None - self.__engine_class = None - self.__engine_path = None - super(EngineFactoryBase,self).do_destroy() + super(EngineFactoryBase, self).do_destroy() class EngineFactoryProxy(interface.IEngineFactory): @@ -77,11 +64,70 @@ class EngineFactoryProxy(interface.IEngineFactory): def Uninitialize(self): return self.__factory.uninitialize() - def CreateEngine(self): - return self.__factory.create_engine() + def CreateEngine(self, engine_name): + engine = self.__factory.create_engine(engine_name) + return engine.get_dbus_object() def Destroy(self): self.__factory.destroy() self.__factory = None self.remove_from_connection () +class FactoryInfo(Serializable): + __NAME__ = "IBusFactoryInfo" + def __init__ (self, path=None, name=None, lang=None, icon=None, authors=None, credits=None): + super(FactoryInfo, self).__init__() + self.__path = path + self.__name = name + self.__lang = lang + self.__icon = icon + self.__authors = authors + self.__credits = credits + + def get_path(self): + return self.__path + + def get_name(self): + return self.__name + + def get_lang(self): + return self.__lang + + def get_icon(self): + return self.__icon + def get_authors(self): + return self.__authors + + def get_credits(self): + return self.__credits + + path = property(get_path) + name = property(get_name) + lang = property(get_lang) + icon = property(get_icon) + authors = property(get_authors) + credits = property(get_credits) + + def serialize(self, struct): + super(FactoryInfo, self).serialize(struct) + struct.append (dbus.ObjectPath(self.__path)) + struct.append (dbus.String(self.__name)) + struct.append (dbus.String(self.__lang)) + struct.append (dbus.String(self.__icon)) + struct.append (dbus.String(self.__authors)) + struct.append (dbus.String(self.__credits)) + + def deserialize(self, struct): + super(FactoryInfo, self).deserialize(struct) + if len(struct) < 5: + raise IBusException ("Can not deserialize IBusFactoryInfo") + + self.__path = struct.pop(0) + self.__name = struct.pop(0) + self.__lang = struct.pop(0) + self.__icon = struct.pop(0) + self.__authors = struct.pop(0) + self.__credits = struct.pop(0) + +serializable_register(FactoryInfo) + diff --git a/ibus/inputcontext.py b/ibus/inputcontext.py new file mode 100644 index 0000000..10233da --- /dev/null +++ b/ibus/inputcontext.py @@ -0,0 +1,301 @@ +# vim:set et sts=4 sw=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 + +__all__ = ( + "InputContext", + ) + +import sys +import gobject +import dbus +import dbus.lowlevel +import object +import common +import serializable + +class InputContext(object.Object): + __gsignals__ = { + "commit-text" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + (gobject.TYPE_PYOBJECT, ) + ), + "update-preedit-text" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + (gobject.TYPE_PYOBJECT, gobject.TYPE_UINT, gobject.TYPE_BOOLEAN) + ), + "show-preedit-text" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "hide-preedit-text" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "update-auxiliary-text" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + (gobject.TYPE_PYOBJECT, gobject.TYPE_BOOLEAN) + ), + "show-auxiliary-text" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "hide-auxiliary-text" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "update-lookup-table" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + (gobject.TYPE_PYOBJECT, gobject.TYPE_BOOLEAN) + ), + "show-lookup-table" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "hide-lookup-table" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "page-up-lookup-table" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "page-down-lookup-table" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "cursor-up-lookup-table" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "cursor-down-lookup-table" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "enabled" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "disabled" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + } + + def __init__(self, bus, path): + super(InputContext, self).__init__() + + self.__bus = bus + self.__context = bus.get_dbusconn().get_object(common.IBUS_SERVICE_IBUS, path) + self.__signal_matches = [] + + m = self.__context.connect_to_signal("CommitText", self.__commit_text_cb) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("UpdatePreeditText", self.__update_preedit_text_cb) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("UpdateAuxiliaryText", self.__update_auxiliary_text_cb) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("UpdateLookupTable", self.__update_lookup_table_cb) + self.__signal_matches.append(m) + + m = self.__context.connect_to_signal("Enabled", lambda *args: self.emit("enabled")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("Disabled", lambda *args: self.emit("disabled")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("ShowPreeditText", lambda *args: self.emit("show-preedit-text")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("HidePreeditText", lambda *args: self.emit("hide-preedit-text")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("ShowAuxiliaryText", lambda *args: self.emit("show-auxiliary-text")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("HideAuxiliaryText", lambda *args: self.emit("hide-auxiliary-text")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("ShowLookupTable", lambda *args: self.emit("show-lookup-table")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("HideLookupTable", lambda *argss: self.emit("hide-lookup-table")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("PageUpLookupTable", lambda *args: self.emit("page-up-lookup-table")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("PageDownLookupTable", lambda *args: self.emit("page-down-lookup-table")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("CursorUpLookupTable", lambda *args: self.emit("cursor-up-lookup-table")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("CursorDownLookupTable", lambda *args: self.emit("cursor-down-lookup-table")) + self.__signal_matches.append(m) + + def __commit_text_cb(self, *args): + text = serializable.deserialize_object(args[0]) + self.emit("commit-text", text) + + def __update_preedit_text_cb(self, *args): + text = serializable.deserialize_object(args[0]) + cursor_pos = args[1] + visible = args[2] + self.emit("update-preedit-text", text, cursor_pos, visible) + + def __update_auxiliary_text_cb(self, *args): + text = serializable.deserialize_object(args[0]) + visible = args[1] + self.emit("update-auxiliray-text", text, visible) + + def __update_lookup_table_cb(self, *args): + table = serializable.deserialize_object(args[0]) + visible = args[1] + self.emit("update-lookup-table", table, visible) + + def process_key_event(self, keyval, modifiers): + keyval = dbus.UInt32(keyval) + modifiers = dbus.UInt32(modifiers) + return self.__context.ProcessKeyEvent(keyval, modifiers) + + def set_cursor_location(self, x, y, w, h): + x = dbus.Int32(x) + y = dbus.Int32(y) + w = dbus.Int32(w) + h = dbus.Int32(h) + return self.__context.SetCursorLocation(x, y, w, h) + + def focus_in(self): + return self.__context.FocusIn() + + def focus_out(self): + return self.__context.FocusOut() + + def reset(self): + return self.__context.Reset() + + def is_enabled(self): + return self.__context.IsEnabled() + + def set_capabilities(self, caps): + caps = dbus.UInt32(caps) + return self.__context.SetCapabilities(caps) + + def destroy(self): + self.__context.Destroy() + super(InputContext, self).destroy() + + def get_engine(self): + try: + engine = self.__context.GetEngine() + engine = serializable.deserialize_object(engine) + return engine + except: + return None + + def set_engine(self, engine): + return self.__context.SetEngine(engine.name) + + +def test(): + import gtk + import gtk.gdk + from bus import Bus + import modifier + import text + import attribute + import property + import lookuptable + import factory + + class TestWindow(gtk.Window): + def __init__(self): + super(TestWindow,self).__init__() + + self.__bus = Bus() + print self.__bus.get_name() + self.__bus.connect("disconnected", gtk.main_quit) + context_path = self.__bus.create_input_context("Test") + print context_path + self.__context = InputContext(self.__bus, context_path) + self.__context.set_capabilities (9) + + self.__context.connect("commit-text", self.__commit_text_cb) + self.__context.connect("update-preedit-text", self.__update_preedit_text_cb) + self.__context.connect("show-preedit-text", self.__show_preedit_text_cb) + self.__context.connect("update-auxiliary-text", self.__update_auxiliary_text_cb) + self.__context.connect("update-lookup-table", self.__update_lookup_table_cb) + self.__context.connect("enabled", self.__enabled_cb) + self.__context.connect("disabled", self.__disabled_cb) + + self.set_events(gtk.gdk.KEY_PRESS_MASK | gtk.gdk.KEY_RELEASE_MASK | gtk.gdk.FOCUS_CHANGE_MASK) + + self.connect("key-press-event", self.__key_press_event_cb) + self.connect("key-release-event", self.__key_release_event_cb) + self.connect("delete-event", gtk.main_quit) + self.connect("focus-in-event", lambda *args: self.__context.focus_in()) + self.connect("focus-out-event", lambda *args: self.__context.focus_out()) + + self.show_all() + + def __commit_text_cb(self, context, text): + print "commit-text:", text.text + + def __update_preedit_text_cb(self, context, text, cursor_pos, visible): + print "preedit-text:", text.text, cursor_pos, visible + + def __show_preedit_text_cb(self, context): + print "show-preedit-text" + + def __hide_preedit_text_cb(self, context): + print "hide-preedit-text" + + def __update_auxiliary_text_cb(self, context, text, visible): + print "auxiliary-text:", text.text, visible + + def __update_lookup_table_cb(self, context, table, visible): + print "update-lookup-table:", visible + + def __enabled_cb(self, context): + print "enabled" + info = context.get_factory_info() + print "factory = %s" % info.name + + def __disabled_cb(self, context): + print "disabled" + + def __key_press_event_cb(self, widget, event): + self.__context.process_key_event(event.keyval, event.state) + + def __key_release_event_cb(self, widget, event): + self.__context.process_key_event(event.keyval, event.state | modifier.RELEASE_MASK) + + w = TestWindow() + gtk.main() + +if __name__ == "__main__": + test() + diff --git a/ibus/interface/Makefile.am b/ibus/interface/Makefile.am index 0e1f8b9..ffc019c 100644 --- a/ibus/interface/Makefile.am +++ b/ibus/interface/Makefile.am @@ -24,6 +24,7 @@ ibus_interface_PYTHON = \ ienginefactory.py \ iengine.py \ iibus.py \ + iinputcontext.py \ ipanel.py \ inotifications.py \ __init__.py \ diff --git a/ibus/interface/__init__.py b/ibus/interface/__init__.py index 5348395..90af265 100644 --- a/ibus/interface/__init__.py +++ b/ibus/interface/__init__.py @@ -20,6 +20,7 @@ # Boston, MA 02111-1307 USA from iibus import * +from iinputcontext import * from iengine import * from ienginefactory import * from ipanel import * diff --git a/ibus/interface/iconfig.py b/ibus/interface/iconfig.py index 171d17a..23954fa 100644 --- a/ibus/interface/iconfig.py +++ b/ibus/interface/iconfig.py @@ -23,22 +23,22 @@ __all__ = ("IConfig", ) import dbus.service from ibus.common import \ - IBUS_CONFIG_IFACE + IBUS_IFACE_CONFIG class IConfig(dbus.service.Object): # define method decorator. method = lambda **args: \ - dbus.service.method(dbus_interface=IBUS_CONFIG_IFACE, \ + dbus.service.method(dbus_interface=IBUS_IFACE_CONFIG, \ **args) # define signal decorator. signal = lambda **args: \ - dbus.service.signal(dbus_interface=IBUS_CONFIG_IFACE, \ + dbus.service.signal(dbus_interface=IBUS_IFACE_CONFIG, \ **args) # define async method decorator. async_method = lambda **args: \ - dbus.service.method(dbus_interface=IBUS_CONFIG_IFACE, \ + dbus.service.method(dbus_interface=IBUS_IFACE_CONFIG, \ async_callbacks=("reply_cb", "error_cb"), \ **args) diff --git a/ibus/interface/iengine.py b/ibus/interface/iengine.py index dfe285a..32ba998 100644 --- a/ibus/interface/iengine.py +++ b/ibus/interface/iengine.py @@ -23,27 +23,27 @@ __all__ = ("IEngine", ) import dbus.service from ibus.common import \ - IBUS_ENGINE_IFACE + IBUS_IFACE_ENGINE class IEngine(dbus.service.Object): # define method decorator. method = lambda **args: \ - dbus.service.method(dbus_interface=IBUS_ENGINE_IFACE, \ + dbus.service.method(dbus_interface=IBUS_IFACE_ENGINE, \ **args) # define signal decorator. signal = lambda **args: \ - dbus.service.signal(dbus_interface=IBUS_ENGINE_IFACE, \ + dbus.service.signal(dbus_interface=IBUS_IFACE_ENGINE, \ **args) # define async method decorator. async_method = lambda **args: \ - dbus.service.method(dbus_interface=IBUS_ENGINE_IFACE, \ + dbus.service.method(dbus_interface=IBUS_IFACE_ENGINE, \ async_callbacks=("reply_cb", "error_cb"), \ **args) - @method(in_signature="ubu", out_signature="b") - def ProcessKeyEvent(self, keyval, is_press, state): + @method(in_signature="uu", out_signature="b") + def ProcessKeyEvent(self, keyval, state): pass @method(in_signature="iiii") @@ -89,29 +89,30 @@ class IEngine(dbus.service.Object): @method() def Destroy(self): pass - @signal(signature="s") - def CommitString(self, text): pass + + @signal(signature="v") + def CommitText(self, text): pass @signal(signature="ubu") def ForwardKeyEvent(self, keyval, is_press, state): pass - @signal(signature="sa(uuuu)ib") - def UpdatePreedit(self, text, attrs, cursor_pos, visible): pass + @signal(signature="vub") + def UpdatePreeditText(self, text, cursor_pos, visible): pass @signal() - def ShowPreedit(self): pass + def ShowPreeditText(self): pass @signal() - def HidePreedit(self): pass + def HidePreeditText(self): pass - @signal(signature="sa(uuuu)b") - def UpdateAuxString(self, text, attrs, visible): pass + @signal(signature="vb") + def UpdateAuxiliaryText(self, text, visible): pass @signal() - def ShowAuxString(self): pass + def ShowAuxiliaryText(self): pass @signal() - def HideAuxString(self): pass + def HideAuxiliaryText(self): pass @signal(signature="vb") def UpdateLookupTable(self, lookup_table, visible): pass diff --git a/ibus/interface/ienginefactory.py b/ibus/interface/ienginefactory.py index 5670e81..5e93fd8 100644 --- a/ibus/interface/ienginefactory.py +++ b/ibus/interface/ienginefactory.py @@ -23,17 +23,17 @@ __all__ = ("IEngineFactory", ) import dbus.service from ibus.common import \ - IBUS_ENGINE_FACTORY_IFACE + IBUS_IFACE_ENGINE_FACTORY class IEngineFactory(dbus.service.Object): # define method decorator. method = lambda **args: \ - dbus.service.method(dbus_interface=IBUS_ENGINE_FACTORY_IFACE, \ + dbus.service.method(dbus_interface=IBUS_IFACE_ENGINE_FACTORY, \ **args) # define async method decorator. async_method = lambda **args: \ - dbus.service.method(dbus_interface=IBUS_ENGINE_FACTORY_IFACE, \ + dbus.service.method(dbus_interface=IBUS_IFACE_ENGINE_FACTORY, \ async_callbacks=("reply_cb", "error_cb"), \ **args) @@ -51,8 +51,8 @@ class IEngineFactory(dbus.service.Object): # Create an input context and return the id of the context. # If failed, it will return "" or None. - @method(out_signature="o") - def CreateEngine(self): pass + @method(in_signature="s", out_signature="o") + def CreateEngine(self, engine_name): pass # Destroy the engine @method() diff --git a/ibus/interface/iibus.py b/ibus/interface/iibus.py index cc5c351..848f798 100644 --- a/ibus/interface/iibus.py +++ b/ibus/interface/iibus.py @@ -23,100 +23,49 @@ __all__ = ("IIBus", ) import dbus.service from ibus.common import \ - IBUS_IFACE + IBUS_IFACE_IBUS class IIBus(dbus.service.Object): # define method decorator. method = lambda **args: \ - dbus.service.method(dbus_interface=IBUS_IFACE, \ + dbus.service.method(dbus_interface=IBUS_IFACE_IBUS, \ connection_keyword="dbusconn", \ **args) # define async method decorator. async_method = lambda **args: \ - dbus.service.method(dbus_interface=IBUS_IFACE, \ + dbus.service.method(dbus_interface=IBUS_IFACE_IBUS, \ connection_keyword="dbusconn", \ async_callbacks=("reply_cb", "error_cb"), \ **args) @method(out_signature="s") - def GetIBusAddress(self, dbusconn): pass + def GetAddress(self, dbusconn): pass # methods for ibus clients - @method(in_signature="s", out_signature="s") + @method(in_signature="s", out_signature="o") def CreateInputContext(self, client_name, dbusconn): pass - @method(in_signature="s") - def ReleaseInputContext(self, ic, dbusconn): pass - - @async_method(in_signature="subu", out_signature="b") - def ProcessKeyEvent(self, ic, keyval, is_press, state, dbusconn, reply_cb, error_cb): pass - - @method(in_signature="siiii") - def SetCursorLocation(self, ic, x, y, w, h, dbusconn): pass - - @method(in_signature="s") - def FocusIn(self, ic, dbusconn): pass - - @method(in_signature="s") - def FocusOut(self, ic, dbusconn): pass - - @method(in_signature="s") - def Reset(self, ic, dbusconn): pass - - @method(in_signature="s", out_signature="b") - def IsEnabled(self, ic, dbusconn): pass - - @method(in_signature="si") - def SetCapabilities(self, ic, caps, dbusconn): pass + @method(in_signature="s", out_signature="sb") + def GetInputContextStates(self, ic, dbusconn): pass # methods for ibus engine provide - @method(in_signature="ao") + @method(in_signature="av") def RegisterFactories(self, object_paths, dbusconn): pass - @method(in_signature="ao") + @method(in_signature="av") def UnregisterFactories(self, object_paths, dbusconn): pass # general methods - @method(out_signature="av") - def GetFactories(self, dbusconn): pass + @method(in_signature="av") + def RegisterComponent(self, components, dbusconn): pass - @method(in_signature="o", out_signature="av") - def GetFactoryInfo(self, factory_path, dbusconn): pass - - @method(in_signature="o") - def SetFactory(self, factory_path, dbusconn): pass - - @method(in_signature="s", out_signature="sb") - def GetInputContextStates(self, ic, dbusconn): pass - - @method(out_signature="a(sssssssb)") - def RegisterListEngines(self, dbusconn): pass - - @method() - def RegisterReloadEngines(self, dbusconn): pass - - @method(in_signature="ss") - def RegisterStartEngine(self, lang, name, dbusconn): pass - - @method(in_signature="ss") - def RegisterRestartEngine(self, lang, name, dbusconn): pass + @method(out_signature="av") + def ListEngines(self, dbusconn): pass - @method(in_signature="ss") - def RegisterStopEngine(self, lang, name, dbusconn): pass + @method(out_signature="av") + def ListActiveEngines(self, dbusconn): pass @async_method() def Kill(self, dbusconn, reply_cb, error_cb): pass - #sigals - def CommitString(self, ic, text): pass - - def UpdatePreedit(self, ic, text, attrs, cursor_pos, show): pass - - def Enabled(self, ic): pass - - def Disabled(self, ic): pass - - def ConfigValueChanged(self, key, value): pass - - def ConfigReload(self): pass diff --git a/ibus/interface/iinputcontext.py b/ibus/interface/iinputcontext.py new file mode 100644 index 0000000..e5cf129 --- /dev/null +++ b/ibus/interface/iinputcontext.py @@ -0,0 +1,133 @@ +# vim:set et sts=4 sw=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 + +__all__ = ("IInputContext", ) + +import dbus.service +from ibus.common import \ + IBUS_IFACE_INPUT_CONTEXT + +class IInputContext(dbus.service.Object): + # define method decorator. + method = lambda **args: \ + dbus.service.method(dbus_interface=IBUS_IFACE_INPUT_CONTEXT, \ + **args) + + # define async method decorator. + async_method = lambda **args: \ + dbus.service.method(dbus_interface=IBUS_IFACE_INPUT_CONTEXT, \ + async_callbacks=("reply_cb", "error_cb"), \ + **args) + + # define signal decorator. + signal = lambda **args: \ + dbus.service.signal(dbus_interface=IBUS_IFACE_INPUT_CONTEXT, \ + **args) + + @async_method(in_signature="uu", out_signature="b") + def ProcessKeyEvent(self, keyval, state, reply_cb, error_cb): pass + + @method(in_signature="iiii") + def SetCursorLocation(self, x, y, w, h): pass + + @method() + def FocusIn(self): pass + + @method() + def FocusOut(self): pass + + @method() + def Reset(self): pass + + @method(out_signature="b") + def IsEnabled(self): pass + + @method(in_signature="u") + def SetCapabilities(self, caps): pass + + @method(out_signature="v") + def GetEngineDesc(self): pass + + @method(in_signature="s") + def SetEngine(self, engine_name): pass + + @method() + def Destroy(self): pass + + #sigals + @signal(signature="v") + def CommitText(self, text): pass + + @signal() + def Enabled(self): pass + + @signal() + def Disabled(self): pass + + @signal(signature="uu") + def ForwardKeyEvent(self, keyval, state): pass + + @signal(signature="vub") + def UpdatePreeditText(self, text, cursor_pos, visible): pass + + @signal() + def ShowPreeditText(self): pass + + @signal() + def HidePreeditText(self): pass + + @signal(signature="vb") + def UpdateAuxiliaryText(self, text, visible): pass + + @signal() + def ShowAuxiliaryText(self): pass + + @signal() + def HideAuxiliaryText(self): pass + + @signal(signature="vb") + def UpdateLookupTable(self, lookup_table, visible): pass + + @signal() + def ShowLookupTable(self): pass + + @signal() + def HideLookupTable(self): pass + + @signal() + def PageUpLookupTable(self): pass + + @signal() + def PageDownLookupTable(self): pass + + @signal() + def CursorUpLookupTable(self): pass + + @signal() + def CursorDownLookupTable(self): pass + + @signal(signature="v") + def RegisterProperties(self, props): pass + + @signal(signature="v") + def UpdateProperty(self, prop): pass + + diff --git a/ibus/interface/inotifications.py b/ibus/interface/inotifications.py index 7d667f2..74d4dcf 100644 --- a/ibus/interface/inotifications.py +++ b/ibus/interface/inotifications.py @@ -23,22 +23,22 @@ __all__ = ("INotifications", ) import dbus.service from ibus.common import \ - IBUS_NOTIFICATIONS_IFACE + IBUS_IFACE_NOTIFICATIONS class INotifications(dbus.service.Object): # define method decorator. method = lambda **args: \ - dbus.service.method(dbus_interface = IBUS_NOTIFICATIONS_IFACE, \ + dbus.service.method(dbus_interface = IBUS_IFACE_NOTIFICATIONS, \ **args) # define signal decorator. signal = lambda **args: \ - dbus.service.signal(dbus_interface = IBUS_NOTIFICATIONS_IFACE, \ + dbus.service.signal(dbus_interface = IBUS_IFACE_NOTIFICATIONS, \ **args) # define async method decorator. async_method = lambda **args: \ - dbus.service.method(dbus_interface = IBUS_NOTIFICATIONS_IFACE, \ + dbus.service.method(dbus_interface = IBUS_IFACE_NOTIFICATIONS, \ async_callbacks = ("reply_cb", "error_cb"), \ **args) diff --git a/ibus/interface/ipanel.py b/ibus/interface/ipanel.py index 83d6585..e5d174c 100644 --- a/ibus/interface/ipanel.py +++ b/ibus/interface/ipanel.py @@ -23,44 +23,44 @@ __all__ = ("IPanel", ) import dbus.service from ibus.common import \ - IBUS_PANEL_IFACE + IBUS_IFACE_PANEL class IPanel(dbus.service.Object): # define method decorator. method = lambda **args: \ - dbus.service.method(dbus_interface=IBUS_PANEL_IFACE, \ + dbus.service.method(dbus_interface=IBUS_IFACE_PANEL, \ **args) # define signal decorator. signal = lambda **args: \ - dbus.service.signal(dbus_interface=IBUS_PANEL_IFACE, \ + dbus.service.signal(dbus_interface=IBUS_IFACE_PANEL, \ **args) # define async method decorator. async_method = lambda **args: \ - dbus.service.method(dbus_interface=IBUS_PANE_IFACE, \ + dbus.service.method(dbus_interface=IBUS_IFACE_PANEL, \ async_callbacks=("reply_cb", "error_cb"), \ **args) @method(in_signature="iiii") def SetCursorLocation(self, x, y, w, h): pass - @method(in_signature="svub") - def UpdatePreedit(self, text, attrs, cursor_pos, visible): pass + @method(in_signature="vub") + def UpdatePreeditText(self, text, cursor_pos, visible): pass @method() - def ShowPreedit(self): pass + def ShowPreeditText(self): pass @method() - def HidePreedit(self): pass + def HidePreeditText(self): pass - @method(in_signature="svb") - def UpdateAuxString(self, text, attrs, visible): pass + @method(in_signature="vb") + def UpdateAuxiliaryText(self, text, visible): pass @method() - def ShowAuxString(self): pass + def ShowAuxiliaryText(self): pass @method() - def HideAuxString(self): pass + def HideAuxiliaryText(self): pass @method(in_signature="vb") def UpdateLookupTable(self, lookup_table, visible): pass @@ -95,14 +95,14 @@ class IPanel(dbus.service.Object): @method() def HideLanguageBar(self): pass - @method(in_signature="s") + @method(in_signature="o") def FocusIn(self, ic): pass - @method(in_signature="s") + @method(in_signature="o") def FocusOut(self, ic): pass @method() - def StatesChanged(self): pass + def StateChanged(self): pass @method() def Reset(self): pass @@ -126,12 +126,12 @@ class IPanel(dbus.service.Object): @signal() def CursorDown(self): pass - @signal() + @signal(signature="si") def PropertyActivate(self, prop_name, prop_state): pass - @signal() + @signal(signature="s") def PropertyShow(self, prop_name): pass - @signal() + @signal(signature="s") def PropertyHide(self, prop_name): pass diff --git a/ibus/lookuptable.py b/ibus/lookuptable.py index 27819ce..bedd8bf 100644 --- a/ibus/lookuptable.py +++ b/ibus/lookuptable.py @@ -21,54 +21,24 @@ __all__ = ( "LookupTable", - "lookup_table_from_dbus_value" ) import dbus -from attribute import * +from serializable import * from exception import * -class CandidateList(list): - def __init__(self, items = []): - super(CandidateList, self).__init__(items) - - def clean(self): - del self[:] - def __getslice__(self, i, j): - items = super(CandidateList, self).__getslice__(i, j) - return CandidateList(items) - - def to_dbus_value(self): - value = dbus.Array([], signature="v") - for text, attrs in self: - value.append(dbus.Struct((dbus.String(text), attrs.to_dbus_value()))) - return value - - def from_dbus_value(self, value): - candidates = [] - if not isinstance(value, dbus.Array): - raise dbus.Exception("Candidates must from dbus.Array(a(sa(...))") - for candidate in value: - if not isinstance(candidate, dbus.Struct): - raise IBusException("Candidates must from dbus.Array(a(sa(...)))") - if len(candidate) != 2 or \ - not isinstance(candidate[0], dbus.String): - raise IBusException("Candidates must from dbus.Array(a(sa(...)))") - text = candidate[0] - attrs = attr_list_from_dbus_value(candidate[1]) - candidates.append((text, attrs)) - - self.clean() - self[:] = candidates - -class LookupTable(object): - def __init__(self, page_size=5, labels=None): +class LookupTable(Serializable): + __NAME__ = "IBusLookupTable" + def __init__(self, page_size=5, cursor_pos=0, coursor_visible=True, candidates=None): super(LookupTable, self).__init__() self.__cursor_visible = True - self.__cursor_pos = 0 - self.__candidates = CandidateList() + self.__cursor_pos = cursor_pos + if candidates == None: + self.__candidates = list() + else: + self.__candidates = candidates self.set_page_size(page_size) - self.set_labels(labels) + self.set_labels(None) def set_page_size(self, page_size): self.__page_size = page_size @@ -159,18 +129,16 @@ class LookupTable(object): return True def clean(self): - self.__candidates.clean() + self.__candidates = list() self.__cursor_pos = 0 - def append_candidate(self, candidate, attrs = None): - if attrs == None: - attrs = AttrList() - self.__candidates.append((candidate, attrs)) + def append_candidate(self, text): + self.__candidates.append(text) def get_candidate(self, index): return self.__candidates[index] - def get_canidates_in_current_page(self): + def get_candidates_in_current_page(self): page = self.__cursor_pos / self.__page_size start_index = page * self.__page_size end_index = min((page + 1) * self.__page_size, len(self.__candidates)) @@ -185,50 +153,43 @@ class LookupTable(object): def __len__(self): return self.get_number_of_candidates() - def to_dbus_value(self): - value = (dbus.Int32(self.__page_size), - dbus.Int32(self.__cursor_pos), - dbus.Boolean(self.__cursor_visible), - self.__candidates.to_dbus_value()) - return dbus.Struct(value) - - def current_page_to_dbus_value(self): - candidates = self.get_canidates_in_current_page() - value = (dbus.Int32(self.__page_size), - dbus.Int32(self.__cursor_pos % self.__page_size), - dbus.Boolean(self.__cursor_visible), - candidates.to_dbus_value()) - return dbus.Struct(value) - - def from_dbus_value(self, value): - if not isinstance(value, dbus.Struct): - raise dbus.Exception("LookupTable must from dbus.Struct(uuba(...))") - - if len(value) != 4 or \ - not isinstance(value[0], dbus.Int32) or \ - not isinstance(value[1], dbus.Int32) or \ - not isinstance(value[2], dbus.Boolean): - raise dbus.Exception("LookupTable must from dbus.Struct(uuba(...))") - - self.__candidates.from_dbus_value(value[3]) - self.__page_size = value[0] - self.__cursor_pos = value[1] - self.__cursor_visible = value[2] - -def lookup_table_from_dbus_value(value): - lookup_table = LookupTable() - lookup_table.from_dbus_value(value) - return lookup_table - -def unit_test(): + def serialize(self, struct): + super(LookupTable, self).serialize(struct) + struct.append(dbus.UInt32(self.__page_size)) + struct.append(dbus.UInt32(self.__cursor_pos)) + struct.append(dbus.Boolean(self.__cursor_visible)) + candidates = map(lambda c: serialize_object(c), self.__candidates) + struct.append(dbus.Array(candidates, signature="v")) + + def get_current_page_as_lookup_table(self): + candidates = self.get_candidates_in_current_page() + return LookupTable(self.__page_size, + self.__cursor_pos % self.__page_size, + self.__cursor_visible, + candidates) + + def deserialize(self, struct): + super(LookupTable, self).deserialize(struct) + + self.__page_size = struct.pop(0) + self.__cursor_pos = struct.pop(0) + self.__cursor_visible = struct.pop(0) + self.__candidates = map(deserialize_object, struct.pop(0)) + + +serializable_register(LookupTable) + +def test(): t = LookupTable() # attrs = AttrList() # attrs.append(AttributeBackground(RGB(233, 0,1), 0, 3)) # attrs.append(AttributeUnderline(1, 3, 5)) t.append_candidate("Hello") - value = t.to_dbus_value() - print value - t = lookup_table_from_dbus_value(value) + value = serialize_object(t) + t = deserialize_object(value) + t = t.get_current_page_as_lookup_table() + value = serialize_object(t) + t = deserialize_object(value) if __name__ == "__main__": - unit_test() + test() diff --git a/ibus/notifications.py b/ibus/notifications.py index 3ae067a..0509548 100644 --- a/ibus/notifications.py +++ b/ibus/notifications.py @@ -21,12 +21,12 @@ __all__ = ( "NotificationsBase", - "IBUS_NOTIFICATIONS_NAME", - "IBUS_NOTIFICATIONS_PATH" + "IBUS_SERVICE_NOTIFICATIONS", + "IBUS_PATH_NOTIFICATIONS" ) -IBUS_NOTIFICATIONS_NAME = "org.freedesktop.ibus.Notifications" -IBUS_NOTIFICATIONS_PATH = "/org/freedesktop/ibus/Notifications" +IBUS_SERVICE_NOTIFICATIONS = "org.freedesktop.IBus.Notifications" +IBUS_PATH_NOTIFICATIONS = "/org/freedesktop/IBus/Notifications" import ibus from ibus import interface @@ -50,7 +50,7 @@ class NotificationsBase(ibus.Object): class NotificationsProxy(interface.INotifications): def __init__ (self, notify, dbusconn): - super(NotificationsProxy, self).__init__(dbusconn, IBUS_NOTIFICATIONS_PATH) + super(NotificationsProxy, self).__init__(dbusconn, IBUS_PATH_NOTIFICATIONS) self.__dbusconn = dbusconn self.__notify = notify diff --git a/ibus/object.py b/ibus/object.py index ca2b380..b00e47a 100644 --- a/ibus/object.py +++ b/ibus/object.py @@ -28,21 +28,30 @@ import gobject class Object(gobject.GObject): __gsignals__ = { 'destroy' : ( - gobject.SIGNAL_RUN_FIRST, + gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()) } def __init__(self): super(Object, self).__init__() - self._destroyed = False + self.__destroyed = False + self.__handlers = [] def destroy(self): - if not self._destroyed: + if not self.__destroyed: self.emit("destroy") - self._destroyed = True + self.__destroyed = True def do_destroy(self): - pass + self.__disconnect_all() + + def connect(self, signal_name, handler, *args): + id = super(Object, self).connect(signal_name, handler, *args) + self.__handlers.append(id) + + def __disconnect_all(self): + map(self.disconnect, self.__handlers) + self.__handlers = [] gobject.type_register(Object) diff --git a/ibus/observedpath.py b/ibus/observedpath.py new file mode 100644 index 0000000..94b3e7e --- /dev/null +++ b/ibus/observedpath.py @@ -0,0 +1,64 @@ +# vim:set et sts=4 sw=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 + +__all__ = ( + "ObservedPath", + ) + +import dbus +from exception import IBusException +from serializable import * + +class ObservedPath(Serializable): + __NAME__ = "IBusObservedPath" + def __init__ (self, path="", mtime=0): + super(ObservedPath, self).__init__() + self.__path = path + self.__mtime = mtime + + def get_path(self): + return self.__path + + def get_mtime(self): + return self.__mtime + + path = property(get_path) + mtime = property(get_mtime) + + def serialize(self, struct): + super(ObservedPath, self).serialize(struct) + struct.append (dbus.String(self.__path)) + struct.append (dbus.Int64(self.__mtime)) + + def deserialize(self, struct): + super(ObservedPath, self).deserialize(struct) + self.__path = struct.pop(0) + self.__mtime = struct.pop(0) + +serializable_register(ObservedPath) + +def test(): + op = ObservedPath("/tmp", 111) + value = serialize_object(op) + op= deserialize_object(value) + +if __name__ == "__main__": + test() diff --git a/ibus/panel.py b/ibus/panel.py index 74b220d..9a34109 100644 --- a/ibus/panel.py +++ b/ibus/panel.py @@ -25,15 +25,17 @@ __all__ = ( "PanelButton", "PanelToggleButton", "PanelMenu", - "IBUS_PANEL_NAME", - "IBUS_PANEL_PATH" + "IBUS_SERVICE_PANEL", + "IBUS_PATH_PANEL" ) -IBUS_PANEL_NAME = "org.freedesktop.ibus.Panel" -IBUS_PANEL_PATH = "/org/freedesktop/ibus/Panel" +IBUS_SERVICE_PANEL = "org.freedesktop.IBus.Panel" +IBUS_PATH_PANEL = "/org/freedesktop/IBus/Panel" -import ibus -from ibus import interface +from serializable import * +from object import Object +import interface +import dbus class PanelItem: pass @@ -47,30 +49,31 @@ class PanelToggleButton(PanelButton): class PanelMenu(PanelItem): pass -class PanelBase(ibus.Object): +class PanelBase(Object): def __init__(self, bus): super(PanelBase, self).__init__() - self.__proxy = PanelProxy(self, bus.get_dbusconn()) + self.__bus = bus + self.__proxy = PanelProxy(self, bus) def set_cursor_location(self, x, y, w, h): pass - def update_preedit(self, text, attrs, cursor_pos, visible): + def update_preedit_text(self, text, cursor_pos, visible): pass - def show_preedit(self): + def show_preedit_text(self): pass - def hide_preedit(self): + def hide_preedit_text(self): pass - def update_aux_string(self, text, attrs, visible): + def update_auxiliary_text(self, text, visible): pass - def show_aux_string(self): + def show_auxiliary_text(self): pass - def hide_aux_string(self): + def hide_auxiliary_text(self): pass def update_lookup_table(self, lookup_table, visible): @@ -118,7 +121,7 @@ class PanelBase(ibus.Object): def focus_out(self, ic): pass - def states_changed(self): + def state_changed(self): pass def reset(self): @@ -140,47 +143,52 @@ class PanelBase(ibus.Object): self.__proxy.CursorDown() def property_activate(self, prop_name, prop_state): + prop_name = dbus.String(prop_name) + prop_state = dbus.Int32(prop_state) self.__proxy.PropertyActivate(prop_name, prop_state) def property_show(self, prop_name): + prop_name = dbus.String(prop_name) self.__proxy.PropertyShow(prop_name) def property_hide(self, prop_name): + prop_name = dbus.String(prop_name) self.__proxy.PropertyHide(prop_name) class PanelProxy(interface.IPanel): - def __init__ (self, panel, dbusconn): - super(PanelProxy, self).__init__(dbusconn, IBUS_PANEL_PATH) - self.__dbusconn = dbusconn + def __init__ (self, panel, bus): + super(PanelProxy, self).__init__(bus.get_dbusconn(), IBUS_PATH_PANEL) + self.__bus = bus self.__panel = panel + self.__focus_ic = None def SetCursorLocation(self, x, y, w, h): self.__panel.set_cursor_location(x, y, w, h) - def UpdatePreedit(self, text, attrs, cursor_pos, show): - attrs = ibus.attr_list_from_dbus_value(attrs) - self.__panel.update_preedit(text, attrs, cursor_pos, show) + def UpdatePreeditText(self, text, cursor_pos, visible): + text = deserialize_object(text) + self.__panel.update_preedit_text(text, cursor_pos, visible) - def ShowPreedit(self): - self.__panel.show_preedit() + def ShowPreeditText(self): + self.__panel.show_preedit_text() - def HidePreedit(self): - self.__panel.hide_preedit() + def HidePreeditText(self): + self.__panel.hide_preedit_text() - def UpdateAuxString(self, text, attrs, show): - attrs = ibus.attr_list_from_dbus_value(attrs) - self.__panel.update_aux_string(text, attrs, show) + def UpdateAuxiliaryText(self, text, visible): + text = deserialize_object(text) + self.__panel.update_auxiliary_text(text, visible) - def ShowAuxString(self): - self.__panel.show_aux_string() + def ShowAuxiliaryText(self): + self.__panel.show_auxiliary_text() - def HideAuxString(self): - self.__panel.hide_aux_string() + def HideAuxiliaryText(self): + self.__panel.hide_auxiliary_text() - def UpdateLookupTable(self, lookup_table, show): - lookup_table = ibus.lookup_table_from_dbus_value(lookup_table) - self.__panel.update_lookup_table(lookup_table, show) + def UpdateLookupTable(self, lookup_table, visible): + lookup_table = deserialize_object(lookup_table) + self.__panel.update_lookup_table(lookup_table, visible) def ShowLookupTable(self): self.__panel.show_lookup_table() @@ -213,11 +221,11 @@ class PanelProxy(interface.IPanel): self.__panel.hide_language_bar() def RegisterProperties(self, props): - props = ibus.prop_list_from_dbus_value(props) + props = deserialize_object(props) self.__panel.register_properties(props) def UpdateProperty(self, prop): - prop = ibus.property_from_dbus_value(prop) + prop = deserialize_object(prop) self.__panel.update_property(prop) def FocusIn(self, ic): @@ -226,8 +234,8 @@ class PanelProxy(interface.IPanel): def FocusOut(self, ic): self.__panel.focus_out(ic) - def StatesChanged(self): - self.__panel.states_changed() + def StateChanged(self): + self.__panel.state_changed() def Reset(self): self.__panel.reset() @@ -238,3 +246,41 @@ class PanelProxy(interface.IPanel): def Destroy(self): self.__panel.destroy() +def test(): + import gtk + from bus import Bus + from inputcontext import InputContext + import factory + import attribute + import property + import text + import lookuptable + + class TestPanel(PanelBase): + def __init__(self): + self.__bus = Bus() + self.__bus.connect("disconnected", gtk.main_quit) + super(TestPanel, self).__init__(self.__bus) + self.__bus.request_name(IBUS_SERVICE_PANEL, 0) + + def focus_in(self, ic): + print "focus-in:", ic + context = InputContext(self.__bus, ic) + info = context.get_factory_info() + print "factory:", info.name + + def focus_out(self, ic): + print "focus-out:", ic + + def update_auxiliary_text(self, text, visible): + print "update-auxiliary-text:", text.text + + def update_lookup_table(self, table, visible): + print "update-lookup-table", table + + panel = TestPanel() + gtk.main() + + +if __name__ == "__main__": + test() diff --git a/ibus/property.py b/ibus/property.py index 970975e..72f72a2 100644 --- a/ibus/property.py +++ b/ibus/property.py @@ -30,11 +30,11 @@ __all__ = ( "PROP_STATE_INCONSISTENT", "Property", "PropList", - "property_from_dbus_value", - "prop_list_from_dbus_value", ) import dbus +from text import Text +from serializable import * PROP_TYPE_NORMAL = 0 PROP_TYPE_TOGGLE = 1 @@ -52,18 +52,18 @@ def _to_unicode(text): if isinstance(text, str): return unicode(text, "utf8") raise TypeError("text must be instance of unicode or str") +def _to_text(text): + if isinstance(text, Text): + return text + text = _to_unicode(text) + return Text(text) -class Property(object): - def __init__(self, name, - type = PROP_TYPE_NORMAL, - label = u"", - icon = u"", - tooltip = u"", - sensitive = True, - visible = True, - state = PROP_STATE_UNCHECKED): +class Property(Serializable): + __NAME__ = "IBusProperty" + def __init__(self, key="", type=PROP_TYPE_NORMAL, label=u"", icon=u"", tooltip=u"", + sensitive=True, visible=True, state=PROP_STATE_UNCHECKED): super(Property, self).__init__() - self.__name = _to_unicode(name) + self.__key = _to_unicode(key) self.__type = type self.label = label self.icon = icon @@ -79,14 +79,14 @@ class Property(object): def get_sub_props(self): return self.__sub_props - def get_name(self): - return self.__name + def get_key(self): + return self.__key def get_type(self): return self.__type def set_label(self, label): - self.__label = _to_unicode(label) + self.__label = _to_text(label) def get_label(self): return self.__label @@ -98,7 +98,7 @@ class Property(object): return self.__icon def set_tooltip(self, tooltip): - self.__tooltip = _to_unicode(tooltip) + self.__tooltip = _to_text(tooltip) def get_tooltip(self): return self.__tooltip @@ -121,7 +121,7 @@ class Property(object): def get_visible(self): return self.__visible - name = property(get_name) + key = property(get_key) type = property(get_type) label = property(get_label, set_label) icon = property(get_icon, set_icon) @@ -146,38 +146,37 @@ class Property(object): return self.__sub_props.is_same(prop.__sub_props, test_all) - def to_dbus_value(self): - sub_props = self.__sub_props.to_dbus_value() - values = (dbus.String(self.__name), - dbus.UInt32(self.__type), - dbus.String(self.__label), - dbus.String(self.__icon), - dbus.String(self.__tooltip), - dbus.Boolean(self.__sensitive), - dbus.Boolean(self.__visible), - dbus.UInt32(self.__state), - sub_props) - return dbus.Struct(values) - - def from_dbus_value(self, value): - self.__name, \ - self.__type, \ - self.__label, \ - self.__icon, \ - self.__tooltip, \ - self.__sensitive, \ - self.__visible, \ - self.__state, \ - props = value - - self.__sub_props = prop_list_from_dbus_value(props) - -def property_from_dbus_value(value): - p = Property("") - p.from_dbus_value(value) - return p - -class PropList(object): + def serialize(self, struct): + super(Property, self).serialize(struct) + struct.append(dbus.String(self.__key)) + struct.append(dbus.UInt32(self.__type)) + struct.append(serialize_object(self.__label)) + struct.append(dbus.String(self.__icon)) + struct.append(serialize_object(self.__tooltip)) + struct.append(dbus.Boolean(self.__sensitive)) + struct.append(dbus.Boolean(self.__visible)) + struct.append(dbus.UInt32(self.__state)) + sub_props = serialize_object(self.__sub_props) + struct.append(sub_props) + + def deserialize(self, struct): + super(Property, self).deserialize(struct) + self.__key = struct.pop(0) + self.__type = struct.pop(0) + self.__label = deserialize_object(struct.pop(0)) + self.__icon = struct.pop(0) + self.__tooltip = deserialize_object(struct.pop(0)) + self.__sensitive = deserialize_object(struct.pop(0)) + self.__visible = struct.pop(0) + self.__state = struct.pop(0) + props = struct.pop(0) + + self.__sub_props = deserialize_object(props) + +serializable_register(Property) + +class PropList(Serializable): + __NAME__ = "IBusPropList" def __init__(self): super(PropList, self).__init__() self.__props = [] @@ -203,14 +202,14 @@ class PropList(object): return False return False - def to_dbus_value(self): - props = map(lambda p: p.to_dbus_value(), self.__props) - return dbus.Array(props, signature = "v") + def serialize(self, struct): + super(PropList, self).serialize(struct) + props = map(lambda p: serialize_object(p), self.__props) + struct.append (dbus.Array(props, signature = "v")) - def from_dbus_value(self, value): - props = [] - for p in value: - props.append(property_from_dbus_value(p)) + def deserialize(self, struct): + super(PropList, self).deserialize(struct) + props = map(lambda v: deserialize_object(v), struct.pop(0)) self.__props = props def __iter__(self): @@ -219,10 +218,7 @@ class PropList(object): def __getitem__(self, i): return self.__props.__getitem__(i) -def prop_list_from_dbus_value(value): - props = PropList() - props.from_dbus_value(value) - return props +serializable_register(PropList) def test(): props = PropList() @@ -230,18 +226,9 @@ def test(): props.append(Property(u"b")) props.append(Property(u"c")) props.append(Property(u"d")) - value = props.to_dbus_value() - print prop_list_from_dbus_value(value) - - p = Property(u"z") - p.set_sub_props(props) - props = PropList() - props.append(p) - value = props.to_dbus_value() - print prop_list_from_dbus_value(value) - p.label = u"a" - p.label = "a" - p.label = 1 + value = serialize_object(props) + props = deserialize_object(value) + print props if __name__ == "__main__": test() diff --git a/ibus/serializable.py b/ibus/serializable.py new file mode 100644 index 0000000..734940a --- /dev/null +++ b/ibus/serializable.py @@ -0,0 +1,81 @@ +# vim:set et sts=4 sw=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 + +__all__ = ( + "serializable_register", + "Serializable", + "serialize_object", + "deserialize_object", + ) + +from object import Object +import dbus +import gobject + +__serializable_name_dict = dict() + +def serializable_register(classobj): + if not issubclass(classobj, Serializable): + raise "%s is not a sub-class of Serializable" % str(classobj) + __serializable_name_dict[classobj.__NAME__] = classobj + +def serialize_object(o): + if isinstance(o, Serializable): + l = [o.__NAME__] + o.serialize(l) + return dbus.Struct(l) + else: + return o + +def deserialize_object(v): + if isinstance(v, tuple): + struct = list(v) + type_name = struct.pop(0) + type_class = __serializable_name_dict[type_name] + o = type_class() + o.deserialize (struct) + return o + return v + +class Serializable(Object): + __NAME__ = "IBusSerializable" + def __init__(self): + super(Serializable, self).__init__() + self.__attachments = dict() + + def serialize(self, struct): + d = dbus.Dictionary(signature="sv") + for k, v in self.__attachments.items(): + d[k] = serialize(v) + struct.append(d) + + def deserialize(self, struct): + d = struct.pop(0) + self.__attachments = dict() + for k, v in d.items(): + self.__atachments[k] = deserialize(v) + + def do_destroy(self): + self.__attachments = None + super(Serializable, self).do_destroy() + +__serializable_name_dict["IBusSerializable"] = Serializable +gobject.type_register(Serializable) diff --git a/ibus/text.py b/ibus/text.py new file mode 100644 index 0000000..9b47dbf --- /dev/null +++ b/ibus/text.py @@ -0,0 +1,68 @@ +# vim:set et sts=4 sw=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 + +__all__ = ( + "Text", + ) + +import dbus +from exception import IBusException +from serializable import * +from attribute import AttrList + +class Text(Serializable): + __NAME__ = "IBusText" + def __init__ (self, text="", attrs=None): + super(Text, self).__init__() + self.__text = text + self.__attrs = attrs + + def get_text(self): + return self.__text + + def get_attributes(self): + return self.__attrs + + text = property(get_text) + attributes = property(get_attributes) + + def serialize(self, struct): + super(Text, self).serialize(struct) + struct.append (dbus.String(self.__text)) + if self.__attrs == None: + self.__attrs = AttrList() + struct.append (serialize_object(self.__attrs)) + + def deserialize(self, struct): + super(Text, self).deserialize(struct) + + self.__text = struct.pop(0) + self.__attrs = deserialize_object(struct.pop(0)) + +serializable_register(Text) + +def test(): + text = Text("Hello") + value = serialize_object(text) + text = deserialize_object(value) + +if __name__ == "__main__": + test() diff --git a/launcher/Makefile.am b/launcher/Makefile.am deleted file mode 100644 index 807f331..0000000 --- a/launcher/Makefile.am +++ /dev/null @@ -1,33 +0,0 @@ -# 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 - -bin_SCRIPTS = ibus - -desktop_DATA = ibus.desktop -desktopdir = $(datadir)/applications - -EXTRA_DIST = \ - ibus.in \ - ibus.desktop.in \ - $(NULL) - -CLEANFILES = \ - $(NULL) diff --git a/launcher/ibus.desktop.in b/launcher/ibus.desktop.in deleted file mode 100644 index 6b15b77..0000000 --- a/launcher/ibus.desktop.in +++ /dev/null @@ -1,11 +0,0 @@ -[Desktop Entry] -Encoding=UTF-8 -Name=iBus -GenericName=Intelligent Input Bus -Comment=Intellignent Input Bus -Exec=ibus -Icon=ibus -Terminal=false -Type=Application -StartupNotify=false -Categories=Utility; diff --git a/launcher/ibus.in b/launcher/ibus.in deleted file mode 100644 index 0f8c5fd..0000000 --- a/launcher/ibus.in +++ /dev/null @@ -1,152 +0,0 @@ -#!/usr/bin/env python -# vim:set et sts=4 sw=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 - -import os -import os.path -import atexit -import sys -import time -import ibus -import dbus -import signal - -daemon = "@prefix@/bin/ibus-daemon" -x11 = "@prefix@/bin/ibus-x11" -ui = "@prefix@/bin/ibus-ui-gtk" -conf = "@prefix@/bin/ibus-gconf" - -class Launcher(object): - def __init__(self): - super(Launcher, self).__init__() - self.__daemon_pid = 0 - self.__ui_pid = 0 - self.__conf_pid = 0 - self.__x11_pid = 0 - self.__bus = None - self.__preload_engine_completed = False - - def __start_process(self, path, args, cmd): - pid = 0 - try: - print "Starting %s" % cmd, - pid = os.spawnv (os.P_NOWAIT, path, args) - print "OK" - except: - print >> sys.stderr, "Start %s Failed" % cmd - return pid - - def __bus_destroy_cb(self, bus): - self.__bus = None - ibus.main_quit() - - def __bus_config_reloaded_cb(self, bus): - self.__launch_auto_load_engines() - - def __signal_cb(self, sig, stack): - if sig == signal.SIGCHLD: - pid, status = os.wait() - if pid == self.__daemon_pid: - self.__daemon_pid = 0 - self.__bus = None - elif pid == self.__x11_pid: - self.__x11_pid = 0 - elif pid == self.__ui_pid: - self.__ui_pid = 0 - elif pid == self.__conf_pid: - self.__conf_pid = 0 - elif sig == signal.SIGTERM or sig == signal.SIGINT: - sys.exit(1) - - def __atexit_cb(self): - if self.__bus: - try: - self.__bus.kill() - except: - pass - os.kill(-os.getpid(), signal.SIGTERM) - - def run(self): - try: - bus = ibus.Bus() - print >> sys.stderr, "Found an ibus-daemon has been started!" - sys.exit(1) - except dbus.DBusException, e: - pass - - # make self process group leader - if os.getpid() != os.getpgid(os.getpid()): - os.setpgid(0, 0) - - signal.signal(signal.SIGCHLD, self.__signal_cb) - signal.signal(signal.SIGINT, self.__signal_cb) - signal.signal(signal.SIGTERM, self.__signal_cb) - atexit.register(self.__atexit_cb) - - # start ibus-daemon - self.__daemon_pid = self.__start_process(daemon, [daemon], "ibus-daemon") - if self.__daemon_pid <= 0: - sys.exit(1) - - for i in range(5): - time.sleep (1) - try: - self.__bus = ibus.Bus() - break - except: - pass - - if self.__bus == None: - print >> sys.stderr, "Start ibus-daemon failed" - sys.exit(1) - - self.__bus.connect("destroy", self.__bus_destroy_cb) - self.__bus.connect("config-reloaded", self.__bus_config_reloaded_cb) - - self.__conf_pid = self.__start_process(conf, [conf], "ibus-conf") - self.__ui_pid = self.__start_process(ui, [ui], "ibus-ui-gtk") - self.__x11_pid = self.__start_process(x11, [x11, "--kill-daemon"], "ibus-x11") - ibus.main() - - def __launch_auto_load_engines(self): - if self.__preload_engine_completed: - return - engines = [] - try: - engines = self.__bus.config_get_value("general", "preload_engines", None) - if not engines: - engines = [] - else: - self.__preload_engine_completed = True - except: - pass - for e in engines: - try: - lang, name = e.split(":") - self.__bus.register_start_engine(lang, name) - except: - import traceback - traceback.print_exc() - - - -if __name__ == "__main__": - Launcher().run() diff --git a/lib/gtk2/Makefile.am b/lib/gtk2/Makefile.am deleted file mode 100644 index e4b1cd1..0000000 --- a/lib/gtk2/Makefile.am +++ /dev/null @@ -1,71 +0,0 @@ -# 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 - -INCLUDES = \ - -I$(top_srcdir) \ - $(NULL) - -BUILT_SOURCES = \ - ibusmarshalers.h \ - ibusmarshalers.c \ - $(NULL) - -lib_LTLIBRARIES = libibus-gtk.la -libibus_gtk_la_SOURCES = \ - ibusmarshalers.h \ - ibusmarshalers.c \ - ibusimclient.h \ - ibusimclient.c \ - ibusattribute.h \ - ibusattribute.c \ - $(NULL) -libibus_gtk_la_CFLAGS = \ - @X11_CFLAGS@ \ - @GDK2_CFLAGS@ \ - @DBUS_CFLAGS@ \ - -DG_LOG_DOMAIN=\"IBUS\" \ - $(NULL) -libibus_gtk_la_LDFLAGS = \ - @X11_LIBS@ \ - @GDK2_LIBS@ \ - @DBUS_LIBS@ \ - $(NULL) - -# gen marshal -ibusmarshalers.h: stamp-ibusmarshalers.h - @true -stamp-ibusmarshalers.h: ibusmarshalers.list - $(GLIB_GENMARSHAL) --prefix=ibus_marshal $(srcdir)/ibusmarshalers.list --header >> xgen-gmh \ - && (cmp -s xgen-gmh ibusmarshalers.h || cp xgen-gmh ibusmarshalers.h) \ - && rm -f xgen-gmh \ - && echo timestamp > $(@F) -ibusmarshalers.c: ibusmarshalers.list - (echo "#include \"ibusmarshalers.h\""; \ - $(GLIB_GENMARSHAL) --prefix=ibus_marshal $(srcdir)/ibusmarshalers.list --body; \ - echo ) >> xgen-gmc \ - && cp xgen-gmc ibusmarshalers.c \ - && rm -f xgen-gmc - -EXTRA_DIST = \ - ibusmarshalers.list \ - $(NULL) - -CLEANFILES = $(BUILT_SOURCES) stamp-ibusmarshalers.h diff --git a/lib/gtk2/ibusattribute.c b/lib/gtk2/ibusattribute.c deleted file mode 100644 index 2237509..0000000 --- a/lib/gtk2/ibusattribute.c +++ /dev/null @@ -1,276 +0,0 @@ -/* vim:set et sts=4: */ -/* IBus - The Input Bus - * Copyright (C) 2008-2009 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 library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -#include <glib.h> -#include "ibusattribute.h" - -GType -ibus_attribute_get_type () -{ - static GType type = 0; - if (type == 0) { - type = g_boxed_type_register_static ("IBusAttribute", - (GBoxedCopyFunc)ibus_attribute_copy, - (GBoxedFreeFunc)ibus_attribute_free); - } - return type; -} - -IBusAttribute * -ibus_attribute_new (guint type, guint value, guint start_index, guint end_index) -{ - g_return_val_if_fail ( - type == IBUS_ATTR_TYPE_UNDERLINE || - type == IBUS_ATTR_TYPE_FOREGROUND || - type == IBUS_ATTR_TYPE_BACKGROUND, NULL); - - IBusAttribute *attr = g_slice_new (IBusAttribute); - - attr->type = type; - attr->value = value; - attr->start_index = start_index; - attr->end_index = end_index; - return attr; -} - -IBusAttribute * -ibus_attribute_copy (IBusAttribute * attr) -{ - g_assert (attr != NULL); - return ibus_attribute_new (attr->type, attr->value, attr->start_index, attr->end_index); -} - -void -ibus_attribute_free (IBusAttribute *attr) -{ - g_assert (attr != NULL); - g_slice_free (IBusAttribute, attr); -} - -IBusAttribute * -ibus_attr_underline_new (guint underline_type, guint start_index, guint end_index) -{ - g_return_val_if_fail ( - underline_type == IBUS_ATTR_UNDERLINE_NONE || - underline_type == IBUS_ATTR_UNDERLINE_SINGLE || - underline_type == IBUS_ATTR_UNDERLINE_DOUBLE || - underline_type == IBUS_ATTR_UNDERLINE_LOW, NULL); - - return ibus_attribute_new (IBUS_ATTR_TYPE_UNDERLINE, underline_type, start_index, end_index); -} - -IBusAttribute * -ibus_attr_foreground_new (guint color, guint start_index, guint end_index) -{ - return ibus_attribute_new (IBUS_ATTR_TYPE_FOREGROUND, color, start_index, end_index); -} - -IBusAttribute * -ibus_attr_background_new (guint color, guint start_index, guint end_index) -{ - return ibus_attribute_new (IBUS_ATTR_TYPE_BACKGROUND, color, start_index, end_index); -} - -GType -ibus_attr_list_get_type () -{ - static GType type = 0; - if (type == 0) { - type = g_boxed_type_register_static ("IBusAttrList", - (GBoxedCopyFunc)ibus_attr_list_copy, - (GBoxedFreeFunc)ibus_attr_list_unref); - } - return type; -} - -IBusAttrList * -ibus_attr_list_new () -{ - IBusAttrList *attr_list = g_slice_new(IBusAttrList); - attr_list->refcount = 1; - attr_list->attributes = g_array_new (TRUE, TRUE, sizeof (IBusAttribute *)); - return attr_list; -} - -IBusAttrList * -ibus_attr_list_copy (IBusAttrList *attr_list) -{ - IBusAttrList *new_list = ibus_attr_list_new (); - guint i; - for (i = 0;; i++) { - IBusAttribute *attr = ibus_attr_list_get (attr_list, i); - if (attr == NULL) { - break; - } - ibus_attr_list_append (new_list, ibus_attribute_copy (attr)); - } - return new_list; -} - -IBusAttrList * -ibus_attr_list_ref (IBusAttrList *attr_list) -{ - if (attr_list == NULL) { - return NULL; - } - attr_list->refcount ++; - return attr_list; -} - -void -ibus_attr_list_unref (IBusAttrList *attr_list) -{ - if (attr_list == NULL) { - return; - } - - attr_list->refcount --; - if (attr_list->refcount <= 0) { - guint i; - for (i = 0; i < attr_list->attributes->len; i++) { - IBusAttribute *attr = g_array_index (attr_list->attributes, - IBusAttribute *, i); - if (attr != NULL) { - ibus_attribute_free (attr); - } - } - g_array_free (attr_list->attributes, TRUE); - g_slice_free (IBusAttrList, attr_list); - } -} - -void -ibus_attr_list_append (IBusAttrList *attr_list, IBusAttribute *attr) -{ - g_return_if_fail (attr_list != NULL); - g_return_if_fail (attr != NULL); - g_array_append_val (attr_list->attributes, attr); -} - -IBusAttribute * -ibus_attr_list_get (IBusAttrList *attr_list, guint index) -{ - g_return_val_if_fail (attr_list != NULL, NULL); - IBusAttribute *attr = NULL; - if (index < attr_list->attributes->len) { - attr = g_array_index (attr_list->attributes, IBusAttribute *, index); - } - return attr; -} - -IBusAttribute * -ibus_attribute_from_dbus_message (DBusMessageIter *iter) -{ - gint type; - DBusMessageIter sub_iter; - - guint _type, value, start_index, end_index; - - type = dbus_message_iter_get_arg_type (iter); - g_return_val_if_fail (type == DBUS_TYPE_STRUCT, NULL); - - dbus_message_iter_recurse (iter, &sub_iter); - - g_return_val_if_fail (dbus_message_iter_get_arg_type (&sub_iter) == DBUS_TYPE_UINT32, NULL); - dbus_message_iter_get_basic (&sub_iter, &_type); - dbus_message_iter_next (&sub_iter); - - g_return_val_if_fail (dbus_message_iter_get_arg_type (&sub_iter) == DBUS_TYPE_UINT32, NULL); - dbus_message_iter_get_basic (&sub_iter, &value); - dbus_message_iter_next (&sub_iter); - - g_return_val_if_fail (dbus_message_iter_get_arg_type (&sub_iter) == DBUS_TYPE_UINT32, NULL); - dbus_message_iter_get_basic (&sub_iter, &start_index); - dbus_message_iter_next (&sub_iter); - - g_return_val_if_fail (dbus_message_iter_get_arg_type (&sub_iter) == DBUS_TYPE_UINT32, NULL); - dbus_message_iter_get_basic (&sub_iter, &end_index); - dbus_message_iter_next (&sub_iter); - - dbus_message_iter_next (iter); - - return ibus_attribute_new (_type, value, start_index, end_index); -} - -IBusAttrList * -ibus_attr_list_from_dbus_message (DBusMessageIter *iter) -{ - gint type; - DBusMessageIter sub_iter; - IBusAttrList *attr_list; - - type = dbus_message_iter_get_arg_type (iter); - g_return_val_if_fail (type == DBUS_TYPE_ARRAY, NULL); - - attr_list = ibus_attr_list_new (); - - dbus_message_iter_recurse (iter, &sub_iter); - - while (dbus_message_iter_get_arg_type (&sub_iter) != DBUS_TYPE_INVALID) { - IBusAttribute *attr = ibus_attribute_from_dbus_message (&sub_iter); - if (attr == NULL) - break; - ibus_attr_list_append (attr_list, attr); - } - - dbus_message_iter_next (iter); - return attr_list; -} - -gboolean -ibus_attribute_to_dbus_message (IBusAttribute *attr, DBusMessageIter *iter) -{ - g_assert (attr != NULL); - g_assert (iter != NULL); - - DBusMessageIter sub_iter; - - dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, 0, &sub_iter); - dbus_message_iter_append_basic (&sub_iter, DBUS_TYPE_UINT32, &attr->type); - dbus_message_iter_append_basic (&sub_iter, DBUS_TYPE_UINT32, &attr->value); - dbus_message_iter_append_basic (&sub_iter, DBUS_TYPE_UINT32, &attr->start_index); - dbus_message_iter_append_basic (&sub_iter, DBUS_TYPE_UINT32, &attr->end_index); - dbus_message_iter_close_container (iter, &sub_iter); - - return TRUE; -} - - -gboolean -ibus_attr_list_to_dbus_message (IBusAttrList *attr_list, DBusMessageIter *iter) -{ - g_assert (attr_list != NULL); - g_assert (iter != NULL); - - gint i; - DBusMessageIter sub_iter; - - dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "(uuuu)", &sub_iter); - for (i = 0;; i++) { - IBusAttribute *attr = ibus_attr_list_get (attr_list, i); - if (attr == NULL) - break; - ibus_attribute_to_dbus_message (attr, &sub_iter); - } - dbus_message_iter_close_container (iter, &sub_iter); - return TRUE; -} - - - diff --git a/lib/gtk2/ibusattribute.h b/lib/gtk2/ibusattribute.h deleted file mode 100644 index 4678522..0000000 --- a/lib/gtk2/ibusattribute.h +++ /dev/null @@ -1,100 +0,0 @@ -/* vim:set et sts=4: */ -/* IBus - The Input Bus - * Copyright (C) 2008-2009 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 library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -#ifndef __IBUS_ATTRIBUTE_H_ -#define __IBUS_ATTRIBUTE_H_ - -#include <glib-object.h> -#include <dbus/dbus.h> - -/* - * Type macros. - */ -#define IBUS_TYPE_ATTRIBUTE (ibus_attribute_get_type ()) -#define IBUS_TYPE_ATTR_LIST (ibus_attr_list_get_type ()) - -/* define GOBJECT macros */ - -#define IBUS_ATTR_TYPE_UNDERLINE 1 -#define IBUS_ATTR_TYPE_FOREGROUND 2 -#define IBUS_ATTR_TYPE_BACKGROUND 3 - -#define IBUS_ATTR_UNDERLINE_NONE 0 -#define IBUS_ATTR_UNDERLINE_SINGLE 1 -#define IBUS_ATTR_UNDERLINE_DOUBLE 2 -#define IBUS_ATTR_UNDERLINE_LOW 3 - -G_BEGIN_DECLS -typedef struct _IBusAttribute IBusAttribute; -typedef struct _IBusAttrList IBusAttrList; - -struct _IBusAttribute { - guint type; - guint value; - guint start_index; - guint end_index; -}; - -struct _IBusAttrList { - gint refcount; - GArray *attributes; -}; - -GType ibus_attribute_get_type (); -IBusAttribute *ibus_attribute_new (guint type, - guint value, - guint start_index, - guint end_index); -IBusAttribute *ibus_attribute_copy (IBusAttribute - *attr); -void ibus_attribute_free (IBusAttribute - *attr); -IBusAttribute *ibus_attr_underline_new (guint underline_type, - guint start_index, - guint end_index); -IBusAttribute *ibus_attr_foreground_new (guint color, - guint start_index, - guint end_index); -IBusAttribute *ibus_attr_background_new (guint color, - guint start_index, - guint end_index); -IBusAttribute *ibus_attribute_from_dbus_message - (DBusMessageIter *iter); -gboolean ibus_attribute_to_dbus_message - (IBusAttribute *attr, - DBusMessageIter *iter); - - -GType ibus_attr_list_get_type (); -IBusAttrList *ibus_attr_list_new (); -IBusAttrList *ibus_attr_list_copy (IBusAttrList *attr_list); -IBusAttrList *ibus_attr_list_ref (IBusAttrList *attr_list); -void ibus_attr_list_unref (IBusAttrList *attr_list); -void ibus_attr_list_append (IBusAttrList *attr_list, - IBusAttribute *attr); -IBusAttribute *ibus_attr_list_get (IBusAttrList *attr_list, - guint index); -IBusAttrList *ibus_attr_list_from_dbus_message - (DBusMessageIter *iter); -gboolean ibus_attr_list_to_dbus_message - (IBusAttrList *attr_list, - DBusMessageIter *iter); -G_END_DECLS -#endif - diff --git a/lib/gtk2/ibusimclient.c b/lib/gtk2/ibusimclient.c deleted file mode 100644 index 31de0a8..0000000 --- a/lib/gtk2/ibusimclient.c +++ /dev/null @@ -1,1536 +0,0 @@ -/* vim:set et ts=4: */ -/* ibus - The Input Bus - * Copyright (C) 2008-2009 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 library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -#include <config.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/time.h> -#include <sys/un.h> -#include <string.h> -#include <stdarg.h> -#include <stdlib.h> -#include <pwd.h> -#include <glib/gstdio.h> -#include <gdk/gdk.h> -#include <gdk/gdkx.h> -#include <gdk/gdkkeysyms.h> -#include <dbus/dbus.h> -#include <dbus/dbus-glib.h> -#include <dbus/dbus-glib-lowlevel.h> - -#ifdef HAVE_X11_XKBLIB_H -# define HAVE_XKB -# include <X11/XKBlib.h> -#endif - -#ifdef HAVE_SYS_INOTIFY_H -#define HAVE_INOTIFY -# include <sys/inotify.h> -#endif - -#include "ibusmarshalers.h" -#include "ibusattribute.h" -#include "ibusimclient.h" -#define IBUS_NAME "org.freedesktop.IBus" -#define IBUS_IFACE "org.freedesktop.IBus" -#define IBUS_PATH "/org/freedesktop/IBus" - -#define I_(string) g_intern_static_string (string) - -enum { - CONNECTED, - DISCONNECTED, - FORWARD_EVENT, - COMMIT_STRING, - UPDATE_PREEDIT, - SHOW_PREEDIT, - HIDE_PREEDIT, - ENABLED, - DISABLED, - LAST_SIGNAL, -}; - - -/* IBusIMClientPriv */ -struct _IBusIMClientPrivate { -#if USE_DBUS_SESSION_BUS - DBusConnection *dbus; -#endif - -#ifdef HAVE_INOTIFY - /* inotify */ - gint inotify_wd; - GIOChannel *inotify_channel; - guint inotify_source; -#endif - - GdkKeymap *keymap; - gulong keymap_handler_id; - - /* hack japanese [yen bar] & [backslash underbar] key */ - guint japan_groups; - GArray *japan_yen_bar_keys; - - DBusConnection *ibus; - -}; - -typedef struct _KeyPressCallData KeyPressCallData; - - -/* variables */ -static guint client_signals[LAST_SIGNAL] = { 0 }; - -/* functions prototype */ -static void ibus_im_client_class_init (IBusIMClientClass *klass); -static void ibus_im_client_init (IBusIMClient *client); -static void ibus_im_client_finalize (GObject *obj); - -static void _keymap_find_japan_groups (IBusIMClient *client); -static void _keymap_find_yen_bar_keys (IBusIMClient *client); -static void _keymap_keys_changed_cb (GdkKeymap *keymap, - IBusIMClient *client); - -static void _ibus_im_client_ibus_open (IBusIMClient *client); -static void _ibus_im_client_ibus_close (IBusIMClient *client); - -static gboolean _ibus_call_with_reply_and_block - (DBusConnection *connection, - const gchar *method, - int first_arg_type, - ...); -static gboolean _ibus_call_with_reply (DBusConnection *connection, - const gchar *method, - DBusPendingCallNotifyFunction - function, - void *data, - DBusFreeFunction free_function, - int first_arg_type, - ...); -static gboolean _dbus_call_with_reply_and_block - (DBusConnection *connection, - const gchar *dest, - const gchar *path, - const gchar *iface, - const char *method, - int first_arg_type, - ...); - -/* callback functions */ -static DBusHandlerResult - _ibus_im_client_message_filter_cb - (DBusConnection *connection, - DBusMessage *message, - void *user_data); -static void _ibus_filter_keypress_reply_cb - (DBusPendingCall *pending, - void *user_data); -static KeyPressCallData * - _key_press_call_data_new (IBusIMClient *client, - const gchar *ic, - GdkEvent *event); -static void _key_press_call_data_free (KeyPressCallData *call_data); - - -static GType _ibus_type_im_client = 0; -static GObjectClass *_parent_class = NULL; - - -GType -ibus_im_client_get_type (void) -{ - if (_ibus_type_im_client == 0) { - ibus_im_client_register_type (NULL); - } - - g_assert (_ibus_type_im_client != 0); - return _ibus_type_im_client; -} - -void -ibus_im_client_register_type (GTypeModule *type_module) -{ - static const GTypeInfo ibus_im_client_info = { - sizeof (IBusIMClientClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) ibus_im_client_class_init, - NULL, /* class finialize */ - NULL, /* class data */ - sizeof (IBusIMClient), - 0, - (GInstanceInitFunc) ibus_im_client_init, - }; - - if (_ibus_type_im_client == 0) { - if (type_module) { - _ibus_type_im_client = - g_type_module_register_type (type_module, - G_TYPE_OBJECT, - "IBusIMClient", - &ibus_im_client_info, - (GTypeFlags)0); - } - else { - _ibus_type_im_client = - g_type_register_static (G_TYPE_OBJECT, - "IBusIMClient", - &ibus_im_client_info, - (GTypeFlags)0); - } - } -} - -IBusIMClient * -ibus_im_client_new (void) -{ - IBusIMClient *client; - - client = IBUS_IM_CLIENT (g_object_new (IBUS_TYPE_IM_CLIENT, NULL)); - - return client; -} - -static void -ibus_im_client_class_init (IBusIMClientClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - _parent_class = (GObjectClass *) g_type_class_peek_parent (klass); - - g_type_class_add_private (klass, sizeof (IBusIMClientPrivate)); - - gobject_class->finalize = ibus_im_client_finalize; - - client_signals[CONNECTED] = - g_signal_new (I_("connected"), - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (IBusIMClientClass, connected), - NULL, NULL, - ibus_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - client_signals[DISCONNECTED] = - g_signal_new (I_("disconnected"), - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (IBusIMClientClass, disconnected), - NULL, NULL, - ibus_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - client_signals[FORWARD_EVENT] = - g_signal_new (I_("forward-event"), - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (IBusIMClientClass, commit_string), - NULL, NULL, - ibus_marshal_VOID__STRING_BOXED, - G_TYPE_NONE, 2, - G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE, - GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); - - - client_signals[COMMIT_STRING] = - g_signal_new (I_("commit-string"), - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (IBusIMClientClass, commit_string), - NULL, NULL, - ibus_marshal_VOID__STRING_STRING, - G_TYPE_NONE, 2, - G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE, - G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE); - - client_signals[UPDATE_PREEDIT] = - g_signal_new (I_("update-preedit"), - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (IBusIMClientClass, update_preedit), - NULL, NULL, - ibus_marshal_VOID__STRING_STRING_BOXED_INT_BOOLEAN, - G_TYPE_NONE, 5, - G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE, - G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE, - IBUS_TYPE_ATTR_LIST | G_SIGNAL_TYPE_STATIC_SCOPE, - G_TYPE_INT | G_SIGNAL_TYPE_STATIC_SCOPE, - G_TYPE_BOOLEAN | G_SIGNAL_TYPE_STATIC_SCOPE - ); - - client_signals[SHOW_PREEDIT] = - g_signal_new (I_("show-preedit"), - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (IBusIMClientClass, show_preedit), - NULL, NULL, - ibus_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE); - - client_signals[HIDE_PREEDIT] = - g_signal_new (I_("hide-preedit"), - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (IBusIMClientClass, hide_preedit), - NULL, NULL, - ibus_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE); - - client_signals[ENABLED] = - g_signal_new (I_("enabled"), - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (IBusIMClientClass, enabled), - NULL, NULL, - ibus_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE); - - client_signals[DISABLED] = - g_signal_new (I_("disabled"), - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (IBusIMClientClass, disabled), - NULL, NULL, - ibus_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE); - -} - -/* - * open ibus connection - */ -static void -_ibus_im_client_ibus_open (IBusIMClient *client) -{ - gchar *ibus_addr = NULL; - DBusError error; - - IBusIMClientPrivate *priv = client->priv; - - if (priv->ibus != NULL) - return; - -#if USE_DBUS_SESSION_BUS - dbus_connection_setup_with_g_main (priv->dbus, NULL); - if (!_dbus_call_with_reply_and_block (priv->dbus, - IBUS_NAME, IBUS_PATH, IBUS_IFACE, - "GetIBusAddress", - DBUS_TYPE_INVALID, - DBUS_TYPE_STRING, &ibus_addr, - DBUS_TYPE_INVALID - )) { - g_warning ("Can not get ibus address"); - return; - } -#endif - if (ibus_addr == NULL) { - gchar *display; - gchar *hostname = ""; - gchar *displaynumber = "0"; - gchar *screennumber = "0"; - gchar *username = NULL; - gchar *p; - - display = g_strdup (g_getenv ("DISPLAY")); - if (display == NULL) { - g_warning ("DISPLAY is empty! We use default DISPLAY (:0.0)"); - } - else { - p = display; - hostname = display; - for (; *p != ':' && *p != '\0'; p++); - - if (*p == ':') { - *p = '\0'; - p++; - displaynumber = p; - } - - for (; *p != '.' && *p != '\0'; p++); - - if (*p == '.') { - *p = '\0'; - p++; - screennumber = p; - } - } - - username = g_strdup (getlogin()); - if (username == NULL) - username = g_strdup (g_getenv("SUDO_USER")); - if (username == NULL) { - const gchar *uid = g_getenv ("USERHELPER_UID"); - if (uid != NULL) { - gchar *end; - uid_t id = (uid_t)strtol(uid, &end, 10); - if (uid != end) { - struct passwd *pw = getpwuid (id); - if (pw != NULL) { - username = g_strdup (pw->pw_name); - } - } - } - } - if (username == NULL) - username = g_strdup (g_getenv("USERNAME")); - if (username == NULL) - username = g_strdup (g_getenv("LOGNAME")); - if (username == NULL) - username = g_strdup (g_getenv("USER")); - if (username == NULL) - username = g_strdup (g_getenv("LNAME")); - - ibus_addr = g_strdup_printf ( - "unix:path=/tmp/ibus-%s/ibus-%s-%s.%s", - username, hostname, displaynumber, screennumber); - - g_free (display); - g_free (username); - } - - /* - * Init ibus and proxy object - */ - dbus_error_init (&error); - priv->ibus = dbus_connection_open_private (ibus_addr, &error); - g_free (ibus_addr); - if (priv->ibus == NULL) { - g_warning ("Error: %s", error.message); - dbus_error_free (&error); - return; - } - - if (!dbus_connection_add_filter (priv->ibus, - _ibus_im_client_message_filter_cb, - client, NULL)) { - g_warning ("Out of memory"); - return; - } - - dbus_connection_setup_with_g_main (priv->ibus, NULL); - - g_signal_emit (client, client_signals[CONNECTED], 0); - -} - -/* - * close ibus connection - */ -static void -_ibus_im_client_ibus_close (IBusIMClient *client) -{ - IBusIMClientPrivate *priv = client->priv; - - if (priv->ibus) { - dbus_connection_close (priv->ibus); - dbus_connection_unref (priv->ibus); - priv->ibus = NULL; - g_signal_emit (client, client_signals[DISCONNECTED], 0); - } -} - - - -#ifdef HAVE_INOTIFY -static gboolean -_ibus_im_client_inotify_cb (GIOChannel *source, GIOCondition condition, IBusIMClient *client) -{ - struct inotify_event *p = NULL; - gchar *name; - gsize n; - - if ((condition & G_IO_IN) == 0) - return TRUE; - - p = g_malloc0 (sizeof (struct inotify_event) + 1024); - - g_io_channel_read_chars (source, (gchar *) p, sizeof (struct inotify_event), &n, NULL); - g_io_channel_read_chars (source, ((gchar *)p) + sizeof (struct inotify_event), p->len, &n, NULL); - - name = g_strdup_printf ("ibus-%s", g_getenv ("DISPLAY")); - for (n = 0; name[n] != 0; n++) { - if (name[n] != ':') - continue; - name[n] = '-'; - break; - } - - if (g_strcmp0 (p->name, name) == 0) { - if (p->mask & IN_CREATE) { - g_usleep (1000); - _ibus_im_client_ibus_open (client); - } - } - g_free (name); - g_free (p); - - return TRUE; -} -#endif - - -static void -ibus_im_client_init (IBusIMClient *obj) -{ - DEBUG_FUNCTION_IN; - - IBusIMClient *client = IBUS_IM_CLIENT (obj); - IBusIMClientPrivate *priv; - - gchar *watch_path; - struct stat stat_buf; - -#ifdef HAVE_INOTIFY - gint inotify_fd = inotify_init (); -#endif - - priv = G_TYPE_INSTANCE_GET_PRIVATE (client, IBUS_TYPE_IM_CLIENT, IBusIMClientPrivate); - client->priv = priv; - - watch_path = g_strdup_printf ("/tmp/ibus-%s", g_get_user_name ()); - - if (g_stat (watch_path, &stat_buf) != 0) { - g_mkdir (watch_path, 0750); - } - -#ifdef HAVE_INOTIFY - /* init inotify */ - priv->inotify_wd = inotify_add_watch (inotify_fd, watch_path, IN_CREATE | IN_DELETE); - priv->inotify_channel = g_io_channel_unix_new (inotify_fd); - g_io_channel_set_close_on_unref (priv->inotify_channel, TRUE); - priv->inotify_source = g_io_add_watch (priv->inotify_channel, - G_IO_IN, - (GIOFunc)_ibus_im_client_inotify_cb, - (gpointer)client); -#endif - g_free (watch_path); - -#if USE_DBUS_SESSION_BUS - /* - * Init dbus - */ - dbus_error_init (&error); - priv->dbus = dbus_bus_get (DBUS_BUS_SESSION, &error); - if (priv->dbus == NULL) { - g_warning ("Error: %s", error.message); - dbus_error_free (&error); - return; - } -#endif - - _ibus_im_client_ibus_open (client); - -#if USE_DBUS_SESSION_BUS - if (!dbus_connection_add_filter (priv->dbus, - _ibus_im_client_message_filter_cb, - client, NULL)) { - g_warning ("Out of memory"); - return; - } - - gchar *rule = - "type='signal'," - "sender='" DBUS_SERVICE_DBUS "'," - "interface='" DBUS_INTERFACE_DBUS "'," - "member='NameOwnerChanged'," - "path='" DBUS_PATH_DBUS "'," - "arg0='" IBUS_NAME "'"; - - if (!_dbus_call_with_reply_and_block (priv->dbus, - DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, - "AddMatch", - DBUS_TYPE_STRING, &rule, - DBUS_TYPE_INVALID, - DBUS_TYPE_INVALID - )) { - g_warning ("Can not get ibus address"); - return; - } -#endif - - if ((priv->keymap = gdk_keymap_get_default ()) != NULL) { - g_object_ref (priv->keymap); - _keymap_find_japan_groups (client); - _keymap_find_yen_bar_keys (client); - // g_debug ("japan_groups = 0x%x", priv->japan_groups); - - priv->keymap_handler_id = - g_signal_connect (priv->keymap, "keys-changed", - G_CALLBACK (_keymap_keys_changed_cb), client); - } - -#if USE_DBUS_SESSION_BUS - /* get dbus proxy */ - priv->dbus = dbus_g_proxy_new_for_name (priv->ibus, - DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - DBUS_INTERFACE_DBUS); - g_assert (priv->dbus != NULL); - - /* connect NameOwnerChanged signal */ - dbus_g_proxy_add_signal (priv->dbus, "NameOwnerChanged", - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_INVALID); - - dbus_g_proxy_connect_signal (priv->dbus, "NameOwnerChanged", - G_CALLBACK (_dbus_name_owner_changed_cb), - (gpointer)client, NULL); - dbus_bus_add_match ((DBusConnection *)dbus_g_connection_get_connection (priv->ibus), - "type='signal'," - "sender='" DBUS_SERVICE_DBUS - "',interface='" DBUS_INTERFACE_DBUS - "',path='" DBUS_PATH_DBUS - "',member='NameOwnerChanged'," - "arg0='" IBUS_DBUS_SERVICE "'", - &dbus_error); - - _ibus_im_client_reinit_imm (client); -#endif - -} - - -static void -ibus_im_client_finalize (GObject *obj) -{ - DEBUG_FUNCTION_IN; - - IBusIMClient *client = IBUS_IM_CLIENT (obj); - IBusIMClientPrivate *priv = client->priv; - - if (priv->keymap) { - g_signal_handler_disconnect (priv->keymap, priv->keymap_handler_id); - g_object_unref (priv->keymap); - } - -#ifdef HAVE_INOTIFY - g_source_remove (priv->inotify_source); - g_io_channel_unref (priv->inotify_channel); -#endif - -#if USE_DBUS_SESSION_BUS - if (priv->dbus) { - dbus_connection_unref (priv->dbus); - } -#endif - _ibus_im_client_ibus_close (client); - - G_OBJECT_CLASS(_parent_class)->finalize (obj); - -} - -/* - * create an input context - */ -const gchar * -ibus_im_client_create_input_context (IBusIMClient *client) -{ - g_return_val_if_fail (IBUS_IS_IM_CLIENT (client), NULL); - - IBusIMClientPrivate *priv = client->priv; - - if (priv->ibus == NULL) - return NULL; - - const gchar *app_name = g_get_application_name (); - gchar *ic = NULL; - _ibus_call_with_reply_and_block (priv->ibus, "CreateInputContext", - DBUS_TYPE_STRING, &app_name, - DBUS_TYPE_INVALID, - DBUS_TYPE_STRING, &ic, - DBUS_TYPE_INVALID); - return ic; -} - -/* - * release an input context - */ -void -ibus_im_client_release_input_context (IBusIMClient *client, const gchar *ic) -{ - g_return_if_fail (IBUS_IS_IM_CLIENT (client)); - g_return_if_fail (ic != NULL); - - IBusIMClientPrivate *priv = client->priv; - - _ibus_call_with_reply_and_block (priv->ibus, "ReleaseInputContext", - DBUS_TYPE_STRING, &ic, - DBUS_TYPE_INVALID, - DBUS_TYPE_INVALID); - -} - - -gboolean -ibus_im_client_filter_keypress (IBusIMClient *client, const gchar *ic, GdkEventKey *event, gboolean block) -{ - g_return_val_if_fail (IBUS_IS_IM_CLIENT(client), FALSE); - g_return_val_if_fail (ic != NULL, FALSE); - g_return_val_if_fail (event != NULL, FALSE); - - IBusIMClientPrivate *priv = client->priv; - - guint state = event->state; - gboolean is_press = event->type == GDK_KEY_PRESS; - - if ((event->state & IBUS_FORWARD_MASK) != 0) { - return FALSE; - } - - /* add forward mask, and will not process this event again */ - event->state |= IBUS_FORWARD_MASK; - - /* hack for [yen bar] and [backslash underscore] keys in Japan keyboard */ - guint keyval = event->keyval; - if (event->keyval == GDK_backslash && - priv->japan_yen_bar_keys != NULL && - (1L << event->group) & priv->japan_groups) - { - int i; - for (i = 0; i < priv->japan_yen_bar_keys->len; i++) { - GdkKeymapKey *key = &g_array_index (priv->japan_yen_bar_keys, GdkKeymapKey, i); - if (event->hardware_keycode == key->keycode && event->group == key->group) { - keyval = GDK_yen; - break; - } - } - } - - /* Call IBus ProcessKeyEvent method */ - if (!block) { - if (!_ibus_call_with_reply (priv->ibus, - "ProcessKeyEvent", - _ibus_filter_keypress_reply_cb, - _key_press_call_data_new (client, ic, (GdkEvent *)event), - (DBusFreeFunction)_key_press_call_data_free, - DBUS_TYPE_STRING, &ic, - DBUS_TYPE_UINT32, &keyval, - DBUS_TYPE_BOOLEAN, &is_press, - DBUS_TYPE_UINT32, &state, - DBUS_TYPE_INVALID)) - return FALSE; - else - return TRUE; - } - else { - gboolean result = FALSE; - if (!_ibus_call_with_reply_and_block (priv->ibus, - "ProcessKeyEvent", - DBUS_TYPE_STRING, &ic, - DBUS_TYPE_UINT32, &keyval, - DBUS_TYPE_BOOLEAN, &is_press, - DBUS_TYPE_UINT32, &state, - DBUS_TYPE_INVALID, - DBUS_TYPE_BOOLEAN, &result, - DBUS_TYPE_INVALID)) - return FALSE; - - return result; - } -} - - -void -ibus_im_client_focus_in (IBusIMClient *client, const gchar *ic) -{ - g_return_if_fail (IBUS_IS_IM_CLIENT (client)); - g_return_if_fail (ic != NULL); - - IBusIMClientPrivate *priv = client->priv; - - /* Call IBus FocusIn method */ - _ibus_call_with_reply_and_block (priv->ibus, - "FocusIn", - DBUS_TYPE_STRING, &ic, - DBUS_TYPE_INVALID, - DBUS_TYPE_INVALID); -} - -void -ibus_im_client_focus_out (IBusIMClient *client, const gchar *ic) -{ - g_return_if_fail (IBUS_IS_IM_CLIENT (client)); - g_return_if_fail (ic != NULL); - - IBusIMClientPrivate *priv = client->priv; - - /* Call IBus FocusOut method */ - _ibus_call_with_reply_and_block (priv->ibus, - "FocusOut", - DBUS_TYPE_STRING, &ic, - DBUS_TYPE_INVALID, - DBUS_TYPE_INVALID); - -} - -void -ibus_im_client_reset (IBusIMClient *client, const gchar *ic) -{ - g_return_if_fail (IBUS_IS_IM_CLIENT (client)); - g_return_if_fail (ic != NULL); - - IBusIMClientPrivate *priv = client->priv; - - /* Call IBus Reset method */ - _ibus_call_with_reply_and_block (priv->ibus, - "Reset", - DBUS_TYPE_STRING, &ic, - DBUS_TYPE_INVALID, - DBUS_TYPE_INVALID); - -} - -void -ibus_im_client_set_cursor_location (IBusIMClient *client, const gchar *ic, GdkRectangle *area) -{ - g_return_if_fail (IBUS_IS_IM_CLIENT (client)); - g_return_if_fail (ic != NULL); - g_return_if_fail (area != NULL); - - _ibus_call_with_reply_and_block (client->priv->ibus, - "SetCursorLocation", - DBUS_TYPE_STRING, &ic, - DBUS_TYPE_INT32, &area->x, - DBUS_TYPE_INT32, &area->y, - DBUS_TYPE_INT32, &area->width, - DBUS_TYPE_INT32, &area->height, - DBUS_TYPE_INVALID, - DBUS_TYPE_INVALID); -} - -void -ibus_im_client_set_capabilities (IBusIMClient *client, const gchar *ic, gint caps) -{ - g_return_if_fail (IBUS_IS_IM_CLIENT (client)); - g_return_if_fail (ic != NULL); - - _ibus_call_with_reply_and_block (client->priv->ibus, - "SetCapabilities", - DBUS_TYPE_STRING, &ic, - DBUS_TYPE_INT32, &caps, - DBUS_TYPE_INVALID, - DBUS_TYPE_INVALID); -} - -void -ibus_im_client_kill_daemon (IBusIMClient *client) -{ - g_return_if_fail (IBUS_IS_IM_CLIENT (client)); - - IBusIMClientPrivate *priv = client->priv; - _ibus_call_with_reply_and_block (priv->ibus, "Kill", - DBUS_TYPE_INVALID, - DBUS_TYPE_INVALID); -} - - -gboolean -ibus_im_client_get_connected (IBusIMClient *client) -{ - g_return_val_if_fail (IBUS_IS_IM_CLIENT (client), FALSE); - - IBusIMClientPrivate *priv = client->priv; - if (priv->ibus == NULL) - return FALSE; - return dbus_connection_get_is_connected (priv->ibus); -} - -static void -_keymap_find_japan_groups (IBusIMClient *client) -{ - -#ifdef HAVE_XKB - /* If have XKB, we will find Japan groups by groups' names */ - gboolean retval = FALSE; - Status status; - XkbDescPtr desc; - - IBusIMClientPrivate *priv = client->priv; - - priv->japan_groups = 0; - - desc = XkbGetMap (GDK_DISPLAY (), 0, XkbUseCoreKbd); - if (desc == NULL) { - g_warning ("Can not allocate XkbDescRec!"); - return; - } - - retval = - Success == (status = XkbGetControls (GDK_DISPLAY (), - XkbSlowKeysMask, - desc)) && - Success == (status = XkbGetNames (GDK_DISPLAY (), - XkbGroupNamesMask | XkbIndicatorNamesMask, - desc)) && - Success == (status = XkbGetIndicatorMap (GDK_DISPLAY (), - XkbAllIndicatorsMask, - desc)); - if (retval) { - Atom *pa = desc->names->groups; - int i; - for (i = 0; i < desc->ctrls->num_groups; pa++, i++) { - gchar *group_name = NULL; - if (*pa == None) - continue; - group_name = XGetAtomName (GDK_DISPLAY (), *pa); - if (g_strcmp0(group_name, "Japan") == 0) { - priv->japan_groups |= (1 << i); - } - } - } - else { - g_warning ("Can not get groups' names from Xkb"); - } - - XkbFreeKeyboard(desc, XkbAllComponentsMask, True); -#else - /* if not have XKB, we assume only Japan group has key [backslash, underscore] - * and [backslash bar]. - * */ - gint backslash_num, bar_num, underscore_num; - GdkKeymapKey *backslash_keys, *bar_keys, *underscore_keys; - gboolean retval; - - IBusIMClientPrivate *priv = client->priv; - - priv->japan_groups = 0; - - retval = gdk_keymap_get_entries_for_keyval (priv->keymap, GDK_backslash, &backslash_keys, &backslash_num); - if (!retval) { - g_warning ("Can not get keycode for backslash key!"); - return; - } - - retval = gdk_keymap_get_entries_for_keyval (priv->keymap, GDK_bar, &bar_keys, &bar_num); - if (!retval) { - g_warning ("Can not get keycode for bar key!"); - g_free (backslash_keys); - return; - } - - retval = gdk_keymap_get_entries_for_keyval (priv->keymap, GDK_underscore, &underscore_keys, &underscore_num); - if (!retval) { - g_warning ("Can not get keycode for underscore key!"); - g_free (backslash_keys); - g_free (bar_keys); - return; - } - - int i, j; - guint groups_have_backslash_and_bar = 0; - guint groups_have_backslash_and_underscore = 0; - - for (i = 0; i < backslash_num; i++) { - for (j = 0; j < bar_num; j++) { - if (backslash_keys[i].keycode != bar_keys[j].keycode || - backslash_keys[i].group != bar_keys[j].group) - continue; - groups_have_backslash_and_bar |= (1L << backslash_keys[i].group); - } - } - - for (i = 0; i < backslash_num; i++) { - for (j = 0; j < underscore_num; j++) { - if (backslash_keys[i].keycode != underscore_keys[j].keycode || - backslash_keys[i].group != underscore_keys[j].group) - continue; - groups_have_backslash_and_underscore |= (1 << backslash_keys[i].group); - } - } - priv->japan_groups = groups_have_backslash_and_bar & groups_have_backslash_and_underscore; - - g_free (backslash_keys); - g_free (bar_keys); - g_free (underscore_keys); -#endif -} - - -static void -_keymap_find_yen_bar_keys (IBusIMClient *client) -{ - IBusIMClientPrivate *priv = client->priv; - gint backslash_num, bar_num; - GdkKeymapKey *backslash_keys, *bar_keys; - gboolean retval; - - if (priv->japan_yen_bar_keys == NULL) { - priv->japan_yen_bar_keys = g_array_new (TRUE, TRUE, sizeof(GdkKeymapKey)); - } - else if (priv->japan_yen_bar_keys->len > 0) { - g_array_remove_range (priv->japan_yen_bar_keys, 0, priv->japan_yen_bar_keys->len); - } - - if (priv->japan_groups == 0) - return; - - retval = gdk_keymap_get_entries_for_keyval (priv->keymap, GDK_backslash, &backslash_keys, &backslash_num); - if (!retval) { - g_warning ("Can not get keycode for backslash key!"); - return; - } - - retval = gdk_keymap_get_entries_for_keyval (priv->keymap, GDK_bar, &bar_keys, &bar_num); - if (!retval) { - g_warning ("Can not get keycode for bar key!"); - g_free (backslash_keys); - return; - } - - int i, j; - for (i = 0; i < backslash_num; i++) { - for (j = 0; j < bar_num; j++) { - if (backslash_keys[i].keycode != bar_keys[j].keycode || - backslash_keys[i].group != bar_keys[j].group) - continue; - - if (0 == (priv->japan_groups & (1 << backslash_keys[i].group))) - continue; - g_array_append_val (priv->japan_yen_bar_keys, backslash_keys[i]); - } - } - - g_free (backslash_keys); - g_free (bar_keys); -} - -static void -_keymap_keys_changed_cb (GdkKeymap *keymap, IBusIMClient *client) -{ - _keymap_find_japan_groups (client); - _keymap_find_yen_bar_keys (client); - /* - g_debug ("keymap changed japan_groups = 0x%x", - client->priv->japan_groups); - */ -} - -static void -_ibus_signal_commit_string_handler (DBusConnection *connection, DBusMessage *message, IBusIMClient *client) -{ - /* Handle CommitString signal */ - DBusError error = {0}; - gchar *ic = NULL; - gchar *string = NULL; - - if (!dbus_message_get_args (message, &error, - DBUS_TYPE_STRING, &ic, - DBUS_TYPE_STRING, &string, - DBUS_TYPE_INVALID)) { - g_warning ("%s", error.message); - dbus_error_free (&error); - } - else { - g_signal_emit (client, client_signals[COMMIT_STRING], 0, ic, string); - } -} - -static void -_ibus_signal_update_preedit_handler (DBusConnection *connection, DBusMessage *message, IBusIMClient *client) -{ - /* Handle UpdatePreedit signal */ - DBusMessageIter iter, sub_iter; - int type, sub_type; - - gchar *ic = NULL; - gchar *string = NULL; - IBusAttrList *attrs = NULL; - int cursor = 0; - gboolean visible = FALSE; - - if (!dbus_message_iter_init (message, &iter)) { - g_warning ("The UpdatePreedit signal does have args!"); - return; - } - - type = dbus_message_iter_get_arg_type (&iter); - if (type != DBUS_TYPE_STRING) { - g_warning ("The 1st argument of UpdatePreedit signal must be a String"); - return; - } - dbus_message_iter_get_basic (&iter, &ic); - dbus_message_iter_next (&iter); - - type = dbus_message_iter_get_arg_type (&iter); - if (type != DBUS_TYPE_STRING) { - g_warning ("The 2nd argument of UpdatePreedit signal must be a String"); - return; - } - dbus_message_iter_get_basic (&iter, &string); - dbus_message_iter_next (&iter); - - - type = dbus_message_iter_get_arg_type (&iter); - if (type != DBUS_TYPE_ARRAY) { - g_warning ("The 3rd argument of UpdatePreedit signal must be a Struct Array"); - return; - } - - attrs = ibus_attr_list_from_dbus_message (&iter); - - type = dbus_message_iter_get_arg_type (&iter); - if (type != DBUS_TYPE_INT32) { - g_warning ("The 4th argument of UpdatePreedit signal must be an Int32 %c", type); - ibus_attr_list_unref (attrs); - return; - } - dbus_message_iter_get_basic (&iter, &cursor); - dbus_message_iter_next (&iter); - - type = dbus_message_iter_get_arg_type (&iter); - if (type != DBUS_TYPE_BOOLEAN) { - g_warning ("The 4th argument of UpdatePreedit signal must be an Int32 %c", type); - ibus_attr_list_unref (attrs); - return; - } - dbus_message_iter_get_basic (&iter, &visible); - dbus_message_iter_next (&iter); - g_signal_emit (client, client_signals[UPDATE_PREEDIT], 0, - ic, string, attrs, cursor, visible); - ibus_attr_list_unref (attrs); -} - -static void -_ibus_signal_show_preedit_handler (DBusConnection *connection, DBusMessage *message, IBusIMClient *client) -{ - /* Handle CommitString signal */ - DBusError error = {0}; - gchar *ic = NULL; - - if (!dbus_message_get_args (message, &error, - DBUS_TYPE_STRING, &ic, - DBUS_TYPE_INVALID)) { - g_warning ("%s", error.message); - dbus_error_free (&error); - } - else { - g_signal_emit (client, client_signals[SHOW_PREEDIT], 0, ic); - } -} - -static void -_ibus_signal_hide_preedit_handler (DBusConnection *connection, DBusMessage *message, IBusIMClient *client) -{ - /* Handle CommitString signal */ - DBusError error = {0}; - gchar *ic = NULL; - - if (!dbus_message_get_args (message, &error, - DBUS_TYPE_STRING, &ic, - DBUS_TYPE_INVALID)) { - g_warning ("%s", error.message); - dbus_error_free (&error); - } - else { - g_signal_emit (client, client_signals[HIDE_PREEDIT], 0, ic); - } -} - -#ifdef USE_DBUS_SESSION_BUS -static void -_ibus_signal_name_owner_changed_handler (DBusConnection *connection, DBusMessage *message, IBusIMClient *client) -{ - gchar *name = NULL; - gchar *old_name = NULL; - gchar *new_name = NULL; - DBusError error = {0}; - - if (!dbus_message_get_args (message, &error, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_STRING, &old_name, - DBUS_TYPE_STRING, &new_name, - DBUS_TYPE_INVALID)) { - g_warning ("%s", error.message); - dbus_error_free (&error); - } - - g_return_if_fail (strcmp (name, IBUS_NAME) == 0); - - if (g_strcmp0 (new_name, "") == 0) { - _ibus_im_client_ibus_close (client); - priv->enable = FALSE; - } - else { - _ibus_im_client_ibus_open (client); - priv->enable = TRUE; - } -} -#endif - -static void -_ibus_signal_disconnected_handler (DBusConnection *connection, DBusMessage *message, IBusIMClient *client) -{ - _ibus_im_client_ibus_close (client); -} - -static void -_ibus_signal_enabled_handler (DBusConnection *connection, DBusMessage *message, IBusIMClient *client) -{ - DEBUG_FUNCTION_IN; - /* Handle CommitString signal */ - DBusError error = {0}; - gchar *ic = NULL; - - if (!dbus_message_get_args (message, &error, - DBUS_TYPE_STRING, &ic, - DBUS_TYPE_INVALID)) { - g_warning ("%s", error.message); - dbus_error_free (&error); - } - else { - g_signal_emit (client, client_signals[ENABLED], 0, ic); - } -} - - -static void -_ibus_signal_disabled_handler (DBusConnection *connection, DBusMessage *message, IBusIMClient *client) -{ - DEBUG_FUNCTION_IN; - /* Handle CommitString signal */ - DBusError error = {0}; - gchar *ic = NULL; - - if (!dbus_message_get_args (message, &error, - DBUS_TYPE_STRING, &ic, - DBUS_TYPE_INVALID)) { - g_warning ("%s", error.message); - dbus_error_free (&error); - } - else { - g_signal_emit (client, client_signals[DISABLED], 0, ic); - } -} - - -static DBusHandlerResult -_ibus_im_client_message_filter_cb (DBusConnection *connection, DBusMessage *message, void *user_data) -{ - IBusIMClient *client = (IBusIMClient *) user_data; - - static struct SIGNAL_HANDLER { - const gchar *iface; - const gchar *name; - void (* handler) (DBusConnection *, DBusMessage *, IBusIMClient *); - } handlers[] = { -#ifdef USE_DBUS_SESSION_BUS - { DBUS_INTERFACE_DBUS, "NameOwnerChanged", _ibus_signal_name_owner_changed_handler }, -#endif - { DBUS_INTERFACE_LOCAL, "Disconnected", _ibus_signal_disconnected_handler }, - { IBUS_IFACE, "CommitString", _ibus_signal_commit_string_handler }, - { IBUS_IFACE, "UpdatePreedit", _ibus_signal_update_preedit_handler }, - { IBUS_IFACE, "ShowPreedit", _ibus_signal_show_preedit_handler }, - { IBUS_IFACE, "HidePreedit", _ibus_signal_hide_preedit_handler }, - { IBUS_IFACE, "Enabled", _ibus_signal_enabled_handler }, - { IBUS_IFACE, "Disabled", _ibus_signal_disabled_handler }, - {0}, - }; - - gint i; - for (i = 0; handlers[i].iface != NULL; i++) { - if (dbus_message_is_signal (message, handlers[i].iface, handlers[i].name)) { - handlers[i].handler (connection, message, client); - return DBUS_HANDLER_RESULT_HANDLED; - } - } - g_debug ("Unknown message %s", dbus_message_get_member (message)); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -inline static gboolean -_dbus_call_with_reply_and_block_valist (DBusConnection *connection, - const gchar *dest, const gchar *path, const gchar* iface, const char *method, - int first_arg_type, va_list args) -{ - - DBusMessage *message, *reply; - DBusError error = {0}; - int type; - va_list tmp; - - if (connection == NULL) - return FALSE; - - message = dbus_message_new_method_call (dest, - path, iface, method); - if (!message) { - g_warning ("Out of memory!"); - return FALSE; - } - - va_copy (tmp, args); - if (!dbus_message_append_args_valist (message, first_arg_type, tmp)) { - dbus_message_unref (message); - g_warning ("Can not create call message"); - return FALSE; - } - - reply = dbus_connection_send_with_reply_and_block (connection, - message, -1, &error); - - dbus_message_unref (message); - - if (!reply) { - g_warning ("%s", error.message); - dbus_error_free (&error); - return FALSE; - } - - type = first_arg_type; - while (type != DBUS_TYPE_INVALID) { - if (type == DBUS_TYPE_ARRAY) { - va_arg (args, int); - va_arg (args, void *); - va_arg (args, int); - } - else { - va_arg (args, void *); - } - type = va_arg (args, int); - } - - type = va_arg (args, int); - if (!dbus_message_get_args_valist (reply, &error, type, args)) { - g_warning ("%s", error.message); - dbus_error_free (&error); - dbus_message_unref (reply); - return FALSE; - } - dbus_message_unref (reply); - - return TRUE; - -} - -inline static gboolean -_dbus_call_with_reply_and_block (DBusConnection *connection, - const gchar *dest, const gchar *path, const gchar* iface, const char *method, - gint first_arg_type, ...) -{ - va_list args; - gboolean retval; - - if (connection == NULL) - return FALSE; - - va_start (args, first_arg_type); - retval = _dbus_call_with_reply_and_block_valist (connection, - dest, path, iface, method, first_arg_type, args); - va_end (args); - - return TRUE; - -} - -static gboolean -_ibus_call_with_reply_and_block (DBusConnection *connection, const gchar *method, int first_arg_type, ...) -{ - va_list args; - gboolean retval; - - if (connection == NULL) - return FALSE; - - va_start (args, first_arg_type); - retval = _dbus_call_with_reply_and_block_valist (connection, - IBUS_NAME, IBUS_PATH, IBUS_IFACE, method, first_arg_type, args); - va_end (args); - - return retval; - -} - - -inline static gboolean -_dbus_call_with_reply_valist (DBusConnection *connection, - const gchar *dest, const gchar *path, const gchar* iface, const char *method, - DBusPendingCallNotifyFunction notify_function, - void *user_data, DBusFreeFunction free_function, - gint first_arg_type, va_list args) -{ - DBusMessage *message = NULL; - DBusPendingCall *pendingcall = NULL; - - if (connection == NULL) { - goto error; - } - - message = dbus_message_new_method_call (dest, - path, iface, method); - if (!message) { - g_warning ("Out of memory!"); - goto error; - } - - if (!dbus_message_append_args_valist (message, first_arg_type, args)) { - g_warning ("Can not create call message!"); - goto error; - } - - if (!dbus_connection_send_with_reply (connection, - message, &pendingcall, -1)) { - g_warning ("Out of memory!"); - goto error; - } - - /* If we got a NULL pending, that means the connection was disconnected, - * and we need to abort this call - * https://bugs.freedesktop.org/show_bug.cgi?id=12675 - */ - if (pendingcall == 0) { - g_warning ("Connection is breaken!"); - goto error; - } - - if (!dbus_pending_call_set_notify (pendingcall, notify_function, - user_data, free_function)) { - g_warning ("Out of memory!"); - goto error; - } - - dbus_message_unref (message); - return TRUE; - -error: - if (message) - dbus_message_unref (message); - if (pendingcall) - dbus_pending_call_cancel (pendingcall); - if (user_data && free_function) - free_function (user_data); - return FALSE; -} - -inline static gboolean -_dbus_call_with_reply (DBusConnection *connection, - const gchar *dest, const gchar *path, const gchar* iface, const char *method, - DBusPendingCallNotifyFunction notify_function, - void *user_data, DBusFreeFunction free_function, - gint first_arg_type, ...) -{ - va_list args; - gboolean retval; - - if (connection == NULL) - return FALSE; - - va_start (args, first_arg_type); - retval = _dbus_call_with_reply_valist (connection, - dest, path, iface, method, - notify_function, - user_data, free_function, - first_arg_type, args); - va_end (args); - - return TRUE; - -} - - - -static gboolean -_ibus_call_with_reply (DBusConnection *connection, const gchar *method, - DBusPendingCallNotifyFunction notify_function, - void *user_data, DBusFreeFunction free_function, - int first_arg_type, ...) -{ - va_list args; - gboolean retval; - - if (connection == NULL) - return FALSE; - - va_start (args, first_arg_type); - retval = _dbus_call_with_reply_valist (connection, - IBUS_NAME, IBUS_PATH, IBUS_IFACE, - method, notify_function, - user_data, free_function, - first_arg_type, args); - va_end (args); - - return retval; -} - -struct _KeyPressCallData { - IBusIMClient *client; - gchar *ic; - GdkEvent *event; -}; - -static KeyPressCallData * -_key_press_call_data_new (IBusIMClient *client, const gchar *ic, GdkEvent *event) -{ - KeyPressCallData *p = g_slice_new (KeyPressCallData); - p->client = g_object_ref (client); - p->ic = g_strdup (ic); - p->event = gdk_event_copy (event); - return p; -} - -static void -_key_press_call_data_free (KeyPressCallData *p) -{ - if (p) { - g_object_unref (p->client); - g_free (p->ic); - gdk_event_free (p->event); - } - g_slice_free (KeyPressCallData, p); -} - -static void -_ibus_filter_keypress_reply_cb (DBusPendingCall *pending, void *user_data) -{ - DBusMessage *reply; - DBusError error = {0}; - KeyPressCallData *call_data = (KeyPressCallData *) user_data; - gboolean retval; - - - reply = dbus_pending_call_steal_reply (pending); - dbus_pending_call_unref (pending); - - if (dbus_set_error_from_message (&error, reply)) { - g_warning ("%s", error.message); - dbus_error_free (&error); - retval = FALSE; - } - else { - if (!dbus_message_get_args (reply, &error, - DBUS_TYPE_BOOLEAN, &retval, DBUS_TYPE_INVALID)) { - g_warning ("%s", error.message); - dbus_error_free (&error); - retval = FALSE; - } - } - - if (!retval) { - g_signal_emit (call_data->client, client_signals[FORWARD_EVENT], 0, - call_data->ic, call_data->event); - } -} - - diff --git a/lib/gtk2/ibusimclient.h b/lib/gtk2/ibusimclient.h deleted file mode 100644 index 9a42332..0000000 --- a/lib/gtk2/ibusimclient.h +++ /dev/null @@ -1,133 +0,0 @@ -/* vim:set et ts=4: */ -/* ibus - The Input Bus - * Copyright (C) 2008-2009 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 library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -#ifndef __IBUS_IM_CLIENT_H_ -#define __IBUS_IM_CLIENT_H_ - -#include <glib-object.h> -/* - * Type macros. - */ - -/* define GOBJECT macros */ -#define IBUS_TYPE_IM_CLIENT \ - (ibus_im_client_get_type ()) -#define IBUS_IM_CLIENT(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_IM_CLIENT, IBusIMClient)) -#define IBUS_IM_CLIENT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_IM_CLIENT, IBusIMClientClass)) -#define IBUS_IS_IM_CLIENT(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_IM_CLIENT)) -#define IBUS_IS_IM_CLIENT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_IM_CLIENT)) -#define IBUS_IM_CLIENT_GET_CLASS(obj) \ - (G_TYPE_CHECK_GET_CLASS ((obj), IBUS_TYPE_IM_CLIENT, IBusIMClientClass)) - -#define IBUS_FORWARD_MASK (1 << 25) - -#if 0 -#define DEBUG_FUNCTION_IN g_debug("%s IN", __FUNCTION__); -#define DEBUG_FUNCTION_OUT g_debug("%s OUT", __FUNCTION__); -#else -#define DEBUG_FUNCTION_IN -#define DEBUG_FUNCTION_OUT -#endif - - - -#define IBUS_DBUS_SERVICE "org.freedesktop.ibus" -#define IBUS_DBUS_INTERFACE "org.freedesktop.ibus.Manager" -#define IBUS_DBUS_PATH "/org/freedesktop/ibus/Manager" - -G_BEGIN_DECLS -enum IBusCap { - IBUS_CAP_PREEDIT = (1), - IBUS_CAP_AUX_STRING = (1 << 1), - IBUS_CAP_LOOKUP_TABLE = (1 << 2), - IBUS_CAP_FOCUS = (1 << 3), -}; - -typedef struct _IBusIMClient IBusIMClient; -typedef struct _IBusIMClientClass IBusIMClientClass; -typedef struct _IBusIMClientPrivate IBusIMClientPrivate; - -struct _IBusIMClient { - GObject parent; - /* instance members */ - IBusIMClientPrivate *priv; -}; - -struct _IBusIMClientClass { - GObjectClass parent; - /* class members */ - void (* connected) (IBusIMClient *client); - void (* disconnected) (IBusIMClient *client); - void (* commit_string) (IBusIMClient *client, - const gchar *ic, - const gchar *text); - void (* update_preedit) (IBusIMClient *client, - const gchar *ic, - const gchar *text, - gpointer *attrs, - gint cursor_pos, - gboolean visible); - void (* show_preedit) (IBusIMClient *client, - const gchar *ic); - void (* hide_preedit) (IBusIMClient *client, - const gchar *ic); - void (* enabled) (IBusIMClient *client, - const gchar *ic); - void (* disabled) (IBusIMClient *client, - const gchar *ic); -}; - -GType ibus_im_client_get_type (void); -void ibus_im_client_register_type (GTypeModule *type_module); -IBusIMClient *ibus_im_client_new (void); -const gchar *ibus_im_client_create_input_context - (IBusIMClient *client); -void ibus_im_client_shutdown (void); -void ibus_im_client_focus_in (IBusIMClient *client, - const gchar *ic); -void ibus_im_client_focus_out (IBusIMClient *client, - const gchar *ic); -void ibus_im_client_reset (IBusIMClient *client, - const gchar *ic); -gboolean ibus_im_client_filter_keypress (IBusIMClient *client, - const gchar *ic, - GdkEventKey *key, - gboolean block); -void ibus_im_client_set_cursor_location - (IBusIMClient *client, - const gchar *ic, - GdkRectangle *area); -void ibus_im_client_set_capabilities (IBusIMClient *client, - const gchar *ic, - gint caps); -gboolean ibus_im_client_is_enabled (IBusIMClient *client); -void ibus_im_client_release_input_context - (IBusIMClient *client, - const gchar *ic); -void ibus_im_client_kill_daemon (IBusIMClient *client); -gboolean ibus_im_client_get_connected (IBusIMClient *client); - - -G_END_DECLS -#endif - diff --git a/lib/gtk2/ibusmarshalers.list b/lib/gtk2/ibusmarshalers.list deleted file mode 100644 index 25c85db..0000000 --- a/lib/gtk2/ibusmarshalers.list +++ /dev/null @@ -1,5 +0,0 @@ -NONE:NONE -NONE:STRING -NONE:STRING,STRING -NONE:STRING,BOXED -NONE:STRING,STRING,BOXED,INT,BOOL diff --git a/po/.gitignore b/po/.gitignore index 3dc4511..76425a9 100644 --- a/po/.gitignore +++ b/po/.gitignore @@ -11,3 +11,8 @@ insert-header.sin quot.sed remove-potcdate.sed remove-potcdate.sin +ja.gmo +pa.gmo +zh_CN.gmo +ibus.pot +stamp-po diff --git a/po/POTFILES.in b/po/POTFILES.in index 775475e..444ed03 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -19,7 +19,7 @@ ./ibus/lang.py ./ibus/lookuptable.py ./ibus/property.py -./ibus/gtk.py +./ibus/_gtk.py ./ibus/ascii.py ./ibus/factory.py ./ui/gtk/menu.py @@ -31,20 +31,6 @@ ./ui/gtk/panel.py ./ui/gtk/propitem.py ./ui/gtk/languagebar.py -./gconf/main.py -./gconf/config.py ./setup/main.py ./setup/keyboardshortcut.py -./daemon/bus.py -./daemon/register.py -./daemon/contextmanager.py -./daemon/ibusdaemon.py -./daemon/factorymanager.py -./daemon/engine.py -./daemon/panel.py -./daemon/config.py -./daemon/inputcontext.py -./daemon/lookuptable.py -./daemon/enginefactory.py -./daemon/connection.py ./setup/setup.glade @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: ibus VERSION\n" "Report-Msgid-Bugs-To: http://code.google.com/p/ibus/issues/entry\n" -"POT-Creation-Date: 2008-10-19 09:45+0800\n" +"POT-Creation-Date: 2009-02-05 10:29+0800\n" "PO-Revision-Date: 2008-08-28 17:31+0900\n" "Last-Translator: UTUMI Hirosi <utuhiro78@yahoo.co.jp>\n" "Language-Team: Japanese <gnome-translation@gnome.gr.jp>\n" @@ -16,20 +16,20 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ibus/lang.py:40 ui/gtk/panel.py:294 ui/gtk/panel.py:295 ui/gtk/panel.py:296 -#: ui/gtk/panel.py:297 setup/main.py:361 setup/main.py:362 setup/main.py:363 +#: ibus/lang.py:40 ui/gtk/panel.py:307 ui/gtk/panel.py:308 ui/gtk/panel.py:309 +#: ui/gtk/panel.py:310 msgid "Other" msgstr "" -#: ui/gtk/panel.py:94 +#: ui/gtk/panel.py:99 msgid "iBus - Running" msgstr "iBus - 実行中" -#: ui/gtk/panel.py:356 +#: ui/gtk/panel.py:370 msgid "IBus is an intelligent input bus for Linux/Unix." msgstr "" -#: ui/gtk/panel.py:360 +#: ui/gtk/panel.py:374 msgid "translator-credits" msgstr "UTUMI Hirosi <utuhiro78@yahoo.co.jp>" @@ -37,23 +37,23 @@ msgstr "UTUMI Hirosi <utuhiro78@yahoo.co.jp>" msgid "Switch engine" msgstr "" -#: setup/main.py:100 +#: setup/main.py:99 msgid "trigger" msgstr "トリガー" -#: setup/main.py:110 +#: setup/main.py:109 msgid "next engine" msgstr "次のエンジン" -#: setup/main.py:120 +#: setup/main.py:119 msgid "prev engine" msgstr "前のエンジン" -#: setup/main.py:165 +#: setup/main.py:197 msgid "IBus daemon is not started. Do you want to start it now?" msgstr "IBus デーモンが動いていません。起動しますか?" -#: setup/main.py:180 +#: setup/main.py:212 msgid "" "IBus has been started! If you can not use IBus, please add below lines in " "$HOME/.bashrc, and relogin your desktop.\n" @@ -67,19 +67,7 @@ msgstr "" " export XMODIFIERS=@im=ibus\n" " export QT_IM_MODULE=ibus" -#: setup/main.py:202 setup/setup.glade:368 -msgid "Engine" -msgstr "エンジン" - -#: setup/main.py:229 -msgid "Started" -msgstr "開始" - -#: setup/main.py:239 -msgid "Preload" -msgstr "プリロード" - -#: setup/main.py:249 +#: setup/main.py:227 #, python-format msgid "Select keyboard shortcut for %s" msgstr "%s のキーボードショートカットを選択" @@ -108,25 +96,6 @@ msgstr "" msgid "Please press a key (or a key combination)" msgstr "キーもしくはキーの組み合わせを入力してください" -#: daemon/bus.py:221 -msgid "Cannot enable input engine" -msgstr "" - -#: daemon/bus.py:222 -msgid "" -"IBus can not enable input engine, because IBus does not load any input " -"engines!\n" -"Please use ibus-setup program to load some input engines." -msgstr "" - -#: daemon/bus.py:224 -msgid "Setup" -msgstr "" - -#: daemon/bus.py:224 -msgid "Don't show this again" -msgstr "" - #: setup/setup.glade:7 msgid "IBus - Setup" msgstr "IBus - セットアップ" @@ -183,7 +152,28 @@ msgstr "" msgid "General" msgstr "一般" -#: setup/setup.glade:385 +#: setup/setup.glade:399 +msgid "gtk-add" +msgstr "" + +#: setup/setup.glade:409 +#, fuzzy +msgid "gtk-remove" +msgstr "gtk-close" + +#: setup/setup.glade:422 +msgid "gtk-go-up" +msgstr "" + +#: setup/setup.glade:435 +msgid "gtk-go-down" +msgstr "" + +#: setup/setup.glade:460 +msgid "Engine" +msgstr "エンジン" + +#: setup/setup.glade:477 msgid "" "<big><b>iBus</b></big>\n" "<small>The intelligent input bus</small>\n" @@ -193,10 +183,16 @@ msgid "" "\n" msgstr "" -#: setup/setup.glade:410 +#: setup/setup.glade:502 msgid "About" msgstr "About" -#: setup/setup.glade:432 +#: setup/setup.glade:524 msgid "gtk-close" msgstr "gtk-close" + +#~ msgid "Started" +#~ msgstr "開始" + +#~ msgid "Preload" +#~ msgstr "プリロード" @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: ibus\n" "Report-Msgid-Bugs-To: http://code.google.com/p/ibus/issues/entry\n" -"POT-Creation-Date: 2008-10-19 09:45+0800\n" +"POT-Creation-Date: 2009-02-05 10:29+0800\n" "PO-Revision-Date: 2008-10-17 14:15+0530\n" "Last-Translator: Amanpreet Singh <aalam@users.sf.net>\n" "Language-Team: Punjabi/Panjabi <punjabi-l10n@lists.sf.net>\n" @@ -16,20 +16,20 @@ msgstr "" "X-Generator: Lokalize 0.2\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: ibus/lang.py:40 ui/gtk/panel.py:294 ui/gtk/panel.py:295 ui/gtk/panel.py:296 -#: ui/gtk/panel.py:297 setup/main.py:361 setup/main.py:362 setup/main.py:363 +#: ibus/lang.py:40 ui/gtk/panel.py:307 ui/gtk/panel.py:308 ui/gtk/panel.py:309 +#: ui/gtk/panel.py:310 msgid "Other" msgstr "ਹੋਰ" -#: ui/gtk/panel.py:94 +#: ui/gtk/panel.py:99 msgid "iBus - Running" msgstr "iBus - ਚੱਲ ਰਿਹਾ ਹੈ" -#: ui/gtk/panel.py:356 +#: ui/gtk/panel.py:370 msgid "IBus is an intelligent input bus for Linux/Unix." msgstr "iBus ਲੀਨਕਸ/ਯੂਨੈਕਸ ਲਈ ਮਾਹਰ ਇੰਪੁੱਟ ਬੱਸ ਹੈ।" -#: ui/gtk/panel.py:360 +#: ui/gtk/panel.py:374 msgid "translator-credits" msgstr "ਅਮਨਪਰੀਤ ਸਿੰਘ ਆਲਮ" @@ -37,23 +37,23 @@ msgstr "ਅਮਨਪਰੀਤ ਸਿੰਘ ਆਲਮ" msgid "Switch engine" msgstr "ਇੰਜਣ ਬਦਲੋ" -#: setup/main.py:100 +#: setup/main.py:99 msgid "trigger" msgstr "ਟਰਿੱਗਰ" -#: setup/main.py:110 +#: setup/main.py:109 msgid "next engine" msgstr "ਅਗਲਾ ਇੰਜਣ" -#: setup/main.py:120 +#: setup/main.py:119 msgid "prev engine" msgstr "ਪਿਛਲਾ ਇੰਜਣ" -#: setup/main.py:165 +#: setup/main.py:197 msgid "IBus daemon is not started. Do you want to start it now?" msgstr "iBus ਡੈਮਨ ਚੱਲਦੀ ਨਹੀਂ ਹੈ। ਕੀ ਤੁਸੀਂ ਇਸ ਨੂੰ ਸ਼ੁਰੂ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?" -#: setup/main.py:180 +#: setup/main.py:212 msgid "" "IBus has been started! If you can not use IBus, please add below lines in " "$HOME/.bashrc, and relogin your desktop.\n" @@ -66,19 +66,7 @@ msgstr "" "
export XMODIFIERS=@im=ibus\n" "
export QT_IM_MODULE=ibus" -#: setup/main.py:202 setup/setup.glade:368 -msgid "Engine" -msgstr "ਇੰਜਣ" - -#: setup/main.py:229 -msgid "Started" -msgstr "ਚਾਲੂ ਹੈ" - -#: setup/main.py:239 -msgid "Preload" -msgstr "ਪ੍ਰੀ-ਲੋਡ" - -#: setup/main.py:249 +#: setup/main.py:227 #, python-format msgid "Select keyboard shortcut for %s" msgstr "%s ਲਈ ਕੀਬੋਰਡ ਸ਼ਾਰਟਕੱਟ ਚੁਣੋ" @@ -107,28 +95,6 @@ msgstr "" msgid "Please press a key (or a key combination)" msgstr "ਕੋਈ ਵੀ ਸਵਿੱਚ ਦੱਬੋ (ਜਾਂ ਸਵਿੱਚ ਜੋੜ)" -#: daemon/bus.py:221 -msgid "Cannot enable input engine" -msgstr "ਇੰਪੁੱਟ ਇੰਜਣ ਯੋਗ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ" - -#: daemon/bus.py:222 -msgid "" -"IBus can not enable input engine, because IBus does not load any input " -"engines!\n" -"Please use ibus-setup program to load some input engines." -msgstr "" -"iBus ਕੋਈ ਇੰਪੁੱਟ ਇੰਜਣ ਯੋਗ ਨਹੀਂ ਕਰ ਸਕਦੀ ਹੈ, ਕਿਉਂਕਿ ਆਈ-ਬੱਸ ਕਿਸੇ ਇੰਪੁੱਟ ਇੰਜਣ ਨੂੰ ਲੋਡ ਨਹੀਂ ਕਰ ਸਕਦੀ " -"ਹੈ!\n" -"
ਕੁਝ ਇੰਪੁੱਟ ਇੰਜਣ ਨੂੰ ਲੋਡ ਕਰਨ ਵਾਸਤੇ ibus-setup ਪਰੋਗਰਾਮ ਵਰਤੋਂ।" - -#: daemon/bus.py:224 -msgid "Setup" -msgstr "ਸੈੱਟਅੱਪ" - -#: daemon/bus.py:224 -msgid "Don't show this again" -msgstr "ਇਹ ਮੁੜ ਨਾ ਵੇਖਾਓ" - #: setup/setup.glade:7 msgid "IBus - Setup" msgstr "IBus - ਸੈੱਟਅੱਪ" @@ -185,7 +151,28 @@ msgstr "<b>UI</b>" msgid "General" msgstr "ਆਮ" -#: setup/setup.glade:385 +#: setup/setup.glade:399 +msgid "gtk-add" +msgstr "" + +#: setup/setup.glade:409 +#, fuzzy +msgid "gtk-remove" +msgstr "gtk-close" + +#: setup/setup.glade:422 +msgid "gtk-go-up" +msgstr "" + +#: setup/setup.glade:435 +msgid "gtk-go-down" +msgstr "" + +#: setup/setup.glade:460 +msgid "Engine" +msgstr "ਇੰਜਣ" + +#: setup/setup.glade:477 msgid "" "<big><b>iBus</b></big>\n" "<small>The intelligent input bus</small>\n" @@ -201,10 +188,34 @@ msgstr "" "
\n" "
\n" -#: setup/setup.glade:410 +#: setup/setup.glade:502 msgid "About" msgstr "ਇਸ ਬਾਰੇ" -#: setup/setup.glade:432 +#: setup/setup.glade:524 msgid "gtk-close" msgstr "gtk-close" + +#~ msgid "Started" +#~ msgstr "ਚਾਲੂ ਹੈ" + +#~ msgid "Preload" +#~ msgstr "ਪ੍ਰੀ-ਲੋਡ" + +#~ msgid "Cannot enable input engine" +#~ msgstr "ਇੰਪੁੱਟ ਇੰਜਣ ਯੋਗ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ" + +#~ msgid "" +#~ "IBus can not enable input engine, because IBus does not load any input " +#~ "engines!\n" +#~ "Please use ibus-setup program to load some input engines." +#~ msgstr "" +#~ "iBus ਕੋਈ ਇੰਪੁੱਟ ਇੰਜਣ ਯੋਗ ਨਹੀਂ ਕਰ ਸਕਦੀ ਹੈ, ਕਿਉਂਕਿ ਆਈ-ਬੱਸ ਕਿਸੇ ਇੰਪੁੱਟ ਇੰਜਣ ਨੂੰ ਲੋਡ ਨਹੀਂ ਕਰ " +#~ "ਸਕਦੀ ਹੈ!\n" +#~ "
ਕੁਝ ਇੰਪੁੱਟ ਇੰਜਣ ਨੂੰ ਲੋਡ ਕਰਨ ਵਾਸਤੇ ibus-setup ਪਰੋਗਰਾਮ ਵਰਤੋਂ।" + +#~ msgid "Setup" +#~ msgstr "ਸੈੱਟਅੱਪ" + +#~ msgid "Don't show this again" +#~ msgstr "ਇਹ ਮੁੜ ਨਾ ਵੇਖਾਓ" diff --git a/po/zh_CN.po b/po/zh_CN.po index fdb59b7..7c5b745 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1.1.20080813\n" "Report-Msgid-Bugs-To: http://code.google.com/p/ibus/issues/entry\n" -"POT-Creation-Date: 2008-10-19 09:45+0800\n" +"POT-Creation-Date: 2009-02-05 10:29+0800\n" "PO-Revision-Date: 2008-08-13 21:59+0800\n" "Last-Translator: Huang Peng <shawn.p.huang@gmail.com>\n" "Language-Team: Huang Peng <shawn.p.huang@gmail.com>\n" @@ -16,20 +16,20 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: ibus/lang.py:40 ui/gtk/panel.py:294 ui/gtk/panel.py:295 ui/gtk/panel.py:296 -#: ui/gtk/panel.py:297 setup/main.py:361 setup/main.py:362 setup/main.py:363 +#: ibus/lang.py:40 ui/gtk/panel.py:307 ui/gtk/panel.py:308 ui/gtk/panel.py:309 +#: ui/gtk/panel.py:310 msgid "Other" msgstr "其他" -#: ui/gtk/panel.py:94 +#: ui/gtk/panel.py:99 msgid "iBus - Running" msgstr "iBus - 运行" -#: ui/gtk/panel.py:356 +#: ui/gtk/panel.py:370 msgid "IBus is an intelligent input bus for Linux/Unix." msgstr "" -#: ui/gtk/panel.py:360 +#: ui/gtk/panel.py:374 msgid "translator-credits" msgstr "Huang Peng <shawn.p.huang@gmail.com>" @@ -37,23 +37,23 @@ msgstr "Huang Peng <shawn.p.huang@gmail.com>" msgid "Switch engine" msgstr "切换引擎" -#: setup/main.py:100 +#: setup/main.py:99 msgid "trigger" msgstr "开关" -#: setup/main.py:110 +#: setup/main.py:109 msgid "next engine" msgstr "下一个引擎" -#: setup/main.py:120 +#: setup/main.py:119 msgid "prev engine" msgstr "上一个引擎" -#: setup/main.py:165 +#: setup/main.py:197 msgid "IBus daemon is not started. Do you want to start it now?" msgstr "IBus守护进程没有启动,您是否想现在启动它?" -#: setup/main.py:180 +#: setup/main.py:212 msgid "" "IBus has been started! If you can not use IBus, please add below lines in " "$HOME/.bashrc, and relogin your desktop.\n" @@ -66,19 +66,7 @@ msgstr "" " export XMODIFIERS=@im=ibus\n" " export QT_IM_MODULE=ibus" -#: setup/main.py:202 setup/setup.glade:368 -msgid "Engine" -msgstr "输入法引擎" - -#: setup/main.py:229 -msgid "Started" -msgstr "启动" - -#: setup/main.py:239 -msgid "Preload" -msgstr "预加载" - -#: setup/main.py:249 +#: setup/main.py:227 #, python-format msgid "Select keyboard shortcut for %s" msgstr "选择%s的快捷键" @@ -107,27 +95,6 @@ msgstr "" msgid "Please press a key (or a key combination)" msgstr "请按一个键盘按键(或者一个组合按键)" -#: daemon/bus.py:221 -msgid "Cannot enable input engine" -msgstr "不能启动输入引擎" - -#: daemon/bus.py:222 -msgid "" -"IBus can not enable input engine, because IBus does not load any input " -"engines!\n" -"Please use ibus-setup program to load some input engines." -msgstr "" -"IBus不能启动输入引擎,因为IBus没有加载任何输入引擎!\n" -"请运行ibus-setup程序,启动需要的输入法引擎。" - -#: daemon/bus.py:224 -msgid "Setup" -msgstr "设置" - -#: daemon/bus.py:224 -msgid "Don't show this again" -msgstr "不再显示该信息" - #: setup/setup.glade:7 msgid "IBus - Setup" msgstr "IBus - 设置" @@ -184,7 +151,27 @@ msgstr "<b>用户界面</b>" msgid "General" msgstr "通用" -#: setup/setup.glade:385 +#: setup/setup.glade:399 +msgid "gtk-add" +msgstr "" + +#: setup/setup.glade:409 +msgid "gtk-remove" +msgstr "" + +#: setup/setup.glade:422 +msgid "gtk-go-up" +msgstr "" + +#: setup/setup.glade:435 +msgid "gtk-go-down" +msgstr "" + +#: setup/setup.glade:460 +msgid "Engine" +msgstr "输入法引擎" + +#: setup/setup.glade:477 msgid "" "<big><b>iBus</b></big>\n" "<small>The intelligent input bus</small>\n" @@ -194,10 +181,33 @@ msgid "" "\n" msgstr "" -#: setup/setup.glade:410 +#: setup/setup.glade:502 msgid "About" msgstr "关于" -#: setup/setup.glade:432 +#: setup/setup.glade:524 msgid "gtk-close" msgstr "" + +#~ msgid "Started" +#~ msgstr "启动" + +#~ msgid "Preload" +#~ msgstr "预加载" + +#~ msgid "Cannot enable input engine" +#~ msgstr "不能启动输入引擎" + +#~ msgid "" +#~ "IBus can not enable input engine, because IBus does not load any input " +#~ "engines!\n" +#~ "Please use ibus-setup program to load some input engines." +#~ msgstr "" +#~ "IBus不能启动输入引擎,因为IBus没有加载任何输入引擎!\n" +#~ "请运行ibus-setup程序,启动需要的输入法引擎。" + +#~ msgid "Setup" +#~ msgstr "设置" + +#~ msgid "Don't show this again" +#~ msgstr "不再显示该信息" diff --git a/setup/.gitignore b/setup/.gitignore index bcebcbe..1a6aff2 100644 --- a/setup/.gitignore +++ b/setup/.gitignore @@ -1 +1,2 @@ ibus-setup +ibus-setup.desktop diff --git a/setup/Makefile.am b/setup/Makefile.am index ad2e9d4..0e144e9 100644 --- a/setup/Makefile.am +++ b/setup/Makefile.am @@ -21,6 +21,9 @@ ibussetup_PYTHON = \ main.py \ + icon.py \ + enginecombobox.py \ + enginetreeview.py \ keyboardshortcut.py \ $(NULL) diff --git a/setup/enginecombobox.py b/setup/enginecombobox.py new file mode 100644 index 0000000..c8eaa15 --- /dev/null +++ b/setup/enginecombobox.py @@ -0,0 +1,92 @@ +# vim:set et sts=4 sw=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 + +import gtk +import gobject +import ibus + +from icon import load_icon + +class EngineComboBox(gtk.ComboBox): + def __init__(self, engines): + super(EngineComboBox, self).__init__() + + self.__model = gtk.TreeStore(gobject.TYPE_PYOBJECT) + + lang = {} + for e in engines: + l = ibus.get_language_name(e.language) + if l not in lang: + lang[l] = [] + lang[l].append(e) + + for l in lang.keys(): + iter1 = self.__model.append(None) + self.__model.set(iter1, 0, l) + for e in lang[l]: + iter2 = self.__model.append(iter1) + self.__model.set(iter2, 0, e) + + self.set_model(self.__model) + + renderer = gtk.CellRendererPixbuf() + renderer.set_property("xalign", 0) + self.pack_start(renderer, False) + self.set_cell_data_func(renderer, self.__icon_cell_data_cb) + + renderer = gtk.CellRendererText() + renderer.set_property("xalign", 0) + self.pack_start(renderer, True) + self.set_cell_data_func(renderer, self.__name_cell_data_cb) + + def __icon_cell_data_cb(self, celllayout, renderer, model, iter): + engine = self.__model.get_value(iter, 0) + + icon_size = gtk.icon_size_lookup(gtk.ICON_SIZE_LARGE_TOOLBAR)[0] + if isinstance (engine, str) or isinstance (engine, unicode): + renderer.set_property("visible", False) + renderer.set_property("sensitive", False) + else: + renderer.set_property("visible", True) + renderer.set_property("sensitive", True) + pixbuf = load_icon(engine.icon, gtk.ICON_SIZE_LARGE_TOOLBAR) + if pixbuf == None: + pixbuf = load_icon("default-engine", gtk.ICON_SIZE_LARGE_TOOLBAR) + if pixbuf == None: + pixbuf = load_icon("gtk-missing-image", gtk.ICON_SIZE_LARGE_TOOLBAR) + renderer.set_property("pixbuf", pixbuf) + + def __name_cell_data_cb(self, celllayout, renderer, model, iter): + engine = self.__model.get_value(iter, 0) + + if isinstance (engine, str) or isinstance (engine, unicode): + renderer.set_property("sensitive", False) + renderer.set_property("text", engine) + else: + renderer.set_property("sensitive", True) + renderer.set_property("text", engine.longname) + + def get_active_engine(self): + iter = self.get_active_iter() + if iter == None: + return None + return self.get_model()[iter][0] + diff --git a/setup/enginetreeview.py b/setup/enginetreeview.py new file mode 100644 index 0000000..4e4c131 --- /dev/null +++ b/setup/enginetreeview.py @@ -0,0 +1,157 @@ +# vim:set et sts=4 sw=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 + +import gtk +import gobject +import ibus + +from icon import load_icon + +class EngineTreeView(gtk.TreeView): + __gsignals__ = { + 'changed' : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + ()) + } + + def __init__(self, engines): + super(EngineTreeView, self).__init__() + + self.__engines = set([]) + + self.__model = gtk.TreeStore(gobject.TYPE_PYOBJECT) + self.set_model(self.__model) + + self.set_headers_visible(False) + + column = gtk.TreeViewColumn() + + renderer = gtk.CellRendererPixbuf() + renderer.set_property("xalign", 0) + column.pack_start(renderer, False) + column.set_cell_data_func(renderer, self.__icon_cell_data_cb) + + renderer = gtk.CellRendererText() + renderer.set_property("xalign", 0) + column.pack_start(renderer, True) + column.set_cell_data_func(renderer, self.__name_cell_data_cb) + self.append_column (column) + + self.set_engines(engines) + + def __icon_cell_data_cb(self, celllayout, renderer, model, iter): + engine = self.__model.get_value(iter, 0) + + icon_size = gtk.icon_size_lookup(gtk.ICON_SIZE_LARGE_TOOLBAR)[0] + pixbuf = load_icon(engine.icon, gtk.ICON_SIZE_LARGE_TOOLBAR) + + if pixbuf == None: + pixbuf = load_icon("default-engine", gtk.ICON_SIZE_LARGE_TOOLBAR) + if pixbuf == None: + pixbuf = load_icon("gtk-missing-image", gtk.ICON_SIZE_LARGE_TOOLBAR) + + renderer.set_property("pixbuf", pixbuf) + + def __name_cell_data_cb(self, celllayout, renderer, model, iter): + engine = self.__model.get_value(iter, 0) + renderer.set_property("sensitive", True) + renderer.set_property("text", engine.longname) + + def set_engines(self, engines): + self.__model.clear() + self.__engines = set([]) + for e in engines: + if e in self.__engines: + continue + iter = self.__model.append(None) + self.__model.set(iter, 0, e) + self.__engines.add(e) + self.emit("changed") + + def get_selected_iter(self): + selection = self.get_selection() + if selection: + return selection.get_selected()[1] + + def get_engines(self): + return map(lambda r: r[0], self.__model) + + def get_select_engine(self): + iter = self.get_selected_iter() + if iter == None: + return None + row = self.__model.get(iter) + return row[0] + + def prepend_engine(self, engine): + if engine == None or engine in self.__engines: + return + iter = self.__model.prepend(None) + self.__model.set(iter, 0, engine) + self.__engines.add(engine) + self.emit("changed") + self.scroll_to_cell(self.__model[0].path, None) + + def remove_engine(self): + iter = self.get_selected_iter() + if iter == None: + return + row = self.__model[iter] + engine = row[0] + self.__engines.remove(engine) + index = row.path[0] + self.__model.remove(iter) + self.emit("changed") + try: + row = self.__model[index] + selection = self.get_selection() + selection.select_path(row.path) + except: + pass + + def move_up_engine(self): + iter = self.get_selected_iter() + if iter == None: + return + row = self.__model[iter] + index = row.path[0] + if index == 0: + return + self.__model.swap(iter, self.__model[index - 1].iter) + self.emit("changed") + self.scroll_to_cell(row.path, None) + + def move_down_engine(self): + iter = self.get_selected_iter() + if iter == None: + return + row = self.__model[iter] + index = row.path[0] + last_row = self.__model[-1] + last_index = last_row.path[0] + if index == last_index: + return + self.__model.swap(iter, self.__model[index + 1].iter) + self.emit("changed") + self.scroll_to_cell(row.path, None) + +gobject.type_register(EngineTreeView) diff --git a/setup/icon.py b/setup/icon.py new file mode 100644 index 0000000..fedd2cf --- /dev/null +++ b/setup/icon.py @@ -0,0 +1,60 @@ +# vim:set et sts=4 sw=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 + +__all__ = ( + "load_icon" +) + +import gtk +from gtk import gdk +from os import path + + +icon_theme = gtk.icon_theme_get_default() +dir = path.dirname(__file__) +icondir = path.join(dir, "..", "icons") +icon_theme.prepend_search_path(icondir) + +icon_cache = {} + +def load_icon(icon, size): + if (icon, size) in icon_cache: + return icon_cache[(icon, size)] + + icon_size = gtk.icon_size_lookup(size)[0] + pixbuf = None + try: + pixbuf = gdk.pixbuf_new_from_file(icon) + w, h = pixbuf.get_width(), pixbuf.get_height() + rate = max(w, h) / float(icon_size) + w = int(w / rate) + h = int(h / rate) + pixbuf = pixbuf.scale_simple(w, h, gdk.INTERP_BILINEAR) + except: + pass + if pixbuf == None: + try: + theme = gtk.icon_theme_get_default() + pixbuf = theme.load_icon(icon, icon_size, 0) + except: + pass + icon_cache[(icon, size)] = pixbuf + return pixbuf diff --git a/setup/keyboardshortcut.py b/setup/keyboardshortcut.py index c667903..c30dbcc 100644 --- a/setup/keyboardshortcut.py +++ b/setup/keyboardshortcut.py @@ -80,7 +80,7 @@ class KeyboardShortcutSelection(gtk.VBox): table = gtk.Table(4, 2) self.__modifier_buttons = [] - self.__modifier_buttons.append(("Ctrl", gtk.CheckButton("_Ctrl"), gdk.CONTROL_MASK)) + self.__modifier_buttons.append(("Control", gtk.CheckButton("_Control"), gdk.CONTROL_MASK)) self.__modifier_buttons.append(("Alt", gtk.CheckButton("A_lt"), gdk.MOD1_MASK)) self.__modifier_buttons.append(("Shift", gtk.CheckButton("_Shift"), gdk.SHIFT_MASK)) self.__modifier_buttons.append(("Meta", gtk.CheckButton("_Meta"), gdk.META_MASK)) @@ -258,7 +258,7 @@ if __name__ == "__main__": dlg = KeyboardShortcutSelectionDialog( title = "Select test", buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK)) - dlg.add_shortcut("Ctrl+Shift+space") + dlg.add_shortcut("Control+Shift+space") dlg.set_shortcuts(None) print dlg.run() print dlg.get_shortcuts() diff --git a/setup/main.py b/setup/main.py index 7fe9f2e..e3349d0 100644 --- a/setup/main.py +++ b/setup/main.py @@ -33,6 +33,9 @@ from os import path from xdg import BaseDirectory from gtk import gdk from gtk import glade +from enginecombobox import EngineComboBox +from enginetreeview import EngineTreeView +from icon import load_icon _ = lambda a : gettext.dgettext("ibus", a) N_ = lambda a : a @@ -75,12 +78,6 @@ class Setup(object): def __init_ui(self): # add icon search path - icon_theme = gtk.icon_theme_get_default() - dir = path.dirname(__file__) - icondir = path.join(dir, "..", "icons") - icon_theme.prepend_search_path(icondir) - - self.__dialog = self.__xml.get_widget("dialog_setup") # auto start ibus @@ -90,76 +87,111 @@ class Setup(object): # keyboard shortcut # trigger - shortcuts = self.__bus.config_get_value( - "general", "keyboard_shortcut_trigger", + self.__config = self.__bus.get_config() + shortcuts = self.__config.get_value( + "general/hotkey", "trigger", ibus.CONFIG_GENERAL_SHORTCUT_TRIGGER_DEFAULT) + button = self.__xml.get_widget("button_trigger") entry = self.__xml.get_widget("entry_trigger") entry.set_text("; ".join(shortcuts)) button.connect("clicked", self.__shortcut_button_clicked_cb, - N_("trigger"), "general", "keyboard_shortcut_trigger", entry) + N_("trigger"), "general/hotkey", "trigger", entry) # next engine - shortcuts = self.__bus.config_get_value( - "general", "keyboard_shortcut_next_engine", + shortcuts = self.__config.get_value( + "general/hotkey", "next_engine", ibus.CONFIG_GENERAL_SHORTCUT_NEXT_ENGINE_DEFAULT) button = self.__xml.get_widget("button_next_engine") entry = self.__xml.get_widget("entry_next_engine") entry.set_text("; ".join(shortcuts)) button.connect("clicked", self.__shortcut_button_clicked_cb, - N_("next engine"), "general", "keyboard_shortcut_next_engine", entry) + N_("next engine"), "general/hotkey", "next_engine", entry) # prev engine - shortcuts = self.__bus.config_get_value( - "general", "keyboard_shortcut_prev_engine", + shortcuts = self.__config.get_value( + "general/hotkey", "prev_engine", ibus.CONFIG_GENERAL_SHORTCUT_PREV_ENGINE_DEFAULT) button = self.__xml.get_widget("button_prev_engine") entry = self.__xml.get_widget("entry_prev_engine") entry.set_text("; ".join(shortcuts)) button.connect("clicked", self.__shortcut_button_clicked_cb, - N_("prev engine"), "general", "keyboard_shortcut_prev_engine", entry) - - + N_("prev engine"), "general/hotkey", "prev_engine", entry) # lookup table orientation self.__combobox_lookup_table_orientation = self.__xml.get_widget("combobox_lookup_table_orientation") self.__combobox_lookup_table_orientation.set_active( - self.__bus.config_get_value("panel", "lookup_table_orientation", 0)) + self.__config.get_value("panel", "lookup_table_orientation", 0)) self.__combobox_lookup_table_orientation.connect("changed", self.__combobox_lookup_table_orientation_changed_cb) # auto hide self.__checkbutton_auto_hide = self.__xml.get_widget("checkbutton_auto_hide") self.__checkbutton_auto_hide.set_active( - self.__bus.config_get_value("panel", "auto_hide", False)) + self.__config.get_value("panel", "auto_hide", False)) self.__checkbutton_auto_hide.connect("toggled", self.__checkbutton_auto_hide_toggled_cb) # custom font self.__checkbutton_custom_font = self.__xml.get_widget("checkbutton_custom_font") self.__checkbutton_custom_font.set_active( - self.__bus.config_get_value("panel", "use_custom_font", False)) + self.__config.get_value("panel", "use_custom_font", False)) self.__checkbutton_custom_font.connect("toggled", self.__checkbutton_custom_font_toggled_cb) self.__fontbutton_custom_font = self.__xml.get_widget("fontbutton_custom_font") - if self.__bus.config_get_value("panel", "use_custom_font", False): + if self.__config.get_value("panel", "use_custom_font", False): self.__fontbutton_custom_font.set_sensitive(True) else: self.__fontbutton_custom_font.set_sensitive(False) font_name = gtk.settings_get_default().get_property("gtk-font-name") font_name = unicode(font_name, "utf-8") - font_name = self.__bus.config_get_value("panel", "custom_font", font_name) + font_name = self.__config.get_value("panel", "custom_font", font_name) self.__fontbutton_custom_font.connect("notify::font-name", self.__fontbutton_custom_font_notify_cb) self.__fontbutton_custom_font.set_font_name(font_name) - self.__init_engine_view() + # init engine page + self.__engines = self.__bus.list_engines() + self.__combobox = EngineComboBox(self.__engines) + self.__combobox.show() + self.__xml.get_widget("alignment_engine_combobox").add(self.__combobox) + + tmp_dict = {} + for e in self.__engines: + tmp_dict[e.name] = e + engine_names = self.__config.get_value("general", "preload_engines", []) + engines = [] + for n in engine_names: + if n in tmp_dict: + engines.append(tmp_dict[n]) + self.__treeview = EngineTreeView(engines) + self.__treeview.show() + self.__xml.get_widget("scrolledwindow_engine_treeview").add(self.__treeview) + + self.__treeview.connect("changed", self.__treeview_changed_cb) + + button = self.__xml.get_widget("button_engine_add") + button.connect("clicked", + lambda *args:self.__treeview.prepend_engine(self.__combobox.get_active_engine())) + button = self.__xml.get_widget("button_engine_remove") + button.connect("clicked", lambda *args:self.__treeview.remove_engine()) + button = self.__xml.get_widget("button_engine_up") + button.connect("clicked", lambda *args:self.__treeview.move_up_engine()) + + button = self.__xml.get_widget("button_engine_down") + button.connect("clicked", lambda *args:self.__treeview.move_down_engine()) + + def __treeview_changed_cb(self, treeview): + engines = self.__treeview.get_engines() + engine_names = map(lambda e: e.name, engines) + self.__config.set_list("general", "preload_engines", engine_names, "s") def __init_bus(self): try: self.__bus = ibus.Bus() # self.__bus.connect("config-value-changed", self.__config_value_changed_cb) - self.__bus.connect("config-reloaded", self.__config_reloaded_cb) - self.__bus.config_add_watch("/general") - self.__bus.config_add_watch("/panel") + # self.__bus.connect("config-reloaded", self.__config_reloaded_cb) + # self.__bus.config_add_watch("/general") + # self.__bus.config_add_watch("/general/hotkey") + # self.__bus.config_add_watch("/panel") except: while self.__bus == None: message = _("IBus daemon is not started. Do you want to start it now?") @@ -190,60 +222,6 @@ class Setup(object): dlg.destroy() self.__flush_gtk_events() - def __init_engine_view(self): - # engines tree - self.__tree = self.__xml.get_widget("treeview_engines") - self.__preload_engines = set(self.__bus.config_get_value("general", "preload_engines", [])) - model = self.__create_model() - self.__tree.set_model(model) - - # column for engine - column = gtk.TreeViewColumn() - column.set_title(_("Engine")) - column.set_resizable(True) - column.set_min_width(120) - - renderer = gtk.CellRendererPixbuf() - renderer.set_property("xalign", 0.5) - - column.pack_start(renderer, False) - column.set_attributes(renderer, pixbuf = COLUMN_ICON, visible = COLUMN_VISIBLE) - - renderer = gtk.CellRendererText() - renderer.set_property("xalign", 0.0) - renderer.set_property("ellipsize", pango.ELLIPSIZE_END) - - # column.set_clickable(True) - column.pack_start(renderer) - column.set_attributes(renderer, text = COLUMN_NAME) - - self.__tree.append_column(column) - - # column for started - renderer = gtk.CellRendererToggle() - renderer.set_data('column', COLUMN_ENABLE) - renderer.set_property("xalign", 0.5) - renderer.connect("toggled", self.__item_started_column_toggled_cb, model) - - #col_offset = gtk.TreeViewColumn("Holiday", renderer, text=HOLIDAY_NAME) - column = gtk.TreeViewColumn(_("Started"), renderer, active = COLUMN_ENABLE, visible = COLUMN_VISIBLE) - column.set_resizable(True) - self.__tree.append_column(column) - - # column for preload - renderer = gtk.CellRendererToggle() - renderer.set_data('column', COLUMN_PRELOAD) - renderer.set_property("xalign", 0.5) - renderer.connect("toggled", self.__item_preload_column_toggled_cb, model) - - column = gtk.TreeViewColumn(_("Preload"), renderer, active = COLUMN_PRELOAD, visible = COLUMN_VISIBLE) - column.set_resizable(True) - self.__tree.append_column(column) - - renderer = gtk.CellRendererText() - column = gtk.TreeViewColumn("", renderer) - self.__tree.append_column(column) - def __shortcut_button_clicked_cb(self, button, name, section, _name, entry): buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK) title = _("Select keyboard shortcut for %s") % _(name) @@ -259,7 +237,7 @@ class Setup(object): dialog.destroy() if id != gtk.RESPONSE_OK: return - self.__bus.config_set_value(section, _name, shortcuts) + self.__config.set_value(section, _name, shortcuts) entry.set_text("; ".join(shortcuts)) @@ -309,94 +287,15 @@ class Setup(object): if data[DATA_PRELOAD]: if engine not in self.__preload_engines: self.__preload_engines.add(engine) - self.__bus.config_set_list("general", "preload_engines", list(self.__preload_engines), "s") + self.__config.set_list("general", "preload_engines", list(self.__preload_engines), "s") else: if engine in self.__preload_engines: self.__preload_engines.remove(engine) - self.__bus.config_set_list("general", "preload_engines", list(self.__preload_engines), "s") + self.__config.set_list("general", "preload_engines", list(self.__preload_engines), "s") # set new value model.set(iter, COLUMN_PRELOAD, data[DATA_PRELOAD]) - def __load_icon(self, icon, icon_size): - pixbuf = None - try: - pixbuf = gdk.pixbuf_new_from_file(icon) - w, h = pixbuf.get_width(), pixbuf.get_height() - rate = max(w, h) / float(icon_size) - w = int(w / rate) - h = int(h / rate) - pixbuf = pixbuf.scale_simple(w, h, gdk.INTERP_BILINEAR) - except: - pass - if pixbuf == None: - try: - theme = gtk.icon_theme_get_default() - pixbuf = theme.load_icon(icon, icon_size, 0) - except: - pass - return pixbuf - - def __create_model(self): - # create tree store - model = gtk.TreeStore( - gobject.TYPE_STRING, - gobject.TYPE_BOOLEAN, - gobject.TYPE_BOOLEAN, - gobject.TYPE_BOOLEAN, - gdk.Pixbuf, - gobject.TYPE_PYOBJECT) - - langs = dict() - - self.__bus.register_reload_engines() - for name, local_name, lang, icon, author, credits, _exec, started in self.__bus.register_list_engines(): - _lang = ibus.get_language_name(lang) - if _lang not in langs: - langs[_lang] = list() - langs[_lang].append([name, local_name, lang, icon, author, credits, _exec, started]) - - keys = langs.keys() - keys.sort() - if _("Other") in keys: - keys.remove(_("Other")) - keys.append(_("Other")) - - icon_size = gtk.icon_size_lookup(gtk.ICON_SIZE_LARGE_TOOLBAR)[0] - pixbuf_missing = self.__load_icon("engine-default", icon_size) - if pixbuf_missing == None: - pixbuf_missing = self.__load_icon("gtk-missing-image", icon_size) - - for key in keys: - iter = model.append(None) - model.set(iter, - COLUMN_NAME, key, - COLUMN_ENABLE, False, - COLUMN_PRELOAD, False, - COLUMN_VISIBLE, False, - COLUMN_ICON, None, - COLUMN_DATA, None) - langs[key].sort() - - for name, local_name, lang, icon, author, credits, _exec, started in langs[key]: - child_iter = model.append(iter) - is_preload = "%s:%s" % (lang, name) in self.__preload_engines - - pixbuf = self.__load_icon(icon, icon_size) - if pixbuf == None: - pixbuf = pixbuf_missing - - model.set(child_iter, - COLUMN_NAME, local_name, - COLUMN_ENABLE, started, - COLUMN_PRELOAD, is_preload, - COLUMN_VISIBLE, True, - COLUMN_ICON, pixbuf, - COLUMN_DATA, - [name, local_name, lang, icon, author, credits, _exec, started, is_preload]) - - return model - def __is_auto_start(self): link_file = path.join(BaseDirectory.xdg_config_home, "autostart/ibus.desktop") ibus_desktop = path.join(os.getenv("IBUS_PREFIX"), "share/applications/ibus.desktop") @@ -425,27 +324,27 @@ class Setup(object): os.symlink(ibus_desktop, link_file) def __combobox_lookup_table_orientation_changed_cb(self, combobox): - self.__bus.config_set_value( + self.__config.set_value( "panel", "lookup_table_orientation", self.__combobox_lookup_table_orientation.get_active()) def __checkbutton_auto_hide_toggled_cb(self, button): - self.__bus.config_set_value( + self.__config.set_value( "panel", "auto_hide", self.__checkbutton_auto_hide.get_active()) def __checkbutton_custom_font_toggled_cb(self, button): if self.__checkbutton_custom_font.get_active(): self.__fontbutton_custom_font.set_sensitive(True) - self.__bus.config_set_value("panel", "use_custom_font", True) + self.__config.set_value("panel", "use_custom_font", True) else: self.__fontbutton_custom_font.set_sensitive(False) - self.__bus.config_set_value("panel", "use_custom_font", False) + self.__config.set_value("panel", "use_custom_font", False) def __fontbutton_custom_font_notify_cb(self, button, arg): font_name = self.__fontbutton_custom_font.get_font_name() font_name = unicode(font_name, "utf-8") - self.__bus.config_set_value("panel", "custom_font", font_name) + self.__config.set_value("panel", "custom_font", font_name) def __config_value_changed_cb(self, bus, section, name, value): pass diff --git a/setup/setup.glade b/setup/setup.glade index 72854d9..c8e63ed 100644 --- a/setup/setup.glade +++ b/setup/setup.glade @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> -<!--Generated with glade3 3.4.5 on Thu Oct 9 11:25:43 2008 --> +<!--Generated with glade3 3.4.5 on Wed Feb 4 15:58:20 2009 --> <glade-interface> <widget class="GtkDialog" id="dialog_setup"> <property name="border_width">5</property> @@ -340,20 +340,112 @@ Vertical</property> <property name="left_padding">2</property> <property name="right_padding">2</property> <child> - <widget class="GtkScrolledWindow" id="scrolledwindow1"> - <property name="width_request">300</property> - <property name="height_request">350</property> + <widget class="GtkHBox" id="hbox1"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="shadow_type">GTK_SHADOW_IN</property> <child> - <widget class="GtkTreeView" id="treeview_engines"> + <widget class="GtkAlignment" id="alignment6"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="reorderable">True</property> + <property name="top_padding">4</property> + <child> + <widget class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkAlignment" id="alignment_engine_combobox"> + <property name="visible">True</property> + <child> + <placeholder/> + </child> + </widget> + </child> + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow_engine_treeview"> + <property name="width_request">240</property> + <property name="height_request">350</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkAlignment" id="alignment2"> + <property name="visible">True</property> + <property name="top_padding">8</property> + <property name="bottom_padding">8</property> + <property name="left_padding">8</property> + <property name="right_padding">8</property> + <child> + <widget class="GtkVButtonBox" id="vbuttonbox1"> + <property name="visible">True</property> + <property name="spacing">5</property> + <property name="layout_style">GTK_BUTTONBOX_START</property> + <child> + <widget class="GtkButton" id="button_engine_add"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="label" translatable="yes">gtk-add</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + </widget> + </child> + <child> + <widget class="GtkButton" id="button_engine_remove"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="label" translatable="yes">gtk-remove</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="button_engine_up"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="label" translatable="yes">gtk-go-up</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="button_engine_down"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="label" translatable="yes">gtk-go-down</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="position">3</property> + </packing> + </child> + </widget> + </child> </widget> + <packing> + <property name="position">1</property> + </packing> </child> </widget> </child> diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..f39eb28 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,12 @@ +ibusmarshalers.c +ibusmarshalers.h +test-attribute +test-bus +test-engine +test-keynames +test-lookuptable +test-proxy +test-server +test-text +stamp-ibusenumtypes.h +stamp-ibusmarshalers.h diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..e8c6614 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,209 @@ +# 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 + +INCLUDES = \ + -I$(top_srcdir) \ + $(NULL) + +# ibus library +lib_LTLIBRARIES = libibus.la +ibus_built_public_h_sources = \ + ibusmarshalers.h \ + ibusenumtypes.h \ + $(NULl) +ibus_built_c_sources = \ + ibusmarshalers.c \ + ibusenumtypes.c \ + $(NULL) +ibus_built_sources = \ + $(ibus_built_public_h_sources) \ + $(ibus_built_c_sources) \ + $(NULL) +ibus_public_h_sources = \ + ibus.h \ + ibusshare.h \ + ibusdebug.h \ + ibusobject.h \ + ibusserializable.h \ + ibusconnection.h \ + ibusserver.h \ + ibusproxy.h \ + ibusservice.h \ + ibusfactory.h \ + ibusengine.h \ + ibustext.h \ + ibusattribute.h \ + ibusproperty.h \ + ibuslookuptable.h \ + ibusinputcontext.h \ + ibusconfig.h \ + ibusconfigservice.h \ + ibusmessage.h \ + ibuspendingcall.h \ + ibuserror.h \ + ibuskeysyms.h \ + ibustypes.h \ + ibusbus.h \ + ibushotkey.h \ + ibusxml.h \ + ibusenginedesc.h \ + ibusobservedpath.h \ + ibuscomponent.h \ + $(NULL) +ibus_h_sources = \ + ibusinternal.h \ + ibusconfigprivate.h \ + keyname-table.h \ + $(ibus_public_h_sources) \ + $(ibus_built_public_h_sources) \ + $(NULL) +ibus_c_sources = \ + ibusshare.c \ + ibusinternal.c \ + ibusobject.c \ + ibusserializable.c \ + ibusconnection.c \ + ibusserver.c \ + ibusproxy.c \ + ibusservice.c \ + ibusfactory.c \ + ibusengine.c \ + ibustext.c \ + ibusattribute.c \ + ibusproperty.c \ + ibuslookuptable.c \ + ibusinputcontext.c \ + ibusconfig.c \ + ibusconfigservice.c \ + ibusmessage.c \ + ibuspendingcall.c \ + ibuserror.c \ + ibusbus.c \ + ibuskeynames.c \ + ibushotkey.c \ + ibusxml.c \ + ibusenginedesc.c \ + ibusobservedpath.c \ + ibuscomponent.c \ + $(ibus_built_c_sources) \ + $(NULL) + +ibusincludedir = $(includedir)/ibus-1.0 +ibusinclude_HEADERS = \ + $(ibus_public_h_sources) \ + $(ibus_built_public_h_sources) \ + $(NULL) + +libibus_la_SOURCES = \ + $(ibus_h_sources) \ + $(ibus_c_sources) \ + $(NULL) +libibus_la_CFLAGS = \ + @X11_CFLAGS@ \ + @GLIB2_CFLAGS@ \ + @GOBJECT2_CFLAGS@ \ + @GIO2_CFLAGS@ \ + @DBUS_CFLAGS@ \ + -DG_LOG_DOMAIN=\"IBUS\" \ + $(NULL) +libibus_la_LDFLAGS = \ + @X11_LIBS@ \ + @GLIB2_LIBS@ \ + @GOBJECT2_LIBS@ \ + @GIO2_LIBS@ \ + @DBUS_LIBS@ \ + -version-info @LT_VERSION_INFO@ \ + $(NULL) + +BUILT_SOURCES = \ + $(ibus_built_sources) \ + $(NULL) + + +# test programs +DEPS = \ + libibus.la \ + $(NULL) +AM_CFLAGS = \ + @X11_CFLAGS@ \ + @GLIB2_CFLAGS@ \ + @GOBJECT2_CFLAGS@ \ + @GIO2_CFLAGS@ \ + @DBUS_CFLAGS@ \ + -DG_LOG_DOMAIN=\"IBUS\" \ + $(NULL) +AM_LDFLAGS = \ + $(DEPS) \ + $(NULL) + +TESTS = \ + test-text \ + test-keynames \ + test-attribute \ + test-lookuptable \ + $(NULL) +noinst_PROGRAMS = $(TESTS) +test_text_DEPENDENCIES = $(DEPS) +test_keynames_DEPENDENCIES = $(DEPS) +test_attribute_DEPENDENCIES = $(DEPS) +test_lookuptable_DEPENDENCIES = $(DEPS) + +# gen enum types +ibusenumtypes.h: stamp-ibusenumtypes.h + @true +stamp-ibusenumtypes.h: @REBUILD@ $(ibus_public_h_sources) ibusenumtypes.h.template + ( cd $(srcdir) && $(GLIB_MKENUMS) --template ibusenumtypes.h.template \ + $(ibus_public_h_sources) ) | sed 's/i_bus_/ibus_/g' | sed 's/I_TYPE_BUS_/IBUS_TYPE_/g' >> xgen-geth \ + && (cmp -s xgen-geth ibusenumtypes.h || cp xgen-geth ibusenumtypes.h ) \ + && rm -f xgen-geth \ + && echo timestamp > $(@F) +ibusenumtypes.c: @REBUILD@ $(ibus_public_h_sources) ibusenumtypes.c.template + ( cd $(srcdir) && $(GLIB_MKENUMS) --template ibusenumtypes.c.template \ + $(ibus_public_h_sources) ) | sed 's/i_bus_/ibus_/g' | sed 's/I_TYPE_BUS_/IBUS_TYPE_/g' > xgen-getc \ + && cp xgen-getc ibusenumtypes.c \ + && rm -f xgen-getc + +# gen marshal +ibusmarshalers.h: stamp-ibusmarshalers.h + @true +stamp-ibusmarshalers.h: ibusmarshalers.list + $(GLIB_GENMARSHAL) --prefix=ibus_marshal $(srcdir)/ibusmarshalers.list --header >> xgen-gmh \ + && (cmp -s xgen-gmh ibusmarshalers.h || cp xgen-gmh ibusmarshalers.h) \ + && rm -f xgen-gmh \ + && echo timestamp > $(@F) +ibusmarshalers.c: ibusmarshalers.list + (echo "#include \"ibusmarshalers.h\""; \ + $(GLIB_GENMARSHAL) --prefix=ibus_marshal $(srcdir)/ibusmarshalers.list --body; \ + echo ) >> xgen-gmc \ + && cp xgen-gmc ibusmarshalers.c \ + && rm -f xgen-gmc + +EXTRA_DIST = \ + ibusmarshalers.list \ + ibusenumtypes.h.template \ + ibusenumtypes.c.template \ + $(NULL) + +CLEANFILES = \ + $(BUILT_SOURCES) \ + stamp-ibusmarshalers.h \ + stamp-ibusenumtypes.h \ + $(NULL) diff --git a/src/ibus.h b/src/ibus.h new file mode 100644 index 0000000..23b270a --- /dev/null +++ b/src/ibus.h @@ -0,0 +1,51 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_H_ +#define __IBUS_H_ + +#include <ibusshare.h> +#include <ibusobject.h> +#include <ibusserializable.h> +#include <ibustext.h> +#include <ibusconnection.h> +#include <ibusserver.h> +#include <ibusproxy.h> +#include <ibusservice.h> +#include <ibusfactory.h> +#include <ibusengine.h> +#include <ibusattribute.h> +#include <ibusproperty.h> +#include <ibuslookuptable.h> +#include <ibusbus.h> +#include <ibuskeysyms.h> +#include <ibusmessage.h> +#include <ibuspendingcall.h> +#include <ibuserror.h> +#include <ibusenumtypes.h> +#include <ibushotkey.h> +#include <ibusxml.h> +#include <ibusenginedesc.h> +#include <ibusobservedpath.h> +#include <ibuscomponent.h> +#include <ibusconfig.h> +#include <ibusconfigservice.h> + +#endif + diff --git a/src/ibusattribute.c b/src/ibusattribute.c new file mode 100644 index 0000000..7b41ab2 --- /dev/null +++ b/src/ibusattribute.c @@ -0,0 +1,433 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include "ibusattribute.h" + +/* functions prototype */ +static void ibus_attribute_class_init (IBusAttributeClass *klass); +static void ibus_attribute_init (IBusAttribute *attr); +// static void ibus_attribute_destroy (IBusAttribute *attr); +static gboolean ibus_attribute_serialize (IBusAttribute *attr, + IBusMessageIter *iter); +static gboolean ibus_attribute_deserialize (IBusAttribute *attr, + IBusMessageIter *iter); +static gboolean ibus_attribute_copy (IBusAttribute *dest, + const IBusAttribute *src); + +static void ibus_attr_list_class_init (IBusAttrListClass *klass); +static void ibus_attr_list_init (IBusAttrList *attr_list); +static void ibus_attr_list_destroy (IBusAttrList *attr_list); +static gboolean ibus_attr_list_serialize (IBusAttrList *attr_list, + IBusMessageIter *iter); +static gboolean ibus_attr_list_deserialize (IBusAttrList *attr_list, + IBusMessageIter *iter); +static gboolean ibus_attr_list_copy (IBusAttrList *dest, + const IBusAttrList *src); + +static IBusSerializableClass *parent_class = NULL; + +GType +ibus_attribute_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusAttributeClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_attribute_class_init, + NULL, /* class finialize */ + NULL, /* class data */ + sizeof (IBusAttribute), + 0, + (GInstanceInitFunc) ibus_attribute_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusAttribute", + &type_info, + 0); + } + + return type; +} + +static void +ibus_attribute_class_init (IBusAttributeClass *klass) +{ + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + // object_class->destroy = (IBusObjectDestroyFunc) ibus_attribute_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_attribute_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_attribute_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_attribute_copy; + + g_string_append (serializable_class->signature, "uuuu"); +} + +static void +ibus_attribute_init (IBusAttribute *attr) +{ +} + +// static void +// ibus_attribute_destroy (IBusAttribute *attr) +// { +// IBUS_OBJECT (parent_class)->destroy ((IBusObject *)attr); +// } + +static gboolean +ibus_attribute_serialize (IBusAttribute *attr, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = parent_class->serialize ((IBusSerializable *) attr, iter); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_ATTRIBUTE (attr), FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_UINT, &attr->type); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_UINT, &attr->value); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_UINT, &attr->start_index); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_UINT, &attr->end_index); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_attribute_deserialize (IBusAttribute *attr, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = parent_class->deserialize ((IBusSerializable *) attr, iter); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_ATTRIBUTE (attr), FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_UINT, &attr->type); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_UINT, &attr->value); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_UINT, &attr->start_index); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_UINT, &attr->end_index); + g_return_val_if_fail (retval, FALSE); + + return TRUE; + +} + +static gboolean +ibus_attribute_copy (IBusAttribute *dest, + const IBusAttribute *src) +{ + gboolean retval; + + retval = parent_class->copy ((IBusSerializable *)dest, + (IBusSerializable *)src); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_ATTRIBUTE (dest), FALSE); + g_return_val_if_fail (IBUS_IS_ATTRIBUTE (src), FALSE); + + dest->type = src->type; + dest->value = src->value; + dest->start_index = src->start_index; + dest->end_index = src->end_index; + + return TRUE; +} + +IBusAttribute * +ibus_attribute_new (guint type, + guint value, + guint start_index, + guint end_index) +{ + g_return_val_if_fail ( + type == IBUS_ATTR_TYPE_UNDERLINE || + type == IBUS_ATTR_TYPE_FOREGROUND || + type == IBUS_ATTR_TYPE_BACKGROUND, NULL); + + IBusAttribute *attr = IBUS_ATTRIBUTE (g_object_new (IBUS_TYPE_ATTRIBUTE, 0)); + + attr->type = type; + attr->value = value; + attr->start_index = start_index; + attr->end_index = end_index; + + return attr; +} + +IBusAttribute * +ibus_attr_underline_new (guint underline_type, + guint start_index, + guint end_index) +{ + g_return_val_if_fail ( + underline_type == IBUS_ATTR_UNDERLINE_NONE || + underline_type == IBUS_ATTR_UNDERLINE_SINGLE || + underline_type == IBUS_ATTR_UNDERLINE_DOUBLE || + underline_type == IBUS_ATTR_UNDERLINE_LOW, NULL); + + return ibus_attribute_new (IBUS_ATTR_TYPE_UNDERLINE, + underline_type, + start_index, + end_index); +} + +IBusAttribute * +ibus_attr_foreground_new (guint color, + guint start_index, + guint end_index) +{ + return ibus_attribute_new (IBUS_ATTR_TYPE_FOREGROUND, + color, + start_index, + end_index); +} + +IBusAttribute * +ibus_attr_background_new (guint color, + guint start_index, + guint end_index) +{ + return ibus_attribute_new (IBUS_ATTR_TYPE_BACKGROUND, + color, + start_index, + end_index); +} + +GType +ibus_attr_list_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusAttrListClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_attr_list_class_init, + NULL, /* class finialize */ + NULL, /* class data */ + sizeof (IBusAttrList), + 0, + (GInstanceInitFunc) ibus_attr_list_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusAttrList", + &type_info, + 0); + } + + return type; +} + +static void +ibus_attr_list_class_init (IBusAttrListClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_attr_list_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_attr_list_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_attr_list_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_attr_list_copy; + + g_string_append (serializable_class->signature, "av"); +} + +static void +ibus_attr_list_init (IBusAttrList *attr_list) +{ + attr_list->attributes = g_array_new (TRUE, TRUE, sizeof (IBusAttribute *)); +} + +static void +ibus_attr_list_destroy (IBusAttrList *attr_list) +{ + g_return_if_fail (IBUS_IS_ATTR_LIST (attr_list)); + + gint i; + for (i = 0;; i++) { + IBusAttribute *attr; + + attr = ibus_attr_list_get (attr_list, i); + if (attr == NULL) + break; + + g_object_unref (attr); + } + + g_array_free (attr_list->attributes, TRUE); + + IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *)attr_list); +} + +static gboolean +ibus_attr_list_serialize (IBusAttrList *attr_list, + IBusMessageIter *iter) +{ + IBusMessageIter array_iter; + gboolean retval; + guint i; + + retval = parent_class->serialize ((IBusSerializable *)attr_list, iter); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_ATTR_LIST (attr_list), FALSE); + + retval = ibus_message_iter_open_container (iter, + IBUS_TYPE_ARRAY, + "v", + &array_iter); + g_return_val_if_fail (retval, FALSE); + + for (i = 0;; i++) { + IBusAttribute *attr; + + attr = ibus_attr_list_get (attr_list, i); + if (attr == NULL) + break; + + retval = ibus_message_iter_append (&array_iter, IBUS_TYPE_ATTRIBUTE, &attr); + g_return_val_if_fail (retval, FALSE); + } + + retval = ibus_message_iter_close_container (iter, &array_iter); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_attr_list_deserialize (IBusAttrList *attr_list, + IBusMessageIter *iter) +{ + DBusMessageIter array_iter; + gboolean retval; + + retval = parent_class->deserialize ((IBusSerializable *)attr_list, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_recurse (iter, IBUS_TYPE_ARRAY, &array_iter); + g_return_val_if_fail (retval, FALSE); + + while (ibus_message_iter_get_arg_type (&array_iter) != G_TYPE_INVALID) { + IBusAttribute *attr; + + retval = ibus_message_iter_get (&array_iter, IBUS_TYPE_ATTRIBUTE, &attr); + + g_return_val_if_fail (retval, FALSE); + + ibus_attr_list_append (attr_list, attr); + } + + ibus_message_iter_next (iter); + + return TRUE; +} + + + +static gboolean +ibus_attr_list_copy (IBusAttrList *dest, + const IBusAttrList *src) +{ + gboolean retval; + + retval = parent_class->copy ((IBusSerializable *)dest, + (IBusSerializable *)src); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_ATTRIBUTE (dest), FALSE); + g_return_val_if_fail (IBUS_IS_ATTRIBUTE (src), FALSE); + + gint i; + for (i = 0; ; i++) { + IBusAttribute *attr = ibus_attr_list_get ((IBusAttrList *)src, i); + if (attr == NULL) { + break; + } + + attr = (IBusAttribute *) ibus_serializable_copy ((IBusSerializable *) attr); + if (attr == NULL) { + g_warning ("can not copy attribute"); + continue; + } + + ibus_attr_list_append (dest, attr); + } + return TRUE; +} + +IBusAttrList * +ibus_attr_list_new () +{ + IBusAttrList *attr_list; + attr_list = g_object_new (IBUS_TYPE_ATTR_LIST, 0); + return attr_list; +} + +void +ibus_attr_list_append (IBusAttrList *attr_list, + IBusAttribute *attr) +{ + g_return_if_fail (IBUS_IS_ATTR_LIST (attr_list)); + g_return_if_fail (IBUS_IS_ATTRIBUTE (attr)); + + g_array_append_val (attr_list->attributes, attr); +} + +IBusAttribute * +ibus_attr_list_get (IBusAttrList *attr_list, + guint index) +{ + g_return_val_if_fail (attr_list != NULL, NULL); + IBusAttribute *attr = NULL; + + if (index < attr_list->attributes->len) { + attr = g_array_index (attr_list->attributes, IBusAttribute *, index); + } + + return attr; +} + + diff --git a/src/ibusattribute.h b/src/ibusattribute.h new file mode 100644 index 0000000..3a0ff7f --- /dev/null +++ b/src/ibusattribute.h @@ -0,0 +1,126 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_ATTRIBUTE_H_ +#define __IBUS_ATTRIBUTE_H_ + +#include "ibusserializable.h" + +/* + * Type macros. + */ +/* define IBusAttribute macros */ +#define IBUS_TYPE_ATTRIBUTE \ + (ibus_attribute_get_type ()) +#define IBUS_ATTRIBUTE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_ATTRIBUTE, IBusAttribute)) +#define IBUS_ATTRIBUTE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_ATTRIBUTE, IBusAttributeClass)) +#define IBUS_IS_ATTRIBUTE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_ATTRIBUTE)) +#define IBUS_IS_ATTRIBUTE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_ATTRIBUTE)) +#define IBUS_ATTRIBUTE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_ATTRIBUTE, IBusAttributeClass)) + +/* define IBusAttrList macros */ +#define IBUS_TYPE_ATTR_LIST \ + (ibus_attr_list_get_type ()) +#define IBUS_ATTR_LIST(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_ATTR_LIST, IBusAttrList)) +#define IBUS_ATTR_LIST_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_ATTR_LIST, IBusAttrListClass)) +#define IBUS_IS_ATTR_LIST(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_ATTR_LIST)) +#define IBUS_IS_ATTR_LIST_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_ATTR_LIST)) +#define IBUS_ATTR_LIST_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_ATTR_LIST, IBusAttrListClass)) + +typedef enum { + IBUS_ATTR_TYPE_UNDERLINE = 1, + IBUS_ATTR_TYPE_FOREGROUND = 2, + IBUS_ATTR_TYPE_BACKGROUND = 3, +} IBusAttrType; + +typedef enum { + IBUS_ATTR_UNDERLINE_NONE = 0, + IBUS_ATTR_UNDERLINE_SINGLE = 1, + IBUS_ATTR_UNDERLINE_DOUBLE = 2, + IBUS_ATTR_UNDERLINE_LOW = 3, +} IBusAttrUnderline; + +G_BEGIN_DECLS + +typedef struct _IBusAttribute IBusAttribute; +typedef struct _IBusAttributeClass IBusAttributeClass; +typedef struct _IBusAttrList IBusAttrList; +typedef struct _IBusAttrListClass IBusAttrListClass; + +struct _IBusAttribute { + IBusSerializable parent; + + /* members */ + guint type; + guint value; + guint start_index; + guint end_index; +}; + +struct _IBusAttributeClass { + IBusSerializableClass parent; +}; + +struct _IBusAttrList { + IBusSerializable parent; + + /* members */ + GArray *attributes; +}; + +struct _IBusAttrListClass { + IBusSerializableClass parent; +}; + +GType ibus_attribute_get_type (); +IBusAttribute *ibus_attribute_new (guint type, + guint value, + guint start_index, + guint end_index); +IBusAttribute *ibus_attr_underline_new (guint underline_type, + guint start_index, + guint end_index); +IBusAttribute *ibus_attr_foreground_new (guint color, + guint start_index, + guint end_index); +IBusAttribute *ibus_attr_background_new (guint color, + guint start_index, + guint end_index); + + +GType ibus_attr_list_get_type (); +IBusAttrList *ibus_attr_list_new (); +void ibus_attr_list_append (IBusAttrList *attr_list, + IBusAttribute *attr); +IBusAttribute *ibus_attr_list_get (IBusAttrList *attr_list, + guint index); + +G_END_DECLS +#endif + diff --git a/src/ibusbus.c b/src/ibusbus.c new file mode 100644 index 0000000..be72770 --- /dev/null +++ b/src/ibusbus.c @@ -0,0 +1,773 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <gio/gio.h> +#include "ibusbus.h" +#include "ibusinternal.h" +#include "ibusshare.h" +#include "ibusconnection.h" + +#define IBUS_BUS_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_BUS, IBusBusPrivate)) + +enum { + CONNECTED, + DISCONNECTED, + NAME_OWNER_CHANGED, + LAST_SIGNAL, +}; + + +/* IBusBusPriv */ +struct _IBusBusPrivate { + GFileMonitor *monitor; + IBusConnection *connection; + gboolean watch_dbus_signal; +}; +typedef struct _IBusBusPrivate IBusBusPrivate; + +static guint bus_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_bus_class_init (IBusBusClass *klass); +static void ibus_bus_init (IBusBus *bus); +static void ibus_bus_destroy (IBusObject *object); +static void ibus_bus_watch_dbus_signal + (IBusBus *bus); +static void ibus_bus_unwatch_dbus_signal + (IBusBus *bus); +static IBusObjectClass *parent_class = NULL; + +GType +ibus_bus_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusBusClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_bus_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusBus), + 0, + (GInstanceInitFunc) ibus_bus_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_OBJECT, + "IBusBus", + &type_info, + (GTypeFlags)0); + } + + return type; +} + +IBusBus * +ibus_bus_new (void) +{ + IBusBus *bus = IBUS_BUS (g_object_new (IBUS_TYPE_BUS, NULL)); + + return bus; +} + +static void +ibus_bus_class_init (IBusBusClass *klass) +{ + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + + parent_class = (IBusObjectClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusBusPrivate)); + + ibus_object_class->destroy = ibus_bus_destroy; + + // install signals + bus_signals[CONNECTED] = + g_signal_new (I_("connected"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + bus_signals[DISCONNECTED] = + g_signal_new (I_("disconnected"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); +#if 0 + bus_signals[NAME_OWNER_CHANGED] = + g_signal_new (I_("name-owner-changed"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__STRING_STRING_STRING, + G_TYPE_NONE, + 3, + G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE, + G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE, + G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE + ); +#endif +} + +#if 0 +static gboolean +_connection_dbus_signal_cb (IBusConnection *connection, + DBusMessage *message, + IBusBus *bus) +{ + g_assert (IBUS_IS_BUS (bus)); + g_assert (message != NULL); + g_assert (IBUS_IS_CONNECTION (connection)); + + IBusBusPrivate *priv; + priv = IBUS_BUS_GET_PRIVATE (bus); + + if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) { + DBusError error; + const gchar *name; + const gchar *old_name; + const gchar *new_name; + gboolean retval; + + dbus_error_init (&error); + retval = dbus_message_get_args (message, &error, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_STRING, &old_name, + DBUS_TYPE_STRING, &new_name, + DBUS_TYPE_INVALID); + if (!retval) { + g_warning ("%s: %s", error.name, error.message); + dbus_error_free (&error); + } + else { + g_signal_emit (bus, + bus_signals[NAME_OWNER_CHANGED], + 0, + name, + old_name, + new_name); + } + } + + return FALSE; +} +#endif + +static void +_connection_destroy_cb (IBusConnection *connection, + IBusBus *bus) +{ + g_assert (IBUS_IS_BUS (bus)); + g_assert (IBUS_IS_CONNECTION (connection)); + + IBusBusPrivate *priv; + priv = IBUS_BUS_GET_PRIVATE (bus); + + g_assert (priv->connection == connection); + g_object_unref (priv->connection); + priv->connection = NULL; + + g_signal_emit (bus, bus_signals[DISCONNECTED], 0); +} + +static void +ibus_bus_connect (IBusBus *bus) +{ + IBusBusPrivate *priv; + priv = IBUS_BUS_GET_PRIVATE (bus); + + g_assert (priv->connection == NULL); + + priv->connection = ibus_connection_open (ibus_get_address ()); + + if (priv->connection) { + ibus_bus_hello (bus); +#if 0 + g_signal_connect (priv->connection, + "dbus-signal", + (GCallback) _connection_dbus_signal_cb, + bus); +#endif + g_signal_connect (priv->connection, + "destroy", + (GCallback) _connection_destroy_cb, + bus); + g_signal_emit (bus, bus_signals[CONNECTED], 0); + + if (priv->watch_dbus_signal) { + ibus_bus_watch_dbus_signal (bus); + } + } +} + +static void +_changed_cb (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + IBusBus *bus) +{ + static GFile *socket_file = NULL; + + if (socket_file == NULL) { + socket_file = g_file_new_for_path (ibus_get_socket_path ()); + } + + if (event_type == G_FILE_MONITOR_EVENT_CREATED) { + if (g_file_equal (file, socket_file)) { + ibus_bus_connect (bus); + } + } +} + +static void +ibus_bus_init (IBusBus *bus) +{ + gchar *path; + GFile *file; + IBusBusPrivate *priv; + priv = IBUS_BUS_GET_PRIVATE (bus); + + priv->connection = NULL; + priv->watch_dbus_signal = FALSE; + + ibus_bus_connect (bus); + + path = g_strdup_printf ("/tmp/ibus-%s/", ibus_get_user_name ()); + file = g_file_new_for_path (path); + priv->monitor = g_file_monitor_directory (file, 0, NULL, NULL); + + g_signal_connect (priv->monitor, "changed", (GCallback) _changed_cb, bus); + + g_object_unref (file); + g_free (path); +} + +static void +ibus_bus_destroy (IBusObject *object) +{ + IBusBus *bus; + IBusBusPrivate *priv; + + bus = IBUS_BUS (object); + priv = IBUS_BUS_GET_PRIVATE (bus); + + if (priv->monitor) { + g_object_unref (priv->monitor); + priv->monitor = NULL; + } + + if (priv->connection) { + ibus_object_destroy (IBUS_OBJECT (priv->connection)); + priv->connection = NULL; + } + + IBUS_OBJECT_CLASS (parent_class)->destroy (object); +} + +gboolean +ibus_bus_is_connected (IBusBus *bus) +{ + g_assert (IBUS_IS_BUS (bus)); + + IBusBusPrivate *priv; + priv = IBUS_BUS_GET_PRIVATE (bus); + + if (priv->connection) { + return ibus_connection_is_connected (priv->connection); + } + + return FALSE; +} + + +IBusInputContext * +ibus_bus_create_input_context (IBusBus *bus, + const gchar *client_name) +{ + g_assert (IBUS_IS_BUS (bus)); + g_assert (client_name != NULL); + g_assert (ibus_bus_is_connected (bus)); + + gchar *path; + DBusMessage *call = NULL; + DBusMessage *reply = NULL; + IBusError *error; + IBusInputContext *context = NULL; + IBusBusPrivate *priv; + priv = IBUS_BUS_GET_PRIVATE (bus); + + call = ibus_message_new_method_call (IBUS_SERVICE_IBUS, + IBUS_PATH_IBUS, + IBUS_INTERFACE_IBUS, + "CreateInputContext"); + ibus_message_append_args (call, + G_TYPE_STRING, &client_name, + G_TYPE_INVALID); + + reply = ibus_connection_send_with_reply_and_block (priv->connection, + call, + -1, + &error); + ibus_message_unref (call); + + if (reply == NULL) { + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + return NULL; + } + + if ((error = ibus_error_new_from_message (reply)) != NULL) { + g_warning ("%s: %s", error->name, error->message); + ibus_message_unref (reply); + ibus_error_free (error); + return NULL; + } + + if (!ibus_message_get_args (reply, + &error, + IBUS_TYPE_OBJECT_PATH, &path, + G_TYPE_INVALID)) { + g_warning ("%s: %s", error->name, error->message); + ibus_message_unref (reply); + ibus_error_free (error); + + return NULL; + } + + context = ibus_input_context_new (path, priv->connection); + ibus_message_unref (reply); + + return context; +} + +static void +ibus_bus_watch_dbus_signal (IBusBus *bus) +{ + g_assert (IBUS_IS_BUS (bus)); + + const gchar *rule; + + rule = "type='signal'," \ + "path='" DBUS_PATH_DBUS "'," \ + "interface='" DBUS_INTERFACE_DBUS "'"; + + ibus_bus_add_match (bus, rule); + +} + +static void +ibus_bus_unwatch_dbus_signal (IBusBus *bus) +{ + g_assert (IBUS_IS_BUS (bus)); + g_assert (ibus_bus_is_connected (bus)); + + const gchar *rule; + + rule = "type='signal'," \ + "path='" DBUS_PATH_DBUS "'," \ + "interface='" DBUS_INTERFACE_DBUS "'"; + + ibus_bus_remove_match (bus, rule); +} + +void +ibus_bus_set_watch_dbus_signal (IBusBus *bus, + gboolean watch) +{ + g_assert (IBUS_IS_BUS (bus)); + + IBusBusPrivate *priv; + priv = IBUS_BUS_GET_PRIVATE (bus); + + if (priv->watch_dbus_signal == watch) + return; + + priv->watch_dbus_signal = watch; + + if (ibus_bus_is_connected (bus)) { + if (watch) { + ibus_bus_watch_dbus_signal (bus); + } + else { + ibus_bus_unwatch_dbus_signal (bus); + } + } +} + + +static gboolean +ibus_bus_call (IBusBus *bus, + const gchar *name, + const gchar *path, + const gchar *interface, + const gchar *member, + GType first_arg_type, + ...) +{ + g_assert (IBUS_IS_BUS (bus)); + g_assert (ibus_bus_is_connected (bus)); + g_assert (name != NULL); + g_assert (path != NULL); + g_assert (interface != NULL); + g_assert (member); + + IBusMessage *message, *reply; + IBusError *error; + va_list args; + GType type; + gboolean retval; + IBusBusPrivate *priv; + + priv = IBUS_BUS_GET_PRIVATE (bus); + + message = ibus_message_new_method_call (name, path, interface, member); + + va_start (args, first_arg_type); + ibus_message_append_args_valist (message, first_arg_type, args); + va_end (args); + + reply = ibus_connection_send_with_reply_and_block ( + priv->connection, + message, + -1, + &error); + ibus_message_unref (message); + + if (reply == NULL) { + g_warning ("%s : %s", error->name, error->message); + ibus_error_free (error); + return FALSE; + } + + if ((error = ibus_error_new_from_message (reply)) != NULL) { + g_warning ("%s : %s", error->name, error->message); + ibus_error_free (error); + ibus_message_unref (reply); + return FALSE; + } + + va_start (args, first_arg_type); + + type = first_arg_type; + + while (type != G_TYPE_INVALID) { + va_arg (args, gpointer); + type = va_arg (args, GType); + } + + type = va_arg (args, GType); + if (type != G_TYPE_INVALID) { + retval = ibus_message_get_args_valist (reply, &error, type, args); + } + else { + retval = TRUE; + } + va_end (args); + + ibus_message_unref (reply); + + if (!retval) { + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + return FALSE; + } + + return TRUE; +} + +const gchar * +ibus_bus_hello (IBusBus *bus) +{ + g_assert (IBUS_IS_BUS (bus)); + + gchar *unique_name = NULL; + gboolean result; + + result = ibus_bus_call (bus, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "Hello", + G_TYPE_INVALID, + G_TYPE_STRING, &unique_name, + G_TYPE_INVALID); + + if (result) + return unique_name; + + return NULL; +} + +guint +ibus_bus_request_name (IBusBus *bus, + const gchar *name, + guint flags) +{ + g_assert (IBUS_IS_BUS (bus)); + + guint retval; + gboolean result; + + result = ibus_bus_call (bus, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "RequestName", + G_TYPE_STRING, &name, + G_TYPE_UINT, &flags, + G_TYPE_INVALID, + G_TYPE_UINT, &retval, + G_TYPE_INVALID); + + if (result) + return retval; + + return 0; +} + +guint +ibus_bus_release_name (IBusBus *bus, + const gchar *name) +{ + g_assert (IBUS_IS_BUS (bus)); + + guint retval; + gboolean result; + + result = ibus_bus_call (bus, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "ReleaseName", + G_TYPE_STRING, &name, + G_TYPE_INVALID, + G_TYPE_UINT, &retval, + G_TYPE_INVALID); + + if (result) + return retval; + + return 0; +} + +gboolean +ibus_bus_name_has_owner (IBusBus *bus, + const gchar *name) +{ + g_assert (IBUS_IS_BUS (bus)); + + gboolean retval; + gboolean result; + + result = ibus_bus_call (bus, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "NameHasOwner", + G_TYPE_STRING, &name, + G_TYPE_INVALID, + G_TYPE_BOOLEAN, &retval, + G_TYPE_INVALID); + + if (result) + return retval; + + return FALSE; +} + +GList * +ibus_bus_list_names (IBusBus *bus) +{ + return NULL; +} + +void +ibus_bus_add_match (IBusBus *bus, + const gchar *rule) +{ + g_assert (IBUS_IS_BUS (bus)); + + gboolean result; + + result = ibus_bus_call (bus, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "AddMatch", + G_TYPE_STRING, &rule, + G_TYPE_INVALID, + G_TYPE_INVALID); +} + +void +ibus_bus_remove_match (IBusBus *bus, + const gchar *rule) +{ + g_assert (IBUS_IS_BUS (bus)); + + gboolean result; + + result = ibus_bus_call (bus, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "RemoveMatch", + G_TYPE_STRING, &rule, + G_TYPE_INVALID, + G_TYPE_INVALID); +} + +const gchar * +ibus_bus_get_name_owner (IBusBus *bus, + const gchar *name) +{ + g_assert (IBUS_IS_BUS (bus)); + + gchar *owner = NULL; + gboolean result; + + result = ibus_bus_call (bus, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "RemoveMatch", + G_TYPE_STRING, &name, + G_TYPE_INVALID, + G_TYPE_STRING, &owner, + G_TYPE_INVALID); + + if (result) + return owner; + + return NULL; +} + +IBusConnection * +ibus_bus_get_connection (IBusBus *bus) +{ + g_assert (IBUS_IS_BUS (bus)); + + IBusBusPrivate *priv; + priv = IBUS_BUS_GET_PRIVATE (bus); + + return priv->connection; +} + +gboolean +ibus_bus_kill (IBusBus *bus) +{ + g_assert (IBUS_IS_BUS (bus)); + + gboolean result; + result = ibus_bus_call (bus, + IBUS_SERVICE_IBUS, + IBUS_PATH_IBUS, + IBUS_INTERFACE_IBUS, + "Kill", + G_TYPE_INVALID, + G_TYPE_INVALID); + return result; +} + +gboolean +ibus_bus_register_component (IBusBus *bus, + IBusComponent *component) +{ + g_assert (IBUS_IS_BUS (bus)); + g_assert (IBUS_IS_COMPONENT (component)); + + gboolean result; + + result = ibus_bus_call (bus, + IBUS_SERVICE_IBUS, + IBUS_PATH_IBUS, + IBUS_INTERFACE_IBUS, + "RegisterComponent", + IBUS_TYPE_COMPONENT, &component, + G_TYPE_INVALID, + G_TYPE_INVALID); + + return result; + + +#if 0 + IBusMessage *message, *reply; + IBusError *error; + + IBusBusPrivate *priv; + priv = IBUS_BUS_GET_PRIVATE (bus); + + message = ibus_message_new_method_call (IBUS_SERVICE_IBUS, + IBUS_PATH_IBUS, + IBUS_INTERFACE_IBUS, + "RegisterComponent"); + + ibus_message_append_args (message, + IBUS_TYPE_COMPONENT, &component, + G_TYPE_INVALID); + + reply = ibus_connection_send_with_reply_and_block ( + priv->connection, + message, + -1, + &error); + ibus_message_unref (message); + + if (reply == NULL) { + g_warning ("%s : %s", error->name, error->message); + ibus_error_free (error); + return FALSE; + } + + if ((error = ibus_error_from_message (reply)) != NULL) { + g_warning ("%s : %s", error->name, error->message); + ibus_error_free (error); + ibus_message_unref (reply); + return FALSE; + } + + return TRUE; +#endif +} + +GList * +ibus_bus_list_engines (IBusBus *bus) +{ + return NULL; +} + +GList * +ibus_bus_list_active_engines (IBusBus *bus) +{ + return NULL; +} diff --git a/src/ibusbus.h b/src/ibusbus.h new file mode 100644 index 0000000..e548c82 --- /dev/null +++ b/src/ibusbus.h @@ -0,0 +1,97 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_BUS_H_ +#define __IBUS_BUS_H_ + +#include <dbus/dbus.h> +#include "ibusinputcontext.h" +#include "ibusconfig.h" +#include "ibuscomponent.h" + + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_BUS \ + (ibus_bus_get_type ()) +#define IBUS_BUS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_BUS, IBusBus)) +#define IBUS_BUS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_BUS, IBusBusClass)) +#define IBUS_IS_BUS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_BUS)) +#define IBUS_IS_BUS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_BUS)) +#define IBUS_BUS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_BUS, IBusBusClass)) + +G_BEGIN_DECLS + +typedef struct _IBusBus IBusBus; +typedef struct _IBusBusClass IBusBusClass; + +struct _IBusBus { + IBusObject parent; + /* instance members */ +}; + +struct _IBusBusClass { + IBusObjectClass parent; + /* class members */ +}; + +GType ibus_bus_get_type (void); +IBusBus *ibus_bus_new (void); +gboolean ibus_bus_is_connected (IBusBus *bus); +IBusConnection + *ibus_bus_get_connection (IBusBus *bus); +/* declare dbus methods */ +const gchar *ibus_bus_hello (IBusBus *bus); +guint ibus_bus_request_name (IBusBus *bus, + const gchar *name, + guint flags); +guint ibus_bus_release_name (IBusBus *bus, + const gchar *name); +gboolean ibus_bus_name_has_owner (IBusBus *bus, + const gchar *name); +GList *ibus_bus_list_names (IBusBus *bus); +void ibus_bus_add_match (IBusBus *bus, + const gchar *rule); +void ibus_bus_remove_match (IBusBus *bus, + const gchar *rule); +const gchar *ibus_bus_get_name_owner (IBusBus *bus, + const gchar *name); +/* declare ibus methods */ +gboolean ibus_bus_kill (IBusBus *bus); +IBusInputContext + *ibus_bus_create_input_context + (IBusBus *bus, + const gchar *client_name); +gboolean ibus_bus_register_component(IBusBus *bus, + IBusComponent *component); +GList *ibus_bus_list_engines (IBusBus *bus); +GList *ibus_bus_list_active_engines + (IBusBus *bus); + +G_END_DECLS +#endif + diff --git a/src/ibuscomponent.c b/src/ibuscomponent.c new file mode 100644 index 0000000..9ca487d --- /dev/null +++ b/src/ibuscomponent.c @@ -0,0 +1,743 @@ +/* vim:set et sts=4: */ +/* bus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <glib/gstdio.h> +#include "ibuscomponent.h" + +enum { + LAST_SIGNAL, +}; + + +/* IBusComponentPriv */ +struct _IBusComponentPrivate { + gpointer pad; +}; +typedef struct _IBusComponentPrivate IBusComponentPrivate; + +#define IBUS_COMPONENT_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), BUS_TYPE_COMPONENT, IBusComponentPrivate)) + +// static guint _signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_component_class_init (IBusComponentClass *klass); +static void ibus_component_init (IBusComponent *component); +static void ibus_component_destroy (IBusComponent *component); +static gboolean ibus_component_serialize (IBusComponent *component, + IBusMessageIter *iter); +static gboolean ibus_component_deserialize (IBusComponent *component, + IBusMessageIter *iter); +static gboolean ibus_component_copy (IBusComponent *dest, + const IBusComponent *src); +static gboolean ibus_component_parse_xml_node + (IBusComponent *component, + XMLNode *node, + gboolean access_fs); + +static void ibus_component_parse_engines(IBusComponent *component, + XMLNode *node); +static void ibus_component_parse_observed_paths + (IBusComponent *component, + XMLNode *node, + gboolean access_fs); + +static IBusSerializableClass *parent_class = NULL; + +GType +ibus_component_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusComponentClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_component_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusComponent), + 0, + (GInstanceInitFunc) ibus_component_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusComponent", + &type_info, + (GTypeFlags)0); + } + + return type; +} + + +static void +ibus_component_class_init (IBusComponentClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_component_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_component_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_component_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_component_copy; + + g_string_append (serializable_class->signature, "ssssssssavav"); +} + + + +static void +ibus_component_init (IBusComponent *component) +{ + component->name = NULL; + component->description = NULL; + component->version = NULL; + component->license = NULL; + component->author = NULL; + component->homepage = NULL; + component->exec = NULL; + component->textdomain = NULL; + component->engines = NULL; + component->observed_paths = NULL; +} + +static void +ibus_component_destroy (IBusComponent *component) +{ + GList *p; + + g_free (component->name); + g_free (component->description); + g_free (component->version); + g_free (component->license); + g_free (component->author); + g_free (component->homepage); + g_free (component->exec); + g_free (component->textdomain); + + component->name = NULL; + component->description = NULL; + component->version = NULL; + component->license = NULL; + component->author = NULL; + component->homepage = NULL; + component->exec = NULL; + component->textdomain = NULL; + + g_list_foreach (component->observed_paths, (GFunc)g_object_unref, NULL); + g_list_free (component->observed_paths); + component->observed_paths = NULL; + + for (p = component->engines; p != NULL; p = p->next) { + g_object_steal_data ((GObject *)p->data, "component"); + ibus_object_destroy ((IBusObject *)p->data); + g_object_unref (p->data); + } + g_list_free (component->engines); + component->engines = NULL; + + IBUS_OBJECT_CLASS (parent_class)->destroy (IBUS_OBJECT (component)); +} + +static gboolean +ibus_component_serialize (IBusComponent *component, + IBusMessageIter *iter) +{ + gboolean retval; + IBusMessageIter array_iter; + GList *p; + + retval = parent_class->serialize ((IBusSerializable *)component, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &component->name); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &component->description); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &component->version); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &component->license); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &component->author); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &component->homepage); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &component->exec); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &component->textdomain); + g_return_val_if_fail (retval, FALSE); + + /* serialize observed paths */ + retval = ibus_message_iter_open_container (iter, IBUS_TYPE_ARRAY, "v", &array_iter); + g_return_val_if_fail (retval, FALSE); + + for (p = component->observed_paths; p != NULL; p = p->next) { + retval = ibus_message_iter_append (&array_iter, IBUS_TYPE_OBSERVED_PATH, &(p->data)); + g_return_val_if_fail (retval, FALSE); + } + retval = ibus_message_iter_close_container (iter, &array_iter); + g_return_val_if_fail (retval, FALSE); + + /* serialize engine desc */ + retval = ibus_message_iter_open_container (iter, IBUS_TYPE_ARRAY, "v", &array_iter); + g_return_val_if_fail (retval, FALSE); + + for (p = component->engines; p != NULL; p = p->next) { + retval = ibus_message_iter_append (&array_iter, IBUS_TYPE_ENGINE_DESC, &(p->data)); + g_return_val_if_fail (retval, FALSE); + } + retval = ibus_message_iter_close_container (iter, &array_iter); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_component_deserialize (IBusComponent *component, + IBusMessageIter *iter) +{ + gboolean retval; + gchar *str; + IBusMessageIter array_iter; + + retval = parent_class->deserialize ((IBusSerializable *)component, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + component->name = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + component->description = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + component->version = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + component->license = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + component->author = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + component->homepage = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + component->exec = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + component->textdomain = g_strdup (str); + + retval = ibus_message_iter_recurse (iter, IBUS_TYPE_ARRAY, &array_iter); + g_return_val_if_fail (retval, FALSE); + while (ibus_message_iter_get_arg_type (&array_iter) != G_TYPE_INVALID) { + IBusObservedPath *path; + retval = ibus_message_iter_get (&array_iter, IBUS_TYPE_OBSERVED_PATH, &path); + component->observed_paths = g_list_append (component->observed_paths, path); + } + ibus_message_iter_next (iter); + + retval = ibus_message_iter_recurse (iter, IBUS_TYPE_ARRAY, &array_iter); + g_return_val_if_fail (retval, FALSE); + + while (ibus_message_iter_get_arg_type (&array_iter) != G_TYPE_INVALID) { + IBusEngineDesc *engine; + retval = ibus_message_iter_get (&array_iter, IBUS_TYPE_ENGINE_DESC, &engine); + ibus_component_add_engine (component, engine); + } + ibus_message_iter_next (iter); + + return TRUE; +} + +static gboolean +ibus_component_copy (IBusComponent *dest, + const IBusComponent *src) +{ + gboolean retval; + + retval = parent_class->copy ((IBusSerializable *)dest, + (IBusSerializable *)src); + g_return_val_if_fail (retval, FALSE); + + + dest->name = g_strdup (src->name); + dest->description = g_strdup (src->description); + dest->version = g_strdup (src->version); + dest->license = g_strdup (src->license); + dest->author = g_strdup (src->author); + dest->homepage = g_strdup (src->homepage); + dest->exec = g_strdup (src->exec); + dest->textdomain = g_strdup (src->textdomain); + + dest->observed_paths = g_list_copy (src->observed_paths); + g_list_foreach (dest->observed_paths, (GFunc) g_object_ref, NULL); + + dest->engines = g_list_copy (src->engines); + g_list_foreach (dest->engines, (GFunc) g_object_ref, NULL); + + return TRUE; +} + + +#define g_string_append_indent(string, indent) \ + { \ + gint i; \ + for (i = 0; i < (indent); i++) { \ + g_string_append (string, " "); \ + } \ + } + +void +ibus_component_output (IBusComponent *component, + GString *output, + gint indent) +{ + g_assert (IBUS_IS_COMPONENT (component)); + GList *p; + + g_string_append_indent (output, indent); + g_string_append (output, "<component>\n"); + +#define OUTPUT_ENTRY(field, element) \ + { \ + gchar *escape_text = g_markup_escape_text (component->field, -1); \ + g_string_append_indent (output, indent + 1); \ + g_string_append_printf (output, "<"element">%s</"element">\n", \ + escape_text); \ + g_free (escape_text); \ + } +#define OUTPUT_ENTRY_1(name) OUTPUT_ENTRY(name, #name) + OUTPUT_ENTRY_1 (name); + OUTPUT_ENTRY_1 (description); + OUTPUT_ENTRY_1 (version); + OUTPUT_ENTRY_1 (license); + OUTPUT_ENTRY_1 (author); + OUTPUT_ENTRY_1 (homepage); + OUTPUT_ENTRY_1 (exec); + OUTPUT_ENTRY_1 (textdomain); +#undef OUTPUT_ENTRY +#undef OUTPUT_ENTRY_1 + + if (component->observed_paths) { + g_string_append_indent (output, indent + 1); + g_string_append (output, "<observed-paths>\n"); + + for (p = component->observed_paths; p != NULL; p = p->next ) { + IBusObservedPath *path = (IBusObservedPath *) p->data; + + g_string_append_indent (output, indent + 2); + g_string_append_printf (output, "<path mtime=\"%ld\" >%s</path>\n", + path->mtime, + path->path); + } + + g_string_append_indent (output, indent + 1); + g_string_append (output, "</observed-paths>\n"); + } + + ibus_component_output_engines (component, output, indent + 1); + + g_string_append_indent (output, indent); + g_string_append (output, "</component>\n"); +} + +void +ibus_component_output_engines (IBusComponent *component, + GString *output, + gint indent) +{ + g_assert (IBUS_IS_COMPONENT (component)); + g_assert (output); + + GList *p; + + g_string_append_indent (output, indent); + g_string_append (output, "<engines>\n"); + + for (p = component->engines; p != NULL; p = p->next) { + ibus_engine_desc_output ((IBusEngineDesc *)p->data, output, indent + 2); + } + + g_string_append_indent (output, indent); + g_string_append (output, "</engines>\n"); +} + +static gboolean +ibus_component_parse_xml_node (IBusComponent *component, + XMLNode *node, + gboolean access_fs) +{ + g_assert (component); + g_assert (node); + + if (G_UNLIKELY (g_strcmp0 (node->name, "component") != 0)) { + return FALSE; + } + + GList *p; + for (p = node->sub_nodes; p != NULL; p = p->next) { + XMLNode *sub_node = (XMLNode *)p->data; + +#define PARSE_ENTRY(field_name, element_name) \ + if (g_strcmp0 (sub_node->name, element_name) == 0) { \ + if (component->field_name != NULL) { \ + g_free (component->field_name); \ + } \ + component->field_name = g_strdup (sub_node->text); \ + continue; \ + } +#define PARSE_ENTRY_1(name) PARSE_ENTRY (name, #name) + PARSE_ENTRY_1 (name); + PARSE_ENTRY_1 (description); + PARSE_ENTRY_1 (version); + PARSE_ENTRY_1 (license); + PARSE_ENTRY_1 (author); + PARSE_ENTRY_1 (homepage); + PARSE_ENTRY_1 (exec); + PARSE_ENTRY_1 (textdomain); +#undef PARSE_ENTRY +#undef PARSE_ENTRY_1 + + if (g_strcmp0 (sub_node->name, "engines") == 0) { + ibus_component_parse_engines (component, sub_node); + continue; + } + + if (g_strcmp0 (sub_node->name, "observed-paths") == 0) { + ibus_component_parse_observed_paths (component, sub_node, access_fs); + continue; + } + + g_warning ("<component> element contains invalidate element <%s>", sub_node->name); + } + + return TRUE; +} + + +static void +ibus_component_parse_engines (IBusComponent *component, + XMLNode *node) +{ + g_assert (IBUS_IS_COMPONENT (component)); + g_assert (node); + + gchar *exec = NULL; + gchar **p; + XMLNode *engines_node = NULL; + + if (g_strcmp0 (node->name, "engines") != 0) { + return; + } + + for (p = node->attributes; *p != NULL; p += 2) { + if (g_strcmp0 (*p, "exec") == 0) { + exec = *(p + 1); + break; + } + } + + if (exec != NULL) { + gchar *output = NULL; + if (g_spawn_command_line_sync (exec, &output, NULL, NULL, NULL)) { + engines_node = ibus_xml_parse_buffer (output); + g_free (output); + + if (engines_node) { + if (g_strcmp0 (engines_node->name, "engines") != 0) { + ibus_xml_free (engines_node); + engines_node = NULL; + } + } + node = engines_node; + } + } + + GList *pl; + for (pl = node->sub_nodes; pl != NULL; pl = pl->next) { + IBusEngineDesc *engine; + engine = ibus_engine_desc_new_from_xml_node ((XMLNode *)pl->data); + + if (G_UNLIKELY (engine == NULL)) + continue; + ibus_component_add_engine (component, engine); + } + + if (engines_node) { + ibus_xml_free (engines_node); + } +} + +static void +ibus_component_parse_observed_paths (IBusComponent *component, + XMLNode *node, + gboolean access_fs) +{ + g_assert (IBUS_IS_COMPONENT (component)); + g_assert (node); + + if (g_strcmp0 (node->name, "observed-paths") != 0) { + return; + } + + GList *p; + for (p = node->sub_nodes; p != NULL; p = p->next) { + IBusObservedPath *path; + + path = ibus_observed_path_new_from_xml_node ((XMLNode *)p->data, access_fs); + component->observed_paths = g_list_append (component->observed_paths, path); + + if (access_fs && path->is_dir && path->is_exist) { + component->observed_paths = g_list_concat (component->observed_paths, + ibus_observed_path_traverse (path)); + } + } +} + +IBusComponent * +ibus_component_new (const gchar *name, + const gchar *descritpion, + const gchar *version, + const gchar *license, + const gchar *author, + const gchar *homepage, + const gchar *exec, + const gchar *textdomain) +{ + + IBusComponent *component; + component = (IBusComponent *)g_object_new (IBUS_TYPE_COMPONENT, NULL); + + component->name = g_strdup (name); + component->description = g_strdup (descritpion); + component->version = g_strdup (version); + component->license = g_strdup (license); + component->author = g_strdup (author); + component->homepage = g_strdup (homepage); + component->exec = g_strdup (exec); + component->textdomain = g_strdup (textdomain); + + return component; +} + + +IBusComponent * +ibus_component_new_from_xml_node (XMLNode *node) +{ + g_assert (node); + + IBusComponent *component; + + component = (IBusComponent *)g_object_new (IBUS_TYPE_COMPONENT, NULL); + if (!ibus_component_parse_xml_node (component, node, FALSE)) { + g_object_unref (component); + component = NULL; + } + + return component; +} + +IBusComponent * +ibus_component_new_from_file (const gchar *filename) +{ + g_assert (filename); + + XMLNode *node; + struct stat buf; + IBusComponent *component; + gboolean retval; + + if (g_stat (filename, &buf) != 0) { + g_warning ("Can not get stat of file %s", filename); + return NULL; + } + + node = ibus_xml_parse_file (filename); + + if (!node) { + return NULL; + } + + component = (IBusComponent *)g_object_new (IBUS_TYPE_COMPONENT, NULL); + retval = ibus_component_parse_xml_node (component, node, TRUE); + ibus_xml_free (node); + + if (!retval) { + g_object_unref (component); + component = NULL; + } + else { + IBusObservedPath *path; + path = ibus_observed_path_new (filename, TRUE); + component->observed_paths = g_list_prepend (component->observed_paths, path); + } + + return component; +} + +void +ibus_component_add_observed_path (IBusComponent *component, + const gchar *path, + gboolean access_fs) +{ + IBusObservedPath *p; + + p = ibus_observed_path_new (path, access_fs); + component->observed_paths = g_list_append (component->observed_paths, p); + + if (access_fs && p->is_dir && p->is_exist) { + component->observed_paths = g_list_concat (component->observed_paths, + ibus_observed_path_traverse (p)); + } +} + +void +ibus_component_add_engine (IBusComponent *component, + IBusEngineDesc *engine) +{ + g_assert (IBUS_IS_COMPONENT (component)); + g_assert (IBUS_IS_ENGINE_DESC (engine)); + + component->engines = g_list_append (component->engines, engine); + g_object_set_data ((GObject *)engine, "component", component); +} + +GList * +ibus_component_get_engines (IBusComponent *component) +{ + return g_list_copy (component->engines); +} + +static void +ibus_component_child_cb (GPid pid, + gint status, + IBusComponent *component) +{ + g_assert (IBUS_IS_COMPONENT (component)); + g_assert (component->pid == pid); + + g_spawn_close_pid (pid); + component->pid = 0; +} + +gboolean +ibus_component_start (IBusComponent *component) +{ + g_assert (IBUS_IS_COMPONENT (component)); + + if (component->pid != 0) + return TRUE; + + gint argc; + gchar **argv; + gboolean retval; + GError *error; + + error = NULL; + if (!g_shell_parse_argv (component->exec, &argc, &argv, &error)) { + g_warning ("Can not parse component %s exec: %s", component->name, error->message); + g_error_free (error); + return FALSE; + } + + error = NULL; + retval = g_spawn_async (NULL, argv, NULL, + G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, + &(component->pid), &error); + g_strfreev (argv) + ; + if (!retval) { + g_warning ("Can not execute component %s: %s", component->name, error->message); + g_error_free (error); + return FALSE; + } + + g_child_watch_add (component->pid, (GChildWatchFunc) ibus_component_child_cb, component); + + return TRUE; +} + +gboolean +ibus_component_stop (IBusComponent *component) +{ + g_assert (IBUS_IS_COMPONENT (component)); + + if (component->pid == 0) + return TRUE; + + kill (component->pid, SIGTERM); + return TRUE; +} + +gboolean +ibus_component_is_running (IBusComponent *component) +{ + g_assert (IBUS_IS_COMPONENT (component)); + + return (component->pid != 0); +} + + +gboolean +ibus_component_check_modification (IBusComponent *component) +{ + g_assert (IBUS_IS_COMPONENT (component)); + + GList *p; + + for (p = component->observed_paths; p != NULL; p = p->next) { + if (ibus_observed_path_check_modification ((IBusObservedPath *)p->data)) + return TRUE; + } + return FALSE; +} + + +IBusComponent * +ibus_component_get_from_engine (IBusEngineDesc *engine) +{ + g_assert (IBUS_IS_ENGINE_DESC (engine)); + + IBusComponent *component; + + component = (IBusComponent *)g_object_get_data ((GObject *)engine, "component"); + return component; +} diff --git a/src/ibuscomponent.h b/src/ibuscomponent.h new file mode 100644 index 0000000..1d5d25a --- /dev/null +++ b/src/ibuscomponent.h @@ -0,0 +1,115 @@ +/* vim:set et sts=4: */ +/* bus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_COMPONENT_H_ +#define __IBUS_COMPONENT_H_ + +#include "ibusserializable.h" +#include "ibusobservedpath.h" +#include "ibusenginedesc.h" +#include "ibusxml.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_COMPONENT \ + (ibus_component_get_type ()) +#define IBUS_COMPONENT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_COMPONENT, IBusComponent)) +#define IBUS_COMPONENT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_COMPONENT, IBusComponentClass)) +#define IBUS_IS_COMPONENT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_COMPONENT)) +#define IBUS_IS_COMPONENT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_COMPONENT)) +#define IBUS_COMPONENT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_COMPONENT, IBusComponentClass)) + +G_BEGIN_DECLS + +typedef struct _IBusComponent IBusComponent; +typedef struct _IBusComponentClass IBusComponentClass; + +struct _IBusComponent { + IBusSerializable parent; + /* instance members */ + + gchar *name; + gchar *description; + gchar *version; + gchar *license; + gchar *author; + gchar *homepage; + gchar *exec; + + /* text domain for dgettext */ + gchar *textdomain; + + /* engines */ + GList *engines; + + /* observed paths */ + GList *observed_paths; + + GPid pid; +}; + +struct _IBusComponentClass { + IBusSerializableClass parent; + + /* class members */ +}; + +GType ibus_component_get_type (void); +IBusComponent *ibus_component_new (const gchar *name, + const gchar *descritpion, + const gchar *version, + const gchar *license, + const gchar *author, + const gchar *homepage, + const gchar *exec, + const gchar *textdomain); +IBusComponent *ibus_component_new_from_xml_node + (XMLNode *node); +IBusComponent *ibus_component_new_from_file (const gchar *filename); +void ibus_component_add_observed_path + (IBusComponent *component, + const gchar *path, + gboolean access_fs); +void ibus_component_add_engine (IBusComponent *component, + IBusEngineDesc *engine); +GList *ibus_component_get_engines (IBusComponent *component); +void ibus_component_output (IBusComponent *component, + GString *output, + gint indent); +void ibus_component_output_engines (IBusComponent *component, + GString *output, + gint indent); +gboolean ibus_component_check_modification + (IBusComponent *component); +gboolean ibus_component_start (IBusComponent *component); +gboolean ibus_component_stop (IBusComponent *component); +gboolean ibus_component_is_running (IBusComponent *component); +IBusComponent *ibus_component_get_from_engine (IBusEngineDesc *engine); + +G_END_DECLS +#endif + diff --git a/src/ibusconfig.c b/src/ibusconfig.c new file mode 100644 index 0000000..9ebc799 --- /dev/null +++ b/src/ibusconfig.c @@ -0,0 +1,357 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "ibusinternal.h" +#include "ibusmarshalers.h" +#include "ibusshare.h" +#include "ibusconfig.h" + +#define IBUS_CONFIG_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_CONFIG, IBusConfigPrivate)) + +enum { + VALUE_CHANGED, + LAST_SIGNAL, +}; + + +/* IBusConfigPriv */ +struct _IBusConfigPrivate { + gpointer pad; +}; +typedef struct _IBusConfigPrivate IBusConfigPrivate; + +#if 0 +struct _BusPair { + GValue car; + GValue cdr; +}; +typedef struct _BusPair BusPair; +#endif + +static guint config_signals[LAST_SIGNAL] = { 0 }; + +#if 0 +/* functions prototype */ +static BusPair *bus_pair_new (GType car_type, + GType cdr_type, + gpointer car, + gpointer cdr); +static BusPair *bus_pair_copy (BusPair *pair); +static void bus_pair_free (BusPair *pair); +#endif +static void ibus_config_class_init (IBusConfigClass *klass); +static void ibus_config_init (IBusConfig *config); +static void ibus_config_real_destroy (IBusConfig *config); + +static gboolean ibus_config_ibus_signal (IBusProxy *proxy, + IBusMessage *message); + +static IBusProxyClass *parent_class = NULL; + +#if 0 +static BusPair * +bus_pair_new (GType car_type, + GType cdr_type, + gpointer car, + gpointer cdr) +{ + + g_assert (car_type == G_TYPE_STRING || + car_type == G_TYPE_INT || + car_type == G_TYPE_BOOLEAN || + car_type == G_TYPE_DOUBLE); + g_assert (cdr_type == G_TYPE_STRING || + cdr_type == G_TYPE_INT || + cdr_type == G_TYPE_BOOLEAN || + cdr_type == G_TYPE_DOUBLE); + g_assert (car != NULL); + g_assert (cdr != NULL); + + BusPair *pair; + + pair = g_slice_new0 (BusPair); + + g_value_init (&(pair->car), car_type); + g_value_init (&(pair->cdr), cdr_type); + + switch (car_type) { + case G_TYPE_STRING: + g_value_set_string (&(pair->car), *(gchar **)car); + break; + case G_TYPE_INT: + g_value_set_int (&(pair->car), *(gint32 *)car); + break; + case G_TYPE_BOOLEAN: + g_value_set_boolean (&(pair->car), *(gboolean *)car); + break; + case G_TYPE_DOUBLE: + g_value_set_double (&(pair->car), *(gdouble *)car); + break; + } + + switch (cdr_type) { + case G_TYPE_STRING: + g_value_set_string (&(pair->cdr), *(gchar **)cdr); + break; + case G_TYPE_INT: + g_value_set_int (&(pair->cdr), *(gint32 *)car); + break; + case G_TYPE_BOOLEAN: + g_value_set_boolean (&(pair->cdr), *(gboolean *)cdr); + break; + case G_TYPE_DOUBLE: + g_value_set_double (&(pair->cdr), *(gdouble *)cdr); + break; + } + return pair; +} + +static BusPair * +bus_pair_copy (BusPair *pair) +{ + g_assert (pair != NULL); + + BusPair *new_pair; + + new_pair = g_slice_new0 (BusPair); + g_value_copy (&(pair->car), &(new_pair->car)); + g_value_copy (&(pair->cdr), &(new_pair->cdr)); + return new_pair; +} + +static void +bus_pair_free (BusPair *pair) +{ + g_assert (pair == NULL); + + g_value_unset (&(pair->car)); + g_value_unset (&(pair->cdr)); + + g_slice_free (BusPair, pair); +} + +#endif + +GType +ibus_config_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusConfigClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_config_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusConfig), + 0, + (GInstanceInitFunc) ibus_config_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_PROXY, + "IBusConfig", + &type_info, + (GTypeFlags)0); + } + return type; +} + +IBusConfig * +ibus_config_new (IBusConnection *connection) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + + GObject *obj; + obj = g_object_new (IBUS_TYPE_CONFIG, + "name", IBUS_SERVICE_CONFIG, + "path", IBUS_PATH_CONFIG, + "connection", connection, + NULL); + + return IBUS_CONFIG (obj); +} + +static void +ibus_config_class_init (IBusConfigClass *klass) +{ + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + IBusProxyClass *proxy_class = IBUS_PROXY_CLASS (klass); + + + parent_class = (IBusProxyClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusConfigPrivate)); + + ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_config_real_destroy; + + proxy_class->ibus_signal = ibus_config_ibus_signal; + + /* install signals */ + config_signals[VALUE_CHANGED] = + g_signal_new (I_("value-changed"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__STRING_STRING_BOXED, + G_TYPE_NONE, + 3, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_VALUE | G_SIGNAL_TYPE_STATIC_SCOPE); +} + +static void +ibus_config_init (IBusConfig *config) +{ + IBusConfigPrivate *priv; + priv = IBUS_CONFIG_GET_PRIVATE (config); +} + +static void +ibus_config_real_destroy (IBusConfig *config) +{ + if (ibus_proxy_get_connection ((IBusProxy *) config) != NULL) { + ibus_proxy_call ((IBusProxy *) config, + "Destroy", + G_TYPE_INVALID); + } + + IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (config)); +} + + +static gboolean +ibus_config_ibus_signal (IBusProxy *proxy, + IBusMessage *message) +{ + g_assert (IBUS_IS_CONFIG (proxy)); + g_assert (message != NULL); + + IBusConfig *config; + config = IBUS_CONFIG (proxy); + + if (ibus_message_is_signal (message, IBUS_INTERFACE_CONFIG, "ValueChanged")) { + gchar *section; + gchar *name; + GValue value = { 0 }; + IBusError *error = NULL; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_STRING, §ion, + G_TYPE_STRING, &name, + G_TYPE_VALUE, &value, + G_TYPE_INVALID); + if (!retval) { + g_warning ("%s: Can not parse arguments of ValueChanges.", DBUS_ERROR_INVALID_ARGS); + return FALSE; + } + + g_signal_emit (config, + config_signals[VALUE_CHANGED], + 0, + section, + name, + &value); + g_value_unset (&value); + + g_signal_stop_emission_by_name (config, "ibus-signal"); + + return TRUE; + } + + return FALSE; +} + +gboolean +ibus_config_get_value (IBusConfig *config, + const gchar *section, + const gchar *name, + GValue *value) +{ + g_assert (IBUS_IS_CONFIG (config)); + g_assert (section != NULL); + g_assert (name != NULL); + g_assert (value != NULL); + + IBusMessage *reply; + IBusError *error; + gboolean retval; + + reply = ibus_proxy_call_with_reply_and_block ((IBusProxy *) config, + "GetValue", + -1, + &error, + G_TYPE_STRING, §ion, + G_TYPE_STRING, &name, + G_TYPE_INVALID); + if (reply == NULL) { + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + return FALSE; + } + + if ((error = ibus_error_new_from_message (reply)) != NULL) { + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + ibus_message_unref (reply); + return FALSE; + } + + retval = ibus_message_get_args (reply, + &error, + G_TYPE_VALUE, value, + G_TYPE_INVALID); + ibus_message_unref (reply); + if (!retval) { + g_warning ("%s: %s", error->name, error->message); + return FALSE; + } + + return TRUE; +} + +gboolean +ibus_config_set_value (IBusConfig *config, + const gchar *section, + const gchar *name, + const GValue *value) +{ + g_assert (IBUS_IS_CONFIG (config)); + g_assert (section != NULL); + g_assert (name != NULL); + g_assert (value != NULL); + + gboolean retval; + + retval = ibus_proxy_call ((IBusProxy *) config, + "SetValue", + G_TYPE_STRING, §ion, + G_TYPE_STRING, &name, + G_TYPE_VALUE, value, + G_TYPE_INVALID); + g_assert (retval); + return TRUE; +} diff --git a/src/ibusconfig.h b/src/ibusconfig.h new file mode 100644 index 0000000..734218f --- /dev/null +++ b/src/ibusconfig.h @@ -0,0 +1,70 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __CONFIG_H_ +#define __CONFIG_H_ + +#include "ibusproxy.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_CONFIG \ + (ibus_config_get_type ()) +#define IBUS_CONFIG(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_CONFIG, IBusConfig)) +#define IBUS_CONFIG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_CONFIG, IBusConfigClass)) +#define IBUS_IS_CONFIG(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_CONFIG)) +#define IBUS_IS_CONFIG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_CONFIG)) +#define IBUS_CONFIG_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_CONFIG, IBusConfigClass)) + +G_BEGIN_DECLS + +typedef struct _IBusConfig IBusConfig; +typedef struct _IBusConfigClass IBusConfigClass; + +struct _IBusConfig { + IBusProxy parent; + /* instance members */ +}; + +struct _IBusConfigClass { + IBusProxyClass parent; + /* class members */ +}; + +GType ibus_config_get_type (void); +IBusConfig *ibus_config_new (IBusConnection *connection); +gboolean ibus_config_get_value (IBusConfig *config, + const gchar *section, + const gchar *name, + GValue *value); +gboolean ibus_config_set_value (IBusConfig *config, + const gchar *section, + const gchar *name, + const GValue *value); +G_END_DECLS +#endif + diff --git a/src/ibusconfigprivate.h b/src/ibusconfigprivate.h new file mode 100644 index 0000000..0bd3b8e --- /dev/null +++ b/src/ibusconfigprivate.h @@ -0,0 +1,221 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_CONFIG_PRIVATE_H_ +#define __IBUS_CONFIG_PRIVATE_H_ + +static void +_from_dbus_value (IBusMessageIter *iter, + GValue *value) +{ + g_assert (iter != NULL); + g_assert (value != NULL); + + gint type; + IBusMessageIter sub_iter; + + type = ibus_message_iter_get_arg_type (iter); + if (type == IBUS_TYPE_VARIANT) { + ibus_message_iter_recurse (iter, IBUS_TYPE_VARIANT, &sub_iter); + ibus_message_iter_next (iter); + iter = &sub_iter; + type = ibus_message_iter_get_arg_type (iter); + } + + switch (type) { + case G_TYPE_STRING: + { + gchar *v; + g_value_init (value, G_TYPE_STRING); + ibus_message_iter_get_basic (iter, &v); + g_value_set_string (value, v); + } + break; + case G_TYPE_INT: + { + gint v; + g_value_init (value, G_TYPE_INT); + ibus_message_iter_get_basic (iter, &v); + g_value_set_int (value, v); + } + break; + case G_TYPE_UINT: + { + guint v; + g_value_init (value, G_TYPE_UINT); + ibus_message_iter_get_basic (iter, &v); + g_value_set_uint (value, v); + } + break; + case G_TYPE_BOOLEAN: + { + gboolean v; + g_value_init (value, G_TYPE_BOOLEAN); + ibus_message_iter_get_basic (iter, &v); + g_value_set_boolean (value, v); + } + break; + case G_TYPE_DOUBLE: + { + gdouble v; + g_value_init (value, G_TYPE_DOUBLE); + ibus_message_iter_get_basic (iter, &v); + g_value_set_double (value, v); + } + break; + default: + if (type == IBUS_TYPE_ARRAY) { + GValue v = { 0 }; + IBusMessageIter sub_iter; + gint sub_type; + GValueArray *array; + + + sub_type = ibus_message_iter_get_element_type (iter); + g_assert (sub_type == G_TYPE_STRING || + sub_type == G_TYPE_INT || + sub_type == G_TYPE_UINT || + sub_type == G_TYPE_BOOLEAN || + sub_type == G_TYPE_DOUBLE || + sub_type == IBUS_TYPE_VARIANT); + + g_value_init (value, G_TYPE_VALUE_ARRAY); + array = g_value_array_new (0); + ibus_message_iter_recurse (iter, IBUS_TYPE_ARRAY, &sub_iter); + while (ibus_message_iter_get_arg_type (&sub_iter) != G_TYPE_INVALID) { + _from_dbus_value (&sub_iter, &v); + g_value_array_append (array, &v); + g_value_unset (&v); + } + g_value_take_boxed (value, array); + ibus_message_iter_next (iter); + break; + } + + g_debug ("type=%s", g_type_name (type)); + + g_assert_not_reached(); + } +} + +static void +_to_dbus_value (IBusMessageIter *iter, + const GValue *value) +{ + IBusMessageIter sub_iter; + gboolean retval; + + + switch (G_VALUE_TYPE (value)) { + case G_TYPE_STRING: + { + retval = ibus_message_iter_open_container (iter, IBUS_TYPE_VARIANT, "s", &sub_iter); + g_assert (retval); + + const gchar *v = g_value_get_string (value); + ibus_message_iter_append (&sub_iter, + G_TYPE_STRING, + &v); + ibus_message_iter_close_container (iter, &sub_iter); + } + break; + case G_TYPE_INT: + { + retval = ibus_message_iter_open_container (iter, IBUS_TYPE_VARIANT, "i", &sub_iter); + g_assert (retval); + + gint v = g_value_get_int (value); + ibus_message_iter_append (&sub_iter, + G_TYPE_INT, + &v); + ibus_message_iter_close_container (iter, &sub_iter); + } + break; + case G_TYPE_UINT: + { + retval = ibus_message_iter_open_container (iter, IBUS_TYPE_VARIANT, "u", &sub_iter); + g_assert (retval); + + guint v = g_value_get_uint (value); + ibus_message_iter_append (&sub_iter, + G_TYPE_UINT, + &v); + ibus_message_iter_close_container (iter, &sub_iter); + } + break; + case G_TYPE_BOOLEAN: + { + retval = ibus_message_iter_open_container (iter, IBUS_TYPE_VARIANT, "b", &sub_iter); + g_assert (retval); + + gboolean v = g_value_get_boolean (value); + ibus_message_iter_append (&sub_iter, + G_TYPE_BOOLEAN, + &v); + ibus_message_iter_close_container (iter, &sub_iter); + } + break; + case G_TYPE_DOUBLE: + { + retval = ibus_message_iter_open_container (iter, IBUS_TYPE_VARIANT, "d", &sub_iter); + g_assert (retval); + + gdouble v = g_value_get_double (value); + ibus_message_iter_append (&sub_iter, + G_TYPE_DOUBLE, + &v); + ibus_message_iter_close_container (iter, &sub_iter); + } + break; + default: + if (G_TYPE_VALUE_ARRAY == G_VALUE_TYPE (value)) { + IBusMessageIter sub_sub_iter; + GType type = G_TYPE_INVALID; + gint i; + + retval = ibus_message_iter_open_container (iter, IBUS_TYPE_VARIANT, "av", &sub_iter); + g_assert (retval); + + GValueArray *array = (GValueArray *)g_value_get_boxed (value); + ibus_message_iter_open_container (&sub_iter, + IBUS_TYPE_ARRAY, + "v", + &sub_sub_iter); + if (array->n_values > 0) { + type = G_VALUE_TYPE (&array->values[0]); + g_assert (type == G_TYPE_STRING || + type == G_TYPE_INT || + type == G_TYPE_UINT || + type == G_TYPE_BOOLEAN || + type == G_TYPE_DOUBLE); + } + for (i = 0; i < array->n_values; i++) { + g_assert (type == G_VALUE_TYPE (&array->values[i])); + _to_dbus_value (&sub_sub_iter, &array->values[i]); + } + ibus_message_iter_close_container (&sub_iter, &sub_sub_iter); + ibus_message_iter_close_container (iter, &sub_iter); + break; + } + g_assert_not_reached(); + } + +} +#endif + diff --git a/src/ibusconfigservice.c b/src/ibusconfigservice.c new file mode 100644 index 0000000..6465add --- /dev/null +++ b/src/ibusconfigservice.c @@ -0,0 +1,314 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "ibusshare.h" +#include "ibusconfigservice.h" + +enum { + LAST_SIGNAL, +}; + +enum { + PROP_0, + PROP_CONNECTION, +}; + +// static guint config_service_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_config_service_class_init (IBusConfigServiceClass *klass); +static void ibus_config_service_init (IBusConfigService *config); +static void ibus_config_service_set_property (IBusConfigService *config, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void ibus_config_service_get_property (IBusConfigService *config, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void ibus_config_service_destroy (IBusConfigService *config); +static gboolean ibus_config_service_ibus_message (IBusConfigService *config, + IBusConnection *connection, + IBusMessage *message); +static gboolean ibus_config_service_set_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + const GValue *value, + IBusError **error); +static gboolean ibus_config_service_get_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GValue *value, + IBusError **error); + +static IBusServiceClass *parent_class = NULL; + +GType +ibus_config_service_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusConfigServiceClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_config_service_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusConfigService), + 0, + (GInstanceInitFunc) ibus_config_service_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERVICE, + "IBusConfigService", + &type_info, + (GTypeFlags) 0); + } + return type; +} + +IBusConfigService * +ibus_config_service_new (IBusConnection *connection) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + + IBusConfigService *config; + + config = (IBusConfigService *) g_object_new (IBUS_TYPE_CONFIG_SERVICE, + "path", IBUS_PATH_CONFIG, + "connection", connection, + NULL); + + return config; +} + +static void +ibus_config_service_class_init (IBusConfigServiceClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + parent_class = (IBusServiceClass *) g_type_class_peek_parent (klass); + + gobject_class->set_property = (GObjectSetPropertyFunc) ibus_config_service_set_property; + gobject_class->get_property = (GObjectGetPropertyFunc) ibus_config_service_get_property; + + IBUS_OBJECT_CLASS (gobject_class)->destroy = (IBusObjectDestroyFunc) ibus_config_service_destroy; + + IBUS_SERVICE_CLASS (klass)->ibus_message = (ServiceIBusMessageFunc) ibus_config_service_ibus_message; + + klass->set_value = ibus_config_service_set_value; + klass->get_value = ibus_config_service_get_value; + + g_object_class_install_property (gobject_class, + PROP_CONNECTION, + g_param_spec_object ("connection", + "connection", + "The connection of config object", + IBUS_TYPE_CONNECTION, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} + +static void +ibus_config_service_init (IBusConfigService *config) +{ +} + +static void +ibus_config_service_set_property (IBusConfigService *config, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_CONNECTION: + ibus_service_add_to_connection ((IBusService *) config, + g_value_get_object (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (config, prop_id, pspec); + } +} + +static void +ibus_config_service_get_property (IBusConfigService *config, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_CONNECTION: + { + GList *connections = ibus_service_get_connections ((IBusService *) config); + if (connections) { + g_value_set_object (value, connections->data); + } + else { + g_value_set_object (value, NULL); + } + g_list_foreach (connections, (GFunc) g_object_unref, NULL); + g_list_free (connections); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (config, prop_id, pspec); + } +} + +static void +ibus_config_service_destroy (IBusConfigService *config) +{ + IBUS_OBJECT_CLASS(parent_class)->destroy ((IBusObject *) config); +} + +static gboolean +ibus_config_service_ibus_message (IBusConfigService *config, + IBusConnection *connection, + IBusMessage *message) +{ + g_assert (IBUS_IS_CONFIG_SERVICE (config)); + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (message != NULL); + + IBusMessage *reply = NULL; + + if (ibus_message_is_method_call (message, IBUS_INTERFACE_CONFIG, "SetValue")) { + gchar *section; + gchar *name; + GValue value = { 0 }; + IBusError *error = NULL; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_STRING, §ion, + G_TYPE_STRING, &name, + G_TYPE_VALUE, &value, + G_TYPE_INVALID); + if (!retval) { + reply = ibus_message_new_error_printf (message, + DBUS_ERROR_INVALID_ARGS, + "Can not parse arguments 1 of SetValue"); + ibus_error_free (error); + } + else if (!IBUS_CONFIG_SERVICE_GET_CLASS (config)->set_value (config, section, name, &value, &error)) { + reply = ibus_message_new_error (message, + error->name, + error->message); + ibus_error_free (error); + } + else { + reply = ibus_message_new_method_return (message); + } + } + else if (ibus_message_is_method_call (message, IBUS_INTERFACE_CONFIG, "GetValue")) { + gchar *section; + gchar *name; + GValue value = { 0 }; + IBusError *error = NULL; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_STRING, §ion, + G_TYPE_STRING, &name, + G_TYPE_INVALID); + + if (!retval) { + reply = ibus_message_new_error (message, + error->name, + error->message); + ibus_error_free (error); + } + else if (!IBUS_CONFIG_SERVICE_GET_CLASS (config)->get_value (config, section, name, &value, &error)) { + reply = ibus_message_new_error (message, + error->name, + error->message); + ibus_error_free (error); + } + else { + reply = ibus_message_new_method_return (message); + ibus_message_append_args (reply, + G_TYPE_VALUE, &value, + G_TYPE_INVALID); + g_value_unset (&value); + } + } + + if (reply) { + ibus_connection_send (connection, reply); + ibus_message_unref (reply); + return TRUE; + } + + return parent_class->ibus_message ((IBusService *) config, connection, message); +} + +static gboolean +ibus_config_service_set_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + const GValue *value, + IBusError **error) +{ + if (error) { + *error = ibus_error_new_from_printf (DBUS_ERROR_FAILED, + "Can not set value [%s, %s]", + section, name); + } + return FALSE; +} + +static gboolean +ibus_config_service_get_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GValue *value, + IBusError **error) +{ + if (error) { + *error = ibus_error_new_from_printf (DBUS_ERROR_FAILED, + "Can not get value [%s, %s]", + section, name); + } + return FALSE; +} + +void +ibus_config_service_value_changed (IBusConfigService *config, + const gchar *section, + const gchar *name, + const GValue *value) +{ + g_assert (IBUS_IS_CONFIG_SERVICE (config)); + g_assert (section); + g_assert (name); + g_assert (G_IS_VALUE (value)); + + ibus_service_send_signal ((IBusService *) config, + IBUS_INTERFACE_CONFIG, + "ValueChanged", + G_TYPE_STRING, §ion, + G_TYPE_STRING, &name, + G_TYPE_VALUE, value, + G_TYPE_INVALID); +} diff --git a/src/ibusconfigservice.h b/src/ibusconfigservice.h new file mode 100644 index 0000000..f04a5eb --- /dev/null +++ b/src/ibusconfigservice.h @@ -0,0 +1,85 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_CONFIG_SERVICE_H_ +#define __IBUS_CONFIG_SERVICE_H_ + +#include "ibuserror.h" +#include "ibusservice.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_CONFIG_SERVICE \ + (ibus_config_service_get_type ()) +#define IBUS_CONFIG_SERVICE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_CONFIG_SERVICE, IBusConfigService)) +#define IBUS_CONFIG_SERVICE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_CONFIG_SERVICE, IBusConfigServiceClass)) +#define IBUS_IS_CONFIG_SERVICE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_CONFIG_SERVICE)) +#define IBUS_IS_CONFIG_SERVICE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_CONFIG_SERVICE)) +#define IBUS_CONFIG_SERVICE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_CONFIG_SERVICE, IBusConfigServiceClass)) + +G_BEGIN_DECLS + +typedef struct _IBusConfigService IBusConfigService; +typedef struct _IBusConfigServiceClass IBusConfigServiceClass; + +struct _IBusConfigService { + IBusService parent; + + /* instance members */ +}; + +struct _IBusConfigServiceClass { + IBusServiceClass parent; + + /* class members */ + gboolean (* set_value) (IBusConfigService *config, + const gchar *section, + const gchar *name, + const GValue *value, + IBusError **error); + gboolean (* get_value) (IBusConfigService *config, + const gchar *section, + const gchar *name, + GValue *value, + IBusError **error); + + /*< private >*/ + /* padding */ + gpointer pdummy[14]; +}; + +GType ibus_config_service_get_type (void); +IBusConfigService *ibus_config_service_new (IBusConnection *connection); +void ibus_config_service_value_changed + (IBusConfigService *config, + const gchar *section, + const gchar *name, + const GValue *value); + +G_END_DECLS +#endif + diff --git a/src/ibusconnection.c b/src/ibusconnection.c new file mode 100644 index 0000000..90776cd --- /dev/null +++ b/src/ibusconnection.c @@ -0,0 +1,697 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include <stdarg.h> +#include "ibusmessage.h" +#include "ibusconnection.h" +#include "ibusinternal.h" + +#define IBUS_CONNECTION_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_CONNECTION, IBusConnectionPrivate)) + +enum { + IBUS_SIGNAL, + IBUS_MESSAGE, + IBUS_MESSAGE_SENT, + DISCONNECTED, + LAST_SIGNAL, +}; + + +/* IBusConnectionPriv */ +struct _IBusConnectionPrivate { + DBusConnection *connection; + gboolean shared; +}; +typedef struct _IBusConnectionPrivate IBusConnectionPrivate; + +static guint connection_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_connection_class_init (IBusConnectionClass *klass); +static void ibus_connection_init (IBusConnection *connection); +static void ibus_connection_destroy (IBusConnection *connection); + +static gboolean ibus_connection_ibus_message(IBusConnection *connection, + IBusMessage *message); +static gboolean ibus_connection_ibus_signal (IBusConnection *connection, + IBusMessage *message); +static void ibus_connection_disconnected(IBusConnection *connection); +static DBusHandlerResult + _connection_handle_message_cb(DBusConnection *dbus_connection, + IBusMessage *message, + IBusConnection *connection); + +static IBusObjectClass *parent_class = NULL; +static GHashTable *_connections = NULL; + +GType +ibus_connection_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusConnectionClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_connection_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusConnection), + 0, + (GInstanceInitFunc) ibus_connection_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_OBJECT, + "IBusConnection", + &type_info, + (GTypeFlags)0); + } + + return type; +} + +IBusConnection * +ibus_connection_new (void) +{ + GObject *object; + object = g_object_new (IBUS_TYPE_CONNECTION, NULL); + return IBUS_CONNECTION (object); +} + +static void +ibus_connection_class_init (IBusConnectionClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + + parent_class = (IBusObjectClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusConnectionPrivate)); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_connection_destroy; + + klass->ibus_message = ibus_connection_ibus_message; + klass->ibus_signal = ibus_connection_ibus_signal; + klass->disconnected = ibus_connection_disconnected; + + connection_signals[IBUS_MESSAGE] = + g_signal_new (I_("ibus-message"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusConnectionClass, ibus_message), + NULL, NULL, + ibus_marshal_BOOLEAN__POINTER, + G_TYPE_BOOLEAN, 1, + G_TYPE_POINTER); + + connection_signals[IBUS_SIGNAL] = + g_signal_new (I_("ibus-signal"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusConnectionClass, ibus_signal), + NULL, NULL, + ibus_marshal_BOOL__POINTER, + G_TYPE_BOOLEAN, 1, + G_TYPE_POINTER); + + connection_signals[IBUS_MESSAGE_SENT] = + g_signal_new (I_("ibus-message-sent"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusConnectionClass, ibus_message_sent), + NULL, NULL, + ibus_marshal_VOID__POINTER, + G_TYPE_NONE, 1, + G_TYPE_POINTER); + + connection_signals[DISCONNECTED] = + g_signal_new (I_("disconnected"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusConnectionClass, disconnected), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + +} + +static void +ibus_connection_init (IBusConnection *connection) +{ + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + priv->connection = NULL; + priv->shared = FALSE; +} + +static void +ibus_connection_destroy (IBusConnection *connection) +{ + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + if (priv->connection) { + dbus_connection_remove_filter (priv->connection, + (DBusHandleMessageFunction) _connection_handle_message_cb, + connection); + } + + if (!priv->shared && priv->connection) { + dbus_connection_close (priv->connection); + dbus_connection_unref (priv->connection); + priv->connection = NULL; + goto _out; + } + + if (priv->shared && priv->connection) { + g_warn_if_fail (_connections != NULL); + if (_connections != NULL) { + g_hash_table_remove (_connections, priv->connection); + } + dbus_connection_unref (priv->connection); + priv->connection = NULL; + goto _out; + } +_out: + parent_class->destroy (IBUS_OBJECT (connection)); +} + +static gboolean +ibus_connection_ibus_message (IBusConnection *connection, + IBusMessage *message) +{ + gboolean retval = FALSE; + + if (ibus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL) + g_signal_emit (connection, connection_signals[IBUS_SIGNAL], 0, message, &retval); + + return retval; +} + +static gboolean +ibus_connection_ibus_signal (IBusConnection *connection, IBusMessage *message) +{ + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + if (ibus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected")) { + g_signal_emit (connection, connection_signals[DISCONNECTED], 0); + return FALSE; + } + return FALSE; +} + +static void +ibus_connection_disconnected (IBusConnection *connection) +{ + ibus_object_destroy (IBUS_OBJECT (connection)); +} + +static DBusHandlerResult +_connection_handle_message_cb (DBusConnection *dbus_connection, + IBusMessage *message, + IBusConnection *connection) +{ + gboolean retval = FALSE; + + gint type; + + type = ibus_message_get_type (message); + g_signal_emit (connection, connection_signals[IBUS_MESSAGE], 0, message, &retval); + + if (retval) + return DBUS_HANDLER_RESULT_HANDLED; + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static gint +_get_slot () +{ + static gint slot = -1; + if (slot == -1) { + dbus_connection_allocate_data_slot (&slot); + } + return slot; +} + +void +ibus_connection_set_connection (IBusConnection *connection, DBusConnection *dbus_connection, gboolean shared) +{ + gboolean result; + IBusConnectionPrivate *priv; + + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (dbus_connection != NULL); + g_assert (dbus_connection_get_is_connected (dbus_connection)); + + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + g_assert (priv->connection == NULL); + + priv->connection = dbus_connection_ref (dbus_connection); + priv->shared = shared; + + dbus_connection_set_data (priv->connection, _get_slot(), connection, NULL); + + result = dbus_connection_add_filter (priv->connection, + (DBusHandleMessageFunction) _connection_handle_message_cb, + connection, NULL); + + dbus_connection_setup (priv->connection, NULL); + g_warn_if_fail (result); +} + +IBusConnection * +ibus_connection_open (const gchar *address) +{ + g_assert (address != NULL); + + DBusError error; + DBusConnection *dbus_connection; + IBusConnection *connection; + + if (_connections == NULL) { + _connections = g_hash_table_new (g_direct_hash, g_direct_equal); + } + + + dbus_error_init (&error); + dbus_connection = dbus_connection_open (address, &error); + if (dbus_connection == NULL) { + g_warning ("Connect to %s failed. %s.", address, error.message); + dbus_error_free (&error); + return NULL; + } + + connection = g_hash_table_lookup (_connections, dbus_connection); + + if (connection) { + dbus_connection_unref (dbus_connection); + g_object_ref (connection); + return connection; + } + + connection = ibus_connection_new (); + ibus_connection_set_connection (connection, dbus_connection, TRUE); + g_hash_table_insert (_connections, dbus_connection, connection); + + return connection; +} + +IBusConnection * +ibus_connection_open_private (const gchar *address) +{ + g_assert (address != NULL); + + DBusError error; + DBusConnection *dbus_connection; + IBusConnection *connection; + + dbus_error_init (&error); + dbus_connection = dbus_connection_open_private (address, &error); + if (dbus_connection == NULL) { + g_warning ("Connect to %s failed. %s.", address, error.message); + dbus_error_free (&error); + return NULL; + } + + connection = ibus_connection_new (); + ibus_connection_set_connection (connection, dbus_connection, FALSE); + + return connection; +} + +void ibus_connection_close (IBusConnection *connection) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + dbus_connection_close (priv->connection); +} + +gboolean +ibus_connection_is_connected (IBusConnection *connection) +{ + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + if (priv->connection == NULL) { + return FALSE; + } + return dbus_connection_get_is_connected (priv->connection); +} + +DBusConnection * +ibus_connection_get_connection (IBusConnection *connection) +{ + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + return priv->connection; +} + +typedef struct _VTableCallData { + IBusMessageFunc message_func; + gpointer user_data; +}VTableCallData; + +void +_unregister_function (DBusConnection *dbus_connection, VTableCallData *data) +{ + g_slice_free (VTableCallData, data); +} + +DBusHandlerResult +_message_function (DBusConnection *dbus_connection, + DBusMessage *message, + VTableCallData *data) +{ + gboolean retval; + IBusConnection *connection; + + connection = IBUS_CONNECTION (dbus_connection_get_data (dbus_connection, _get_slot())); + retval = data->message_func (connection, message, data->user_data); + + return retval ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +gboolean +ibus_connection_register_object_path (IBusConnection *connection, + const gchar *path, IBusMessageFunc message_func, gpointer user_data) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (path != NULL); + g_assert (message_func != NULL); + + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + gboolean retval; + DBusObjectPathVTable vtable = {0}; + VTableCallData *data; + + vtable.unregister_function = (DBusObjectPathUnregisterFunction) _unregister_function; + vtable.message_function = (DBusObjectPathMessageFunction) _message_function; + + data = g_slice_new (VTableCallData); + data->message_func = message_func; + data->user_data = user_data; + + retval = dbus_connection_register_object_path (priv->connection, path, &vtable, data); + if (!retval) { + g_warning ("Out of memory!"); + return FALSE; + } + return TRUE; +} + +gboolean +ibus_connection_unregister_object_path (IBusConnection *connection, const gchar *path) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (path != NULL); + + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + gboolean retval; + + retval = dbus_connection_unregister_object_path (priv->connection, path); + if (!retval) { + g_warning ("Out of memory!"); + return FALSE; + } + + return TRUE; +} + + +gboolean +ibus_connection_send (IBusConnection *connection, + IBusMessage *message) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (message != NULL); + + gboolean retval; + IBusConnectionPrivate *priv; + + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + retval = dbus_connection_send (priv->connection, message, NULL); + + if (retval) { + g_signal_emit (connection, + connection_signals[IBUS_MESSAGE_SENT], + 0, + message); + } + + return retval; +} + + +gboolean +ibus_connection_send_signal (IBusConnection *connection, + const gchar *path, + const gchar *interface, + const gchar *name, + GType first_arg_type, + ...) +{ + va_list args; + gboolean retval; + + va_start (args, first_arg_type); + retval = ibus_connection_send_signal_valist (connection, + path, + interface, + name, + first_arg_type, + args); + va_end (args); + return retval; +} + +gboolean +ibus_connection_send_signal_valist (IBusConnection *connection, + const gchar *path, + const gchar *interface, + const gchar *name, + GType first_arg_type, + va_list args) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (interface != NULL); + g_assert (name != NULL); + + gboolean retval; + IBusMessage *message; + + message = ibus_message_new_signal (path, interface, name); + + ibus_message_append_args_valist (message, first_arg_type, args); + retval = ibus_connection_send (connection, message); + ibus_message_unref (message); + + return retval; +} + +gboolean +ibus_connection_send_valist (IBusConnection *connection, + gint message_type, + const gchar *path, + const gchar *interface, + const gchar *name, + GType first_arg_type, + va_list args) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (interface != NULL); + g_assert (name != NULL); + + gboolean retval; + IBusMessage *message; + + message = ibus_message_new (message_type); + ibus_message_set_path (message, path); + ibus_message_set_interface (message, interface); + ibus_message_set_member (message, name); + + ibus_message_append_args_valist (message, first_arg_type, args); + retval = ibus_connection_send (connection, message); + ibus_message_unref (message); + + return retval; +} + +gboolean +ibus_connection_send_with_reply (IBusConnection *connection, + IBusMessage *message, + IBusPendingCall **pending_return, + gint timeout_milliseconds) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (message != NULL); + g_assert (pending_return != NULL); + g_assert (timeout_milliseconds > 0 || timeout_milliseconds == -1); + + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + return dbus_connection_send_with_reply (priv->connection, + message, + pending_return, + timeout_milliseconds); +} + +IBusMessage * +ibus_connection_send_with_reply_and_block (IBusConnection *connection, + IBusMessage *message, + gint timeout_milliseconds, + IBusError **error) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (message != NULL); + g_assert (timeout_milliseconds > 0 || timeout_milliseconds == -1); + + IBusError *_error; + IBusMessage *reply; + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + _error = ibus_error_new (); + + reply = dbus_connection_send_with_reply_and_block (priv->connection, + message, + timeout_milliseconds, + _error); + + if (reply != NULL) { + g_signal_emit (connection, + connection_signals[IBUS_MESSAGE_SENT], + 0, + message); + } + + if (reply == NULL && error != NULL) { + *error = _error; + } + else + ibus_error_free (_error); + + return reply; +} + +gboolean +ibus_connection_call (IBusConnection *connection, + const gchar *name, + const gchar *path, + const gchar *interface, + const gchar *member, + IBusError **error, + GType first_arg_type, + ...) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (name != NULL); + g_assert (path != NULL); + g_assert (interface != NULL); + g_assert (member != NULL); + + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + g_assert (dbus_connection_get_is_connected (priv->connection)); + + IBusMessage *message, *reply; + IBusError *tmp_error; + va_list args; + GType type; + gboolean retval; + + message = ibus_message_new_method_call (name, path, interface, member); + + va_start (args, first_arg_type); + + ibus_message_append_args_valist (message, first_arg_type, args); + + va_end (args); + + reply = ibus_connection_send_with_reply_and_block ( + connection, + message, + -1, + error); + ibus_message_unref (message); + + if (reply == NULL) { + return FALSE; + } + + if ((tmp_error = ibus_error_new_from_message (reply)) != NULL) { + if (error) { + *error = tmp_error; + } + else + ibus_error_free (tmp_error); + ibus_message_unref (reply); + return FALSE; + } + + va_start (args, first_arg_type); + + type = first_arg_type; + + while (type != DBUS_TYPE_INVALID) { + va_arg (args, gpointer); + type = va_arg (args, GType); + } + type = va_arg (args, GType); + + if (type != G_TYPE_INVALID) { + retval = ibus_message_get_args_valist (reply, error, type, args); + } + + va_end (args); + + ibus_message_unref (reply); + + if (!retval) { + return FALSE; + } + + return TRUE; +} + +void +ibus_connection_flush (IBusConnection *connection) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (ibus_connection_is_connected (connection)); + + IBusConnectionPrivate *priv; + + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + dbus_connection_flush (priv->connection); +} diff --git a/src/ibusconnection.h b/src/ibusconnection.h new file mode 100644 index 0000000..e4a70f7 --- /dev/null +++ b/src/ibusconnection.h @@ -0,0 +1,147 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_CONNECTION_H_ +#define __IBUS_CONNECTION_H_ + +#include <dbus/dbus.h> +#include "ibusmessage.h" +#include "ibuspendingcall.h" +#include "ibusobject.h" +#include "ibuserror.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_CONNECTION \ + (ibus_connection_get_type ()) +#define IBUS_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_CONNECTION, IBusConnection)) +#define IBUS_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_CONNECTION, IBusConnectionClass)) +#define IBUS_IS_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_CONNECTION)) +#define IBUS_IS_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_CONNECTION)) +#define IBUS_CONNECTION_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_CONNECTION, IBusConnectionClass)) + +G_BEGIN_DECLS + +typedef struct _IBusConnection IBusConnection; +typedef struct _IBusConnectionClass IBusConnectionClass; + +typedef gboolean (* IBusIBusMessageFunc)(IBusConnection *connection, + IBusMessage *message); +typedef gboolean (* IBusIBusSignalFunc) (IBusConnection *connection, + IBusMessage *message); +typedef gboolean (* IBusMessageFunc) (IBusConnection *connection, + IBusMessage *message, + gpointer user_data); +typedef void (* IBusConnectionReplyFunc) + (IBusConnection *connection, + IBusMessage *reply, + gpointer user_data); + +struct _IBusConnection { + IBusObject parent; + /* instance members */ +}; + +struct _IBusConnectionClass { + IBusObjectClass parent; + + /* signals */ + gboolean (* ibus_message) (IBusConnection *connection, + IBusMessage *message); + gboolean (* ibus_signal) (IBusConnection *connection, + IBusMessage *message); + void (* ibus_message_sent) + (IBusConnection *connection, + IBusMessage *message); + void (* disconnected) (IBusConnection *connection); + + /*< private >*/ + /* padding */ + gpointer pdummy[4]; +}; + +GType ibus_connection_get_type (void); +IBusConnection *ibus_connection_new (void); +void ibus_connection_set_connection (IBusConnection *connection, + DBusConnection *dbus_connection, + gboolean shared); +IBusConnection *ibus_connection_open (const gchar *address); +IBusConnection *ibus_connection_open_private (const gchar *address); +void ibus_connection_close (IBusConnection *connection); +gboolean ibus_connection_is_connected (IBusConnection *connection); +DBusConnection *ibus_connection_get_connection (IBusConnection *connection); +gboolean ibus_connection_send (IBusConnection *connection, + IBusMessage *message); +gboolean ibus_connection_send_signal (IBusConnection *connection, + const gchar *path, + const gchar *interface, + const gchar *name, + GType first_arg_type, + ...); +gboolean ibus_connection_send_signal_valist (IBusConnection *connection, + const gchar *path, + const gchar *interface, + const gchar *name, + GType first_arg_type, + va_list args); +gboolean ibus_connection_send_valist (IBusConnection *connection, + gint message_type, + const gchar *path, + const gchar *interface, + const gchar *name, + GType first_arg_type, + va_list args); +gboolean ibus_connection_send_with_reply (IBusConnection *connection, + IBusMessage *message, + IBusPendingCall **pending_return, + gint timeout_milliseconds); +IBusMessage *ibus_connection_send_with_reply_and_block + (IBusConnection *connection, + IBusMessage *message, + gint timeout_milliseconds, + IBusError **error); +gboolean ibus_connection_call (IBusConnection *connection, + const gchar *name, + const gchar *path, + const gchar *interface, + const gchar *member, + IBusError **error, + GType first_arg_type, + ...); +void ibus_connection_flush (IBusConnection *connection); +gboolean ibus_connection_register_object_path + (IBusConnection *connection, + const gchar *path, + IBusMessageFunc message_func, + gpointer user_data); +gboolean ibus_connection_unregister_object_path + (IBusConnection *connection, + const gchar *path); + +G_END_DECLS +#endif + diff --git a/src/ibusdebug.h b/src/ibusdebug.h new file mode 100644 index 0000000..7a59a8d --- /dev/null +++ b/src/ibusdebug.h @@ -0,0 +1,27 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_DEBUG_H_ +#define __IBUS_DEBUG_H_ + +#define ibus_warning(msg, args...) \ + g_warning("%s:%d, " msg, __FILE__, __LINE__, ##args) + +#endif + diff --git a/src/ibusengine.c b/src/ibusengine.c new file mode 100644 index 0000000..ddedcde --- /dev/null +++ b/src/ibusengine.c @@ -0,0 +1,957 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <stdarg.h> +#include "ibusengine.h" +#include "ibusinternal.h" +#include "ibusshare.h" + +#define IBUS_ENGINE_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_ENGINE, IBusEnginePrivate)) + +enum { + PROCESS_KEY_EVENT, + FOCUS_IN, + FOCUS_OUT, + RESET, + ENABLE, + DISABLE, + SET_CURSOR_LOCATION, + SET_CAPABILITIES, + PAGE_UP, + PAGE_DOWN, + CURSOR_UP, + CURSOR_DOWN, + PROPERTY_ACTIVATE, + PROPERTY_SHOW, + PROPERTY_HIDE, + LAST_SIGNAL, +}; + +enum { + PROP_0, + PROP_NAME, + PROP_CONNECTION, +}; + + +/* IBusEnginePriv */ +struct _IBusEnginePrivate { + gchar *name; + IBusConnection *connection; +}; +typedef struct _IBusEnginePrivate IBusEnginePrivate; + +static guint engine_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_engine_class_init (IBusEngineClass *klass); +static void ibus_engine_init (IBusEngine *engine); +static void ibus_engine_destroy (IBusEngine *engine); +static void ibus_engine_set_property (IBusEngine *engine, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void ibus_engine_get_property (IBusEngine *engine, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static gboolean ibus_engine_ibus_message (IBusEngine *engine, + IBusConnection *connection, + IBusMessage *message); +static gboolean ibus_engine_process_key_event + (IBusEngine *engine, + guint keyval, + guint state); +static void ibus_engine_focus_in (IBusEngine *engine); +static void ibus_engine_focus_out (IBusEngine *engine); +static void ibus_engine_reset (IBusEngine *engine); +static void ibus_engine_enable (IBusEngine *engine); +static void ibus_engine_disable (IBusEngine *engine); +static void ibus_engine_set_cursor_location + (IBusEngine *engine, + gint x, + gint y, + gint w, + gint h); +static void ibus_engine_set_capabilities + (IBusEngine *engine, + guint caps); +static void ibus_engine_page_up (IBusEngine *engine); +static void ibus_engine_page_down (IBusEngine *engine); +static void ibus_engine_cursor_up (IBusEngine *engine); +static void ibus_engine_cursor_down (IBusEngine *engine); +static void ibus_engine_property_activate + (IBusEngine *engine, + const gchar *prop_name, + gint prop_state); +static void ibus_engine_property_show (IBusEngine *engine, + const gchar *prop_name); +static void ibus_engine_property_hide (IBusEngine *engine, + const gchar *prop_name); + + +static IBusServiceClass *parent_class = NULL; + +GType +ibus_engine_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusEngineClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_engine_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusEngine), + 0, + (GInstanceInitFunc) ibus_engine_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERVICE, + "IBusEngine", + &type_info, + (GTypeFlags) 0); + } + return type; +} + +IBusEngine * +ibus_engine_new (const gchar *name, + const gchar *path, + IBusConnection *connection) +{ + g_assert (path); + g_assert (IBUS_IS_CONNECTION (connection)); + + IBusEngine *engine; + + engine = (IBusEngine *) g_object_new (IBUS_TYPE_ENGINE, + "name", name, + "path", path, + "connection", connection, + NULL); + + return engine; +} + +static void +ibus_engine_class_init (IBusEngineClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + + parent_class = (IBusServiceClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusEnginePrivate)); + + gobject_class->set_property = (GObjectSetPropertyFunc) ibus_engine_set_property; + gobject_class->get_property = (GObjectGetPropertyFunc) ibus_engine_get_property; + + ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_engine_destroy; + + IBUS_SERVICE_CLASS (klass)->ibus_message = (ServiceIBusMessageFunc) ibus_engine_ibus_message; + + klass->process_key_event = ibus_engine_process_key_event; + klass->focus_in = ibus_engine_focus_in; + klass->focus_out = ibus_engine_focus_out; + klass->reset = ibus_engine_reset; + klass->enable = ibus_engine_enable; + klass->disable = ibus_engine_disable; + klass->page_up = ibus_engine_page_up; + klass->page_down = ibus_engine_page_down; + klass->cursor_up = ibus_engine_cursor_up; + klass->cursor_down = ibus_engine_cursor_down; + klass->property_activate = ibus_engine_property_activate; + klass->property_show = ibus_engine_property_show; + klass->property_hide = ibus_engine_property_hide; + klass->set_cursor_location = ibus_engine_set_cursor_location; + klass->set_capabilities = ibus_engine_set_capabilities; + + + /* install properties */ + g_object_class_install_property (gobject_class, + PROP_NAME, + g_param_spec_string ("name", + "name", + "engine name", + "noname", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + + g_object_class_install_property (gobject_class, + PROP_CONNECTION, + g_param_spec_object ("connection", + "connection", + "The connection of engine object", + IBUS_TYPE_CONNECTION, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + /* install signals */ + engine_signals[PROCESS_KEY_EVENT] = + g_signal_new (I_("process-key-event"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, process_key_event), + NULL, NULL, + ibus_marshal_BOOL__UINT_UINT, + G_TYPE_BOOLEAN, + 2, + G_TYPE_UINT, + G_TYPE_UINT); + + engine_signals[FOCUS_IN] = + g_signal_new (I_("focus-in"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, focus_in), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + engine_signals[FOCUS_OUT] = + g_signal_new (I_("focus-out"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, focus_out), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + engine_signals[RESET] = + g_signal_new (I_("reset"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, reset), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + engine_signals[ENABLE] = + g_signal_new (I_("enable"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, enable), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + engine_signals[DISABLE] = + g_signal_new (I_("disable"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, disable), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + engine_signals[SET_CURSOR_LOCATION] = + g_signal_new (I_("set-cursor-location"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, set_cursor_location), + NULL, NULL, + ibus_marshal_VOID__INT_INT_INT_INT, + G_TYPE_NONE, 4, + G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT); + + engine_signals[SET_CAPABILITIES] = + g_signal_new (I_("set-capabilities"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, set_capabilities), + NULL, NULL, + ibus_marshal_VOID__UINT, + G_TYPE_NONE, 1, + G_TYPE_UINT); + + engine_signals[PAGE_UP] = + g_signal_new (I_("page-up"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, page_up), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + engine_signals[PAGE_DOWN] = + g_signal_new (I_("page-down"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, page_down), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + engine_signals[CURSOR_UP] = + g_signal_new (I_("cursor-up"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, cursor_up), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + engine_signals[CURSOR_DOWN] = + g_signal_new (I_("cursor-down"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, cursor_down), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + engine_signals[PROPERTY_ACTIVATE] = + g_signal_new (I_("property-activate"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, property_activate), + NULL, NULL, + ibus_marshal_VOID__STRING_INT, + G_TYPE_NONE, 0); + + engine_signals[PROPERTY_SHOW] = + g_signal_new (I_("property-show"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, property_show), + NULL, NULL, + ibus_marshal_VOID__STRING, + G_TYPE_NONE, 0); + + engine_signals[PROPERTY_HIDE] = + g_signal_new (I_("property-hide"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, property_hide), + NULL, NULL, + ibus_marshal_VOID__STRING, + G_TYPE_NONE, 0); + +} + +static void +ibus_engine_init (IBusEngine *engine) +{ + IBusEnginePrivate *priv; + priv = IBUS_ENGINE_GET_PRIVATE (engine); + + priv->name = NULL; + priv->connection = NULL; +} + +static void +ibus_engine_destroy (IBusEngine *engine) +{ + IBusEnginePrivate *priv; + priv = IBUS_ENGINE_GET_PRIVATE (engine); + + g_free (priv->name); + + if (priv->connection) { + g_object_unref (priv->connection); + priv->connection = NULL; + } + + IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (engine)); +} + +static void +ibus_engine_set_property (IBusEngine *engine, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + IBusEnginePrivate *priv; + priv = IBUS_ENGINE_GET_PRIVATE (engine); + + switch (prop_id) { + case PROP_NAME: + priv->name = g_strdup (g_value_dup_string (value)); + break; + + case PROP_CONNECTION: + priv->connection = g_value_get_object (value); + g_object_ref (priv->connection); + ibus_service_add_to_connection ((IBusService *) engine, + priv->connection); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (engine, prop_id, pspec); + } +} + +static void +ibus_engine_get_property (IBusEngine *engine, + guint prop_id, GValue *value, GParamSpec *pspec) +{ + IBusEnginePrivate *priv; + priv = IBUS_ENGINE_GET_PRIVATE (engine); + + switch (prop_id) { + case PROP_NAME: + g_value_set_string (value, priv->name); + break; + + case PROP_CONNECTION: + g_value_set_object (value, priv->connection); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (engine, prop_id, pspec); + } +} + +static gboolean +ibus_engine_ibus_message (IBusEngine *engine, + IBusConnection *connection, + IBusMessage *message) +{ + g_assert (IBUS_IS_ENGINE (engine)); + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (message != NULL); + + IBusEnginePrivate *priv; + priv = IBUS_ENGINE_GET_PRIVATE (engine); + + g_assert (priv->connection == connection); + + IBusMessage *return_message = NULL; + IBusMessage *error_message = NULL; + + static const struct { + gchar *member; + guint signal_id; + } no_arg_methods[] = { + {"FocusIn", FOCUS_IN}, + {"FocusOut", FOCUS_OUT}, + {"Reset", RESET}, + {"Enable", ENABLE}, + {"Disable", DISABLE}, + {"PageUp", PAGE_UP}, + {"PageDown", PAGE_DOWN}, + {"CursorUp", CURSOR_UP}, + {"CursorDown", CURSOR_DOWN}, + {NULL, 0}, + }; + gint i; + + for (i = 0; no_arg_methods[i].member != NULL; i++) { + if (!ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, no_arg_methods[i].member)) + continue; + + IBusMessageIter iter; + ibus_message_iter_init (message, &iter); + if (ibus_message_iter_has_next (&iter)) { + error_message = ibus_message_new_error_printf (message, + "%s.%s: Method does not have arguments", + IBUS_INTERFACE_ENGINE, no_arg_methods[i].member); + ibus_connection_send (connection, error_message); + ibus_message_unref (error_message); + return TRUE; + } + + g_signal_emit (engine, engine_signals[no_arg_methods[i].signal_id], 0); + return_message = ibus_message_new_method_return (message); + ibus_connection_send (connection, return_message); + ibus_message_unref (return_message); + return TRUE; + } + + + if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "ProcessKeyEvent")) { + guint keyval, state; + gboolean retval; + IBusError *error = NULL; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_UINT, &keyval, + G_TYPE_UINT, &state, + G_TYPE_INVALID); + + if (!retval) + goto _keypress_fail; + + retval = FALSE; + g_signal_emit (engine, + engine_signals[PROCESS_KEY_EVENT], + 0, + keyval, + state, + &retval); + + return_message = ibus_message_new_method_return (message); + ibus_message_append_args (return_message, + G_TYPE_BOOLEAN, &retval, + DBUS_TYPE_INVALID); + ibus_connection_send (connection, return_message); + ibus_message_unref (return_message); + return TRUE; + + _keypress_fail: + error_message = ibus_message_new_error_printf (message, + "%s.%s: Can not match signature (ubu) of method", + IBUS_INTERFACE_ENGINE, "ProcessKeyEvent"); + ibus_connection_send (connection, error_message); + ibus_message_unref (error_message); + return TRUE; + } + else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "PropertyActivate")) { + gchar *name; + gint state; + gboolean retval; + IBusError *error = NULL; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_STRING, &name, + G_TYPE_INT, &state, + G_TYPE_INVALID); + + if (!retval) + goto _property_activate_fail; + + g_signal_emit (engine, + engine_signals[PROPERTY_ACTIVATE], + 0, + name, + state); + + return_message = ibus_message_new_method_return (message); + ibus_connection_send (connection, return_message); + ibus_message_unref (return_message); + return TRUE; + + _property_activate_fail: + error_message = ibus_message_new_error_printf (message, + "%s.%s: Can not match signature (si) of method", + IBUS_INTERFACE_ENGINE, + "PropertyActivate"); + ibus_connection_send (connection, error_message); + ibus_message_unref (error_message); + return TRUE; + + } + else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "PropertyShow")) { + gchar *name; + gboolean retval; + IBusError *error; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_STRING, &name, + G_TYPE_INVALID); + + if (!retval) + goto _property_show_fail; + + g_signal_emit (engine, + engine_signals[PROPERTY_SHOW], + 0, + name); + + return_message = ibus_message_new_method_return (message); + ibus_connection_send (connection, return_message); + ibus_message_unref (return_message); + return TRUE; + + _property_show_fail: + error_message = ibus_message_new_error_printf (message, + "%s.%s: Can not match signature (s) of method", + IBUS_INTERFACE_ENGINE, + "PropertyShow"); + ibus_connection_send (connection, error_message); + ibus_message_unref (error_message); + return TRUE; + } + else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "PropertyHide")) { + gchar *name; + gboolean retval; + IBusError *error = NULL; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_STRING, &name, + G_TYPE_INVALID); + if (!retval) + goto _property_hide_fail; + + g_signal_emit (engine, engine_signals[PROPERTY_HIDE], 0, name); + + return_message = ibus_message_new_method_return (message); + ibus_connection_send (connection, return_message); + ibus_message_unref (return_message); + return TRUE; + + _property_hide_fail: + error_message = ibus_message_new_error_printf (message, + "%s.%s: Can not match signature (s) of method", + IBUS_INTERFACE_ENGINE, "PropertyHide"); + ibus_connection_send (connection, error_message); + ibus_message_unref (error_message); + return TRUE; + } + else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "SetCursorLocation")) { + gint x, y, w, h; + gboolean retval; + IBusError *error = NULL; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_INT, &x, + G_TYPE_INT, &y, + G_TYPE_INT, &w, + G_TYPE_INT, &h, + G_TYPE_INVALID); + if (!retval) + goto _set_cursor_location_fail; + + engine->cursor_area.x = x; + engine->cursor_area.y = y; + engine->cursor_area.width = w; + engine->cursor_area.height = h; + + g_signal_emit (engine, + engine_signals[SET_CURSOR_LOCATION], + 0, + x, y, w, h); + + return_message = ibus_message_new_method_return (message); + ibus_connection_send (connection, return_message); + ibus_message_unref (return_message); + return TRUE; + + _set_cursor_location_fail: + error_message = ibus_message_new_error_printf (message, + "%s.%s: Can not match signature (iiii) of method", + IBUS_INTERFACE_ENGINE, + "SetCursorLocation"); + ibus_connection_send (connection, error_message); + ibus_message_unref (error_message); + return TRUE; + } + else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "SetCapabilities")) { + guint caps; + gboolean retval; + IBusError *error = NULL; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_UINT, &caps, + G_TYPE_INVALID); + + if (!retval) + goto _set_capabilities_fail; + + engine->client_capabilities = caps; + + g_signal_emit (engine, engine_signals[SET_CAPABILITIES], 0, caps); + + return_message = ibus_message_new_method_return (message); + ibus_connection_send (connection, return_message); + ibus_message_unref (return_message); + return TRUE; + + _set_capabilities_fail: + error_message = ibus_message_new_error_printf (message, + "%s.%s: Can not match signature (u) of method", + IBUS_INTERFACE_ENGINE, "SetCapabilities"); + ibus_connection_send (connection, error_message); + ibus_message_unref (error_message); + return TRUE; + } + else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "Destroy")) { + return_message = ibus_message_new_method_return (message); + + ibus_connection_send (connection, return_message); + ibus_message_unref (return_message); + + ibus_object_destroy ((IBusObject *) engine); + } + + return parent_class->ibus_message ((IBusService *) engine, connection, message); +} + +static gboolean +ibus_engine_process_key_event (IBusEngine *engine, + guint keyval, + guint state) +{ + // g_debug ("process-key-event (%d, %d)", keyval, state); + return FALSE; +} + +static void +ibus_engine_focus_in (IBusEngine *engine) +{ + // g_debug ("focus-in"); +} + +static void +ibus_engine_focus_out (IBusEngine *engine) +{ + // g_debug ("focus-out"); +} + +static void +ibus_engine_reset (IBusEngine *engine) +{ + // g_debug ("reset"); +} + +static void +ibus_engine_enable (IBusEngine *engine) +{ + // g_debug ("enable"); +} + +static void +ibus_engine_disable (IBusEngine *engine) +{ + // g_debug ("disable"); +} + +static void +ibus_engine_set_cursor_location (IBusEngine *engine, + gint x, + gint y, + gint w, + gint h) +{ + // g_debug ("set-cursor-location (%d, %d, %d, %d)", x, y, w, h); +} + +static void +ibus_engine_set_capabilities (IBusEngine *engine, + guint caps) +{ + // g_debug ("set-capabilities (0x%04x)", caps); +} + +static void +ibus_engine_page_up (IBusEngine *engine) +{ + // g_debug ("page-up"); +} + +static void +ibus_engine_page_down (IBusEngine *engine) +{ + // g_debug ("page-down"); +} + +static void +ibus_engine_cursor_up (IBusEngine *engine) +{ + // g_debug ("cursor-up"); +} + +static void +ibus_engine_cursor_down (IBusEngine *engine) +{ + // g_debug ("cursor-down"); +} + +static void +ibus_engine_property_activate (IBusEngine *engine, + const gchar *prop_name, gint prop_state) +{ + // g_debug ("property-activate ('%s', %d)", prop_name, prop_state); +} + +static void +ibus_engine_property_show (IBusEngine *engine, const gchar *prop_name) +{ + // g_debug ("property-show ('%s')", prop_name); +} + +static void +ibus_engine_property_hide (IBusEngine *engine, const gchar *prop_name) +{ + // g_debug ("property-hide ('%s')", prop_name); +} + +static void +_send_signal (IBusEngine *engine, + const gchar *name, + GType first_arg_type, + ...) +{ + g_assert (IBUS_IS_ENGINE (engine)); + g_assert (name != NULL); + + va_list args; + const gchar *path; + IBusEnginePrivate *priv; + + priv = IBUS_ENGINE_GET_PRIVATE (engine); + + path = ibus_service_get_path ((IBusService *)engine); + + va_start (args, first_arg_type); + ibus_connection_send_signal_valist (priv->connection, + path, + IBUS_INTERFACE_ENGINE, + name, + first_arg_type, + args); + va_end (args); +} + +void +ibus_engine_commit_text (IBusEngine *engine, + IBusText *text) +{ + _send_signal (engine, + "CommitText", + IBUS_TYPE_TEXT, &text, + G_TYPE_INVALID); +} + +void +ibus_engine_update_preedit_text (IBusEngine *engine, + IBusText *text, + guint cursor_pos, + gboolean visible) +{ + _send_signal (engine, + "UpdatePreeditText", + IBUS_TYPE_TEXT, &text, + G_TYPE_UINT, &cursor_pos, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); +} + +void +ibus_engine_show_preedit_text (IBusEngine *engine) +{ + _send_signal (engine, + "ShowPreeditText", + G_TYPE_INVALID); +} + +void ibus_engine_hide_preedit_text (IBusEngine *engine) +{ + _send_signal (engine, + "HidePreeditText", + G_TYPE_INVALID); +} + +void ibus_engine_update_auxiliary_text (IBusEngine *engine, + IBusText *text, + gboolean visible) +{ + _send_signal (engine, + "UpdateAuxiliaryText", + IBUS_TYPE_TEXT, &text, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); +} + +void +ibus_engine_show_auxiliary_text (IBusEngine *engine) +{ + _send_signal (engine, + "ShowAuxiliaryText", + G_TYPE_INVALID); +} + +void +ibus_engine_hide_auxiliary_text (IBusEngine *engine) +{ + _send_signal (engine, + "HideAuxiliaryText", + G_TYPE_INVALID); +} + +void ibus_engine_update_lookup_table (IBusEngine *engine, + IBusLookupTable *table, + gboolean visible) +{ + _send_signal (engine, + "UpdateLookupTable", + IBUS_TYPE_LOOKUP_TABLE, &table, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); +} + +void ibus_engine_show_lookup_table (IBusEngine *engine) +{ + _send_signal (engine, + "ShowLookupTable", + G_TYPE_INVALID); +} + +void ibus_engine_hide_lookup_table (IBusEngine *engine) +{ + _send_signal (engine, + "HideLookupTable", + G_TYPE_INVALID); +} + +void ibus_engine_forward_key_event (IBusEngine *engine, + guint keyval, + gboolean is_press, + guint state) +{ + _send_signal (engine, + "HideLookupTable", + G_TYPE_UINT, &keyval, + G_TYPE_BOOLEAN, &is_press, + G_TYPE_UINT, &state, + G_TYPE_INVALID); +} + +void +ibus_engine_register_properties (IBusEngine *engine, + IBusPropList *prop_list) +{ + _send_signal (engine, + "RegisterProperties", + IBUS_TYPE_PROP_LIST, &prop_list, + G_TYPE_INVALID); +} + +void +ibus_engine_update_property (IBusEngine *engine, + IBusProperty *prop) +{ + _send_signal (engine, + "UpdateProperty", + IBUS_TYPE_PROPERTY, &prop, + G_TYPE_INVALID); +} + +const gchar * +ibus_engine_get_name (IBusEngine *engine) +{ + g_assert (IBUS_IS_ENGINE (engine)); + + IBusEnginePrivate *priv; + priv = IBUS_ENGINE_GET_PRIVATE (engine); + + return priv->name; +} + diff --git a/src/ibusengine.h b/src/ibusengine.h new file mode 100644 index 0000000..0a827af --- /dev/null +++ b/src/ibusengine.h @@ -0,0 +1,152 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_ENGINE_H_ +#define __IBUS_ENGINE_H_ + +#include <dbus/dbus.h> +#include "ibusservice.h" +#include "ibusattribute.h" +#include "ibuslookuptable.h" +#include "ibusproperty.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_ENGINE \ + (ibus_engine_get_type ()) +#define IBUS_ENGINE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_ENGINE, IBusEngine)) +#define IBUS_ENGINE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_ENGINE, IBusEngineClass)) +#define IBUS_IS_ENGINE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_ENGINE)) +#define IBUS_IS_ENGINE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_ENGINE)) +#define IBUS_ENGINE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_ENGINE, IBusEngineClass)) + +G_BEGIN_DECLS + +typedef struct _IBusEngine IBusEngine; +typedef struct _IBusEngineClass IBusEngineClass; + +struct _IBusEngine { + IBusService parent; + /* instance members */ + gboolean enabled; + gboolean has_focus; + + /* cursor location */ + IBusRectangle cursor_area; + guint client_capabilities; +}; + +struct _IBusEngineClass { + IBusServiceClass parent; + + /* class members */ + gboolean (* process_key_event) + (IBusEngine *engine, + guint keyval, + guint state); + void (* focus_in) (IBusEngine *engine); + void (* focus_out) (IBusEngine *engine); + void (* reset) (IBusEngine *engine); + void (* enable) (IBusEngine *engine); + void (* disable) (IBusEngine *engine); + void (* set_cursor_location) + (IBusEngine *engine, + gint x, + gint y, + gint w, + gint h); + void (* set_capabilities) + (IBusEngine *engine, + guint caps); + + void (* page_up) (IBusEngine *engine); + void (* page_down) (IBusEngine *engine); + void (* cursor_up) (IBusEngine *engine); + void (* cursor_down) (IBusEngine *engine); + + void (* property_activate) + (IBusEngine *engine, + const gchar *prop_name, + gint prop_state); + void (* property_show) (IBusEngine *engine, + const gchar *prop_name); + void (* property_hide) (IBusEngine *engine, + const gchar *prop_name); + + /*< private >*/ + /* padding */ + gpointer pdummy[9]; +}; + +GType ibus_engine_get_type (void); +IBusEngine *ibus_engine_new (const gchar *name, + const gchar *path, + IBusConnection *connection); +void ibus_engine_commit_text (IBusEngine *engine, + IBusText *text); +void ibus_engine_update_preedit_text + (IBusEngine *engine, + IBusText *text, + guint cursor_pos, + gboolean visible); +void ibus_engine_show_preedit_text + (IBusEngine *engine); +void ibus_engine_hide_preedit_text + (IBusEngine *engine); +void ibus_engine_update_auxiliary_text + (IBusEngine *engine, + IBusText *text, + gboolean visible); +void ibus_engine_show_auxiliary_text + (IBusEngine *engine); +void ibus_engine_hide_auxiliary_text + (IBusEngine *engine); +void ibus_engine_update_lookup_table + (IBusEngine *engine, + IBusLookupTable *lookup_table, + gboolean visible); +void ibus_engine_show_lookup_table + (IBusEngine *engine); +void ibus_engine_hide_lookup_table + (IBusEngine *engine); + +void ibus_engine_forward_key_event + (IBusEngine *engine, + guint keyval, + gboolean is_press, + guint state); + +void ibus_engine_register_properties + (IBusEngine *engine, + IBusPropList *prop_list); +void ibus_engine_update_property(IBusEngine *engine, + IBusProperty *prop); +const gchar *ibus_engine_get_name (IBusEngine *engine); + +G_END_DECLS +#endif + diff --git a/src/ibusenginedesc.c b/src/ibusenginedesc.c new file mode 100644 index 0000000..0410b67 --- /dev/null +++ b/src/ibusenginedesc.c @@ -0,0 +1,356 @@ +/* vim:set et sts=4: */ +/* bus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include "ibusenginedesc.h" +#include "ibusxml.h" + +enum { + LAST_SIGNAL, +}; + + +/* IBusEngineDescPriv */ +struct _IBusEngineDescPrivate { + gpointer pad; +}; +typedef struct _IBusEngineDescPrivate IBusEngineDescPrivate; + +#define IBUS_ENGINE_DESC_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), BUS_TYPE_ENGINE_INFO, IBusEngineDescPrivate)) + +// static guint _signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_engine_desc_class_init (IBusEngineDescClass *klass); +static void ibus_engine_desc_init (IBusEngineDesc *desc); +static void ibus_engine_desc_destroy (IBusEngineDesc *desc); +static gboolean ibus_engine_desc_serialize (IBusEngineDesc *desc, + IBusMessageIter *iter); +static gboolean ibus_engine_desc_deserialize (IBusEngineDesc *desc, + IBusMessageIter *iter); +static gboolean ibus_engine_desc_copy (IBusEngineDesc *dest, + const IBusEngineDesc *src); +static gboolean ibus_engine_desc_parse_xml_node (IBusEngineDesc *desc, + XMLNode *node); + +static IBusSerializableClass *parent_class = NULL; + +GType +ibus_engine_desc_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusEngineDescClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_engine_desc_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusEngineDesc), + 0, + (GInstanceInitFunc) ibus_engine_desc_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusEngineDesc", + &type_info, + (GTypeFlags)0); + } + + return type; +} + + +static void +ibus_engine_desc_class_init (IBusEngineDescClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_engine_desc_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_engine_desc_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_engine_desc_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_engine_desc_copy; + + g_string_append (serializable_class->signature, "ssssssss"); +} + +static void +ibus_engine_desc_init (IBusEngineDesc *desc) +{ + + desc->name = NULL; + desc->longname = NULL; + desc->description = NULL; + desc->language = NULL; + desc->license = NULL; + desc->author = NULL; + desc->icon = NULL; + desc->layout = NULL; +} + +static void +ibus_engine_desc_destroy (IBusEngineDesc *desc) +{ + g_free (desc->name); + g_free (desc->longname); + g_free (desc->description); + g_free (desc->language); + g_free (desc->license); + g_free (desc->author); + g_free (desc->icon); + g_free (desc->layout); + + IBUS_OBJECT_CLASS (parent_class)->destroy (IBUS_OBJECT (desc)); +} + +static gboolean +ibus_engine_desc_serialize (IBusEngineDesc *desc, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = parent_class->serialize ((IBusSerializable *)desc, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &desc->name); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &desc->longname); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &desc->description); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &desc->language); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &desc->license); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &desc->author); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &desc->icon); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &desc->layout); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_engine_desc_deserialize (IBusEngineDesc *desc, + IBusMessageIter *iter) +{ + gboolean retval; + gchar *str; + + retval = parent_class->deserialize ((IBusSerializable *)desc, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + desc->name = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + desc->longname = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + desc->description = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + desc->language = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + desc->license = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + desc->author = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + desc->icon = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + desc->layout = g_strdup (str); + + return TRUE; +} + +static gboolean +ibus_engine_desc_copy (IBusEngineDesc *dest, + const IBusEngineDesc *src) +{ + gboolean retval; + + retval = parent_class->copy ((IBusSerializable *)dest, + (IBusSerializable *)src); + g_return_val_if_fail (retval, FALSE); + + + dest->name = g_strdup (src->name); + dest->longname = g_strdup (src->longname); + dest->description = g_strdup (src->description); + dest->language = g_strdup (src->language); + dest->license = g_strdup (src->license); + dest->author = g_strdup (src->author); + dest->icon = g_strdup (src->icon); + dest->layout = g_strdup (src->layout); + + return TRUE; +} + +#define g_string_append_indent(string, indent) \ + { \ + gint i; \ + for (i = 0; i < (indent); i++) { \ + g_string_append (string, " "); \ + } \ + } + +void +ibus_engine_desc_output (IBusEngineDesc *desc, + GString *output, + gint indent) +{ + g_string_append_indent (output, indent); + g_string_append (output, "<engine>\n"); +#define OUTPUT_ENTRY(field, element) \ + { \ + gchar *escape_text = g_markup_escape_text (desc->field, -1); \ + g_string_append_indent (output, indent + 1); \ + g_string_append_printf (output, "<"element">%s</"element">\n", \ + escape_text); \ + g_free (escape_text); \ + } +#define OUTPUT_ENTRY_1(name) OUTPUT_ENTRY(name, #name) + OUTPUT_ENTRY_1(name); + OUTPUT_ENTRY_1(longname); + OUTPUT_ENTRY_1(description); + OUTPUT_ENTRY_1(language); + OUTPUT_ENTRY_1(license); + OUTPUT_ENTRY_1(author); + OUTPUT_ENTRY_1(icon); + OUTPUT_ENTRY_1(layout); +#undef OUTPUT_ENTRY +#undef OUTPUT_ENTRY_1 + g_string_append_indent (output, indent); + g_string_append (output, "</engine>\n"); +} + +static gboolean +ibus_engine_desc_parse_xml_node (IBusEngineDesc *desc, + XMLNode *node) +{ + GList *p; + for (p = node->sub_nodes; p != NULL; p = p->next) { + XMLNode *sub_node = (XMLNode *) p->data; + +#define PARSE_ENTRY(field_name, element_name) \ + if (g_strcmp0 (sub_node->name, element_name) == 0) { \ + if (desc->field_name != NULL) { \ + g_free (desc->field_name); \ + } \ + desc->field_name = g_strdup (sub_node->text); \ + continue; \ + } +#define PARSE_ENTRY_1(name) PARSE_ENTRY(name, #name) + PARSE_ENTRY_1(name); + PARSE_ENTRY_1(longname); + PARSE_ENTRY_1(description); + PARSE_ENTRY_1(language); + PARSE_ENTRY_1(license); + PARSE_ENTRY_1(author); + PARSE_ENTRY_1(icon); + PARSE_ENTRY_1(layout); +#undef PARSE_ENTRY +#undef PARSE_ENTRY1 + g_warning ("<engines> element contains invalidate element <%s>", sub_node->name); + } + return TRUE; +} + +IBusEngineDesc * +ibus_engine_desc_new (const gchar *name, + const gchar *longname, + const gchar *description, + const gchar *language, + const gchar *license, + const gchar *author, + const gchar *icon, + const gchar *layout) +{ + g_assert (name); + g_assert (longname); + g_assert (description); + g_assert (language); + g_assert (license); + g_assert (author); + g_assert (icon); + g_assert (layout); + + IBusEngineDesc *desc; + desc = (IBusEngineDesc *)g_object_new (IBUS_TYPE_ENGINE_DESC, NULL); + + desc->name = g_strdup (name); + desc->longname = g_strdup (longname); + desc->description = g_strdup (description); + desc->language = g_strdup (language); + desc->license = g_strdup (license); + desc->author = g_strdup (author); + desc->icon = g_strdup (icon); + desc->layout = g_strdup (layout); + + return desc; +} + +IBusEngineDesc * +ibus_engine_desc_new_from_xml_node (XMLNode *node) +{ + g_assert (node); + + IBusEngineDesc *desc; + + if (G_UNLIKELY (g_strcmp0 (node->name, "engine") != 0)) { + return NULL; + } + + desc = (IBusEngineDesc *)g_object_new (IBUS_TYPE_ENGINE_DESC, NULL); + + if (!ibus_engine_desc_parse_xml_node (desc, node)) { + g_object_unref (desc); + desc = NULL; + } + + return desc; +} + diff --git a/src/ibusenginedesc.h b/src/ibusenginedesc.h new file mode 100644 index 0000000..ffc5a52 --- /dev/null +++ b/src/ibusenginedesc.h @@ -0,0 +1,86 @@ +/* vim:set et sts=4: */ +/* bus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __ENGINE_DESC_H_ +#define __ENGINE_DESC_H_ + +#include "ibusserializable.h" +#include "ibusxml.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_ENGINE_DESC \ + (ibus_engine_desc_get_type ()) +#define IBUS_ENGINE_DESC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_ENGINE_DESC, IBusEngineDesc)) +#define IBUS_ENGINE_DESC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_ENGINE_DESC, IBusEngineDescClass)) +#define IBUS_IS_ENGINE_DESC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_ENGINE_DESC)) +#define IBUS_IS_ENGINE_DESC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_ENGINE_DESC)) +#define IBUS_ENGINE_DESC_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_ENGINE_DESC, IBusEngineDescClass)) + +G_BEGIN_DECLS + +typedef struct _IBusEngineDesc IBusEngineDesc; +typedef struct _IBusEngineDescClass IBusEngineDescClass; +typedef struct _BusComponent BusComponent; + +struct _IBusEngineDesc { + IBusSerializable parent; + /* instance members */ + + gchar *name; + gchar *longname; + gchar *description; + gchar *language; + gchar *license; + gchar *author; + gchar *icon; + gchar *layout; +}; + +struct _IBusEngineDescClass { + IBusSerializableClass parent; + + /* class members */ +}; + +GType ibus_engine_desc_get_type (void); +IBusEngineDesc *ibus_engine_desc_new (const gchar *name, + const gchar *longname, + const gchar *description, + const gchar *language, + const gchar *license, + const gchar *author, + const gchar *icon, + const gchar *layout); +IBusEngineDesc *ibus_engine_desc_new_from_xml_node + (XMLNode *node); +void ibus_engine_desc_output (IBusEngineDesc *info, + GString *output, + gint indent); +G_END_DECLS +#endif + diff --git a/src/ibusenumtypes.c b/src/ibusenumtypes.c new file mode 100644 index 0000000..591b3f0 --- /dev/null +++ b/src/ibusenumtypes.c @@ -0,0 +1,146 @@ + +/* Generated data (by glib-mkenums) */ + +#include "ibus.h" + +/* enumerations from "ibusobject.h" */ +GType +ibus_object_flags_get_type (void) +{ + static GType etype = 0; + if (G_UNLIKELY(etype == 0)) { + static const GFlagsValue values[] = { + { IBUS_IN_DESTRUCTION, "IBUS_IN_DESTRUCTION", "in-destruction" }, + { IBUS_DESTROYED, "IBUS_DESTROYED", "destroyed" }, + { IBUS_RESERVED_1, "IBUS_RESERVED_1", "reserved-1" }, + { IBUS_RESERVED_2, "IBUS_RESERVED_2", "reserved-2" }, + { 0, NULL, NULL } + }; + etype = g_flags_register_static (g_intern_static_string ("IBusObjectFlags"), values); + } + return etype; +} + +/* enumerations from "ibusattribute.h" */ +GType +ibus_attr_type_get_type (void) +{ + static GType etype = 0; + if (G_UNLIKELY(etype == 0)) { + static const GEnumValue values[] = { + { IBUS_ATTR_TYPE_UNDERLINE, "IBUS_ATTR_TYPE_UNDERLINE", "underline" }, + { IBUS_ATTR_TYPE_FOREGROUND, "IBUS_ATTR_TYPE_FOREGROUND", "foreground" }, + { IBUS_ATTR_TYPE_BACKGROUND, "IBUS_ATTR_TYPE_BACKGROUND", "background" }, + { 0, NULL, NULL } + }; + etype = g_enum_register_static (g_intern_static_string ("IBusAttrType"), values); + } + return etype; +} + +GType +ibus_attr_underline_get_type (void) +{ + static GType etype = 0; + if (G_UNLIKELY(etype == 0)) { + static const GEnumValue values[] = { + { IBUS_ATTR_UNDERLINE_NONE, "IBUS_ATTR_UNDERLINE_NONE", "none" }, + { IBUS_ATTR_UNDERLINE_SINGLE, "IBUS_ATTR_UNDERLINE_SINGLE", "single" }, + { IBUS_ATTR_UNDERLINE_DOUBLE, "IBUS_ATTR_UNDERLINE_DOUBLE", "double" }, + { IBUS_ATTR_UNDERLINE_LOW, "IBUS_ATTR_UNDERLINE_LOW", "low" }, + { 0, NULL, NULL } + }; + etype = g_enum_register_static (g_intern_static_string ("IBusAttrUnderline"), values); + } + return etype; +} + +/* enumerations from "ibusproperty.h" */ +GType +ibus_prop_type_get_type (void) +{ + static GType etype = 0; + if (G_UNLIKELY(etype == 0)) { + static const GEnumValue values[] = { + { PROP_TYPE_NORMAL, "PROP_TYPE_NORMAL", "normal" }, + { PROP_TYPE_TOGGLE, "PROP_TYPE_TOGGLE", "toggle" }, + { PROP_TYPE_RADIO, "PROP_TYPE_RADIO", "radio" }, + { PROP_TYPE_MENU, "PROP_TYPE_MENU", "menu" }, + { PROP_TYPE_SEPARATOR, "PROP_TYPE_SEPARATOR", "separator" }, + { 0, NULL, NULL } + }; + etype = g_enum_register_static (g_intern_static_string ("IBusPropType"), values); + } + return etype; +} + +GType +ibus_prop_state_get_type (void) +{ + static GType etype = 0; + if (G_UNLIKELY(etype == 0)) { + static const GEnumValue values[] = { + { PROP_STATE_UNCHECKED, "PROP_STATE_UNCHECKED", "unchecked" }, + { PROP_STATE_CHECKED, "PROP_STATE_CHECKED", "checked" }, + { PROP_STATE_INCONSISTENT, "PROP_STATE_INCONSISTENT", "inconsistent" }, + { 0, NULL, NULL } + }; + etype = g_enum_register_static (g_intern_static_string ("IBusPropState"), values); + } + return etype; +} + +/* enumerations from "ibustypes.h" */ +GType +ibus_modifier_type_get_type (void) +{ + static GType etype = 0; + if (G_UNLIKELY(etype == 0)) { + static const GFlagsValue values[] = { + { IBUS_SHIFT_MASK, "IBUS_SHIFT_MASK", "shift-mask" }, + { IBUS_LOCK_MASK, "IBUS_LOCK_MASK", "lock-mask" }, + { IBUS_CONTROL_MASK, "IBUS_CONTROL_MASK", "control-mask" }, + { IBUS_MOD1_MASK, "IBUS_MOD1_MASK", "mod1-mask" }, + { IBUS_MOD2_MASK, "IBUS_MOD2_MASK", "mod2-mask" }, + { IBUS_MOD3_MASK, "IBUS_MOD3_MASK", "mod3-mask" }, + { IBUS_MOD4_MASK, "IBUS_MOD4_MASK", "mod4-mask" }, + { IBUS_MOD5_MASK, "IBUS_MOD5_MASK", "mod5-mask" }, + { IBUS_BUTTON1_MASK, "IBUS_BUTTON1_MASK", "button1-mask" }, + { IBUS_BUTTON2_MASK, "IBUS_BUTTON2_MASK", "button2-mask" }, + { IBUS_BUTTON3_MASK, "IBUS_BUTTON3_MASK", "button3-mask" }, + { IBUS_BUTTON4_MASK, "IBUS_BUTTON4_MASK", "button4-mask" }, + { IBUS_BUTTON5_MASK, "IBUS_BUTTON5_MASK", "button5-mask" }, + { IBUS_FORWARD_MASK, "IBUS_FORWARD_MASK", "forward-mask" }, + { IBUS_SUPER_MASK, "IBUS_SUPER_MASK", "super-mask" }, + { IBUS_HYPER_MASK, "IBUS_HYPER_MASK", "hyper-mask" }, + { IBUS_META_MASK, "IBUS_META_MASK", "meta-mask" }, + { IBUS_RELEASE_MASK, "IBUS_RELEASE_MASK", "release-mask" }, + { IBUS_MODIFIER_MASK, "IBUS_MODIFIER_MASK", "modifier-mask" }, + { 0, NULL, NULL } + }; + etype = g_flags_register_static (g_intern_static_string ("IBusModifierType"), values); + } + return etype; +} + +GType +ibus_capabilite_get_type (void) +{ + static GType etype = 0; + if (G_UNLIKELY(etype == 0)) { + static const GFlagsValue values[] = { + { IBUS_CAP_PREEDIT_TEXT, "IBUS_CAP_PREEDIT_TEXT", "preedit-text" }, + { IBUS_CAP_AUXILIARY_TEXT, "IBUS_CAP_AUXILIARY_TEXT", "auxiliary-text" }, + { IBUS_CAP_LOOKUP_TABLE, "IBUS_CAP_LOOKUP_TABLE", "lookup-table" }, + { IBUS_CAP_FOCUS, "IBUS_CAP_FOCUS", "focus" }, + { IBUS_CAP_PROPERTY, "IBUS_CAP_PROPERTY", "property" }, + { 0, NULL, NULL } + }; + etype = g_flags_register_static (g_intern_static_string ("IBusCapabilite"), values); + } + return etype; +} + + +/* Generated data ends here */ + diff --git a/src/ibusenumtypes.c.template b/src/ibusenumtypes.c.template new file mode 100644 index 0000000..9f607a0 --- /dev/null +++ b/src/ibusenumtypes.c.template @@ -0,0 +1,34 @@ +/*** BEGIN file-header ***/ +#include "ibus.h" + +/*** END file-header ***/ + +/*** BEGIN file-production ***/ +/* enumerations from "@filename@" */ +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType +@enum_name@_get_type (void) +{ + static GType etype = 0; + if (G_UNLIKELY(etype == 0)) { + static const G@Type@Value values[] = { +/*** END value-header ***/ + +/*** BEGIN value-production ***/ + { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, +/*** END value-production ***/ + +/*** BEGIN value-tail ***/ + { 0, NULL, NULL } + }; + etype = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); + } + return etype; +} + +/*** END value-tail ***/ + +/*** BEGIN file-tail ***/ +/*** END file-tail ***/ diff --git a/src/ibusenumtypes.h b/src/ibusenumtypes.h new file mode 100644 index 0000000..2e977a0 --- /dev/null +++ b/src/ibusenumtypes.h @@ -0,0 +1,37 @@ + +/* Generated data (by glib-mkenums) */ + +#ifndef __IBUS_ENUM_TYPES_H__ +#define __IBUS_ENUM_TYPES_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS + +/* enumerations from "ibusobject.h" */ +GType ibus_object_flags_get_type (void) G_GNUC_CONST; +#define IBUS_TYPE_OBJECT_FLAGS (ibus_object_flags_get_type ()) + +/* enumerations from "ibusattribute.h" */ +GType ibus_attr_type_get_type (void) G_GNUC_CONST; +#define IBUS_TYPE_ATTR_TYPE (ibus_attr_type_get_type ()) +GType ibus_attr_underline_get_type (void) G_GNUC_CONST; +#define IBUS_TYPE_ATTR_UNDERLINE (ibus_attr_underline_get_type ()) + +/* enumerations from "ibusproperty.h" */ +GType ibus_prop_type_get_type (void) G_GNUC_CONST; +#define IBUS_TYPE_PROP_TYPE (ibus_prop_type_get_type ()) +GType ibus_prop_state_get_type (void) G_GNUC_CONST; +#define IBUS_TYPE_PROP_STATE (ibus_prop_state_get_type ()) + +/* enumerations from "ibustypes.h" */ +GType ibus_modifier_type_get_type (void) G_GNUC_CONST; +#define IBUS_TYPE_MODIFIER_TYPE (ibus_modifier_type_get_type ()) +GType ibus_capabilite_get_type (void) G_GNUC_CONST; +#define IBUS_TYPE_CAPABILITE (ibus_capabilite_get_type ()) +G_END_DECLS + +#endif /* __IBUS_ENUM_TYPES_H__ */ + +/* Generated data ends here */ + diff --git a/src/ibusenumtypes.h.template b/src/ibusenumtypes.h.template new file mode 100644 index 0000000..15c1f02 --- /dev/null +++ b/src/ibusenumtypes.h.template @@ -0,0 +1,24 @@ +/*** BEGIN file-header ***/ +#ifndef __IBUS_ENUM_TYPES_H__ +#define __IBUS_ENUM_TYPES_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS +/*** END file-header ***/ + +/*** BEGIN file-production ***/ + +/* enumerations from "@filename@" */ +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType @enum_name@_get_type (void) G_GNUC_CONST; +#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) +/*** END value-header ***/ + +/*** BEGIN file-tail ***/ +G_END_DECLS + +#endif /* __IBUS_ENUM_TYPES_H__ */ +/*** END file-tail ***/ diff --git a/src/ibuserror.c b/src/ibuserror.c new file mode 100644 index 0000000..c55f4a4 --- /dev/null +++ b/src/ibuserror.c @@ -0,0 +1,87 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include "ibuserror.h" + +IBusError * +ibus_error_new (void) +{ + IBusError *error; + + error = g_slice_new0 (IBusError); + dbus_error_init (error); + + return error; +} + +IBusError * +ibus_error_new_from_text (const gchar *name, + const gchar *message) +{ + IBusError *error = ibus_error_new (); + + dbus_set_error (error, name, "%s", message); + + return error; +} + +IBusError * +ibus_error_new_from_printf (const gchar *name, + const gchar *format_message, + ...) +{ + IBusError *error; + gchar *message; + va_list va_args; + + va_start (va_args, format_message); + message = g_strdup_vprintf (format_message, va_args); + + error = ibus_error_new_from_text (name, message); + g_free (message); + + return error; +} + +IBusError * +ibus_error_new_from_message (DBusMessage *message) +{ + g_assert (message != NULL); + + IBusError *error; + + if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) + return NULL; + + error = ibus_error_new (); + + if (dbus_set_error_from_message (error, message)) + return error; + + dbus_error_free (error); + return NULL; +} + +void +ibus_error_free (IBusError *error) +{ + dbus_error_free (error); + g_slice_free (IBusError, error); +} + diff --git a/src/ibuserror.h b/src/ibuserror.h new file mode 100644 index 0000000..05733d5 --- /dev/null +++ b/src/ibuserror.h @@ -0,0 +1,41 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_ERROR_H_ +#define __IBUS_ERROR_H_ + +#include <glib.h> +#include <dbus/dbus.h> + +G_BEGIN_DECLS + +typedef DBusError IBusError; + +IBusError *ibus_error_new (void); +IBusError *ibus_error_new_from_text (const gchar *name, + const gchar *message); +IBusError *ibus_error_new_from_printf (const gchar *name, + const gchar *format_message, + ...); +IBusError *ibus_error_new_from_message + (DBusMessage *message); +void ibus_error_free (IBusError *error); + +G_END_DECLS +#endif diff --git a/src/ibusfactory.c b/src/ibusfactory.c new file mode 100644 index 0000000..af9d887 --- /dev/null +++ b/src/ibusfactory.c @@ -0,0 +1,483 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "ibusfactory.h" +#include "ibusengine.h" +#include "ibusshare.h" +#include "ibusinternal.h" + +#define IBUS_FACTORY_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_FACTORY, IBusFactoryPrivate)) + +enum { + LAST_SIGNAL, +}; + +/* IBusFactoryPriv */ +struct _IBusFactoryPrivate { + guint id; + IBusConnection *connection; + GList *engine_list; + GHashTable *engine_table; +}; +typedef struct _IBusFactoryPrivate IBusFactoryPrivate; + +/* functions prototype */ +static void ibus_factory_class_init (IBusFactoryClass *klass); +static void ibus_factory_init (IBusFactory *factory); +static void ibus_factory_destroy (IBusFactory *factory); +static gboolean ibus_factory_ibus_message (IBusFactory *factory, + IBusConnection *connection, + IBusMessage *message); + +static void _engine_destroy_cb (IBusEngine *engine, + IBusFactory *factory); +static void ibus_factory_info_class_init(IBusFactoryInfoClass *klass); +static void ibus_factory_info_init (IBusFactoryInfo *info); +static void ibus_factory_info_destroy (IBusFactoryInfo *info); +static gboolean ibus_factory_info_serialize (IBusFactoryInfo *info, + IBusMessageIter *iter); +static gboolean ibus_factory_info_deserialize + (IBusFactoryInfo *info, + IBusMessageIter *iter); +static gboolean ibus_factory_info_copy (IBusFactoryInfo *dest, + const IBusFactoryInfo *src); + +static IBusServiceClass *factory_parent_class = NULL; +static IBusSerializableClass *factory_info_parent_class = NULL; + +GType +ibus_factory_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusFactoryClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_factory_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusFactory), + 0, + (GInstanceInitFunc) ibus_factory_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERVICE, + "IBusFactory", + &type_info, + (GTypeFlags) 0); + } + return type; +} + +IBusFactory * +ibus_factory_new (IBusConnection *connection) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + + IBusFactory *factory; + IBusFactoryPrivate *priv; + + factory = (IBusFactory *) g_object_new (IBUS_TYPE_FACTORY, + "path", IBUS_PATH_FACTORY, + 0); + priv = IBUS_FACTORY_GET_PRIVATE (factory); + + priv->connection = g_object_ref (connection); + ibus_service_add_to_connection ((IBusService *)factory, connection); + + return factory; +} + +static void +ibus_factory_class_init (IBusFactoryClass *klass) +{ + // GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + + factory_parent_class = (IBusServiceClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusFactoryPrivate)); + + ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_factory_destroy; + + IBUS_SERVICE_CLASS (klass)->ibus_message = (ServiceIBusMessageFunc) ibus_factory_ibus_message; + +} + +static void +ibus_factory_init (IBusFactory *factory) +{ + IBusFactoryPrivate *priv; + priv = IBUS_FACTORY_GET_PRIVATE (factory); + + priv->id = 0; + priv->connection = NULL; + priv->engine_table = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + NULL); + priv->engine_list = NULL; +} + +static void +ibus_factory_destroy (IBusFactory *factory) +{ + GList *list; + IBusFactoryPrivate *priv; + priv = IBUS_FACTORY_GET_PRIVATE (factory); + + list = g_list_copy (priv->engine_list); + g_list_foreach (list, (GFunc) ibus_object_destroy, NULL); + g_list_free (priv->engine_list); + g_list_free (list); + priv->engine_list = NULL; + + if (priv->engine_table) { + g_hash_table_destroy (priv->engine_table); + } + + if (priv->connection) { + ibus_service_remove_from_connection ((IBusService *)factory, + priv->connection); + g_object_unref (priv->connection); + } + + IBUS_OBJECT_CLASS(factory_parent_class)->destroy (IBUS_OBJECT (factory)); +} + +static void +_engine_destroy_cb (IBusEngine *engine, + IBusFactory *factory) +{ + GList *list; + IBusFactoryPrivate *priv; + priv = IBUS_FACTORY_GET_PRIVATE (factory); + + list = g_list_remove (priv->engine_list, engine); + + if (list) { + g_object_unref (engine); + g_list_free_1 (list); + } +} + +static gboolean +ibus_factory_ibus_message (IBusFactory *factory, + IBusConnection *connection, + IBusMessage *message) +{ + g_assert (IBUS_IS_FACTORY (factory)); + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (message != NULL); + + IBusMessage *reply_message; + IBusFactoryPrivate *priv; + priv = IBUS_FACTORY_GET_PRIVATE (factory); + + g_assert (priv->connection == connection); + + if (ibus_message_is_method_call (message, + IBUS_INTERFACE_FACTORY, + "CreateEngine")) { + gchar *engine_name; + gchar *path; + IBusError *error; + IBusEngine *engine; + gboolean retval; + GType engine_type; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_STRING, &engine_name, + G_TYPE_INVALID); + + if (!retval) { + reply_message = ibus_message_new_error_printf (message, + DBUS_ERROR_INVALID_ARGS, + "The 1st arg should be engine name"); + ibus_connection_send (connection, reply_message); + ibus_message_unref (reply_message); + return TRUE; + } + + engine_type = (GType )g_hash_table_lookup (priv->engine_table, engine_name); + + if (engine_type == G_TYPE_INVALID) { + reply_message = ibus_message_new_error_printf (message, + DBUS_ERROR_FAILED, + "Can not create engine %s", engine_name); + ibus_connection_send (connection, reply_message); + ibus_message_unref (reply_message); + return TRUE; + + } + + path = g_strdup_printf ("/org/freedesktop/IBus/Engine/%d", ++priv->id); + + engine = g_object_new (engine_type, + "name", engine_name, + "path", path, + "connection", priv->connection, + 0); + + priv->engine_list = g_list_append (priv->engine_list, engine); + g_signal_connect (engine, + "destroy", + G_CALLBACK (_engine_destroy_cb), + factory); + + reply_message = ibus_message_new_method_return (message); + ibus_message_append_args (reply_message, + IBUS_TYPE_OBJECT_PATH, &path, + G_TYPE_INVALID); + g_free (path); + ibus_connection_send (connection, reply_message); + ibus_message_unref (reply_message); + return TRUE; + } + + return factory_parent_class->ibus_message ((IBusService *)factory, + connection, + message); +} + +void +ibus_factory_add_engine (IBusFactory *factory, + const gchar *engine_name, + GType engine_type) +{ + g_assert (IBUS_IS_FACTORY (factory)); + g_assert (engine_name); + g_assert (g_type_is_a (engine_type, IBUS_TYPE_ENGINE)); + + IBusFactoryPrivate *priv; + priv = IBUS_FACTORY_GET_PRIVATE (factory); + + g_hash_table_insert (priv->engine_table, g_strdup (engine_name), (gpointer) engine_type); +} + +#if 0 +IBusFactoryInfo * +ibus_factory_get_info (IBusFactory *factory) +{ + IBusFactoryPrivate *priv; + priv = IBUS_FACTORY_GET_PRIVATE (factory); + + return priv->info; +} +#endif + +GType +ibus_factory_info_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusFactoryInfoClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_factory_info_class_init, + NULL, /* class finialize */ + NULL, /* class data */ + sizeof (IBusFactoryInfo), + 0, + (GInstanceInitFunc) ibus_factory_info_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusFactoryInfo", + &type_info, + 0); + } + + return type; +} + +static void +ibus_factory_info_class_init (IBusFactoryInfoClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + factory_info_parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_factory_info_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_factory_info_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_factory_info_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_factory_info_copy; + + g_string_append (serializable_class->signature, "osssss"); +} + +static void +ibus_factory_info_init (IBusFactoryInfo *info) +{ + info->path = NULL; + info->name = NULL; + info->lang = NULL; + info->icon = NULL; + info->authors = NULL; + info->credits = NULL; +} + +static void +ibus_factory_info_destroy (IBusFactoryInfo *info) +{ + g_free (info->path); + g_free (info->name); + g_free (info->lang); + g_free (info->icon); + g_free (info->authors); + g_free (info->credits); + + info->path = NULL; + info->lang = NULL; + info->name = NULL; + info->icon = NULL; + info->authors = NULL; + info->credits = NULL; + + IBUS_OBJECT_CLASS (factory_info_parent_class)->destroy ((IBusObject *)info); +} + +static gboolean +ibus_factory_info_serialize (IBusFactoryInfo *info, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = factory_info_parent_class->serialize ((IBusSerializable *)info, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, IBUS_TYPE_OBJECT_PATH, &info->path); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &info->name); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &info->lang); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &info->icon); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &info->authors); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &info->credits); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_factory_info_deserialize (IBusFactoryInfo *info, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = factory_info_parent_class->deserialize ((IBusSerializable *)info, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, IBUS_TYPE_OBJECT_PATH, &info->path); + g_return_val_if_fail (retval, FALSE); + info->path = g_strdup (info->path); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &info->name); + g_return_val_if_fail (retval, FALSE); + info->name = g_strdup (info->name); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &info->lang); + g_return_val_if_fail (retval, FALSE); + info->lang = g_strdup (info->lang); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &info->icon); + g_return_val_if_fail (retval, FALSE); + info->icon = g_strdup (info->icon); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &info->authors); + g_return_val_if_fail (retval, FALSE); + info->authors = g_strdup (info->authors); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &info->credits); + g_return_val_if_fail (retval, FALSE); + info->credits = g_strdup (info->credits); + + return TRUE; +} + +static gboolean +ibus_factory_info_copy (IBusFactoryInfo *dest, + const IBusFactoryInfo *src) +{ + gboolean retval; + + retval = factory_info_parent_class->copy ((IBusSerializable *)dest, + (IBusSerializable *)src); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_FACTORY_INFO (dest), FALSE); + g_return_val_if_fail (IBUS_IS_FACTORY_INFO (src), FALSE); + + dest->path = g_strdup (src->path); + dest->name = g_strdup (src->name); + dest->lang = g_strdup (src->lang); + dest->icon = g_strdup (src->icon); + dest->authors = g_strdup (src->authors); + dest->credits = g_strdup (src->credits); + + return TRUE; +} + +IBusFactoryInfo * +ibus_factory_info_new (const gchar *path, + const gchar *name, + const gchar *lang, + const gchar *icon, + const gchar *authors, + const gchar *credits) +{ + g_assert (path); + g_assert (name); + g_assert (lang); + g_assert (icon); + g_assert (authors); + g_assert (credits); + + IBusFactoryInfo *info; + + info = (IBusFactoryInfo *)g_object_new (IBUS_TYPE_FACTORY_INFO, 0); + + info->path = g_strdup (path); + info->name = g_strdup (name); + info->lang = g_strdup (lang); + info->icon = g_strdup (icon); + info->authors = g_strdup (authors); + info->credits = g_strdup (credits); + + return info; +} + + diff --git a/src/ibusfactory.h b/src/ibusfactory.h new file mode 100644 index 0000000..02c883c --- /dev/null +++ b/src/ibusfactory.h @@ -0,0 +1,120 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_FACTORY_H_ +#define __IBUS_FACTORY_H_ + +#include <dbus/dbus.h> +#include "ibusservice.h" +#include "ibusserializable.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_FACTORY \ + (ibus_factory_get_type ()) +#define IBUS_FACTORY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_FACTORY, IBusFactory)) +#define IBUS_FACTORY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_FACTORY, IBusFactoryClass)) +#define IBUS_IS_FACTORY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_FACTORY)) +#define IBUS_IS_FACTORY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_FACTORY)) +#define IBUS_FACTORY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_FACTORY, IBusFactoryClass)) + +#define IBUS_TYPE_FACTORY_INFO \ + (ibus_factory_info_get_type ()) +#define IBUS_FACTORY_INFO(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_FACTORY_INFO, IBusFactoryInfo)) +#define IBUS_FACTORY_INFO_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_FACTORY_INFO, IBusFactoryInfoClass)) +#define IBUS_IS_FACTORY_INFO(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_FACTORY_INFO)) +#define IBUS_IS_FACTORY_INFO_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_FACTORY_INFO)) +#define IBUS_FACTORY_INFO_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_FACTORY_INFO, IBusFactoryInfoClass)) + + +G_BEGIN_DECLS + +typedef struct _IBusFactory IBusFactory; +typedef struct _IBusFactoryClass IBusFactoryClass; +typedef struct _IBusFactoryInfo IBusFactoryInfo; +typedef struct _IBusFactoryInfoClass IBusFactoryInfoClass; + +struct _IBusFactory { + IBusService parent; + + /* instance members */ +}; + +struct _IBusFactoryClass { + IBusServiceClass parent; + + /* signals */ + + /*< private >*/ + /* padding */ + gpointer pdummy[8]; +}; + +struct _IBusFactoryInfo { + IBusSerializable parent; + + /* instance members */ + gchar *path; + gchar *name; + gchar *lang; + gchar *icon; + gchar *authors; + gchar *credits; +}; + +struct _IBusFactoryInfoClass { + IBusSerializableClass parent; + + /* signals */ + + /*< private >*/ + /* padding */ + gpointer pdummy[8]; +}; + +GType ibus_factory_get_type (void); +IBusFactory *ibus_factory_new (IBusConnection *connection); +void ibus_factory_add_engine (IBusFactory *factory, + const gchar *engine_name, + GType engine_type); +IBusFactoryInfo *ibus_factory_get_info (IBusFactory *factory); +GType ibus_factory_info_get_type (void); +IBusFactoryInfo *ibus_factory_info_new (const gchar *path, + const gchar *name, + const gchar *lang, + const gchar *icon, + const gchar *authors, + const gchar *credits); + +G_END_DECLS +#endif + diff --git a/src/ibushotkey.c b/src/ibushotkey.c new file mode 100644 index 0000000..16aad70 --- /dev/null +++ b/src/ibushotkey.c @@ -0,0 +1,479 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include "ibushotkey.h" +#include "ibuskeysyms.h" +#include "ibusinternal.h" +#include "ibusshare.h" + +#define IBUS_HOTKEY_PROFILE_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_HOTKEY_PROFILE, IBusHotkeyProfilePrivate)) + +enum { + TRIGGER, + LAST_SIGNAL, +}; + +typedef struct _IBusHotkey IBusHotkey; +typedef struct _IBusHotkeyEvent IBusHotkeyEvent; +typedef struct _IBusHotkeyProfilePrivate IBusHotkeyProfilePrivate; + +struct _IBusHotkey { + guint keyval; + guint modifiers; +}; + +struct _IBusHotkeyEvent { + GQuark event; + GList *hotkeys; +}; + +struct _IBusHotkeyProfilePrivate { + GTree *hotkeys; + GArray *events; + guint mask; +}; + + + +/* functions prototype */ +static IBusHotkey *ibus_hotkey_new (guint keyval, + guint modifiers); +static IBusHotkey *ibus_hotkey_copy (const IBusHotkey *src); +static void ibus_hotkey_free (IBusHotkey *hotkey); +static gboolean ibus_hotkey_serialize (IBusHotkey *hotkey, + IBusMessageIter *iter); +static gboolean ibus_hotkey_deserialize (IBusHotkey *hotkey, + IBusMessageIter *iter); + +static void ibus_hotkey_profile_class_init (IBusHotkeyProfileClass *klass); +static void ibus_hotkey_profile_init (IBusHotkeyProfile *profile); +static void ibus_hotkey_profile_destroy (IBusHotkeyProfile *profile); +static gboolean ibus_hotkey_profile_serialize (IBusHotkeyProfile *profile, + IBusMessageIter *iter); +static gboolean ibus_hotkey_profile_deserialize(IBusHotkeyProfile *profile, + IBusMessageIter *iter); +static gboolean ibus_hotkey_profile_copy (IBusHotkeyProfile *dest, + const IBusHotkeyProfile*src); +static void ibus_hotkey_profile_trigger (IBusHotkeyProfile *profile, + GQuark event); + +static IBusSerializableClass *parent_class = NULL; + +static guint profile_signals[LAST_SIGNAL] = { 0 }; + +GType +ibus_hotkey_get_type (void) +{ + static GType type = 0; + + if (type == 0) { + type = g_boxed_type_register_static ("IBusHotkey", + (GBoxedCopyFunc) ibus_hotkey_copy, + (GBoxedFreeFunc) ibus_hotkey_free); + } + + return type; +} + +static gboolean +ibus_hotkey_serialize (IBusHotkey *hotkey, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = ibus_message_iter_append (iter, G_TYPE_UINT, &hotkey->keyval); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_UINT, &hotkey->modifiers); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_hotkey_deserialize (IBusHotkey *hotkey, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = ibus_message_iter_get (iter, G_TYPE_UINT, &hotkey->keyval); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_UINT, &hotkey->modifiers); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + + +static IBusHotkey * +ibus_hotkey_new (guint keyval, + guint modifiers) +{ + IBusHotkey *hotkey = g_slice_new (IBusHotkey); + + hotkey->keyval = keyval; + hotkey->modifiers = modifiers; + + return hotkey; +} + +static void +ibus_hotkey_free (IBusHotkey *hotkey) +{ + g_slice_free (IBusHotkey, hotkey); +} + + +static IBusHotkey * +ibus_hotkey_copy (const IBusHotkey *src) +{ + return ibus_hotkey_new (src->keyval, src->modifiers); +} + +static gint +ibus_hotkey_cmp_with_data (IBusHotkey *hotkey1, + IBusHotkey *hotkey2, + gpointer user_data) +{ + gint retval; + + if (hotkey1 == hotkey2) + return 0; + + retval = hotkey1->keyval - hotkey2->keyval; + if (retval == 0) + retval = hotkey1->modifiers - hotkey2->modifiers; + + return retval; +} + + + +GType +ibus_hotkey_profile_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusHotkeyProfileClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_hotkey_profile_class_init, + NULL, /* class finialize */ + NULL, /* class data */ + sizeof (IBusHotkeyProfile), + 0, + (GInstanceInitFunc) ibus_hotkey_profile_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusHotkeyProfile", + &type_info, + 0); + } + + return type; +} + +static void +ibus_hotkey_profile_class_init (IBusHotkeyProfileClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusHotkeyProfilePrivate)); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_hotkey_profile_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_hotkey_profile_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_hotkey_profile_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_hotkey_profile_copy; + + klass->trigger = ibus_hotkey_profile_trigger; + + g_string_append (serializable_class->signature, "av"); + + /* install signals */ + profile_signals[TRIGGER] = + g_signal_new (I_("trigger"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + G_STRUCT_OFFSET (IBusHotkeyProfileClass, trigger), + NULL, NULL, + ibus_marshal_VOID__UINT_POINTER, + G_TYPE_NONE, + 2, + G_TYPE_UINT, + G_TYPE_POINTER); +} + +static void +ibus_hotkey_profile_init (IBusHotkeyProfile *profile) +{ + IBusHotkeyProfilePrivate *priv; + priv = IBUS_HOTKEY_PROFILE_GET_PRIVATE (profile); + + priv->hotkeys = g_tree_new_full ((GCompareDataFunc) ibus_hotkey_cmp_with_data, + NULL, + (GDestroyNotify) ibus_hotkey_free, + NULL); + priv->events = g_array_new (TRUE, TRUE, sizeof (IBusHotkeyEvent)); + + priv->mask = IBUS_SHIFT_MASK | + IBUS_CONTROL_MASK | + IBUS_MOD1_MASK | + IBUS_RELEASE_MASK; +} + +static void +ibus_hotkey_profile_destroy (IBusHotkeyProfile *profile) +{ + IBusHotkeyProfilePrivate *priv; + priv = IBUS_HOTKEY_PROFILE_GET_PRIVATE (profile); + + if (priv->hotkeys) { + g_tree_destroy (priv->hotkeys); + priv->hotkeys = NULL; + } + + if (priv->events) { + IBusHotkeyEvent *events, *p; + p = events = (IBusHotkeyEvent *)g_array_free (priv->events, FALSE); + priv->events = NULL; + + while (p->event != 0) { + if (p->hotkeys) + g_list_free (p->hotkeys); + p ++; + } + g_free (events); + } + IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *)profile); +} + +static gboolean +ibus_hotkey_profile_serialize (IBusHotkeyProfile *profile, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = parent_class->serialize ((IBusSerializable *) profile, iter); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_hotkey_profile_deserialize (IBusHotkeyProfile *profile, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = parent_class->deserialize ((IBusSerializable *) profile, iter); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_hotkey_profile_copy (IBusHotkeyProfile *dest, + const IBusHotkeyProfile *src) +{ + gboolean retval; + + retval = parent_class->copy ((IBusSerializable *)dest, + (IBusSerializable *)src); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_HOTKEY_PROFILE (dest), FALSE); + g_return_val_if_fail (IBUS_IS_HOTKEY_PROFILE (src), FALSE); + + return TRUE; +} + +IBusHotkeyProfile * +ibus_hotkey_profile_new (void) +{ + IBusHotkeyProfile *profile = g_object_new (IBUS_TYPE_HOTKEY_PROFILE, 0); + + return profile; +} + +static void +ibus_hotkey_profile_trigger (IBusHotkeyProfile *profile, + GQuark event) +{ + // g_debug ("%s is triggerred", g_quark_to_string (event)); +} + +gboolean +ibus_hotkey_profile_add_hotkey (IBusHotkeyProfile *profile, + guint keyval, + guint modifiers, + GQuark event) +{ + IBusHotkeyProfilePrivate *priv; + priv = IBUS_HOTKEY_PROFILE_GET_PRIVATE (profile); + + IBusHotkey *hotkey = ibus_hotkey_new (keyval, modifiers); + + /* has the same hotkey in profile */ + if (g_tree_lookup (priv->hotkeys, hotkey) != NULL) { + ibus_hotkey_free (hotkey); + g_return_val_if_reached (FALSE); + } + + g_tree_insert (priv->hotkeys, hotkey, (gpointer)event); + + gint i; + IBusHotkeyEvent *p = NULL; + for ( i = 0; i < priv->events->len; i++) { + p = &g_array_index (priv->events, IBusHotkeyEvent, i); + if (p->event == event) + break; + } + + if (i >= priv->events->len) { + g_array_set_size (priv->events, i + 1); + p = &g_array_index (priv->events, IBusHotkeyEvent, i); + p->event = event; + } + + p->hotkeys = g_list_append (p->hotkeys, hotkey); + + return TRUE; +} + + +gboolean +ibus_hotkey_profile_add_hotkey_from_string (IBusHotkeyProfile *profile, + const gchar *str, + GQuark event) +{ + guint keyval; + guint modifiers; + + if (ibus_key_event_from_string (str, &keyval, &modifiers) == FALSE) { + return FALSE; + } + + return ibus_hotkey_profile_add_hotkey (profile, keyval, modifiers, event); +} + +gboolean +ibus_hotkey_profile_remove_hotkey (IBusHotkeyProfile *profile, + guint keyval, + guint modifiers) +{ + IBusHotkeyProfilePrivate *priv; + priv = IBUS_HOTKEY_PROFILE_GET_PRIVATE (profile); + + IBusHotkey hotkey = { + keyval : keyval, + modifiers : modifiers + }; + + IBusHotkey *p1; + GQuark event; + gboolean retval; + + retval = g_tree_lookup_extended (priv->hotkeys, + &hotkey, + (gpointer)&p1, + (gpointer)&event); + + if (!retval) + return FALSE; + + gint i; + IBusHotkeyEvent *p2 = NULL; + for ( i = 0; i < priv->events->len; i++) { + p2 = &g_array_index (priv->events, IBusHotkeyEvent, i); + if (p2->event == event) + break; + } + + g_assert (p2->event == event); + + p2->hotkeys = g_list_remove (p2->hotkeys, p1); + if (p2->hotkeys == NULL) { + g_array_remove_index_fast (priv->events, i); + } + + g_tree_remove (priv->hotkeys, p1); + + return TRUE; +} + +gboolean +ibus_hotkey_profile_remove_hotkey_by_event (IBusHotkeyProfile *profile, + GQuark event) +{ + IBusHotkeyProfilePrivate *priv; + priv = IBUS_HOTKEY_PROFILE_GET_PRIVATE (profile); + + gint i; + IBusHotkeyEvent *p = NULL; + for ( i = 0; i < priv->events->len; i++) { + p = &g_array_index (priv->events, IBusHotkeyEvent, i); + if (p->event == event) + break; + } + + if (p == NULL || p->event != event) + return FALSE; + + GList *list; + for (list = p->hotkeys; list != NULL; list = list->next) { + g_tree_remove (priv->hotkeys, (IBusHotkey *)list->data); + } + + g_list_free (p->hotkeys); + g_array_remove_index_fast (priv->events, i); + + return TRUE; +} + +GQuark +ibus_hotkey_profile_filter_key_event (IBusHotkeyProfile *profile, + guint keyval, + guint modifiers, + gpointer user_data) +{ + IBusHotkeyProfilePrivate *priv; + priv = IBUS_HOTKEY_PROFILE_GET_PRIVATE (profile); + + IBusHotkey hotkey = { + keyval : keyval, + modifiers : modifiers & priv->mask, + }; + + GQuark event = (GQuark) g_tree_lookup (priv->hotkeys, &hotkey); + + if (event != 0) { + g_signal_emit (profile, profile_signals[TRIGGER], event, event, user_data); + } + + return event; +} diff --git a/src/ibushotkey.h b/src/ibushotkey.h new file mode 100644 index 0000000..75b0844 --- /dev/null +++ b/src/ibushotkey.h @@ -0,0 +1,87 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_HOTKEY_H_ +#define __IBUS_HOTKEY_H_ + +#include "ibusserializable.h" + +/* + * Type macros. + */ +/* define IBusHotkeyProfile macros */ +#define IBUS_TYPE_HOTKEY_PROFILE \ + (ibus_hotkey_profile_get_type ()) +#define IBUS_HOTKEY_PROFILE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_HOTKEY_PROFILE, IBusHotkeyProfile)) +#define IBUS_HOTKEY_PROFILE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_HOTKEY_PROFILE, IBusHotkeyProfileClass)) +#define IBUS_IS_HOTKEY_PROFILE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_HOTKEY_PROFILE)) +#define IBUS_IS_HOTKEY_PROFILE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_HOTKEY_PROFILE)) +#define IBUS_HOTKEY_PROFILE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_HOTKEY_PROFILE, IBusHotkeyProfileClass)) + +G_BEGIN_DECLS + +typedef struct _IBusHotkeyProfile IBusHotkeyProfile; +typedef struct _IBusHotkeyProfileClass IBusHotkeyProfileClass; + +struct _IBusHotkeyProfile { + IBusSerializable parent; + + /* members */ +}; + +struct _IBusHotkeyProfileClass { + IBusSerializableClass parent; + + void (* trigger) (IBusHotkeyProfile *profile, + GQuark event); +}; + +/* hotkey profile functions */ +GType ibus_hotkey_profile_get_type (void); +IBusHotkeyProfile + *ibus_hotkey_profile_new (void); +gboolean ibus_hotkey_profile_add_hotkey (IBusHotkeyProfile *profile, + guint keyval, + guint modifiers, + GQuark event); +gboolean ibus_hotkey_profile_add_hotkey_from_string + (IBusHotkeyProfile *profile, + const gchar *str, + GQuark event); +gboolean ibus_hotkey_profile_remove_hotkey + (IBusHotkeyProfile *profile, + guint keyval, + guint modifiers); +gboolean ibus_hotkey_profile_remove_hotkey_by_event + (IBusHotkeyProfile *profile, + GQuark event); +GQuark ibus_hotkey_profile_filter_key_event + (IBusHotkeyProfile *profile, + guint keyval, + guint modifiers, + gpointer user_data); + +G_END_DECLS +#endif + diff --git a/src/ibusinputcontext.c b/src/ibusinputcontext.c new file mode 100644 index 0000000..71de8fb --- /dev/null +++ b/src/ibusinputcontext.c @@ -0,0 +1,695 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include "ibusshare.h" +#include "ibusinternal.h" +#include "ibusinputcontext.h" +#include "ibusattribute.h" +#include "ibuslookuptable.h" +#include "ibusproperty.h" + +#define IBUS_INPUT_CONTEXT_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_INPUT_CONTEXT, IBusInputContextPrivate)) + +enum { + ENABLED, + DISABLED, + COMMIT_TEXT, + FORWARD_KEY_EVENT, + UPDATE_PREEDIT_TEXT, + SHOW_PREEDIT_TEXT, + HIDE_PREEDIT_TEXT, + UPDATE_AUXILIARY_TEXT, + SHOW_AUXILIARY_TEXT, + HIDE_AUXILIARY_TEXT, + UPDATE_LOOKUP_TABLE, + SHOW_LOOKUP_TABLE, + HIDE_LOOKUP_TABLE, + PAGE_UP_LOOKUP_TABLE, + PAGE_DOWN_LOOKUP_TABLE, + CURSOR_UP_LOOKUP_TABLE, + CURSOR_DOWN_LOOKUP_TABLE, + REGISTER_PROPERTIES, + UPDATE_PROPERTY, + LAST_SIGNAL, +}; + + +/* BusInputContextPriv */ +struct _IBusInputContextPrivate { + void *pad; +}; +typedef struct _IBusInputContextPrivate IBusInputContextPrivate; + +static guint context_signals[LAST_SIGNAL] = { 0 }; +// static guint context_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_input_context_class_init (IBusInputContextClass *klass); +static void ibus_input_context_init (IBusInputContext *context); +static void ibus_input_context_real_destroy (IBusInputContext *context); +static gboolean ibus_input_context_ibus_signal (IBusProxy *proxy, + DBusMessage *message); + +static IBusProxyClass *parent_class = NULL; + +GType +ibus_input_context_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusInputContextClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_input_context_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusInputContext), + 0, + (GInstanceInitFunc) ibus_input_context_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_PROXY, + "IBusInputContext", + &type_info, + (GTypeFlags)0); + } + return type; +} + +IBusInputContext * +ibus_input_context_new (const gchar *path, + IBusConnection *connection) +{ + g_assert (path != NULL); + g_assert (IBUS_IS_CONNECTION (connection)); + GObject *obj; + + obj = g_object_new (IBUS_TYPE_INPUT_CONTEXT, + "name", IBUS_SERVICE_IBUS, + "path", path, + "connection", connection, + NULL); + + return IBUS_INPUT_CONTEXT (obj); +} + +static void +ibus_input_context_class_init (IBusInputContextClass *klass) +{ + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + IBusProxyClass *proxy_class = IBUS_PROXY_CLASS (klass); + + + parent_class = (IBusProxyClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusInputContextPrivate)); + + ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_input_context_real_destroy; + + proxy_class->ibus_signal = ibus_input_context_ibus_signal; + + /* install signals */ + context_signals[ENABLED] = + g_signal_new (I_("enabled"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[DISABLED] = + g_signal_new (I_("disabled"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[COMMIT_TEXT] = + g_signal_new (I_("commit-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + IBUS_TYPE_TEXT); + + context_signals[FORWARD_KEY_EVENT] = + g_signal_new (I_("forward-key-event"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__UINT_UINT, + G_TYPE_NONE, + 2, + G_TYPE_UINT, + G_TYPE_UINT); + + context_signals[UPDATE_PREEDIT_TEXT] = + g_signal_new (I_("update-preedit-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT_UINT_BOOLEAN, + G_TYPE_NONE, + 3, + IBUS_TYPE_TEXT, + G_TYPE_UINT, + G_TYPE_BOOLEAN); + + context_signals[SHOW_PREEDIT_TEXT] = + g_signal_new (I_("show-preedit-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[HIDE_PREEDIT_TEXT] = + g_signal_new (I_("hide-preedit-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[UPDATE_AUXILIARY_TEXT] = + g_signal_new (I_("update-auxiliary-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT_BOOLEAN, + G_TYPE_NONE, 2, + IBUS_TYPE_TEXT, + G_TYPE_BOOLEAN); + + context_signals[SHOW_AUXILIARY_TEXT] = + g_signal_new (I_("show-auxiliary-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[HIDE_AUXILIARY_TEXT] = + g_signal_new (I_("hide-auxiliary-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[UPDATE_LOOKUP_TABLE] = + g_signal_new (I_("update-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT_BOOLEAN, + G_TYPE_NONE, 2, + IBUS_TYPE_LOOKUP_TABLE, + G_TYPE_BOOLEAN); + + context_signals[SHOW_LOOKUP_TABLE] = + g_signal_new (I_("show-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[HIDE_LOOKUP_TABLE] = + g_signal_new (I_("hide-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[PAGE_UP_LOOKUP_TABLE] = + g_signal_new (I_("page-up-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[PAGE_DOWN_LOOKUP_TABLE] = + g_signal_new (I_("page-down-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[CURSOR_UP_LOOKUP_TABLE] = + g_signal_new (I_("cursor-up-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[CURSOR_DOWN_LOOKUP_TABLE] = + g_signal_new (I_("cursor-down-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + context_signals[REGISTER_PROPERTIES] = + g_signal_new (I_("register-properties"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + IBUS_TYPE_PROP_LIST); + + context_signals[UPDATE_PROPERTY] = + g_signal_new (I_("update-property"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + IBUS_TYPE_PROPERTY); +} + +static void +ibus_input_context_init (IBusInputContext *context) +{ + IBusInputContextPrivate *priv; + priv = IBUS_INPUT_CONTEXT_GET_PRIVATE (context); +} + +static void +ibus_input_context_real_destroy (IBusInputContext *context) +{ + if (ibus_proxy_get_connection ((IBusProxy *) context) != NULL) { + ibus_proxy_call (IBUS_PROXY (context), + "Destroy", + G_TYPE_INVALID); + } + + IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (context)); +} + +static gboolean +ibus_input_context_ibus_signal (IBusProxy *proxy, + IBusMessage *message) +{ + g_assert (IBUS_IS_INPUT_CONTEXT (proxy)); + g_assert (message != NULL); + + IBusInputContext *context; + IBusError *error = NULL; + gint i; + + context = IBUS_INPUT_CONTEXT (proxy); + + static const struct { + const gchar *member; + guint signal_id; + } signals [] = { + { "Enabled", ENABLED }, + { "Disabled", DISABLED }, + { "ShowPreeditText", SHOW_PREEDIT_TEXT }, + { "HidePreeditText", HIDE_PREEDIT_TEXT }, + { "ShowAuxiliaryText", SHOW_AUXILIARY_TEXT }, + { "HideAuxiliaryText", HIDE_AUXILIARY_TEXT }, + { "ShowLookupTable", SHOW_LOOKUP_TABLE }, + { "HideLookupTable", HIDE_LOOKUP_TABLE }, + { "PageUpLookupTable", PAGE_UP_LOOKUP_TABLE }, + { "PageDownLookupTable", PAGE_DOWN_LOOKUP_TABLE }, + { "CursorUpLookupTable", CURSOR_UP_LOOKUP_TABLE }, + { "CursorDownLookupTable", CURSOR_DOWN_LOOKUP_TABLE}, + { NULL, 0}, + }; + + for (i = 0; ; i++) { + if (signals[i].member == NULL) + break; + if (ibus_message_is_signal (message, + IBUS_INTERFACE_INPUT_CONTEXT, + signals[i].member)) { + g_signal_emit (context, context_signals[signals[i].signal_id], 0); + goto handled; + } + } + + if (ibus_message_is_signal (message, + IBUS_INTERFACE_INPUT_CONTEXT, + "CommitText")) { + IBusText *text; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_TEXT, &text, + G_TYPE_INVALID); + if (!retval) + goto failed; + + g_signal_emit (context, context_signals[COMMIT_TEXT], 0, text); + g_object_unref (text); + } + else if (ibus_message_is_signal (message, + IBUS_INTERFACE_INPUT_CONTEXT, + "UpdatePreeditText")) { + IBusText *text; + gint32 cursor_pos; + gboolean visible; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_TEXT, &text, + G_TYPE_UINT, &cursor_pos, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); + + if (!retval) + goto failed; + + g_signal_emit (context, + context_signals[UPDATE_PREEDIT_TEXT], + 0, + text, + cursor_pos, + visible); + g_object_unref (text); + } + else if (ibus_message_is_signal (message, + IBUS_INTERFACE_INPUT_CONTEXT, + "ForwardKeyEvent")) { + guint32 keyval; + gboolean is_press; + guint32 state; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_UINT, &keyval, + G_TYPE_BOOLEAN, &is_press, + G_TYPE_UINT, &state, + G_TYPE_INVALID); + + if (!retval) + goto failed; + g_signal_emit (context, + context_signals[FORWARD_KEY_EVENT], + 0, + keyval, + state | IBUS_FORWARD_MASK); + } + else if (ibus_message_is_signal (message, + IBUS_INTERFACE_INPUT_CONTEXT, + "UpdateAuxiliaryText")) { + IBusText *text; + gboolean visible; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_TEXT, &text, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); + + if (!retval) + goto failed; + + g_signal_emit (context, + context_signals[UPDATE_AUXILIARY_TEXT], + 0, + text, + visible); + g_object_unref (text); + } + else if (ibus_message_is_signal (message, + IBUS_INTERFACE_INPUT_CONTEXT, + "UpdateLookupTable")) { + IBusLookupTable *table; + gboolean visible; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_LOOKUP_TABLE, &table, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); + + if (!retval) + goto failed; + + g_signal_emit (context, + context_signals[UPDATE_LOOKUP_TABLE], + 0, + table, + visible); + g_object_unref (table); + } + else if (ibus_message_is_signal (message, + IBUS_INTERFACE_INPUT_CONTEXT, + "RegisterProperties")) { + IBusPropList *prop_list; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_PROP_LIST, &prop_list, + G_TYPE_INVALID); + + if (!retval) + goto failed; + + g_signal_emit (context, + context_signals[REGISTER_PROPERTIES], + 0, + prop_list); + g_object_unref (prop_list); + } + else if (ibus_message_is_signal (message, + IBUS_INTERFACE_INPUT_CONTEXT, + "UpdateProperty")) { + IBusProperty *prop; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_PROPERTY, &prop, + G_TYPE_INVALID); + if (!retval) + goto failed; + + g_signal_emit (context, context_signals[UPDATE_PROPERTY], 0, prop); + g_object_unref (prop); + } + else { + return FALSE; + } + +handled: + g_signal_stop_emission_by_name (context, "ibus-signal"); + return TRUE; + +failed: + if (error) { + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + } + return FALSE; +} + +gboolean +ibus_input_context_process_key_event (IBusInputContext *context, + guint32 keyval, + guint32 state) +{ + g_assert (IBUS_IS_INPUT_CONTEXT (context)); + + IBusMessage *reply_message; + IBusPendingCall *pending = NULL; + IBusError *error = NULL; + gboolean retval; + + if (state & IBUS_FORWARD_MASK) + return FALSE; + + retval = ibus_proxy_call_with_reply ((IBusProxy *) context, + "ProcessKeyEvent", + &pending, + -1, + &error, + G_TYPE_UINT, &keyval, + G_TYPE_UINT, &state, + G_TYPE_INVALID); + if (!retval) { + g_debug ("%s: %s", error->name, error->message); + ibus_error_free (error); + return FALSE; + } + + /* wait reply or timeout */ + ibus_pending_call_wait (pending); + + reply_message = ibus_pending_call_steal_reply (pending); + ibus_pending_call_unref (pending); + + if (reply_message == NULL) { + g_debug ("%s: Do not recevie reply of ProcessKeyEvent", DBUS_ERROR_NO_REPLY); + retval = FALSE; + } + else if ((error = ibus_error_new_from_message (reply_message)) != NULL) { + g_debug ("%s: %s", error->name, error->message); + ibus_message_unref (reply_message); + ibus_error_free (error); + retval = FALSE; + } + else { + + if (!ibus_message_get_args (reply_message, + &error, + G_TYPE_BOOLEAN, &retval, + G_TYPE_INVALID)) { + g_debug ("%s: %s", error->name, error->message); + ibus_error_free (error); + retval = FALSE; + } + ibus_message_unref (reply_message); + } + return retval; +} + +void +ibus_input_context_set_cursor_location (IBusInputContext *context, + gint32 x, + gint32 y, + gint32 w, + gint32 h) +{ + g_assert (IBUS_IS_INPUT_CONTEXT (context)); + + ibus_proxy_call ((IBusProxy *) context, + "SetCursorLocation", + G_TYPE_INT, &x, + G_TYPE_INT, &y, + G_TYPE_INT, &w, + G_TYPE_INT, &h, + G_TYPE_INVALID); +} + +void +ibus_input_context_set_capabilities (IBusInputContext *context, + guint32 capabilites) +{ + g_assert (IBUS_IS_INPUT_CONTEXT (context)); + + ibus_proxy_call ((IBusProxy *) context, + "SetCapabilities", + G_TYPE_UINT, &capabilites, + G_TYPE_INVALID); +} + +void +ibus_input_context_property_activate (IBusInputContext *context, + const gchar *prop_name, + gint32 state) +{ + g_assert (IBUS_IS_INPUT_CONTEXT (context)); + + ibus_proxy_call ((IBusProxy *) context, + "PropertyActivate", + G_TYPE_STRING, &prop_name, + G_TYPE_INT, &state, + G_TYPE_INVALID); +} + +void +ibus_input_context_property_show (IBusInputContext *context, + const gchar *prop_name) +{ + g_assert (IBUS_IS_INPUT_CONTEXT (context)); + + ibus_proxy_call ((IBusProxy *) context, + "PropertyShow", + G_TYPE_STRING, &prop_name, + G_TYPE_INVALID); +} + +void +ibus_input_context_property_hide (IBusInputContext *context, + const gchar *prop_name) +{ + g_assert (IBUS_IS_INPUT_CONTEXT (context)); + + ibus_proxy_call ((IBusProxy *) context, + "PropertyHide", + G_TYPE_STRING, &prop_name, + G_TYPE_INVALID); +} + +#define DEFINE_FUNC(name,Name) \ + void \ + ibus_input_context_##name (IBusInputContext *context) \ + { \ + g_assert (IBUS_IS_INPUT_CONTEXT (context)); \ + ibus_proxy_call ((IBusProxy *) context, \ + #Name, \ + G_TYPE_INVALID); \ + } + +DEFINE_FUNC(focus_in, FocusIn); +DEFINE_FUNC(focus_out, FocusOut); +DEFINE_FUNC(reset, Reset); +DEFINE_FUNC(page_up, PageUp); +DEFINE_FUNC(page_down, PageDown); +DEFINE_FUNC(cursor_up, CursorUp); +DEFINE_FUNC(cursor_down, CursorDown); +DEFINE_FUNC(enable, Enable); +DEFINE_FUNC(disable, Disable); + +#undef DEFINE_FUNC + diff --git a/src/ibusinputcontext.h b/src/ibusinputcontext.h new file mode 100644 index 0000000..3ec1bf9 --- /dev/null +++ b/src/ibusinputcontext.h @@ -0,0 +1,87 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; 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 "ibusproxy.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_INPUT_CONTEXT \ + (ibus_input_context_get_type ()) +#define IBUS_INPUT_CONTEXT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_INPUT_CONTEXT, IBusInputContext)) +#define IBUS_INPUT_CONTEXT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_INPUT_CONTEXT, IBusInputContextClass)) +#define IBUS_IS_INPUT_CONTEXT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_INPUT_CONTEXT)) +#define IBUS_IS_INPUT_CONTEXT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_INPUT_CONTEXT)) +#define IBUS_INPUT_CONTEXT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_INPUT_CONTEXT, IBusInputContextClass)) + +G_BEGIN_DECLS + +typedef struct _IBusInputContext IBusInputContext; +typedef struct _IBusInputContextClass IBusInputContextClass; + +struct _IBusInputContext { + IBusProxy parent; + /* instance members */ +}; + +struct _IBusInputContextClass { + IBusProxyClass parent; + /* signals */ + + /*< private >*/ + /* padding */ + gpointer pdummy[24]; +}; + +GType ibus_input_context_get_type (void); +IBusInputContext + *ibus_input_context_new (const gchar *path, + IBusConnection *connection); +gboolean ibus_input_context_process_key_event + (IBusInputContext *context, + guint32 keyval, + guint32 state); +void ibus_input_context_set_cursor_location + (IBusInputContext *context, + gint32 x, + gint32 y, + gint32 w, + gint32 h); +void ibus_input_context_set_capabilities + (IBusInputContext *context, + guint32 capabilites); +void ibus_input_context_focus_in (IBusInputContext *context); +void ibus_input_context_focus_out (IBusInputContext *context); +void ibus_input_context_reset (IBusInputContext *context); +void ibus_input_context_enable (IBusInputContext *context); +void ibus_input_context_disable (IBusInputContext *context); + +G_END_DECLS +#endif + diff --git a/src/ibusinternal.c b/src/ibusinternal.c new file mode 100644 index 0000000..3610b52 --- /dev/null +++ b/src/ibusinternal.c @@ -0,0 +1,667 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-gmain.c GLib main loop integration + * + * Copyright (C) 2002, 2003 CodeFactory AB + * Copyright (C) 2005 Red Hat, Inc. + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 "ibusinternal.h" + +/** + * IBusMessageQueue: + * A GSource subclass for dispatching DBusConnection messages. + * We need this on top of the IO handlers, because sometimes + * there are messages to dispatch queued up but no IO pending. + */ +typedef struct +{ + GSource source; /**< the parent GSource */ + DBusConnection *connection; /**< the connection to dispatch */ +} IBusMessageQueue; + +static gboolean message_queue_prepare (GSource *source, + gint *timeout); +static gboolean message_queue_check (GSource *source); +static gboolean message_queue_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data); + +static const GSourceFuncs message_queue_funcs = { + message_queue_prepare, + message_queue_check, + message_queue_dispatch, + NULL +}; + +static gboolean +message_queue_prepare (GSource *source, + gint *timeout) +{ + DBusConnection *connection = ((IBusMessageQueue *)source)->connection; + + *timeout = -1; + + return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS); +} + +static gboolean +message_queue_check (GSource *source) +{ + return FALSE; +} + +static gboolean +message_queue_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + DBusConnection *connection = ((IBusMessageQueue *)source)->connection; + + dbus_connection_ref (connection); + + /* Only dispatch once - we don't want to starve other GSource */ + dbus_connection_dispatch (connection); + + dbus_connection_unref (connection); + + return TRUE; +} + +typedef struct +{ + GMainContext *context; /**< the main context */ + GSList *ios; /**< all IOHandler */ + GSList *timeouts; /**< all TimeoutHandler */ + DBusConnection *connection; /**< NULL if this is really for a server not a connection */ + GSource *message_queue_source; /**< IBusMessageQueue */ +} ConnectionSetup; + + +typedef struct +{ + ConnectionSetup *cs; + GSource *source; + DBusWatch *watch; +} IOHandler; + +typedef struct +{ + ConnectionSetup *cs; + GSource *source; + DBusTimeout *timeout; +} TimeoutHandler; + +dbus_int32_t _dbus_gmain_connection_slot = -1; +static dbus_int32_t server_slot = -1; + +static ConnectionSetup* +connection_setup_new (GMainContext *context, + DBusConnection *connection) +{ + ConnectionSetup *cs; + + cs = g_new0 (ConnectionSetup, 1); + + g_assert (context != NULL); + + cs->context = context; + g_main_context_ref (cs->context); + + if (connection) + { + cs->connection = connection; + + cs->message_queue_source = g_source_new ((GSourceFuncs *) &message_queue_funcs, + sizeof (IBusMessageQueue)); + ((IBusMessageQueue*)cs->message_queue_source)->connection = connection; + g_source_attach (cs->message_queue_source, cs->context); + } + + return cs; +} + +static void +io_handler_source_finalized (gpointer data) +{ + IOHandler *handler; + + handler = data; + + if (handler->watch) + dbus_watch_set_data (handler->watch, NULL, NULL); + + g_free (handler); +} + +static void +io_handler_destroy_source (void *data) +{ + IOHandler *handler; + + handler = data; + + if (handler->source) + { + GSource *source = handler->source; + handler->source = NULL; + handler->cs->ios = g_slist_remove (handler->cs->ios, handler); + g_source_destroy (source); + g_source_unref (source); + } +} + +static void +io_handler_watch_freed (void *data) +{ + IOHandler *handler; + + handler = data; + + handler->watch = NULL; + + io_handler_destroy_source (handler); +} + +static gboolean +io_handler_dispatch (GIOChannel *source, + GIOCondition condition, + gpointer data) +{ + IOHandler *handler; + guint dbus_condition = 0; + DBusConnection *connection; + + handler = data; + + connection = handler->cs->connection; + + if (connection) + dbus_connection_ref (connection); + + if (condition & G_IO_IN) + dbus_condition |= DBUS_WATCH_READABLE; + if (condition & G_IO_OUT) + dbus_condition |= DBUS_WATCH_WRITABLE; + if (condition & G_IO_ERR) + dbus_condition |= DBUS_WATCH_ERROR; + if (condition & G_IO_HUP) + dbus_condition |= DBUS_WATCH_HANGUP; + + /* Note that we don't touch the handler after this, because + * dbus may have disabled the watch and thus killed the + * handler. + */ + dbus_watch_handle (handler->watch, dbus_condition); + handler = NULL; + + if (connection) + dbus_connection_unref (connection); + + return TRUE; +} + +static void +connection_setup_add_watch (ConnectionSetup *cs, + DBusWatch *watch) +{ + guint flags; + GIOCondition condition; + GIOChannel *channel; + IOHandler *handler; + + if (!dbus_watch_get_enabled (watch)) + return; + + g_assert (dbus_watch_get_data (watch) == NULL); + + flags = dbus_watch_get_flags (watch); + + condition = G_IO_ERR | G_IO_HUP; + if (flags & DBUS_WATCH_READABLE) + condition |= G_IO_IN; + if (flags & DBUS_WATCH_WRITABLE) + condition |= G_IO_OUT; + + handler = g_new0 (IOHandler, 1); + handler->cs = cs; + handler->watch = watch; + + channel = g_io_channel_unix_new (dbus_watch_get_unix_fd (watch)); + + handler->source = g_io_create_watch (channel, condition); + g_source_set_callback (handler->source, (GSourceFunc) io_handler_dispatch, handler, + io_handler_source_finalized); + g_source_attach (handler->source, cs->context); + + cs->ios = g_slist_prepend (cs->ios, handler); + + dbus_watch_set_data (watch, handler, io_handler_watch_freed); + g_io_channel_unref (channel); +} + +static void +connection_setup_remove_watch (ConnectionSetup *cs, + DBusWatch *watch) +{ + IOHandler *handler; + + handler = dbus_watch_get_data (watch); + + if (handler == NULL) + return; + + io_handler_destroy_source (handler); +} + +static void +timeout_handler_source_finalized (gpointer data) +{ + TimeoutHandler *handler; + + handler = data; + + if (handler->timeout) + dbus_timeout_set_data (handler->timeout, NULL, NULL); + + g_free (handler); +} + +static void +timeout_handler_destroy_source (void *data) +{ + TimeoutHandler *handler; + + handler = data; + + if (handler->source) + { + GSource *source = handler->source; + handler->source = NULL; + handler->cs->timeouts = g_slist_remove (handler->cs->timeouts, handler); + g_source_destroy (source); + g_source_unref (source); + } +} + +static void +timeout_handler_timeout_freed (void *data) +{ + TimeoutHandler *handler; + + handler = data; + + handler->timeout = NULL; + + timeout_handler_destroy_source (handler); +} + +static gboolean +timeout_handler_dispatch (gpointer data) +{ + TimeoutHandler *handler; + + handler = data; + + dbus_timeout_handle (handler->timeout); + + return TRUE; +} + +static void +connection_setup_add_timeout (ConnectionSetup *cs, + DBusTimeout *timeout) +{ + TimeoutHandler *handler; + + if (!dbus_timeout_get_enabled (timeout)) + return; + + g_assert (dbus_timeout_get_data (timeout) == NULL); + + handler = g_new0 (TimeoutHandler, 1); + handler->cs = cs; + handler->timeout = timeout; + + handler->source = g_timeout_source_new (dbus_timeout_get_interval (timeout)); + g_source_set_callback (handler->source, timeout_handler_dispatch, handler, + timeout_handler_source_finalized); + g_source_attach (handler->source, handler->cs->context); + + cs->timeouts = g_slist_prepend (cs->timeouts, handler); + + dbus_timeout_set_data (timeout, handler, timeout_handler_timeout_freed); +} + +static void +connection_setup_remove_timeout (ConnectionSetup *cs, + DBusTimeout *timeout) +{ + TimeoutHandler *handler; + + handler = dbus_timeout_get_data (timeout); + + if (handler == NULL) + return; + + timeout_handler_destroy_source (handler); +} + +static void +connection_setup_free (ConnectionSetup *cs) +{ + while (cs->ios) + io_handler_destroy_source (cs->ios->data); + + while (cs->timeouts) + timeout_handler_destroy_source (cs->timeouts->data); + + if (cs->message_queue_source) + { + GSource *source; + + source = cs->message_queue_source; + cs->message_queue_source = NULL; + + g_source_destroy (source); + g_source_unref (source); + } + + g_main_context_unref (cs->context); + g_free (cs); +} + +static dbus_bool_t +add_watch (DBusWatch *watch, + gpointer data) +{ + ConnectionSetup *cs; + + cs = data; + + connection_setup_add_watch (cs, watch); + + return TRUE; +} + +static void +remove_watch (DBusWatch *watch, + gpointer data) +{ + ConnectionSetup *cs; + + cs = data; + + connection_setup_remove_watch (cs, watch); +} + +static void +watch_toggled (DBusWatch *watch, + void *data) +{ + /* Because we just exit on OOM, enable/disable is + * no different from add/remove + */ + if (dbus_watch_get_enabled (watch)) + add_watch (watch, data); + else + remove_watch (watch, data); +} + +static dbus_bool_t +add_timeout (DBusTimeout *timeout, + void *data) +{ + ConnectionSetup *cs; + + cs = data; + + if (!dbus_timeout_get_enabled (timeout)) + return TRUE; + + connection_setup_add_timeout (cs, timeout); + + return TRUE; +} + +static void +remove_timeout (DBusTimeout *timeout, + void *data) +{ + ConnectionSetup *cs; + + cs = data; + + connection_setup_remove_timeout (cs, timeout); +} + +static void +timeout_toggled (DBusTimeout *timeout, + void *data) +{ + /* Because we just exit on OOM, enable/disable is + * no different from add/remove + */ + if (dbus_timeout_get_enabled (timeout)) + add_timeout (timeout, data); + else + remove_timeout (timeout, data); +} + +static void +wakeup_main (void *data) +{ + ConnectionSetup *cs = data; + + g_main_context_wakeup (cs->context); +} + + +/* Move to a new context */ +static ConnectionSetup* +connection_setup_new_from_old (GMainContext *context, + ConnectionSetup *old) +{ + GSList *tmp; + ConnectionSetup *cs; + + g_assert (old->context != context); + + cs = connection_setup_new (context, old->connection); + + tmp = old->ios; + while (tmp != NULL) + { + IOHandler *handler = tmp->data; + + connection_setup_add_watch (cs, handler->watch); + + tmp = tmp->next; + } + + tmp = old->timeouts; + while (tmp != NULL) + { + TimeoutHandler *handler = tmp->data; + + connection_setup_add_timeout (cs, handler->timeout); + + tmp = tmp->next; + } + + return cs; +} + +/** @} */ /* End of GLib bindings internals */ + +/** @addtogroup IBusLib + * @{ + */ + +/** + * dbus_connection_setup_with_g_main: + * @connection: the connection + * @context: the #GMainContext or #NULL for default context + * + * Sets the watch and timeout functions of a #DBusConnection + * to integrate the connection with the GLib main loop. + * Pass in #NULL for the #GMainContext unless you're + * doing something specialized. + * + * If called twice for the same context, does nothing the second + * time. If called once with context A and once with context B, + * context B replaces context A as the context monitoring the + * connection. + */ +void +dbus_connection_setup (DBusConnection *connection, + GMainContext *context) +{ + ConnectionSetup *old_setup; + ConnectionSetup *cs; + + /* FIXME we never free the slot, so its refcount just keeps growing, + * which is kind of broken. + */ + dbus_connection_allocate_data_slot (&_dbus_gmain_connection_slot); + if (_dbus_gmain_connection_slot < 0) + goto nomem; + + if (context == NULL) + context = g_main_context_default (); + + cs = NULL; + + old_setup = dbus_connection_get_data (connection, _dbus_gmain_connection_slot); + if (old_setup != NULL) + { + if (old_setup->context == context) + return; /* nothing to do */ + + cs = connection_setup_new_from_old (context, old_setup); + + /* Nuke the old setup */ + dbus_connection_set_data (connection, _dbus_gmain_connection_slot, NULL, NULL); + old_setup = NULL; + } + + if (cs == NULL) + cs = connection_setup_new (context, connection); + + if (!dbus_connection_set_data (connection, _dbus_gmain_connection_slot, cs, + (DBusFreeFunction)connection_setup_free)) + goto nomem; + + if (!dbus_connection_set_watch_functions (connection, + add_watch, + remove_watch, + watch_toggled, + cs, NULL)) + goto nomem; + + if (!dbus_connection_set_timeout_functions (connection, + add_timeout, + remove_timeout, + timeout_toggled, + cs, NULL)) + goto nomem; + + dbus_connection_set_wakeup_main_function (connection, + wakeup_main, + cs, NULL); + + return; + + nomem: + g_error ("Not enough memory to set up DBusConnection for use with GLib"); +} + +/** + * dbus_server_setup_with_g_main: + * @server: the server + * @context: the #GMainContext or #NULL for default + * + * Sets the watch and timeout functions of a #DBusServer + * to integrate the server with the GLib main loop. + * In most cases the context argument should be #NULL. + * + * If called twice for the same context, does nothing the second + * time. If called once with context A and once with context B, + * context B replaces context A as the context monitoring the + * connection. + */ +void +dbus_server_setup (DBusServer *server, + GMainContext *context) +{ + ConnectionSetup *old_setup; + ConnectionSetup *cs; + + /* FIXME we never free the slot, so its refcount just keeps growing, + * which is kind of broken. + */ + dbus_server_allocate_data_slot (&server_slot); + if (server_slot < 0) + goto nomem; + + if (context == NULL) + context = g_main_context_default (); + + cs = NULL; + + old_setup = dbus_server_get_data (server, server_slot); + if (old_setup != NULL) + { + if (old_setup->context == context) + return; /* nothing to do */ + + cs = connection_setup_new_from_old (context, old_setup); + + /* Nuke the old setup */ + dbus_server_set_data (server, server_slot, NULL, NULL); + old_setup = NULL; + } + + if (cs == NULL) + cs = connection_setup_new (context, NULL); + + if (!dbus_server_set_data (server, server_slot, cs, + (DBusFreeFunction)connection_setup_free)) + goto nomem; + + if (!dbus_server_set_watch_functions (server, + add_watch, + remove_watch, + watch_toggled, + cs, NULL)) + goto nomem; + + if (!dbus_server_set_timeout_functions (server, + add_timeout, + remove_timeout, + timeout_toggled, + cs, NULL)) + goto nomem; + + return; + + nomem: + g_error ("Not enough memory to set up DBusServer for use with GLib"); +} + diff --git a/src/ibusinternal.h b/src/ibusinternal.h new file mode 100644 index 0000000..924d96e --- /dev/null +++ b/src/ibusinternal.h @@ -0,0 +1,36 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_INTERNEL_H_ +#define __IBUS_INTERNEL_H_ + +#include <glib.h> +#include <dbus/dbus.h> + +#define I_(string) g_intern_static_string (string) + +void dbus_server_setup (DBusServer *server, + GMainContext *context); +void dbus_connection_setup (DBusConnection *connection, + GMainContext *context); + + + +#endif + diff --git a/src/ibuskeynames.c b/src/ibuskeynames.c new file mode 100644 index 0000000..9a8c1e4 --- /dev/null +++ b/src/ibuskeynames.c @@ -0,0 +1,199 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* Key handling not part of the keymap */ +#include <glib.h> +#include <glib/gprintf.h> +#include <stdlib.h> +#include <string.h> +#include "ibuskeysyms.h" +#include "keyname-table.h" + +#define IBUS_NUM_KEYS G_N_ELEMENTS (gdk_keys_by_keyval) + +static int +gdk_keys_keyval_compare (const void *pkey, const void *pbase) +{ + return (*(int *) pkey) - ((gdk_key *) pbase)->keyval; +} + +const gchar* +ibus_keyval_name (guint keyval) +{ + static gchar buf[100]; + gdk_key *found; + + /* Check for directly encoded 24-bit UCS characters: */ + if ((keyval & 0xff000000) == 0x01000000) + { + g_sprintf (buf, "U+%.04X", (keyval & 0x00ffffff)); + return buf; + } + + found = bsearch (&keyval, gdk_keys_by_keyval, + IBUS_NUM_KEYS, sizeof (gdk_key), + gdk_keys_keyval_compare); + + if (found != NULL) + { + while ((found > gdk_keys_by_keyval) && + ((found - 1)->keyval == keyval)) + found--; + + return (gchar *) (keynames + found->offset); + } + else if (keyval != 0) + { + g_sprintf (buf, "%#x", keyval); + return buf; + } + + return NULL; +} + +static int +gdk_keys_name_compare (const void *pkey, const void *pbase) +{ + return strcmp ((const char *) pkey, + (const char *) (keynames + ((const gdk_key *) pbase)->offset)); +} + +guint +ibus_keyval_from_name (const gchar *keyval_name) +{ + gdk_key *found; + + g_return_val_if_fail (keyval_name != NULL, 0); + + found = bsearch (keyval_name, gdk_keys_by_name, + IBUS_NUM_KEYS, sizeof (gdk_key), + gdk_keys_name_compare); + if (found != NULL) + return found->keyval; + else + return IBUS_VoidSymbol; +} + +static const gchar * +modifier_name[] = { + "Shift", + "Lock", + "Control", + "Alt", + "Mod2", + "Mod3", + "Mod4", + "Mod5", + "Button1", + "Button2", + "Button3", + "Button4", + "Button5", + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, + "Supper", + "Hyper", + "Meta", + NULL, + "Release", + NULL, + NULL, +}; + +const gchar * +ibus_key_event_to_string (guint keyval, + guint modifiers) +{ + guint i; + GString *str; + const gchar *keyval_name; + + g_return_val_if_fail (keyval != IBUS_VoidSymbol, NULL); + + keyval_name = ibus_keyval_name (keyval); + g_return_val_if_fail (keyval_name != NULL, NULL); + + str = g_string_new (""); + + for (i = 0; i < 32; i++) { + guint mask = 1 << i; + + if ((modifiers & mask) == 0) + continue; + if (modifier_name[i] == NULL) + continue; + + g_string_append (str, modifier_name[i]); + g_string_append_c (str, '+'); + } + + g_string_append (str, keyval_name); + + return g_string_free (str, FALSE); +} + +gboolean +ibus_key_event_from_string (const gchar *string, + guint *keyval, + guint *modifiers) +{ + g_return_val_if_fail (string != NULL, FALSE); + g_return_val_if_fail (keyval != NULL, FALSE); + g_return_val_if_fail (modifiers != NULL, FALSE); + + gchar **tokens = NULL; + gchar **p; + gboolean retval = FALSE; + + tokens = g_strsplit (string, "+", 0); + g_return_val_if_fail (tokens != NULL, FALSE); + + *keyval = 0; + *modifiers = 0; + + for (p = tokens; *(p + 1) != NULL; p++) { + gint i; + for (i = 0; i < 32; i++) { + if (g_strcmp0 (modifier_name[i], *p) != 0) + continue; + *modifiers |= (1 << i); + break; + } + if (i == 32) { + goto _out; + } + } + + *keyval = ibus_keyval_from_name (*p); + if (*keyval != IBUS_VoidSymbol) + retval = TRUE; +_out: + if (tokens) + g_strfreev (tokens); + return retval; +} + diff --git a/src/ibuskeysyms-update.pl b/src/ibuskeysyms-update.pl new file mode 100755 index 0000000..4fd426d --- /dev/null +++ b/src/ibuskeysyms-update.pl @@ -0,0 +1,105 @@ +#!/usr/bin/env perl + +# Updates http://svn.gnome.org/viewcvs/gtk%2B/trunk/gdk/gdkkeysyms.h?view=log from upstream (X.org 7.x), +# from http://gitweb.freedesktop.org/?p=xorg/proto/x11proto.git;a=blob_plain;f=keysymdef.h +# +# Author : Simos Xenitellis <simos at gnome dot org>. +# Version : 1.2 +# +# Input : http://gitweb.freedesktop.org/?p=xorg/proto/x11proto.git;a=blob_plain;f=keysymdef.h +# Output : http://svn.gnome.org/svn/gtk+/trunk/gdk/gdkkeysyms.h +# +# Notes : It downloads keysymdef.h from the Internet, if not found locally, +# Notes : and creates an updated gdkkeysyms.h +# Notes : This version updates the source of gdkkeysyms.h from CVS to the GIT server. + +use strict; + +# Used for reading the keysymdef symbols. +my @keysymelements; + +if ( ! -f "keysymdef.h" ) +{ + print "Trying to download keysymdef.h from\n"; + print "http://gitweb.freedesktop.org/?p=xorg/proto/x11proto.git;a=blob_plain;f=keysymdef.h\n"; + die "Unable to download keysymdef.h from http://gitweb.freedesktop.org/?p=xorg/proto/x11proto.git;a=blob_plain;f=keysymdef.h\n" + unless system("wget -c -O keysymdef.h \"http://gitweb.freedesktop.org/?p=xorg/proto/x11proto.git;a=blob_plain;f=keysymdef.h\"") == 0; + print " done.\n\n"; +} +else +{ + print "We are using existing keysymdef.h found in this directory.\n"; + print "It is assumed that you took care and it is a recent version\n"; + print "as found at http://gitweb.freedesktop.org/?p=xorg/proto/x11proto.git;a=blob;f=keysymdef.h\n\n"; +} + + +if ( -f "ibuskeysyms.h" ) +{ + print "There is already a ibuskeysyms.h file in this directory. We are not overwriting it.\n"; + print "Please move it somewhere else in order to run this script.\n"; + die "Exiting...\n\n"; +} + +# Source: http://cvs.freedesktop.org/xorg/xc/include/keysymdef.h +die "Could not open file keysymdef.h: $!\n" unless open(IN_KEYSYMDEF, "<:utf8", "keysymdef.h"); + +# Output: gtk+/gdk/gdkkeysyms.h +die "Could not open file ibuskeysyms.h: $!\n" unless open(OUT_IBUSKEYSYMS, ">:utf8", "ibuskeysyms.h"); + +print OUT_IBUSKEYSYMS<<EOF; +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __IBUS_KEYSYMS_H__ +#define __IBUS_KEYSYMS_H__ + + +EOF + + +while (<IN_KEYSYMDEF>) +{ + next if ( ! /^#define / ); + + @keysymelements = split(/\s+/); + die "Internal error, no \@keysymelements: $_\n" unless @keysymelements; + + $_ = $keysymelements[1]; + die "Internal error, was expecting \"XC_*\", found: $_\n" if ( ! /^XK_/ ); + + $_ = $keysymelements[2]; + die "Internal error, was expecting \"0x*\", found: $_\n" if ( ! /^0x/ ); + + $keysymelements[1] =~ s/^XK_/IBUS_/g; + + printf OUT_IBUSKEYSYMS "#define %s 0x%03x\n", $keysymelements[1], hex($keysymelements[2]); +} + +#$ibussyms{"0"} = "0000"; + +close IN_KEYSYMDEF; + + +print OUT_IBUSKEYSYMS<<EOF; + +#endif /* __IBUS_KEYSYMS_H__ */ +EOF + +printf "We just finished converting keysymdef.h to ibuskeysyms.h\nThank you\n"; diff --git a/src/ibuskeysyms.h b/src/ibuskeysyms.h new file mode 100644 index 0000000..cfcfe8d --- /dev/null +++ b/src/ibuskeysyms.h @@ -0,0 +1,2014 @@ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __IBUS_KEYSYMS_H__ +#define __IBUS_KEYSYMS_H__ + + +#define IBUS_VoidSymbol 0xffffff +#define IBUS_BackSpace 0xff08 +#define IBUS_Tab 0xff09 +#define IBUS_Linefeed 0xff0a +#define IBUS_Clear 0xff0b +#define IBUS_Return 0xff0d +#define IBUS_Pause 0xff13 +#define IBUS_Scroll_Lock 0xff14 +#define IBUS_Sys_Req 0xff15 +#define IBUS_Escape 0xff1b +#define IBUS_Delete 0xffff +#define IBUS_Multi_key 0xff20 +#define IBUS_Codeinput 0xff37 +#define IBUS_SingleCandidate 0xff3c +#define IBUS_MultipleCandidate 0xff3d +#define IBUS_PreviousCandidate 0xff3e +#define IBUS_Kanji 0xff21 +#define IBUS_Muhenkan 0xff22 +#define IBUS_Henkan_Mode 0xff23 +#define IBUS_Henkan 0xff23 +#define IBUS_Romaji 0xff24 +#define IBUS_Hiragana 0xff25 +#define IBUS_Katakana 0xff26 +#define IBUS_Hiragana_Katakana 0xff27 +#define IBUS_Zenkaku 0xff28 +#define IBUS_Hankaku 0xff29 +#define IBUS_Zenkaku_Hankaku 0xff2a +#define IBUS_Touroku 0xff2b +#define IBUS_Massyo 0xff2c +#define IBUS_Kana_Lock 0xff2d +#define IBUS_Kana_Shift 0xff2e +#define IBUS_Eisu_Shift 0xff2f +#define IBUS_Eisu_toggle 0xff30 +#define IBUS_Kanji_Bangou 0xff37 +#define IBUS_Zen_Koho 0xff3d +#define IBUS_Mae_Koho 0xff3e +#define IBUS_Home 0xff50 +#define IBUS_Left 0xff51 +#define IBUS_Up 0xff52 +#define IBUS_Right 0xff53 +#define IBUS_Down 0xff54 +#define IBUS_Prior 0xff55 +#define IBUS_Page_Up 0xff55 +#define IBUS_Next 0xff56 +#define IBUS_Page_Down 0xff56 +#define IBUS_End 0xff57 +#define IBUS_Begin 0xff58 +#define IBUS_Select 0xff60 +#define IBUS_Print 0xff61 +#define IBUS_Execute 0xff62 +#define IBUS_Insert 0xff63 +#define IBUS_Undo 0xff65 +#define IBUS_Redo 0xff66 +#define IBUS_Menu 0xff67 +#define IBUS_Find 0xff68 +#define IBUS_Cancel 0xff69 +#define IBUS_Help 0xff6a +#define IBUS_Break 0xff6b +#define IBUS_Mode_switch 0xff7e +#define IBUS_script_switch 0xff7e +#define IBUS_Num_Lock 0xff7f +#define IBUS_KP_Space 0xff80 +#define IBUS_KP_Tab 0xff89 +#define IBUS_KP_Enter 0xff8d +#define IBUS_KP_F1 0xff91 +#define IBUS_KP_F2 0xff92 +#define IBUS_KP_F3 0xff93 +#define IBUS_KP_F4 0xff94 +#define IBUS_KP_Home 0xff95 +#define IBUS_KP_Left 0xff96 +#define IBUS_KP_Up 0xff97 +#define IBUS_KP_Right 0xff98 +#define IBUS_KP_Down 0xff99 +#define IBUS_KP_Prior 0xff9a +#define IBUS_KP_Page_Up 0xff9a +#define IBUS_KP_Next 0xff9b +#define IBUS_KP_Page_Down 0xff9b +#define IBUS_KP_End 0xff9c +#define IBUS_KP_Begin 0xff9d +#define IBUS_KP_Insert 0xff9e +#define IBUS_KP_Delete 0xff9f +#define IBUS_KP_Equal 0xffbd +#define IBUS_KP_Multiply 0xffaa +#define IBUS_KP_Add 0xffab +#define IBUS_KP_Separator 0xffac +#define IBUS_KP_Subtract 0xffad +#define IBUS_KP_Decimal 0xffae +#define IBUS_KP_Divide 0xffaf +#define IBUS_KP_0 0xffb0 +#define IBUS_KP_1 0xffb1 +#define IBUS_KP_2 0xffb2 +#define IBUS_KP_3 0xffb3 +#define IBUS_KP_4 0xffb4 +#define IBUS_KP_5 0xffb5 +#define IBUS_KP_6 0xffb6 +#define IBUS_KP_7 0xffb7 +#define IBUS_KP_8 0xffb8 +#define IBUS_KP_9 0xffb9 +#define IBUS_F1 0xffbe +#define IBUS_F2 0xffbf +#define IBUS_F3 0xffc0 +#define IBUS_F4 0xffc1 +#define IBUS_F5 0xffc2 +#define IBUS_F6 0xffc3 +#define IBUS_F7 0xffc4 +#define IBUS_F8 0xffc5 +#define IBUS_F9 0xffc6 +#define IBUS_F10 0xffc7 +#define IBUS_F11 0xffc8 +#define IBUS_L1 0xffc8 +#define IBUS_F12 0xffc9 +#define IBUS_L2 0xffc9 +#define IBUS_F13 0xffca +#define IBUS_L3 0xffca +#define IBUS_F14 0xffcb +#define IBUS_L4 0xffcb +#define IBUS_F15 0xffcc +#define IBUS_L5 0xffcc +#define IBUS_F16 0xffcd +#define IBUS_L6 0xffcd +#define IBUS_F17 0xffce +#define IBUS_L7 0xffce +#define IBUS_F18 0xffcf +#define IBUS_L8 0xffcf +#define IBUS_F19 0xffd0 +#define IBUS_L9 0xffd0 +#define IBUS_F20 0xffd1 +#define IBUS_L10 0xffd1 +#define IBUS_F21 0xffd2 +#define IBUS_R1 0xffd2 +#define IBUS_F22 0xffd3 +#define IBUS_R2 0xffd3 +#define IBUS_F23 0xffd4 +#define IBUS_R3 0xffd4 +#define IBUS_F24 0xffd5 +#define IBUS_R4 0xffd5 +#define IBUS_F25 0xffd6 +#define IBUS_R5 0xffd6 +#define IBUS_F26 0xffd7 +#define IBUS_R6 0xffd7 +#define IBUS_F27 0xffd8 +#define IBUS_R7 0xffd8 +#define IBUS_F28 0xffd9 +#define IBUS_R8 0xffd9 +#define IBUS_F29 0xffda +#define IBUS_R9 0xffda +#define IBUS_F30 0xffdb +#define IBUS_R10 0xffdb +#define IBUS_F31 0xffdc +#define IBUS_R11 0xffdc +#define IBUS_F32 0xffdd +#define IBUS_R12 0xffdd +#define IBUS_F33 0xffde +#define IBUS_R13 0xffde +#define IBUS_F34 0xffdf +#define IBUS_R14 0xffdf +#define IBUS_F35 0xffe0 +#define IBUS_R15 0xffe0 +#define IBUS_Shift_L 0xffe1 +#define IBUS_Shift_R 0xffe2 +#define IBUS_Control_L 0xffe3 +#define IBUS_Control_R 0xffe4 +#define IBUS_Caps_Lock 0xffe5 +#define IBUS_Shift_Lock 0xffe6 +#define IBUS_Meta_L 0xffe7 +#define IBUS_Meta_R 0xffe8 +#define IBUS_Alt_L 0xffe9 +#define IBUS_Alt_R 0xffea +#define IBUS_Super_L 0xffeb +#define IBUS_Super_R 0xffec +#define IBUS_Hyper_L 0xffed +#define IBUS_Hyper_R 0xffee +#define IBUS_ISO_Lock 0xfe01 +#define IBUS_ISO_Level2_Latch 0xfe02 +#define IBUS_ISO_Level3_Shift 0xfe03 +#define IBUS_ISO_Level3_Latch 0xfe04 +#define IBUS_ISO_Level3_Lock 0xfe05 +#define IBUS_ISO_Level5_Shift 0xfe11 +#define IBUS_ISO_Level5_Latch 0xfe12 +#define IBUS_ISO_Level5_Lock 0xfe13 +#define IBUS_ISO_Group_Shift 0xff7e +#define IBUS_ISO_Group_Latch 0xfe06 +#define IBUS_ISO_Group_Lock 0xfe07 +#define IBUS_ISO_Next_Group 0xfe08 +#define IBUS_ISO_Next_Group_Lock 0xfe09 +#define IBUS_ISO_Prev_Group 0xfe0a +#define IBUS_ISO_Prev_Group_Lock 0xfe0b +#define IBUS_ISO_First_Group 0xfe0c +#define IBUS_ISO_First_Group_Lock 0xfe0d +#define IBUS_ISO_Last_Group 0xfe0e +#define IBUS_ISO_Last_Group_Lock 0xfe0f +#define IBUS_ISO_Left_Tab 0xfe20 +#define IBUS_ISO_Move_Line_Up 0xfe21 +#define IBUS_ISO_Move_Line_Down 0xfe22 +#define IBUS_ISO_Partial_Line_Up 0xfe23 +#define IBUS_ISO_Partial_Line_Down 0xfe24 +#define IBUS_ISO_Partial_Space_Left 0xfe25 +#define IBUS_ISO_Partial_Space_Right 0xfe26 +#define IBUS_ISO_Set_Margin_Left 0xfe27 +#define IBUS_ISO_Set_Margin_Right 0xfe28 +#define IBUS_ISO_Release_Margin_Left 0xfe29 +#define IBUS_ISO_Release_Margin_Right 0xfe2a +#define IBUS_ISO_Release_Both_Margins 0xfe2b +#define IBUS_ISO_Fast_Cursor_Left 0xfe2c +#define IBUS_ISO_Fast_Cursor_Right 0xfe2d +#define IBUS_ISO_Fast_Cursor_Up 0xfe2e +#define IBUS_ISO_Fast_Cursor_Down 0xfe2f +#define IBUS_ISO_Continuous_Underline 0xfe30 +#define IBUS_ISO_Discontinuous_Underline 0xfe31 +#define IBUS_ISO_Emphasize 0xfe32 +#define IBUS_ISO_Center_Object 0xfe33 +#define IBUS_ISO_Enter 0xfe34 +#define IBUS_dead_grave 0xfe50 +#define IBUS_dead_acute 0xfe51 +#define IBUS_dead_circumflex 0xfe52 +#define IBUS_dead_tilde 0xfe53 +#define IBUS_dead_perispomeni 0xfe53 +#define IBUS_dead_macron 0xfe54 +#define IBUS_dead_breve 0xfe55 +#define IBUS_dead_abovedot 0xfe56 +#define IBUS_dead_diaeresis 0xfe57 +#define IBUS_dead_abovering 0xfe58 +#define IBUS_dead_doubleacute 0xfe59 +#define IBUS_dead_caron 0xfe5a +#define IBUS_dead_cedilla 0xfe5b +#define IBUS_dead_ogonek 0xfe5c +#define IBUS_dead_iota 0xfe5d +#define IBUS_dead_voiced_sound 0xfe5e +#define IBUS_dead_semivoiced_sound 0xfe5f +#define IBUS_dead_belowdot 0xfe60 +#define IBUS_dead_hook 0xfe61 +#define IBUS_dead_horn 0xfe62 +#define IBUS_dead_stroke 0xfe63 +#define IBUS_dead_abovecomma 0xfe64 +#define IBUS_dead_psili 0xfe64 +#define IBUS_dead_abovereversedcomma 0xfe65 +#define IBUS_dead_dasia 0xfe65 +#define IBUS_dead_belowring 0xfe67 +#define IBUS_dead_belowmacron 0xfe68 +#define IBUS_dead_belowcircumflex 0xfe69 +#define IBUS_dead_belowtilde 0xfe6a +#define IBUS_dead_belowbreve 0xfe6b +#define IBUS_dead_belowdiaeresis 0xfe6c +#define IBUS_First_Virtual_Screen 0xfed0 +#define IBUS_Prev_Virtual_Screen 0xfed1 +#define IBUS_Next_Virtual_Screen 0xfed2 +#define IBUS_Last_Virtual_Screen 0xfed4 +#define IBUS_Terminate_Server 0xfed5 +#define IBUS_AccessX_Enable 0xfe70 +#define IBUS_AccessX_Feedback_Enable 0xfe71 +#define IBUS_RepeatKeys_Enable 0xfe72 +#define IBUS_SlowKeys_Enable 0xfe73 +#define IBUS_BounceKeys_Enable 0xfe74 +#define IBUS_StickyKeys_Enable 0xfe75 +#define IBUS_MouseKeys_Enable 0xfe76 +#define IBUS_MouseKeys_Accel_Enable 0xfe77 +#define IBUS_Overlay1_Enable 0xfe78 +#define IBUS_Overlay2_Enable 0xfe79 +#define IBUS_AudibleBell_Enable 0xfe7a +#define IBUS_Pointer_Left 0xfee0 +#define IBUS_Pointer_Right 0xfee1 +#define IBUS_Pointer_Up 0xfee2 +#define IBUS_Pointer_Down 0xfee3 +#define IBUS_Pointer_UpLeft 0xfee4 +#define IBUS_Pointer_UpRight 0xfee5 +#define IBUS_Pointer_DownLeft 0xfee6 +#define IBUS_Pointer_DownRight 0xfee7 +#define IBUS_Pointer_Button_Dflt 0xfee8 +#define IBUS_Pointer_Button1 0xfee9 +#define IBUS_Pointer_Button2 0xfeea +#define IBUS_Pointer_Button3 0xfeeb +#define IBUS_Pointer_Button4 0xfeec +#define IBUS_Pointer_Button5 0xfeed +#define IBUS_Pointer_DblClick_Dflt 0xfeee +#define IBUS_Pointer_DblClick1 0xfeef +#define IBUS_Pointer_DblClick2 0xfef0 +#define IBUS_Pointer_DblClick3 0xfef1 +#define IBUS_Pointer_DblClick4 0xfef2 +#define IBUS_Pointer_DblClick5 0xfef3 +#define IBUS_Pointer_Drag_Dflt 0xfef4 +#define IBUS_Pointer_Drag1 0xfef5 +#define IBUS_Pointer_Drag2 0xfef6 +#define IBUS_Pointer_Drag3 0xfef7 +#define IBUS_Pointer_Drag4 0xfef8 +#define IBUS_Pointer_Drag5 0xfefd +#define IBUS_Pointer_EnableKeys 0xfef9 +#define IBUS_Pointer_Accelerate 0xfefa +#define IBUS_Pointer_DfltBtnNext 0xfefb +#define IBUS_Pointer_DfltBtnPrev 0xfefc +#define IBUS_3270_Duplicate 0xfd01 +#define IBUS_3270_FieldMark 0xfd02 +#define IBUS_3270_Right2 0xfd03 +#define IBUS_3270_Left2 0xfd04 +#define IBUS_3270_BackTab 0xfd05 +#define IBUS_3270_EraseEOF 0xfd06 +#define IBUS_3270_EraseInput 0xfd07 +#define IBUS_3270_Reset 0xfd08 +#define IBUS_3270_Quit 0xfd09 +#define IBUS_3270_PA1 0xfd0a +#define IBUS_3270_PA2 0xfd0b +#define IBUS_3270_PA3 0xfd0c +#define IBUS_3270_Test 0xfd0d +#define IBUS_3270_Attn 0xfd0e +#define IBUS_3270_CursorBlink 0xfd0f +#define IBUS_3270_AltCursor 0xfd10 +#define IBUS_3270_KeyClick 0xfd11 +#define IBUS_3270_Jump 0xfd12 +#define IBUS_3270_Ident 0xfd13 +#define IBUS_3270_Rule 0xfd14 +#define IBUS_3270_Copy 0xfd15 +#define IBUS_3270_Play 0xfd16 +#define IBUS_3270_Setup 0xfd17 +#define IBUS_3270_Record 0xfd18 +#define IBUS_3270_ChangeScreen 0xfd19 +#define IBUS_3270_DeleteWord 0xfd1a +#define IBUS_3270_ExSelect 0xfd1b +#define IBUS_3270_CursorSelect 0xfd1c +#define IBUS_3270_PrintScreen 0xfd1d +#define IBUS_3270_Enter 0xfd1e +#define IBUS_space 0x020 +#define IBUS_exclam 0x021 +#define IBUS_quotedbl 0x022 +#define IBUS_numbersign 0x023 +#define IBUS_dollar 0x024 +#define IBUS_percent 0x025 +#define IBUS_ampersand 0x026 +#define IBUS_apostrophe 0x027 +#define IBUS_quoteright 0x027 +#define IBUS_parenleft 0x028 +#define IBUS_parenright 0x029 +#define IBUS_asterisk 0x02a +#define IBUS_plus 0x02b +#define IBUS_comma 0x02c +#define IBUS_minus 0x02d +#define IBUS_period 0x02e +#define IBUS_slash 0x02f +#define IBUS_0 0x030 +#define IBUS_1 0x031 +#define IBUS_2 0x032 +#define IBUS_3 0x033 +#define IBUS_4 0x034 +#define IBUS_5 0x035 +#define IBUS_6 0x036 +#define IBUS_7 0x037 +#define IBUS_8 0x038 +#define IBUS_9 0x039 +#define IBUS_colon 0x03a +#define IBUS_semicolon 0x03b +#define IBUS_less 0x03c +#define IBUS_equal 0x03d +#define IBUS_greater 0x03e +#define IBUS_question 0x03f +#define IBUS_at 0x040 +#define IBUS_A 0x041 +#define IBUS_B 0x042 +#define IBUS_C 0x043 +#define IBUS_D 0x044 +#define IBUS_E 0x045 +#define IBUS_F 0x046 +#define IBUS_G 0x047 +#define IBUS_H 0x048 +#define IBUS_I 0x049 +#define IBUS_J 0x04a +#define IBUS_K 0x04b +#define IBUS_L 0x04c +#define IBUS_M 0x04d +#define IBUS_N 0x04e +#define IBUS_O 0x04f +#define IBUS_P 0x050 +#define IBUS_Q 0x051 +#define IBUS_R 0x052 +#define IBUS_S 0x053 +#define IBUS_T 0x054 +#define IBUS_U 0x055 +#define IBUS_V 0x056 +#define IBUS_W 0x057 +#define IBUS_X 0x058 +#define IBUS_Y 0x059 +#define IBUS_Z 0x05a +#define IBUS_bracketleft 0x05b +#define IBUS_backslash 0x05c +#define IBUS_bracketright 0x05d +#define IBUS_asciicircum 0x05e +#define IBUS_underscore 0x05f +#define IBUS_grave 0x060 +#define IBUS_quoteleft 0x060 +#define IBUS_a 0x061 +#define IBUS_b 0x062 +#define IBUS_c 0x063 +#define IBUS_d 0x064 +#define IBUS_e 0x065 +#define IBUS_f 0x066 +#define IBUS_g 0x067 +#define IBUS_h 0x068 +#define IBUS_i 0x069 +#define IBUS_j 0x06a +#define IBUS_k 0x06b +#define IBUS_l 0x06c +#define IBUS_m 0x06d +#define IBUS_n 0x06e +#define IBUS_o 0x06f +#define IBUS_p 0x070 +#define IBUS_q 0x071 +#define IBUS_r 0x072 +#define IBUS_s 0x073 +#define IBUS_t 0x074 +#define IBUS_u 0x075 +#define IBUS_v 0x076 +#define IBUS_w 0x077 +#define IBUS_x 0x078 +#define IBUS_y 0x079 +#define IBUS_z 0x07a +#define IBUS_braceleft 0x07b +#define IBUS_bar 0x07c +#define IBUS_braceright 0x07d +#define IBUS_asciitilde 0x07e +#define IBUS_nobreakspace 0x0a0 +#define IBUS_exclamdown 0x0a1 +#define IBUS_cent 0x0a2 +#define IBUS_sterling 0x0a3 +#define IBUS_currency 0x0a4 +#define IBUS_yen 0x0a5 +#define IBUS_brokenbar 0x0a6 +#define IBUS_section 0x0a7 +#define IBUS_diaeresis 0x0a8 +#define IBUS_copyright 0x0a9 +#define IBUS_ordfeminine 0x0aa +#define IBUS_guillemotleft 0x0ab +#define IBUS_notsign 0x0ac +#define IBUS_hyphen 0x0ad +#define IBUS_registered 0x0ae +#define IBUS_macron 0x0af +#define IBUS_degree 0x0b0 +#define IBUS_plusminus 0x0b1 +#define IBUS_twosuperior 0x0b2 +#define IBUS_threesuperior 0x0b3 +#define IBUS_acute 0x0b4 +#define IBUS_mu 0x0b5 +#define IBUS_paragraph 0x0b6 +#define IBUS_periodcentered 0x0b7 +#define IBUS_cedilla 0x0b8 +#define IBUS_onesuperior 0x0b9 +#define IBUS_masculine 0x0ba +#define IBUS_guillemotright 0x0bb +#define IBUS_onequarter 0x0bc +#define IBUS_onehalf 0x0bd +#define IBUS_threequarters 0x0be +#define IBUS_questiondown 0x0bf +#define IBUS_Agrave 0x0c0 +#define IBUS_Aacute 0x0c1 +#define IBUS_Acircumflex 0x0c2 +#define IBUS_Atilde 0x0c3 +#define IBUS_Adiaeresis 0x0c4 +#define IBUS_Aring 0x0c5 +#define IBUS_AE 0x0c6 +#define IBUS_Ccedilla 0x0c7 +#define IBUS_Egrave 0x0c8 +#define IBUS_Eacute 0x0c9 +#define IBUS_Ecircumflex 0x0ca +#define IBUS_Ediaeresis 0x0cb +#define IBUS_Igrave 0x0cc +#define IBUS_Iacute 0x0cd +#define IBUS_Icircumflex 0x0ce +#define IBUS_Idiaeresis 0x0cf +#define IBUS_ETH 0x0d0 +#define IBUS_Eth 0x0d0 +#define IBUS_Ntilde 0x0d1 +#define IBUS_Ograve 0x0d2 +#define IBUS_Oacute 0x0d3 +#define IBUS_Ocircumflex 0x0d4 +#define IBUS_Otilde 0x0d5 +#define IBUS_Odiaeresis 0x0d6 +#define IBUS_multiply 0x0d7 +#define IBUS_Oslash 0x0d8 +#define IBUS_Ooblique 0x0d8 +#define IBUS_Ugrave 0x0d9 +#define IBUS_Uacute 0x0da +#define IBUS_Ucircumflex 0x0db +#define IBUS_Udiaeresis 0x0dc +#define IBUS_Yacute 0x0dd +#define IBUS_THORN 0x0de +#define IBUS_Thorn 0x0de +#define IBUS_ssharp 0x0df +#define IBUS_agrave 0x0e0 +#define IBUS_aacute 0x0e1 +#define IBUS_acircumflex 0x0e2 +#define IBUS_atilde 0x0e3 +#define IBUS_adiaeresis 0x0e4 +#define IBUS_aring 0x0e5 +#define IBUS_ae 0x0e6 +#define IBUS_ccedilla 0x0e7 +#define IBUS_egrave 0x0e8 +#define IBUS_eacute 0x0e9 +#define IBUS_ecircumflex 0x0ea +#define IBUS_ediaeresis 0x0eb +#define IBUS_igrave 0x0ec +#define IBUS_iacute 0x0ed +#define IBUS_icircumflex 0x0ee +#define IBUS_idiaeresis 0x0ef +#define IBUS_eth 0x0f0 +#define IBUS_ntilde 0x0f1 +#define IBUS_ograve 0x0f2 +#define IBUS_oacute 0x0f3 +#define IBUS_ocircumflex 0x0f4 +#define IBUS_otilde 0x0f5 +#define IBUS_odiaeresis 0x0f6 +#define IBUS_division 0x0f7 +#define IBUS_oslash 0x0f8 +#define IBUS_ooblique 0x0f8 +#define IBUS_ugrave 0x0f9 +#define IBUS_uacute 0x0fa +#define IBUS_ucircumflex 0x0fb +#define IBUS_udiaeresis 0x0fc +#define IBUS_yacute 0x0fd +#define IBUS_thorn 0x0fe +#define IBUS_ydiaeresis 0x0ff +#define IBUS_Aogonek 0x1a1 +#define IBUS_breve 0x1a2 +#define IBUS_Lstroke 0x1a3 +#define IBUS_Lcaron 0x1a5 +#define IBUS_Sacute 0x1a6 +#define IBUS_Scaron 0x1a9 +#define IBUS_Scedilla 0x1aa +#define IBUS_Tcaron 0x1ab +#define IBUS_Zacute 0x1ac +#define IBUS_Zcaron 0x1ae +#define IBUS_Zabovedot 0x1af +#define IBUS_aogonek 0x1b1 +#define IBUS_ogonek 0x1b2 +#define IBUS_lstroke 0x1b3 +#define IBUS_lcaron 0x1b5 +#define IBUS_sacute 0x1b6 +#define IBUS_caron 0x1b7 +#define IBUS_scaron 0x1b9 +#define IBUS_scedilla 0x1ba +#define IBUS_tcaron 0x1bb +#define IBUS_zacute 0x1bc +#define IBUS_doubleacute 0x1bd +#define IBUS_zcaron 0x1be +#define IBUS_zabovedot 0x1bf +#define IBUS_Racute 0x1c0 +#define IBUS_Abreve 0x1c3 +#define IBUS_Lacute 0x1c5 +#define IBUS_Cacute 0x1c6 +#define IBUS_Ccaron 0x1c8 +#define IBUS_Eogonek 0x1ca +#define IBUS_Ecaron 0x1cc +#define IBUS_Dcaron 0x1cf +#define IBUS_Dstroke 0x1d0 +#define IBUS_Nacute 0x1d1 +#define IBUS_Ncaron 0x1d2 +#define IBUS_Odoubleacute 0x1d5 +#define IBUS_Rcaron 0x1d8 +#define IBUS_Uring 0x1d9 +#define IBUS_Udoubleacute 0x1db +#define IBUS_Tcedilla 0x1de +#define IBUS_racute 0x1e0 +#define IBUS_abreve 0x1e3 +#define IBUS_lacute 0x1e5 +#define IBUS_cacute 0x1e6 +#define IBUS_ccaron 0x1e8 +#define IBUS_eogonek 0x1ea +#define IBUS_ecaron 0x1ec +#define IBUS_dcaron 0x1ef +#define IBUS_dstroke 0x1f0 +#define IBUS_nacute 0x1f1 +#define IBUS_ncaron 0x1f2 +#define IBUS_odoubleacute 0x1f5 +#define IBUS_udoubleacute 0x1fb +#define IBUS_rcaron 0x1f8 +#define IBUS_uring 0x1f9 +#define IBUS_tcedilla 0x1fe +#define IBUS_abovedot 0x1ff +#define IBUS_Hstroke 0x2a1 +#define IBUS_Hcircumflex 0x2a6 +#define IBUS_Iabovedot 0x2a9 +#define IBUS_Gbreve 0x2ab +#define IBUS_Jcircumflex 0x2ac +#define IBUS_hstroke 0x2b1 +#define IBUS_hcircumflex 0x2b6 +#define IBUS_idotless 0x2b9 +#define IBUS_gbreve 0x2bb +#define IBUS_jcircumflex 0x2bc +#define IBUS_Cabovedot 0x2c5 +#define IBUS_Ccircumflex 0x2c6 +#define IBUS_Gabovedot 0x2d5 +#define IBUS_Gcircumflex 0x2d8 +#define IBUS_Ubreve 0x2dd +#define IBUS_Scircumflex 0x2de +#define IBUS_cabovedot 0x2e5 +#define IBUS_ccircumflex 0x2e6 +#define IBUS_gabovedot 0x2f5 +#define IBUS_gcircumflex 0x2f8 +#define IBUS_ubreve 0x2fd +#define IBUS_scircumflex 0x2fe +#define IBUS_kra 0x3a2 +#define IBUS_kappa 0x3a2 +#define IBUS_Rcedilla 0x3a3 +#define IBUS_Itilde 0x3a5 +#define IBUS_Lcedilla 0x3a6 +#define IBUS_Emacron 0x3aa +#define IBUS_Gcedilla 0x3ab +#define IBUS_Tslash 0x3ac +#define IBUS_rcedilla 0x3b3 +#define IBUS_itilde 0x3b5 +#define IBUS_lcedilla 0x3b6 +#define IBUS_emacron 0x3ba +#define IBUS_gcedilla 0x3bb +#define IBUS_tslash 0x3bc +#define IBUS_ENG 0x3bd +#define IBUS_eng 0x3bf +#define IBUS_Amacron 0x3c0 +#define IBUS_Iogonek 0x3c7 +#define IBUS_Eabovedot 0x3cc +#define IBUS_Imacron 0x3cf +#define IBUS_Ncedilla 0x3d1 +#define IBUS_Omacron 0x3d2 +#define IBUS_Kcedilla 0x3d3 +#define IBUS_Uogonek 0x3d9 +#define IBUS_Utilde 0x3dd +#define IBUS_Umacron 0x3de +#define IBUS_amacron 0x3e0 +#define IBUS_iogonek 0x3e7 +#define IBUS_eabovedot 0x3ec +#define IBUS_imacron 0x3ef +#define IBUS_ncedilla 0x3f1 +#define IBUS_omacron 0x3f2 +#define IBUS_kcedilla 0x3f3 +#define IBUS_uogonek 0x3f9 +#define IBUS_utilde 0x3fd +#define IBUS_umacron 0x3fe +#define IBUS_Babovedot 0x1001e02 +#define IBUS_babovedot 0x1001e03 +#define IBUS_Dabovedot 0x1001e0a +#define IBUS_Wgrave 0x1001e80 +#define IBUS_Wacute 0x1001e82 +#define IBUS_dabovedot 0x1001e0b +#define IBUS_Ygrave 0x1001ef2 +#define IBUS_Fabovedot 0x1001e1e +#define IBUS_fabovedot 0x1001e1f +#define IBUS_Mabovedot 0x1001e40 +#define IBUS_mabovedot 0x1001e41 +#define IBUS_Pabovedot 0x1001e56 +#define IBUS_wgrave 0x1001e81 +#define IBUS_pabovedot 0x1001e57 +#define IBUS_wacute 0x1001e83 +#define IBUS_Sabovedot 0x1001e60 +#define IBUS_ygrave 0x1001ef3 +#define IBUS_Wdiaeresis 0x1001e84 +#define IBUS_wdiaeresis 0x1001e85 +#define IBUS_sabovedot 0x1001e61 +#define IBUS_Wcircumflex 0x1000174 +#define IBUS_Tabovedot 0x1001e6a +#define IBUS_Ycircumflex 0x1000176 +#define IBUS_wcircumflex 0x1000175 +#define IBUS_tabovedot 0x1001e6b +#define IBUS_ycircumflex 0x1000177 +#define IBUS_OE 0x13bc +#define IBUS_oe 0x13bd +#define IBUS_Ydiaeresis 0x13be +#define IBUS_overline 0x47e +#define IBUS_kana_fullstop 0x4a1 +#define IBUS_kana_openingbracket 0x4a2 +#define IBUS_kana_closingbracket 0x4a3 +#define IBUS_kana_comma 0x4a4 +#define IBUS_kana_conjunctive 0x4a5 +#define IBUS_kana_middledot 0x4a5 +#define IBUS_kana_WO 0x4a6 +#define IBUS_kana_a 0x4a7 +#define IBUS_kana_i 0x4a8 +#define IBUS_kana_u 0x4a9 +#define IBUS_kana_e 0x4aa +#define IBUS_kana_o 0x4ab +#define IBUS_kana_ya 0x4ac +#define IBUS_kana_yu 0x4ad +#define IBUS_kana_yo 0x4ae +#define IBUS_kana_tsu 0x4af +#define IBUS_kana_tu 0x4af +#define IBUS_prolongedsound 0x4b0 +#define IBUS_kana_A 0x4b1 +#define IBUS_kana_I 0x4b2 +#define IBUS_kana_U 0x4b3 +#define IBUS_kana_E 0x4b4 +#define IBUS_kana_O 0x4b5 +#define IBUS_kana_KA 0x4b6 +#define IBUS_kana_KI 0x4b7 +#define IBUS_kana_KU 0x4b8 +#define IBUS_kana_KE 0x4b9 +#define IBUS_kana_KO 0x4ba +#define IBUS_kana_SA 0x4bb +#define IBUS_kana_SHI 0x4bc +#define IBUS_kana_SU 0x4bd +#define IBUS_kana_SE 0x4be +#define IBUS_kana_SO 0x4bf +#define IBUS_kana_TA 0x4c0 +#define IBUS_kana_CHI 0x4c1 +#define IBUS_kana_TI 0x4c1 +#define IBUS_kana_TSU 0x4c2 +#define IBUS_kana_TU 0x4c2 +#define IBUS_kana_TE 0x4c3 +#define IBUS_kana_TO 0x4c4 +#define IBUS_kana_NA 0x4c5 +#define IBUS_kana_NI 0x4c6 +#define IBUS_kana_NU 0x4c7 +#define IBUS_kana_NE 0x4c8 +#define IBUS_kana_NO 0x4c9 +#define IBUS_kana_HA 0x4ca +#define IBUS_kana_HI 0x4cb +#define IBUS_kana_FU 0x4cc +#define IBUS_kana_HU 0x4cc +#define IBUS_kana_HE 0x4cd +#define IBUS_kana_HO 0x4ce +#define IBUS_kana_MA 0x4cf +#define IBUS_kana_MI 0x4d0 +#define IBUS_kana_MU 0x4d1 +#define IBUS_kana_ME 0x4d2 +#define IBUS_kana_MO 0x4d3 +#define IBUS_kana_YA 0x4d4 +#define IBUS_kana_YU 0x4d5 +#define IBUS_kana_YO 0x4d6 +#define IBUS_kana_RA 0x4d7 +#define IBUS_kana_RI 0x4d8 +#define IBUS_kana_RU 0x4d9 +#define IBUS_kana_RE 0x4da +#define IBUS_kana_RO 0x4db +#define IBUS_kana_WA 0x4dc +#define IBUS_kana_N 0x4dd +#define IBUS_voicedsound 0x4de +#define IBUS_semivoicedsound 0x4df +#define IBUS_kana_switch 0xff7e +#define IBUS_Farsi_0 0x10006f0 +#define IBUS_Farsi_1 0x10006f1 +#define IBUS_Farsi_2 0x10006f2 +#define IBUS_Farsi_3 0x10006f3 +#define IBUS_Farsi_4 0x10006f4 +#define IBUS_Farsi_5 0x10006f5 +#define IBUS_Farsi_6 0x10006f6 +#define IBUS_Farsi_7 0x10006f7 +#define IBUS_Farsi_8 0x10006f8 +#define IBUS_Farsi_9 0x10006f9 +#define IBUS_Arabic_percent 0x100066a +#define IBUS_Arabic_superscript_alef 0x1000670 +#define IBUS_Arabic_tteh 0x1000679 +#define IBUS_Arabic_peh 0x100067e +#define IBUS_Arabic_tcheh 0x1000686 +#define IBUS_Arabic_ddal 0x1000688 +#define IBUS_Arabic_rreh 0x1000691 +#define IBUS_Arabic_comma 0x5ac +#define IBUS_Arabic_fullstop 0x10006d4 +#define IBUS_Arabic_0 0x1000660 +#define IBUS_Arabic_1 0x1000661 +#define IBUS_Arabic_2 0x1000662 +#define IBUS_Arabic_3 0x1000663 +#define IBUS_Arabic_4 0x1000664 +#define IBUS_Arabic_5 0x1000665 +#define IBUS_Arabic_6 0x1000666 +#define IBUS_Arabic_7 0x1000667 +#define IBUS_Arabic_8 0x1000668 +#define IBUS_Arabic_9 0x1000669 +#define IBUS_Arabic_semicolon 0x5bb +#define IBUS_Arabic_question_mark 0x5bf +#define IBUS_Arabic_hamza 0x5c1 +#define IBUS_Arabic_maddaonalef 0x5c2 +#define IBUS_Arabic_hamzaonalef 0x5c3 +#define IBUS_Arabic_hamzaonwaw 0x5c4 +#define IBUS_Arabic_hamzaunderalef 0x5c5 +#define IBUS_Arabic_hamzaonyeh 0x5c6 +#define IBUS_Arabic_alef 0x5c7 +#define IBUS_Arabic_beh 0x5c8 +#define IBUS_Arabic_tehmarbuta 0x5c9 +#define IBUS_Arabic_teh 0x5ca +#define IBUS_Arabic_theh 0x5cb +#define IBUS_Arabic_jeem 0x5cc +#define IBUS_Arabic_hah 0x5cd +#define IBUS_Arabic_khah 0x5ce +#define IBUS_Arabic_dal 0x5cf +#define IBUS_Arabic_thal 0x5d0 +#define IBUS_Arabic_ra 0x5d1 +#define IBUS_Arabic_zain 0x5d2 +#define IBUS_Arabic_seen 0x5d3 +#define IBUS_Arabic_sheen 0x5d4 +#define IBUS_Arabic_sad 0x5d5 +#define IBUS_Arabic_dad 0x5d6 +#define IBUS_Arabic_tah 0x5d7 +#define IBUS_Arabic_zah 0x5d8 +#define IBUS_Arabic_ain 0x5d9 +#define IBUS_Arabic_ghain 0x5da +#define IBUS_Arabic_tatweel 0x5e0 +#define IBUS_Arabic_feh 0x5e1 +#define IBUS_Arabic_qaf 0x5e2 +#define IBUS_Arabic_kaf 0x5e3 +#define IBUS_Arabic_lam 0x5e4 +#define IBUS_Arabic_meem 0x5e5 +#define IBUS_Arabic_noon 0x5e6 +#define IBUS_Arabic_ha 0x5e7 +#define IBUS_Arabic_heh 0x5e7 +#define IBUS_Arabic_waw 0x5e8 +#define IBUS_Arabic_alefmaksura 0x5e9 +#define IBUS_Arabic_yeh 0x5ea +#define IBUS_Arabic_fathatan 0x5eb +#define IBUS_Arabic_dammatan 0x5ec +#define IBUS_Arabic_kasratan 0x5ed +#define IBUS_Arabic_fatha 0x5ee +#define IBUS_Arabic_damma 0x5ef +#define IBUS_Arabic_kasra 0x5f0 +#define IBUS_Arabic_shadda 0x5f1 +#define IBUS_Arabic_sukun 0x5f2 +#define IBUS_Arabic_madda_above 0x1000653 +#define IBUS_Arabic_hamza_above 0x1000654 +#define IBUS_Arabic_hamza_below 0x1000655 +#define IBUS_Arabic_jeh 0x1000698 +#define IBUS_Arabic_veh 0x10006a4 +#define IBUS_Arabic_keheh 0x10006a9 +#define IBUS_Arabic_gaf 0x10006af +#define IBUS_Arabic_noon_ghunna 0x10006ba +#define IBUS_Arabic_heh_doachashmee 0x10006be +#define IBUS_Farsi_yeh 0x10006cc +#define IBUS_Arabic_farsi_yeh 0x10006cc +#define IBUS_Arabic_yeh_baree 0x10006d2 +#define IBUS_Arabic_heh_goal 0x10006c1 +#define IBUS_Arabic_switch 0xff7e +#define IBUS_Cyrillic_GHE_bar 0x1000492 +#define IBUS_Cyrillic_ghe_bar 0x1000493 +#define IBUS_Cyrillic_ZHE_descender 0x1000496 +#define IBUS_Cyrillic_zhe_descender 0x1000497 +#define IBUS_Cyrillic_KA_descender 0x100049a +#define IBUS_Cyrillic_ka_descender 0x100049b +#define IBUS_Cyrillic_KA_vertstroke 0x100049c +#define IBUS_Cyrillic_ka_vertstroke 0x100049d +#define IBUS_Cyrillic_EN_descender 0x10004a2 +#define IBUS_Cyrillic_en_descender 0x10004a3 +#define IBUS_Cyrillic_U_straight 0x10004ae +#define IBUS_Cyrillic_u_straight 0x10004af +#define IBUS_Cyrillic_U_straight_bar 0x10004b0 +#define IBUS_Cyrillic_u_straight_bar 0x10004b1 +#define IBUS_Cyrillic_HA_descender 0x10004b2 +#define IBUS_Cyrillic_ha_descender 0x10004b3 +#define IBUS_Cyrillic_CHE_descender 0x10004b6 +#define IBUS_Cyrillic_che_descender 0x10004b7 +#define IBUS_Cyrillic_CHE_vertstroke 0x10004b8 +#define IBUS_Cyrillic_che_vertstroke 0x10004b9 +#define IBUS_Cyrillic_SHHA 0x10004ba +#define IBUS_Cyrillic_shha 0x10004bb +#define IBUS_Cyrillic_SCHWA 0x10004d8 +#define IBUS_Cyrillic_schwa 0x10004d9 +#define IBUS_Cyrillic_I_macron 0x10004e2 +#define IBUS_Cyrillic_i_macron 0x10004e3 +#define IBUS_Cyrillic_O_bar 0x10004e8 +#define IBUS_Cyrillic_o_bar 0x10004e9 +#define IBUS_Cyrillic_U_macron 0x10004ee +#define IBUS_Cyrillic_u_macron 0x10004ef +#define IBUS_Serbian_dje 0x6a1 +#define IBUS_Macedonia_gje 0x6a2 +#define IBUS_Cyrillic_io 0x6a3 +#define IBUS_Ukrainian_ie 0x6a4 +#define IBUS_Ukranian_je 0x6a4 +#define IBUS_Macedonia_dse 0x6a5 +#define IBUS_Ukrainian_i 0x6a6 +#define IBUS_Ukranian_i 0x6a6 +#define IBUS_Ukrainian_yi 0x6a7 +#define IBUS_Ukranian_yi 0x6a7 +#define IBUS_Cyrillic_je 0x6a8 +#define IBUS_Serbian_je 0x6a8 +#define IBUS_Cyrillic_lje 0x6a9 +#define IBUS_Serbian_lje 0x6a9 +#define IBUS_Cyrillic_nje 0x6aa +#define IBUS_Serbian_nje 0x6aa +#define IBUS_Serbian_tshe 0x6ab +#define IBUS_Macedonia_kje 0x6ac +#define IBUS_Ukrainian_ghe_with_upturn 0x6ad +#define IBUS_Byelorussian_shortu 0x6ae +#define IBUS_Cyrillic_dzhe 0x6af +#define IBUS_Serbian_dze 0x6af +#define IBUS_numerosign 0x6b0 +#define IBUS_Serbian_DJE 0x6b1 +#define IBUS_Macedonia_GJE 0x6b2 +#define IBUS_Cyrillic_IO 0x6b3 +#define IBUS_Ukrainian_IE 0x6b4 +#define IBUS_Ukranian_JE 0x6b4 +#define IBUS_Macedonia_DSE 0x6b5 +#define IBUS_Ukrainian_I 0x6b6 +#define IBUS_Ukranian_I 0x6b6 +#define IBUS_Ukrainian_YI 0x6b7 +#define IBUS_Ukranian_YI 0x6b7 +#define IBUS_Cyrillic_JE 0x6b8 +#define IBUS_Serbian_JE 0x6b8 +#define IBUS_Cyrillic_LJE 0x6b9 +#define IBUS_Serbian_LJE 0x6b9 +#define IBUS_Cyrillic_NJE 0x6ba +#define IBUS_Serbian_NJE 0x6ba +#define IBUS_Serbian_TSHE 0x6bb +#define IBUS_Macedonia_KJE 0x6bc +#define IBUS_Ukrainian_GHE_WITH_UPTURN 0x6bd +#define IBUS_Byelorussian_SHORTU 0x6be +#define IBUS_Cyrillic_DZHE 0x6bf +#define IBUS_Serbian_DZE 0x6bf +#define IBUS_Cyrillic_yu 0x6c0 +#define IBUS_Cyrillic_a 0x6c1 +#define IBUS_Cyrillic_be 0x6c2 +#define IBUS_Cyrillic_tse 0x6c3 +#define IBUS_Cyrillic_de 0x6c4 +#define IBUS_Cyrillic_ie 0x6c5 +#define IBUS_Cyrillic_ef 0x6c6 +#define IBUS_Cyrillic_ghe 0x6c7 +#define IBUS_Cyrillic_ha 0x6c8 +#define IBUS_Cyrillic_i 0x6c9 +#define IBUS_Cyrillic_shorti 0x6ca +#define IBUS_Cyrillic_ka 0x6cb +#define IBUS_Cyrillic_el 0x6cc +#define IBUS_Cyrillic_em 0x6cd +#define IBUS_Cyrillic_en 0x6ce +#define IBUS_Cyrillic_o 0x6cf +#define IBUS_Cyrillic_pe 0x6d0 +#define IBUS_Cyrillic_ya 0x6d1 +#define IBUS_Cyrillic_er 0x6d2 +#define IBUS_Cyrillic_es 0x6d3 +#define IBUS_Cyrillic_te 0x6d4 +#define IBUS_Cyrillic_u 0x6d5 +#define IBUS_Cyrillic_zhe 0x6d6 +#define IBUS_Cyrillic_ve 0x6d7 +#define IBUS_Cyrillic_softsign 0x6d8 +#define IBUS_Cyrillic_yeru 0x6d9 +#define IBUS_Cyrillic_ze 0x6da +#define IBUS_Cyrillic_sha 0x6db +#define IBUS_Cyrillic_e 0x6dc +#define IBUS_Cyrillic_shcha 0x6dd +#define IBUS_Cyrillic_che 0x6de +#define IBUS_Cyrillic_hardsign 0x6df +#define IBUS_Cyrillic_YU 0x6e0 +#define IBUS_Cyrillic_A 0x6e1 +#define IBUS_Cyrillic_BE 0x6e2 +#define IBUS_Cyrillic_TSE 0x6e3 +#define IBUS_Cyrillic_DE 0x6e4 +#define IBUS_Cyrillic_IE 0x6e5 +#define IBUS_Cyrillic_EF 0x6e6 +#define IBUS_Cyrillic_GHE 0x6e7 +#define IBUS_Cyrillic_HA 0x6e8 +#define IBUS_Cyrillic_I 0x6e9 +#define IBUS_Cyrillic_SHORTI 0x6ea +#define IBUS_Cyrillic_KA 0x6eb +#define IBUS_Cyrillic_EL 0x6ec +#define IBUS_Cyrillic_EM 0x6ed +#define IBUS_Cyrillic_EN 0x6ee +#define IBUS_Cyrillic_O 0x6ef +#define IBUS_Cyrillic_PE 0x6f0 +#define IBUS_Cyrillic_YA 0x6f1 +#define IBUS_Cyrillic_ER 0x6f2 +#define IBUS_Cyrillic_ES 0x6f3 +#define IBUS_Cyrillic_TE 0x6f4 +#define IBUS_Cyrillic_U 0x6f5 +#define IBUS_Cyrillic_ZHE 0x6f6 +#define IBUS_Cyrillic_VE 0x6f7 +#define IBUS_Cyrillic_SOFTSIGN 0x6f8 +#define IBUS_Cyrillic_YERU 0x6f9 +#define IBUS_Cyrillic_ZE 0x6fa +#define IBUS_Cyrillic_SHA 0x6fb +#define IBUS_Cyrillic_E 0x6fc +#define IBUS_Cyrillic_SHCHA 0x6fd +#define IBUS_Cyrillic_CHE 0x6fe +#define IBUS_Cyrillic_HARDSIGN 0x6ff +#define IBUS_Greek_ALPHAaccent 0x7a1 +#define IBUS_Greek_EPSILONaccent 0x7a2 +#define IBUS_Greek_ETAaccent 0x7a3 +#define IBUS_Greek_IOTAaccent 0x7a4 +#define IBUS_Greek_IOTAdieresis 0x7a5 +#define IBUS_Greek_IOTAdiaeresis 0x7a5 +#define IBUS_Greek_OMICRONaccent 0x7a7 +#define IBUS_Greek_UPSILONaccent 0x7a8 +#define IBUS_Greek_UPSILONdieresis 0x7a9 +#define IBUS_Greek_OMEGAaccent 0x7ab +#define IBUS_Greek_accentdieresis 0x7ae +#define IBUS_Greek_horizbar 0x7af +#define IBUS_Greek_alphaaccent 0x7b1 +#define IBUS_Greek_epsilonaccent 0x7b2 +#define IBUS_Greek_etaaccent 0x7b3 +#define IBUS_Greek_iotaaccent 0x7b4 +#define IBUS_Greek_iotadieresis 0x7b5 +#define IBUS_Greek_iotaaccentdieresis 0x7b6 +#define IBUS_Greek_omicronaccent 0x7b7 +#define IBUS_Greek_upsilonaccent 0x7b8 +#define IBUS_Greek_upsilondieresis 0x7b9 +#define IBUS_Greek_upsilonaccentdieresis 0x7ba +#define IBUS_Greek_omegaaccent 0x7bb +#define IBUS_Greek_ALPHA 0x7c1 +#define IBUS_Greek_BETA 0x7c2 +#define IBUS_Greek_GAMMA 0x7c3 +#define IBUS_Greek_DELTA 0x7c4 +#define IBUS_Greek_EPSILON 0x7c5 +#define IBUS_Greek_ZETA 0x7c6 +#define IBUS_Greek_ETA 0x7c7 +#define IBUS_Greek_THETA 0x7c8 +#define IBUS_Greek_IOTA 0x7c9 +#define IBUS_Greek_KAPPA 0x7ca +#define IBUS_Greek_LAMDA 0x7cb +#define IBUS_Greek_LAMBDA 0x7cb +#define IBUS_Greek_MU 0x7cc +#define IBUS_Greek_NU 0x7cd +#define IBUS_Greek_XI 0x7ce +#define IBUS_Greek_OMICRON 0x7cf +#define IBUS_Greek_PI 0x7d0 +#define IBUS_Greek_RHO 0x7d1 +#define IBUS_Greek_SIGMA 0x7d2 +#define IBUS_Greek_TAU 0x7d4 +#define IBUS_Greek_UPSILON 0x7d5 +#define IBUS_Greek_PHI 0x7d6 +#define IBUS_Greek_CHI 0x7d7 +#define IBUS_Greek_PSI 0x7d8 +#define IBUS_Greek_OMEGA 0x7d9 +#define IBUS_Greek_alpha 0x7e1 +#define IBUS_Greek_beta 0x7e2 +#define IBUS_Greek_gamma 0x7e3 +#define IBUS_Greek_delta 0x7e4 +#define IBUS_Greek_epsilon 0x7e5 +#define IBUS_Greek_zeta 0x7e6 +#define IBUS_Greek_eta 0x7e7 +#define IBUS_Greek_theta 0x7e8 +#define IBUS_Greek_iota 0x7e9 +#define IBUS_Greek_kappa 0x7ea +#define IBUS_Greek_lamda 0x7eb +#define IBUS_Greek_lambda 0x7eb +#define IBUS_Greek_mu 0x7ec +#define IBUS_Greek_nu 0x7ed +#define IBUS_Greek_xi 0x7ee +#define IBUS_Greek_omicron 0x7ef +#define IBUS_Greek_pi 0x7f0 +#define IBUS_Greek_rho 0x7f1 +#define IBUS_Greek_sigma 0x7f2 +#define IBUS_Greek_finalsmallsigma 0x7f3 +#define IBUS_Greek_tau 0x7f4 +#define IBUS_Greek_upsilon 0x7f5 +#define IBUS_Greek_phi 0x7f6 +#define IBUS_Greek_chi 0x7f7 +#define IBUS_Greek_psi 0x7f8 +#define IBUS_Greek_omega 0x7f9 +#define IBUS_Greek_switch 0xff7e +#define IBUS_leftradical 0x8a1 +#define IBUS_topleftradical 0x8a2 +#define IBUS_horizconnector 0x8a3 +#define IBUS_topintegral 0x8a4 +#define IBUS_botintegral 0x8a5 +#define IBUS_vertconnector 0x8a6 +#define IBUS_topleftsqbracket 0x8a7 +#define IBUS_botleftsqbracket 0x8a8 +#define IBUS_toprightsqbracket 0x8a9 +#define IBUS_botrightsqbracket 0x8aa +#define IBUS_topleftparens 0x8ab +#define IBUS_botleftparens 0x8ac +#define IBUS_toprightparens 0x8ad +#define IBUS_botrightparens 0x8ae +#define IBUS_leftmiddlecurlybrace 0x8af +#define IBUS_rightmiddlecurlybrace 0x8b0 +#define IBUS_topleftsummation 0x8b1 +#define IBUS_botleftsummation 0x8b2 +#define IBUS_topvertsummationconnector 0x8b3 +#define IBUS_botvertsummationconnector 0x8b4 +#define IBUS_toprightsummation 0x8b5 +#define IBUS_botrightsummation 0x8b6 +#define IBUS_rightmiddlesummation 0x8b7 +#define IBUS_lessthanequal 0x8bc +#define IBUS_notequal 0x8bd +#define IBUS_greaterthanequal 0x8be +#define IBUS_integral 0x8bf +#define IBUS_therefore 0x8c0 +#define IBUS_variation 0x8c1 +#define IBUS_infinity 0x8c2 +#define IBUS_nabla 0x8c5 +#define IBUS_approximate 0x8c8 +#define IBUS_similarequal 0x8c9 +#define IBUS_ifonlyif 0x8cd +#define IBUS_implies 0x8ce +#define IBUS_identical 0x8cf +#define IBUS_radical 0x8d6 +#define IBUS_includedin 0x8da +#define IBUS_includes 0x8db +#define IBUS_intersection 0x8dc +#define IBUS_union 0x8dd +#define IBUS_logicaland 0x8de +#define IBUS_logicalor 0x8df +#define IBUS_partialderivative 0x8ef +#define IBUS_function 0x8f6 +#define IBUS_leftarrow 0x8fb +#define IBUS_uparrow 0x8fc +#define IBUS_rightarrow 0x8fd +#define IBUS_downarrow 0x8fe +#define IBUS_blank 0x9df +#define IBUS_soliddiamond 0x9e0 +#define IBUS_checkerboard 0x9e1 +#define IBUS_ht 0x9e2 +#define IBUS_ff 0x9e3 +#define IBUS_cr 0x9e4 +#define IBUS_lf 0x9e5 +#define IBUS_nl 0x9e8 +#define IBUS_vt 0x9e9 +#define IBUS_lowrightcorner 0x9ea +#define IBUS_uprightcorner 0x9eb +#define IBUS_upleftcorner 0x9ec +#define IBUS_lowleftcorner 0x9ed +#define IBUS_crossinglines 0x9ee +#define IBUS_horizlinescan1 0x9ef +#define IBUS_horizlinescan3 0x9f0 +#define IBUS_horizlinescan5 0x9f1 +#define IBUS_horizlinescan7 0x9f2 +#define IBUS_horizlinescan9 0x9f3 +#define IBUS_leftt 0x9f4 +#define IBUS_rightt 0x9f5 +#define IBUS_bott 0x9f6 +#define IBUS_topt 0x9f7 +#define IBUS_vertbar 0x9f8 +#define IBUS_emspace 0xaa1 +#define IBUS_enspace 0xaa2 +#define IBUS_em3space 0xaa3 +#define IBUS_em4space 0xaa4 +#define IBUS_digitspace 0xaa5 +#define IBUS_punctspace 0xaa6 +#define IBUS_thinspace 0xaa7 +#define IBUS_hairspace 0xaa8 +#define IBUS_emdash 0xaa9 +#define IBUS_endash 0xaaa +#define IBUS_signifblank 0xaac +#define IBUS_ellipsis 0xaae +#define IBUS_doubbaselinedot 0xaaf +#define IBUS_onethird 0xab0 +#define IBUS_twothirds 0xab1 +#define IBUS_onefifth 0xab2 +#define IBUS_twofifths 0xab3 +#define IBUS_threefifths 0xab4 +#define IBUS_fourfifths 0xab5 +#define IBUS_onesixth 0xab6 +#define IBUS_fivesixths 0xab7 +#define IBUS_careof 0xab8 +#define IBUS_figdash 0xabb +#define IBUS_leftanglebracket 0xabc +#define IBUS_decimalpoint 0xabd +#define IBUS_rightanglebracket 0xabe +#define IBUS_marker 0xabf +#define IBUS_oneeighth 0xac3 +#define IBUS_threeeighths 0xac4 +#define IBUS_fiveeighths 0xac5 +#define IBUS_seveneighths 0xac6 +#define IBUS_trademark 0xac9 +#define IBUS_signaturemark 0xaca +#define IBUS_trademarkincircle 0xacb +#define IBUS_leftopentriangle 0xacc +#define IBUS_rightopentriangle 0xacd +#define IBUS_emopencircle 0xace +#define IBUS_emopenrectangle 0xacf +#define IBUS_leftsinglequotemark 0xad0 +#define IBUS_rightsinglequotemark 0xad1 +#define IBUS_leftdoublequotemark 0xad2 +#define IBUS_rightdoublequotemark 0xad3 +#define IBUS_prescription 0xad4 +#define IBUS_minutes 0xad6 +#define IBUS_seconds 0xad7 +#define IBUS_latincross 0xad9 +#define IBUS_hexagram 0xada +#define IBUS_filledrectbullet 0xadb +#define IBUS_filledlefttribullet 0xadc +#define IBUS_filledrighttribullet 0xadd +#define IBUS_emfilledcircle 0xade +#define IBUS_emfilledrect 0xadf +#define IBUS_enopencircbullet 0xae0 +#define IBUS_enopensquarebullet 0xae1 +#define IBUS_openrectbullet 0xae2 +#define IBUS_opentribulletup 0xae3 +#define IBUS_opentribulletdown 0xae4 +#define IBUS_openstar 0xae5 +#define IBUS_enfilledcircbullet 0xae6 +#define IBUS_enfilledsqbullet 0xae7 +#define IBUS_filledtribulletup 0xae8 +#define IBUS_filledtribulletdown 0xae9 +#define IBUS_leftpointer 0xaea +#define IBUS_rightpointer 0xaeb +#define IBUS_club 0xaec +#define IBUS_diamond 0xaed +#define IBUS_heart 0xaee +#define IBUS_maltesecross 0xaf0 +#define IBUS_dagger 0xaf1 +#define IBUS_doubledagger 0xaf2 +#define IBUS_checkmark 0xaf3 +#define IBUS_ballotcross 0xaf4 +#define IBUS_musicalsharp 0xaf5 +#define IBUS_musicalflat 0xaf6 +#define IBUS_malesymbol 0xaf7 +#define IBUS_femalesymbol 0xaf8 +#define IBUS_telephone 0xaf9 +#define IBUS_telephonerecorder 0xafa +#define IBUS_phonographcopyright 0xafb +#define IBUS_caret 0xafc +#define IBUS_singlelowquotemark 0xafd +#define IBUS_doublelowquotemark 0xafe +#define IBUS_cursor 0xaff +#define IBUS_leftcaret 0xba3 +#define IBUS_rightcaret 0xba6 +#define IBUS_downcaret 0xba8 +#define IBUS_upcaret 0xba9 +#define IBUS_overbar 0xbc0 +#define IBUS_downtack 0xbc2 +#define IBUS_upshoe 0xbc3 +#define IBUS_downstile 0xbc4 +#define IBUS_underbar 0xbc6 +#define IBUS_jot 0xbca +#define IBUS_quad 0xbcc +#define IBUS_uptack 0xbce +#define IBUS_circle 0xbcf +#define IBUS_upstile 0xbd3 +#define IBUS_downshoe 0xbd6 +#define IBUS_rightshoe 0xbd8 +#define IBUS_leftshoe 0xbda +#define IBUS_lefttack 0xbdc +#define IBUS_righttack 0xbfc +#define IBUS_hebrew_doublelowline 0xcdf +#define IBUS_hebrew_aleph 0xce0 +#define IBUS_hebrew_bet 0xce1 +#define IBUS_hebrew_beth 0xce1 +#define IBUS_hebrew_gimel 0xce2 +#define IBUS_hebrew_gimmel 0xce2 +#define IBUS_hebrew_dalet 0xce3 +#define IBUS_hebrew_daleth 0xce3 +#define IBUS_hebrew_he 0xce4 +#define IBUS_hebrew_waw 0xce5 +#define IBUS_hebrew_zain 0xce6 +#define IBUS_hebrew_zayin 0xce6 +#define IBUS_hebrew_chet 0xce7 +#define IBUS_hebrew_het 0xce7 +#define IBUS_hebrew_tet 0xce8 +#define IBUS_hebrew_teth 0xce8 +#define IBUS_hebrew_yod 0xce9 +#define IBUS_hebrew_finalkaph 0xcea +#define IBUS_hebrew_kaph 0xceb +#define IBUS_hebrew_lamed 0xcec +#define IBUS_hebrew_finalmem 0xced +#define IBUS_hebrew_mem 0xcee +#define IBUS_hebrew_finalnun 0xcef +#define IBUS_hebrew_nun 0xcf0 +#define IBUS_hebrew_samech 0xcf1 +#define IBUS_hebrew_samekh 0xcf1 +#define IBUS_hebrew_ayin 0xcf2 +#define IBUS_hebrew_finalpe 0xcf3 +#define IBUS_hebrew_pe 0xcf4 +#define IBUS_hebrew_finalzade 0xcf5 +#define IBUS_hebrew_finalzadi 0xcf5 +#define IBUS_hebrew_zade 0xcf6 +#define IBUS_hebrew_zadi 0xcf6 +#define IBUS_hebrew_qoph 0xcf7 +#define IBUS_hebrew_kuf 0xcf7 +#define IBUS_hebrew_resh 0xcf8 +#define IBUS_hebrew_shin 0xcf9 +#define IBUS_hebrew_taw 0xcfa +#define IBUS_hebrew_taf 0xcfa +#define IBUS_Hebrew_switch 0xff7e +#define IBUS_Thai_kokai 0xda1 +#define IBUS_Thai_khokhai 0xda2 +#define IBUS_Thai_khokhuat 0xda3 +#define IBUS_Thai_khokhwai 0xda4 +#define IBUS_Thai_khokhon 0xda5 +#define IBUS_Thai_khorakhang 0xda6 +#define IBUS_Thai_ngongu 0xda7 +#define IBUS_Thai_chochan 0xda8 +#define IBUS_Thai_choching 0xda9 +#define IBUS_Thai_chochang 0xdaa +#define IBUS_Thai_soso 0xdab +#define IBUS_Thai_chochoe 0xdac +#define IBUS_Thai_yoying 0xdad +#define IBUS_Thai_dochada 0xdae +#define IBUS_Thai_topatak 0xdaf +#define IBUS_Thai_thothan 0xdb0 +#define IBUS_Thai_thonangmontho 0xdb1 +#define IBUS_Thai_thophuthao 0xdb2 +#define IBUS_Thai_nonen 0xdb3 +#define IBUS_Thai_dodek 0xdb4 +#define IBUS_Thai_totao 0xdb5 +#define IBUS_Thai_thothung 0xdb6 +#define IBUS_Thai_thothahan 0xdb7 +#define IBUS_Thai_thothong 0xdb8 +#define IBUS_Thai_nonu 0xdb9 +#define IBUS_Thai_bobaimai 0xdba +#define IBUS_Thai_popla 0xdbb +#define IBUS_Thai_phophung 0xdbc +#define IBUS_Thai_fofa 0xdbd +#define IBUS_Thai_phophan 0xdbe +#define IBUS_Thai_fofan 0xdbf +#define IBUS_Thai_phosamphao 0xdc0 +#define IBUS_Thai_moma 0xdc1 +#define IBUS_Thai_yoyak 0xdc2 +#define IBUS_Thai_rorua 0xdc3 +#define IBUS_Thai_ru 0xdc4 +#define IBUS_Thai_loling 0xdc5 +#define IBUS_Thai_lu 0xdc6 +#define IBUS_Thai_wowaen 0xdc7 +#define IBUS_Thai_sosala 0xdc8 +#define IBUS_Thai_sorusi 0xdc9 +#define IBUS_Thai_sosua 0xdca +#define IBUS_Thai_hohip 0xdcb +#define IBUS_Thai_lochula 0xdcc +#define IBUS_Thai_oang 0xdcd +#define IBUS_Thai_honokhuk 0xdce +#define IBUS_Thai_paiyannoi 0xdcf +#define IBUS_Thai_saraa 0xdd0 +#define IBUS_Thai_maihanakat 0xdd1 +#define IBUS_Thai_saraaa 0xdd2 +#define IBUS_Thai_saraam 0xdd3 +#define IBUS_Thai_sarai 0xdd4 +#define IBUS_Thai_saraii 0xdd5 +#define IBUS_Thai_saraue 0xdd6 +#define IBUS_Thai_sarauee 0xdd7 +#define IBUS_Thai_sarau 0xdd8 +#define IBUS_Thai_sarauu 0xdd9 +#define IBUS_Thai_phinthu 0xdda +#define IBUS_Thai_maihanakat_maitho 0xdde +#define IBUS_Thai_baht 0xddf +#define IBUS_Thai_sarae 0xde0 +#define IBUS_Thai_saraae 0xde1 +#define IBUS_Thai_sarao 0xde2 +#define IBUS_Thai_saraaimaimuan 0xde3 +#define IBUS_Thai_saraaimaimalai 0xde4 +#define IBUS_Thai_lakkhangyao 0xde5 +#define IBUS_Thai_maiyamok 0xde6 +#define IBUS_Thai_maitaikhu 0xde7 +#define IBUS_Thai_maiek 0xde8 +#define IBUS_Thai_maitho 0xde9 +#define IBUS_Thai_maitri 0xdea +#define IBUS_Thai_maichattawa 0xdeb +#define IBUS_Thai_thanthakhat 0xdec +#define IBUS_Thai_nikhahit 0xded +#define IBUS_Thai_leksun 0xdf0 +#define IBUS_Thai_leknung 0xdf1 +#define IBUS_Thai_leksong 0xdf2 +#define IBUS_Thai_leksam 0xdf3 +#define IBUS_Thai_leksi 0xdf4 +#define IBUS_Thai_lekha 0xdf5 +#define IBUS_Thai_lekhok 0xdf6 +#define IBUS_Thai_lekchet 0xdf7 +#define IBUS_Thai_lekpaet 0xdf8 +#define IBUS_Thai_lekkao 0xdf9 +#define IBUS_Hangul 0xff31 +#define IBUS_Hangul_Start 0xff32 +#define IBUS_Hangul_End 0xff33 +#define IBUS_Hangul_Hanja 0xff34 +#define IBUS_Hangul_Jamo 0xff35 +#define IBUS_Hangul_Romaja 0xff36 +#define IBUS_Hangul_Codeinput 0xff37 +#define IBUS_Hangul_Jeonja 0xff38 +#define IBUS_Hangul_Banja 0xff39 +#define IBUS_Hangul_PreHanja 0xff3a +#define IBUS_Hangul_PostHanja 0xff3b +#define IBUS_Hangul_SingleCandidate 0xff3c +#define IBUS_Hangul_MultipleCandidate 0xff3d +#define IBUS_Hangul_PreviousCandidate 0xff3e +#define IBUS_Hangul_Special 0xff3f +#define IBUS_Hangul_switch 0xff7e +#define IBUS_Hangul_Kiyeog 0xea1 +#define IBUS_Hangul_SsangKiyeog 0xea2 +#define IBUS_Hangul_KiyeogSios 0xea3 +#define IBUS_Hangul_Nieun 0xea4 +#define IBUS_Hangul_NieunJieuj 0xea5 +#define IBUS_Hangul_NieunHieuh 0xea6 +#define IBUS_Hangul_Dikeud 0xea7 +#define IBUS_Hangul_SsangDikeud 0xea8 +#define IBUS_Hangul_Rieul 0xea9 +#define IBUS_Hangul_RieulKiyeog 0xeaa +#define IBUS_Hangul_RieulMieum 0xeab +#define IBUS_Hangul_RieulPieub 0xeac +#define IBUS_Hangul_RieulSios 0xead +#define IBUS_Hangul_RieulTieut 0xeae +#define IBUS_Hangul_RieulPhieuf 0xeaf +#define IBUS_Hangul_RieulHieuh 0xeb0 +#define IBUS_Hangul_Mieum 0xeb1 +#define IBUS_Hangul_Pieub 0xeb2 +#define IBUS_Hangul_SsangPieub 0xeb3 +#define IBUS_Hangul_PieubSios 0xeb4 +#define IBUS_Hangul_Sios 0xeb5 +#define IBUS_Hangul_SsangSios 0xeb6 +#define IBUS_Hangul_Ieung 0xeb7 +#define IBUS_Hangul_Jieuj 0xeb8 +#define IBUS_Hangul_SsangJieuj 0xeb9 +#define IBUS_Hangul_Cieuc 0xeba +#define IBUS_Hangul_Khieuq 0xebb +#define IBUS_Hangul_Tieut 0xebc +#define IBUS_Hangul_Phieuf 0xebd +#define IBUS_Hangul_Hieuh 0xebe +#define IBUS_Hangul_A 0xebf +#define IBUS_Hangul_AE 0xec0 +#define IBUS_Hangul_YA 0xec1 +#define IBUS_Hangul_YAE 0xec2 +#define IBUS_Hangul_EO 0xec3 +#define IBUS_Hangul_E 0xec4 +#define IBUS_Hangul_YEO 0xec5 +#define IBUS_Hangul_YE 0xec6 +#define IBUS_Hangul_O 0xec7 +#define IBUS_Hangul_WA 0xec8 +#define IBUS_Hangul_WAE 0xec9 +#define IBUS_Hangul_OE 0xeca +#define IBUS_Hangul_YO 0xecb +#define IBUS_Hangul_U 0xecc +#define IBUS_Hangul_WEO 0xecd +#define IBUS_Hangul_WE 0xece +#define IBUS_Hangul_WI 0xecf +#define IBUS_Hangul_YU 0xed0 +#define IBUS_Hangul_EU 0xed1 +#define IBUS_Hangul_YI 0xed2 +#define IBUS_Hangul_I 0xed3 +#define IBUS_Hangul_J_Kiyeog 0xed4 +#define IBUS_Hangul_J_SsangKiyeog 0xed5 +#define IBUS_Hangul_J_KiyeogSios 0xed6 +#define IBUS_Hangul_J_Nieun 0xed7 +#define IBUS_Hangul_J_NieunJieuj 0xed8 +#define IBUS_Hangul_J_NieunHieuh 0xed9 +#define IBUS_Hangul_J_Dikeud 0xeda +#define IBUS_Hangul_J_Rieul 0xedb +#define IBUS_Hangul_J_RieulKiyeog 0xedc +#define IBUS_Hangul_J_RieulMieum 0xedd +#define IBUS_Hangul_J_RieulPieub 0xede +#define IBUS_Hangul_J_RieulSios 0xedf +#define IBUS_Hangul_J_RieulTieut 0xee0 +#define IBUS_Hangul_J_RieulPhieuf 0xee1 +#define IBUS_Hangul_J_RieulHieuh 0xee2 +#define IBUS_Hangul_J_Mieum 0xee3 +#define IBUS_Hangul_J_Pieub 0xee4 +#define IBUS_Hangul_J_PieubSios 0xee5 +#define IBUS_Hangul_J_Sios 0xee6 +#define IBUS_Hangul_J_SsangSios 0xee7 +#define IBUS_Hangul_J_Ieung 0xee8 +#define IBUS_Hangul_J_Jieuj 0xee9 +#define IBUS_Hangul_J_Cieuc 0xeea +#define IBUS_Hangul_J_Khieuq 0xeeb +#define IBUS_Hangul_J_Tieut 0xeec +#define IBUS_Hangul_J_Phieuf 0xeed +#define IBUS_Hangul_J_Hieuh 0xeee +#define IBUS_Hangul_RieulYeorinHieuh 0xeef +#define IBUS_Hangul_SunkyeongeumMieum 0xef0 +#define IBUS_Hangul_SunkyeongeumPieub 0xef1 +#define IBUS_Hangul_PanSios 0xef2 +#define IBUS_Hangul_KkogjiDalrinIeung 0xef3 +#define IBUS_Hangul_SunkyeongeumPhieuf 0xef4 +#define IBUS_Hangul_YeorinHieuh 0xef5 +#define IBUS_Hangul_AraeA 0xef6 +#define IBUS_Hangul_AraeAE 0xef7 +#define IBUS_Hangul_J_PanSios 0xef8 +#define IBUS_Hangul_J_KkogjiDalrinIeung 0xef9 +#define IBUS_Hangul_J_YeorinHieuh 0xefa +#define IBUS_Korean_Won 0xeff +#define IBUS_Armenian_ligature_ew 0x1000587 +#define IBUS_Armenian_full_stop 0x1000589 +#define IBUS_Armenian_verjaket 0x1000589 +#define IBUS_Armenian_separation_mark 0x100055d +#define IBUS_Armenian_but 0x100055d +#define IBUS_Armenian_hyphen 0x100058a +#define IBUS_Armenian_yentamna 0x100058a +#define IBUS_Armenian_exclam 0x100055c +#define IBUS_Armenian_amanak 0x100055c +#define IBUS_Armenian_accent 0x100055b +#define IBUS_Armenian_shesht 0x100055b +#define IBUS_Armenian_question 0x100055e +#define IBUS_Armenian_paruyk 0x100055e +#define IBUS_Armenian_AYB 0x1000531 +#define IBUS_Armenian_ayb 0x1000561 +#define IBUS_Armenian_BEN 0x1000532 +#define IBUS_Armenian_ben 0x1000562 +#define IBUS_Armenian_GIM 0x1000533 +#define IBUS_Armenian_gim 0x1000563 +#define IBUS_Armenian_DA 0x1000534 +#define IBUS_Armenian_da 0x1000564 +#define IBUS_Armenian_YECH 0x1000535 +#define IBUS_Armenian_yech 0x1000565 +#define IBUS_Armenian_ZA 0x1000536 +#define IBUS_Armenian_za 0x1000566 +#define IBUS_Armenian_E 0x1000537 +#define IBUS_Armenian_e 0x1000567 +#define IBUS_Armenian_AT 0x1000538 +#define IBUS_Armenian_at 0x1000568 +#define IBUS_Armenian_TO 0x1000539 +#define IBUS_Armenian_to 0x1000569 +#define IBUS_Armenian_ZHE 0x100053a +#define IBUS_Armenian_zhe 0x100056a +#define IBUS_Armenian_INI 0x100053b +#define IBUS_Armenian_ini 0x100056b +#define IBUS_Armenian_LYUN 0x100053c +#define IBUS_Armenian_lyun 0x100056c +#define IBUS_Armenian_KHE 0x100053d +#define IBUS_Armenian_khe 0x100056d +#define IBUS_Armenian_TSA 0x100053e +#define IBUS_Armenian_tsa 0x100056e +#define IBUS_Armenian_KEN 0x100053f +#define IBUS_Armenian_ken 0x100056f +#define IBUS_Armenian_HO 0x1000540 +#define IBUS_Armenian_ho 0x1000570 +#define IBUS_Armenian_DZA 0x1000541 +#define IBUS_Armenian_dza 0x1000571 +#define IBUS_Armenian_GHAT 0x1000542 +#define IBUS_Armenian_ghat 0x1000572 +#define IBUS_Armenian_TCHE 0x1000543 +#define IBUS_Armenian_tche 0x1000573 +#define IBUS_Armenian_MEN 0x1000544 +#define IBUS_Armenian_men 0x1000574 +#define IBUS_Armenian_HI 0x1000545 +#define IBUS_Armenian_hi 0x1000575 +#define IBUS_Armenian_NU 0x1000546 +#define IBUS_Armenian_nu 0x1000576 +#define IBUS_Armenian_SHA 0x1000547 +#define IBUS_Armenian_sha 0x1000577 +#define IBUS_Armenian_VO 0x1000548 +#define IBUS_Armenian_vo 0x1000578 +#define IBUS_Armenian_CHA 0x1000549 +#define IBUS_Armenian_cha 0x1000579 +#define IBUS_Armenian_PE 0x100054a +#define IBUS_Armenian_pe 0x100057a +#define IBUS_Armenian_JE 0x100054b +#define IBUS_Armenian_je 0x100057b +#define IBUS_Armenian_RA 0x100054c +#define IBUS_Armenian_ra 0x100057c +#define IBUS_Armenian_SE 0x100054d +#define IBUS_Armenian_se 0x100057d +#define IBUS_Armenian_VEV 0x100054e +#define IBUS_Armenian_vev 0x100057e +#define IBUS_Armenian_TYUN 0x100054f +#define IBUS_Armenian_tyun 0x100057f +#define IBUS_Armenian_RE 0x1000550 +#define IBUS_Armenian_re 0x1000580 +#define IBUS_Armenian_TSO 0x1000551 +#define IBUS_Armenian_tso 0x1000581 +#define IBUS_Armenian_VYUN 0x1000552 +#define IBUS_Armenian_vyun 0x1000582 +#define IBUS_Armenian_PYUR 0x1000553 +#define IBUS_Armenian_pyur 0x1000583 +#define IBUS_Armenian_KE 0x1000554 +#define IBUS_Armenian_ke 0x1000584 +#define IBUS_Armenian_O 0x1000555 +#define IBUS_Armenian_o 0x1000585 +#define IBUS_Armenian_FE 0x1000556 +#define IBUS_Armenian_fe 0x1000586 +#define IBUS_Armenian_apostrophe 0x100055a +#define IBUS_Georgian_an 0x10010d0 +#define IBUS_Georgian_ban 0x10010d1 +#define IBUS_Georgian_gan 0x10010d2 +#define IBUS_Georgian_don 0x10010d3 +#define IBUS_Georgian_en 0x10010d4 +#define IBUS_Georgian_vin 0x10010d5 +#define IBUS_Georgian_zen 0x10010d6 +#define IBUS_Georgian_tan 0x10010d7 +#define IBUS_Georgian_in 0x10010d8 +#define IBUS_Georgian_kan 0x10010d9 +#define IBUS_Georgian_las 0x10010da +#define IBUS_Georgian_man 0x10010db +#define IBUS_Georgian_nar 0x10010dc +#define IBUS_Georgian_on 0x10010dd +#define IBUS_Georgian_par 0x10010de +#define IBUS_Georgian_zhar 0x10010df +#define IBUS_Georgian_rae 0x10010e0 +#define IBUS_Georgian_san 0x10010e1 +#define IBUS_Georgian_tar 0x10010e2 +#define IBUS_Georgian_un 0x10010e3 +#define IBUS_Georgian_phar 0x10010e4 +#define IBUS_Georgian_khar 0x10010e5 +#define IBUS_Georgian_ghan 0x10010e6 +#define IBUS_Georgian_qar 0x10010e7 +#define IBUS_Georgian_shin 0x10010e8 +#define IBUS_Georgian_chin 0x10010e9 +#define IBUS_Georgian_can 0x10010ea +#define IBUS_Georgian_jil 0x10010eb +#define IBUS_Georgian_cil 0x10010ec +#define IBUS_Georgian_char 0x10010ed +#define IBUS_Georgian_xan 0x10010ee +#define IBUS_Georgian_jhan 0x10010ef +#define IBUS_Georgian_hae 0x10010f0 +#define IBUS_Georgian_he 0x10010f1 +#define IBUS_Georgian_hie 0x10010f2 +#define IBUS_Georgian_we 0x10010f3 +#define IBUS_Georgian_har 0x10010f4 +#define IBUS_Georgian_hoe 0x10010f5 +#define IBUS_Georgian_fi 0x10010f6 +#define IBUS_Xabovedot 0x1001e8a +#define IBUS_Ibreve 0x100012c +#define IBUS_Zstroke 0x10001b5 +#define IBUS_Gcaron 0x10001e6 +#define IBUS_Ocaron 0x10001d1 +#define IBUS_Obarred 0x100019f +#define IBUS_xabovedot 0x1001e8b +#define IBUS_ibreve 0x100012d +#define IBUS_zstroke 0x10001b6 +#define IBUS_gcaron 0x10001e7 +#define IBUS_ocaron 0x10001d2 +#define IBUS_obarred 0x1000275 +#define IBUS_SCHWA 0x100018f +#define IBUS_schwa 0x1000259 +#define IBUS_Lbelowdot 0x1001e36 +#define IBUS_lbelowdot 0x1001e37 +#define IBUS_Abelowdot 0x1001ea0 +#define IBUS_abelowdot 0x1001ea1 +#define IBUS_Ahook 0x1001ea2 +#define IBUS_ahook 0x1001ea3 +#define IBUS_Acircumflexacute 0x1001ea4 +#define IBUS_acircumflexacute 0x1001ea5 +#define IBUS_Acircumflexgrave 0x1001ea6 +#define IBUS_acircumflexgrave 0x1001ea7 +#define IBUS_Acircumflexhook 0x1001ea8 +#define IBUS_acircumflexhook 0x1001ea9 +#define IBUS_Acircumflextilde 0x1001eaa +#define IBUS_acircumflextilde 0x1001eab +#define IBUS_Acircumflexbelowdot 0x1001eac +#define IBUS_acircumflexbelowdot 0x1001ead +#define IBUS_Abreveacute 0x1001eae +#define IBUS_abreveacute 0x1001eaf +#define IBUS_Abrevegrave 0x1001eb0 +#define IBUS_abrevegrave 0x1001eb1 +#define IBUS_Abrevehook 0x1001eb2 +#define IBUS_abrevehook 0x1001eb3 +#define IBUS_Abrevetilde 0x1001eb4 +#define IBUS_abrevetilde 0x1001eb5 +#define IBUS_Abrevebelowdot 0x1001eb6 +#define IBUS_abrevebelowdot 0x1001eb7 +#define IBUS_Ebelowdot 0x1001eb8 +#define IBUS_ebelowdot 0x1001eb9 +#define IBUS_Ehook 0x1001eba +#define IBUS_ehook 0x1001ebb +#define IBUS_Etilde 0x1001ebc +#define IBUS_etilde 0x1001ebd +#define IBUS_Ecircumflexacute 0x1001ebe +#define IBUS_ecircumflexacute 0x1001ebf +#define IBUS_Ecircumflexgrave 0x1001ec0 +#define IBUS_ecircumflexgrave 0x1001ec1 +#define IBUS_Ecircumflexhook 0x1001ec2 +#define IBUS_ecircumflexhook 0x1001ec3 +#define IBUS_Ecircumflextilde 0x1001ec4 +#define IBUS_ecircumflextilde 0x1001ec5 +#define IBUS_Ecircumflexbelowdot 0x1001ec6 +#define IBUS_ecircumflexbelowdot 0x1001ec7 +#define IBUS_Ihook 0x1001ec8 +#define IBUS_ihook 0x1001ec9 +#define IBUS_Ibelowdot 0x1001eca +#define IBUS_ibelowdot 0x1001ecb +#define IBUS_Obelowdot 0x1001ecc +#define IBUS_obelowdot 0x1001ecd +#define IBUS_Ohook 0x1001ece +#define IBUS_ohook 0x1001ecf +#define IBUS_Ocircumflexacute 0x1001ed0 +#define IBUS_ocircumflexacute 0x1001ed1 +#define IBUS_Ocircumflexgrave 0x1001ed2 +#define IBUS_ocircumflexgrave 0x1001ed3 +#define IBUS_Ocircumflexhook 0x1001ed4 +#define IBUS_ocircumflexhook 0x1001ed5 +#define IBUS_Ocircumflextilde 0x1001ed6 +#define IBUS_ocircumflextilde 0x1001ed7 +#define IBUS_Ocircumflexbelowdot 0x1001ed8 +#define IBUS_ocircumflexbelowdot 0x1001ed9 +#define IBUS_Ohornacute 0x1001eda +#define IBUS_ohornacute 0x1001edb +#define IBUS_Ohorngrave 0x1001edc +#define IBUS_ohorngrave 0x1001edd +#define IBUS_Ohornhook 0x1001ede +#define IBUS_ohornhook 0x1001edf +#define IBUS_Ohorntilde 0x1001ee0 +#define IBUS_ohorntilde 0x1001ee1 +#define IBUS_Ohornbelowdot 0x1001ee2 +#define IBUS_ohornbelowdot 0x1001ee3 +#define IBUS_Ubelowdot 0x1001ee4 +#define IBUS_ubelowdot 0x1001ee5 +#define IBUS_Uhook 0x1001ee6 +#define IBUS_uhook 0x1001ee7 +#define IBUS_Uhornacute 0x1001ee8 +#define IBUS_uhornacute 0x1001ee9 +#define IBUS_Uhorngrave 0x1001eea +#define IBUS_uhorngrave 0x1001eeb +#define IBUS_Uhornhook 0x1001eec +#define IBUS_uhornhook 0x1001eed +#define IBUS_Uhorntilde 0x1001eee +#define IBUS_uhorntilde 0x1001eef +#define IBUS_Uhornbelowdot 0x1001ef0 +#define IBUS_uhornbelowdot 0x1001ef1 +#define IBUS_Ybelowdot 0x1001ef4 +#define IBUS_ybelowdot 0x1001ef5 +#define IBUS_Yhook 0x1001ef6 +#define IBUS_yhook 0x1001ef7 +#define IBUS_Ytilde 0x1001ef8 +#define IBUS_ytilde 0x1001ef9 +#define IBUS_Ohorn 0x10001a0 +#define IBUS_ohorn 0x10001a1 +#define IBUS_Uhorn 0x10001af +#define IBUS_uhorn 0x10001b0 +#define IBUS_EcuSign 0x10020a0 +#define IBUS_ColonSign 0x10020a1 +#define IBUS_CruzeiroSign 0x10020a2 +#define IBUS_FFrancSign 0x10020a3 +#define IBUS_LiraSign 0x10020a4 +#define IBUS_MillSign 0x10020a5 +#define IBUS_NairaSign 0x10020a6 +#define IBUS_PesetaSign 0x10020a7 +#define IBUS_RupeeSign 0x10020a8 +#define IBUS_WonSign 0x10020a9 +#define IBUS_NewSheqelSign 0x10020aa +#define IBUS_DongSign 0x10020ab +#define IBUS_EuroSign 0x20ac +#define IBUS_zerosuperior 0x1002070 +#define IBUS_foursuperior 0x1002074 +#define IBUS_fivesuperior 0x1002075 +#define IBUS_sixsuperior 0x1002076 +#define IBUS_sevensuperior 0x1002077 +#define IBUS_eightsuperior 0x1002078 +#define IBUS_ninesuperior 0x1002079 +#define IBUS_zerosubscript 0x1002080 +#define IBUS_onesubscript 0x1002081 +#define IBUS_twosubscript 0x1002082 +#define IBUS_threesubscript 0x1002083 +#define IBUS_foursubscript 0x1002084 +#define IBUS_fivesubscript 0x1002085 +#define IBUS_sixsubscript 0x1002086 +#define IBUS_sevensubscript 0x1002087 +#define IBUS_eightsubscript 0x1002088 +#define IBUS_ninesubscript 0x1002089 +#define IBUS_partdifferential 0x1002202 +#define IBUS_emptyset 0x1002205 +#define IBUS_elementof 0x1002208 +#define IBUS_notelementof 0x1002209 +#define IBUS_containsas 0x100220b +#define IBUS_squareroot 0x100221a +#define IBUS_cuberoot 0x100221b +#define IBUS_fourthroot 0x100221c +#define IBUS_dintegral 0x100222c +#define IBUS_tintegral 0x100222d +#define IBUS_because 0x1002235 +#define IBUS_approxeq 0x1002248 +#define IBUS_notapproxeq 0x1002247 +#define IBUS_notidentical 0x1002262 +#define IBUS_stricteq 0x1002263 +#define IBUS_braille_dot_1 0xfff1 +#define IBUS_braille_dot_2 0xfff2 +#define IBUS_braille_dot_3 0xfff3 +#define IBUS_braille_dot_4 0xfff4 +#define IBUS_braille_dot_5 0xfff5 +#define IBUS_braille_dot_6 0xfff6 +#define IBUS_braille_dot_7 0xfff7 +#define IBUS_braille_dot_8 0xfff8 +#define IBUS_braille_dot_9 0xfff9 +#define IBUS_braille_dot_10 0xfffa +#define IBUS_braille_blank 0x1002800 +#define IBUS_braille_dots_1 0x1002801 +#define IBUS_braille_dots_2 0x1002802 +#define IBUS_braille_dots_12 0x1002803 +#define IBUS_braille_dots_3 0x1002804 +#define IBUS_braille_dots_13 0x1002805 +#define IBUS_braille_dots_23 0x1002806 +#define IBUS_braille_dots_123 0x1002807 +#define IBUS_braille_dots_4 0x1002808 +#define IBUS_braille_dots_14 0x1002809 +#define IBUS_braille_dots_24 0x100280a +#define IBUS_braille_dots_124 0x100280b +#define IBUS_braille_dots_34 0x100280c +#define IBUS_braille_dots_134 0x100280d +#define IBUS_braille_dots_234 0x100280e +#define IBUS_braille_dots_1234 0x100280f +#define IBUS_braille_dots_5 0x1002810 +#define IBUS_braille_dots_15 0x1002811 +#define IBUS_braille_dots_25 0x1002812 +#define IBUS_braille_dots_125 0x1002813 +#define IBUS_braille_dots_35 0x1002814 +#define IBUS_braille_dots_135 0x1002815 +#define IBUS_braille_dots_235 0x1002816 +#define IBUS_braille_dots_1235 0x1002817 +#define IBUS_braille_dots_45 0x1002818 +#define IBUS_braille_dots_145 0x1002819 +#define IBUS_braille_dots_245 0x100281a +#define IBUS_braille_dots_1245 0x100281b +#define IBUS_braille_dots_345 0x100281c +#define IBUS_braille_dots_1345 0x100281d +#define IBUS_braille_dots_2345 0x100281e +#define IBUS_braille_dots_12345 0x100281f +#define IBUS_braille_dots_6 0x1002820 +#define IBUS_braille_dots_16 0x1002821 +#define IBUS_braille_dots_26 0x1002822 +#define IBUS_braille_dots_126 0x1002823 +#define IBUS_braille_dots_36 0x1002824 +#define IBUS_braille_dots_136 0x1002825 +#define IBUS_braille_dots_236 0x1002826 +#define IBUS_braille_dots_1236 0x1002827 +#define IBUS_braille_dots_46 0x1002828 +#define IBUS_braille_dots_146 0x1002829 +#define IBUS_braille_dots_246 0x100282a +#define IBUS_braille_dots_1246 0x100282b +#define IBUS_braille_dots_346 0x100282c +#define IBUS_braille_dots_1346 0x100282d +#define IBUS_braille_dots_2346 0x100282e +#define IBUS_braille_dots_12346 0x100282f +#define IBUS_braille_dots_56 0x1002830 +#define IBUS_braille_dots_156 0x1002831 +#define IBUS_braille_dots_256 0x1002832 +#define IBUS_braille_dots_1256 0x1002833 +#define IBUS_braille_dots_356 0x1002834 +#define IBUS_braille_dots_1356 0x1002835 +#define IBUS_braille_dots_2356 0x1002836 +#define IBUS_braille_dots_12356 0x1002837 +#define IBUS_braille_dots_456 0x1002838 +#define IBUS_braille_dots_1456 0x1002839 +#define IBUS_braille_dots_2456 0x100283a +#define IBUS_braille_dots_12456 0x100283b +#define IBUS_braille_dots_3456 0x100283c +#define IBUS_braille_dots_13456 0x100283d +#define IBUS_braille_dots_23456 0x100283e +#define IBUS_braille_dots_123456 0x100283f +#define IBUS_braille_dots_7 0x1002840 +#define IBUS_braille_dots_17 0x1002841 +#define IBUS_braille_dots_27 0x1002842 +#define IBUS_braille_dots_127 0x1002843 +#define IBUS_braille_dots_37 0x1002844 +#define IBUS_braille_dots_137 0x1002845 +#define IBUS_braille_dots_237 0x1002846 +#define IBUS_braille_dots_1237 0x1002847 +#define IBUS_braille_dots_47 0x1002848 +#define IBUS_braille_dots_147 0x1002849 +#define IBUS_braille_dots_247 0x100284a +#define IBUS_braille_dots_1247 0x100284b +#define IBUS_braille_dots_347 0x100284c +#define IBUS_braille_dots_1347 0x100284d +#define IBUS_braille_dots_2347 0x100284e +#define IBUS_braille_dots_12347 0x100284f +#define IBUS_braille_dots_57 0x1002850 +#define IBUS_braille_dots_157 0x1002851 +#define IBUS_braille_dots_257 0x1002852 +#define IBUS_braille_dots_1257 0x1002853 +#define IBUS_braille_dots_357 0x1002854 +#define IBUS_braille_dots_1357 0x1002855 +#define IBUS_braille_dots_2357 0x1002856 +#define IBUS_braille_dots_12357 0x1002857 +#define IBUS_braille_dots_457 0x1002858 +#define IBUS_braille_dots_1457 0x1002859 +#define IBUS_braille_dots_2457 0x100285a +#define IBUS_braille_dots_12457 0x100285b +#define IBUS_braille_dots_3457 0x100285c +#define IBUS_braille_dots_13457 0x100285d +#define IBUS_braille_dots_23457 0x100285e +#define IBUS_braille_dots_123457 0x100285f +#define IBUS_braille_dots_67 0x1002860 +#define IBUS_braille_dots_167 0x1002861 +#define IBUS_braille_dots_267 0x1002862 +#define IBUS_braille_dots_1267 0x1002863 +#define IBUS_braille_dots_367 0x1002864 +#define IBUS_braille_dots_1367 0x1002865 +#define IBUS_braille_dots_2367 0x1002866 +#define IBUS_braille_dots_12367 0x1002867 +#define IBUS_braille_dots_467 0x1002868 +#define IBUS_braille_dots_1467 0x1002869 +#define IBUS_braille_dots_2467 0x100286a +#define IBUS_braille_dots_12467 0x100286b +#define IBUS_braille_dots_3467 0x100286c +#define IBUS_braille_dots_13467 0x100286d +#define IBUS_braille_dots_23467 0x100286e +#define IBUS_braille_dots_123467 0x100286f +#define IBUS_braille_dots_567 0x1002870 +#define IBUS_braille_dots_1567 0x1002871 +#define IBUS_braille_dots_2567 0x1002872 +#define IBUS_braille_dots_12567 0x1002873 +#define IBUS_braille_dots_3567 0x1002874 +#define IBUS_braille_dots_13567 0x1002875 +#define IBUS_braille_dots_23567 0x1002876 +#define IBUS_braille_dots_123567 0x1002877 +#define IBUS_braille_dots_4567 0x1002878 +#define IBUS_braille_dots_14567 0x1002879 +#define IBUS_braille_dots_24567 0x100287a +#define IBUS_braille_dots_124567 0x100287b +#define IBUS_braille_dots_34567 0x100287c +#define IBUS_braille_dots_134567 0x100287d +#define IBUS_braille_dots_234567 0x100287e +#define IBUS_braille_dots_1234567 0x100287f +#define IBUS_braille_dots_8 0x1002880 +#define IBUS_braille_dots_18 0x1002881 +#define IBUS_braille_dots_28 0x1002882 +#define IBUS_braille_dots_128 0x1002883 +#define IBUS_braille_dots_38 0x1002884 +#define IBUS_braille_dots_138 0x1002885 +#define IBUS_braille_dots_238 0x1002886 +#define IBUS_braille_dots_1238 0x1002887 +#define IBUS_braille_dots_48 0x1002888 +#define IBUS_braille_dots_148 0x1002889 +#define IBUS_braille_dots_248 0x100288a +#define IBUS_braille_dots_1248 0x100288b +#define IBUS_braille_dots_348 0x100288c +#define IBUS_braille_dots_1348 0x100288d +#define IBUS_braille_dots_2348 0x100288e +#define IBUS_braille_dots_12348 0x100288f +#define IBUS_braille_dots_58 0x1002890 +#define IBUS_braille_dots_158 0x1002891 +#define IBUS_braille_dots_258 0x1002892 +#define IBUS_braille_dots_1258 0x1002893 +#define IBUS_braille_dots_358 0x1002894 +#define IBUS_braille_dots_1358 0x1002895 +#define IBUS_braille_dots_2358 0x1002896 +#define IBUS_braille_dots_12358 0x1002897 +#define IBUS_braille_dots_458 0x1002898 +#define IBUS_braille_dots_1458 0x1002899 +#define IBUS_braille_dots_2458 0x100289a +#define IBUS_braille_dots_12458 0x100289b +#define IBUS_braille_dots_3458 0x100289c +#define IBUS_braille_dots_13458 0x100289d +#define IBUS_braille_dots_23458 0x100289e +#define IBUS_braille_dots_123458 0x100289f +#define IBUS_braille_dots_68 0x10028a0 +#define IBUS_braille_dots_168 0x10028a1 +#define IBUS_braille_dots_268 0x10028a2 +#define IBUS_braille_dots_1268 0x10028a3 +#define IBUS_braille_dots_368 0x10028a4 +#define IBUS_braille_dots_1368 0x10028a5 +#define IBUS_braille_dots_2368 0x10028a6 +#define IBUS_braille_dots_12368 0x10028a7 +#define IBUS_braille_dots_468 0x10028a8 +#define IBUS_braille_dots_1468 0x10028a9 +#define IBUS_braille_dots_2468 0x10028aa +#define IBUS_braille_dots_12468 0x10028ab +#define IBUS_braille_dots_3468 0x10028ac +#define IBUS_braille_dots_13468 0x10028ad +#define IBUS_braille_dots_23468 0x10028ae +#define IBUS_braille_dots_123468 0x10028af +#define IBUS_braille_dots_568 0x10028b0 +#define IBUS_braille_dots_1568 0x10028b1 +#define IBUS_braille_dots_2568 0x10028b2 +#define IBUS_braille_dots_12568 0x10028b3 +#define IBUS_braille_dots_3568 0x10028b4 +#define IBUS_braille_dots_13568 0x10028b5 +#define IBUS_braille_dots_23568 0x10028b6 +#define IBUS_braille_dots_123568 0x10028b7 +#define IBUS_braille_dots_4568 0x10028b8 +#define IBUS_braille_dots_14568 0x10028b9 +#define IBUS_braille_dots_24568 0x10028ba +#define IBUS_braille_dots_124568 0x10028bb +#define IBUS_braille_dots_34568 0x10028bc +#define IBUS_braille_dots_134568 0x10028bd +#define IBUS_braille_dots_234568 0x10028be +#define IBUS_braille_dots_1234568 0x10028bf +#define IBUS_braille_dots_78 0x10028c0 +#define IBUS_braille_dots_178 0x10028c1 +#define IBUS_braille_dots_278 0x10028c2 +#define IBUS_braille_dots_1278 0x10028c3 +#define IBUS_braille_dots_378 0x10028c4 +#define IBUS_braille_dots_1378 0x10028c5 +#define IBUS_braille_dots_2378 0x10028c6 +#define IBUS_braille_dots_12378 0x10028c7 +#define IBUS_braille_dots_478 0x10028c8 +#define IBUS_braille_dots_1478 0x10028c9 +#define IBUS_braille_dots_2478 0x10028ca +#define IBUS_braille_dots_12478 0x10028cb +#define IBUS_braille_dots_3478 0x10028cc +#define IBUS_braille_dots_13478 0x10028cd +#define IBUS_braille_dots_23478 0x10028ce +#define IBUS_braille_dots_123478 0x10028cf +#define IBUS_braille_dots_578 0x10028d0 +#define IBUS_braille_dots_1578 0x10028d1 +#define IBUS_braille_dots_2578 0x10028d2 +#define IBUS_braille_dots_12578 0x10028d3 +#define IBUS_braille_dots_3578 0x10028d4 +#define IBUS_braille_dots_13578 0x10028d5 +#define IBUS_braille_dots_23578 0x10028d6 +#define IBUS_braille_dots_123578 0x10028d7 +#define IBUS_braille_dots_4578 0x10028d8 +#define IBUS_braille_dots_14578 0x10028d9 +#define IBUS_braille_dots_24578 0x10028da +#define IBUS_braille_dots_124578 0x10028db +#define IBUS_braille_dots_34578 0x10028dc +#define IBUS_braille_dots_134578 0x10028dd +#define IBUS_braille_dots_234578 0x10028de +#define IBUS_braille_dots_1234578 0x10028df +#define IBUS_braille_dots_678 0x10028e0 +#define IBUS_braille_dots_1678 0x10028e1 +#define IBUS_braille_dots_2678 0x10028e2 +#define IBUS_braille_dots_12678 0x10028e3 +#define IBUS_braille_dots_3678 0x10028e4 +#define IBUS_braille_dots_13678 0x10028e5 +#define IBUS_braille_dots_23678 0x10028e6 +#define IBUS_braille_dots_123678 0x10028e7 +#define IBUS_braille_dots_4678 0x10028e8 +#define IBUS_braille_dots_14678 0x10028e9 +#define IBUS_braille_dots_24678 0x10028ea +#define IBUS_braille_dots_124678 0x10028eb +#define IBUS_braille_dots_34678 0x10028ec +#define IBUS_braille_dots_134678 0x10028ed +#define IBUS_braille_dots_234678 0x10028ee +#define IBUS_braille_dots_1234678 0x10028ef +#define IBUS_braille_dots_5678 0x10028f0 +#define IBUS_braille_dots_15678 0x10028f1 +#define IBUS_braille_dots_25678 0x10028f2 +#define IBUS_braille_dots_125678 0x10028f3 +#define IBUS_braille_dots_35678 0x10028f4 +#define IBUS_braille_dots_135678 0x10028f5 +#define IBUS_braille_dots_235678 0x10028f6 +#define IBUS_braille_dots_1235678 0x10028f7 +#define IBUS_braille_dots_45678 0x10028f8 +#define IBUS_braille_dots_145678 0x10028f9 +#define IBUS_braille_dots_245678 0x10028fa +#define IBUS_braille_dots_1245678 0x10028fb +#define IBUS_braille_dots_345678 0x10028fc +#define IBUS_braille_dots_1345678 0x10028fd +#define IBUS_braille_dots_2345678 0x10028fe +#define IBUS_braille_dots_12345678 0x10028ff + +#endif /* __IBUS_KEYSYMS_H__ */ diff --git a/src/ibuslookuptable.c b/src/ibuslookuptable.c new file mode 100644 index 0000000..aab3ecd --- /dev/null +++ b/src/ibuslookuptable.c @@ -0,0 +1,283 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include "ibuslookuptable.h" + +/* functions prototype */ +static void ibus_lookup_table_class_init (IBusLookupTableClass *klass); +static void ibus_lookup_table_init (IBusLookupTable *table); +static void ibus_lookup_table_destroy (IBusLookupTable *table); +static gboolean ibus_lookup_table_serialize (IBusLookupTable *table, + IBusMessageIter *iter); +static gboolean ibus_lookup_table_deserialize (IBusLookupTable *table, + IBusMessageIter *iter); +static gboolean ibus_lookup_table_copy (IBusLookupTable *dest, + IBusLookupTable *src); + +static IBusSerializableClass *parent_class = NULL; + +GType +ibus_lookup_table_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusLookupTableClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_lookup_table_class_init, + NULL, /* class finialize */ + NULL, /* class data */ + sizeof (IBusLookupTable), + 0, + (GInstanceInitFunc) ibus_lookup_table_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusLookupTable", + &type_info, + 0); + } + + return type; +} + +static void +ibus_lookup_table_class_init (IBusLookupTableClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_lookup_table_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_lookup_table_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_lookup_table_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_lookup_table_copy; + + g_string_append (serializable_class->signature, "uubav"); +} + +static void +ibus_lookup_table_init (IBusLookupTable *table) +{ + table->candidates = g_array_new (TRUE, TRUE, sizeof (IBusText *)); +} + +static void +ibus_lookup_table_destroy (IBusLookupTable *table) +{ + IBusText **sp, **p; + + if (table->candidates != NULL) { + p = sp = (IBusText **) g_array_free (table->candidates, FALSE); + table->candidates = NULL; + while (*p != NULL) { + g_object_unref (*p); + p ++; + } + g_free (sp); + } + + IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *) table); +} + +static gboolean +ibus_lookup_table_serialize (IBusLookupTable *table, + IBusMessageIter *iter) +{ + IBusMessageIter array_iter; + gboolean retval; + guint i; + + retval = parent_class->serialize ((IBusSerializable *)table, iter); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_LOOKUP_TABLE (table), FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_UINT, &table->page_size); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_UINT, &table->cursor_pos); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_BOOLEAN, &table->cursor_visible); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_open_container (iter, + IBUS_TYPE_ARRAY, + "v", + &array_iter); + g_return_val_if_fail (retval, FALSE); + + for (i = 0;; i++) { + IBusText *text; + + text = ibus_lookup_table_get_candidate (table, i); + if (text == NULL) + break; + + retval = ibus_message_iter_append (&array_iter, IBUS_TYPE_TEXT, &text); + g_return_val_if_fail (retval, FALSE); + } + + retval = ibus_message_iter_close_container (iter, &array_iter); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_lookup_table_deserialize (IBusLookupTable *table, + IBusMessageIter *iter) +{ + DBusMessageIter array_iter; + gboolean retval; + + retval = parent_class->deserialize ((IBusSerializable *)table, iter); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_LOOKUP_TABLE (table), FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_UINT, &table->page_size); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_UINT, &table->cursor_pos); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_BOOLEAN, &table->cursor_visible); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_recurse (iter, IBUS_TYPE_ARRAY, &array_iter); + g_return_val_if_fail (retval, FALSE); + + while (ibus_message_iter_get_arg_type (&array_iter) != G_TYPE_INVALID) { + IBusText *text; + retval = ibus_message_iter_get (&array_iter, IBUS_TYPE_TEXT, &text); + g_return_val_if_fail (retval, FALSE); + + ibus_lookup_table_append_candidate (table, text); + } + + ibus_message_iter_next (iter); + + return TRUE; +} + +static gboolean +ibus_lookup_table_copy (IBusLookupTable *dest, + IBusLookupTable *src) +{ + gboolean retval; + guint i; + + retval = parent_class->copy ((IBusSerializable *)dest, (IBusSerializable *)src); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_LOOKUP_TABLE (dest), FALSE); + g_return_val_if_fail (IBUS_IS_LOOKUP_TABLE (src), FALSE); + + for (i = 0;; i++) { + IBusText *text; + + text = ibus_lookup_table_get_candidate (src, i); + if (text == NULL) + break; + + text = (IBusText *) ibus_serializable_copy ((IBusSerializable *) text); + + ibus_lookup_table_append_candidate (dest, text); + g_object_unref (text); + } + + return TRUE; +} + +IBusLookupTable * +ibus_lookup_table_new (guint page_size, + gboolean cursor_visible) +{ + IBusLookupTable *table; + + table= g_object_new (IBUS_TYPE_LOOKUP_TABLE, NULL); + + table->cursor_pos = 0; + table->page_size = page_size; + table->cursor_visible = cursor_visible; + + return table; +} + +void +ibus_lookup_table_append_candidate (IBusLookupTable *table, + IBusText *text) +{ + g_return_if_fail (IBUS_IS_LOOKUP_TABLE (table)); + g_return_if_fail (IBUS_IS_TEXT (text)); + + g_object_ref (text); + g_array_append_val (table->candidates, text); +} + +IBusText * +ibus_lookup_table_get_candidate (IBusLookupTable *table, + guint index) +{ + g_return_val_if_fail (IBUS_IS_LOOKUP_TABLE (table), NULL); + + if (index >= table->candidates->len) + return NULL; + + return g_array_index (table->candidates, IBusText *, index); +} + + +void +ibus_lookup_table_clear (IBusLookupTable *table) +{ + g_return_if_fail (IBUS_IS_LOOKUP_TABLE (table)); + + gint index; + + for (index = 0; index < table->candidates->len; index ++) { + g_object_unref (g_array_index (table->candidates, IBusText *, index)); + } + + g_array_set_size (table->candidates, 0); +} + +void +ibus_lookup_table_set_cursor_pos (IBusLookupTable *table, + guint cursor_pos) +{ + g_assert (IBUS_IS_LOOKUP_TABLE (table)); + + table->cursor_pos = cursor_pos; +} +void +ibus_lookup_table_set_page_size (IBusLookupTable *table, + guint page_size) +{ + g_assert (IBUS_IS_LOOKUP_TABLE (table)); + + table->page_size = page_size; +} + diff --git a/src/ibuslookuptable.h b/src/ibuslookuptable.h new file mode 100644 index 0000000..2b29138 --- /dev/null +++ b/src/ibuslookuptable.h @@ -0,0 +1,82 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_LOOKUP_TABLE_H_ +#define __IBUS_LOOKUP_TABLE_H_ + +#include "ibusserializable.h" +#include "ibustext.h" + +/* + * Type macros. + */ +/* define IBusLookupTable macros */ +#define IBUS_TYPE_LOOKUP_TABLE \ + (ibus_lookup_table_get_type ()) +#define IBUS_LOOKUP_TABLE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_LOOKUP_TABLE, IBusLookupTable)) +#define IBUS_LOOKUP_TABLE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_LOOKUP_TABLE, IBusLookupTableClass)) +#define IBUS_IS_LOOKUP_TABLE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_LOOKUP_TABLE)) +#define IBUS_IS_LOOKUP_TABLE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_LOOKUP_TABLE)) +#define IBUS_LOOKUP_TABLE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_LOOKUP_TABLE, IBusLookupTableClass)) + + +G_BEGIN_DECLS + +typedef struct _IBusLookupTable IBusLookupTable; +typedef struct _IBusLookupTableClass IBusLookupTableClass; + +struct _IBusLookupTable { + IBusSerializable parent; + + guint page_size; + guint cursor_pos; + gboolean cursor_visible; + + GArray *candidates; +}; + +struct _IBusLookupTableClass { + IBusSerializableClass parent; +}; + + +GType ibus_lookup_table_get_type (void); +IBusLookupTable *ibus_lookup_table_new (guint page_size, + gboolean cursor_visible); +void ibus_lookup_table_append_candidate + (IBusLookupTable *table, + IBusText *text); +IBusText *ibus_lookup_table_get_candidate + (IBusLookupTable *table, + guint index); +void ibus_lookup_table_set_cursor_pos + (IBusLookupTable *table, + guint cursor_pos); +void ibus_lookup_table_set_page_size + (IBusLookupTable *table, + guint page_size); +void ibus_lookup_table_clear (IBusLookupTable *table); +G_END_DECLS +#endif + diff --git a/src/ibusmarshalers.list b/src/ibusmarshalers.list new file mode 100644 index 0000000..14def28 --- /dev/null +++ b/src/ibusmarshalers.list @@ -0,0 +1,18 @@ +VOID:NONE +VOID:OBJECT +VOID:POINTER +VOID:STRING +VOID:STRING,INT +BOOL:POINTER +BOOL:POINTER,POINTER +BOOL:UINT,UINT +VOID:INT,INT,INT,INT +VOID:UINT,UINT +VOID:OBJECT,UINT,BOOL +VOID:OBJECT,BOOL +VOID:BOXED,BOOL +VOID:BOXED +VOID:STRING,STRING,BOXED +VOID:STRING,STRING,STRING +VOID:UINT +VOID:UINT,POINTER diff --git a/src/ibusmessage.c b/src/ibusmessage.c new file mode 100644 index 0000000..08457a3 --- /dev/null +++ b/src/ibusmessage.c @@ -0,0 +1,872 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include "ibusmessage.h" +#include "ibusserializable.h" +#include "ibusconfigprivate.h" + +GType +ibus_type_get_object_path (void) +{ + static GType type = 0; + + if (type == 0) { + type = g_type_register_static_simple ( + G_TYPE_STRING, + "IBusObjectPath", + 0, + NULL, + 0, + NULL, + G_TYPE_FLAG_ABSTRACT); + } + return type; +} + +GType +ibus_type_get_array (void) +{ + static GType type = 0; + + if (type == 0) { + type = g_type_register_static_simple ( + G_TYPE_BOXED, + "IBusArray", + 0, + NULL, + 0, + NULL, + G_TYPE_FLAG_ABSTRACT); + } + return type; +} + +GType +ibus_type_get_struct (void) +{ + static GType type = 0; + + if (type == 0) { + type = g_type_register_static_simple ( + G_TYPE_BOXED, + "IBusStruct", + 0, + NULL, + 0, + NULL, + G_TYPE_FLAG_ABSTRACT); + } + return type; +} + +GType +ibus_type_get_dict_entry (void) +{ + static GType type = 0; + + if (type == 0) { + type = g_type_register_static_simple ( + G_TYPE_BOXED, + "IBusDictEntry", + 0, + NULL, + 0, + NULL, + G_TYPE_FLAG_ABSTRACT); + } + return type; +} + +GType +ibus_type_get_variant (void) +{ + static GType type = 0; + + if (type == 0) { + type = g_type_register_static_simple (G_TYPE_BOXED, + "IBusVariant", + 0, + NULL, + 0, + NULL, + 0); + } + return type; +} + +IBusMessage * +ibus_message_new (gint message_type) +{ + return dbus_message_new (message_type); +} + +IBusMessage * +ibus_message_ref (IBusMessage *message) +{ + return dbus_message_ref (message); +} + +void +ibus_message_unref (IBusMessage *message) +{ + dbus_message_unref (message); +} + +IBusMessage * +ibus_message_new_method_call (const gchar *destination, + const gchar *path, + const gchar *interface, + const gchar *method) +{ + return dbus_message_new_method_call (destination, + path, + interface, + method); +} + +IBusMessage * +ibus_message_new_method_return (IBusMessage *reply_to) +{ + return dbus_message_new_method_return (reply_to); +} + +IBusMessage * +ibus_message_new_error (IBusMessage *reply_to, + const gchar *error_name, + const gchar *error_message) +{ + return dbus_message_new_error (reply_to, + error_name, + error_message); +} + +IBusMessage * +ibus_message_new_error_printf (IBusMessage *reply_to, + const gchar *error_name, + const gchar *error_format, + ...) +{ + va_list va_args; + gchar *error_message; + IBusMessage *message; + + va_start (va_args, error_format); + error_message = g_strdup_vprintf (error_format, va_args); + va_end (va_args); + + message = ibus_message_new_error (reply_to, + error_name, + error_message); + g_free (error_message); + + return message; +} + +IBusMessage * +ibus_message_new_signal (const gchar *path, + const gchar *interface, + const gchar *name) +{ + return dbus_message_new_signal (path, + interface, + name); +} + +gboolean +ibus_message_is_method_call (IBusMessage *message, + const gchar *interface, + const gchar *method) +{ + return dbus_message_is_method_call (message, + interface, + method); +} + +gboolean +ibus_message_is_error (IBusMessage *message, + const gchar *error_name) +{ + return dbus_message_is_error (message, error_name); +} + +gboolean +ibus_message_is_signal (IBusMessage *message, + const gchar *interface, + const gchar *signal_name) +{ + return dbus_message_is_signal (message, + interface, + signal_name); +} + +gboolean +ibus_message_set_destination (IBusMessage *message, + const gchar *destination) +{ + return dbus_message_set_destination (message, destination); +} + +gboolean +ibus_message_set_sender (IBusMessage *message, + const gchar *sender) +{ + return dbus_message_set_sender (message, sender); +} + +gboolean +ibus_message_set_error_name (IBusMessage *message, + const gchar *error_name) +{ + return dbus_message_set_error_name (message, error_name); +} + +gboolean +ibus_message_set_interface (IBusMessage *message, + const gchar *interface) +{ + return dbus_message_set_interface (message, interface); +} + +gboolean +ibus_message_set_member (IBusMessage *message, + const gchar *member) +{ + return dbus_message_set_member (message, member); +} + +gboolean +ibus_message_set_path (IBusMessage *message, + const gchar *path) +{ + return dbus_message_set_path (message, path); +} + +void +ibus_message_set_no_reply (IBusMessage *message, + gboolean no_reply) +{ + return dbus_message_set_no_reply (message, no_reply); +} + +gboolean +ibus_message_set_reply_serial (IBusMessage *message, + guint32 reply_serial) +{ + return dbus_message_set_reply_serial (message, reply_serial); +} + +gint +ibus_message_get_type (IBusMessage *message) +{ + return dbus_message_get_type (message); +} + +const gchar * +ibus_message_get_destination (IBusMessage *message) +{ + return dbus_message_get_destination (message); +} + +const gchar * +ibus_message_get_sender (IBusMessage *message) +{ + return dbus_message_get_sender (message); +} + +const gchar * +ibus_message_get_error_name (IBusMessage *message) +{ + return dbus_message_get_error_name (message); +} + +const gchar * +ibus_message_get_error_message (IBusMessage *message) +{ + gchar *error_message; + gboolean retval; + + retval = ibus_message_get_args (message, NULL, G_TYPE_STRING, &error_message, G_TYPE_INVALID); + + if (retval) + return error_message; + return NULL; +} + +const gchar * +ibus_message_get_interface (IBusMessage *message) +{ + return dbus_message_get_interface (message); +} + +const gchar * +ibus_message_get_member (IBusMessage *message) +{ + return dbus_message_get_member (message); +} + +const gchar * +ibus_message_get_path (IBusMessage *message) +{ + return dbus_message_get_path (message); +} + +gboolean +ibus_message_get_no_reply (IBusMessage *message) +{ + return dbus_message_get_no_reply (message); +} + +guint32 +ibus_message_get_reply_serial (IBusMessage *message) +{ + return dbus_message_get_reply_serial (message); +} + +guint32 +ibus_message_get_serial (IBusMessage *message) +{ + return dbus_message_get_serial (message); +} + +gboolean +ibus_message_append_args (IBusMessage *message, + GType first_arg_type, + ...) +{ + gboolean retval; + va_list va_args; + + va_start (va_args, first_arg_type); + retval = ibus_message_append_args_valist (message, + first_arg_type, + va_args); + va_end (va_args); + + return retval; +} + +gboolean +ibus_message_append_args_valist (IBusMessage *message, + GType first_arg_type, + va_list va_args) +{ + GType type; + gboolean retval; + IBusMessageIter iter; + + ibus_message_iter_init_append (message, &iter); + + type = first_arg_type; + while (type != G_TYPE_INVALID) { + gpointer value = va_arg (va_args, gpointer); + retval = ibus_message_iter_append (&iter, type, value); + type = va_arg (va_args, GType); + + g_return_val_if_fail (retval, FALSE); + } + + return TRUE; +} + +gboolean +ibus_message_get_args (IBusMessage *message, + IBusError **error, + GType first_arg_type, + ...) +{ + gboolean retval; + va_list va_args; + + va_start (va_args, first_arg_type); + retval = ibus_message_get_args_valist (message, + error, + first_arg_type, + va_args); + va_end (va_args); + + return retval; + +} + +gboolean +ibus_message_get_args_valist (IBusMessage *message, + IBusError **error, + GType first_arg_type, + va_list va_args) +{ + g_assert (message != NULL); + + gboolean retval; + IBusMessageIter iter; + GType type; + gpointer value; + va_list backup_args; + gint i; + + retval = ibus_message_iter_init (message, &iter); + + if (!retval) { + if (error) { + *error = ibus_error_new_from_printf (DBUS_ERROR_INVALID_ARGS, + "Message does not have arguments!"); + } + return FALSE; + } + + va_copy (backup_args, va_args); + + i = 0; + type = first_arg_type; + while (type != G_TYPE_INVALID) { + value = va_arg (va_args, gpointer); + retval = ibus_message_iter_get (&iter, type, value); + if (!retval) + goto _failed; + i ++; + type = va_arg (va_args, GType); + } + va_end (backup_args); + + return TRUE; + +_failed: + *error = ibus_error_new_from_printf (DBUS_ERROR_INVALID_ARGS, + "The argument %d is not %s", + i, + g_type_name (type)); + /* release resources */ + type = first_arg_type; + while (i > 0) { + gpointer *value = va_arg (backup_args, gpointer *); + if (g_type_is_a (type, G_TYPE_BOXED)) { + g_boxed_free (type, *value); + } + else if (g_type_is_a (type, G_TYPE_OBJECT)) { + g_object_unref (*value); + } + i --; + type = va_arg (backup_args, GType); + } + va_end (backup_args); + + return FALSE; +} + +void +ibus_message_iter_init_append (IBusMessage *message, + IBusMessageIter *iter) +{ + dbus_message_iter_init_append (message, iter); +} + +gboolean +ibus_message_iter_append (IBusMessageIter *iter, + GType type, + gconstpointer value) +{ + g_assert (iter != NULL); + g_assert (type != G_TYPE_INVALID); + g_assert (value != NULL); + + switch (type) { + case G_TYPE_CHAR: + { + char v; + v = * (gchar *)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_BYTE, &v); + } + case G_TYPE_INT: + { + dbus_int32_t v; + v = * (gint *)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_INT32, &v); + } + case G_TYPE_UINT: + { + dbus_uint32_t v; + v = * (guint *)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &v); + } + case G_TYPE_ULONG: + { + dbus_uint64_t v; + v = * (gulong *)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT64, &v); + } + case G_TYPE_LONG: + { + dbus_int64_t v; + v = * (glong *)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &v); + } + case G_TYPE_BOOLEAN: + { + dbus_bool_t v; + v = * (gboolean *)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &v); + } + case G_TYPE_STRING: + { + const gchar *v; + v = * (gchar **)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &v); + } + case G_TYPE_INT64: + { + dbus_int64_t v; + v = * (gint64 *)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &v); + } + case G_TYPE_UINT64: + { + dbus_uint64_t v; + v = * (guint64 *)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT64, &v); + } + case G_TYPE_FLOAT: + { + double v; + v = * (gfloat *)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_DOUBLE, &v); + } + + case G_TYPE_DOUBLE: + { + double v; + v = * (gdouble *)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_DOUBLE, &v); + } + default: + if (type == G_TYPE_VALUE) { + _to_dbus_value (iter, (GValue *)value); + return TRUE; + } + if (type == IBUS_TYPE_OBJECT_PATH) { + const gchar *v; + v = * (gchar **)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_OBJECT_PATH, &v); + } + + if (g_type_is_a (type, IBUS_TYPE_SERIALIZABLE)) { + return ibus_serializable_serialize (*(IBusSerializable **)value, iter); + } + } + + return FALSE; +} + +gboolean +ibus_message_iter_init (IBusMessage *message, + IBusMessageIter *iter) +{ + return dbus_message_iter_init (message, iter); +} + +void +ibus_message_iter_get_basic (IBusMessageIter *iter, + gpointer value) +{ + dbus_message_iter_get_basic (iter, value); + dbus_message_iter_next (iter); +} + +gboolean +ibus_message_iter_get (IBusMessageIter *iter, + GType type, + gpointer value) +{ + gboolean retval; + + retval = ibus_message_iter_peek (iter, type, value); + ibus_message_iter_next (iter); + + return retval; +} + +gboolean +ibus_message_iter_peek (IBusMessageIter *iter, + GType type, + gpointer value) +{ + g_assert (iter != NULL); + g_assert (type != G_TYPE_INVALID); + g_assert (value != NULL); + + switch (type) { + case G_TYPE_CHAR: + { + char v; + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_BYTE) + return FALSE; + dbus_message_iter_get_basic (iter, &v); + *(gchar *) value = (gchar) v; + return TRUE; + } + case G_TYPE_INT: + { + dbus_int32_t v; + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_INT32) + return FALSE; + dbus_message_iter_get_basic (iter, &v); + *(gint *) value = (gint) v; + return TRUE; + } + case G_TYPE_UINT: + { + dbus_uint32_t v; + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_UINT32) + return FALSE; + dbus_message_iter_get_basic (iter, &v); + *(guint *) value = (guint) v; + return TRUE; + } + case G_TYPE_BOOLEAN: + { + dbus_bool_t v; + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_BOOLEAN) + return FALSE; + dbus_message_iter_get_basic (iter, &v); + *(gboolean *) value = (gboolean) v; + return TRUE; + } + case G_TYPE_STRING: + { + gchar *v; + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRING) + return FALSE; + dbus_message_iter_get_basic (iter, &v); + *(gchar **) value = (gchar *) v; + return TRUE; + } + case G_TYPE_INT64: + { + dbus_int64_t v; + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_INT64) + return FALSE; + dbus_message_iter_get_basic (iter, &v); + *(gint64 *) value = (gint64) v; + return TRUE; + } + case G_TYPE_UINT64: + { + dbus_uint64_t v; + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_UINT64) + return FALSE; + dbus_message_iter_get_basic (iter, &v); + *(guint64 *) value = (guint64) v; + return TRUE; + } + case G_TYPE_FLOAT: + { + double v; + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_DOUBLE) + return FALSE; + dbus_message_iter_get_basic (iter, &v); + *(gfloat *) value = (gfloat) v; + return TRUE; + } + + case G_TYPE_DOUBLE: + { + double v; + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_DOUBLE) + return FALSE; + dbus_message_iter_get_basic (iter, &v); + *(gdouble *) value = (gdouble) v; + return TRUE; + } + default: + if (type == G_TYPE_VALUE) { + _from_dbus_value (iter, (GValue *) value); + return TRUE; + } + if (type == IBUS_TYPE_OBJECT_PATH) { + gchar *v; + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_OBJECT_PATH) + return FALSE; + dbus_message_iter_get_basic (iter, &v); + *(gchar **) value = (gchar *) v; + return TRUE; + } + + if (g_type_is_a (type, IBUS_TYPE_SERIALIZABLE)) { + IBusSerializable *v; + v = ibus_serializable_deserialize (iter); + + if (v == NULL) + return FALSE; + if (!g_type_is_a (G_OBJECT_TYPE (v), type)) { + g_object_unref (v); + return FALSE; + } + *(gpointer *) value = v; + return TRUE; + } + } + return FALSE; +} + +gboolean +ibus_message_iter_next (IBusMessageIter *iter) +{ + return dbus_message_iter_next (iter); +} + +gboolean +ibus_message_iter_has_next (IBusMessageIter *iter) +{ + return dbus_message_iter_has_next (iter); +} + +gboolean +ibus_message_iter_open_container (IBusMessageIter *iter, + GType type, + const gchar *contained_signature, + IBusMessageIter *sub) +{ + gint dbus_type; + + if (type == IBUS_TYPE_ARRAY) { + dbus_type = DBUS_TYPE_ARRAY; + } + else if (type == IBUS_TYPE_STRUCT) { + dbus_type = DBUS_TYPE_STRUCT; + } + else if (type == IBUS_TYPE_DICT_ENTRY) { + dbus_type = DBUS_TYPE_DICT_ENTRY; + } + else if (type == IBUS_TYPE_VARIANT) { + dbus_type = DBUS_TYPE_VARIANT; + } + else + g_return_val_if_reached (FALSE); + + return dbus_message_iter_open_container (iter, + dbus_type, + contained_signature, + sub); +} + +gboolean +ibus_message_iter_close_container (IBusMessageIter *iter, + IBusMessageIter *sub) +{ + return dbus_message_iter_close_container (iter, sub); +} + + +static GType +dbus_type_to_gtype (gint type) +{ + switch (type) { +#define TYPE_TABLE(a, b) case a: return (b); + TYPE_TABLE (DBUS_TYPE_BYTE, G_TYPE_CHAR); + TYPE_TABLE (DBUS_TYPE_INT32, G_TYPE_INT); + TYPE_TABLE (DBUS_TYPE_INT64, G_TYPE_INT64); + TYPE_TABLE (DBUS_TYPE_UINT32, G_TYPE_UINT); + TYPE_TABLE (DBUS_TYPE_UINT64, G_TYPE_UINT64); + TYPE_TABLE (DBUS_TYPE_BOOLEAN, G_TYPE_BOOLEAN); + TYPE_TABLE (DBUS_TYPE_DOUBLE, G_TYPE_DOUBLE); + TYPE_TABLE (DBUS_TYPE_STRING, G_TYPE_STRING); + TYPE_TABLE (DBUS_TYPE_OBJECT_PATH, IBUS_TYPE_OBJECT_PATH); + TYPE_TABLE (DBUS_TYPE_ARRAY, IBUS_TYPE_ARRAY); + TYPE_TABLE (DBUS_TYPE_STRUCT, IBUS_TYPE_STRUCT); + TYPE_TABLE (DBUS_TYPE_DICT_ENTRY, IBUS_TYPE_DICT_ENTRY); + TYPE_TABLE (DBUS_TYPE_VARIANT, IBUS_TYPE_VARIANT); +#undef TYPE_TABLE + } + return G_TYPE_INVALID; +} + + +gboolean +ibus_message_iter_recurse (IBusMessageIter *iter, + GType type, + IBusMessageIter *sub) +{ + g_assert (iter != NULL); + g_assert (sub != NULL); + g_assert (type == IBUS_TYPE_ARRAY || + type == IBUS_TYPE_STRUCT || + type == IBUS_TYPE_DICT_ENTRY || + type == IBUS_TYPE_VARIANT); + GType gtype; + + gtype = ibus_message_iter_get_arg_type (iter); + + g_return_val_if_fail (gtype == type, FALSE); + + dbus_message_iter_recurse (iter, sub); + + return TRUE; +} + +GType +ibus_message_iter_get_arg_type (IBusMessageIter *iter) +{ + gint type; + + type = dbus_message_iter_get_arg_type (iter); + + return dbus_type_to_gtype (type); +} + + +GType +ibus_message_iter_get_element_type (IBusMessageIter *iter) +{ + gint type; + + type = dbus_message_iter_get_element_type (iter); + + return dbus_type_to_gtype (type); +} + +gchar * +ibus_message_to_string (IBusMessage *message) +{ + g_assert (message != NULL); + + GString *string = g_string_new (""); + + IBusMessageIter iter; + GType type; + gint i = 0; + + g_string_append_printf (string, + "message: %d\n" + "\tdestination = %s\n" + "\tpath = %s\n" + "\tinterface = %s\n" + "\tmember = %s\n", + ibus_message_get_type (message), + ibus_message_get_destination (message), + ibus_message_get_path (message), + ibus_message_get_interface (message), + ibus_message_get_member (message)); + + ibus_message_iter_init (message, &iter); + while ((type = ibus_message_iter_get_arg_type (&iter)) != G_TYPE_INVALID) { + g_string_append_printf (string, "\t\targ%d is %s\n", i++, g_type_name (type)); + ibus_message_iter_next (&iter); + } + + return g_string_free (string, FALSE); +} + diff --git a/src/ibusmessage.h b/src/ibusmessage.h new file mode 100644 index 0000000..36f4066 --- /dev/null +++ b/src/ibusmessage.h @@ -0,0 +1,146 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_MESSAGE_H_ +#define __IBUS_MESSAGE_H_ + +#include <glib.h> +#include <glib-object.h> +#include <dbus/dbus.h> +#include "ibuserror.h" + +#define IBUS_TYPE_OBJECT_PATH (ibus_type_get_object_path ()) +#define IBUS_TYPE_ARRAY (ibus_type_get_array ()) +#define IBUS_TYPE_STRUCT (ibus_type_get_struct ()) +#define IBUS_TYPE_DICT_ENTRY (ibus_type_get_dict_entry ()) +#define IBUS_TYPE_VARIANT (ibus_type_get_variant ()) + +G_BEGIN_DECLS + +typedef DBusMessage IBusMessage; +typedef DBusMessageIter IBusMessageIter; + +GType ibus_type_get_object_path (void); +GType ibus_type_get_array (void); +GType ibus_type_get_struct (void); +GType ibus_type_get_dict_entry (void); +GType ibus_type_get_variant (void); + +IBusMessage *ibus_message_new (gint message_type); +IBusMessage *ibus_message_ref (IBusMessage *message); +void ibus_message_unref (IBusMessage *message); +IBusMessage *ibus_message_new_method_call (const gchar *destination, + const gchar *path, + const gchar *interface, + const gchar *method); +IBusMessage *ibus_message_new_method_return (IBusMessage *reply_to); +IBusMessage *ibus_message_new_error (IBusMessage *reply_to, + const gchar *error_name, + const gchar *error_message); +IBusMessage *ibus_message_new_error_printf (IBusMessage *reply_to, + const gchar *error_name, + const gchar *error_format, + ...); +IBusMessage *ibus_message_new_signal (const gchar *path, + const gchar *interface, + const gchar *method); +gboolean ibus_message_is_method_call (IBusMessage *message, + const gchar *interface, + const gchar *method); +gboolean ibus_message_is_error (IBusMessage *message, + const gchar *error_name); +gboolean ibus_message_is_signal (IBusMessage *message, + const gchar *interface, + const gchar *signal_name); +gboolean ibus_message_set_destination (IBusMessage *message, + const gchar *destination); +gboolean ibus_message_set_sender (IBusMessage *message, + const gchar *sender); +gboolean ibus_message_set_error_name (IBusMessage *message, + const gchar *error_name); +gboolean ibus_message_set_interface (IBusMessage *message, + const gchar *interface); +gboolean ibus_message_set_member (IBusMessage *message, + const gchar *member); +gboolean ibus_message_set_path (IBusMessage *message, + const gchar *path); +void ibus_message_set_no_reply (IBusMessage *message, + gboolean no_reply); +gboolean ibus_message_set_reply_serial (IBusMessage *message, + guint32 reply_serial); +gint ibus_message_get_type (IBusMessage *message); +const gchar *ibus_message_get_destination (IBusMessage *message); +const gchar *ibus_message_get_sender (IBusMessage *message); +const gchar *ibus_message_get_error_name (IBusMessage *message); +const gchar *ibus_message_get_error_message (IBusMessage *message); +const gchar *ibus_message_get_interface (IBusMessage *message); +const gchar *ibus_message_get_member (IBusMessage *message); +const gchar *ibus_message_get_path (IBusMessage *message); +gboolean ibus_message_get_no_reply (IBusMessage *message); +guint32 ibus_message_get_reply_serial (IBusMessage *message); +guint32 ibus_message_get_serial (IBusMessage *message); +gboolean ibus_message_append_args (IBusMessage *message, + GType first_arg_type, + ...); +gboolean ibus_message_append_args_valist(IBusMessage *message, + GType first_arg_type, + va_list va_args); +gboolean ibus_message_get_args (IBusMessage *message, + IBusError **error, + GType first_arg_type, + ...); +gboolean ibus_message_get_args_valist (IBusMessage *message, + IBusError **error, + GType first_arg_type, + va_list va_args); +void ibus_message_iter_init_append (IBusMessage *message, + IBusMessageIter *iter); +gboolean ibus_message_iter_append (IBusMessageIter *iter, + GType type, + gconstpointer value); +gboolean ibus_message_iter_init (IBusMessage *message, + IBusMessageIter *iter); +gboolean ibus_message_iter_peek (IBusMessageIter *iter, + GType type, + gpointer value); +void ibus_message_iter_get_basic (IBusMessageIter *iter, + gpointer value); +gboolean ibus_message_iter_get (IBusMessageIter *iter, + GType type, + gpointer value); +gboolean ibus_message_iter_next (IBusMessageIter *iter); +gboolean ibus_message_iter_has_next (IBusMessageIter *iter); +gboolean ibus_message_iter_open_container + (IBusMessageIter *iter, + GType type, + const gchar *contained_signature, + IBusMessageIter *sub); +gboolean ibus_message_iter_close_container + (IBusMessageIter *iter, + IBusMessageIter *sub); +gboolean ibus_message_iter_recurse (IBusMessageIter *iter, + GType type, + IBusMessageIter *sub); +GType ibus_message_iter_get_arg_type (IBusMessageIter *iter); +GType ibus_message_iter_get_element_type + (IBusMessageIter *iter); +gchar *ibus_message_to_string (IBusMessage *message); + +G_END_DECLS +#endif diff --git a/src/ibusobject.c b/src/ibusobject.c new file mode 100644 index 0000000..2c2c25a --- /dev/null +++ b/src/ibusobject.c @@ -0,0 +1,189 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "ibusobject.h" +#include "ibusinternal.h" + +#define IBUS_OBJECT_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_OBJECT, IBusObjectPrivate)) + +enum { + DESTROY, + LAST_SIGNAL, +}; + +typedef struct _IBusObjectPrivate IBusObjectPrivate; +struct _IBusObjectPrivate { + gpointer pad; +}; + +static guint object_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_object_class_init (IBusObjectClass *klass); +static void ibus_object_init (IBusObject *obj); +static GObject *ibus_object_constructor (GType type, + guint n, + GObjectConstructParam + *args); +static void ibus_object_dispose (IBusObject *obj); +static void ibus_object_finalize (IBusObject *obj); +static void ibus_object_real_destroy (IBusObject *obj); + +static GObjectClass *parent_class = NULL; + + +GType +ibus_object_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusObjectClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_object_class_init, + NULL, /* class finialize */ + NULL, /* class data */ + sizeof (IBusObject), + 0, + (GInstanceInitFunc) ibus_object_init, + }; + + if (type == 0) { + type = g_type_register_static (G_TYPE_OBJECT, + "IBusObject", + &type_info, + G_TYPE_FLAG_ABSTRACT); + } + + return type; +} + +/** + * ibus_object_new: + * + * Creates a new instance of an #IBusObject. + * + * Returns: a new instance of #IBusObject. + */ +IBusObject * +ibus_object_new (void) +{ + return IBUS_OBJECT (g_object_new (IBUS_TYPE_OBJECT, NULL)); +} + +static void +ibus_object_class_init (IBusObjectClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + parent_class = (GObjectClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusObjectPrivate)); + + gobject_class->constructor = ibus_object_constructor; + gobject_class->dispose = (GObjectFinalizeFunc) ibus_object_dispose; + gobject_class->finalize = (GObjectFinalizeFunc) ibus_object_finalize; + + klass->destroy = ibus_object_real_destroy; + + /* install signals */ + object_signals[DESTROY] = + g_signal_new (I_("destroy"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusObjectClass, destroy), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +ibus_object_init (IBusObject *obj) +{ + IBusObjectPrivate *priv; + priv = IBUS_OBJECT_GET_PRIVATE (obj); + + obj->flags = 0; +} + + +static GObject * +ibus_object_constructor (GType type, + guint n, + GObjectConstructParam *args) +{ + GObject *object; + + object = parent_class->constructor (type, n ,args); + + return object; +} + + +static void +ibus_object_dispose (IBusObject *obj) +{ + if (! (IBUS_OBJECT_FLAGS (obj) & IBUS_IN_DESTRUCTION)) { + IBUS_OBJECT_SET_FLAGS (obj, IBUS_IN_DESTRUCTION); + if (! (IBUS_OBJECT_FLAGS (obj) & IBUS_DESTROYED)) { + g_signal_emit (obj, object_signals[DESTROY], 0); + IBUS_OBJECT_SET_FLAGS (obj, IBUS_DESTROYED); + } + IBUS_OBJECT_UNSET_FLAGS (obj, IBUS_IN_DESTRUCTION); + } + + G_OBJECT_CLASS(parent_class)->dispose (G_OBJECT (obj)); +} + +static void +ibus_object_finalize (IBusObject *obj) +{ + G_OBJECT_CLASS(parent_class)->finalize (G_OBJECT (obj)); +} + +static void +ibus_object_real_destroy (IBusObject *obj) +{ + g_signal_handlers_destroy (obj); +} + +/** + * ibus_object_destroy: + * @object: an #IBusObject to destroy. + * + * Emit the "destory" signal notifying all reference holders that they should + * release the #IBusObject. + * + * The memory for the object itself won't be deleted until its reference count + * actually drops to 0; ibus_object_destroy merely asks reference holders to + * release their references. it does not free the object. + */ +void +ibus_object_destroy (IBusObject *obj) +{ + IBusObjectPrivate *priv; + priv = IBUS_OBJECT_GET_PRIVATE (obj); + + if (! (IBUS_OBJECT_FLAGS (obj) & IBUS_IN_DESTRUCTION)) { + g_object_run_dispose (G_OBJECT (obj)); + } +} diff --git a/src/ibusobject.h b/src/ibusobject.h new file mode 100644 index 0000000..2c09882 --- /dev/null +++ b/src/ibusobject.h @@ -0,0 +1,92 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_OBJECT_H_ +#define __IBUS_OBJECT_H_ + +#include <glib-object.h> +#include "ibusmarshalers.h" +#include "ibustypes.h" +#include "ibusdebug.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_OBJECT \ + (ibus_object_get_type ()) +#define IBUS_OBJECT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_OBJECT, IBusObject)) +#define IBUS_OBJECT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_OBJECT, IBusObjectClass)) +#define IBUS_IS_OBJECT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_OBJECT)) +#define IBUS_IS_OBJECT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_OBJECT)) +#define IBUS_OBJECT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_OBJECT, IBusObjectClass)) + +typedef enum { + IBUS_IN_DESTRUCTION = (1 << 0), + IBUS_DESTROYED = (1 << 1), + IBUS_RESERVED_1 = (1 << 2), + IBUS_RESERVED_2 = (1 << 3), +} IBusObjectFlags; + +#define IBUS_OBJECT_FLAGS(obj) (IBUS_OBJECT (obj)->flags) +#define IBUS_OBJECT_SET_FLAGS(obj,flag) G_STMT_START{ (IBUS_OBJECT_FLAGS (obj) |= (flag)); }G_STMT_END +#define IBUS_OBJECT_UNSET_FLAGS(obj,flag) G_STMT_START{ (IBUS_OBJECT_FLAGS (obj) &= ~(flag)); }G_STMT_END + +G_BEGIN_DECLS + +typedef struct _IBusObject IBusObject; +typedef struct _IBusObjectClass IBusObjectClass; +/** + * IBusObject: + * + * All the fields in the <structname>IBusObject</structname> structure are + * prtivate to the #IBusObject and should never be accessed directly. + */ +struct _IBusObject { + GObject parent; + /* instance members */ + guint32 flags; +}; + +typedef void ( *IBusObjectDestroyFunc) (IBusObject *); + +struct _IBusObjectClass { + GObjectClass parent; + + /* signals */ + void (* destroy) (IBusObject *object); + + /*< private >*/ + /* padding */ + gpointer pdummy[7]; +}; + +GType ibus_object_get_type (void); +IBusObject *ibus_object_new (void); +void ibus_object_destroy (IBusObject *object); + +G_END_DECLS +#endif + diff --git a/src/ibusobservedpath.c b/src/ibusobservedpath.c new file mode 100644 index 0000000..4dea00b --- /dev/null +++ b/src/ibusobservedpath.c @@ -0,0 +1,335 @@ +/* vim:set et sts=4: */ +/* ibus - The Input IBus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include <glib/gstdio.h> +#include <stdlib.h> +#include "ibusobservedpath.h" + + +enum { + LAST_SIGNAL, +}; + + +/* IBusObservedPathPriv */ +struct _IBusObservedPathPrivate { + gpointer pad; +}; +typedef struct _IBusObservedPathPrivate IBusObservedPathPrivate; + +#define IBUS_OBSERVED_PATH_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_OBSERVED_PATH, IBusObservedPathPrivate)) + +// static guint _signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_observed_path_class_init (IBusObservedPathClass *klass); +static void ibus_observed_path_init (IBusObservedPath *path); +static void ibus_observed_path_destroy (IBusObservedPath *path); +static gboolean ibus_observed_path_serialize (IBusObservedPath *path, + IBusMessageIter *iter); +static gboolean ibus_observed_path_deserialize (IBusObservedPath *path, + IBusMessageIter *iter); +static gboolean ibus_observed_path_copy (IBusObservedPath *dest, + const IBusObservedPath *src); +static gboolean ibus_observed_path_parse_xml_node (IBusObservedPath *path, + XMLNode *node); + +static IBusSerializableClass *parent_class = NULL; + +GType +ibus_observed_path_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusObservedPathClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_observed_path_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusObservedPath), + 0, + (GInstanceInitFunc) ibus_observed_path_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusObservedPath", + &type_info, + (GTypeFlags)0); + } + + return type; +} + + +static void +ibus_observed_path_class_init (IBusObservedPathClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + // g_type_class_add_private (klass, sizeof (IBusObservedPathPrivate)); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_observed_path_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_observed_path_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_observed_path_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_observed_path_copy; + + g_string_append (serializable_class->signature, "sx"); +} + + +static void +ibus_observed_path_init (IBusObservedPath *path) +{ + path->path = NULL; +} + +static void +ibus_observed_path_destroy (IBusObservedPath *path) +{ + g_free (path->path); + IBUS_OBJECT_CLASS (parent_class)->destroy (IBUS_OBJECT (path)); +} + +static gboolean +ibus_observed_path_serialize (IBusObservedPath *path, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = parent_class->serialize ((IBusSerializable *)path, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &(path->path)); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_LONG, &(path->mtime)); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_observed_path_deserialize (IBusObservedPath *path, + IBusMessageIter *iter) +{ + gboolean retval; + gchar *str; + + retval = parent_class->deserialize ((IBusSerializable *)path, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + path->path = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_LONG, &(path->mtime)); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_observed_path_copy (IBusObservedPath *dest, + const IBusObservedPath *src) +{ + gboolean retval; + + retval = parent_class->copy ((IBusSerializable *)dest, (IBusSerializable *)src); + g_return_val_if_fail (retval, FALSE); + + dest->path = g_strdup (src->path); + dest->mtime = src->mtime; + + return TRUE; +} + +#define g_string_append_indent(string, indent) \ + { \ + gint i; \ + for (i = 0; i < (indent); i++) { \ + g_string_append (string, " "); \ + } \ + } + +void +ibus_observed_path_output (IBusObservedPath *path, + GString *output, + gint indent) +{ + g_assert (IBUS_IS_OBSERVED_PATH (path)); + g_assert (output); + + g_string_append_indent (output, indent); + g_string_append_printf (output, "<path mtime=\"%ld\" >%s</path>\n", + path->mtime, + path->path); +} + +gboolean +ibus_observed_path_check_modification (IBusObservedPath *path) +{ + g_assert (IBUS_IS_OBSERVED_PATH (path)); + struct stat buf; + + if (g_stat (path->path, &buf) != 0) { + buf.st_mtime = 0; + } + + if (path->mtime == buf.st_mtime) + return FALSE; + return TRUE; +} + +static void +ibus_observed_path_fill_stat (IBusObservedPath *path) +{ + g_assert (IBUS_IS_OBSERVED_PATH (path)); + + struct stat buf; + + if (g_stat (path->path, &buf) == 0) { + path->is_exist = 1; + if (S_ISDIR (buf.st_mode)) { + path->is_dir = 1; + } + path->mtime = buf.st_mtime; + } + else { + path->is_dir = 0; + path->is_exist = 0; + path->mtime = 0; + } +} + +GList * +ibus_observed_path_traverse (IBusObservedPath *path) +{ + g_assert (IBUS_IS_OBSERVED_PATH (path)); + + GDir *dir; + const gchar *name; + GList *paths = NULL; + + dir = g_dir_open (path->path, 0, NULL); + + if (dir == NULL) + return NULL; + + while ((name = g_dir_read_name (dir)) != NULL) { + IBusObservedPath *sub; + + sub = g_object_new (IBUS_TYPE_OBSERVED_PATH, NULL); + sub->path = g_build_filename (path->path, name, NULL); + + ibus_observed_path_fill_stat (sub); + paths = g_list_append (paths, sub); + + if (sub->is_exist && sub->is_dir) + paths = g_list_concat (paths, ibus_observed_path_traverse (sub)); + } + g_dir_close (dir); + + return paths; +} + +static gboolean +ibus_observed_path_parse_xml_node (IBusObservedPath *path, + XMLNode *node) +{ + g_assert (IBUS_IS_OBSERVED_PATH (path)); + g_assert (node); + + if (G_UNLIKELY (g_strcmp0 (node->name, "path") != 0)) { + return FALSE; + } + + if (node->text[0] == '~' && node->text[1] != G_DIR_SEPARATOR) { + g_warning ("invalide path \"%s\"", node->text); + return FALSE; + } + + if (node->text[0] == '~') { + const gchar *homedir = g_getenv ("HOME"); + if (homedir == NULL) + homedir = g_get_home_dir (); + path->path = g_build_filename (homedir, node->text + 2, NULL); + } + else { + path->path = g_strdup (node->text); + } + + gchar **attr; + for (attr = node->attributes; attr[0]; attr += 2) { + if (g_strcmp0 (*attr, "mtime") == 0) { + path->mtime = atol (attr[1]); + continue; + } + g_warning ("Unkonwn attribute %s", attr[0]); + } + + return TRUE; +} + +IBusObservedPath * +ibus_observed_path_new_from_xml_node (XMLNode *node, + gboolean fill_stat) +{ + g_assert (node); + + IBusObservedPath *path; + + path = (IBusObservedPath *) g_object_new (IBUS_TYPE_OBSERVED_PATH, NULL); + + if (!ibus_observed_path_parse_xml_node (path, node)) { + g_object_unref (path); + path = NULL; + } + else if (fill_stat) { + ibus_observed_path_fill_stat (path); + } + + return path; +} + +IBusObservedPath * +ibus_observed_path_new (const gchar *path, + gboolean fill_stat) +{ + g_assert (path); + + IBusObservedPath *op; + + op = (IBusObservedPath *) g_object_new (IBUS_TYPE_OBSERVED_PATH, NULL); + op->path = g_strdup (path); + + if (fill_stat) { + ibus_observed_path_fill_stat (op); + } + + return op; +} + diff --git a/src/ibusobservedpath.h b/src/ibusobservedpath.h new file mode 100644 index 0000000..4ebd625 --- /dev/null +++ b/src/ibusobservedpath.h @@ -0,0 +1,79 @@ +/* vim:set et sts=4: */ +/* ibus - The Input IBus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_OBSERVED_PATH_H_ +#define __IBUS_OBSERVED_PATH_H_ + +#include "ibusserializable.h" +#include "ibusxml.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_OBSERVED_PATH \ + (ibus_observed_path_get_type ()) +#define IBUS_OBSERVED_PATH(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_OBSERVED_PATH, IBusObservedPath)) +#define IBUS_OBSERVED_PATH_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_OBSERVED_PATH, IBusObservedPathClass)) +#define IBUS_IS_OBSERVED_PATH(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_OBSERVED_PATH)) +#define IBUS_IS_OBSERVED_PATH_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_OBSERVED_PATH)) +#define IBUS_OBSERVED_PATH_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_OBSERVED_PATH, IBusObservedPathClass)) + +G_BEGIN_DECLS + +typedef struct _IBusObservedPath IBusObservedPath; +typedef struct _IBusObservedPathClass IBusObservedPathClass; + +struct _IBusObservedPath { + IBusSerializable parent; + /* instance members */ + + gchar *path; + glong mtime; + gboolean is_dir; + gboolean is_exist; + +}; + +struct _IBusObservedPathClass { + IBusSerializableClass parent; + + /* class members */ +}; + +GType ibus_observed_path_get_type (void); +IBusObservedPath *ibus_observed_path_new_from_xml_node (XMLNode *node, + gboolean fill_stat); +IBusObservedPath *ibus_observed_path_new (const gchar *path, + gboolean fill_stat); +GList *ibus_observed_path_traverse (IBusObservedPath *path); +gboolean ibus_observed_path_check_modification (IBusObservedPath *path); +void ibus_observed_path_output (IBusObservedPath *path, + GString *output, + gint indent); + +G_END_DECLS +#endif + diff --git a/src/ibuspendingcall.c b/src/ibuspendingcall.c new file mode 100644 index 0000000..2812dbf --- /dev/null +++ b/src/ibuspendingcall.c @@ -0,0 +1,103 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include "ibuspendingcall.h" + +IBusPendingCall* +ibus_pending_call_ref (IBusPendingCall *pending) +{ + return dbus_pending_call_ref (pending); +} + +void +ibus_pending_call_unref (IBusPendingCall *pending) +{ + dbus_pending_call_unref (pending); +} + +gboolean +ibus_pending_call_set_notify (IBusPendingCall *pending, + IBusPendingCallNotifyFunction function, + gpointer user_data, + GDestroyNotify free_user_data) +{ + return dbus_pending_call_set_notify (pending, function, user_data, free_user_data); +} + +void +ibus_pending_call_cancel (IBusPendingCall *pending) +{ + dbus_pending_call_cancel (pending); +} + +gboolean +ibus_pending_call_get_completed (IBusPendingCall *pending) +{ + return dbus_pending_call_get_completed (pending); +} + +IBusMessage* +ibus_pending_call_steal_reply (IBusPendingCall *pending) +{ + return dbus_pending_call_steal_reply (pending); +} + +void +ibus_pending_call_block (IBusPendingCall *pending) +{ + return dbus_pending_call_block (pending); +} + +void +ibus_pending_call_wait (IBusPendingCall *pending) +{ + g_assert (pending); + + while (!ibus_pending_call_get_completed (pending)) { + g_main_context_iteration (NULL, TRUE); + } +} + +gboolean +ibus_pending_call_allocate_data_slot (gint *slot_p) +{ + return dbus_pending_call_allocate_data_slot (slot_p); +} + +void +ibus_pending_call_free_data_slot (gint *slot_p) +{ + dbus_pending_call_free_data_slot (slot_p); +} + +gboolean +ibus_pending_call_set_data (IBusPendingCall *pending, + gint slot, + gpointer data, + GDestroyNotify free_data_func) +{ + return dbus_pending_call_set_data (pending, slot, data, free_data_func); +} + +gpointer +ibus_pending_call_get_data (IBusPendingCall *pending, + gint slot) +{ + return dbus_pending_call_get_data (pending, slot); +} diff --git a/src/ibuspendingcall.h b/src/ibuspendingcall.h new file mode 100644 index 0000000..ff76df6 --- /dev/null +++ b/src/ibuspendingcall.h @@ -0,0 +1,56 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_PENDING_CALL_H_ +#define __IBUS_PENDING_CALL_H_ + +#include <glib.h> +#include <dbus/dbus.h> +#include "ibusmessage.h" + +G_BEGIN_DECLS + +typedef DBusPendingCall IBusPendingCall; +typedef void (* IBusPendingCallNotifyFunction)(IBusPendingCall *pending, gpointer user_data); + + +IBusPendingCall* ibus_pending_call_ref (IBusPendingCall *pending); +void ibus_pending_call_unref (IBusPendingCall *pending); +gboolean ibus_pending_call_set_notify (IBusPendingCall *pending, + IBusPendingCallNotifyFunction function, + gpointer user_data, + GDestroyNotify free_user_data); +void ibus_pending_call_cancel (IBusPendingCall *pending); +gboolean ibus_pending_call_get_completed (IBusPendingCall *pending); +IBusMessage* ibus_pending_call_steal_reply (IBusPendingCall *pending); +void ibus_pending_call_block (IBusPendingCall *pending); +void ibus_pending_call_wait (IBusPendingCall *pending); +gboolean ibus_pending_call_allocate_data_slot + (gint *slot_p); +void ibus_pending_call_free_data_slot + (gint *slot_p); +gboolean ibus_pending_call_set_data (IBusPendingCall *pending, + gint slot, + gpointer data, + GDestroyNotify free_data_func); +gpointer ibus_pending_call_get_data (IBusPendingCall *pending, + gint slot); + +G_END_DECLS +#endif diff --git a/src/ibusproperty.c b/src/ibusproperty.c new file mode 100644 index 0000000..712bf1f --- /dev/null +++ b/src/ibusproperty.c @@ -0,0 +1,531 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include "ibusproperty.h" + +/* functions prototype */ +static void ibus_property_class_init (IBusPropertyClass *klass); +static void ibus_property_init (IBusProperty *prop); +static void ibus_property_destroy (IBusProperty *prop); +static gboolean ibus_property_serialize (IBusProperty *prop, + IBusMessageIter *iter); +static gboolean ibus_property_deserialize (IBusProperty *prop, + IBusMessageIter *iter); +static gboolean ibus_property_copy (IBusProperty *dest, + const IBusProperty *src); + +static void ibus_prop_list_class_init (IBusPropListClass *klass); +static void ibus_prop_list_init (IBusPropList *prop_list); +static void ibus_prop_list_destroy (IBusPropList *prop_list); +static gboolean ibus_prop_list_serialize (IBusPropList *prop_list, + IBusMessageIter *iter); +static gboolean ibus_prop_list_deserialize (IBusPropList *prop_list, + IBusMessageIter *iter); +static gboolean ibus_prop_list_copy (IBusPropList *dest, + const IBusPropList *src); + +static IBusSerializableClass *parent_class = NULL; + +GType +ibus_property_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusPropertyClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_property_class_init, + NULL, /* class finialize */ + NULL, /* class data */ + sizeof (IBusProperty), + 0, + (GInstanceInitFunc) ibus_property_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusProperty", + &type_info, + 0); + } + + return type; +} + +static void +ibus_property_class_init (IBusPropertyClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_property_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_property_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_property_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_property_copy; + + g_string_append (serializable_class->signature, "suvsvbbuv"); +} + +static void +ibus_property_init (IBusProperty *prop) +{ + prop->key = NULL; + prop->type = 0; + prop->label = NULL; + prop->icon = NULL; + prop->tooltip = NULL; + prop->sensitive = FALSE; + prop->visible = FALSE; + prop->state = 0; +} + +static void +ibus_property_destroy (IBusProperty *prop) +{ + g_free (prop->key); + g_free (prop->icon); + + prop->key = NULL; + prop->icon = NULL; + + if (prop->label) { + g_object_unref (prop->label); + prop->label = NULL; + } + + if (prop->tooltip) { + g_object_unref (prop->tooltip); + prop->tooltip = NULL; + } + + IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *)prop); +} + +gboolean +ibus_property_serialize (IBusProperty *prop, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = parent_class->serialize ((IBusSerializable *) prop, iter); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_PROPERTY (prop), FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &prop->key); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_UINT, &prop->type); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, IBUS_TYPE_TEXT, &prop->label); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &prop->icon); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, IBUS_TYPE_TEXT, &prop->tooltip); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_BOOLEAN, &prop->sensitive); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_BOOLEAN, &prop->visible); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_UINT, &prop->state); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, IBUS_TYPE_PROP_LIST, &prop->sub_props); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_property_deserialize (IBusProperty *prop, + IBusMessageIter *iter) +{ + gboolean retval; + gchar *p; + + retval = parent_class->deserialize ((IBusSerializable *) prop, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &p); + g_return_val_if_fail (retval, FALSE); + prop->key = g_strdup (p); + + retval = ibus_message_iter_get (iter, G_TYPE_UINT, &prop->type); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, IBUS_TYPE_TEXT, &prop->label); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &p); + g_return_val_if_fail (retval, FALSE); + prop->icon = g_strdup (p); + + retval = ibus_message_iter_get (iter, IBUS_TYPE_TEXT, &prop->tooltip); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_BOOLEAN, &prop->sensitive); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_BOOLEAN, &prop->visible); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_UINT, &prop->state); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, IBUS_TYPE_PROP_LIST, &prop->sub_props); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_property_copy (IBusProperty *dest, + const IBusProperty *src) +{ + gboolean retval; + + retval = parent_class->copy ((IBusSerializable *) dest, (IBusSerializable *) src); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_PROPERTY (dest), FALSE); + g_return_val_if_fail (IBUS_IS_PROPERTY (src), FALSE); + + dest->key = g_strdup (src->key); + dest->icon = g_strdup (src->icon); + if (src->label) { + dest->label = (IBusText *) ibus_serializable_copy ((IBusSerializable *) src->label); + } + else + dest->label = ibus_text_new_from_static_string (""); + if (src->tooltip) { + dest->tooltip = (IBusText *) ibus_serializable_copy ((IBusSerializable *) src->tooltip); + } + else + dest->tooltip = ibus_text_new_from_static_string (""); + + dest->sensitive = src->sensitive; + dest->visible = src->visible; + dest->type = src->type; + dest->state = src->state; + + dest->sub_props = (IBusPropList *) ibus_serializable_copy ((IBusSerializable *) src->sub_props); + + return TRUE; +} + +IBusProperty * +ibus_property_new (const gchar *key, + IBusPropType type, + IBusText *label, + const gchar *icon, + IBusText *tooltip, + gboolean sensitive, + gboolean visible, + IBusPropState state, + IBusPropList *prop_list) +{ + g_return_val_if_fail (key != NULL, NULL); + g_return_val_if_fail (type >= PROP_TYPE_NORMAL && + type <= PROP_TYPE_SEPARATOR, + NULL); + g_return_val_if_fail (label == NULL || IBUS_IS_TEXT (label), NULL); + g_return_val_if_fail (tooltip == NULL || IBUS_IS_TEXT (tooltip), NULL); + g_return_val_if_fail (state == PROP_STATE_UNCHECKED || + state == PROP_STATE_CHECKED || + state == PROP_STATE_INCONSISTENT, + NULL); + + IBusProperty *prop; + + prop = (IBusProperty *)g_object_new (IBUS_TYPE_PROPERTY, 0); + + prop->key = g_strdup (key); + prop->icon = g_strdup (icon != NULL ? icon : ""); + prop->type = type; + + if (label) + prop->label = (IBusText *) g_object_ref (label); + else + prop->label = ibus_text_new_from_static_string (""); + + if (tooltip) + prop->tooltip = (IBusText *) g_object_ref (tooltip); + else + prop->tooltip = ibus_text_new_from_static_string (""); + + prop->sensitive = sensitive; + prop->visible = visible; + prop->state = state; + + if (prop_list) + prop->sub_props = g_object_ref (prop_list); + else + prop->sub_props = ibus_prop_list_new (); + + return prop; +} + +void +ibus_property_set_label (IBusProperty *prop, + IBusText *label) +{ + g_assert (IBUS_IS_PROPERTY (prop)); + + if (prop->label) { + g_object_unref (prop->label); + } + + if (label == NULL) { + label = ibus_text_new_from_static_string (""); + } + + prop->label = g_object_ref (label); +} + +void +ibus_property_set_visible (IBusProperty *prop, + gboolean visible) +{ + g_assert (IBUS_IS_PROPERTY (prop)); + prop->visible = visible; +} + +void +ibus_property_set_sub_props (IBusProperty *prop, + IBusPropList *prop_list) +{ + g_return_if_fail (IBUS_IS_PROPERTY (prop)); + g_return_if_fail (IBUS_IS_PROP_LIST (prop_list) || prop_list == NULL); + + if (prop->sub_props) { + g_object_unref (prop->sub_props); + } + + if (prop_list) { + g_object_ref (prop_list); + prop->sub_props = prop_list; + } + else + prop->sub_props = ibus_prop_list_new (); +} + +GType +ibus_prop_list_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusPropListClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_prop_list_class_init, + NULL, /* class finialize */ + NULL, /* class data */ + sizeof (IBusProperty), + 0, + (GInstanceInitFunc) ibus_prop_list_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusPropList", + &type_info, + 0); + } + + return type; +} + +static void +ibus_prop_list_class_init (IBusPropListClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_prop_list_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_prop_list_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_prop_list_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_prop_list_copy; + + g_string_append (serializable_class->signature, "av"); +} + +static void +ibus_prop_list_init (IBusPropList *prop_list) +{ + prop_list->properties = g_array_new (TRUE, TRUE, sizeof (IBusProperty *)); +} + +static void +ibus_prop_list_destroy (IBusPropList *prop_list) +{ + IBusProperty **ps, **p; + p = ps = (IBusProperty **) g_array_free (prop_list->properties, FALSE); + + while (*p != NULL) { + g_object_unref (*p); + p ++; + } + g_free (ps); + + IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *) prop_list); +} + +static gboolean +ibus_prop_list_serialize (IBusPropList *prop_list, + IBusMessageIter *iter) +{ + gboolean retval; + IBusMessageIter array_iter; + IBusProperty *prop; + guint i; + + retval = parent_class->serialize ((IBusSerializable *) prop_list, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_open_container (iter, IBUS_TYPE_ARRAY, "v", &array_iter); + g_return_val_if_fail (retval, FALSE); + + i = 0; + + while ((prop = ibus_prop_list_get (prop_list, i)) != NULL) { + retval = ibus_message_iter_append (&array_iter, IBUS_TYPE_PROPERTY, &prop); + g_return_val_if_fail (retval, FALSE); + i ++; + } + + retval = ibus_message_iter_close_container (iter, &array_iter); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +gboolean +ibus_prop_list_deserialize (IBusPropList *prop_list, + IBusMessageIter *iter) +{ + gboolean retval; + IBusMessageIter array_iter; + IBusSerializable *object; + + retval = parent_class->deserialize ((IBusSerializable *) prop_list, iter); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_PROP_LIST (prop_list), FALSE); + + retval = ibus_message_iter_recurse (iter, IBUS_TYPE_ARRAY, &array_iter); + g_return_val_if_fail (retval, FALSE); + + while (ibus_message_iter_get_arg_type (&array_iter) != G_TYPE_INVALID) { + retval = ibus_message_iter_get (&array_iter, IBUS_TYPE_PROPERTY, &object); + g_return_val_if_fail (retval, FALSE); + + ibus_prop_list_append (prop_list, (IBusProperty *)object); + g_object_unref (object); + } + + ibus_message_iter_next (iter); + + return TRUE; +} + + + +static gboolean +ibus_prop_list_copy (IBusPropList *dest, + const IBusPropList *src) +{ + gboolean retval; + IBusProperty *prop; + guint i; + + retval = parent_class->copy ((IBusSerializable *) dest, + (const IBusSerializable *) src); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_PROP_LIST (dest), FALSE); + g_return_val_if_fail (IBUS_IS_PROP_LIST (src), FALSE); + + i = 0; + while ((prop = ibus_prop_list_get ((IBusPropList *)src, i)) != NULL) { + prop = (IBusProperty *) ibus_serializable_copy ((IBusSerializable *) prop); + ibus_prop_list_append (dest, prop); + g_object_unref (prop); + i ++; + } + return TRUE; +} + + +IBusPropList * +ibus_prop_list_new () +{ + IBusPropList *prop_list; + + prop_list = g_object_new (IBUS_TYPE_PROP_LIST, NULL); + + return prop_list; +} + +void +ibus_prop_list_append (IBusPropList *prop_list, + IBusProperty *prop) +{ + g_return_if_fail (IBUS_IS_PROP_LIST (prop_list)); + g_return_if_fail (IBUS_IS_PROPERTY (prop)); + + g_object_ref (prop); + + g_array_append_val (prop_list->properties, prop); +} + +IBusProperty * +ibus_prop_list_get (IBusPropList *prop_list, + guint index) +{ + g_return_val_if_fail (IBUS_IS_PROP_LIST (prop_list), NULL); + + + if (index >= prop_list->properties->len) + return NULL; + + return g_array_index (prop_list->properties, IBusProperty *, index); +} + + + +gboolean +ibus_prop_list_update_property (IBusPropList *prop_list, + IBusProperty *prop) +{ + return FALSE; +} diff --git a/src/ibusproperty.h b/src/ibusproperty.h new file mode 100644 index 0000000..7cd90c9 --- /dev/null +++ b/src/ibusproperty.h @@ -0,0 +1,140 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_PROPERTY_H_ +#define __IBUS_PROPERTY_H_ + +#include "ibusserializable.h" +#include "ibustext.h" + +G_BEGIN_DECLS + +/* + * Type macros. + */ +#define IBUS_TYPE_PROPERTY (ibus_property_get_type ()) +#define IBUS_TYPE_PROP_LIST (ibus_prop_list_get_type ()) + +/* define IBusProperty macros */ +#define IBUS_TYPE_PROPERTY \ + (ibus_property_get_type ()) +#define IBUS_PROPERTY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_PROPERTY, IBusProperty)) +#define IBUS_PROPERTY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_PROPERTY, IBusPropertyClass)) +#define IBUS_IS_PROPERTY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_PROPERTY)) +#define IBUS_IS_PROPERTY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_PROPERTY)) +#define IBUS_PROPERTY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_PROPERTY, IBusPropertyClass)) + +/* define IBusPropList macros */ +#define IBUS_TYPE_PROP_LIST \ + (ibus_prop_list_get_type ()) +#define IBUS_PROP_LIST(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_PROP_LIST, IBusPropList)) +#define IBUS_PROP_LIST_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_PROP_LIST, IBusPropListClass)) +#define IBUS_IS_PROP_LIST(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_PROP_LIST)) +#define IBUS_IS_PROP_LIST_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_PROP_LIST)) +#define IBUS_PROP_LIST_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_PROP_LIST, IBusPropListClass)) + + +typedef enum { + PROP_TYPE_NORMAL = 0, + PROP_TYPE_TOGGLE = 1, + PROP_TYPE_RADIO = 2, + PROP_TYPE_MENU = 3, + PROP_TYPE_SEPARATOR = 4, +} IBusPropType; + +typedef enum { + PROP_STATE_UNCHECKED = 0, + PROP_STATE_CHECKED = 1, + PROP_STATE_INCONSISTENT = 2, +} IBusPropState; + + +typedef struct _IBusProperty IBusProperty; +typedef struct _IBusPropertyClass IBusPropertyClass; +typedef struct _IBusPropList IBusPropList; +typedef struct _IBusPropListClass IBusPropListClass; + +struct _IBusProperty { + IBusSerializable parent; + + gchar *key; + gchar *icon; + IBusText *label; + IBusText *tooltip; + + gboolean sensitive; + gboolean visible; + guint type; + guint state; + + IBusPropList *sub_props; +}; + +struct _IBusPropertyClass { + IBusSerializableClass parent; +}; + +struct _IBusPropList { + IBusSerializable parent; + + GArray *properties; +}; + +struct _IBusPropListClass { + IBusSerializableClass parent; +}; + +GType ibus_property_get_type (); +IBusProperty *ibus_property_new (const gchar *key, + IBusPropType type, + IBusText *label, + const gchar *icon, + IBusText *tooltip, + gboolean sensitive, + gboolean visible, + IBusPropState state, + IBusPropList *prop_list); +void ibus_property_set_label (IBusProperty *prop, + IBusText *label); +void ibus_property_set_visible (IBusProperty *prop, + gboolean visible); +void ibus_property_set_sub_props(IBusProperty *prop, + IBusPropList *prop_list); + +GType ibus_prop_list_get_type (); +IBusPropList *ibus_prop_list_new (); +void ibus_prop_list_append (IBusPropList *prop_list, + IBusProperty *prop); +IBusProperty *ibus_prop_list_get (IBusPropList *prop_list, + guint index); +gboolean ibus_prop_list_update_property + (IBusPropList *prop_list, + IBusProperty *prop); +G_END_DECLS +#endif diff --git a/src/ibusproxy.c b/src/ibusproxy.c new file mode 100644 index 0000000..5ef3b40 --- /dev/null +++ b/src/ibusproxy.c @@ -0,0 +1,638 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <stdarg.h> +#include "ibusmessage.h" +#include "ibusproxy.h" +#include "ibusinternal.h" + +#define IBUS_PROXY_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_PROXY, IBusProxyPrivate)) + +enum { + IBUS_SIGNAL, + LAST_SIGNAL, +}; + +enum { + PROP_0, + PROP_NAME, + PROP_PATH, + PROP_INTERFACE, + PROP_CONNECTION, +}; + + +/* IBusProxyPriv */ +struct _IBusProxyPrivate { + gchar *name; + gchar *path; + gchar *interface; + IBusConnection *connection; +}; +typedef struct _IBusProxyPrivate IBusProxyPrivate; + +static guint proxy_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_proxy_class_init (IBusProxyClass *klass); +static void ibus_proxy_init (IBusProxy *proxy); +static GObject *ibus_proxy_constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params); +static void ibus_proxy_destroy (IBusProxy *proxy); +static void ibus_proxy_set_property(IBusProxy *proxy, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void ibus_proxy_get_property(IBusProxy *proxy, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static gboolean ibus_proxy_ibus_signal (IBusProxy *proxy, + IBusMessage *message); + +static IBusObjectClass *parent_class = NULL; + +GType +ibus_proxy_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusProxyClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_proxy_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusProxy), + 0, + (GInstanceInitFunc) ibus_proxy_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_OBJECT, + "IBusProxy", + &type_info, + (GTypeFlags)0); + } + return type; +} + +IBusProxy * +ibus_proxy_new (const gchar *name, + const gchar *path, + IBusConnection *connection) +{ + g_assert (name != NULL); + g_assert (path != NULL); + g_assert (IBUS_IS_CONNECTION (connection)); + + IBusProxy *proxy; + + proxy = IBUS_PROXY (g_object_new (IBUS_TYPE_PROXY, + "name", name, + "path", path, + "connection", connection, + NULL)); + + return proxy; +} + +static void +ibus_proxy_class_init (IBusProxyClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + + parent_class = (IBusObjectClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusProxyPrivate)); + + gobject_class->constructor = ibus_proxy_constructor; + gobject_class->set_property = (GObjectSetPropertyFunc) ibus_proxy_set_property; + gobject_class->get_property = (GObjectGetPropertyFunc) ibus_proxy_get_property; + + ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_proxy_destroy; + + klass->ibus_signal = ibus_proxy_ibus_signal; + + /* install properties */ + g_object_class_install_property (gobject_class, + PROP_NAME, + g_param_spec_string ("name", + "service name", + "The service name of proxy object", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (gobject_class, + PROP_PATH, + g_param_spec_string ("path", + "object path", + "The path of proxy object", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (gobject_class, + PROP_INTERFACE, + g_param_spec_string ("interface", + "interface", + "The interface of proxy object", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (gobject_class, + PROP_CONNECTION, + g_param_spec_object ("connection", + "object path", + "The path of proxy object", + IBUS_TYPE_CONNECTION, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + /* install signals */ + proxy_signals[IBUS_SIGNAL] = + g_signal_new (I_("ibus-signal"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusProxyClass, ibus_signal), + NULL, NULL, + ibus_marshal_BOOLEAN__POINTER, + G_TYPE_BOOLEAN, + 1, G_TYPE_POINTER); + +} + +static gboolean +_connection_ibus_signal_cb (IBusConnection *connection, + IBusMessage *message, + IBusProxy *proxy) +{ + if (ibus_proxy_handle_signal (proxy, message)) { + g_signal_stop_emission_by_name (connection, "ibus-signal"); + return TRUE; + } + + return FALSE; +} + +static void +_connection_destroy_cb (IBusConnection *connection, + IBusProxy *proxy) +{ + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + g_assert (priv->connection == connection); + + g_object_unref (connection); + priv->connection = NULL; + + ibus_object_destroy ((IBusObject *) proxy); +} + +static GObject * +ibus_proxy_constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *obj; + IBusProxy *proxy; + IBusProxyPrivate *priv; + + obj = G_OBJECT_CLASS (parent_class)->constructor (type, n_construct_params, construct_params); + + proxy = IBUS_PROXY (obj); + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + if (priv->connection != NULL) { + if (priv->name != NULL) { + + IBusError *error; + gchar *rule; + + rule = g_strdup_printf ("type='signal'," + "sender='" DBUS_SERVICE_DBUS "'," + "path='" DBUS_PATH_DBUS "'," + "interface='" DBUS_INTERFACE_DBUS "'," + "member='NameOwnerChanged'," + "arg0='%s'", + priv->name); + + if (!ibus_connection_call (priv->connection, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "AddMatch", + &error, + G_TYPE_STRING, &rule, + G_TYPE_INVALID, + G_TYPE_INVALID)) { + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + } + g_free (rule); + } + g_signal_connect (priv->connection, + "ibus-signal", + (GCallback) _connection_ibus_signal_cb, + proxy); + + g_signal_connect (priv->connection, + "destroy", + (GCallback) _connection_destroy_cb, + proxy); + } + + return obj; +} + +static void +ibus_proxy_init (IBusProxy *proxy) +{ + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + priv->name = NULL; + priv->path = NULL; + priv->interface = NULL; + priv->connection = NULL; +} + +static void +ibus_proxy_destroy (IBusProxy *proxy) +{ + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + if (priv->connection) { + + g_signal_handlers_disconnect_by_func (priv->connection, + (GCallback) _connection_ibus_signal_cb, + proxy); + g_signal_handlers_disconnect_by_func (priv->connection, + (GCallback) _connection_destroy_cb, + proxy); + + if (priv->name != NULL) { + + IBusError *error; + gchar *rule; + + rule = g_strdup_printf ("type='signal'," + "sender='" DBUS_SERVICE_DBUS "'," + "path='" DBUS_PATH_DBUS "'," + "interface='" DBUS_INTERFACE_DBUS "'," + "member='NameOwnerChanged'," + "arg0='%s'", + priv->name); + + if (!ibus_connection_call (priv->connection, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "RemoveMatch", + &error, + G_TYPE_STRING, &rule, + G_TYPE_INVALID, + G_TYPE_INVALID)) { + + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + } + g_free (rule); + } + } + + g_free (priv->name); + g_free (priv->path); + g_free (priv->interface); + + priv->name = NULL; + priv->path = NULL; + priv->interface = NULL; + + if (priv->connection) { + g_object_unref (priv->connection); + priv->connection = NULL; + } + + IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (proxy)); +} + +static void +ibus_proxy_set_property (IBusProxy *proxy, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + switch (prop_id) { + case PROP_NAME: + g_assert (priv->name == NULL); + priv->name = g_strdup (g_value_get_string (value)); + break; + case PROP_PATH: + g_assert (priv->path == NULL); + priv->path = g_strdup (g_value_get_string (value)); + break; + case PROP_INTERFACE: + g_assert (priv->interface == NULL); + priv->interface = g_strdup (g_value_get_string (value)); + break; + case PROP_CONNECTION: + g_assert (priv->connection == NULL); + priv->connection = IBUS_CONNECTION (g_value_get_object (value)); + g_object_ref (priv->connection); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (proxy, prop_id, pspec); + } +} + +static void +ibus_proxy_get_property (IBusProxy *proxy, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_NAME: + g_value_set_string (value, ibus_proxy_get_name (proxy)); + break; + case PROP_PATH: + g_value_set_string (value, ibus_proxy_get_path (proxy)); + break; + case PROP_INTERFACE: + g_value_set_string (value, ibus_proxy_get_interface (proxy)); + break; + case PROP_CONNECTION: + g_value_set_object (value, ibus_proxy_get_connection (proxy)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (proxy, prop_id, pspec); + } +} + + +gboolean +ibus_proxy_handle_signal (IBusProxy *proxy, + DBusMessage *message) +{ + g_assert (IBUS_IS_PROXY (proxy)); + g_assert (message != NULL); + + gboolean retval = FALSE; + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + if (ibus_message_is_signal (message, DBUS_SERVICE_DBUS, "NameOwnerChanged")) { + gchar *name, *old_name, *new_name; + IBusError *error; + + if (!ibus_message_get_args (message, + &error, + G_TYPE_STRING, &name, + G_TYPE_STRING, &old_name, + G_TYPE_STRING, &new_name, + G_TYPE_INVALID)) { + g_warning ("%s :%s", error->name, error->message); + ibus_error_free (error); + } + + if (g_strcmp0 (priv->name, old_name) == 0) { + ibus_object_destroy (IBUS_OBJECT (proxy)); + return FALSE; + } + } + + if (g_strcmp0 (ibus_message_get_path (message), priv->path) == 0) { + g_signal_emit (proxy, proxy_signals[IBUS_SIGNAL], 0, message, &retval); + } + + return retval; +} + +static gboolean +ibus_proxy_ibus_signal (IBusProxy *proxy, + DBusMessage *message) +{ + return FALSE; +} + + +const gchar * +ibus_proxy_get_name (IBusProxy *proxy) +{ + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + return priv->name; +} + +const gchar * +ibus_proxy_get_path (IBusProxy *proxy) +{ + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + return priv->path; +} + +const gchar * +ibus_proxy_get_interface (IBusProxy *proxy) +{ + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + return priv->interface; +} + +IBusConnection * +ibus_proxy_get_connection (IBusProxy *proxy) +{ + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + return priv->connection; +} + +gboolean +ibus_proxy_send (IBusProxy *proxy, + DBusMessage *message) +{ + g_assert (IBUS_IS_PROXY (proxy)); + g_assert (message != NULL); + + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + g_return_val_if_fail (priv->connection, FALSE); + g_return_val_if_fail (ibus_connection_is_connected (priv->connection), FALSE); + + return ibus_connection_send (priv->connection, message); +} + +gboolean +ibus_proxy_call (IBusProxy *proxy, + const gchar *method, + GType first_arg_type, + ...) +{ + g_assert (IBUS_IS_PROXY (proxy)); + g_assert (method != NULL); + + va_list args; + gboolean retval; + DBusMessage *message; + + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + g_return_val_if_fail (priv->connection, FALSE); + g_return_val_if_fail (ibus_connection_is_connected (priv->connection), FALSE); + + message = ibus_message_new_method_call (priv->name, + priv->path, + priv->interface, + method); + va_start (args, first_arg_type); + retval = ibus_message_append_args_valist (message, + first_arg_type, + args); + if (!retval) { + ibus_message_unref (message); + g_return_val_if_reached (FALSE); + } + + va_end (args); + + retval = ibus_connection_send (priv->connection, message); + + ibus_message_unref (message); + + return retval; +} + +gboolean +ibus_proxy_call_with_reply (IBusProxy *proxy, + const gchar *method, + IBusPendingCall **pending, + gint timeout_milliseconds, + IBusError **error, + GType first_arg_type, + ...) +{ + g_assert (IBUS_IS_PROXY (proxy)); + g_assert (pending != NULL); + g_assert (method != NULL); + + va_list args; + gboolean retval; + DBusMessage *message; + + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + if (priv->connection == NULL || !ibus_connection_is_connected (priv->connection)) { + if (error) { + *error = ibus_error_new_from_printf (DBUS_ERROR_DISCONNECTED, + "Connection of %s was disconnected.", + G_OBJECT_TYPE_NAME (proxy)); + } + return FALSE; + } + + message = ibus_message_new_method_call (priv->name, + priv->path, + priv->interface, + method); + va_start (args, first_arg_type); + retval = ibus_message_append_args_valist (message, + first_arg_type, + args); + va_end (args); + + *pending = NULL; + retval = ibus_connection_send_with_reply (priv->connection, + message, + pending, + timeout_milliseconds); + ibus_message_unref (message); + + if (!retval && error != NULL) { + *error = ibus_error_new_from_printf (DBUS_ERROR_NO_MEMORY, ""); + } + + return retval; +} + + +IBusMessage * +ibus_proxy_call_with_reply_and_block (IBusProxy *proxy, + const gchar *method, + gint timeout_milliseconds, + IBusError **error, + GType first_arg_type, + ...) +{ + g_assert (IBUS_IS_PROXY (proxy)); + g_assert (method != NULL); + + va_list args; + gboolean retval; + DBusMessage *message; + DBusMessage *reply_message; + + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + if (priv->connection == NULL || !ibus_connection_is_connected (priv->connection)) { + if (error) { + *error = ibus_error_new_from_printf (DBUS_ERROR_DISCONNECTED, + "Connection of %s was disconnected.", + G_OBJECT_TYPE_NAME (proxy)); + } + return NULL; + } + + message = ibus_message_new_method_call (priv->name, + priv->path, + priv->interface, + method); + va_start (args, first_arg_type); + retval = ibus_message_append_args_valist (message, + first_arg_type, + args); + va_end (args); + + reply_message = ibus_connection_send_with_reply_and_block ( + priv->connection, + message, + timeout_milliseconds, + error); + ibus_message_unref (message); + + return reply_message; +} diff --git a/src/ibusproxy.h b/src/ibusproxy.h new file mode 100644 index 0000000..0cc22d4 --- /dev/null +++ b/src/ibusproxy.h @@ -0,0 +1,107 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_PROXY_H_ +#define __IBUS_PROXY_H_ + +#include <dbus/dbus.h> +#include "ibusobject.h" +#include "ibusconnection.h" +#include "ibusmessage.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_PROXY \ + (ibus_proxy_get_type ()) +#define IBUS_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_PROXY, IBusProxy)) +#define IBUS_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_PROXY, IBusProxyClass)) +#define IBUS_IS_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_PROXY)) +#define IBUS_IS_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_PROXY)) +#define IBUS_PROXY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_PROXY, IBusProxyClass)) + +G_BEGIN_DECLS + +typedef struct _IBusProxy IBusProxy; +typedef struct _IBusProxyClass IBusProxyClass; + +struct _IBusProxy { + IBusObject parent; + /* instance members */ +}; + +struct _IBusProxyClass { + IBusObjectClass parent; + + /* class members */ + gboolean (* ibus_signal) (IBusProxy *proxy, + IBusMessage *message); + /*< private >*/ + /* padding */ + gpointer pdummy[7]; +}; + +GType ibus_proxy_get_type (void); +IBusProxy *ibus_proxy_new (const gchar *name, + const gchar *path, + IBusConnection *connection); +gboolean ibus_proxy_send (IBusProxy *proxy, + IBusMessage *message); +gboolean ibus_proxy_call (IBusProxy *proxy, + const gchar *method, + GType first_agr_type, + ...); +gboolean ibus_proxy_call_with_reply (IBusProxy *proxy, + const gchar *method, + IBusPendingCall **pending, + gint timeout_milliseconds, + IBusError **error, + GType first_arg_type, + ...); +IBusMessage *ibus_proxy_call_with_reply_and_block + (IBusProxy *proxy, + const gchar *method, + gint timeout_milliseconds, + IBusError **error, + GType first_arg_type, + ...); +gboolean ibus_proxy_send_with_reply (IBusProxy *proxy, + IBusMessage *message, + IBusPendingCall **pending, + gint timeout_milliseconds); +IBusMessage *ibus_proxy_send_with_reply_and_block + (IBusProxy *proxy, + IBusMessage *message); +gboolean ibus_proxy_handle_signal (IBusProxy *proxy, + IBusMessage *message); +const gchar *ibus_proxy_get_name (IBusProxy *proxy); +const gchar *ibus_proxy_get_path (IBusProxy *proxy); +const gchar *ibus_proxy_get_interface (IBusProxy *proxy); +IBusConnection *ibus_proxy_get_connection (IBusProxy *proxy); + +G_END_DECLS +#endif + diff --git a/src/ibusserializable.c b/src/ibusserializable.c new file mode 100644 index 0000000..82a49bc --- /dev/null +++ b/src/ibusserializable.c @@ -0,0 +1,578 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "ibusinternal.h" +#include "ibusserializable.h" + +#define IBUS_SERIALIZABLE_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_SERIALIZABLE, IBusSerializablePrivate)) + +enum { + LAST_SIGNAL, +}; + +typedef struct _IBusSerializablePrivate IBusSerializablePrivate; +struct _IBusSerializablePrivate { + GData *attachments; +}; + +// static guint object_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_serializable_base_init (IBusSerializableClass *klass); +static void ibus_serializable_base_fini (IBusSerializableClass *klass); +static void ibus_serializable_class_init (IBusSerializableClass *klass); +static void ibus_serializable_init (IBusSerializable *object); +static void ibus_serializable_destroy (IBusSerializable *object); +static gboolean ibus_serializable_real_serialize (IBusSerializable *object, + IBusMessageIter *iter); +static gboolean ibus_serializable_real_deserialize (IBusSerializable *object, + IBusMessageIter *iter); +static gboolean ibus_serializable_real_copy (IBusSerializable *dest, + const IBusSerializable *src); + +static IBusObjectClass *parent_class = NULL; + + +GType +ibus_serializable_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusSerializableClass), + (GBaseInitFunc) ibus_serializable_base_init, + (GBaseFinalizeFunc) ibus_serializable_base_fini, + (GClassInitFunc) ibus_serializable_class_init, + NULL, /* class finialize */ + NULL, /* class data */ + sizeof (IBusSerializable), + 0, + (GInstanceInitFunc) ibus_serializable_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_OBJECT, + "IBusSerializable", + &type_info, + 0); + } + + return type; +} + +/** + * ibus_serializable_new: + * + * Creates a new instance of an #IBusSerializable. + * + * Returns: a new instance of #IBusSerializable. + */ +IBusSerializable * +ibus_serializable_new (void) +{ + return IBUS_SERIALIZABLE (g_object_new (IBUS_TYPE_SERIALIZABLE, NULL)); +} + +static void +ibus_serializable_base_init (IBusSerializableClass *klass) +{ + /* init signature */ + klass->signature = g_string_new ("a{sv}"); +} + +static void +ibus_serializable_base_fini (IBusSerializableClass *klass) +{ + /* init signature */ + g_string_free (klass->signature, TRUE); + klass->signature = NULL; +} + +static void +ibus_serializable_class_init (IBusSerializableClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + + parent_class = (IBusObjectClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusSerializablePrivate)); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_serializable_destroy; + + klass->serialize = ibus_serializable_real_serialize; + klass->deserialize = ibus_serializable_real_deserialize; + klass->copy = ibus_serializable_real_copy; +} + +static void +ibus_serializable_init (IBusSerializable *object) +{ + IBusSerializablePrivate *priv; + priv = IBUS_SERIALIZABLE_GET_PRIVATE (object); + + priv->attachments = NULL; + g_datalist_init (&priv->attachments); +} + +static void +ibus_serializable_destroy (IBusSerializable *object) +{ + IBusSerializablePrivate *priv; + priv = IBUS_SERIALIZABLE_GET_PRIVATE (object); + + g_datalist_clear (&priv->attachments); + + parent_class->destroy (IBUS_OBJECT (object)); +} + +static GValue * +ibus_g_value_dup (const GValue *value) +{ + GValue *new_value; + + new_value = g_slice_new0 (GValue); + g_value_init (new_value, G_VALUE_TYPE (value)); + g_value_copy (value, new_value); + + return new_value; +} + +static void +ibus_g_value_free (GValue *value) +{ + g_value_unset (value); + g_slice_free (GValue, value); +} + +static gboolean +_g_value_serialize (GValue *value, + IBusMessageIter *iter) +{ + gboolean retval; + GType type; + + type = G_VALUE_TYPE (value); + g_return_val_if_fail (type != G_TYPE_INVALID, FALSE); + + + if (g_type_is_a (type, IBUS_TYPE_SERIALIZABLE)) { + IBusSerializable *object; + object = IBUS_SERIALIZABLE (g_value_get_object (value)); + retval = ibus_message_iter_append (iter, + type, + &object); + g_return_val_if_fail (retval, FALSE); + return TRUE; + } + + typedef const gchar *gstring; + switch (type) { +#define CASE_ENTRY(TYPE, _type, signature) \ + case G_TYPE_##TYPE: \ + { \ + g##_type v; \ + IBusMessageIter variant_iter; \ + \ + retval = ibus_message_iter_open_container (iter, \ + IBUS_TYPE_VARIANT, \ + signature, \ + &variant_iter); \ + g_return_val_if_fail (retval, FALSE); \ + \ + v = g_value_get_##_type (value); \ + retval = ibus_message_iter_append (&variant_iter, \ + G_TYPE_##TYPE, \ + &v); \ + g_return_val_if_fail (retval, FALSE); \ + \ + retval = ibus_message_iter_close_container (iter, &variant_iter); \ + g_return_val_if_fail (retval, FALSE); \ + \ + return TRUE; \ + } + CASE_ENTRY(CHAR, char, "y"); + CASE_ENTRY(BOOLEAN, boolean, "b"); + CASE_ENTRY(INT, int, "i"); + CASE_ENTRY(UINT, uint, "u"); + CASE_ENTRY(INT64, int64, "x"); + CASE_ENTRY(UINT64, uint64, "t"); + CASE_ENTRY(FLOAT, float, "d"); + CASE_ENTRY(DOUBLE, double, "d"); + CASE_ENTRY(STRING, string, "s"); +#undef CASE_ENTRY + } + + g_return_val_if_reached (FALSE); +} + +static GValue * +_g_value_deserialize (IBusMessageIter *iter) +{ + IBusMessageIter variant_iter; + gboolean retval; + GValue *value = NULL; + GType type; + + retval = ibus_message_iter_recurse (iter, IBUS_TYPE_VARIANT, &variant_iter); + g_return_val_if_fail (retval, NULL); + + type = ibus_message_iter_get_arg_type (&variant_iter); + + if (type == IBUS_TYPE_STRUCT) { + IBusSerializable *object; + retval = ibus_message_iter_get (iter, IBUS_TYPE_SERIALIZABLE, &object); + g_return_val_if_fail (retval, NULL); + + value = g_slice_new0 (GValue); + g_value_init (value, G_OBJECT_TYPE (object)); + g_value_take_object (value, object); + return value; + } + + typedef gchar *gstring; + switch (type) { +#define CASE_ENTRY(TYPE, _type) \ + case G_TYPE_##TYPE: \ + { \ + g##_type v; \ + ibus_message_iter_get_basic (&variant_iter, &v); \ + value = g_slice_new0 (GValue); \ + g_value_init (value, G_TYPE_##TYPE); \ + g_value_set_##_type (value, v); \ + ibus_message_iter_next (iter); \ + return value; \ + } + CASE_ENTRY(CHAR, char); + CASE_ENTRY(BOOLEAN, boolean); + CASE_ENTRY(INT, int); + CASE_ENTRY(UINT, uint); + CASE_ENTRY(INT64, int64); + CASE_ENTRY(UINT64, uint64); + CASE_ENTRY(FLOAT, float); + CASE_ENTRY(DOUBLE, double); + CASE_ENTRY(STRING, string); + } + g_return_val_if_reached (NULL); +} + +static void +_serialize_cb (GQuark key, + GValue *value, + IBusMessageIter *iter) +{ + IBusMessageIter dict_entry; + gboolean retval; + const gchar *name; + + retval = ibus_message_iter_open_container (iter, + IBUS_TYPE_DICT_ENTRY, + NULL, + &dict_entry); + g_return_if_fail (retval); + name = g_quark_to_string (key); + retval = ibus_message_iter_append (&dict_entry, + G_TYPE_STRING, + &name); + g_return_if_fail (retval); + + retval = _g_value_serialize (value, &dict_entry); + g_return_if_fail (retval); + + retval = ibus_message_iter_close_container (iter, &dict_entry); + g_return_if_fail (retval); +} + +static gboolean +ibus_serializable_real_serialize (IBusSerializable *object, + IBusMessageIter *iter) +{ + IBusSerializablePrivate *priv; + IBusMessageIter array_iter; + gboolean retval; + + priv = IBUS_SERIALIZABLE_GET_PRIVATE (object); + + retval = ibus_message_iter_open_container (iter, + IBUS_TYPE_ARRAY, + "{sv}", + &array_iter); + g_return_val_if_fail (retval, FALSE); + + g_datalist_foreach (&priv->attachments, + (GDataForeachFunc) _serialize_cb, + &array_iter); + + retval = ibus_message_iter_close_container (iter, &array_iter); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_serializable_real_deserialize (IBusSerializable *object, + IBusMessageIter *iter) +{ + IBusMessageIter array_iter; + gboolean retval; + + retval = ibus_message_iter_recurse (iter, + IBUS_TYPE_ARRAY, + &array_iter); + g_return_val_if_fail (retval, FALSE); + + while (ibus_message_iter_get_arg_type (&array_iter) != G_TYPE_INVALID) { + gchar *name; + GValue *value; + IBusMessageIter dict_entry; + + retval = ibus_message_iter_recurse (&array_iter, + IBUS_TYPE_DICT_ENTRY, + &dict_entry); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (&dict_entry, + G_TYPE_STRING, + &name); + g_return_val_if_fail (retval, FALSE); + + value = _g_value_deserialize (&dict_entry); + g_return_val_if_fail (value != NULL, FALSE); + + ibus_serializable_set_attachment (object, name, value); + + ibus_message_iter_next (&array_iter); + } + + ibus_message_iter_next (iter); + + return TRUE; +} + +static void +_copy_cb (GQuark key, + GValue *value, + GData **datalist) +{ + g_datalist_id_set_data_full (datalist, + key, + ibus_g_value_dup (value), + (GDestroyNotify) ibus_g_value_free); +} + +static gboolean +ibus_serializable_real_copy (IBusSerializable *dest, + const IBusSerializable *src) +{ + IBusSerializablePrivate *src_priv; + IBusSerializablePrivate *dest_priv; + src_priv = IBUS_SERIALIZABLE_GET_PRIVATE (src); + dest_priv = IBUS_SERIALIZABLE_GET_PRIVATE (dest); + + g_datalist_foreach (&src_priv->attachments, + (GDataForeachFunc) _copy_cb, + &dest_priv->attachments); + return TRUE; +} + +gboolean +ibus_serializable_set_qattachment (IBusSerializable *object, + GQuark key, + const GValue *value) +{ + g_return_val_if_fail (IBUS_IS_SERIALIZABLE (object), FALSE); + g_return_val_if_fail (key != 0, FALSE); + g_return_val_if_fail (G_IS_VALUE (value), FALSE); + + IBusSerializablePrivate *priv; + priv = IBUS_SERIALIZABLE_GET_PRIVATE (object); + + GType type = G_VALUE_TYPE (value); + + switch (type) { + case G_TYPE_CHAR: + case G_TYPE_INT: + case G_TYPE_INT64: + case G_TYPE_UINT: + case G_TYPE_UINT64: + case G_TYPE_BOOLEAN: + case G_TYPE_DOUBLE: + case G_TYPE_FLOAT: + case G_TYPE_STRING: + g_datalist_id_set_data_full (&priv->attachments, + key, + ibus_g_value_dup (value), + (GDestroyNotify) ibus_g_value_free); + return TRUE; + } + + if (g_type_is_a (type, IBUS_TYPE_SERIALIZABLE)) { + g_datalist_id_set_data_full (&priv->attachments, + key, + ibus_g_value_dup (value), + (GDestroyNotify) ibus_g_value_free); + return TRUE; + } + + g_warning ("The value of %s is not support serializing", g_type_name (type)); + return FALSE; +} + +const GValue * +ibus_serializable_get_qattachment (IBusSerializable *object, + GQuark key) +{ + + g_return_val_if_fail (IBUS_IS_SERIALIZABLE (object), NULL); + g_return_val_if_fail (key != 0, NULL); + + IBusSerializablePrivate *priv; + priv = IBUS_SERIALIZABLE_GET_PRIVATE (object); + + return (const GValue *) g_datalist_id_get_data (&priv->attachments, key); +} + +void +ibus_serializable_remove_qattachment (IBusSerializable *object, + GQuark key) +{ + + g_return_if_fail (IBUS_IS_SERIALIZABLE (object)); + g_return_if_fail (key != 0); + + IBusSerializablePrivate *priv; + priv = IBUS_SERIALIZABLE_GET_PRIVATE (object); + + g_datalist_id_remove_no_notify (&priv->attachments, key); +} + +IBusSerializable * +ibus_serializable_copy (IBusSerializable *object) +{ + g_return_val_if_fail (IBUS_IS_SERIALIZABLE (object), NULL); + + GType type; + IBusSerializable *new_object; + + type = G_OBJECT_TYPE (object); + + new_object = g_object_new (type, 0); + g_return_val_if_fail (new_object != NULL, NULL); + + if (IBUS_SERIALIZABLE_GET_CLASS (new_object)->copy (new_object, object)) { + return new_object; + } + + g_object_unref (new_object); + g_return_val_if_reached (NULL); +} + +gboolean +ibus_serializable_serialize (IBusSerializable *object, + IBusMessageIter *iter) +{ + g_return_val_if_fail (IBUS_IS_SERIALIZABLE (object), FALSE); + g_return_val_if_fail (iter != NULL, FALSE); + + IBusMessageIter variant_iter; + IBusMessageIter sub_iter; + gboolean retval; + + gchar *signature; + + signature = g_strdup_printf ("(s%s)", IBUS_SERIALIZABLE_GET_CLASS (object)->signature->str); + retval = ibus_message_iter_open_container (iter, + IBUS_TYPE_VARIANT, + signature, + &variant_iter); + g_free (signature); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_open_container (&variant_iter, + IBUS_TYPE_STRUCT, + NULL, + &sub_iter); + g_return_val_if_fail (retval, FALSE); + + const gchar *type_name = g_type_name (G_OBJECT_TYPE (object)); + g_return_val_if_fail (type_name != NULL, FALSE); + + retval = ibus_message_iter_append (&sub_iter, + G_TYPE_STRING, + &type_name); + g_return_val_if_fail (retval, FALSE); + + retval = IBUS_SERIALIZABLE_GET_CLASS (object)->serialize (object, &sub_iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_close_container (&variant_iter, &sub_iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_close_container (iter, &variant_iter); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +IBusSerializable * +ibus_serializable_deserialize (IBusMessageIter *iter) +{ + g_return_val_if_fail (iter != NULL, NULL); + + gboolean retval; + IBusMessageIter variant_iter; + IBusMessageIter sub_iter; + gchar *type_name; + GType type; + IBusSerializable *object; + + type = ibus_message_iter_get_arg_type (iter); + + if (type == IBUS_TYPE_VARIANT) { + retval = ibus_message_iter_recurse (iter, IBUS_TYPE_VARIANT, &variant_iter); + g_return_val_if_fail (retval, NULL); + + retval = ibus_message_iter_recurse (&variant_iter, IBUS_TYPE_STRUCT, &sub_iter); + g_return_val_if_fail (retval, NULL); + } + else if (type == IBUS_TYPE_STRUCT) { + retval = ibus_message_iter_recurse (iter, IBUS_TYPE_STRUCT, &sub_iter); + g_return_val_if_fail (retval, NULL); + } + else + g_return_val_if_reached (NULL); + + retval = ibus_message_iter_get (&sub_iter, G_TYPE_STRING, &type_name); + g_return_val_if_fail (retval, NULL); + + type = g_type_from_name (type_name); + + g_return_val_if_fail (g_type_is_a (type, IBUS_TYPE_SERIALIZABLE), NULL); + + object = g_object_new (type, 0); + + retval = IBUS_SERIALIZABLE_GET_CLASS (object)->deserialize (object, &sub_iter); + if (retval) + return object; + + g_object_unref (object); + g_return_val_if_reached (NULL); +} + diff --git a/src/ibusserializable.h b/src/ibusserializable.h new file mode 100644 index 0000000..a99f123 --- /dev/null +++ b/src/ibusserializable.h @@ -0,0 +1,108 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_SERIALIZABLE_H_ +#define __IBUS_SERIALIZABLE_H_ + +#include "ibusobject.h" +#include "ibusmessage.h" + +/* + * Type macros. + */ + +/* define IBusSerializable macros */ +#define IBUS_TYPE_SERIALIZABLE \ + (ibus_serializable_get_type ()) +#define IBUS_SERIALIZABLE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_SERIALIZABLE, IBusSerializable)) +#define IBUS_SERIALIZABLE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_SERIALIZABLE, IBusSerializableClass)) +#define IBUS_IS_SERIALIZABLE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_SERIALIZABLE)) +#define IBUS_IS_SERIALIZABLE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_SERIALIZABLE)) +#define IBUS_SERIALIZABLE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_SERIALIZABLE, IBusSerializableClass)) + +#define ibus_serializable_set_attachment(o, k, v) \ + ibus_serializable_set_qattachment (o, g_quark_from_string (k), v) +#define ibus_serializable_get_attachment(o, k, v) \ + ibus_serializable_get_qattachment (o, g_quark_from_string (k)) +#define ibus_serializable_remove_attachment(o, k) \ + ibus_serializable_remove_qattachment (o, g_quark_from_string (k)) + +G_BEGIN_DECLS + +typedef struct _IBusSerializable IBusSerializable; +typedef struct _IBusSerializableClass IBusSerializableClass; +/** + * IBusSerializable: + * + * All the fields in the <structname>IBusSerializable</structname> structure are + * prtivate to the #IBusSerializable and should never be accessed directly. + */ +struct _IBusSerializable { + GObject parent; + /* instance members */ + guint32 flags; +}; + +typedef gboolean (* IBusSerializableSerializeFunc) (IBusSerializable *object, + IBusMessageIter *iter); +typedef gboolean (* IBusSerializableDeserializeFunc) (IBusSerializable *object, + IBusMessageIter *iter); +typedef gboolean (* IBusSerializableCopyFunc) (IBusSerializable *dest, + const IBusSerializable *src); +struct _IBusSerializableClass { + IBusObjectClass parent; + + /* signature */ + GString *signature; + + /* virtual table */ + gboolean (* serialize) (IBusSerializable *object, + IBusMessageIter *iter); + gboolean (* deserialize) (IBusSerializable *object, + IBusMessageIter *iter); + gboolean (* copy) (IBusSerializable *dest, + const IBusSerializable *src); + /*< private >*/ + /* padding */ + gpointer pdummy[5]; +}; + +GType ibus_serializable_get_type (void); +IBusSerializable * ibus_serializable_new (void); +gboolean ibus_serializable_set_qattachment (IBusSerializable *object, + GQuark key, + const GValue *value); +const GValue *ibus_serializable_get_qattachment (IBusSerializable *object, + GQuark key); +void ibus_serializable_remove_qattachment + (IBusSerializable *object, + GQuark key); +IBusSerializable *ibus_serializable_copy (IBusSerializable *object); +gboolean ibus_serializable_serialize (IBusSerializable *object, + IBusMessageIter *iter); +IBusSerializable *ibus_serializable_deserialize (IBusMessageIter *iter); + +G_END_DECLS +#endif + diff --git a/src/ibusserver.c b/src/ibusserver.c new file mode 100644 index 0000000..cda80af --- /dev/null +++ b/src/ibusserver.c @@ -0,0 +1,327 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "ibusserver.h" +#include "ibusinternal.h" + +#define IBUS_SERVER_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_SERVER, IBusServerPrivate)) +#define DECLARE_PRIV IBusServerPrivate *priv = IBUS_SERVER_GET_PRIVATE(server) + +enum { + NEW_CONNECTION, + LAST_SIGNAL, +}; + +enum { + PROP_0, + PROP_CONNECTION_TYPE, +}; + +/* IBusServerPriv */ +struct _IBusServerPrivate { + DBusServer *server; + GType connection_type; +}; +typedef struct _IBusServerPrivate IBusServerPrivate; + +static guint server_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_server_class_init (IBusServerClass *klass); +static void ibus_server_init (IBusServer *server); +static void ibus_server_destroy (IBusServer *server); +static void ibus_server_set_property(IBusServer *server, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void ibus_server_get_property(IBusServer *server, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void ibus_server_listen_internal + (IBusServer *server, + const gchar *address); +static void ibus_server_new_connection + (IBusServer *server, + IBusConnection *connection); + +static IBusObjectClass *parent_class = NULL; + +GType +ibus_server_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusServerClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_server_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusServer), + 0, + (GInstanceInitFunc) ibus_server_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_OBJECT, + "IBusServer", + &type_info, + (GTypeFlags)0); + } + + return type; +} + +IBusServer * +ibus_server_new (void) +{ + IBusServer *server; + + server = IBUS_SERVER (g_object_new (IBUS_TYPE_SERVER, NULL)); + return server; +} + +gboolean +ibus_server_listen (IBusServer *server, + const gchar *address) +{ + g_assert (IBUS_IS_SERVER (server)); + g_assert (address != NULL); + ibus_server_listen_internal (server, address); + + return TRUE; +} + +static void +ibus_server_class_init (IBusServerClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + + parent_class = (IBusObjectClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusServerPrivate)); + + gobject_class->set_property = (GObjectSetPropertyFunc) ibus_server_set_property; + gobject_class->get_property = (GObjectGetPropertyFunc) ibus_server_get_property; + + ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_server_destroy; + + klass->new_connection = ibus_server_new_connection; + + /* install properties */ + g_object_class_install_property (gobject_class, + PROP_CONNECTION_TYPE, + g_param_spec_gtype ("connection-type", + "connection type", + "The connection type of server object", + IBUS_TYPE_CONNECTION, + G_PARAM_READWRITE)); + + /* install signals */ + server_signals[NEW_CONNECTION] = + g_signal_new (I_("new-connection"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusServerClass, new_connection), + NULL, NULL, + ibus_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); +} + +static void +ibus_server_init (IBusServer *server) +{ + IBusServerPrivate *priv; + priv = IBUS_SERVER_GET_PRIVATE (server); + priv->server = NULL; + priv->connection_type = IBUS_TYPE_CONNECTION; +} + +static void +ibus_server_destroy (IBusServer *server) +{ + IBusServerPrivate *priv; + priv = IBUS_SERVER_GET_PRIVATE (server); + + if (priv->server) { + dbus_server_unref (priv->server); + priv->server = NULL; + } + + IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (server)); +} + +static void +ibus_server_set_property (IBusServer *server, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + IBusServerPrivate *priv; + priv = IBUS_SERVER_GET_PRIVATE (server); + + switch (prop_id) { + case PROP_CONNECTION_TYPE: + { + GType type; + type = g_value_get_gtype (value); + g_assert (g_type_is_a (type, IBUS_TYPE_CONNECTION)); + priv->connection_type = type; + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (server, prop_id, pspec); + } +} + +static void +ibus_server_get_property (IBusServer *server, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + IBusServerPrivate *priv; + priv = IBUS_SERVER_GET_PRIVATE (server); + + switch (prop_id) { + case PROP_CONNECTION_TYPE: + g_value_set_gtype (value, priv->connection_type); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (server, prop_id, pspec); + } +} + +static void +ibus_server_new_connection (IBusServer *server, + IBusConnection *connection) +{ +} + +static void +_new_connection_cb (DBusServer *dbus_server, + DBusConnection *new_connection, + IBusServer *server) +{ + IBusServerPrivate *priv; + IBusConnection *connection; + + priv = IBUS_SERVER_GET_PRIVATE (server); + connection = IBUS_CONNECTION (g_object_new (priv->connection_type, NULL)); + ibus_connection_set_connection (connection, new_connection, FALSE); + + g_signal_emit (server, server_signals[NEW_CONNECTION], 0, connection); + g_object_unref (connection); +} + +static void +ibus_server_listen_internal (IBusServer *server, + const gchar *address) +{ + g_assert (IBUS_IS_SERVER (server)); + g_assert (address != NULL); + + IBusServerPrivate *priv; + DBusError error; + + priv = IBUS_SERVER_GET_PRIVATE (server); + + g_assert (priv->server == NULL); + + dbus_error_init (&error); + priv->server = dbus_server_listen (address, &error); + + if (priv->server == NULL) { + g_error ("Can not listen on '%s':\n" + " %s:%s", + address, error.name, error.message); + } + + dbus_server_set_new_connection_function (priv->server, + (DBusNewConnectionFunction) _new_connection_cb, + server, NULL); + + dbus_server_set_auth_mechanisms (priv->server, NULL); + + dbus_server_setup (priv->server, NULL); +} + +void ibus_server_disconnect (IBusServer *server) +{ + g_assert (IBUS_IS_SERVER (server)); + + IBusServerPrivate *priv; + priv = IBUS_SERVER_GET_PRIVATE (server); + + g_assert (priv->server != NULL); + dbus_server_disconnect (priv->server); +} + +const gchar *ibus_server_get_address (IBusServer *server) +{ + g_assert (IBUS_IS_SERVER (server)); + + gchar *address, *tmp; + IBusServerPrivate *priv; + priv = IBUS_SERVER_GET_PRIVATE (server); + + g_assert (priv->server != NULL); + + tmp = dbus_server_get_address (priv->server); + address = g_strdup (tmp); + dbus_free (tmp); + return address; +} + +const gchar *ibus_server_get_id (IBusServer *server) +{ + g_assert (IBUS_IS_SERVER (server)); + + gchar *id, *tmp; + IBusServerPrivate *priv; + priv = IBUS_SERVER_GET_PRIVATE (server); + + g_assert (priv->server != NULL); + + tmp = dbus_server_get_id (priv->server); + id = g_strdup (tmp); + dbus_free (tmp); + return id; +} + +gboolean +ibus_server_is_connected (IBusServer *server) +{ + g_assert (IBUS_IS_SERVER (server)); + + IBusServerPrivate *priv; + priv = IBUS_SERVER_GET_PRIVATE (server); + + g_assert (priv->server != NULL); + + return dbus_server_get_is_connected (priv->server); +} + + diff --git a/src/ibusserver.h b/src/ibusserver.h new file mode 100644 index 0000000..cf3547f --- /dev/null +++ b/src/ibusserver.h @@ -0,0 +1,79 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_SERVER_H_ +#define __IBUS_SERVER_H_ + +#include <dbus/dbus.h> +#include "ibusobject.h" +#include "ibusconnection.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_SERVER \ + (ibus_server_get_type ()) +#define IBUS_SERVER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_SERVER, IBusServer)) +#define IBUS_SERVER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_SERVER, IBusServerClass)) +#define IBUS_IS_SERVER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_SERVER)) +#define IBUS_IS_SERVER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_SERVER)) +#define IBUS_SERVER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_SERVER, IBusServerClass)) + +G_BEGIN_DECLS + +typedef struct _IBusServer IBusServer; +typedef struct _IBusServerClass IBusServerClass; + +typedef void (* IBusNewConnectionFunc) (IBusServer *server, IBusConnection *connection); + +struct _IBusServer { + IBusObject parent; + /* instance members */ +}; + +struct _IBusServerClass { + IBusObjectClass parent; + + /* signals */ + void (* new_connection) (IBusServer *server, + IBusConnection *connectin); + /*< private >*/ + /* padding */ + gpointer pdummy[7]; +}; + +GType ibus_server_get_type (void); +IBusServer *ibus_server_new (void); +gboolean ibus_server_listen (IBusServer *server, + const gchar *address); +void ibus_server_disconnect (IBusServer *server); +const gchar *ibus_server_get_address (IBusServer *server); +const gchar *ibus_server_get_id (IBusServer *server); +gboolean ibus_server_is_connected (IBusServer *server); + +G_END_DECLS +#endif + diff --git a/src/ibusservice.c b/src/ibusservice.c new file mode 100644 index 0000000..380e3ee --- /dev/null +++ b/src/ibusservice.c @@ -0,0 +1,406 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "ibusservice.h" +#include "ibusinternal.h" + +#define IBUS_SERVICE_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_SERVICE, IBusServicePrivate)) + +enum { + IBUS_MESSAGE, + IBUS_SIGNAL, + LAST_SIGNAL, +}; + +enum { + PROP_0, + PROP_PATH +}; + +/* IBusServicePriv */ +struct _IBusServicePrivate { + gchar *path; + GList *connections; +}; +typedef struct _IBusServicePrivate IBusServicePrivate; + +static guint service_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_service_class_init (IBusServiceClass *klass); +static void ibus_service_init (IBusService *service); +static void ibus_service_destroy (IBusService *service); +static void ibus_service_set_property (IBusService *service, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void ibus_service_get_property (IBusService *service, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static gboolean ibus_service_ibus_message (IBusService *service, + IBusConnection *connection, + IBusMessage *message); +static gboolean ibus_service_ibus_signal (IBusService *service, + IBusConnection *connection, + IBusMessage *message); + +static IBusObjectClass *parent_class = NULL; + +GType +ibus_service_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusServiceClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_service_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusService), + 0, + (GInstanceInitFunc) ibus_service_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_OBJECT, + "IBusService", + &type_info, + (GTypeFlags) 0); + } + return type; +} + +IBusService * +ibus_service_new (const gchar *path) +{ + GObject *obj; + obj = g_object_new (IBUS_TYPE_SERVICE, + "path", path, + NULL); + return IBUS_SERVICE (obj); +} + +static void +ibus_service_class_init (IBusServiceClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + + parent_class = (IBusObjectClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusServicePrivate)); + + gobject_class->set_property = (GObjectSetPropertyFunc) ibus_service_set_property; + gobject_class->get_property = (GObjectGetPropertyFunc) ibus_service_get_property; + ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_service_destroy; + + klass->ibus_message = ibus_service_ibus_message; + klass->ibus_signal = ibus_service_ibus_signal; + + /* install properties */ + g_object_class_install_property ( + gobject_class, + PROP_PATH, + g_param_spec_string ( + "path", + "object path", + "The path of service object", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY) + ); + + /* Install signals */ + service_signals[IBUS_MESSAGE] = + g_signal_new (I_("ibus-message"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusServiceClass, ibus_message), + NULL, NULL, + ibus_marshal_BOOLEAN__POINTER_POINTER, + G_TYPE_BOOLEAN, + 2, + G_TYPE_POINTER, + G_TYPE_POINTER); + + service_signals[IBUS_SIGNAL] = + g_signal_new (I_("ibus-signal"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusServiceClass, ibus_signal), + NULL, NULL, + ibus_marshal_BOOLEAN__POINTER_POINTER, + G_TYPE_BOOLEAN, + 2, + G_TYPE_POINTER, + G_TYPE_POINTER); + +} + +static void +ibus_service_init (IBusService *service) +{ + IBusServicePrivate *priv; + priv = IBUS_SERVICE_GET_PRIVATE (service); + + priv->path = NULL; + priv->connections = NULL; +} + +static void +ibus_service_destroy (IBusService *service) +{ + IBusServicePrivate *priv; + priv = IBUS_SERVICE_GET_PRIVATE (service); + + ibus_service_remove_from_all_connections (service); + + g_free (priv->path); + priv->path = NULL; + + IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (service)); +} + +static void +ibus_service_set_property (IBusService *service, + guint prop_id, const GValue *value, GParamSpec *pspec) +{ + IBusServicePrivate *priv; + priv = IBUS_SERVICE_GET_PRIVATE (service); + + switch (prop_id) { + case PROP_PATH: + priv->path = g_strdup (g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (service, prop_id, pspec); + } +} + +static void +ibus_service_get_property (IBusService *service, + guint prop_id, GValue *value, GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_PATH: + g_value_set_string (value, ibus_service_get_path (service)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (service, prop_id, pspec); + } +} + +const gchar * +ibus_service_get_path (IBusService *service) +{ + g_assert (IBUS_IS_SERVICE (service)); + + IBusServicePrivate *priv; + priv = IBUS_SERVICE_GET_PRIVATE (service); + + return priv->path; +} + +gboolean +ibus_service_handle_message (IBusService *service, + IBusConnection *connection, + IBusMessage *message) +{ + gboolean retval = FALSE; + g_return_val_if_fail (message != NULL, FALSE); + + g_signal_emit (service, service_signals[IBUS_MESSAGE], 0, connection, message, &retval); + return retval; +} + +static gboolean +ibus_service_ibus_message (IBusService *service, + IBusConnection *connection, + IBusMessage *message) +{ + if (ibus_message_is_method_call (message, "", "Destroy")) { + IBusMessage *reply; + reply = ibus_message_new_method_return (message); + ibus_connection_send (connection, reply); + ibus_message_unref (reply); + return TRUE; + } + return FALSE; +} + +static gboolean +ibus_service_ibus_signal (IBusService *service, + IBusConnection *connection, + IBusMessage *message) +{ + return FALSE; +} + + +gboolean +_service_message_function (IBusConnection *connection, + IBusMessage *message, + IBusService *service) +{ + return ibus_service_handle_message (service, connection, message); +} + +static void +_connection_destroy_cb (IBusConnection *connection, IBusService *service) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (IBUS_IS_SERVICE (service)); + + ibus_service_remove_from_connection (service, connection); +} + +gboolean +ibus_service_add_to_connection (IBusService *service, IBusConnection *connection) +{ + g_assert (IBUS_IS_SERVICE (service)); + g_assert (IBUS_IS_CONNECTION (connection)); + + gboolean retval; + IBusServicePrivate *priv; + priv = IBUS_SERVICE_GET_PRIVATE (service); + + g_return_val_if_fail (priv->path != NULL, FALSE); + g_return_val_if_fail (g_list_find (priv->connections, connection) == NULL, FALSE); + + g_object_ref (connection); + + retval = ibus_connection_register_object_path (connection, priv->path, + (IBusMessageFunc) _service_message_function, service); + if (!retval) { + g_object_unref (connection); + return FALSE; + } + + priv->connections = g_list_append (priv->connections, connection); + g_signal_connect (connection, + "destroy", + (GCallback) _connection_destroy_cb, + service); + + return retval; +} + +GList * +ibus_service_get_connections (IBusService *service) +{ + g_assert (IBUS_IS_SERVICE (service)); + + IBusServicePrivate *priv; + priv = IBUS_SERVICE_GET_PRIVATE (service); + + GList *l; + + l = g_list_copy (priv->connections); + g_list_foreach (l, (GFunc) g_object_ref, NULL); + return l; +} + +gboolean +ibus_service_remove_from_connection (IBusService *service, IBusConnection *connection) +{ + g_return_val_if_fail (IBUS_IS_SERVICE (service), FALSE); + g_return_val_if_fail (IBUS_IS_CONNECTION (connection), FALSE); + + IBusServicePrivate *priv; + priv = IBUS_SERVICE_GET_PRIVATE (service); + + g_assert (priv->path != NULL); + g_assert (g_list_find (priv->connections, connection) != NULL); + + gboolean retval; + retval = ibus_connection_unregister_object_path (connection, priv->path); + + if (!retval) { + return FALSE; + } + + g_signal_handlers_disconnect_by_func (connection, + (GCallback) _connection_destroy_cb, + service); + priv->connections = g_list_remove (priv->connections, connection); + g_object_unref (connection); + + return TRUE; +} + +gboolean +ibus_service_remove_from_all_connections (IBusService *service) +{ + g_return_val_if_fail (IBUS_IS_SERVICE (service), FALSE); + + IBusServicePrivate *priv; + priv = IBUS_SERVICE_GET_PRIVATE (service); + + GList *element = priv->connections; + while (element != NULL) { + IBusConnection *connection = IBUS_CONNECTION (element->data); + + gboolean retval; + retval = ibus_connection_unregister_object_path (connection, priv->path); + + g_signal_handlers_disconnect_by_func (connection, + (GCallback) _connection_destroy_cb, + service); + g_object_unref (connection); + element = element->next; + } + + g_list_free (priv->connections); + priv->connections = NULL; + return TRUE; +} + +gboolean +ibus_service_send_signal (IBusService *service, + const gchar *interface, + const gchar *name, + GType first_arg_type, + ...) +{ + g_assert (IBUS_IS_SERVICE (service)); + g_assert (name != NULL); + + gboolean retval; + va_list args; + GList *p; + + IBusServicePrivate *priv; + priv = IBUS_SERVICE_GET_PRIVATE (service); + + for (p = priv->connections; p != NULL; p = p->next) { + va_start (args, first_arg_type); + retval = ibus_connection_send_signal_valist ((IBusConnection *) p->data, + priv->path, + interface, + name, + first_arg_type, + args); + va_end (args); + } + return retval; +} diff --git a/src/ibusservice.h b/src/ibusservice.h new file mode 100644 index 0000000..9d90a85 --- /dev/null +++ b/src/ibusservice.h @@ -0,0 +1,99 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_SERVICE_H_ +#define __IBUS_SERVICE_H_ + +#include <dbus/dbus.h> +#include "ibusobject.h" +#include "ibusconnection.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_SERVICE \ + (ibus_service_get_type ()) +#define IBUS_SERVICE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_SERVICE, IBusService)) +#define IBUS_SERVICE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_SERVICE, IBusServiceClass)) +#define IBUS_IS_SERVICE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_SERVICE)) +#define IBUS_IS_SERVICE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_SERVICE)) +#define IBUS_SERVICE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_SERVICE, IBusServiceClass)) + +G_BEGIN_DECLS + +typedef struct _IBusService IBusService; +typedef struct _IBusServiceClass IBusServiceClass; + +struct _IBusService { + IBusObject parent; + /* instance members */ +}; + +typedef gboolean (* ServiceIBusMessageFunc) (IBusService *service, + IBusConnection *connection, + IBusMessage *message); +typedef gboolean (* ServiceIBusSignalFunc) (IBusService *service, + IBusConnection *connection, + IBusMessage *message); + +struct _IBusServiceClass { + IBusObjectClass parent; + + /* signals */ + gboolean (* ibus_message) (IBusService *service, + IBusConnection *connection, + IBusMessage *message); + gboolean (* ibus_signal) (IBusService *service, + IBusConnection *connection, + IBusMessage *message); + /*< private >*/ + /* padding */ + gpointer pdummy[6]; +}; + + +GType ibus_service_get_type (void); +IBusService *ibus_service_new (const gchar *path); +const gchar *ibus_service_get_path (IBusService *service); +gboolean ibus_service_handle_message (IBusService *service, + IBusConnection *connection, + IBusMessage *message); +gboolean ibus_service_add_to_connection (IBusService *service, + IBusConnection *connection); +GList *ibus_service_get_connections (IBusService *service); +gboolean ibus_service_remove_from_connection + (IBusService *service, + IBusConnection *connection); +gboolean ibus_service_remove_from_all_connections + (IBusService *service); +gboolean ibus_service_send_signal (IBusService *service, + const gchar *interface, + const gchar *name, + GType first_arg_type, + ...); +G_END_DECLS +#endif + diff --git a/src/ibusshare.c b/src/ibusshare.c new file mode 100644 index 0000000..26a6480 --- /dev/null +++ b/src/ibusshare.c @@ -0,0 +1,164 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <glib-object.h> +#include <unistd.h> +#include <stdlib.h> +#include <pwd.h> +#include "ibusshare.h" + +const gchar * +ibus_get_user_name (void) +{ + static gchar *username = NULL; + if (username == NULL) { + username = g_strdup (getlogin()); + if (username == NULL) + username = g_strdup (g_getenv("SUDO_USER")); + if (username == NULL) { + const gchar *uid = g_getenv ("USERHELPER_UID"); + if (uid != NULL) { + gchar *end; + uid_t id = (uid_t)strtol(uid, &end, 10); + if (uid != end) { + struct passwd *pw = getpwuid (id); + if (pw != NULL) { + username = g_strdup (pw->pw_name); + } + } + } + } + if (username == NULL) + username = g_strdup (g_getenv("USERNAME")); + if (username == NULL) + username = g_strdup (g_getenv("LOGNAME")); + if (username == NULL) + username = g_strdup (g_getenv("USER")); + if (username == NULL) + username = g_strdup (g_getenv("LNAME")); + + } + return username; +} + +const gchar * +ibus_get_socket_path (void) +{ + static gchar *path = NULL; + + if (path == NULL) { + gchar *display; + gchar *hostname = ""; + gchar *displaynumber = "0"; + gchar *screennumber = "0"; + const gchar *username = NULL; + gchar *p; + + display = g_strdup (g_getenv ("DISPLAY")); + if (display == NULL) { + g_warning ("DISPLAY is empty! We use default DISPLAY (:0.0)"); + } + else { + p = display; + hostname = display; + for (; *p != ':' && *p != '\0'; p++); + + if (*p == ':') { + *p = '\0'; + p++; + displaynumber = p; + } + + for (; *p != '.' && *p != '\0'; p++); + + if (*p == '.') { + *p = '\0'; + p++; + screennumber = p; + } + } + + username = ibus_get_user_name (); + + path = g_strdup_printf ( + "/tmp/ibus-%s/ibus-%s-%s.%s", + username, hostname, displaynumber, screennumber); + + g_free (display); + } + return path; + +} + +const gchar * +ibus_get_address (void) +{ + static gchar *address = NULL; + + if (address == NULL) { + address = g_strdup_printf ( + "unix:path=%s", + ibus_get_socket_path ()); + } + return address; +} + +void +ibus_free_strv (gchar **strv) +{ + gchar **p; + + if (strv == NULL) + return; + + for (p = strv; *p != NULL; p++) { + g_free (*p); + } + + g_free (strv); +} + + +void +ibus_init (void) +{ + g_type_init (); +} + +static GMainLoop *main_loop = NULL; + +void +ibus_main (void) +{ + main_loop = g_main_loop_new (NULL, FALSE); + + g_main_loop_run (main_loop); + + g_main_loop_unref (main_loop); + main_loop = NULL; +} + +void +ibus_quit (void) +{ + if (main_loop) { + g_main_loop_quit (main_loop); + } +} diff --git a/src/ibusshare.h b/src/ibusshare.h new file mode 100644 index 0000000..142bd47 --- /dev/null +++ b/src/ibusshare.h @@ -0,0 +1,68 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_SHARE_H_ +#define __IBUS_SHARE_H_ + +#include <glib.h> + +#define IBUS_SERVICE_IBUS "org.freedesktop.IBus" +#define IBUS_SERVICE_PANEL "org.freedesktop.IBus.Panel" +#define IBUS_SERVICE_CONFIG "org.freedesktop.IBus.Config" +#define IBUS_SERVICE_NOTIFICATIONS "org.freedesktop.IBus.Notifications" + +#define IBUS_PATH_IBUS "/org/freedesktop/IBus" +#define IBUS_PATH_FACTORY "/org/freedesktop/IBus/Factory" +#define IBUS_PATH_PANEL "/org/freedesktop/IBus/Panel" +#define IBUS_PATH_CONFIG "/org/freedesktop/IBus/Config" +#define IBUS_PATH_NOTIFICATIONS "/org/freedesktop/IBus/Notifications" +#define IBUS_PATH_INPUT_CONTEXT "/org/freedesktop/IBus/InputContext_%d" + +#define IBUS_INTERFACE_IBUS "org.freedesktop.IBus" +#define IBUS_INTERFACE_INPUT_CONTEXT \ + "org.freedesktop.IBus.InputContext" +#define IBUS_INTERFACE_FACTORY "org.freedesktop.IBus.Factory" +#define IBUS_INTERFACE_ENGINE "org.freedesktop.IBus.Engine" +#define IBUS_INTERFACE_PANEL "org.freedesktop.IBus.Panel" +#define IBUS_INTERFACE_CONFIG "org.freedesktop.IBus.Config" +#define IBUS_INTERFACE_NOTIFICATIONS "org.freedesktop.IBus.Notifications" + +G_BEGIN_DECLS + +const gchar *ibus_get_address (void); +const gchar *ibus_get_user_name (void); +const gchar *ibus_get_socket_path (void); + +const gchar *ibus_keyval_name (guint keyval); +guint ibus_keyval_from_name (const gchar *keyval_name); +void ibus_free_strv (gchar **strv); +const gchar *ibus_key_event_to_string + (guint keyval, + guint modifiers); + +gboolean ibus_key_event_from_string + (const gchar *string, + guint *keyval, + guint *modifiers); +void ibus_init (void); +void ibus_main (void); +void ibus_quit (void); + +G_END_DECLS +#endif diff --git a/src/ibustext.c b/src/ibustext.c new file mode 100644 index 0000000..9b87701 --- /dev/null +++ b/src/ibustext.c @@ -0,0 +1,283 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include "ibustext.h" + +/* functions prototype */ +static void ibus_text_class_init (IBusTextClass *klass); +static void ibus_text_init (IBusText *text); +static void ibus_text_destroy (IBusText *text); +static gboolean ibus_text_serialize (IBusText *text, + IBusMessageIter *iter); +static gboolean ibus_text_deserialize (IBusText *text, + IBusMessageIter *iter); +static gboolean ibus_text_copy (IBusText *dest, + const IBusText *src); + +static IBusSerializableClass *parent_class = NULL; + +GType +ibus_text_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusTextClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_text_class_init, + NULL, /* class finialize */ + NULL, /* class data */ + sizeof (IBusText), + 0, + (GInstanceInitFunc) ibus_text_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusText", + &type_info, + 0); + } + + return type; +} + +static void +ibus_text_class_init (IBusTextClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_text_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_text_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_text_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_text_copy; + + g_string_append (serializable_class->signature, "sv"); +} + +static void +ibus_text_init (IBusText *text) +{ + text->is_static = TRUE; + text->text = ""; + text->attrs = NULL; +} + +static void +ibus_text_destroy (IBusText *text) +{ + if (text->text != NULL && text->is_static == FALSE) { + g_free (text->text); + text->text = NULL; + } + + if (text->attrs) { + g_object_unref (text->attrs); + text->attrs = NULL; + } + + IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *)text); +} + +static gboolean +ibus_text_serialize (IBusText *text, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = parent_class->serialize ((IBusSerializable *)text, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &text->text); + g_return_val_if_fail (retval, FALSE); + + if (text->attrs == NULL) + text->attrs = ibus_attr_list_new (); + + retval = ibus_message_iter_append (iter, IBUS_TYPE_ATTR_LIST, &text->attrs); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_text_deserialize (IBusText *text, + IBusMessageIter *iter) +{ + gboolean retval; + gchar *str; + + retval = parent_class->deserialize ((IBusSerializable *)text, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + + text->is_static = FALSE; + text->text = g_strdup (str); + + if (text->attrs) { + g_object_unref (text->attrs); + text->attrs = NULL; + } + + retval = ibus_message_iter_get (iter, IBUS_TYPE_ATTR_LIST, &text->attrs); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_text_copy (IBusText *dest, + const IBusText *src) +{ + gboolean retval; + + retval = parent_class->copy ((IBusSerializable *)dest, + (IBusSerializable *)src); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_TEXT (dest), FALSE); + g_return_val_if_fail (IBUS_IS_TEXT (src), FALSE); + + dest->text = g_strdup (src->text); + dest->is_static = FALSE; + if (src->attrs) + dest->attrs = (IBusAttrList *)ibus_serializable_copy ((IBusSerializable *)src->attrs); + + return TRUE; +} + +IBusText * +ibus_text_new_from_string (const gchar *str) +{ + g_return_val_if_fail (str != NULL, NULL); + + IBusText *text; + + text= g_object_new (IBUS_TYPE_TEXT, 0); + + text->is_static = FALSE; + text->text = g_strdup (str); + + return text; +} + +IBusText * +ibus_text_new_from_ucs4 (const gunichar *str) +{ + g_return_val_if_fail (str != NULL, NULL); + + IBusText *text; + + text= g_object_new (IBUS_TYPE_TEXT, 0); + + text->is_static = FALSE; + text->text = g_ucs4_to_utf8 (str, -1, NULL, NULL, NULL); + + return text; +} + +IBusText * +ibus_text_new_from_static_string (const gchar *str) +{ + g_return_val_if_fail (str != NULL, NULL); + + IBusText *text; + + text= g_object_new (IBUS_TYPE_TEXT, 0); + + text->is_static = TRUE; + text->text = (gchar *)str; + + return text; +} + +IBusText * +ibus_text_new_from_printf (const gchar *format, + ...) +{ + g_return_val_if_fail (format != NULL, NULL); + + gchar *str; + IBusText *text; + va_list args; + + va_start (args, format); + str = g_strdup_vprintf (format, args); + va_end (args); + + if (str == NULL) + return NULL; + + text= g_object_new (IBUS_TYPE_TEXT, 0); + + text->text = (gchar *)str; + + return text; +} + +IBusText * +ibus_text_new_from_unichar (gunichar c) +{ + IBusText *text; + gint len; + + text= g_object_new (IBUS_TYPE_TEXT, 0); + + text->text = (gchar *)g_malloc (12); + len = g_unichar_to_utf8 (c, text->text); + text->text[len] = 0; + + return text; + +} + +void +ibus_text_append_attribute (IBusText *text, + guint type, + guint value, + guint start_index, + gint end_index) +{ + g_assert (IBUS_IS_TEXT (text)); + + if (end_index < 0) { + end_index += g_utf8_strlen(text->text, -1) + 1; + } + + if (end_index <= 0) + return; + + if (text->attrs == NULL) + text->attrs = ibus_attr_list_new (); + + ibus_attr_list_append (text->attrs, ibus_attribute_new (type, value, start_index, end_index)); +} + +guint +ibus_text_get_length (IBusText *text) +{ + return g_utf8_strlen (text->text, -1); +} diff --git a/src/ibustext.h b/src/ibustext.h new file mode 100644 index 0000000..9696f80 --- /dev/null +++ b/src/ibustext.h @@ -0,0 +1,77 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_TEXT_H_ +#define __IBUS_TEXT_H_ + +#include "ibusserializable.h" +#include "ibusattribute.h" + +/* + * Type macros. + */ +/* define IBusText macros */ +#define IBUS_TYPE_TEXT \ + (ibus_text_get_type ()) +#define IBUS_TEXT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_TEXT, IBusText)) +#define IBUS_TEXT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_TEXT, IBusTextClass)) +#define IBUS_IS_TEXT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_TEXT)) +#define IBUS_IS_TEXT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_TEXT)) +#define IBUS_TEXT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_TEXT, IBusTextClass)) + +G_BEGIN_DECLS + +typedef struct _IBusText IBusText; +typedef struct _IBusTextClass IBusTextClass; + +struct _IBusText { + IBusSerializable parent; + + /* members */ + gboolean is_static; + gchar *text; + IBusAttrList *attrs; +}; + +struct _IBusTextClass { + IBusSerializableClass parent; +}; + +GType ibus_text_get_type (void); +IBusText *ibus_text_new_from_string (const gchar *str); +IBusText *ibus_text_new_from_ucs4 (const gunichar *str); +IBusText *ibus_text_new_from_static_string (const gchar *str); +IBusText *ibus_text_new_from_printf (const gchar *fmt, + ...); +IBusText *ibus_text_new_from_unichar (gunichar c); +void ibus_text_append_attribute (IBusText *text, + guint type, + guint value, + guint start_index, + gint end_index); +guint ibus_text_get_length (IBusText *text); + +G_END_DECLS +#endif + diff --git a/src/ibustypes.h b/src/ibustypes.h new file mode 100644 index 0000000..a977db4 --- /dev/null +++ b/src/ibustypes.h @@ -0,0 +1,74 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_TYPES_H_ +#define __IBUS_TYPES_H_ + +typedef enum +{ + IBUS_SHIFT_MASK = 1 << 0, + IBUS_LOCK_MASK = 1 << 1, + IBUS_CONTROL_MASK = 1 << 2, + IBUS_MOD1_MASK = 1 << 3, + IBUS_MOD2_MASK = 1 << 4, + IBUS_MOD3_MASK = 1 << 5, + IBUS_MOD4_MASK = 1 << 6, + IBUS_MOD5_MASK = 1 << 7, + IBUS_BUTTON1_MASK = 1 << 8, + IBUS_BUTTON2_MASK = 1 << 9, + IBUS_BUTTON3_MASK = 1 << 10, + IBUS_BUTTON4_MASK = 1 << 11, + IBUS_BUTTON5_MASK = 1 << 12, + + /* The next few modifiers are used by XKB, so we skip to the end. + * Bits 15 - 25 are currently unused. Bit 29 is used internally. + */ + + /* forard mask */ + IBUS_FORWARD_MASK = 1 << 25, + + IBUS_SUPER_MASK = 1 << 26, + IBUS_HYPER_MASK = 1 << 27, + IBUS_META_MASK = 1 << 28, + + IBUS_RELEASE_MASK = 1 << 30, + + IBUS_MODIFIER_MASK = 0x5c001fff +} IBusModifierType; + +typedef enum { + IBUS_CAP_PREEDIT_TEXT = 1 << 0, + IBUS_CAP_AUXILIARY_TEXT = 1 << 1, + IBUS_CAP_LOOKUP_TABLE = 1 << 2, + IBUS_CAP_FOCUS = 1 << 3, + IBUS_CAP_PROPERTY = 1 << 4, +} IBusCapabilite; + +typedef struct _IBusRectangle IBusRectangle; +struct _IBusRectangle { + gint x; + gint y; + gint width; + gint height; +}; + +typedef void (* IBusFreeFunc) (gpointer ); + +#endif + diff --git a/src/ibusxml.c b/src/ibusxml.c new file mode 100644 index 0000000..6a1e0bf --- /dev/null +++ b/src/ibusxml.c @@ -0,0 +1,317 @@ +/* vim:set et sts=4: */ +/* bus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include <stdio.h> +#include <string.h> +#include "ibusxml.h" + +static GMarkupParser parser; + +void +ibus_xml_free (XMLNode *node) +{ + g_free (node->name); + + g_free (node->text); + + g_strfreev (node->attributes); + + g_list_foreach (node->sub_nodes, (GFunc) ibus_xml_free, NULL); + g_list_free (node->sub_nodes); + + g_slice_free (XMLNode, node); +} + +static void +_start_root_element_cb (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) +{ + XMLNode **node = (XMLNode **) user_data; + g_assert (node != NULL); + + XMLNode *p = g_slice_new0 (XMLNode); + + + p->name = g_strdup (element_name); + + GArray *attributes = g_array_new (TRUE, TRUE, sizeof (gchar *)); + while (*attribute_names != NULL && *attribute_values != NULL) { + gchar *p; + p = g_strdup (*attribute_names++); + g_array_append_val (attributes, p); + p = g_strdup (*attribute_values++); + g_array_append_val (attributes, p); + } + + p->attributes = (gchar **) g_array_free (attributes, FALSE); + + g_markup_parse_context_push (context, &parser, p); + *node = p; +} + + +static void +_start_element_cb (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) +{ + XMLNode *node = (XMLNode *) user_data; + + if (node->text) { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, " "); + return; + } + + XMLNode *p = g_slice_new0 (XMLNode); + + node->sub_nodes = g_list_append (node->sub_nodes, p); + g_markup_parse_context_push (context, &parser, p); + + p->name = g_strdup (element_name); + + GArray *attributes = g_array_new (TRUE, TRUE, sizeof (gchar *)); + while (*attribute_names != NULL && *attribute_values != NULL) { + gchar *p; + p = g_strdup (*attribute_names++); + g_array_append_val (attributes, p); + p = g_strdup (*attribute_values++); + g_array_append_val (attributes, p); + } + + p->attributes = (gchar **)g_array_free (attributes, FALSE); +} + +static void +_end_element_cb (GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, + GError **error) +{ + XMLNode *p = (XMLNode *) g_markup_parse_context_pop (context); + + if (p->text && p->sub_nodes) { + g_debug ("Error"); + } + + if (p->text == NULL && p->sub_nodes == NULL) { + p->text = g_strdup (""); + } +} + +static gboolean +_is_space (const gchar *text, + gsize text_len) +{ + gsize i = 0; + + for (i = 0; text[i] != '\0' && i < text_len; i++) { + switch (text[i]) { + case '\t': + case ' ': + case '\n': + case '\r': + continue; + default: + return FALSE; + } + } + + return TRUE; +} + +static void +_text_cb (GMarkupParseContext *context, + const gchar *text, + gsize text_len, + gpointer user_data, + GError **error) +{ + XMLNode *p = (XMLNode *)user_data; + + if (_is_space (text, text_len)) { + return; + } + + if (p->sub_nodes || p->text) { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, " "); + return; + } + + p->text = g_strndup (text, text_len); +} + +static GMarkupParser parser = { + _start_element_cb, + _end_element_cb, + _text_cb, + 0, + 0, +}; + +XMLNode * +ibus_xml_parse_file (const gchar *filename) +{ + gboolean retval; + GError *error = NULL; + FILE *pf = fopen (filename, "r"); + + if (pf == NULL) { + return NULL; + } + + GMarkupParseContext *context; + XMLNode *node; + + const static GMarkupParser root_parser = { + _start_root_element_cb, + _end_element_cb, + _text_cb, + 0, + 0, + }; + + context = g_markup_parse_context_new (&root_parser, 0, &node, 0); + + while (!feof (pf)) { + gchar buf[1024]; + gssize len = 0; + + len = fread (buf, 1, sizeof (buf), pf); + retval = g_markup_parse_context_parse (context, buf, len, &error); + + if (!retval) + goto _failed_out; + } + + fclose (pf); + + retval = g_markup_parse_context_end_parse (context, &error); + if (!retval) + goto _failed_out; + + g_markup_parse_context_free (context); + + return node; + +_failed_out: + g_warning ("Parse %s failed: %s", filename, error->message); + g_error_free (error); + g_markup_parse_context_free (context); + return NULL; +} + +XMLNode * +ibus_xml_parse_buffer (const gchar *buffer) +{ + gboolean retval; + GError *error = NULL; + + GMarkupParseContext *context; + XMLNode *node; + + const static GMarkupParser root_parser = { + _start_root_element_cb, + _end_element_cb, + _text_cb, + 0, + 0, + }; + + context = g_markup_parse_context_new (&root_parser, 0, &node, 0); + + retval = g_markup_parse_context_parse (context, buffer, strlen (buffer), &error); + + if (!retval) + goto _failed_out; + + retval = g_markup_parse_context_end_parse (context, &error); + if (!retval) + goto _failed_out; + + g_markup_parse_context_free (context); + + return node; + +_failed_out: + g_warning ("Parse buffer failed: %s", error->message); + g_error_free (error); + g_markup_parse_context_free (context); + return NULL; + +} + + +void ibus_xml_free (XMLNode *node); +static void +output_indent (int level, GString *output) +{ + gint i; + for (i = 0; i < level; i++) { + g_string_append (output, " "); + } +} + +static void +xml_output_indent (const XMLNode *node, int level, GString *output) +{ + gchar **attrs; + + output_indent (level, output); + g_string_append_printf (output, "<%s", node->name); + + attrs = node->attributes; + + while (attrs != NULL && *attrs != NULL) { + g_string_append_printf (output, " %s", *(attrs++)); + g_string_append_printf (output, "=\"%s\"", *(attrs++)); + } + + if (node->sub_nodes != NULL){ + g_string_append (output, ">\n"); + GList *sub_node; + + for (sub_node = node->sub_nodes; sub_node != NULL; sub_node = sub_node->next) { + xml_output_indent (sub_node->data, level + 1, output); + } + output_indent (level, output); + g_string_append_printf (output, "</%s>\n",node->name); + } + else if (node->text != NULL) { + gchar *text = g_markup_escape_text (node->text, -1); + g_string_append_printf (output, ">%s</%s>\n", text, node->name); + g_free (text); + } + else { + g_string_append (output, "/>\n"); + } +} + +void +xml_output (const XMLNode *node, GString *output) +{ + xml_output_indent (node, 0, output); +} + diff --git a/src/ibusxml.h b/src/ibusxml.h new file mode 100644 index 0000000..f6aeb25 --- /dev/null +++ b/src/ibusxml.h @@ -0,0 +1,37 @@ +/* vim:set et sts=4: */ +/* bus - The Input Bus + * Copyright (C) 2008-2009 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __IBUS_XML_H__ +#define __IBUS_XML_H__ + +#include <glib.h> + +typedef struct { + gchar *name; + gchar *text; + gchar **attributes; + GList *sub_nodes; +} XMLNode; + +XMLNode *ibus_xml_parse_file (const gchar *name); +XMLNode *ibus_xml_parse_buffer (const gchar *buffer); +void ibus_xml_free (XMLNode *node); +void ibus_xml_output (const XMLNode *node, + GString *output); +#endif diff --git a/src/keyname-table.h b/src/keyname-table.h new file mode 100644 index 0000000..6c51cc8 --- /dev/null +++ b/src/keyname-table.h @@ -0,0 +1,3978 @@ +/* keyname-table.h: Generated by gen-keyname-table.pl from keynames.txt + * + * Date: Thu Nov 2 17:26:30 2006 + * + * Do not edit. + */ +static const char keynames[] = + "space\0" + "exclam\0" + "quotedbl\0" + "numbersign\0" + "dollar\0" + "percent\0" + "ampersand\0" + "apostrophe\0" + "quoteright\0" + "parenleft\0" + "parenright\0" + "asterisk\0" + "plus\0" + "comma\0" + "minus\0" + "period\0" + "slash\0" + "0\0" + "1\0" + "2\0" + "3\0" + "4\0" + "5\0" + "6\0" + "7\0" + "8\0" + "9\0" + "colon\0" + "semicolon\0" + "less\0" + "equal\0" + "greater\0" + "question\0" + "at\0" + "A\0" + "B\0" + "C\0" + "D\0" + "E\0" + "F\0" + "G\0" + "H\0" + "I\0" + "J\0" + "K\0" + "L\0" + "M\0" + "N\0" + "O\0" + "P\0" + "Q\0" + "R\0" + "S\0" + "T\0" + "U\0" + "V\0" + "W\0" + "X\0" + "Y\0" + "Z\0" + "bracketleft\0" + "backslash\0" + "bracketright\0" + "asciicircum\0" + "underscore\0" + "grave\0" + "quoteleft\0" + "a\0" + "b\0" + "c\0" + "d\0" + "e\0" + "f\0" + "g\0" + "h\0" + "i\0" + "j\0" + "k\0" + "l\0" + "m\0" + "n\0" + "o\0" + "p\0" + "q\0" + "r\0" + "s\0" + "t\0" + "u\0" + "v\0" + "w\0" + "x\0" + "y\0" + "z\0" + "braceleft\0" + "bar\0" + "braceright\0" + "asciitilde\0" + "nobreakspace\0" + "exclamdown\0" + "cent\0" + "sterling\0" + "currency\0" + "yen\0" + "brokenbar\0" + "section\0" + "diaeresis\0" + "copyright\0" + "ordfeminine\0" + "guillemotleft\0" + "notsign\0" + "hyphen\0" + "registered\0" + "macron\0" + "degree\0" + "plusminus\0" + "twosuperior\0" + "threesuperior\0" + "acute\0" + "mu\0" + "paragraph\0" + "periodcentered\0" + "cedilla\0" + "onesuperior\0" + "masculine\0" + "guillemotright\0" + "onequarter\0" + "onehalf\0" + "threequarters\0" + "questiondown\0" + "Agrave\0" + "Aacute\0" + "Acircumflex\0" + "Atilde\0" + "Adiaeresis\0" + "Aring\0" + "AE\0" + "Ccedilla\0" + "Egrave\0" + "Eacute\0" + "Ecircumflex\0" + "Ediaeresis\0" + "Igrave\0" + "Iacute\0" + "Icircumflex\0" + "Idiaeresis\0" + "ETH\0" + "Eth\0" + "Ntilde\0" + "Ograve\0" + "Oacute\0" + "Ocircumflex\0" + "Otilde\0" + "Odiaeresis\0" + "multiply\0" + "Ooblique\0" + "Ugrave\0" + "Uacute\0" + "Ucircumflex\0" + "Udiaeresis\0" + "Yacute\0" + "THORN\0" + "Thorn\0" + "ssharp\0" + "agrave\0" + "aacute\0" + "acircumflex\0" + "atilde\0" + "adiaeresis\0" + "aring\0" + "ae\0" + "ccedilla\0" + "egrave\0" + "eacute\0" + "ecircumflex\0" + "ediaeresis\0" + "igrave\0" + "iacute\0" + "icircumflex\0" + "idiaeresis\0" + "eth\0" + "ntilde\0" + "ograve\0" + "oacute\0" + "ocircumflex\0" + "otilde\0" + "odiaeresis\0" + "division\0" + "oslash\0" + "ugrave\0" + "uacute\0" + "ucircumflex\0" + "udiaeresis\0" + "yacute\0" + "thorn\0" + "ydiaeresis\0" + "Aogonek\0" + "breve\0" + "Lstroke\0" + "Lcaron\0" + "Sacute\0" + "Scaron\0" + "Scedilla\0" + "Tcaron\0" + "Zacute\0" + "Zcaron\0" + "Zabovedot\0" + "aogonek\0" + "ogonek\0" + "lstroke\0" + "lcaron\0" + "sacute\0" + "caron\0" + "scaron\0" + "scedilla\0" + "tcaron\0" + "zacute\0" + "doubleacute\0" + "zcaron\0" + "zabovedot\0" + "Racute\0" + "Abreve\0" + "Lacute\0" + "Cacute\0" + "Ccaron\0" + "Eogonek\0" + "Ecaron\0" + "Dcaron\0" + "Dstroke\0" + "Nacute\0" + "Ncaron\0" + "Odoubleacute\0" + "Rcaron\0" + "Uring\0" + "Udoubleacute\0" + "Tcedilla\0" + "racute\0" + "abreve\0" + "lacute\0" + "cacute\0" + "ccaron\0" + "eogonek\0" + "ecaron\0" + "dcaron\0" + "dstroke\0" + "nacute\0" + "ncaron\0" + "odoubleacute\0" + "rcaron\0" + "uring\0" + "udoubleacute\0" + "tcedilla\0" + "abovedot\0" + "Hstroke\0" + "Hcircumflex\0" + "Iabovedot\0" + "Gbreve\0" + "Jcircumflex\0" + "hstroke\0" + "hcircumflex\0" + "idotless\0" + "gbreve\0" + "jcircumflex\0" + "Cabovedot\0" + "Ccircumflex\0" + "Gabovedot\0" + "Gcircumflex\0" + "Ubreve\0" + "Scircumflex\0" + "cabovedot\0" + "ccircumflex\0" + "gabovedot\0" + "gcircumflex\0" + "ubreve\0" + "scircumflex\0" + "kappa\0" + "kra\0" + "Rcedilla\0" + "Itilde\0" + "Lcedilla\0" + "Emacron\0" + "Gcedilla\0" + "Tslash\0" + "rcedilla\0" + "itilde\0" + "lcedilla\0" + "emacron\0" + "gcedilla\0" + "tslash\0" + "ENG\0" + "eng\0" + "Amacron\0" + "Iogonek\0" + "Eabovedot\0" + "Imacron\0" + "Ncedilla\0" + "Omacron\0" + "Kcedilla\0" + "Uogonek\0" + "Utilde\0" + "Umacron\0" + "amacron\0" + "iogonek\0" + "eabovedot\0" + "imacron\0" + "ncedilla\0" + "omacron\0" + "kcedilla\0" + "uogonek\0" + "utilde\0" + "umacron\0" + "overline\0" + "kana_fullstop\0" + "kana_openingbracket\0" + "kana_closingbracket\0" + "kana_comma\0" + "kana_conjunctive\0" + "kana_middledot\0" + "kana_WO\0" + "kana_a\0" + "kana_i\0" + "kana_u\0" + "kana_e\0" + "kana_o\0" + "kana_ya\0" + "kana_yu\0" + "kana_yo\0" + "kana_tsu\0" + "kana_tu\0" + "prolongedsound\0" + "kana_A\0" + "kana_I\0" + "kana_U\0" + "kana_E\0" + "kana_O\0" + "kana_KA\0" + "kana_KI\0" + "kana_KU\0" + "kana_KE\0" + "kana_KO\0" + "kana_SA\0" + "kana_SHI\0" + "kana_SU\0" + "kana_SE\0" + "kana_SO\0" + "kana_TA\0" + "kana_CHI\0" + "kana_TI\0" + "kana_TSU\0" + "kana_TU\0" + "kana_TE\0" + "kana_TO\0" + "kana_NA\0" + "kana_NI\0" + "kana_NU\0" + "kana_NE\0" + "kana_NO\0" + "kana_HA\0" + "kana_HI\0" + "kana_FU\0" + "kana_HU\0" + "kana_HE\0" + "kana_HO\0" + "kana_MA\0" + "kana_MI\0" + "kana_MU\0" + "kana_ME\0" + "kana_MO\0" + "kana_YA\0" + "kana_YU\0" + "kana_YO\0" + "kana_RA\0" + "kana_RI\0" + "kana_RU\0" + "kana_RE\0" + "kana_RO\0" + "kana_WA\0" + "kana_N\0" + "voicedsound\0" + "semivoicedsound\0" + "Arabic_comma\0" + "Arabic_semicolon\0" + "Arabic_question_mark\0" + "Arabic_hamza\0" + "Arabic_maddaonalef\0" + "Arabic_hamzaonalef\0" + "Arabic_hamzaonwaw\0" + "Arabic_hamzaunderalef\0" + "Arabic_hamzaonyeh\0" + "Arabic_alef\0" + "Arabic_beh\0" + "Arabic_tehmarbuta\0" + "Arabic_teh\0" + "Arabic_theh\0" + "Arabic_jeem\0" + "Arabic_hah\0" + "Arabic_khah\0" + "Arabic_dal\0" + "Arabic_thal\0" + "Arabic_ra\0" + "Arabic_zain\0" + "Arabic_seen\0" + "Arabic_sheen\0" + "Arabic_sad\0" + "Arabic_dad\0" + "Arabic_tah\0" + "Arabic_zah\0" + "Arabic_ain\0" + "Arabic_ghain\0" + "Arabic_tatweel\0" + "Arabic_feh\0" + "Arabic_qaf\0" + "Arabic_kaf\0" + "Arabic_lam\0" + "Arabic_meem\0" + "Arabic_noon\0" + "Arabic_ha\0" + "Arabic_heh\0" + "Arabic_waw\0" + "Arabic_alefmaksura\0" + "Arabic_yeh\0" + "Arabic_fathatan\0" + "Arabic_dammatan\0" + "Arabic_kasratan\0" + "Arabic_fatha\0" + "Arabic_damma\0" + "Arabic_kasra\0" + "Arabic_shadda\0" + "Arabic_sukun\0" + "Serbian_dje\0" + "Macedonia_gje\0" + "Cyrillic_io\0" + "Ukrainian_ie\0" + "Ukranian_je\0" + "Macedonia_dse\0" + "Ukrainian_i\0" + "Ukranian_i\0" + "Ukrainian_yi\0" + "Ukranian_yi\0" + "Cyrillic_je\0" + "Serbian_je\0" + "Cyrillic_lje\0" + "Serbian_lje\0" + "Cyrillic_nje\0" + "Serbian_nje\0" + "Serbian_tshe\0" + "Macedonia_kje\0" + "Byelorussian_shortu\0" + "Cyrillic_dzhe\0" + "Serbian_dze\0" + "numerosign\0" + "Serbian_DJE\0" + "Macedonia_GJE\0" + "Cyrillic_IO\0" + "Ukrainian_IE\0" + "Ukranian_JE\0" + "Macedonia_DSE\0" + "Ukrainian_I\0" + "Ukranian_I\0" + "Ukrainian_YI\0" + "Ukranian_YI\0" + "Cyrillic_JE\0" + "Serbian_JE\0" + "Cyrillic_LJE\0" + "Serbian_LJE\0" + "Cyrillic_NJE\0" + "Serbian_NJE\0" + "Serbian_TSHE\0" + "Macedonia_KJE\0" + "Byelorussian_SHORTU\0" + "Cyrillic_DZHE\0" + "Serbian_DZE\0" + "Cyrillic_yu\0" + "Cyrillic_a\0" + "Cyrillic_be\0" + "Cyrillic_tse\0" + "Cyrillic_de\0" + "Cyrillic_ie\0" + "Cyrillic_ef\0" + "Cyrillic_ghe\0" + "Cyrillic_ha\0" + "Cyrillic_i\0" + "Cyrillic_shorti\0" + "Cyrillic_ka\0" + "Cyrillic_el\0" + "Cyrillic_em\0" + "Cyrillic_en\0" + "Cyrillic_o\0" + "Cyrillic_pe\0" + "Cyrillic_ya\0" + "Cyrillic_er\0" + "Cyrillic_es\0" + "Cyrillic_te\0" + "Cyrillic_u\0" + "Cyrillic_zhe\0" + "Cyrillic_ve\0" + "Cyrillic_softsign\0" + "Cyrillic_yeru\0" + "Cyrillic_ze\0" + "Cyrillic_sha\0" + "Cyrillic_e\0" + "Cyrillic_shcha\0" + "Cyrillic_che\0" + "Cyrillic_hardsign\0" + "Cyrillic_YU\0" + "Cyrillic_A\0" + "Cyrillic_BE\0" + "Cyrillic_TSE\0" + "Cyrillic_DE\0" + "Cyrillic_IE\0" + "Cyrillic_EF\0" + "Cyrillic_GHE\0" + "Cyrillic_HA\0" + "Cyrillic_I\0" + "Cyrillic_SHORTI\0" + "Cyrillic_KA\0" + "Cyrillic_EL\0" + "Cyrillic_EM\0" + "Cyrillic_EN\0" + "Cyrillic_O\0" + "Cyrillic_PE\0" + "Cyrillic_YA\0" + "Cyrillic_ER\0" + "Cyrillic_ES\0" + "Cyrillic_TE\0" + "Cyrillic_U\0" + "Cyrillic_ZHE\0" + "Cyrillic_VE\0" + "Cyrillic_SOFTSIGN\0" + "Cyrillic_YERU\0" + "Cyrillic_ZE\0" + "Cyrillic_SHA\0" + "Cyrillic_E\0" + "Cyrillic_SHCHA\0" + "Cyrillic_CHE\0" + "Cyrillic_HARDSIGN\0" + "Greek_ALPHAaccent\0" + "Greek_EPSILONaccent\0" + "Greek_ETAaccent\0" + "Greek_IOTAaccent\0" + "Greek_IOTAdieresis\0" + "Greek_IOTAdiaeresis\0" + "Greek_OMICRONaccent\0" + "Greek_UPSILONaccent\0" + "Greek_UPSILONdieresis\0" + "Greek_OMEGAaccent\0" + "Greek_accentdieresis\0" + "Greek_horizbar\0" + "Greek_alphaaccent\0" + "Greek_epsilonaccent\0" + "Greek_etaaccent\0" + "Greek_iotaaccent\0" + "Greek_iotadieresis\0" + "Greek_iotaaccentdieresis\0" + "Greek_omicronaccent\0" + "Greek_upsilonaccent\0" + "Greek_upsilondieresis\0" + "Greek_upsilonaccentdieresis\0" + "Greek_omegaaccent\0" + "Greek_ALPHA\0" + "Greek_BETA\0" + "Greek_GAMMA\0" + "Greek_DELTA\0" + "Greek_EPSILON\0" + "Greek_ZETA\0" + "Greek_ETA\0" + "Greek_THETA\0" + "Greek_IOTA\0" + "Greek_KAPPA\0" + "Greek_LAMBDA\0" + "Greek_LAMDA\0" + "Greek_MU\0" + "Greek_NU\0" + "Greek_XI\0" + "Greek_OMICRON\0" + "Greek_PI\0" + "Greek_RHO\0" + "Greek_SIGMA\0" + "Greek_TAU\0" + "Greek_UPSILON\0" + "Greek_PHI\0" + "Greek_CHI\0" + "Greek_PSI\0" + "Greek_OMEGA\0" + "Greek_alpha\0" + "Greek_beta\0" + "Greek_gamma\0" + "Greek_delta\0" + "Greek_epsilon\0" + "Greek_zeta\0" + "Greek_eta\0" + "Greek_theta\0" + "Greek_iota\0" + "Greek_kappa\0" + "Greek_lambda\0" + "Greek_lamda\0" + "Greek_mu\0" + "Greek_nu\0" + "Greek_xi\0" + "Greek_omicron\0" + "Greek_pi\0" + "Greek_rho\0" + "Greek_sigma\0" + "Greek_finalsmallsigma\0" + "Greek_tau\0" + "Greek_upsilon\0" + "Greek_phi\0" + "Greek_chi\0" + "Greek_psi\0" + "Greek_omega\0" + "leftradical\0" + "topleftradical\0" + "horizconnector\0" + "topintegral\0" + "botintegral\0" + "vertconnector\0" + "topleftsqbracket\0" + "botleftsqbracket\0" + "toprightsqbracket\0" + "botrightsqbracket\0" + "topleftparens\0" + "botleftparens\0" + "toprightparens\0" + "botrightparens\0" + "leftmiddlecurlybrace\0" + "rightmiddlecurlybrace\0" + "topleftsummation\0" + "botleftsummation\0" + "topvertsummationconnector\0" + "botvertsummationconnector\0" + "toprightsummation\0" + "botrightsummation\0" + "rightmiddlesummation\0" + "lessthanequal\0" + "notequal\0" + "greaterthanequal\0" + "integral\0" + "therefore\0" + "variation\0" + "infinity\0" + "nabla\0" + "approximate\0" + "similarequal\0" + "ifonlyif\0" + "implies\0" + "identical\0" + "radical\0" + "includedin\0" + "includes\0" + "intersection\0" + "union\0" + "logicaland\0" + "logicalor\0" + "partialderivative\0" + "function\0" + "leftarrow\0" + "uparrow\0" + "rightarrow\0" + "downarrow\0" + "blank\0" + "soliddiamond\0" + "checkerboard\0" + "ht\0" + "ff\0" + "cr\0" + "lf\0" + "nl\0" + "vt\0" + "lowrightcorner\0" + "uprightcorner\0" + "upleftcorner\0" + "lowleftcorner\0" + "crossinglines\0" + "horizlinescan1\0" + "horizlinescan3\0" + "horizlinescan5\0" + "horizlinescan7\0" + "horizlinescan9\0" + "leftt\0" + "rightt\0" + "bott\0" + "topt\0" + "vertbar\0" + "emspace\0" + "enspace\0" + "em3space\0" + "em4space\0" + "digitspace\0" + "punctspace\0" + "thinspace\0" + "hairspace\0" + "emdash\0" + "endash\0" + "signifblank\0" + "ellipsis\0" + "doubbaselinedot\0" + "onethird\0" + "twothirds\0" + "onefifth\0" + "twofifths\0" + "threefifths\0" + "fourfifths\0" + "onesixth\0" + "fivesixths\0" + "careof\0" + "figdash\0" + "leftanglebracket\0" + "decimalpoint\0" + "rightanglebracket\0" + "marker\0" + "oneeighth\0" + "threeeighths\0" + "fiveeighths\0" + "seveneighths\0" + "trademark\0" + "signaturemark\0" + "trademarkincircle\0" + "leftopentriangle\0" + "rightopentriangle\0" + "emopencircle\0" + "emopenrectangle\0" + "leftsinglequotemark\0" + "rightsinglequotemark\0" + "leftdoublequotemark\0" + "rightdoublequotemark\0" + "prescription\0" + "minutes\0" + "seconds\0" + "latincross\0" + "hexagram\0" + "filledrectbullet\0" + "filledlefttribullet\0" + "filledrighttribullet\0" + "emfilledcircle\0" + "emfilledrect\0" + "enopencircbullet\0" + "enopensquarebullet\0" + "openrectbullet\0" + "opentribulletup\0" + "opentribulletdown\0" + "openstar\0" + "enfilledcircbullet\0" + "enfilledsqbullet\0" + "filledtribulletup\0" + "filledtribulletdown\0" + "leftpointer\0" + "rightpointer\0" + "club\0" + "diamond\0" + "heart\0" + "maltesecross\0" + "dagger\0" + "doubledagger\0" + "checkmark\0" + "ballotcross\0" + "musicalsharp\0" + "musicalflat\0" + "malesymbol\0" + "femalesymbol\0" + "telephone\0" + "telephonerecorder\0" + "phonographcopyright\0" + "caret\0" + "singlelowquotemark\0" + "doublelowquotemark\0" + "cursor\0" + "leftcaret\0" + "rightcaret\0" + "downcaret\0" + "upcaret\0" + "overbar\0" + "downtack\0" + "upshoe\0" + "downstile\0" + "underbar\0" + "jot\0" + "quad\0" + "uptack\0" + "circle\0" + "upstile\0" + "downshoe\0" + "rightshoe\0" + "leftshoe\0" + "lefttack\0" + "righttack\0" + "hebrew_doublelowline\0" + "hebrew_aleph\0" + "hebrew_bet\0" + "hebrew_beth\0" + "hebrew_gimel\0" + "hebrew_gimmel\0" + "hebrew_dalet\0" + "hebrew_daleth\0" + "hebrew_he\0" + "hebrew_waw\0" + "hebrew_zain\0" + "hebrew_zayin\0" + "hebrew_chet\0" + "hebrew_het\0" + "hebrew_tet\0" + "hebrew_teth\0" + "hebrew_yod\0" + "hebrew_finalkaph\0" + "hebrew_kaph\0" + "hebrew_lamed\0" + "hebrew_finalmem\0" + "hebrew_mem\0" + "hebrew_finalnun\0" + "hebrew_nun\0" + "hebrew_samech\0" + "hebrew_samekh\0" + "hebrew_ayin\0" + "hebrew_finalpe\0" + "hebrew_pe\0" + "hebrew_finalzade\0" + "hebrew_finalzadi\0" + "hebrew_zade\0" + "hebrew_zadi\0" + "hebrew_kuf\0" + "hebrew_qoph\0" + "hebrew_resh\0" + "hebrew_shin\0" + "hebrew_taf\0" + "hebrew_taw\0" + "Thai_kokai\0" + "Thai_khokhai\0" + "Thai_khokhuat\0" + "Thai_khokhwai\0" + "Thai_khokhon\0" + "Thai_khorakhang\0" + "Thai_ngongu\0" + "Thai_chochan\0" + "Thai_choching\0" + "Thai_chochang\0" + "Thai_soso\0" + "Thai_chochoe\0" + "Thai_yoying\0" + "Thai_dochada\0" + "Thai_topatak\0" + "Thai_thothan\0" + "Thai_thonangmontho\0" + "Thai_thophuthao\0" + "Thai_nonen\0" + "Thai_dodek\0" + "Thai_totao\0" + "Thai_thothung\0" + "Thai_thothahan\0" + "Thai_thothong\0" + "Thai_nonu\0" + "Thai_bobaimai\0" + "Thai_popla\0" + "Thai_phophung\0" + "Thai_fofa\0" + "Thai_phophan\0" + "Thai_fofan\0" + "Thai_phosamphao\0" + "Thai_moma\0" + "Thai_yoyak\0" + "Thai_rorua\0" + "Thai_ru\0" + "Thai_loling\0" + "Thai_lu\0" + "Thai_wowaen\0" + "Thai_sosala\0" + "Thai_sorusi\0" + "Thai_sosua\0" + "Thai_hohip\0" + "Thai_lochula\0" + "Thai_oang\0" + "Thai_honokhuk\0" + "Thai_paiyannoi\0" + "Thai_saraa\0" + "Thai_maihanakat\0" + "Thai_saraaa\0" + "Thai_saraam\0" + "Thai_sarai\0" + "Thai_saraii\0" + "Thai_saraue\0" + "Thai_sarauee\0" + "Thai_sarau\0" + "Thai_sarauu\0" + "Thai_phinthu\0" + "Thai_maihanakat_maitho\0" + "Thai_baht\0" + "Thai_sarae\0" + "Thai_saraae\0" + "Thai_sarao\0" + "Thai_saraaimaimuan\0" + "Thai_saraaimaimalai\0" + "Thai_lakkhangyao\0" + "Thai_maiyamok\0" + "Thai_maitaikhu\0" + "Thai_maiek\0" + "Thai_maitho\0" + "Thai_maitri\0" + "Thai_maichattawa\0" + "Thai_thanthakhat\0" + "Thai_nikhahit\0" + "Thai_leksun\0" + "Thai_leknung\0" + "Thai_leksong\0" + "Thai_leksam\0" + "Thai_leksi\0" + "Thai_lekha\0" + "Thai_lekhok\0" + "Thai_lekchet\0" + "Thai_lekpaet\0" + "Thai_lekkao\0" + "Hangul_Kiyeog\0" + "Hangul_SsangKiyeog\0" + "Hangul_KiyeogSios\0" + "Hangul_Nieun\0" + "Hangul_NieunJieuj\0" + "Hangul_NieunHieuh\0" + "Hangul_Dikeud\0" + "Hangul_SsangDikeud\0" + "Hangul_Rieul\0" + "Hangul_RieulKiyeog\0" + "Hangul_RieulMieum\0" + "Hangul_RieulPieub\0" + "Hangul_RieulSios\0" + "Hangul_RieulTieut\0" + "Hangul_RieulPhieuf\0" + "Hangul_RieulHieuh\0" + "Hangul_Mieum\0" + "Hangul_Pieub\0" + "Hangul_SsangPieub\0" + "Hangul_PieubSios\0" + "Hangul_Sios\0" + "Hangul_SsangSios\0" + "Hangul_Ieung\0" + "Hangul_Jieuj\0" + "Hangul_SsangJieuj\0" + "Hangul_Cieuc\0" + "Hangul_Khieuq\0" + "Hangul_Tieut\0" + "Hangul_Phieuf\0" + "Hangul_Hieuh\0" + "Hangul_A\0" + "Hangul_AE\0" + "Hangul_YA\0" + "Hangul_YAE\0" + "Hangul_EO\0" + "Hangul_E\0" + "Hangul_YEO\0" + "Hangul_YE\0" + "Hangul_O\0" + "Hangul_WA\0" + "Hangul_WAE\0" + "Hangul_OE\0" + "Hangul_YO\0" + "Hangul_U\0" + "Hangul_WEO\0" + "Hangul_WE\0" + "Hangul_WI\0" + "Hangul_YU\0" + "Hangul_EU\0" + "Hangul_YI\0" + "Hangul_I\0" + "Hangul_J_Kiyeog\0" + "Hangul_J_SsangKiyeog\0" + "Hangul_J_KiyeogSios\0" + "Hangul_J_Nieun\0" + "Hangul_J_NieunJieuj\0" + "Hangul_J_NieunHieuh\0" + "Hangul_J_Dikeud\0" + "Hangul_J_Rieul\0" + "Hangul_J_RieulKiyeog\0" + "Hangul_J_RieulMieum\0" + "Hangul_J_RieulPieub\0" + "Hangul_J_RieulSios\0" + "Hangul_J_RieulTieut\0" + "Hangul_J_RieulPhieuf\0" + "Hangul_J_RieulHieuh\0" + "Hangul_J_Mieum\0" + "Hangul_J_Pieub\0" + "Hangul_J_PieubSios\0" + "Hangul_J_Sios\0" + "Hangul_J_SsangSios\0" + "Hangul_J_Ieung\0" + "Hangul_J_Jieuj\0" + "Hangul_J_Cieuc\0" + "Hangul_J_Khieuq\0" + "Hangul_J_Tieut\0" + "Hangul_J_Phieuf\0" + "Hangul_J_Hieuh\0" + "Hangul_RieulYeorinHieuh\0" + "Hangul_SunkyeongeumMieum\0" + "Hangul_SunkyeongeumPieub\0" + "Hangul_PanSios\0" + "Hangul_KkogjiDalrinIeung\0" + "Hangul_SunkyeongeumPhieuf\0" + "Hangul_YeorinHieuh\0" + "Hangul_AraeA\0" + "Hangul_AraeAE\0" + "Hangul_J_PanSios\0" + "Hangul_J_KkogjiDalrinIeung\0" + "Hangul_J_YeorinHieuh\0" + "Korean_Won\0" + "OE\0" + "oe\0" + "Ydiaeresis\0" + "EcuSign\0" + "ColonSign\0" + "CruzeiroSign\0" + "FFrancSign\0" + "LiraSign\0" + "MillSign\0" + "NairaSign\0" + "PesetaSign\0" + "RupeeSign\0" + "WonSign\0" + "NewSheqelSign\0" + "DongSign\0" + "EuroSign\0" + "3270_Duplicate\0" + "3270_FieldMark\0" + "3270_Right2\0" + "3270_Left2\0" + "3270_BackTab\0" + "3270_EraseEOF\0" + "3270_EraseInput\0" + "3270_Reset\0" + "3270_Quit\0" + "3270_PA1\0" + "3270_PA2\0" + "3270_PA3\0" + "3270_Test\0" + "3270_Attn\0" + "3270_CursorBlink\0" + "3270_AltCursor\0" + "3270_KeyClick\0" + "3270_Jump\0" + "3270_Ident\0" + "3270_Rule\0" + "3270_Copy\0" + "3270_Play\0" + "3270_Setup\0" + "3270_Record\0" + "3270_ChangeScreen\0" + "3270_DeleteWord\0" + "3270_ExSelect\0" + "3270_CursorSelect\0" + "3270_PrintScreen\0" + "3270_Enter\0" + "ISO_Lock\0" + "ISO_Level2_Latch\0" + "ISO_Level3_Shift\0" + "ISO_Level3_Latch\0" + "ISO_Level3_Lock\0" + "ISO_Group_Latch\0" + "ISO_Group_Lock\0" + "ISO_Next_Group\0" + "ISO_Next_Group_Lock\0" + "ISO_Prev_Group\0" + "ISO_Prev_Group_Lock\0" + "ISO_First_Group\0" + "ISO_First_Group_Lock\0" + "ISO_Last_Group\0" + "ISO_Last_Group_Lock\0" + "ISO_Left_Tab\0" + "ISO_Move_Line_Up\0" + "ISO_Move_Line_Down\0" + "ISO_Partial_Line_Up\0" + "ISO_Partial_Line_Down\0" + "ISO_Partial_Space_Left\0" + "ISO_Partial_Space_Right\0" + "ISO_Set_Margin_Left\0" + "ISO_Set_Margin_Right\0" + "ISO_Release_Margin_Left\0" + "ISO_Release_Margin_Right\0" + "ISO_Release_Both_Margins\0" + "ISO_Fast_Cursor_Left\0" + "ISO_Fast_Cursor_Right\0" + "ISO_Fast_Cursor_Up\0" + "ISO_Fast_Cursor_Down\0" + "ISO_Continuous_Underline\0" + "ISO_Discontinuous_Underline\0" + "ISO_Emphasize\0" + "ISO_Center_Object\0" + "ISO_Enter\0" + "dead_grave\0" + "dead_acute\0" + "dead_circumflex\0" + "dead_tilde\0" + "dead_macron\0" + "dead_breve\0" + "dead_abovedot\0" + "dead_diaeresis\0" + "dead_abovering\0" + "dead_doubleacute\0" + "dead_caron\0" + "dead_cedilla\0" + "dead_ogonek\0" + "dead_iota\0" + "dead_voiced_sound\0" + "dead_semivoiced_sound\0" + "dead_belowdot\0" + "dead_hook\0" + "dead_horn\0" + "AccessX_Enable\0" + "AccessX_Feedback_Enable\0" + "RepeatKeys_Enable\0" + "SlowKeys_Enable\0" + "BounceKeys_Enable\0" + "StickyKeys_Enable\0" + "MouseKeys_Enable\0" + "MouseKeys_Accel_Enable\0" + "Overlay1_Enable\0" + "Overlay2_Enable\0" + "AudibleBell_Enable\0" + "First_Virtual_Screen\0" + "Prev_Virtual_Screen\0" + "Next_Virtual_Screen\0" + "Last_Virtual_Screen\0" + "Terminate_Server\0" + "Pointer_Left\0" + "Pointer_Right\0" + "Pointer_Up\0" + "Pointer_Down\0" + "Pointer_UpLeft\0" + "Pointer_UpRight\0" + "Pointer_DownLeft\0" + "Pointer_DownRight\0" + "Pointer_Button_Dflt\0" + "Pointer_Button1\0" + "Pointer_Button2\0" + "Pointer_Button3\0" + "Pointer_Button4\0" + "Pointer_Button5\0" + "Pointer_DblClick_Dflt\0" + "Pointer_DblClick1\0" + "Pointer_DblClick2\0" + "Pointer_DblClick3\0" + "Pointer_DblClick4\0" + "Pointer_DblClick5\0" + "Pointer_Drag_Dflt\0" + "Pointer_Drag1\0" + "Pointer_Drag2\0" + "Pointer_Drag3\0" + "Pointer_Drag4\0" + "Pointer_EnableKeys\0" + "Pointer_Accelerate\0" + "Pointer_DfltBtnNext\0" + "Pointer_DfltBtnPrev\0" + "Pointer_Drag5\0" + "BackSpace\0" + "Tab\0" + "Linefeed\0" + "Clear\0" + "Return\0" + "Pause\0" + "Scroll_Lock\0" + "Sys_Req\0" + "Escape\0" + "Multi_key\0" + "Kanji\0" + "Muhenkan\0" + "Henkan\0" + "Henkan_Mode\0" + "Romaji\0" + "Hiragana\0" + "Katakana\0" + "Hiragana_Katakana\0" + "Zenkaku\0" + "Hankaku\0" + "Zenkaku_Hankaku\0" + "Touroku\0" + "Massyo\0" + "Kana_Lock\0" + "Kana_Shift\0" + "Eisu_Shift\0" + "Eisu_toggle\0" + "Hangul\0" + "Hangul_Start\0" + "Hangul_End\0" + "Hangul_Hanja\0" + "Hangul_Jamo\0" + "Hangul_Romaja\0" + "Codeinput\0" + "Hangul_Jeonja\0" + "Hangul_Banja\0" + "Hangul_PreHanja\0" + "Hangul_PostHanja\0" + "SingleCandidate\0" + "MultipleCandidate\0" + "PreviousCandidate\0" + "Hangul_Special\0" + "Home\0" + "Left\0" + "Up\0" + "Right\0" + "Down\0" + "Page_Up\0" + "Prior\0" + "Page_Down\0" + "Next\0" + "End\0" + "Begin\0" + "Select\0" + "Print\0" + "Execute\0" + "Insert\0" + "Undo\0" + "Redo\0" + "Menu\0" + "Find\0" + "Cancel\0" + "Help\0" + "Break\0" + "Arabic_switch\0" + "Greek_switch\0" + "Hangul_switch\0" + "Hebrew_switch\0" + "ISO_Group_Shift\0" + "Mode_switch\0" + "kana_switch\0" + "script_switch\0" + "Num_Lock\0" + "KP_Space\0" + "KP_Tab\0" + "KP_Enter\0" + "KP_F1\0" + "KP_F2\0" + "KP_F3\0" + "KP_F4\0" + "KP_Home\0" + "KP_Left\0" + "KP_Up\0" + "KP_Right\0" + "KP_Down\0" + "KP_Page_Up\0" + "KP_Prior\0" + "KP_Page_Down\0" + "KP_Next\0" + "KP_End\0" + "KP_Begin\0" + "KP_Insert\0" + "KP_Delete\0" + "KP_Multiply\0" + "KP_Add\0" + "KP_Separator\0" + "KP_Subtract\0" + "KP_Decimal\0" + "KP_Divide\0" + "KP_0\0" + "KP_1\0" + "KP_2\0" + "KP_3\0" + "KP_4\0" + "KP_5\0" + "KP_6\0" + "KP_7\0" + "KP_8\0" + "KP_9\0" + "KP_Equal\0" + "F1\0" + "F2\0" + "F3\0" + "F4\0" + "F5\0" + "F6\0" + "F7\0" + "F8\0" + "F9\0" + "F10\0" + "F11\0" + "F12\0" + "F13\0" + "F14\0" + "F15\0" + "F16\0" + "F17\0" + "F18\0" + "F19\0" + "F20\0" + "F21\0" + "F22\0" + "F23\0" + "F24\0" + "F25\0" + "F26\0" + "F27\0" + "F28\0" + "F29\0" + "F30\0" + "F31\0" + "F32\0" + "F33\0" + "F34\0" + "F35\0" + "Shift_L\0" + "Shift_R\0" + "Control_L\0" + "Control_R\0" + "Caps_Lock\0" + "Shift_Lock\0" + "Meta_L\0" + "Meta_R\0" + "Alt_L\0" + "Alt_R\0" + "Super_L\0" + "Super_R\0" + "Hyper_L\0" + "Hyper_R\0" + "Delete\0" + "VoidSymbol\0"; + +typedef struct { + guint keyval; + guint offset; +} gdk_key; + +static const gdk_key gdk_keys_by_keyval[] = { + { 0x000020, 0 }, + { 0x000021, 6 }, + { 0x000022, 13 }, + { 0x000023, 22 }, + { 0x000024, 33 }, + { 0x000025, 40 }, + { 0x000026, 48 }, + { 0x000027, 58 }, + { 0x000027, 69 }, + { 0x000028, 80 }, + { 0x000029, 90 }, + { 0x00002a, 101 }, + { 0x00002b, 110 }, + { 0x00002c, 115 }, + { 0x00002d, 121 }, + { 0x00002e, 127 }, + { 0x00002f, 134 }, + { 0x000030, 140 }, + { 0x000031, 142 }, + { 0x000032, 144 }, + { 0x000033, 146 }, + { 0x000034, 148 }, + { 0x000035, 150 }, + { 0x000036, 152 }, + { 0x000037, 154 }, + { 0x000038, 156 }, + { 0x000039, 158 }, + { 0x00003a, 160 }, + { 0x00003b, 166 }, + { 0x00003c, 176 }, + { 0x00003d, 181 }, + { 0x00003e, 187 }, + { 0x00003f, 195 }, + { 0x000040, 204 }, + { 0x000041, 207 }, + { 0x000042, 209 }, + { 0x000043, 211 }, + { 0x000044, 213 }, + { 0x000045, 215 }, + { 0x000046, 217 }, + { 0x000047, 219 }, + { 0x000048, 221 }, + { 0x000049, 223 }, + { 0x00004a, 225 }, + { 0x00004b, 227 }, + { 0x00004c, 229 }, + { 0x00004d, 231 }, + { 0x00004e, 233 }, + { 0x00004f, 235 }, + { 0x000050, 237 }, + { 0x000051, 239 }, + { 0x000052, 241 }, + { 0x000053, 243 }, + { 0x000054, 245 }, + { 0x000055, 247 }, + { 0x000056, 249 }, + { 0x000057, 251 }, + { 0x000058, 253 }, + { 0x000059, 255 }, + { 0x00005a, 257 }, + { 0x00005b, 259 }, + { 0x00005c, 271 }, + { 0x00005d, 281 }, + { 0x00005e, 294 }, + { 0x00005f, 306 }, + { 0x000060, 317 }, + { 0x000060, 323 }, + { 0x000061, 333 }, + { 0x000062, 335 }, + { 0x000063, 337 }, + { 0x000064, 339 }, + { 0x000065, 341 }, + { 0x000066, 343 }, + { 0x000067, 345 }, + { 0x000068, 347 }, + { 0x000069, 349 }, + { 0x00006a, 351 }, + { 0x00006b, 353 }, + { 0x00006c, 355 }, + { 0x00006d, 357 }, + { 0x00006e, 359 }, + { 0x00006f, 361 }, + { 0x000070, 363 }, + { 0x000071, 365 }, + { 0x000072, 367 }, + { 0x000073, 369 }, + { 0x000074, 371 }, + { 0x000075, 373 }, + { 0x000076, 375 }, + { 0x000077, 377 }, + { 0x000078, 379 }, + { 0x000079, 381 }, + { 0x00007a, 383 }, + { 0x00007b, 385 }, + { 0x00007c, 395 }, + { 0x00007d, 399 }, + { 0x00007e, 410 }, + { 0x0000a0, 421 }, + { 0x0000a1, 434 }, + { 0x0000a2, 445 }, + { 0x0000a3, 450 }, + { 0x0000a4, 459 }, + { 0x0000a5, 468 }, + { 0x0000a6, 472 }, + { 0x0000a7, 482 }, + { 0x0000a8, 490 }, + { 0x0000a9, 500 }, + { 0x0000aa, 510 }, + { 0x0000ab, 522 }, + { 0x0000ac, 536 }, + { 0x0000ad, 544 }, + { 0x0000ae, 551 }, + { 0x0000af, 562 }, + { 0x0000b0, 569 }, + { 0x0000b1, 576 }, + { 0x0000b2, 586 }, + { 0x0000b3, 598 }, + { 0x0000b4, 612 }, + { 0x0000b5, 618 }, + { 0x0000b6, 621 }, + { 0x0000b7, 631 }, + { 0x0000b8, 646 }, + { 0x0000b9, 654 }, + { 0x0000ba, 666 }, + { 0x0000bb, 676 }, + { 0x0000bc, 691 }, + { 0x0000bd, 702 }, + { 0x0000be, 710 }, + { 0x0000bf, 724 }, + { 0x0000c0, 737 }, + { 0x0000c1, 744 }, + { 0x0000c2, 751 }, + { 0x0000c3, 763 }, + { 0x0000c4, 770 }, + { 0x0000c5, 781 }, + { 0x0000c6, 787 }, + { 0x0000c7, 790 }, + { 0x0000c8, 799 }, + { 0x0000c9, 806 }, + { 0x0000ca, 813 }, + { 0x0000cb, 825 }, + { 0x0000cc, 836 }, + { 0x0000cd, 843 }, + { 0x0000ce, 850 }, + { 0x0000cf, 862 }, + { 0x0000d0, 873 }, + { 0x0000d0, 877 }, + { 0x0000d1, 881 }, + { 0x0000d2, 888 }, + { 0x0000d3, 895 }, + { 0x0000d4, 902 }, + { 0x0000d5, 914 }, + { 0x0000d6, 921 }, + { 0x0000d7, 932 }, + { 0x0000d8, 941 }, + { 0x0000d9, 950 }, + { 0x0000da, 957 }, + { 0x0000db, 964 }, + { 0x0000dc, 976 }, + { 0x0000dd, 987 }, + { 0x0000de, 994 }, + { 0x0000de, 1000 }, + { 0x0000df, 1006 }, + { 0x0000e0, 1013 }, + { 0x0000e1, 1020 }, + { 0x0000e2, 1027 }, + { 0x0000e3, 1039 }, + { 0x0000e4, 1046 }, + { 0x0000e5, 1057 }, + { 0x0000e6, 1063 }, + { 0x0000e7, 1066 }, + { 0x0000e8, 1075 }, + { 0x0000e9, 1082 }, + { 0x0000ea, 1089 }, + { 0x0000eb, 1101 }, + { 0x0000ec, 1112 }, + { 0x0000ed, 1119 }, + { 0x0000ee, 1126 }, + { 0x0000ef, 1138 }, + { 0x0000f0, 1149 }, + { 0x0000f1, 1153 }, + { 0x0000f2, 1160 }, + { 0x0000f3, 1167 }, + { 0x0000f4, 1174 }, + { 0x0000f5, 1186 }, + { 0x0000f6, 1193 }, + { 0x0000f7, 1204 }, + { 0x0000f8, 1213 }, + { 0x0000f9, 1220 }, + { 0x0000fa, 1227 }, + { 0x0000fb, 1234 }, + { 0x0000fc, 1246 }, + { 0x0000fd, 1257 }, + { 0x0000fe, 1264 }, + { 0x0000ff, 1270 }, + { 0x0001a1, 1281 }, + { 0x0001a2, 1289 }, + { 0x0001a3, 1295 }, + { 0x0001a5, 1303 }, + { 0x0001a6, 1310 }, + { 0x0001a9, 1317 }, + { 0x0001aa, 1324 }, + { 0x0001ab, 1333 }, + { 0x0001ac, 1340 }, + { 0x0001ae, 1347 }, + { 0x0001af, 1354 }, + { 0x0001b1, 1364 }, + { 0x0001b2, 1372 }, + { 0x0001b3, 1379 }, + { 0x0001b5, 1387 }, + { 0x0001b6, 1394 }, + { 0x0001b7, 1401 }, + { 0x0001b9, 1407 }, + { 0x0001ba, 1414 }, + { 0x0001bb, 1423 }, + { 0x0001bc, 1430 }, + { 0x0001bd, 1437 }, + { 0x0001be, 1449 }, + { 0x0001bf, 1456 }, + { 0x0001c0, 1466 }, + { 0x0001c3, 1473 }, + { 0x0001c5, 1480 }, + { 0x0001c6, 1487 }, + { 0x0001c8, 1494 }, + { 0x0001ca, 1501 }, + { 0x0001cc, 1509 }, + { 0x0001cf, 1516 }, + { 0x0001d0, 1523 }, + { 0x0001d1, 1531 }, + { 0x0001d2, 1538 }, + { 0x0001d5, 1545 }, + { 0x0001d8, 1558 }, + { 0x0001d9, 1565 }, + { 0x0001db, 1571 }, + { 0x0001de, 1584 }, + { 0x0001e0, 1593 }, + { 0x0001e3, 1600 }, + { 0x0001e5, 1607 }, + { 0x0001e6, 1614 }, + { 0x0001e8, 1621 }, + { 0x0001ea, 1628 }, + { 0x0001ec, 1636 }, + { 0x0001ef, 1643 }, + { 0x0001f0, 1650 }, + { 0x0001f1, 1658 }, + { 0x0001f2, 1665 }, + { 0x0001f5, 1672 }, + { 0x0001f8, 1685 }, + { 0x0001f9, 1692 }, + { 0x0001fb, 1698 }, + { 0x0001fe, 1711 }, + { 0x0001ff, 1720 }, + { 0x0002a1, 1729 }, + { 0x0002a6, 1737 }, + { 0x0002a9, 1749 }, + { 0x0002ab, 1759 }, + { 0x0002ac, 1766 }, + { 0x0002b1, 1778 }, + { 0x0002b6, 1786 }, + { 0x0002b9, 1798 }, + { 0x0002bb, 1807 }, + { 0x0002bc, 1814 }, + { 0x0002c5, 1826 }, + { 0x0002c6, 1836 }, + { 0x0002d5, 1848 }, + { 0x0002d8, 1858 }, + { 0x0002dd, 1870 }, + { 0x0002de, 1877 }, + { 0x0002e5, 1889 }, + { 0x0002e6, 1899 }, + { 0x0002f5, 1911 }, + { 0x0002f8, 1921 }, + { 0x0002fd, 1933 }, + { 0x0002fe, 1940 }, + { 0x0003a2, 1952 }, + { 0x0003a2, 1958 }, + { 0x0003a3, 1962 }, + { 0x0003a5, 1971 }, + { 0x0003a6, 1978 }, + { 0x0003aa, 1987 }, + { 0x0003ab, 1995 }, + { 0x0003ac, 2004 }, + { 0x0003b3, 2011 }, + { 0x0003b5, 2020 }, + { 0x0003b6, 2027 }, + { 0x0003ba, 2036 }, + { 0x0003bb, 2044 }, + { 0x0003bc, 2053 }, + { 0x0003bd, 2060 }, + { 0x0003bf, 2064 }, + { 0x0003c0, 2068 }, + { 0x0003c7, 2076 }, + { 0x0003cc, 2084 }, + { 0x0003cf, 2094 }, + { 0x0003d1, 2102 }, + { 0x0003d2, 2111 }, + { 0x0003d3, 2119 }, + { 0x0003d9, 2128 }, + { 0x0003dd, 2136 }, + { 0x0003de, 2143 }, + { 0x0003e0, 2151 }, + { 0x0003e7, 2159 }, + { 0x0003ec, 2167 }, + { 0x0003ef, 2177 }, + { 0x0003f1, 2185 }, + { 0x0003f2, 2194 }, + { 0x0003f3, 2202 }, + { 0x0003f9, 2211 }, + { 0x0003fd, 2219 }, + { 0x0003fe, 2226 }, + { 0x00047e, 2234 }, + { 0x0004a1, 2243 }, + { 0x0004a2, 2257 }, + { 0x0004a3, 2277 }, + { 0x0004a4, 2297 }, + { 0x0004a5, 2308 }, + { 0x0004a5, 2325 }, + { 0x0004a6, 2340 }, + { 0x0004a7, 2348 }, + { 0x0004a8, 2355 }, + { 0x0004a9, 2362 }, + { 0x0004aa, 2369 }, + { 0x0004ab, 2376 }, + { 0x0004ac, 2383 }, + { 0x0004ad, 2391 }, + { 0x0004ae, 2399 }, + { 0x0004af, 2407 }, + { 0x0004af, 2416 }, + { 0x0004b0, 2424 }, + { 0x0004b1, 2439 }, + { 0x0004b2, 2446 }, + { 0x0004b3, 2453 }, + { 0x0004b4, 2460 }, + { 0x0004b5, 2467 }, + { 0x0004b6, 2474 }, + { 0x0004b7, 2482 }, + { 0x0004b8, 2490 }, + { 0x0004b9, 2498 }, + { 0x0004ba, 2506 }, + { 0x0004bb, 2514 }, + { 0x0004bc, 2522 }, + { 0x0004bd, 2531 }, + { 0x0004be, 2539 }, + { 0x0004bf, 2547 }, + { 0x0004c0, 2555 }, + { 0x0004c1, 2563 }, + { 0x0004c1, 2572 }, + { 0x0004c2, 2580 }, + { 0x0004c2, 2589 }, + { 0x0004c3, 2597 }, + { 0x0004c4, 2605 }, + { 0x0004c5, 2613 }, + { 0x0004c6, 2621 }, + { 0x0004c7, 2629 }, + { 0x0004c8, 2637 }, + { 0x0004c9, 2645 }, + { 0x0004ca, 2653 }, + { 0x0004cb, 2661 }, + { 0x0004cc, 2669 }, + { 0x0004cc, 2677 }, + { 0x0004cd, 2685 }, + { 0x0004ce, 2693 }, + { 0x0004cf, 2701 }, + { 0x0004d0, 2709 }, + { 0x0004d1, 2717 }, + { 0x0004d2, 2725 }, + { 0x0004d3, 2733 }, + { 0x0004d4, 2741 }, + { 0x0004d5, 2749 }, + { 0x0004d6, 2757 }, + { 0x0004d7, 2765 }, + { 0x0004d8, 2773 }, + { 0x0004d9, 2781 }, + { 0x0004da, 2789 }, + { 0x0004db, 2797 }, + { 0x0004dc, 2805 }, + { 0x0004dd, 2813 }, + { 0x0004de, 2820 }, + { 0x0004df, 2832 }, + { 0x0005ac, 2848 }, + { 0x0005bb, 2861 }, + { 0x0005bf, 2878 }, + { 0x0005c1, 2899 }, + { 0x0005c2, 2912 }, + { 0x0005c3, 2931 }, + { 0x0005c4, 2950 }, + { 0x0005c5, 2968 }, + { 0x0005c6, 2990 }, + { 0x0005c7, 3008 }, + { 0x0005c8, 3020 }, + { 0x0005c9, 3031 }, + { 0x0005ca, 3049 }, + { 0x0005cb, 3060 }, + { 0x0005cc, 3072 }, + { 0x0005cd, 3084 }, + { 0x0005ce, 3095 }, + { 0x0005cf, 3107 }, + { 0x0005d0, 3118 }, + { 0x0005d1, 3130 }, + { 0x0005d2, 3140 }, + { 0x0005d3, 3152 }, + { 0x0005d4, 3164 }, + { 0x0005d5, 3177 }, + { 0x0005d6, 3188 }, + { 0x0005d7, 3199 }, + { 0x0005d8, 3210 }, + { 0x0005d9, 3221 }, + { 0x0005da, 3232 }, + { 0x0005e0, 3245 }, + { 0x0005e1, 3260 }, + { 0x0005e2, 3271 }, + { 0x0005e3, 3282 }, + { 0x0005e4, 3293 }, + { 0x0005e5, 3304 }, + { 0x0005e6, 3316 }, + { 0x0005e7, 3328 }, + { 0x0005e7, 3338 }, + { 0x0005e8, 3349 }, + { 0x0005e9, 3360 }, + { 0x0005ea, 3379 }, + { 0x0005eb, 3390 }, + { 0x0005ec, 3406 }, + { 0x0005ed, 3422 }, + { 0x0005ee, 3438 }, + { 0x0005ef, 3451 }, + { 0x0005f0, 3464 }, + { 0x0005f1, 3477 }, + { 0x0005f2, 3491 }, + { 0x0006a1, 3504 }, + { 0x0006a2, 3516 }, + { 0x0006a3, 3530 }, + { 0x0006a4, 3542 }, + { 0x0006a4, 3555 }, + { 0x0006a5, 3567 }, + { 0x0006a6, 3581 }, + { 0x0006a6, 3593 }, + { 0x0006a7, 3604 }, + { 0x0006a7, 3617 }, + { 0x0006a8, 3629 }, + { 0x0006a8, 3641 }, + { 0x0006a9, 3652 }, + { 0x0006a9, 3665 }, + { 0x0006aa, 3677 }, + { 0x0006aa, 3690 }, + { 0x0006ab, 3702 }, + { 0x0006ac, 3715 }, + { 0x0006ae, 3729 }, + { 0x0006af, 3749 }, + { 0x0006af, 3763 }, + { 0x0006b0, 3775 }, + { 0x0006b1, 3786 }, + { 0x0006b2, 3798 }, + { 0x0006b3, 3812 }, + { 0x0006b4, 3824 }, + { 0x0006b4, 3837 }, + { 0x0006b5, 3849 }, + { 0x0006b6, 3863 }, + { 0x0006b6, 3875 }, + { 0x0006b7, 3886 }, + { 0x0006b7, 3899 }, + { 0x0006b8, 3911 }, + { 0x0006b8, 3923 }, + { 0x0006b9, 3934 }, + { 0x0006b9, 3947 }, + { 0x0006ba, 3959 }, + { 0x0006ba, 3972 }, + { 0x0006bb, 3984 }, + { 0x0006bc, 3997 }, + { 0x0006be, 4011 }, + { 0x0006bf, 4031 }, + { 0x0006bf, 4045 }, + { 0x0006c0, 4057 }, + { 0x0006c1, 4069 }, + { 0x0006c2, 4080 }, + { 0x0006c3, 4092 }, + { 0x0006c4, 4105 }, + { 0x0006c5, 4117 }, + { 0x0006c6, 4129 }, + { 0x0006c7, 4141 }, + { 0x0006c8, 4154 }, + { 0x0006c9, 4166 }, + { 0x0006ca, 4177 }, + { 0x0006cb, 4193 }, + { 0x0006cc, 4205 }, + { 0x0006cd, 4217 }, + { 0x0006ce, 4229 }, + { 0x0006cf, 4241 }, + { 0x0006d0, 4252 }, + { 0x0006d1, 4264 }, + { 0x0006d2, 4276 }, + { 0x0006d3, 4288 }, + { 0x0006d4, 4300 }, + { 0x0006d5, 4312 }, + { 0x0006d6, 4323 }, + { 0x0006d7, 4336 }, + { 0x0006d8, 4348 }, + { 0x0006d9, 4366 }, + { 0x0006da, 4380 }, + { 0x0006db, 4392 }, + { 0x0006dc, 4405 }, + { 0x0006dd, 4416 }, + { 0x0006de, 4431 }, + { 0x0006df, 4444 }, + { 0x0006e0, 4462 }, + { 0x0006e1, 4474 }, + { 0x0006e2, 4485 }, + { 0x0006e3, 4497 }, + { 0x0006e4, 4510 }, + { 0x0006e5, 4522 }, + { 0x0006e6, 4534 }, + { 0x0006e7, 4546 }, + { 0x0006e8, 4559 }, + { 0x0006e9, 4571 }, + { 0x0006ea, 4582 }, + { 0x0006eb, 4598 }, + { 0x0006ec, 4610 }, + { 0x0006ed, 4622 }, + { 0x0006ee, 4634 }, + { 0x0006ef, 4646 }, + { 0x0006f0, 4657 }, + { 0x0006f1, 4669 }, + { 0x0006f2, 4681 }, + { 0x0006f3, 4693 }, + { 0x0006f4, 4705 }, + { 0x0006f5, 4717 }, + { 0x0006f6, 4728 }, + { 0x0006f7, 4741 }, + { 0x0006f8, 4753 }, + { 0x0006f9, 4771 }, + { 0x0006fa, 4785 }, + { 0x0006fb, 4797 }, + { 0x0006fc, 4810 }, + { 0x0006fd, 4821 }, + { 0x0006fe, 4836 }, + { 0x0006ff, 4849 }, + { 0x0007a1, 4867 }, + { 0x0007a2, 4885 }, + { 0x0007a3, 4905 }, + { 0x0007a4, 4921 }, + { 0x0007a5, 4938 }, + { 0x0007a5, 4957 }, + { 0x0007a7, 4977 }, + { 0x0007a8, 4997 }, + { 0x0007a9, 5017 }, + { 0x0007ab, 5039 }, + { 0x0007ae, 5057 }, + { 0x0007af, 5078 }, + { 0x0007b1, 5093 }, + { 0x0007b2, 5111 }, + { 0x0007b3, 5131 }, + { 0x0007b4, 5147 }, + { 0x0007b5, 5164 }, + { 0x0007b6, 5183 }, + { 0x0007b7, 5208 }, + { 0x0007b8, 5228 }, + { 0x0007b9, 5248 }, + { 0x0007ba, 5270 }, + { 0x0007bb, 5298 }, + { 0x0007c1, 5316 }, + { 0x0007c2, 5328 }, + { 0x0007c3, 5339 }, + { 0x0007c4, 5351 }, + { 0x0007c5, 5363 }, + { 0x0007c6, 5377 }, + { 0x0007c7, 5388 }, + { 0x0007c8, 5398 }, + { 0x0007c9, 5410 }, + { 0x0007ca, 5421 }, + { 0x0007cb, 5433 }, + { 0x0007cb, 5446 }, + { 0x0007cc, 5458 }, + { 0x0007cd, 5467 }, + { 0x0007ce, 5476 }, + { 0x0007cf, 5485 }, + { 0x0007d0, 5499 }, + { 0x0007d1, 5508 }, + { 0x0007d2, 5518 }, + { 0x0007d4, 5530 }, + { 0x0007d5, 5540 }, + { 0x0007d6, 5554 }, + { 0x0007d7, 5564 }, + { 0x0007d8, 5574 }, + { 0x0007d9, 5584 }, + { 0x0007e1, 5596 }, + { 0x0007e2, 5608 }, + { 0x0007e3, 5619 }, + { 0x0007e4, 5631 }, + { 0x0007e5, 5643 }, + { 0x0007e6, 5657 }, + { 0x0007e7, 5668 }, + { 0x0007e8, 5678 }, + { 0x0007e9, 5690 }, + { 0x0007ea, 5701 }, + { 0x0007eb, 5713 }, + { 0x0007eb, 5726 }, + { 0x0007ec, 5738 }, + { 0x0007ed, 5747 }, + { 0x0007ee, 5756 }, + { 0x0007ef, 5765 }, + { 0x0007f0, 5779 }, + { 0x0007f1, 5788 }, + { 0x0007f2, 5798 }, + { 0x0007f3, 5810 }, + { 0x0007f4, 5832 }, + { 0x0007f5, 5842 }, + { 0x0007f6, 5856 }, + { 0x0007f7, 5866 }, + { 0x0007f8, 5876 }, + { 0x0007f9, 5886 }, + { 0x0008a1, 5898 }, + { 0x0008a2, 5910 }, + { 0x0008a3, 5925 }, + { 0x0008a4, 5940 }, + { 0x0008a5, 5952 }, + { 0x0008a6, 5964 }, + { 0x0008a7, 5978 }, + { 0x0008a8, 5995 }, + { 0x0008a9, 6012 }, + { 0x0008aa, 6030 }, + { 0x0008ab, 6048 }, + { 0x0008ac, 6062 }, + { 0x0008ad, 6076 }, + { 0x0008ae, 6091 }, + { 0x0008af, 6106 }, + { 0x0008b0, 6127 }, + { 0x0008b1, 6149 }, + { 0x0008b2, 6166 }, + { 0x0008b3, 6183 }, + { 0x0008b4, 6209 }, + { 0x0008b5, 6235 }, + { 0x0008b6, 6253 }, + { 0x0008b7, 6271 }, + { 0x0008bc, 6292 }, + { 0x0008bd, 6306 }, + { 0x0008be, 6315 }, + { 0x0008bf, 6332 }, + { 0x0008c0, 6341 }, + { 0x0008c1, 6351 }, + { 0x0008c2, 6361 }, + { 0x0008c5, 6370 }, + { 0x0008c8, 6376 }, + { 0x0008c9, 6388 }, + { 0x0008cd, 6401 }, + { 0x0008ce, 6410 }, + { 0x0008cf, 6418 }, + { 0x0008d6, 6428 }, + { 0x0008da, 6436 }, + { 0x0008db, 6447 }, + { 0x0008dc, 6456 }, + { 0x0008dd, 6469 }, + { 0x0008de, 6475 }, + { 0x0008df, 6486 }, + { 0x0008ef, 6496 }, + { 0x0008f6, 6514 }, + { 0x0008fb, 6523 }, + { 0x0008fc, 6533 }, + { 0x0008fd, 6541 }, + { 0x0008fe, 6552 }, + { 0x0009df, 6562 }, + { 0x0009e0, 6568 }, + { 0x0009e1, 6581 }, + { 0x0009e2, 6594 }, + { 0x0009e3, 6597 }, + { 0x0009e4, 6600 }, + { 0x0009e5, 6603 }, + { 0x0009e8, 6606 }, + { 0x0009e9, 6609 }, + { 0x0009ea, 6612 }, + { 0x0009eb, 6627 }, + { 0x0009ec, 6641 }, + { 0x0009ed, 6654 }, + { 0x0009ee, 6668 }, + { 0x0009ef, 6682 }, + { 0x0009f0, 6697 }, + { 0x0009f1, 6712 }, + { 0x0009f2, 6727 }, + { 0x0009f3, 6742 }, + { 0x0009f4, 6757 }, + { 0x0009f5, 6763 }, + { 0x0009f6, 6770 }, + { 0x0009f7, 6775 }, + { 0x0009f8, 6780 }, + { 0x000aa1, 6788 }, + { 0x000aa2, 6796 }, + { 0x000aa3, 6804 }, + { 0x000aa4, 6813 }, + { 0x000aa5, 6822 }, + { 0x000aa6, 6833 }, + { 0x000aa7, 6844 }, + { 0x000aa8, 6854 }, + { 0x000aa9, 6864 }, + { 0x000aaa, 6871 }, + { 0x000aac, 6878 }, + { 0x000aae, 6890 }, + { 0x000aaf, 6899 }, + { 0x000ab0, 6915 }, + { 0x000ab1, 6924 }, + { 0x000ab2, 6934 }, + { 0x000ab3, 6943 }, + { 0x000ab4, 6953 }, + { 0x000ab5, 6965 }, + { 0x000ab6, 6976 }, + { 0x000ab7, 6985 }, + { 0x000ab8, 6996 }, + { 0x000abb, 7003 }, + { 0x000abc, 7011 }, + { 0x000abd, 7028 }, + { 0x000abe, 7041 }, + { 0x000abf, 7059 }, + { 0x000ac3, 7066 }, + { 0x000ac4, 7076 }, + { 0x000ac5, 7089 }, + { 0x000ac6, 7101 }, + { 0x000ac9, 7114 }, + { 0x000aca, 7124 }, + { 0x000acb, 7138 }, + { 0x000acc, 7156 }, + { 0x000acd, 7173 }, + { 0x000ace, 7191 }, + { 0x000acf, 7204 }, + { 0x000ad0, 7220 }, + { 0x000ad1, 7240 }, + { 0x000ad2, 7261 }, + { 0x000ad3, 7281 }, + { 0x000ad4, 7302 }, + { 0x000ad6, 7315 }, + { 0x000ad7, 7323 }, + { 0x000ad9, 7331 }, + { 0x000ada, 7342 }, + { 0x000adb, 7351 }, + { 0x000adc, 7368 }, + { 0x000add, 7388 }, + { 0x000ade, 7409 }, + { 0x000adf, 7424 }, + { 0x000ae0, 7437 }, + { 0x000ae1, 7454 }, + { 0x000ae2, 7473 }, + { 0x000ae3, 7488 }, + { 0x000ae4, 7504 }, + { 0x000ae5, 7522 }, + { 0x000ae6, 7531 }, + { 0x000ae7, 7550 }, + { 0x000ae8, 7567 }, + { 0x000ae9, 7585 }, + { 0x000aea, 7605 }, + { 0x000aeb, 7617 }, + { 0x000aec, 7630 }, + { 0x000aed, 7635 }, + { 0x000aee, 7643 }, + { 0x000af0, 7649 }, + { 0x000af1, 7662 }, + { 0x000af2, 7669 }, + { 0x000af3, 7682 }, + { 0x000af4, 7692 }, + { 0x000af5, 7704 }, + { 0x000af6, 7717 }, + { 0x000af7, 7729 }, + { 0x000af8, 7740 }, + { 0x000af9, 7753 }, + { 0x000afa, 7763 }, + { 0x000afb, 7781 }, + { 0x000afc, 7801 }, + { 0x000afd, 7807 }, + { 0x000afe, 7826 }, + { 0x000aff, 7845 }, + { 0x000ba3, 7852 }, + { 0x000ba6, 7862 }, + { 0x000ba8, 7873 }, + { 0x000ba9, 7883 }, + { 0x000bc0, 7891 }, + { 0x000bc2, 7899 }, + { 0x000bc3, 7908 }, + { 0x000bc4, 7915 }, + { 0x000bc6, 7925 }, + { 0x000bca, 7934 }, + { 0x000bcc, 7938 }, + { 0x000bce, 7943 }, + { 0x000bcf, 7950 }, + { 0x000bd3, 7957 }, + { 0x000bd6, 7965 }, + { 0x000bd8, 7974 }, + { 0x000bda, 7984 }, + { 0x000bdc, 7993 }, + { 0x000bfc, 8002 }, + { 0x000cdf, 8012 }, + { 0x000ce0, 8033 }, + { 0x000ce1, 8046 }, + { 0x000ce1, 8057 }, + { 0x000ce2, 8069 }, + { 0x000ce2, 8082 }, + { 0x000ce3, 8096 }, + { 0x000ce3, 8109 }, + { 0x000ce4, 8123 }, + { 0x000ce5, 8133 }, + { 0x000ce6, 8144 }, + { 0x000ce6, 8156 }, + { 0x000ce7, 8169 }, + { 0x000ce7, 8181 }, + { 0x000ce8, 8192 }, + { 0x000ce8, 8203 }, + { 0x000ce9, 8215 }, + { 0x000cea, 8226 }, + { 0x000ceb, 8243 }, + { 0x000cec, 8255 }, + { 0x000ced, 8268 }, + { 0x000cee, 8284 }, + { 0x000cef, 8295 }, + { 0x000cf0, 8311 }, + { 0x000cf1, 8322 }, + { 0x000cf1, 8336 }, + { 0x000cf2, 8350 }, + { 0x000cf3, 8362 }, + { 0x000cf4, 8377 }, + { 0x000cf5, 8387 }, + { 0x000cf5, 8404 }, + { 0x000cf6, 8421 }, + { 0x000cf6, 8433 }, + { 0x000cf7, 8445 }, + { 0x000cf7, 8456 }, + { 0x000cf8, 8468 }, + { 0x000cf9, 8480 }, + { 0x000cfa, 8492 }, + { 0x000cfa, 8503 }, + { 0x000da1, 8514 }, + { 0x000da2, 8525 }, + { 0x000da3, 8538 }, + { 0x000da4, 8552 }, + { 0x000da5, 8566 }, + { 0x000da6, 8579 }, + { 0x000da7, 8595 }, + { 0x000da8, 8607 }, + { 0x000da9, 8620 }, + { 0x000daa, 8634 }, + { 0x000dab, 8648 }, + { 0x000dac, 8658 }, + { 0x000dad, 8671 }, + { 0x000dae, 8683 }, + { 0x000daf, 8696 }, + { 0x000db0, 8709 }, + { 0x000db1, 8722 }, + { 0x000db2, 8741 }, + { 0x000db3, 8757 }, + { 0x000db4, 8768 }, + { 0x000db5, 8779 }, + { 0x000db6, 8790 }, + { 0x000db7, 8804 }, + { 0x000db8, 8819 }, + { 0x000db9, 8833 }, + { 0x000dba, 8843 }, + { 0x000dbb, 8857 }, + { 0x000dbc, 8868 }, + { 0x000dbd, 8882 }, + { 0x000dbe, 8892 }, + { 0x000dbf, 8905 }, + { 0x000dc0, 8916 }, + { 0x000dc1, 8932 }, + { 0x000dc2, 8942 }, + { 0x000dc3, 8953 }, + { 0x000dc4, 8964 }, + { 0x000dc5, 8972 }, + { 0x000dc6, 8984 }, + { 0x000dc7, 8992 }, + { 0x000dc8, 9004 }, + { 0x000dc9, 9016 }, + { 0x000dca, 9028 }, + { 0x000dcb, 9039 }, + { 0x000dcc, 9050 }, + { 0x000dcd, 9063 }, + { 0x000dce, 9073 }, + { 0x000dcf, 9087 }, + { 0x000dd0, 9102 }, + { 0x000dd1, 9113 }, + { 0x000dd2, 9129 }, + { 0x000dd3, 9141 }, + { 0x000dd4, 9153 }, + { 0x000dd5, 9164 }, + { 0x000dd6, 9176 }, + { 0x000dd7, 9188 }, + { 0x000dd8, 9201 }, + { 0x000dd9, 9212 }, + { 0x000dda, 9224 }, + { 0x000dde, 9237 }, + { 0x000ddf, 9260 }, + { 0x000de0, 9270 }, + { 0x000de1, 9281 }, + { 0x000de2, 9293 }, + { 0x000de3, 9304 }, + { 0x000de4, 9323 }, + { 0x000de5, 9343 }, + { 0x000de6, 9360 }, + { 0x000de7, 9374 }, + { 0x000de8, 9389 }, + { 0x000de9, 9400 }, + { 0x000dea, 9412 }, + { 0x000deb, 9424 }, + { 0x000dec, 9441 }, + { 0x000ded, 9458 }, + { 0x000df0, 9472 }, + { 0x000df1, 9484 }, + { 0x000df2, 9497 }, + { 0x000df3, 9510 }, + { 0x000df4, 9522 }, + { 0x000df5, 9533 }, + { 0x000df6, 9544 }, + { 0x000df7, 9556 }, + { 0x000df8, 9569 }, + { 0x000df9, 9582 }, + { 0x000ea1, 9594 }, + { 0x000ea2, 9608 }, + { 0x000ea3, 9627 }, + { 0x000ea4, 9645 }, + { 0x000ea5, 9658 }, + { 0x000ea6, 9676 }, + { 0x000ea7, 9694 }, + { 0x000ea8, 9708 }, + { 0x000ea9, 9727 }, + { 0x000eaa, 9740 }, + { 0x000eab, 9759 }, + { 0x000eac, 9777 }, + { 0x000ead, 9795 }, + { 0x000eae, 9812 }, + { 0x000eaf, 9830 }, + { 0x000eb0, 9849 }, + { 0x000eb1, 9867 }, + { 0x000eb2, 9880 }, + { 0x000eb3, 9893 }, + { 0x000eb4, 9911 }, + { 0x000eb5, 9928 }, + { 0x000eb6, 9940 }, + { 0x000eb7, 9957 }, + { 0x000eb8, 9970 }, + { 0x000eb9, 9983 }, + { 0x000eba, 10001 }, + { 0x000ebb, 10014 }, + { 0x000ebc, 10028 }, + { 0x000ebd, 10041 }, + { 0x000ebe, 10055 }, + { 0x000ebf, 10068 }, + { 0x000ec0, 10077 }, + { 0x000ec1, 10087 }, + { 0x000ec2, 10097 }, + { 0x000ec3, 10108 }, + { 0x000ec4, 10118 }, + { 0x000ec5, 10127 }, + { 0x000ec6, 10138 }, + { 0x000ec7, 10148 }, + { 0x000ec8, 10157 }, + { 0x000ec9, 10167 }, + { 0x000eca, 10178 }, + { 0x000ecb, 10188 }, + { 0x000ecc, 10198 }, + { 0x000ecd, 10207 }, + { 0x000ece, 10218 }, + { 0x000ecf, 10228 }, + { 0x000ed0, 10238 }, + { 0x000ed1, 10248 }, + { 0x000ed2, 10258 }, + { 0x000ed3, 10268 }, + { 0x000ed4, 10277 }, + { 0x000ed5, 10293 }, + { 0x000ed6, 10314 }, + { 0x000ed7, 10334 }, + { 0x000ed8, 10349 }, + { 0x000ed9, 10369 }, + { 0x000eda, 10389 }, + { 0x000edb, 10405 }, + { 0x000edc, 10420 }, + { 0x000edd, 10441 }, + { 0x000ede, 10461 }, + { 0x000edf, 10481 }, + { 0x000ee0, 10500 }, + { 0x000ee1, 10520 }, + { 0x000ee2, 10541 }, + { 0x000ee3, 10561 }, + { 0x000ee4, 10576 }, + { 0x000ee5, 10591 }, + { 0x000ee6, 10610 }, + { 0x000ee7, 10624 }, + { 0x000ee8, 10643 }, + { 0x000ee9, 10658 }, + { 0x000eea, 10673 }, + { 0x000eeb, 10688 }, + { 0x000eec, 10704 }, + { 0x000eed, 10719 }, + { 0x000eee, 10735 }, + { 0x000eef, 10750 }, + { 0x000ef0, 10774 }, + { 0x000ef1, 10799 }, + { 0x000ef2, 10824 }, + { 0x000ef3, 10839 }, + { 0x000ef4, 10864 }, + { 0x000ef5, 10890 }, + { 0x000ef6, 10909 }, + { 0x000ef7, 10922 }, + { 0x000ef8, 10936 }, + { 0x000ef9, 10953 }, + { 0x000efa, 10980 }, + { 0x000eff, 11001 }, + { 0x0013bc, 11012 }, + { 0x0013bd, 11015 }, + { 0x0013be, 11018 }, + { 0x0020a0, 11029 }, + { 0x0020a1, 11037 }, + { 0x0020a2, 11047 }, + { 0x0020a3, 11060 }, + { 0x0020a4, 11071 }, + { 0x0020a5, 11080 }, + { 0x0020a6, 11089 }, + { 0x0020a7, 11099 }, + { 0x0020a8, 11110 }, + { 0x0020a9, 11120 }, + { 0x0020aa, 11128 }, + { 0x0020ab, 11142 }, + { 0x0020ac, 11151 }, + { 0x00fd01, 11160 }, + { 0x00fd02, 11175 }, + { 0x00fd03, 11190 }, + { 0x00fd04, 11202 }, + { 0x00fd05, 11213 }, + { 0x00fd06, 11226 }, + { 0x00fd07, 11240 }, + { 0x00fd08, 11256 }, + { 0x00fd09, 11267 }, + { 0x00fd0a, 11277 }, + { 0x00fd0b, 11286 }, + { 0x00fd0c, 11295 }, + { 0x00fd0d, 11304 }, + { 0x00fd0e, 11314 }, + { 0x00fd0f, 11324 }, + { 0x00fd10, 11341 }, + { 0x00fd11, 11356 }, + { 0x00fd12, 11370 }, + { 0x00fd13, 11380 }, + { 0x00fd14, 11391 }, + { 0x00fd15, 11401 }, + { 0x00fd16, 11411 }, + { 0x00fd17, 11421 }, + { 0x00fd18, 11432 }, + { 0x00fd19, 11444 }, + { 0x00fd1a, 11462 }, + { 0x00fd1b, 11478 }, + { 0x00fd1c, 11492 }, + { 0x00fd1d, 11510 }, + { 0x00fd1e, 11527 }, + { 0x00fe01, 11538 }, + { 0x00fe02, 11547 }, + { 0x00fe03, 11564 }, + { 0x00fe04, 11581 }, + { 0x00fe05, 11598 }, + { 0x00fe06, 11614 }, + { 0x00fe07, 11630 }, + { 0x00fe08, 11645 }, + { 0x00fe09, 11660 }, + { 0x00fe0a, 11680 }, + { 0x00fe0b, 11695 }, + { 0x00fe0c, 11715 }, + { 0x00fe0d, 11731 }, + { 0x00fe0e, 11752 }, + { 0x00fe0f, 11767 }, + { 0x00fe20, 11787 }, + { 0x00fe21, 11800 }, + { 0x00fe22, 11817 }, + { 0x00fe23, 11836 }, + { 0x00fe24, 11856 }, + { 0x00fe25, 11878 }, + { 0x00fe26, 11901 }, + { 0x00fe27, 11925 }, + { 0x00fe28, 11945 }, + { 0x00fe29, 11966 }, + { 0x00fe2a, 11990 }, + { 0x00fe2b, 12015 }, + { 0x00fe2c, 12040 }, + { 0x00fe2d, 12061 }, + { 0x00fe2e, 12083 }, + { 0x00fe2f, 12102 }, + { 0x00fe30, 12123 }, + { 0x00fe31, 12148 }, + { 0x00fe32, 12176 }, + { 0x00fe33, 12190 }, + { 0x00fe34, 12208 }, + { 0x00fe50, 12218 }, + { 0x00fe51, 12229 }, + { 0x00fe52, 12240 }, + { 0x00fe53, 12256 }, + { 0x00fe54, 12267 }, + { 0x00fe55, 12279 }, + { 0x00fe56, 12290 }, + { 0x00fe57, 12304 }, + { 0x00fe58, 12319 }, + { 0x00fe59, 12334 }, + { 0x00fe5a, 12351 }, + { 0x00fe5b, 12362 }, + { 0x00fe5c, 12375 }, + { 0x00fe5d, 12387 }, + { 0x00fe5e, 12397 }, + { 0x00fe5f, 12415 }, + { 0x00fe60, 12437 }, + { 0x00fe61, 12451 }, + { 0x00fe62, 12461 }, + { 0x00fe70, 12471 }, + { 0x00fe71, 12486 }, + { 0x00fe72, 12510 }, + { 0x00fe73, 12528 }, + { 0x00fe74, 12544 }, + { 0x00fe75, 12562 }, + { 0x00fe76, 12580 }, + { 0x00fe77, 12597 }, + { 0x00fe78, 12620 }, + { 0x00fe79, 12636 }, + { 0x00fe7a, 12652 }, + { 0x00fed0, 12671 }, + { 0x00fed1, 12692 }, + { 0x00fed2, 12712 }, + { 0x00fed4, 12732 }, + { 0x00fed5, 12752 }, + { 0x00fee0, 12769 }, + { 0x00fee1, 12782 }, + { 0x00fee2, 12796 }, + { 0x00fee3, 12807 }, + { 0x00fee4, 12820 }, + { 0x00fee5, 12835 }, + { 0x00fee6, 12851 }, + { 0x00fee7, 12868 }, + { 0x00fee8, 12886 }, + { 0x00fee9, 12906 }, + { 0x00feea, 12922 }, + { 0x00feeb, 12938 }, + { 0x00feec, 12954 }, + { 0x00feed, 12970 }, + { 0x00feee, 12986 }, + { 0x00feef, 13008 }, + { 0x00fef0, 13026 }, + { 0x00fef1, 13044 }, + { 0x00fef2, 13062 }, + { 0x00fef3, 13080 }, + { 0x00fef4, 13098 }, + { 0x00fef5, 13116 }, + { 0x00fef6, 13130 }, + { 0x00fef7, 13144 }, + { 0x00fef8, 13158 }, + { 0x00fef9, 13172 }, + { 0x00fefa, 13191 }, + { 0x00fefb, 13210 }, + { 0x00fefc, 13230 }, + { 0x00fefd, 13250 }, + { 0x00ff08, 13264 }, + { 0x00ff09, 13274 }, + { 0x00ff0a, 13278 }, + { 0x00ff0b, 13287 }, + { 0x00ff0d, 13293 }, + { 0x00ff13, 13300 }, + { 0x00ff14, 13306 }, + { 0x00ff15, 13318 }, + { 0x00ff1b, 13326 }, + { 0x00ff20, 13333 }, + { 0x00ff21, 13343 }, + { 0x00ff22, 13349 }, + { 0x00ff23, 13358 }, + { 0x00ff23, 13365 }, + { 0x00ff24, 13377 }, + { 0x00ff25, 13384 }, + { 0x00ff26, 13393 }, + { 0x00ff27, 13402 }, + { 0x00ff28, 13420 }, + { 0x00ff29, 13428 }, + { 0x00ff2a, 13436 }, + { 0x00ff2b, 13452 }, + { 0x00ff2c, 13460 }, + { 0x00ff2d, 13467 }, + { 0x00ff2e, 13477 }, + { 0x00ff2f, 13488 }, + { 0x00ff30, 13499 }, + { 0x00ff31, 13511 }, + { 0x00ff32, 13518 }, + { 0x00ff33, 13531 }, + { 0x00ff34, 13542 }, + { 0x00ff35, 13555 }, + { 0x00ff36, 13567 }, + { 0x00ff37, 13581 }, + { 0x00ff38, 13591 }, + { 0x00ff39, 13605 }, + { 0x00ff3a, 13618 }, + { 0x00ff3b, 13634 }, + { 0x00ff3c, 13651 }, + { 0x00ff3d, 13667 }, + { 0x00ff3e, 13685 }, + { 0x00ff3f, 13703 }, + { 0x00ff50, 13718 }, + { 0x00ff51, 13723 }, + { 0x00ff52, 13728 }, + { 0x00ff53, 13731 }, + { 0x00ff54, 13737 }, + { 0x00ff55, 13742 }, + { 0x00ff55, 13750 }, + { 0x00ff56, 13756 }, + { 0x00ff56, 13766 }, + { 0x00ff57, 13771 }, + { 0x00ff58, 13775 }, + { 0x00ff60, 13781 }, + { 0x00ff61, 13788 }, + { 0x00ff62, 13794 }, + { 0x00ff63, 13802 }, + { 0x00ff65, 13809 }, + { 0x00ff66, 13814 }, + { 0x00ff67, 13819 }, + { 0x00ff68, 13824 }, + { 0x00ff69, 13829 }, + { 0x00ff6a, 13836 }, + { 0x00ff6b, 13841 }, + { 0x00ff7e, 13847 }, + { 0x00ff7e, 13861 }, + { 0x00ff7e, 13874 }, + { 0x00ff7e, 13888 }, + { 0x00ff7e, 13902 }, + { 0x00ff7e, 13918 }, + { 0x00ff7e, 13930 }, + { 0x00ff7e, 13942 }, + { 0x00ff7f, 13956 }, + { 0x00ff80, 13965 }, + { 0x00ff89, 13974 }, + { 0x00ff8d, 13981 }, + { 0x00ff91, 13990 }, + { 0x00ff92, 13996 }, + { 0x00ff93, 14002 }, + { 0x00ff94, 14008 }, + { 0x00ff95, 14014 }, + { 0x00ff96, 14022 }, + { 0x00ff97, 14030 }, + { 0x00ff98, 14036 }, + { 0x00ff99, 14045 }, + { 0x00ff9a, 14053 }, + { 0x00ff9a, 14064 }, + { 0x00ff9b, 14073 }, + { 0x00ff9b, 14086 }, + { 0x00ff9c, 14094 }, + { 0x00ff9d, 14101 }, + { 0x00ff9e, 14110 }, + { 0x00ff9f, 14120 }, + { 0x00ffaa, 14130 }, + { 0x00ffab, 14142 }, + { 0x00ffac, 14149 }, + { 0x00ffad, 14162 }, + { 0x00ffae, 14174 }, + { 0x00ffaf, 14185 }, + { 0x00ffb0, 14195 }, + { 0x00ffb1, 14200 }, + { 0x00ffb2, 14205 }, + { 0x00ffb3, 14210 }, + { 0x00ffb4, 14215 }, + { 0x00ffb5, 14220 }, + { 0x00ffb6, 14225 }, + { 0x00ffb7, 14230 }, + { 0x00ffb8, 14235 }, + { 0x00ffb9, 14240 }, + { 0x00ffbd, 14245 }, + { 0x00ffbe, 14254 }, + { 0x00ffbf, 14257 }, + { 0x00ffc0, 14260 }, + { 0x00ffc1, 14263 }, + { 0x00ffc2, 14266 }, + { 0x00ffc3, 14269 }, + { 0x00ffc4, 14272 }, + { 0x00ffc5, 14275 }, + { 0x00ffc6, 14278 }, + { 0x00ffc7, 14281 }, + { 0x00ffc8, 14285 }, + { 0x00ffc9, 14289 }, + { 0x00ffca, 14293 }, + { 0x00ffcb, 14297 }, + { 0x00ffcc, 14301 }, + { 0x00ffcd, 14305 }, + { 0x00ffce, 14309 }, + { 0x00ffcf, 14313 }, + { 0x00ffd0, 14317 }, + { 0x00ffd1, 14321 }, + { 0x00ffd2, 14325 }, + { 0x00ffd3, 14329 }, + { 0x00ffd4, 14333 }, + { 0x00ffd5, 14337 }, + { 0x00ffd6, 14341 }, + { 0x00ffd7, 14345 }, + { 0x00ffd8, 14349 }, + { 0x00ffd9, 14353 }, + { 0x00ffda, 14357 }, + { 0x00ffdb, 14361 }, + { 0x00ffdc, 14365 }, + { 0x00ffdd, 14369 }, + { 0x00ffde, 14373 }, + { 0x00ffdf, 14377 }, + { 0x00ffe0, 14381 }, + { 0x00ffe1, 14385 }, + { 0x00ffe2, 14393 }, + { 0x00ffe3, 14401 }, + { 0x00ffe4, 14411 }, + { 0x00ffe5, 14421 }, + { 0x00ffe6, 14431 }, + { 0x00ffe7, 14442 }, + { 0x00ffe8, 14449 }, + { 0x00ffe9, 14456 }, + { 0x00ffea, 14462 }, + { 0x00ffeb, 14468 }, + { 0x00ffec, 14476 }, + { 0x00ffed, 14484 }, + { 0x00ffee, 14492 }, + { 0x00ffff, 14500 }, + { 0xffffff, 14507 } +}; + +static const gdk_key gdk_keys_by_name[] = { + { 0x000030, 140 }, + { 0x000031, 142 }, + { 0x000032, 144 }, + { 0x000033, 146 }, + { 0x00fd10, 11341 }, + { 0x00fd0e, 11314 }, + { 0x00fd05, 11213 }, + { 0x00fd19, 11444 }, + { 0x00fd15, 11401 }, + { 0x00fd0f, 11324 }, + { 0x00fd1c, 11492 }, + { 0x00fd1a, 11462 }, + { 0x00fd01, 11160 }, + { 0x00fd1e, 11527 }, + { 0x00fd06, 11226 }, + { 0x00fd07, 11240 }, + { 0x00fd1b, 11478 }, + { 0x00fd02, 11175 }, + { 0x00fd13, 11380 }, + { 0x00fd12, 11370 }, + { 0x00fd11, 11356 }, + { 0x00fd04, 11202 }, + { 0x00fd0a, 11277 }, + { 0x00fd0b, 11286 }, + { 0x00fd0c, 11295 }, + { 0x00fd16, 11411 }, + { 0x00fd1d, 11510 }, + { 0x00fd09, 11267 }, + { 0x00fd18, 11432 }, + { 0x00fd08, 11256 }, + { 0x00fd03, 11190 }, + { 0x00fd14, 11391 }, + { 0x00fd17, 11421 }, + { 0x00fd0d, 11304 }, + { 0x000034, 148 }, + { 0x000035, 150 }, + { 0x000036, 152 }, + { 0x000037, 154 }, + { 0x000038, 156 }, + { 0x000039, 158 }, + { 0x000041, 207 }, + { 0x0000c6, 787 }, + { 0x0000c1, 744 }, + { 0x0001c3, 1473 }, + { 0x00fe70, 12471 }, + { 0x00fe71, 12486 }, + { 0x0000c2, 751 }, + { 0x0000c4, 770 }, + { 0x0000c0, 737 }, + { 0x00ffe9, 14456 }, + { 0x00ffea, 14462 }, + { 0x0003c0, 2068 }, + { 0x0001a1, 1281 }, + { 0x0005d9, 3221 }, + { 0x0005c7, 3008 }, + { 0x0005e9, 3360 }, + { 0x0005c8, 3020 }, + { 0x0005ac, 2848 }, + { 0x0005d6, 3188 }, + { 0x0005cf, 3107 }, + { 0x0005ef, 3451 }, + { 0x0005ec, 3406 }, + { 0x0005ee, 3438 }, + { 0x0005eb, 3390 }, + { 0x0005e1, 3260 }, + { 0x0005da, 3232 }, + { 0x0005e7, 3328 }, + { 0x0005cd, 3084 }, + { 0x0005c1, 2899 }, + { 0x0005c3, 2931 }, + { 0x0005c4, 2950 }, + { 0x0005c6, 2990 }, + { 0x0005c5, 2968 }, + { 0x0005e7, 3338 }, + { 0x0005cc, 3072 }, + { 0x0005e3, 3282 }, + { 0x0005f0, 3464 }, + { 0x0005ed, 3422 }, + { 0x0005ce, 3095 }, + { 0x0005e4, 3293 }, + { 0x0005c2, 2912 }, + { 0x0005e5, 3304 }, + { 0x0005e6, 3316 }, + { 0x0005e2, 3271 }, + { 0x0005bf, 2878 }, + { 0x0005d1, 3130 }, + { 0x0005d5, 3177 }, + { 0x0005d3, 3152 }, + { 0x0005bb, 2861 }, + { 0x0005f1, 3477 }, + { 0x0005d4, 3164 }, + { 0x0005f2, 3491 }, + { 0x00ff7e, 13847 }, + { 0x0005d7, 3199 }, + { 0x0005e0, 3245 }, + { 0x0005ca, 3049 }, + { 0x0005c9, 3031 }, + { 0x0005d0, 3118 }, + { 0x0005cb, 3060 }, + { 0x0005e8, 3349 }, + { 0x0005ea, 3379 }, + { 0x0005d8, 3210 }, + { 0x0005d2, 3140 }, + { 0x0000c5, 781 }, + { 0x0000c3, 763 }, + { 0x00fe7a, 12652 }, + { 0x000042, 209 }, + { 0x00ff08, 13264 }, + { 0x00ff58, 13775 }, + { 0x00fe74, 12544 }, + { 0x00ff6b, 13841 }, + { 0x0006be, 4011 }, + { 0x0006ae, 3729 }, + { 0x000043, 211 }, + { 0x0002c5, 1826 }, + { 0x0001c6, 1487 }, + { 0x00ff69, 13829 }, + { 0x00ffe5, 14421 }, + { 0x0001c8, 1494 }, + { 0x0000c7, 790 }, + { 0x0002c6, 1836 }, + { 0x00ff0b, 13287 }, + { 0x00ff37, 13581 }, + { 0x0020a1, 11037 }, + { 0x00ffe3, 14401 }, + { 0x00ffe4, 14411 }, + { 0x0020a2, 11047 }, + { 0x0006e1, 4474 }, + { 0x0006e2, 4485 }, + { 0x0006fe, 4836 }, + { 0x0006e4, 4510 }, + { 0x0006bf, 4031 }, + { 0x0006fc, 4810 }, + { 0x0006e6, 4534 }, + { 0x0006ec, 4610 }, + { 0x0006ed, 4622 }, + { 0x0006ee, 4634 }, + { 0x0006f2, 4681 }, + { 0x0006f3, 4693 }, + { 0x0006e7, 4546 }, + { 0x0006e8, 4559 }, + { 0x0006ff, 4849 }, + { 0x0006e9, 4571 }, + { 0x0006e5, 4522 }, + { 0x0006b3, 3812 }, + { 0x0006b8, 3911 }, + { 0x0006eb, 4598 }, + { 0x0006b9, 3934 }, + { 0x0006ba, 3959 }, + { 0x0006ef, 4646 }, + { 0x0006f0, 4657 }, + { 0x0006fb, 4797 }, + { 0x0006fd, 4821 }, + { 0x0006ea, 4582 }, + { 0x0006f8, 4753 }, + { 0x0006f4, 4705 }, + { 0x0006e3, 4497 }, + { 0x0006f5, 4717 }, + { 0x0006f7, 4741 }, + { 0x0006f1, 4669 }, + { 0x0006f9, 4771 }, + { 0x0006e0, 4462 }, + { 0x0006fa, 4785 }, + { 0x0006f6, 4728 }, + { 0x0006c1, 4069 }, + { 0x0006c2, 4080 }, + { 0x0006de, 4431 }, + { 0x0006c4, 4105 }, + { 0x0006af, 3749 }, + { 0x0006dc, 4405 }, + { 0x0006c6, 4129 }, + { 0x0006cc, 4205 }, + { 0x0006cd, 4217 }, + { 0x0006ce, 4229 }, + { 0x0006d2, 4276 }, + { 0x0006d3, 4288 }, + { 0x0006c7, 4141 }, + { 0x0006c8, 4154 }, + { 0x0006df, 4444 }, + { 0x0006c9, 4166 }, + { 0x0006c5, 4117 }, + { 0x0006a3, 3530 }, + { 0x0006a8, 3629 }, + { 0x0006cb, 4193 }, + { 0x0006a9, 3652 }, + { 0x0006aa, 3677 }, + { 0x0006cf, 4241 }, + { 0x0006d0, 4252 }, + { 0x0006db, 4392 }, + { 0x0006dd, 4416 }, + { 0x0006ca, 4177 }, + { 0x0006d8, 4348 }, + { 0x0006d4, 4300 }, + { 0x0006c3, 4092 }, + { 0x0006d5, 4312 }, + { 0x0006d7, 4336 }, + { 0x0006d1, 4264 }, + { 0x0006d9, 4366 }, + { 0x0006c0, 4057 }, + { 0x0006da, 4380 }, + { 0x0006d6, 4323 }, + { 0x000044, 213 }, + { 0x0001cf, 1516 }, + { 0x00ffff, 14500 }, + { 0x0020ab, 11142 }, + { 0x00ff54, 13737 }, + { 0x0001d0, 1523 }, + { 0x000045, 215 }, + { 0x0003bd, 2060 }, + { 0x0000d0, 873 }, + { 0x0003cc, 2084 }, + { 0x0000c9, 806 }, + { 0x0001cc, 1509 }, + { 0x0000ca, 813 }, + { 0x0020a0, 11029 }, + { 0x0000cb, 825 }, + { 0x0000c8, 799 }, + { 0x00ff2f, 13488 }, + { 0x00ff30, 13499 }, + { 0x0003aa, 1987 }, + { 0x00ff57, 13771 }, + { 0x0001ca, 1501 }, + { 0x00ff1b, 13326 }, + { 0x0000d0, 877 }, + { 0x0020ac, 11151 }, + { 0x00ff62, 13794 }, + { 0x000046, 217 }, + { 0x00ffbe, 14254 }, + { 0x00ffc7, 14281 }, + { 0x00ffc8, 14285 }, + { 0x00ffc9, 14289 }, + { 0x00ffca, 14293 }, + { 0x00ffcb, 14297 }, + { 0x00ffcc, 14301 }, + { 0x00ffcd, 14305 }, + { 0x00ffce, 14309 }, + { 0x00ffcf, 14313 }, + { 0x00ffd0, 14317 }, + { 0x00ffbf, 14257 }, + { 0x00ffd1, 14321 }, + { 0x00ffd2, 14325 }, + { 0x00ffd3, 14329 }, + { 0x00ffd4, 14333 }, + { 0x00ffd5, 14337 }, + { 0x00ffd6, 14341 }, + { 0x00ffd7, 14345 }, + { 0x00ffd8, 14349 }, + { 0x00ffd9, 14353 }, + { 0x00ffda, 14357 }, + { 0x00ffc0, 14260 }, + { 0x00ffdb, 14361 }, + { 0x00ffdc, 14365 }, + { 0x00ffdd, 14369 }, + { 0x00ffde, 14373 }, + { 0x00ffdf, 14377 }, + { 0x00ffe0, 14381 }, + { 0x00ffc1, 14263 }, + { 0x00ffc2, 14266 }, + { 0x00ffc3, 14269 }, + { 0x00ffc4, 14272 }, + { 0x00ffc5, 14275 }, + { 0x00ffc6, 14278 }, + { 0x0020a3, 11060 }, + { 0x00ff68, 13824 }, + { 0x00fed0, 12671 }, + { 0x000047, 219 }, + { 0x0002d5, 1848 }, + { 0x0002ab, 1759 }, + { 0x0003ab, 1995 }, + { 0x0002d8, 1858 }, + { 0x0007c1, 5316 }, + { 0x0007a1, 4867 }, + { 0x0007c2, 5328 }, + { 0x0007d7, 5564 }, + { 0x0007c4, 5351 }, + { 0x0007c5, 5363 }, + { 0x0007a2, 4885 }, + { 0x0007c7, 5388 }, + { 0x0007a3, 4905 }, + { 0x0007c3, 5339 }, + { 0x0007c9, 5410 }, + { 0x0007a4, 4921 }, + { 0x0007a5, 4957 }, + { 0x0007a5, 4938 }, + { 0x0007ca, 5421 }, + { 0x0007cb, 5433 }, + { 0x0007cb, 5446 }, + { 0x0007cc, 5458 }, + { 0x0007cd, 5467 }, + { 0x0007d9, 5584 }, + { 0x0007ab, 5039 }, + { 0x0007cf, 5485 }, + { 0x0007a7, 4977 }, + { 0x0007d6, 5554 }, + { 0x0007d0, 5499 }, + { 0x0007d8, 5574 }, + { 0x0007d1, 5508 }, + { 0x0007d2, 5518 }, + { 0x0007d4, 5530 }, + { 0x0007c8, 5398 }, + { 0x0007d5, 5540 }, + { 0x0007a8, 4997 }, + { 0x0007a9, 5017 }, + { 0x0007ce, 5476 }, + { 0x0007c6, 5377 }, + { 0x0007ae, 5057 }, + { 0x0007e1, 5596 }, + { 0x0007b1, 5093 }, + { 0x0007e2, 5608 }, + { 0x0007f7, 5866 }, + { 0x0007e4, 5631 }, + { 0x0007e5, 5643 }, + { 0x0007b2, 5111 }, + { 0x0007e7, 5668 }, + { 0x0007b3, 5131 }, + { 0x0007f3, 5810 }, + { 0x0007e3, 5619 }, + { 0x0007af, 5078 }, + { 0x0007e9, 5690 }, + { 0x0007b4, 5147 }, + { 0x0007b6, 5183 }, + { 0x0007b5, 5164 }, + { 0x0007ea, 5701 }, + { 0x0007eb, 5713 }, + { 0x0007eb, 5726 }, + { 0x0007ec, 5738 }, + { 0x0007ed, 5747 }, + { 0x0007f9, 5886 }, + { 0x0007bb, 5298 }, + { 0x0007ef, 5765 }, + { 0x0007b7, 5208 }, + { 0x0007f6, 5856 }, + { 0x0007f0, 5779 }, + { 0x0007f8, 5876 }, + { 0x0007f1, 5788 }, + { 0x0007f2, 5798 }, + { 0x00ff7e, 13861 }, + { 0x0007f4, 5832 }, + { 0x0007e8, 5678 }, + { 0x0007f5, 5842 }, + { 0x0007b8, 5228 }, + { 0x0007ba, 5270 }, + { 0x0007b9, 5248 }, + { 0x0007ee, 5756 }, + { 0x0007e6, 5657 }, + { 0x000048, 221 }, + { 0x00ff31, 13511 }, + { 0x000ebf, 10068 }, + { 0x000ec0, 10077 }, + { 0x000ef6, 10909 }, + { 0x000ef7, 10922 }, + { 0x00ff39, 13605 }, + { 0x000eba, 10001 }, + { 0x000ea7, 9694 }, + { 0x000ec4, 10118 }, + { 0x000ec3, 10108 }, + { 0x000ed1, 10248 }, + { 0x00ff33, 13531 }, + { 0x00ff34, 13542 }, + { 0x000ebe, 10055 }, + { 0x000ed3, 10268 }, + { 0x000eb7, 9957 }, + { 0x000eea, 10673 }, + { 0x000eda, 10389 }, + { 0x000eee, 10735 }, + { 0x000ee8, 10643 }, + { 0x000ee9, 10658 }, + { 0x000eeb, 10688 }, + { 0x000ed4, 10277 }, + { 0x000ed6, 10314 }, + { 0x000ef9, 10953 }, + { 0x000ee3, 10561 }, + { 0x000ed7, 10334 }, + { 0x000ed9, 10369 }, + { 0x000ed8, 10349 }, + { 0x000ef8, 10936 }, + { 0x000eed, 10719 }, + { 0x000ee4, 10576 }, + { 0x000ee5, 10591 }, + { 0x000edb, 10405 }, + { 0x000ee2, 10541 }, + { 0x000edc, 10420 }, + { 0x000edd, 10441 }, + { 0x000ee1, 10520 }, + { 0x000ede, 10461 }, + { 0x000edf, 10481 }, + { 0x000ee0, 10500 }, + { 0x000ee6, 10610 }, + { 0x000ed5, 10293 }, + { 0x000ee7, 10624 }, + { 0x000eec, 10704 }, + { 0x000efa, 10980 }, + { 0x00ff35, 13555 }, + { 0x00ff38, 13591 }, + { 0x000eb8, 9970 }, + { 0x000ebb, 10014 }, + { 0x000ea1, 9594 }, + { 0x000ea3, 9627 }, + { 0x000ef3, 10839 }, + { 0x000eb1, 9867 }, + { 0x000ea4, 9645 }, + { 0x000ea6, 9676 }, + { 0x000ea5, 9658 }, + { 0x000ec7, 10148 }, + { 0x000eca, 10178 }, + { 0x000ef2, 10824 }, + { 0x000ebd, 10041 }, + { 0x000eb2, 9880 }, + { 0x000eb4, 9911 }, + { 0x00ff3b, 13634 }, + { 0x00ff3a, 13618 }, + { 0x000ea9, 9727 }, + { 0x000eb0, 9849 }, + { 0x000eaa, 9740 }, + { 0x000eab, 9759 }, + { 0x000eaf, 9830 }, + { 0x000eac, 9777 }, + { 0x000ead, 9795 }, + { 0x000eae, 9812 }, + { 0x000eef, 10750 }, + { 0x00ff36, 13567 }, + { 0x000eb5, 9928 }, + { 0x00ff3f, 13703 }, + { 0x000ea8, 9708 }, + { 0x000eb9, 9983 }, + { 0x000ea2, 9608 }, + { 0x000eb3, 9893 }, + { 0x000eb6, 9940 }, + { 0x00ff32, 13518 }, + { 0x000ef0, 10774 }, + { 0x000ef4, 10864 }, + { 0x000ef1, 10799 }, + { 0x000ebc, 10028 }, + { 0x000ecc, 10198 }, + { 0x000ec8, 10157 }, + { 0x000ec9, 10167 }, + { 0x000ece, 10218 }, + { 0x000ecd, 10207 }, + { 0x000ecf, 10228 }, + { 0x000ec1, 10087 }, + { 0x000ec2, 10097 }, + { 0x000ec6, 10138 }, + { 0x000ec5, 10127 }, + { 0x000ed2, 10258 }, + { 0x000ecb, 10188 }, + { 0x000ed0, 10238 }, + { 0x000ef5, 10890 }, + { 0x00ff7e, 13874 }, + { 0x00ff29, 13428 }, + { 0x0002a6, 1737 }, + { 0x00ff7e, 13888 }, + { 0x00ff6a, 13836 }, + { 0x00ff23, 13358 }, + { 0x00ff23, 13365 }, + { 0x00ff25, 13384 }, + { 0x00ff27, 13402 }, + { 0x00ff50, 13718 }, + { 0x0002a1, 1729 }, + { 0x00ffed, 14484 }, + { 0x00ffee, 14492 }, + { 0x000049, 223 }, + { 0x00fe33, 12190 }, + { 0x00fe30, 12123 }, + { 0x00fe31, 12148 }, + { 0x00fe32, 12176 }, + { 0x00fe34, 12208 }, + { 0x00fe2f, 12102 }, + { 0x00fe2c, 12040 }, + { 0x00fe2d, 12061 }, + { 0x00fe2e, 12083 }, + { 0x00fe0c, 11715 }, + { 0x00fe0d, 11731 }, + { 0x00fe06, 11614 }, + { 0x00fe07, 11630 }, + { 0x00ff7e, 13902 }, + { 0x00fe0e, 11752 }, + { 0x00fe0f, 11767 }, + { 0x00fe20, 11787 }, + { 0x00fe02, 11547 }, + { 0x00fe04, 11581 }, + { 0x00fe05, 11598 }, + { 0x00fe03, 11564 }, + { 0x00fe01, 11538 }, + { 0x00fe22, 11817 }, + { 0x00fe21, 11800 }, + { 0x00fe08, 11645 }, + { 0x00fe09, 11660 }, + { 0x00fe24, 11856 }, + { 0x00fe23, 11836 }, + { 0x00fe25, 11878 }, + { 0x00fe26, 11901 }, + { 0x00fe0a, 11680 }, + { 0x00fe0b, 11695 }, + { 0x00fe2b, 12015 }, + { 0x00fe29, 11966 }, + { 0x00fe2a, 11990 }, + { 0x00fe27, 11925 }, + { 0x00fe28, 11945 }, + { 0x0002a9, 1749 }, + { 0x0000cd, 843 }, + { 0x0000ce, 850 }, + { 0x0000cf, 862 }, + { 0x0000cc, 836 }, + { 0x0003cf, 2094 }, + { 0x00ff63, 13802 }, + { 0x0003c7, 2076 }, + { 0x0003a5, 1971 }, + { 0x00004a, 225 }, + { 0x0002ac, 1766 }, + { 0x00004b, 227 }, + { 0x00ffb0, 14195 }, + { 0x00ffb1, 14200 }, + { 0x00ffb2, 14205 }, + { 0x00ffb3, 14210 }, + { 0x00ffb4, 14215 }, + { 0x00ffb5, 14220 }, + { 0x00ffb6, 14225 }, + { 0x00ffb7, 14230 }, + { 0x00ffb8, 14235 }, + { 0x00ffb9, 14240 }, + { 0x00ffab, 14142 }, + { 0x00ff9d, 14101 }, + { 0x00ffae, 14174 }, + { 0x00ff9f, 14120 }, + { 0x00ffaf, 14185 }, + { 0x00ff99, 14045 }, + { 0x00ff9c, 14094 }, + { 0x00ff8d, 13981 }, + { 0x00ffbd, 14245 }, + { 0x00ff91, 13990 }, + { 0x00ff92, 13996 }, + { 0x00ff93, 14002 }, + { 0x00ff94, 14008 }, + { 0x00ff95, 14014 }, + { 0x00ff9e, 14110 }, + { 0x00ff96, 14022 }, + { 0x00ffaa, 14130 }, + { 0x00ff9b, 14086 }, + { 0x00ff9b, 14073 }, + { 0x00ff9a, 14053 }, + { 0x00ff9a, 14064 }, + { 0x00ff98, 14036 }, + { 0x00ffac, 14149 }, + { 0x00ff80, 13965 }, + { 0x00ffad, 14162 }, + { 0x00ff89, 13974 }, + { 0x00ff97, 14030 }, + { 0x00ff2d, 13467 }, + { 0x00ff2e, 13477 }, + { 0x00ff21, 13343 }, + { 0x00ff26, 13393 }, + { 0x0003d3, 2119 }, + { 0x000eff, 11001 }, + { 0x00004c, 229 }, + { 0x0001c5, 1480 }, + { 0x00fed4, 12732 }, + { 0x0001a5, 1303 }, + { 0x0003a6, 1978 }, + { 0x00ff51, 13723 }, + { 0x00ff0a, 13278 }, + { 0x0020a4, 11071 }, + { 0x0001a3, 1295 }, + { 0x00004d, 231 }, + { 0x0006b5, 3849 }, + { 0x0006b2, 3798 }, + { 0x0006bc, 3997 }, + { 0x0006a5, 3567 }, + { 0x0006a2, 3516 }, + { 0x0006ac, 3715 }, + { 0x00ff2c, 13460 }, + { 0x00ff67, 13819 }, + { 0x00ffe7, 14442 }, + { 0x00ffe8, 14449 }, + { 0x0020a5, 11080 }, + { 0x00ff7e, 13918 }, + { 0x00fe77, 12597 }, + { 0x00fe76, 12580 }, + { 0x00ff22, 13349 }, + { 0x00ff20, 13333 }, + { 0x00ff3d, 13667 }, + { 0x00004e, 233 }, + { 0x0001d1, 1531 }, + { 0x0020a6, 11089 }, + { 0x0001d2, 1538 }, + { 0x0003d1, 2102 }, + { 0x0020aa, 11128 }, + { 0x00ff56, 13766 }, + { 0x00fed2, 12712 }, + { 0x0000d1, 881 }, + { 0x00ff7f, 13956 }, + { 0x00004f, 235 }, + { 0x0013bc, 11012 }, + { 0x0000d3, 895 }, + { 0x0000d4, 902 }, + { 0x0000d6, 921 }, + { 0x0001d5, 1545 }, + { 0x0000d2, 888 }, + { 0x0003d2, 2111 }, + { 0x0000d8, 941 }, + { 0x0000d5, 914 }, + { 0x00fe78, 12620 }, + { 0x00fe79, 12636 }, + { 0x000050, 237 }, + { 0x00ff56, 13756 }, + { 0x00ff55, 13742 }, + { 0x00ff13, 13300 }, + { 0x0020a7, 11099 }, + { 0x00fefa, 13191 }, + { 0x00fee9, 12906 }, + { 0x00feea, 12922 }, + { 0x00feeb, 12938 }, + { 0x00feec, 12954 }, + { 0x00feed, 12970 }, + { 0x00fee8, 12886 }, + { 0x00feef, 13008 }, + { 0x00fef0, 13026 }, + { 0x00fef1, 13044 }, + { 0x00fef2, 13062 }, + { 0x00fef3, 13080 }, + { 0x00feee, 12986 }, + { 0x00fefb, 13210 }, + { 0x00fefc, 13230 }, + { 0x00fee3, 12807 }, + { 0x00fee6, 12851 }, + { 0x00fee7, 12868 }, + { 0x00fef5, 13116 }, + { 0x00fef6, 13130 }, + { 0x00fef7, 13144 }, + { 0x00fef8, 13158 }, + { 0x00fefd, 13250 }, + { 0x00fef4, 13098 }, + { 0x00fef9, 13172 }, + { 0x00fee0, 12769 }, + { 0x00fee1, 12782 }, + { 0x00fee2, 12796 }, + { 0x00fee4, 12820 }, + { 0x00fee5, 12835 }, + { 0x00fed1, 12692 }, + { 0x00ff3e, 13685 }, + { 0x00ff61, 13788 }, + { 0x00ff55, 13750 }, + { 0x000051, 239 }, + { 0x000052, 241 }, + { 0x0001c0, 1466 }, + { 0x0001d8, 1558 }, + { 0x0003a3, 1962 }, + { 0x00ff66, 13814 }, + { 0x00fe72, 12510 }, + { 0x00ff0d, 13293 }, + { 0x00ff53, 13731 }, + { 0x00ff24, 13377 }, + { 0x0020a8, 11110 }, + { 0x000053, 243 }, + { 0x0001a6, 1310 }, + { 0x0001a9, 1317 }, + { 0x0001aa, 1324 }, + { 0x0002de, 1877 }, + { 0x00ff14, 13306 }, + { 0x00ff60, 13781 }, + { 0x0006b1, 3786 }, + { 0x0006bf, 4045 }, + { 0x0006b8, 3923 }, + { 0x0006b9, 3947 }, + { 0x0006ba, 3972 }, + { 0x0006bb, 3984 }, + { 0x0006a1, 3504 }, + { 0x0006af, 3763 }, + { 0x0006a8, 3641 }, + { 0x0006a9, 3665 }, + { 0x0006aa, 3690 }, + { 0x0006ab, 3702 }, + { 0x00ffe1, 14385 }, + { 0x00ffe6, 14431 }, + { 0x00ffe2, 14393 }, + { 0x00ff3c, 13651 }, + { 0x00fe73, 12528 }, + { 0x00fe75, 12562 }, + { 0x00ffeb, 14468 }, + { 0x00ffec, 14476 }, + { 0x00ff15, 13318 }, + { 0x000054, 245 }, + { 0x0000de, 994 }, + { 0x00ff09, 13274 }, + { 0x0001ab, 1333 }, + { 0x0001de, 1584 }, + { 0x00fed5, 12752 }, + { 0x000ddf, 9260 }, + { 0x000dba, 8843 }, + { 0x000da8, 8607 }, + { 0x000daa, 8634 }, + { 0x000da9, 8620 }, + { 0x000dac, 8658 }, + { 0x000dae, 8683 }, + { 0x000db4, 8768 }, + { 0x000dbd, 8882 }, + { 0x000dbf, 8905 }, + { 0x000dcb, 9039 }, + { 0x000dce, 9073 }, + { 0x000da2, 8525 }, + { 0x000da5, 8566 }, + { 0x000da3, 8538 }, + { 0x000da4, 8552 }, + { 0x000da6, 8579 }, + { 0x000da1, 8514 }, + { 0x000de5, 9343 }, + { 0x000df7, 9556 }, + { 0x000df5, 9533 }, + { 0x000df6, 9544 }, + { 0x000df9, 9582 }, + { 0x000df1, 9484 }, + { 0x000df8, 9569 }, + { 0x000df3, 9510 }, + { 0x000df4, 9522 }, + { 0x000df2, 9497 }, + { 0x000df0, 9472 }, + { 0x000dcc, 9050 }, + { 0x000dc5, 8972 }, + { 0x000dc6, 8984 }, + { 0x000deb, 9424 }, + { 0x000de8, 9389 }, + { 0x000dd1, 9113 }, + { 0x000dde, 9237 }, + { 0x000de7, 9374 }, + { 0x000de9, 9400 }, + { 0x000dea, 9412 }, + { 0x000de6, 9360 }, + { 0x000dc1, 8932 }, + { 0x000da7, 8595 }, + { 0x000ded, 9458 }, + { 0x000db3, 8757 }, + { 0x000db9, 8833 }, + { 0x000dcd, 9063 }, + { 0x000dcf, 9087 }, + { 0x000dda, 9224 }, + { 0x000dbe, 8892 }, + { 0x000dbc, 8868 }, + { 0x000dc0, 8916 }, + { 0x000dbb, 8857 }, + { 0x000dc3, 8953 }, + { 0x000dc4, 8964 }, + { 0x000dd0, 9102 }, + { 0x000dd2, 9129 }, + { 0x000de1, 9281 }, + { 0x000de4, 9323 }, + { 0x000de3, 9304 }, + { 0x000dd3, 9141 }, + { 0x000de0, 9270 }, + { 0x000dd4, 9153 }, + { 0x000dd5, 9164 }, + { 0x000de2, 9293 }, + { 0x000dd8, 9201 }, + { 0x000dd6, 9176 }, + { 0x000dd7, 9188 }, + { 0x000dd9, 9212 }, + { 0x000dc9, 9016 }, + { 0x000dc8, 9004 }, + { 0x000dab, 8648 }, + { 0x000dca, 9028 }, + { 0x000dec, 9441 }, + { 0x000db1, 8722 }, + { 0x000db2, 8741 }, + { 0x000db7, 8804 }, + { 0x000db0, 8709 }, + { 0x000db8, 8819 }, + { 0x000db6, 8790 }, + { 0x000daf, 8696 }, + { 0x000db5, 8779 }, + { 0x000dc7, 8992 }, + { 0x000dc2, 8942 }, + { 0x000dad, 8671 }, + { 0x0000de, 1000 }, + { 0x00ff2b, 13452 }, + { 0x0003ac, 2004 }, + { 0x000055, 247 }, + { 0x0000da, 957 }, + { 0x0002dd, 1870 }, + { 0x0000db, 964 }, + { 0x0000dc, 976 }, + { 0x0001db, 1571 }, + { 0x0000d9, 950 }, + { 0x0006b6, 3863 }, + { 0x0006b4, 3824 }, + { 0x0006b7, 3886 }, + { 0x0006a6, 3581 }, + { 0x0006a4, 3542 }, + { 0x0006a7, 3604 }, + { 0x0006b6, 3875 }, + { 0x0006b4, 3837 }, + { 0x0006b7, 3899 }, + { 0x0006a6, 3593 }, + { 0x0006a4, 3555 }, + { 0x0006a7, 3617 }, + { 0x0003de, 2143 }, + { 0x00ff65, 13809 }, + { 0x0003d9, 2128 }, + { 0x00ff52, 13728 }, + { 0x0001d9, 1565 }, + { 0x0003dd, 2136 }, + { 0x000056, 249 }, + { 0xffffff, 14507 }, + { 0x000057, 251 }, + { 0x0020a9, 11120 }, + { 0x000058, 253 }, + { 0x000059, 255 }, + { 0x0000dd, 987 }, + { 0x0013be, 11018 }, + { 0x00005a, 257 }, + { 0x0001af, 1354 }, + { 0x0001ac, 1340 }, + { 0x0001ae, 1347 }, + { 0x00ff28, 13420 }, + { 0x00ff2a, 13436 }, + { 0x000061, 333 }, + { 0x0000e1, 1020 }, + { 0x0001ff, 1720 }, + { 0x0001e3, 1600 }, + { 0x0000e2, 1027 }, + { 0x0000b4, 612 }, + { 0x0000e4, 1046 }, + { 0x0000e6, 1063 }, + { 0x0000e0, 1013 }, + { 0x0003e0, 2151 }, + { 0x000026, 48 }, + { 0x0001b1, 1364 }, + { 0x000027, 58 }, + { 0x0008c8, 6376 }, + { 0x0000e5, 1057 }, + { 0x00005e, 294 }, + { 0x00007e, 410 }, + { 0x00002a, 101 }, + { 0x000040, 204 }, + { 0x0000e3, 1039 }, + { 0x000062, 335 }, + { 0x00005c, 271 }, + { 0x000af4, 7692 }, + { 0x00007c, 395 }, + { 0x0009df, 6562 }, + { 0x0008a5, 5952 }, + { 0x0008ac, 6062 }, + { 0x0008a8, 5995 }, + { 0x0008b2, 6166 }, + { 0x0008ae, 6091 }, + { 0x0008aa, 6030 }, + { 0x0008b6, 6253 }, + { 0x0009f6, 6770 }, + { 0x0008b4, 6209 }, + { 0x00007b, 385 }, + { 0x00007d, 399 }, + { 0x00005b, 259 }, + { 0x00005d, 281 }, + { 0x0001a2, 1289 }, + { 0x0000a6, 472 }, + { 0x000063, 337 }, + { 0x0002e5, 1889 }, + { 0x0001e6, 1614 }, + { 0x000ab8, 6996 }, + { 0x000afc, 7801 }, + { 0x0001b7, 1401 }, + { 0x0001e8, 1621 }, + { 0x0000e7, 1066 }, + { 0x0002e6, 1899 }, + { 0x0000b8, 646 }, + { 0x0000a2, 445 }, + { 0x0009e1, 6581 }, + { 0x000af3, 7682 }, + { 0x000bcf, 7950 }, + { 0x000aec, 7630 }, + { 0x00003a, 160 }, + { 0x00002c, 115 }, + { 0x0000a9, 500 }, + { 0x0009e4, 6600 }, + { 0x0009ee, 6668 }, + { 0x0000a4, 459 }, + { 0x000aff, 7845 }, + { 0x000064, 339 }, + { 0x000af1, 7662 }, + { 0x0001ef, 1643 }, + { 0x00fe56, 12290 }, + { 0x00fe58, 12319 }, + { 0x00fe51, 12229 }, + { 0x00fe60, 12437 }, + { 0x00fe55, 12279 }, + { 0x00fe5a, 12351 }, + { 0x00fe5b, 12362 }, + { 0x00fe52, 12240 }, + { 0x00fe57, 12304 }, + { 0x00fe59, 12334 }, + { 0x00fe50, 12218 }, + { 0x00fe61, 12451 }, + { 0x00fe62, 12461 }, + { 0x00fe5d, 12387 }, + { 0x00fe54, 12267 }, + { 0x00fe5c, 12375 }, + { 0x00fe5f, 12415 }, + { 0x00fe53, 12256 }, + { 0x00fe5e, 12397 }, + { 0x000abd, 7028 }, + { 0x0000b0, 569 }, + { 0x0000a8, 490 }, + { 0x000aed, 7635 }, + { 0x000aa5, 6822 }, + { 0x0000f7, 1204 }, + { 0x000024, 33 }, + { 0x000aaf, 6899 }, + { 0x0001bd, 1437 }, + { 0x000af2, 7669 }, + { 0x000afe, 7826 }, + { 0x0008fe, 6552 }, + { 0x000ba8, 7873 }, + { 0x000bd6, 7965 }, + { 0x000bc4, 7915 }, + { 0x000bc2, 7899 }, + { 0x0001f0, 1650 }, + { 0x000065, 341 }, + { 0x0003ec, 2167 }, + { 0x0000e9, 1082 }, + { 0x0001ec, 1636 }, + { 0x0000ea, 1089 }, + { 0x0000eb, 1101 }, + { 0x0000e8, 1075 }, + { 0x000aae, 6890 }, + { 0x000aa3, 6804 }, + { 0x000aa4, 6813 }, + { 0x0003ba, 2036 }, + { 0x000aa9, 6864 }, + { 0x000ade, 7409 }, + { 0x000adf, 7424 }, + { 0x000ace, 7191 }, + { 0x000acf, 7204 }, + { 0x000aa1, 6788 }, + { 0x000aaa, 6871 }, + { 0x000ae6, 7531 }, + { 0x000ae7, 7550 }, + { 0x0003bf, 2064 }, + { 0x000ae0, 7437 }, + { 0x000ae1, 7454 }, + { 0x000aa2, 6796 }, + { 0x0001ea, 1628 }, + { 0x00003d, 181 }, + { 0x0000f0, 1149 }, + { 0x000021, 6 }, + { 0x0000a1, 434 }, + { 0x000066, 343 }, + { 0x000af8, 7740 }, + { 0x0009e3, 6597 }, + { 0x000abb, 7003 }, + { 0x000adc, 7368 }, + { 0x000adb, 7351 }, + { 0x000add, 7388 }, + { 0x000ae9, 7585 }, + { 0x000ae8, 7567 }, + { 0x000ac5, 7089 }, + { 0x000ab7, 6985 }, + { 0x000ab5, 6965 }, + { 0x0008f6, 6514 }, + { 0x000067, 345 }, + { 0x0002f5, 1911 }, + { 0x0002bb, 1807 }, + { 0x0003bb, 2044 }, + { 0x0002f8, 1921 }, + { 0x000060, 317 }, + { 0x00003e, 187 }, + { 0x0008be, 6315 }, + { 0x0000ab, 522 }, + { 0x0000bb, 676 }, + { 0x000068, 347 }, + { 0x000aa8, 6854 }, + { 0x0002b6, 1786 }, + { 0x000aee, 7643 }, + { 0x000ce0, 8033 }, + { 0x000cf2, 8350 }, + { 0x000ce1, 8046 }, + { 0x000ce1, 8057 }, + { 0x000ce7, 8169 }, + { 0x000ce3, 8096 }, + { 0x000ce3, 8109 }, + { 0x000cdf, 8012 }, + { 0x000cea, 8226 }, + { 0x000ced, 8268 }, + { 0x000cef, 8295 }, + { 0x000cf3, 8362 }, + { 0x000cf5, 8387 }, + { 0x000cf5, 8404 }, + { 0x000ce2, 8069 }, + { 0x000ce2, 8082 }, + { 0x000ce4, 8123 }, + { 0x000ce7, 8181 }, + { 0x000ceb, 8243 }, + { 0x000cf7, 8445 }, + { 0x000cec, 8255 }, + { 0x000cee, 8284 }, + { 0x000cf0, 8311 }, + { 0x000cf4, 8377 }, + { 0x000cf7, 8456 }, + { 0x000cf8, 8468 }, + { 0x000cf1, 8322 }, + { 0x000cf1, 8336 }, + { 0x000cf9, 8480 }, + { 0x000cfa, 8492 }, + { 0x000cfa, 8503 }, + { 0x000ce8, 8192 }, + { 0x000ce8, 8203 }, + { 0x000ce5, 8133 }, + { 0x000ce9, 8215 }, + { 0x000cf6, 8421 }, + { 0x000cf6, 8433 }, + { 0x000ce6, 8144 }, + { 0x000ce6, 8156 }, + { 0x000ada, 7342 }, + { 0x0008a3, 5925 }, + { 0x0009ef, 6682 }, + { 0x0009f0, 6697 }, + { 0x0009f1, 6712 }, + { 0x0009f2, 6727 }, + { 0x0009f3, 6742 }, + { 0x0002b1, 1778 }, + { 0x0009e2, 6594 }, + { 0x0000ad, 544 }, + { 0x000069, 349 }, + { 0x0000ed, 1119 }, + { 0x0000ee, 1126 }, + { 0x0008cf, 6418 }, + { 0x0000ef, 1138 }, + { 0x0002b9, 1798 }, + { 0x0008cd, 6401 }, + { 0x0000ec, 1112 }, + { 0x0003ef, 2177 }, + { 0x0008ce, 6410 }, + { 0x0008da, 6436 }, + { 0x0008db, 6447 }, + { 0x0008c2, 6361 }, + { 0x0008bf, 6332 }, + { 0x0008dc, 6456 }, + { 0x0003e7, 2159 }, + { 0x0003b5, 2020 }, + { 0x00006a, 351 }, + { 0x0002bc, 1814 }, + { 0x000bca, 7934 }, + { 0x00006b, 353 }, + { 0x0004b1, 2439 }, + { 0x0004c1, 2563 }, + { 0x0004b4, 2460 }, + { 0x0004cc, 2669 }, + { 0x0004ca, 2653 }, + { 0x0004cd, 2685 }, + { 0x0004cb, 2661 }, + { 0x0004ce, 2693 }, + { 0x0004cc, 2677 }, + { 0x0004b2, 2446 }, + { 0x0004b6, 2474 }, + { 0x0004b9, 2498 }, + { 0x0004b7, 2482 }, + { 0x0004ba, 2506 }, + { 0x0004b8, 2490 }, + { 0x0004cf, 2701 }, + { 0x0004d2, 2725 }, + { 0x0004d0, 2709 }, + { 0x0004d3, 2733 }, + { 0x0004d1, 2717 }, + { 0x0004dd, 2813 }, + { 0x0004c5, 2613 }, + { 0x0004c8, 2637 }, + { 0x0004c6, 2621 }, + { 0x0004c9, 2645 }, + { 0x0004c7, 2629 }, + { 0x0004b5, 2467 }, + { 0x0004d7, 2765 }, + { 0x0004da, 2789 }, + { 0x0004d8, 2773 }, + { 0x0004db, 2797 }, + { 0x0004d9, 2781 }, + { 0x0004bb, 2514 }, + { 0x0004be, 2539 }, + { 0x0004bc, 2522 }, + { 0x0004bf, 2547 }, + { 0x0004bd, 2531 }, + { 0x0004c0, 2555 }, + { 0x0004c3, 2597 }, + { 0x0004c1, 2572 }, + { 0x0004c4, 2605 }, + { 0x0004c2, 2580 }, + { 0x0004c2, 2589 }, + { 0x0004b3, 2453 }, + { 0x0004dc, 2805 }, + { 0x0004a6, 2340 }, + { 0x0004d4, 2741 }, + { 0x0004d6, 2757 }, + { 0x0004d5, 2749 }, + { 0x0004a7, 2348 }, + { 0x0004a3, 2277 }, + { 0x0004a4, 2297 }, + { 0x0004a5, 2308 }, + { 0x0004aa, 2369 }, + { 0x0004a1, 2243 }, + { 0x0004a8, 2355 }, + { 0x0004a5, 2325 }, + { 0x0004ab, 2376 }, + { 0x0004a2, 2257 }, + { 0x00ff7e, 13930 }, + { 0x0004af, 2407 }, + { 0x0004af, 2416 }, + { 0x0004a9, 2362 }, + { 0x0004ac, 2383 }, + { 0x0004ae, 2399 }, + { 0x0004ad, 2391 }, + { 0x0003a2, 1952 }, + { 0x0003f3, 2202 }, + { 0x0003a2, 1958 }, + { 0x00006c, 355 }, + { 0x0001e5, 1607 }, + { 0x000ad9, 7331 }, + { 0x0001b5, 1387 }, + { 0x0003b6, 2027 }, + { 0x000abc, 7011 }, + { 0x0008fb, 6523 }, + { 0x000ba3, 7852 }, + { 0x000ad2, 7261 }, + { 0x0008af, 6106 }, + { 0x000acc, 7156 }, + { 0x000aea, 7605 }, + { 0x0008a1, 5898 }, + { 0x000bda, 7984 }, + { 0x000ad0, 7220 }, + { 0x0009f4, 6757 }, + { 0x000bdc, 7993 }, + { 0x00003c, 176 }, + { 0x0008bc, 6292 }, + { 0x0009e5, 6603 }, + { 0x0008de, 6475 }, + { 0x0008df, 6486 }, + { 0x0009ed, 6654 }, + { 0x0009ea, 6612 }, + { 0x0001b3, 1379 }, + { 0x00006d, 357 }, + { 0x0000af, 562 }, + { 0x000af7, 7729 }, + { 0x000af0, 7649 }, + { 0x000abf, 7059 }, + { 0x0000ba, 666 }, + { 0x00002d, 121 }, + { 0x000ad6, 7315 }, + { 0x0000b5, 618 }, + { 0x0000d7, 932 }, + { 0x000af6, 7717 }, + { 0x000af5, 7704 }, + { 0x00006e, 359 }, + { 0x0008c5, 6370 }, + { 0x0001f1, 1658 }, + { 0x0001f2, 1665 }, + { 0x0003f1, 2185 }, + { 0x0009e8, 6606 }, + { 0x0000a0, 421 }, + { 0x0008bd, 6306 }, + { 0x0000ac, 536 }, + { 0x0000f1, 1153 }, + { 0x000023, 22 }, + { 0x0006b0, 3775 }, + { 0x00006f, 361 }, + { 0x0000f3, 1167 }, + { 0x0000f4, 1174 }, + { 0x0000f6, 1193 }, + { 0x0001f5, 1672 }, + { 0x0013bd, 11015 }, + { 0x0001b2, 1372 }, + { 0x0000f2, 1160 }, + { 0x0003f2, 2194 }, + { 0x000ac3, 7066 }, + { 0x000ab2, 6934 }, + { 0x0000bd, 702 }, + { 0x0000bc, 691 }, + { 0x000ab6, 6976 }, + { 0x0000b9, 654 }, + { 0x000ab0, 6915 }, + { 0x000ae2, 7473 }, + { 0x000ae5, 7522 }, + { 0x000ae4, 7504 }, + { 0x000ae3, 7488 }, + { 0x0000aa, 510 }, + { 0x0000f8, 1213 }, + { 0x0000f5, 1186 }, + { 0x000bc0, 7891 }, + { 0x00047e, 2234 }, + { 0x000070, 363 }, + { 0x0000b6, 621 }, + { 0x000028, 80 }, + { 0x000029, 90 }, + { 0x0008ef, 6496 }, + { 0x000025, 40 }, + { 0x00002e, 127 }, + { 0x0000b7, 631 }, + { 0x000afb, 7781 }, + { 0x00002b, 110 }, + { 0x0000b1, 576 }, + { 0x000ad4, 7302 }, + { 0x0004b0, 2424 }, + { 0x000aa6, 6833 }, + { 0x000071, 365 }, + { 0x000bcc, 7938 }, + { 0x00003f, 195 }, + { 0x0000bf, 724 }, + { 0x000022, 13 }, + { 0x000060, 323 }, + { 0x000027, 69 }, + { 0x000072, 367 }, + { 0x0001e0, 1593 }, + { 0x0008d6, 6428 }, + { 0x0001f8, 1685 }, + { 0x0003b3, 2011 }, + { 0x0000ae, 551 }, + { 0x000abe, 7041 }, + { 0x0008fd, 6541 }, + { 0x000ba6, 7862 }, + { 0x000ad3, 7281 }, + { 0x0008b0, 6127 }, + { 0x0008b7, 6271 }, + { 0x000acd, 7173 }, + { 0x000aeb, 7617 }, + { 0x000bd8, 7974 }, + { 0x000ad1, 7240 }, + { 0x0009f5, 6763 }, + { 0x000bfc, 8002 }, + { 0x000073, 369 }, + { 0x0001b6, 1394 }, + { 0x0001b9, 1407 }, + { 0x0001ba, 1414 }, + { 0x0002fe, 1940 }, + { 0x00ff7e, 13942 }, + { 0x000ad7, 7323 }, + { 0x0000a7, 482 }, + { 0x00003b, 166 }, + { 0x0004df, 2832 }, + { 0x000ac6, 7101 }, + { 0x000aca, 7124 }, + { 0x000aac, 6878 }, + { 0x0008c9, 6388 }, + { 0x000afd, 7807 }, + { 0x00002f, 134 }, + { 0x0009e0, 6568 }, + { 0x000020, 0 }, + { 0x0000df, 1006 }, + { 0x0000a3, 450 }, + { 0x000074, 371 }, + { 0x0001bb, 1423 }, + { 0x0001fe, 1711 }, + { 0x000af9, 7753 }, + { 0x000afa, 7763 }, + { 0x0008c0, 6341 }, + { 0x000aa7, 6844 }, + { 0x0000fe, 1264 }, + { 0x000ac4, 7076 }, + { 0x000ab4, 6953 }, + { 0x0000be, 710 }, + { 0x0000b3, 598 }, + { 0x0008a4, 5940 }, + { 0x0008ab, 6048 }, + { 0x0008a2, 5910 }, + { 0x0008a7, 5978 }, + { 0x0008b1, 6149 }, + { 0x0008ad, 6076 }, + { 0x0008a9, 6012 }, + { 0x0008b5, 6235 }, + { 0x0009f7, 6775 }, + { 0x0008b3, 6183 }, + { 0x000ac9, 7114 }, + { 0x000acb, 7138 }, + { 0x0003bc, 2053 }, + { 0x000ab3, 6943 }, + { 0x0000b2, 586 }, + { 0x000ab1, 6924 }, + { 0x000075, 373 }, + { 0x0000fa, 1227 }, + { 0x0002fd, 1933 }, + { 0x0000fb, 1234 }, + { 0x0000fc, 1246 }, + { 0x0001fb, 1698 }, + { 0x0000f9, 1220 }, + { 0x0003fe, 2226 }, + { 0x000bc6, 7925 }, + { 0x00005f, 306 }, + { 0x0008dd, 6469 }, + { 0x0003f9, 2211 }, + { 0x0008fc, 6533 }, + { 0x000ba9, 7883 }, + { 0x0009ec, 6641 }, + { 0x0009eb, 6627 }, + { 0x000bc3, 7908 }, + { 0x000bd3, 7957 }, + { 0x000bce, 7943 }, + { 0x0001f9, 1692 }, + { 0x0003fd, 2219 }, + { 0x000076, 375 }, + { 0x0008c1, 6351 }, + { 0x0009f8, 6780 }, + { 0x0008a6, 5964 }, + { 0x0004de, 2820 }, + { 0x0009e9, 6609 }, + { 0x000077, 377 }, + { 0x000078, 379 }, + { 0x000079, 381 }, + { 0x0000fd, 1257 }, + { 0x0000ff, 1270 }, + { 0x0000a5, 468 }, + { 0x00007a, 383 }, + { 0x0001bf, 1456 }, + { 0x0001bc, 1430 }, + { 0x0001be, 1449 }}; + + +#if 0 + +N_("keyboard label|BackSpace") +N_("keyboard label|Tab") +N_("keyboard label|Return") +N_("keyboard label|Pause") +N_("keyboard label|Scroll_Lock") +N_("keyboard label|Sys_Req") +N_("keyboard label|Escape") +N_("keyboard label|Multi_key") +N_("keyboard label|Home") +N_("keyboard label|Left") +N_("keyboard label|Up") +N_("keyboard label|Right") +N_("keyboard label|Down") +N_("keyboard label|Page_Up") +N_("keyboard label|Page_Down") +N_("keyboard label|End") +N_("keyboard label|Begin") +N_("keyboard label|Print") +N_("keyboard label|Insert") +N_("keyboard label|Num_Lock") +N_("keyboard label|KP_Space") +N_("keyboard label|KP_Tab") +N_("keyboard label|KP_Enter") +N_("keyboard label|KP_Home") +N_("keyboard label|KP_Left") +N_("keyboard label|KP_Up") +N_("keyboard label|KP_Right") +N_("keyboard label|KP_Down") +N_("keyboard label|KP_Page_Up") +N_("keyboard label|KP_Prior") +N_("keyboard label|KP_Page_Down") +N_("keyboard label|KP_Next") +N_("keyboard label|KP_End") +N_("keyboard label|KP_Begin") +N_("keyboard label|KP_Insert") +N_("keyboard label|KP_Delete") +N_("keyboard label|Delete") + +#endif diff --git a/src/test-attribute.c b/src/test-attribute.c new file mode 100644 index 0000000..b2ab4e5 --- /dev/null +++ b/src/test-attribute.c @@ -0,0 +1,44 @@ +#include "ibus.h" +#include "stdio.h" + +int main() +{ + g_type_init (); + IBusAttrList *list; + IBusMessage *message; + gboolean retval; + IBusError *error; + + list = ibus_attr_list_new (); + ibus_attr_list_append (list, ibus_attribute_new (1, 1, 1, 2)); + ibus_attr_list_append (list, ibus_attribute_new (2, 1, 1, 2)); + ibus_attr_list_append (list, ibus_attribute_new (3, 1, 1, 2)); + ibus_attr_list_append (list, ibus_attribute_new (3, 1, 1, 2)); + + message = ibus_message_new_signal ("/org/freedesktop/IBus", + "org.freedesktop.IBus", + "Test"); + + IBusSerializable *p = ibus_serializable_new (); + retval = ibus_message_append_args (message, + IBUS_TYPE_SERIALIZABLE, &p, + IBUS_TYPE_SERIALIZABLE, &p, + IBUS_TYPE_SERIALIZABLE, &p, + IBUS_TYPE_SERIALIZABLE, &p, + IBUS_TYPE_SERIALIZABLE, &p, + G_TYPE_INVALID); + g_assert (retval); + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_SERIALIZABLE, &p, + IBUS_TYPE_SERIALIZABLE, &p, + IBUS_TYPE_SERIALIZABLE, &p, + IBUS_TYPE_SERIALIZABLE, &p, + IBUS_TYPE_SERIALIZABLE, &p, + G_TYPE_INVALID); + g_assert (retval); + + return 0; + +} diff --git a/src/test-bus.c b/src/test-bus.c new file mode 100644 index 0000000..a7756fa --- /dev/null +++ b/src/test-bus.c @@ -0,0 +1,22 @@ +#include "ibus.h" + +int main() +{ + g_type_init (); + + GMainLoop *mainloop; + IBusBus *bus; + IBusInputContext *context; + + mainloop = g_main_loop_new (NULL, FALSE); + bus = ibus_bus_new (); + context = ibus_bus_create_input_context (bus, "test"); + ibus_input_context_set_capabilities (context, 0); + ibus_input_context_destroy (context); + g_object_unref (context); + g_object_unref (bus); + + g_main_loop_run (mainloop); + + return 0; +} diff --git a/src/test-engine.c b/src/test-engine.c new file mode 100644 index 0000000..bea99cf --- /dev/null +++ b/src/test-engine.c @@ -0,0 +1,16 @@ +#include "ibus.h" + +int main() +{ + g_type_init (); + + GMainLoop *mainloop; + IBusConnection *connection; + IBusService *service; + + mainloop = g_main_loop_new (NULL, FALSE); + connection = ibus_connection_open ("unix:path=/tmp/ibus-phuang/ibus--0.0"); + service = IBUS_SERVICE (ibus_engine_new ("/a/Engine", connection)); + g_main_loop_run (mainloop); + return 0; +} diff --git a/src/test-keynames.c b/src/test-keynames.c new file mode 100644 index 0000000..629f4d3 --- /dev/null +++ b/src/test-keynames.c @@ -0,0 +1,8 @@ +#include "ibus.h" + +int main() +{ + g_assert_cmpstr (ibus_keyval_name (IBUS_Home), ==, "Home"); + g_assert (ibus_keyval_from_name ("Home") == IBUS_Home); + return 0; +} diff --git a/src/test-lookuptable.c b/src/test-lookuptable.c new file mode 100644 index 0000000..ec56811 --- /dev/null +++ b/src/test-lookuptable.c @@ -0,0 +1,39 @@ +#include "ibus.h" + +int main() +{ + g_type_init (); + IBusLookupTable *table, *table1; + IBusMessage *message; + IBusError *error; + gboolean retval; + + table = ibus_lookup_table_new (9, TRUE); + ibus_lookup_table_append_candidate (table, ibus_text_new_from_static_string ("Hello")); + ibus_lookup_table_append_candidate (table, ibus_text_new_from_static_string ("Cool")); + + message = ibus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL); + + retval = ibus_message_append_args (message, + IBUS_TYPE_LOOKUP_TABLE, &table, + IBUS_TYPE_LOOKUP_TABLE, &table, + G_TYPE_INVALID); + g_assert (retval); + + g_object_unref (table); + table = table1 = NULL; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_LOOKUP_TABLE, &table, + IBUS_TYPE_LOOKUP_TABLE, &table1, + G_TYPE_INVALID); + g_assert (retval); + g_assert (table); + g_assert (table1); + + g_object_unref (table); + g_object_unref (table1); + + return 0; +} diff --git a/src/test-proxy.c b/src/test-proxy.c new file mode 100644 index 0000000..31866f1 --- /dev/null +++ b/src/test-proxy.c @@ -0,0 +1,18 @@ +#include "ibus.h" + +int main() +{ + g_type_init (); + + IBusConnection *connection; + IBusProxy *proxy; + + connection = ibus_connection_new (); + proxy = ibus_proxy_new ("a", "/a", connection); + GValue value = {0}; + g_value_init (&value, G_TYPE_STRING); + g_value_set_static_string (&value, "aaa"); + g_object_set_property (G_OBJECT (proxy), "name", &value); + + return 0; +} diff --git a/src/test-server.c b/src/test-server.c new file mode 100644 index 0000000..4e37085 --- /dev/null +++ b/src/test-server.c @@ -0,0 +1,30 @@ +#include "ibus.h" + + +void connection_destroy_cb (IBusConnection *connection, gpointer user_data) +{ + g_debug ("connnection %p destroyed", connection ); +} + +void new_connection_cb (IBusServer *server, IBusConnection *connection, gpointer user_data) +{ + g_debug ("new-connection %p", connection); + g_signal_connect (connection, "destroy", (GCallback) connection_destroy_cb, 0); +} + +int main() +{ + g_type_init (); + + GMainLoop *mainloop; + IBusServer *server; + + mainloop = g_main_loop_new (NULL, FALSE); + server = ibus_server_new (); + ibus_server_listen (server, "unix:abstract=/tmp/1234567"); + g_signal_connect (server, "new-connection", (GCallback) new_connection_cb, 0); + + g_main_loop_run (mainloop); + + return 0; +} diff --git a/src/test-text.c b/src/test-text.c new file mode 100644 index 0000000..37bc3a6 --- /dev/null +++ b/src/test-text.c @@ -0,0 +1,42 @@ +#include "ibus.h" + +int main() +{ + g_type_init (); + + IBusText *text1; + IBusText *text2; + IBusMessage *message; + IBusError *error; + gboolean retval; + + text1 = ibus_text_new_from_string ("Hello"); + text2 = ibus_text_new_from_static_string ("Hello"); + + message = ibus_message_new_signal ("/org/freedesktop/IBus", + "org.freedesktop.IBus", + "Test"); + + retval = ibus_message_append_args (message, + IBUS_TYPE_SERIALIZABLE, &text1, + IBUS_TYPE_SERIALIZABLE, &text2, + G_TYPE_INVALID); + g_assert (retval); + g_object_unref (text1); + g_object_unref (text2); + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_SERIALIZABLE, &text1, + IBUS_TYPE_SERIALIZABLE, &text2, + G_TYPE_INVALID); + g_assert (retval); + g_assert_cmpstr (text1->text, ==, "Hello"); + g_assert_cmpstr (text2->text, ==, "Hello"); + + g_object_unref (text1); + g_object_unref (text2); + + return 0; + +} diff --git a/ui/gtk/.gitignore b/ui/gtk/.gitignore index 17bbd09..abac3c8 100644 --- a/ui/gtk/.gitignore +++ b/ui/gtk/.gitignore @@ -1 +1,2 @@ ibus-ui-gtk +gtkpanel.xml diff --git a/ui/gtk/Makefile.am b/ui/gtk/Makefile.am index 18f773e..e80cf96 100644 --- a/ui/gtk/Makefile.am +++ b/ui/gtk/Makefile.am @@ -31,10 +31,16 @@ ui_gtk_PYTHON = \ propitem.py \ toolitem.py \ $(NULL) - ui_gtkdir = $(pkgdatadir)/ui/gtk -bin_SCRIPTS = ibus-ui-gtk +libexec_SCRIPTS = \ + ibus-ui-gtk \ + $(NULL) + +component_DATA = \ + gtkpanel.xml \ + $(NULL) +componentdir = $(pkgdatadir)/component CLEANFILES = \ *.pyc \ @@ -42,9 +48,11 @@ CLEANFILES = \ EXTRA_DIST = \ ibus-ui-gtk.in \ + gtkpanel.xml.in \ $(NULL) test: $(ENV) DBUS_DEBUG=true \ + IBUS_PREFIX=@prefix@ \ PYTHONPATH=$(top_srcdir) \ $(PYTHON) $(srcdir)/main.py diff --git a/ui/gtk/candidatepanel.py b/ui/gtk/candidatepanel.py index 528c7e7..db02163 100644 --- a/ui/gtk/candidatepanel.py +++ b/ui/gtk/candidatepanel.py @@ -24,7 +24,7 @@ import gtk.gdk as gdk import gobject import pango import ibus -from ibus.gtk import PangoAttrList +from ibus._gtk import PangoAttrList class Label(gtk.Label): pass gobject.type_register(Label, "IBusPanelLabel") @@ -260,58 +260,53 @@ class CandidatePanel(gtk.VBox): # self.hide_all() # self.show_all() - def show_preedit(self): + def show_preedit_text(self): self.__preedit_visible = True self.__preedit_label.show() self.__check_show_states() - def hide_preedit(self): + def hide_preedit_text(self): self.__preedit_visible = False self.__preedit_label.hide() self.__check_show_states() - def update_preedit(self, text, attrs, cursor_pos, visible): - if attrs: - attrs = PangoAttrList(attrs, text) + def update_preedit_text(self, text, cursor_pos, visible): + attrs = PangoAttrList(text.attributes, text.text) if visible: - self.show_preedit() + self.show_preedit_text() else: - self.hide_preedit() - self.__preedit_string = text - self.__preedit_label.set_text(text) - if attrs == None: - attrs = pango.AttrList() + self.hide_preedit_text() + self.__preedit_stribg = text.text + self.__preedit_label.set_text(text.text) self.__preedit_attrs = attrs self.__preedit_label.set_attributes(attrs) - def show_aux_string(self): + def show_auxiliary_text(self): self.__aux_string_visible = True self.__aux_label.show() self.__check_show_states() - def hide_aux_string(self): + def hide_auxiliary_text(self): self.__aux_string_visible = False self.__aux_label.hide() self.__check_show_states() - def update_aux_string(self, text, attrs, show): - attrs = PangoAttrList(attrs, text) + def update_auxiliary_text(self, text, show): + attrs = PangoAttrList(text.attributes, text.text) if show: - self.show_aux_string() + self.show_auxiliary_text() else: - self.hide_aux_string() + self.hide_auxiliary_text() - self.__aux_string = text - self.__aux_label.set_text(text) - if attrs == None: - attrs = pango.AttrList() + self.__aux_string = text.text + self.__aux_label.set_text(text.text) self.__aux_attrs = attrs self.__aux_label.set_attributes(attrs) def __refresh_candidates(self): - candidates = self.__lookup_table.get_canidates_in_current_page() - candidates = map(lambda x: (x[0], PangoAttrList(x[1], x[0]) if x[1] else None), candidates) + candidates = self.__lookup_table.get_candidates_in_current_page() + candidates = map(lambda x: (x.text, PangoAttrList(x.attributes, x.text)), candidates) self.__candidate_area.set_candidates(candidates, self.__lookup_table.get_cursor_pos_in_current_page(), self.__lookup_table.is_cursor_visible() @@ -372,8 +367,8 @@ class CandidatePanel(gtk.VBox): self.emit("hide") def reset(self): - self.update_preedit("", None, 0, False) - self.update_aux_string("", None, False) + self.update_preedit_text(ibus.Text(""), 0, False) + self.update_auxiliary_text(ibus.Text(""), False) self.update_lookup_table(None, False) self.hide() diff --git a/ui/gtk/gtkpanel.xml.in b/ui/gtk/gtkpanel.xml.in new file mode 100644 index 0000000..961dc5a --- /dev/null +++ b/ui/gtk/gtkpanel.xml.in @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- filename: pinyin.xml --> +<component> + <name>org.freedesktop.IBus.Panel</name> + <description>Gtk Panel Component</description> + <exec>@prefix@/libexec/ibus-ui-gtk</exec> + <version>@VERSION@</version> + <author>Peng Huang <shawn.p.huang@gmail.com></author> + <license>GPL</license> + <homepage>http://code.google.com/p/ibus</homepage> + <textdomain>ibus</textdomain> +</component> diff --git a/ui/gtk/icon.py b/ui/gtk/icon.py index 4a373a9..077848d 100644 --- a/ui/gtk/icon.py +++ b/ui/gtk/icon.py @@ -33,9 +33,6 @@ class IconWidget(gtk.Image): theme = gtk.icon_theme_get_default() pixbuf = theme.load_icon(icon, size, 0) except: - pass - - if pixbuf == None: theme = gtk.icon_theme_get_default() pixbuf = theme.load_icon(gtk.STOCK_MISSING_IMAGE, size, 0) diff --git a/ui/gtk/languagebar.py b/ui/gtk/languagebar.py index 65eb2e5..7a8a106 100644 --- a/ui/gtk/languagebar.py +++ b/ui/gtk/languagebar.py @@ -78,7 +78,7 @@ class LanguageBar(gtk.Toolbar): self.insert(self.__handle, -1) # create input methods menu - prop = ibus.Property(name = "", type = ibus.PROP_TYPE_TOGGLE, icon = "ibus", tooltip = _("Switch engine")) + prop = ibus.Property(key = "", type = ibus.PROP_TYPE_TOGGLE, icon = "ibus", tooltip = _("Switch engine")) self.__im_menu = ToggleToolButton(prop) self.__im_menu.set_homogeneous(False) self.__im_menu.connect("toggled", self.__im_menu_toggled_cb) @@ -192,6 +192,8 @@ class LanguageBar(gtk.Toolbar): self.__im_menu.set_sensitive(False) if self.__auto_hide: self.hide_all() + else: + self.show_all() gobject.type_register(LanguageBar, "IBusLanguageBar") diff --git a/ui/gtk/main.py b/ui/gtk/main.py index 489f96a..f9f9ff6 100644 --- a/ui/gtk/main.py +++ b/ui/gtk/main.py @@ -31,19 +31,16 @@ import notifications class UIApplication: def __init__ (self): self.__bus = ibus.Bus() - self.__bus.connect("destroy", self.__bus_destroy_cb) + self.__bus.connect("disconnected", gtk.main_quit) self.__panel = panel.Panel(self.__bus) - self.__notify = notifications.Notifications(self.__bus) - self.__notify.set_status_icon(self.__panel.get_status_icon()) + self.__bus.request_name(ibus.IBUS_SERVICE_PANEL, 0) + # self.__notify = notifications.Notifications(self.__bus) + # self.__notify.set_status_icon(self.__panel.get_status_icon()) def run(self): gtk.main() - def __bus_destroy_cb(self, _ibus): - gtk.main_quit() - - def launch_panel(): # gtk.settings_get_default().props.gtk_theme_name = "/home/phuang/.themes/aud-Default/gtk-2.0/gtkrc" # gtk.rc_parse("./themes/default/gtkrc") diff --git a/ui/gtk/menu.py b/ui/gtk/menu.py index 19911e8..9a3b30a 100644 --- a/ui/gtk/menu.py +++ b/ui/gtk/menu.py @@ -107,7 +107,7 @@ class ImageMenuItem (gtk.ImageMenuItem, PropItem): self.hide_all () def do_activate (self): - self.emit ("property-activate", self._prop.name, self._prop.state) + self.emit ("property-activate", self._prop.key, self._prop.state) def property_changed (self): self.set_sensitive (self._prop.sensitive) @@ -145,7 +145,7 @@ class CheckMenuItem (gtk.CheckMenuItem, PropItem): self._prop.state = ibus.PROP_STATE_CHECKED else: self._prop.state = ibus.PROP_STATE_UNCHECKED - self.emit ("property-activate", self._prop.name, self._prop.state) + self.emit ("property-activate", self._prop.key, self._prop.state) def property_changed (self): self.set_active (self._prop.state == ibus.PROP_STATE_CHECKED) @@ -167,7 +167,7 @@ class RadioMenuItem (gtk.RadioMenuItem, PropItem): } def __init__ (self, group, prop): - gtk.RadioMenuItem.__init__ (self, group, label = prop.label) + gtk.RadioMenuItem.__init__ (self, group, label = prop.label.text) PropItem.__init__ (self, prop) self.set_active (self._prop.state == ibus.PROP_STATE_CHECKED) @@ -194,7 +194,7 @@ class RadioMenuItem (gtk.RadioMenuItem, PropItem): self._prop.state = ibus.PROP_STATE_CHECKED else: self._prop.state = ibus.PROP_STATE_UNCHECKED - self.emit ("property-activate", self._prop.name, self._prop.state) + self.emit ("property-activate", self._prop.key, self._prop.state) class SeparatorMenuItem (gtk.SeparatorMenuItem, PropItem): __gsignals__ = { diff --git a/ui/gtk/notifications.py b/ui/gtk/notifications.py index cebedf5..1e990f3 100644 --- a/ui/gtk/notifications.py +++ b/ui/gtk/notifications.py @@ -34,17 +34,13 @@ from gettext import dgettext _ = lambda a : dgettext("ibus", a) N_ = lambda a : a -BUS_NOTIFICATIONS_NAME = "org.freedesktop.Notifications" -BUS_NOTIFICATIONS_PATH = "/org/freedesktop/Notifications" -BUS_NOTIFICATIONS_IFACE = "org.freedesktop.Notifications" - class Notifications(ibus.NotificationsBase): def __init__ (self, bus): super(Notifications, self).__init__(bus) self.__bus = bus try: self.__dbus = dbus.SessionBus() - self.__dbus.watch_name_owner(BUS_NOTIFICATIONS_NAME, + self.__dbus.watch_name_owner(ibus.IBUS_SERVICE_NOTIFICATIONS, self.__notifications_name_owner_changed_cb) except: self.__dbus = None @@ -52,7 +48,7 @@ class Notifications(ibus.NotificationsBase): self.__ids = set([]) self.__init_notifications() self.__status_icons = None - self.__bus.request_name(ibus.IBUS_NOTIFICATIONS_NAME, 0) + self.__bus.request_name(ibus.IBUS_SERVICE_NOTIFICATIONS, 0) def __notifications_name_owner_changed_cb(self, unique_name): if unique_name: @@ -66,13 +62,13 @@ class Notifications(ibus.NotificationsBase): try: self.__notifications = self.__dbus.get_object( - BUS_NOTIFICATIONS_NAME, BUS_NOTIFICATIONS_PATH) + ibus.IBUS_SERVICE_NOTIFICATIONS, ibus.IBUS_PATH_NOTIFICATIONS) self.__notifications.connect_to_signal("NotificationClosed", self.__notification_closed_cb, - dbus_interface=BUS_NOTIFICATIONS_IFACE) + dbus_interface=ibus.IBUS_IFACE_NOTIFICATIONS) self.__notifications.connect_to_signal("ActionInvoked", self.__action_invoked_cb, - dbus_interface=BUS_NOTIFICATIONS_IFACE) + dbus_interface=ibus.IBUS_IFACE_NOTIFICATIONS) self.__ids = set([]) except: self.__notifications = None diff --git a/ui/gtk/panel.py b/ui/gtk/panel.py index 1456cc4..284dbb6 100644 --- a/ui/gtk/panel.py +++ b/ui/gtk/panel.py @@ -55,6 +55,7 @@ class Panel(ibus.PanelBase): def __init__ (self, bus): super(Panel, self).__init__(bus) self.__bus = bus + self.__config = self.__bus.get_config() self.__focus_ic = None self.__setup_pid = 0 self.__prefix = os.getenv("IBUS_PREFIX") @@ -67,9 +68,9 @@ class Panel(ibus.PanelBase): signal.signal(signal.SIGCHLD, self.__sigchld_cb) # connect bus signal - self.__bus.connect("config-value-changed", self.__config_value_changed_cb) - self.__bus.connect("config-reloaded", self.__config_reloaded_cb) - self.__bus.config_add_watch("panel") + self.__config.connect("value-changed", self.__config_value_changed_cb) + self.__config.connect("reloaded", self.__config_reloaded_cb) + # self.__bus.config_add_watch("panel") # add icon search path icon_theme = gtk.icon_theme_get_default() @@ -101,28 +102,28 @@ class Panel(ibus.PanelBase): self.__config_load_lookup_table_orientation() self.__config_load_auto_hide() self.__config_load_custom_font() - self.__bus.request_name(ibus.panel.IBUS_PANEL_NAME, 0) + # self.__bus.request_name(ibus.panel.IBUS_SERVICE_PANEL, 0) def set_cursor_location(self, x, y, w, h): self.__candidate_panel.set_cursor_location(x + w, y + h) - def update_preedit(self, text, attrs, cursor_pos, visible): - self.__candidate_panel.update_preedit(text, attrs, cursor_pos, visible) + def update_preedit_text(self, text, cursor_pos, visible): + self.__candidate_panel.update_preedit_text(text, cursor_pos, visible) - def show_preedit(self): - self.__candidate_panel.show_preedit() + def show_preedit_text(self): + self.__candidate_panel.show_preedit_text() - def hide_preedit(self): - self.__candidate_panel.hide_preedit() + def hide_preedit_text(self): + self.__candidate_panel.hide_preedit_text() - def update_aux_string(self, text, attrs, visible): - self.__candidate_panel.update_aux_string(text, attrs, visible) + def update_auxiliary_text(self, text, visible): + self.__candidate_panel.update_auxiliary_text(text, visible) - def show_aux_string(self): - self.__candidate_panel.show_aux_string() + def show_auxiliary_text(self): + self.__candidate_panel.show_auxiliary_text() - def hide_aux_string(self): - self.__candidate_panel.hide_aux_string() + def hide_auxiliary_text(self): + self.__candidate_panel.hide_auxiliary_text() def update_lookup_table(self, lookup_table, visible): self.__candidate_panel.update_lookup_table(lookup_table, visible) @@ -175,35 +176,43 @@ class Panel(ibus.PanelBase): def focus_in(self, ic): self.reset() - self.__focus_ic = ic - - factory, enabled = self.__bus.get_input_context_states(ic) + self.__focus_ic = ibus.InputContext(self.__bus, ic) + enabled = self.__focus_ic.is_enabled() self.__language_bar.set_enabled(enabled) - if factory == "" or not enabled: + if not enabled: self.__set_im_icon(self.__ibus_icon) else: - name, lang, icon, authors, credits = self.__bus.get_factory_info(factory) - self.__set_im_icon(icon) + engine = self.__focus_ic.get_engine() + if engine: + self.__set_im_icon(engine.icon) + else: + self.__set_im_icon(self.__ibus_icon) self.__language_bar.focus_in() def focus_out(self, ic): self.reset() - if self.__focus_ic == ic: - self.__focus_ic = None - self.__language_bar.focus_out() - self.__set_im_icon(self.__ibus_icon) + self.__focus_ic = None + self.__language_bar.focus_out() + self.__set_im_icon(self.__ibus_icon) - def states_changed(self): + def state_changed(self): if not self.__focus_ic: return - factory, enabled = self.__bus.get_input_context_states(self.__focus_ic) + + enabled = self.__focus_ic.is_enabled() self.__language_bar.set_enabled(enabled) - if enabled == False or not factory: + + if enabled == False: + self.reset() self.__set_im_icon(self.__ibus_icon) else: - name, lang, icon, authors, credits = self.__bus.get_factory_info(factory) - self.__set_im_icon(icon) + engine = self.__focus_ic.get_engine() + if engine: + self.__set_im_icon(engine.icon) + else: + self.__set_im_icon(self.__ibus_icon) + def reset(self): self.__candidate_panel.reset() @@ -216,7 +225,7 @@ class Panel(ibus.PanelBase): gtk.main_quit() def __config_load_lookup_table_orientation(self): - value = self.__bus.config_get_value("panel", "lookup_table_orientation", 0) + value = self.__config.get_value("panel", "lookup_table_orientation", 0) if value != 0 and value != 1: value = 0 if value == 0: @@ -225,14 +234,14 @@ class Panel(ibus.PanelBase): self.__candidate_panel.set_orientation(gtk.ORIENTATION_VERTICAL) def __config_load_auto_hide(self): - auto_hide = self.__bus.config_get_value("panel", "auto_hide", False) + auto_hide = self.__config.get_value("panel", "auto_hide", False) self.__language_bar.set_auto_hide(auto_hide) def __config_load_custom_font(self): - use_custom_font = self.__bus.config_get_value("panel", "use_custom_font", False) + use_custom_font = self.__config.get_value("panel", "use_custom_font", False) font_name = gtk.settings_get_default().get_property("gtk-font-name") font_name = unicode(font_name, "utf-8") - custom_font = self.__bus.config_get_value("panel", "custom_font", font_name) + custom_font = self.__config.get_value("panel", "custom_font", font_name) style_string = 'style "custom-font" { font_name="%s" }\n' \ 'class "IBusPanelLabel" style "custom-font"\n' if use_custom_font: @@ -246,6 +255,8 @@ class Panel(ibus.PanelBase): gtk.rc_reset_styles(settings) def __config_value_changed_cb(self, bus, section, name, value): + if section != "panel": + return if name == "lookup_table_orientation": self.__config_load_lookup_table_orientation() elif name == "auto_hide": @@ -278,45 +289,44 @@ class Panel(ibus.PanelBase): def __create_im_menu(self): menu = gtk.Menu() - factories = self.__bus.get_factories() + engines = self.__bus.list_active_engines() - if not factories: + if not engines: item = gtk.MenuItem(label = "no engine") item.set_sensitive(False) menu.add(item) else: tmp = {} - for factory in factories: - name, lang, icon, authors, credits = self.__bus.get_factory_info(factory) - lang = ibus.get_language_name(lang) - if not icon: - icon = "engine-default" + for engine in engines: + lang = ibus.get_language_name(engine.language) if lang not in tmp: tmp[lang] = [] - tmp[lang].append((name, lang, icon, authors, credits, factory)) + tmp[lang].append(engine) + langs = tmp.keys() other = tmp.get(_("Other"), []) if _("Other") in tmp: langs.remove(_("Other")) langs.append(_("Other")) + for lang in langs: if len(tmp[lang]) == 1: - name, lang, icon, authors, credits, factory = tmp[lang][0] - item = gtk.ImageMenuItem("%s - %s" % (lang, name)) + engine = tmp[lang][0] + item = gtk.ImageMenuItem("%s - %s" % (lang, engine.longname)) size = gtk.icon_size_lookup(gtk.ICON_SIZE_MENU) - item.set_image (_icon.IconWidget(icon, size[0])) - item.connect("activate", self.__im_menu_item_activate_cb, factory) + item.set_image (_icon.IconWidget(engine.icon, size[0])) + item.connect("activate", self.__im_menu_item_activate_cb, engine) menu.add(item) else: item = gtk.MenuItem(lang) menu.add(item) submenu = gtk.Menu() item.set_submenu(submenu) - for name, __lang, icon, authors, credits, factory in tmp[lang]: - item = gtk.ImageMenuItem(name) + for engine in tmp[lang]: + item = gtk.ImageMenuItem(engine.longname) size = gtk.icon_size_lookup(gtk.ICON_SIZE_MENU) - item.set_image (_icon.IconWidget(icon, size[0])) - item.connect("activate", self.__im_menu_item_activate_cb, factory) + item.set_image (_icon.IconWidget(engine.icon, size[0])) + item.connect("activate", self.__im_menu_item_activate_cb, engine) submenu.add(item) menu.show_all() @@ -345,8 +355,8 @@ class Panel(ibus.PanelBase): gtk.get_current_event_time(), self.__status_icon) - def __im_menu_item_activate_cb(self, item, factory): - self.__bus.set_factory(factory) + def __im_menu_item_activate_cb(self, item, engine): + self.__focus_ic.set_engine(engine) def __sys_menu_item_activate_cb(self, item, command): if command == gtk.STOCK_PREFERENCES: diff --git a/ui/gtk/propitem.py b/ui/gtk/propitem.py index 3d363ed..bb66174 100644 --- a/ui/gtk/propitem.py +++ b/ui/gtk/propitem.py @@ -30,7 +30,7 @@ class PropItem: retval = False - if self._prop.name == prop.name and self._prop.type == prop.type: + if self._prop.key == prop.key and self._prop.type == prop.type: self._prop = prop self.property_changed () retval = True diff --git a/ui/gtk/toolitem.py b/ui/gtk/toolitem.py index 48147a7..0e4e4ad 100644 --- a/ui/gtk/toolitem.py +++ b/ui/gtk/toolitem.py @@ -36,7 +36,7 @@ class ToolButton(gtk.ToolButton, PropItem): } def __init__(self, prop): - gtk.ToolButton.__init__ (self, label = prop.label) + gtk.ToolButton.__init__ (self, label = prop.label.text) self.set_homogeneous(False) PropItem.__init__ (self, prop) self.property_changed() @@ -58,14 +58,14 @@ class ToolButton(gtk.ToolButton, PropItem): def set_tooltip_text(self, text): if text: - gtk.ToolButton.set_tooltip_text(self, text) + gtk.ToolButton.set_tooltip_text(self, text.text) else: gtk.ToolButton.set_tooltip_text(self, None) self._prop.tooltip = text def property_changed(self): - self.set_label(self._prop.label) + self.set_label(self._prop.label.text) self.set_tooltip_text(self._prop.tooltip) self.set_sensitive(self._prop.sensitive) self.set_icon_name(self._prop.icon) @@ -78,7 +78,7 @@ class ToolButton(gtk.ToolButton, PropItem): self.hide_all() def do_clicked(self): - self.emit("property-activate", self._prop.name, self._prop.state) + self.emit("property-activate", self._prop.key, self._prop.state) class ToggleToolButton(gtk.ToggleToolButton, PropItem): @@ -112,7 +112,7 @@ class ToggleToolButton(gtk.ToggleToolButton, PropItem): def set_tooltip_text(self, text): if text: - gtk.ToggleToolButton.set_tooltip_text(self, text) + gtk.ToggleToolButton.set_tooltip_text(self, text.text) else: gtk.ToggleToolButton.set_tooltip_text(self, None) @@ -120,7 +120,7 @@ class ToggleToolButton(gtk.ToggleToolButton, PropItem): def property_changed(self): self.set_tooltip_text(self._prop.tooltip) - self.set_label(self._prop.label) + self.set_label(self._prop.label.text) self.set_icon_name(self._prop.icon) self.set_active(self._prop.state == ibus.PROP_STATE_CHECKED) self.set_sensitive(self._prop.sensitive) @@ -136,7 +136,7 @@ class ToggleToolButton(gtk.ToggleToolButton, PropItem): self._prop.state = ibus.PROP_STATE_CHECKED else: self._prop.state = ibus.PROP_STATE_UNCHECKED - self.emit("property-activate", self._prop.name, self._prop.state) + self.emit("property-activate", self._prop.key, self._prop.state) class SeparatorToolItem(gtk.SeparatorToolItem, PropItem): def __init__ (self, prop): diff --git a/util/Makefile.am b/util/Makefile.am index 0fcbd4e..de4882b 100644 --- a/util/Makefile.am +++ b/util/Makefile.am @@ -21,5 +21,4 @@ SUBDIRS = \ IMdkit \ - gconf \ $(NULL) diff --git a/util/gconf/Makefile.am b/util/gconf/Makefile.am deleted file mode 100644 index 2317229..0000000 --- a/util/gconf/Makefile.am +++ /dev/null @@ -1,51 +0,0 @@ -INCLUDES = $(PYTHON_INCLUDES) $(PYGTK_CFLAGS) - -defsdir = $(datadir)/pygtk/2.0/defs - -if IBUS_BUILD_PYGCONF -# defs_DATA = gconf.defs -endif - -common_ldflags = -module -avoid-version $(PYTHON_LDFLAGS) - -# pkgpythondir = $(pyexecdir)/gtk-2.0 -# pkgpyexecdir = $(pyexecdir)/gtk-2.0 - -# gconf binding - -if IBUS_BUILD_PYGCONF -pkgpyexec_LTLIBRARIES = gconf.la -endif -gconf_la_CFLAGS = $(GCONF_CFLAGS) -gconf_la_LDFLAGS = $(common_ldflags) -export-symbols-regex initgconf -gconf_la_LIBADD = $(PYGTK_LIBS) $(GCONF_LIBS) $(PYTHON_LIBS) -gconf_la_SOURCES = \ - gconfmodule.c \ - gconf-fixes.c \ - gconf-fixes.h \ - gconf-types.c \ - gconf-types.h -nodist_gconf_la_SOURCES = gconf.c -CLEANFILES = gconf.c -EXTRA_DIST = gconf.defs gconf.override gconf-arg-types.py -gconf.c: gconf.defs gconf.override gconf-arg-types.py - -argtypesdir = $(datadir)/pygtk/2.0/argtypes - -if IBUS_BUILD_PYGCONF -# argtypes_PYTHON = gconf-arg-types.py -endif - -.defs.c: - (cd $(srcdir) \ - && $(PYGTK_CODEGEN) \ - --py_ssize_t-clean \ - --load-types gconf-arg-types.py \ - --override $*.override \ - --prefix py$* $*.defs) > gen-$*.c \ - && cp gen-$*.c $*.c \ - && rm -f gen-$*.c - - -EXTRA_DIST += wscript - diff --git a/util/gconf/gconf-arg-types.py b/util/gconf/gconf-arg-types.py deleted file mode 100644 index 1610495..0000000 --- a/util/gconf/gconf-arg-types.py +++ /dev/null @@ -1,30 +0,0 @@ -import argtypes - -class GConfEngineArg (argtypes.ArgType): - engine = (' %(name)s = pygconf_engine_from_pyobject (py_%(name)s);\n' - ' if (PyErr_Occurred ())\n' - ' return NULL;\n') - - def write_param(self, ptype, pname, pdflt, pnull, info): - # pdflt and pnull not handled - we don't use "default" or "null-ok" - info.varlist.add ('GConfEngine*', pname) - info.varlist.add ('PyObject', '*py_' + pname + ' = NULL') - info.codebefore.append (self.engine % { 'name' : pname }) - info.arglist.append (pname) - info.add_parselist ('O', ['&py_' + pname], [pname]) - - def write_return (self, ptype, ownsreturn, info): - if ptype[-1] == '*': - ptype = ptype[:-1] - info.varlist.add (ptype, '*ret') - if ownsreturn: - info.varlist.add ('PyObject', '*py_ret') - info.codeafter.append (' py_ret = pygconf_engine_new (ret);\n' - ' if (ret != NULL)\n' - ' gconf_engine_unref (ret);\n' - ' return py_ret;') - else: - info.codeafter.append (' /* pygconf_engine_new() handles NULL checking */\n' + - ' return pygconf_engine_new (ret);') - -argtypes.matcher.register ("GConfEngine*", GConfEngineArg ()) diff --git a/util/gconf/gconf-fixes.c b/util/gconf/gconf-fixes.c deleted file mode 100644 index dbef754..0000000 --- a/util/gconf/gconf-fixes.c +++ /dev/null @@ -1,57 +0,0 @@ -/* GConf-python - * Copyright (C) 2002 Johan Dahlin - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Johan Dahlin <jdahlin@telia.com> - */ - -#include <gconf/gconf-client.h> -#include <gconf/gconf-value.h> - -#include "gconf-fixes.h" - -GConfMetaInfo* -gconf_meta_info_copy (const GConfMetaInfo *src) -{ - GConfMetaInfo *info; - - info = gconf_meta_info_new (); - - info->schema = g_strdup (src->schema); - info->mod_user = g_strdup (src->mod_user); - info->mod_time = src->mod_time; - - return info; -} - -#define BOILERPLATE_TYPE_BOXED(func,name) \ -GType \ -py##func##_get_type (void) \ -{ \ - static GType type = 0; \ - if (type == 0) { \ - type = g_boxed_type_register_static(name, \ - (GBoxedCopyFunc)func##_copy, \ - (GBoxedFreeFunc)func##_free); \ - } \ - return type; \ -} - -BOILERPLATE_TYPE_BOXED(gconf_value, "GConfValue") -BOILERPLATE_TYPE_BOXED(gconf_entry, "GConfEntry") -BOILERPLATE_TYPE_BOXED(gconf_schema, "GConfSchema") -BOILERPLATE_TYPE_BOXED(gconf_meta_info, "GConfMetaInfo") diff --git a/util/gconf/gconf-fixes.h b/util/gconf/gconf-fixes.h deleted file mode 100644 index 50eb7ec..0000000 --- a/util/gconf/gconf-fixes.h +++ /dev/null @@ -1,14 +0,0 @@ -#include <glib-object.h> -#include <gconf/gconf-value.h> - -extern GConfEntry* gconf_entry_copy (const GConfEntry *src); - -GType pygconf_value_get_type (void); -GType pygconf_entry_get_type (void); -GType pygconf_schema_get_type (void); -GType pygconf_meta_info_get_type (void); - -#define GCONF_TYPE_VALUE (pygconf_value_get_type ()) -#define GCONF_TYPE_ENTRY (pygconf_entry_get_type ()) -#define GCONF_TYPE_SCHEMA (pygconf_schema_get_type ()) -#define GCONF_TYPE_METAINFO (pygconf_meta_info_get_type ()) diff --git a/util/gconf/gconf-types.c b/util/gconf/gconf-types.c deleted file mode 100644 index 9e0b1a9..0000000 --- a/util/gconf/gconf-types.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2005 Red Hat, Inc. - * - * gconf-types.c: wrappers for some specialised GConf types. - * - * 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.1 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 library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#include "gconf-types.h" -#define NO_IMPORT_PYGOBJECT -#include <pygobject.h> - -typedef struct { - PyObject_HEAD - GConfEngine *engine; -} PyGConfEngine; -extern PyTypeObject PyGConfEngine_Type; - -static void -pygconf_engine_dealloc (PyGConfEngine *self) -{ - pyg_begin_allow_threads; - gconf_engine_unref (self->engine); - pyg_end_allow_threads; - PyObject_DEL (self); -} - - -static PyObject * -pygconf_engine_associate_schema(PyGConfEngine *self, PyObject *args, PyObject *kwargs) -{ - gchar *key, *schema_key; - gboolean result; - GError *err = NULL; - char *kwlist[] = {"key", "schema_key", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "ss:gconf.Engine.associate_schema", - kwlist, &key, &schema_key)) - return NULL; - - result = gconf_engine_associate_schema(self->engine, key, schema_key, &err); - - if (pyg_error_check(&err)) - return NULL; - - if (result) { - Py_INCREF(Py_True); - return Py_True; - } else { - Py_INCREF(Py_False); - return Py_False; - } -} - -static PyMethodDef pygconf_engine_methods[] = { - {"associate_schema", (PyCFunction)pygconf_engine_associate_schema, - METH_KEYWORDS, NULL}, - - {NULL, NULL, 0, NULL} -}; - - -PyTypeObject PyGConfEngine_Type = { - PyObject_HEAD_INIT (NULL) - 0, - "gconf.GConfEngine", - sizeof (PyGConfEngine), - 0, - (destructor) pygconf_engine_dealloc, - (printfunc) 0, - (getattrfunc) 0, - (setattrfunc) 0, - (cmpfunc) 0, - (reprfunc) 0, - 0, - 0, - 0, - (hashfunc) 0, - (ternaryfunc) 0, - (reprfunc) 0, - (getattrofunc) 0, - (setattrofunc) 0, - 0, - Py_TPFLAGS_DEFAULT, - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - pygconf_engine_methods, /* tp_methods */ -}; - -PyObject * -pygconf_engine_new (GConfEngine *engine) -{ - PyGConfEngine *self; - - if (engine == NULL) - { - Py_INCREF (Py_None); - return Py_None; - } - - self = (PyGConfEngine *) PyObject_NEW (PyGConfEngine, &PyGConfEngine_Type); - if (self == NULL) - return NULL; - - pyg_begin_allow_threads; - self->engine = engine; - gconf_engine_ref (engine); - pyg_end_allow_threads; - - return (PyObject *) self; -} - -GConfEngine * -pygconf_engine_from_pyobject (PyObject *object) -{ - PyGConfEngine *self; - - if (object == NULL) - return NULL; - - if (!PyObject_TypeCheck (object, &PyGConfEngine_Type)) - { - PyErr_SetString (PyExc_TypeError, "unable to convert argument to GConfEngine*"); - return NULL; - } - - self = (PyGConfEngine *) object; - - return self->engine; -} - -void -pygconf_register_engine_type (PyObject *moddict) -{ - PyGConfEngine_Type.ob_type = &PyType_Type; - - PyType_Ready(&PyGConfEngine_Type); -} diff --git a/util/gconf/gconf-types.h b/util/gconf/gconf-types.h deleted file mode 100644 index 210a417..0000000 --- a/util/gconf/gconf-types.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2005 Red Hat, Inc. - * - * gconf-types.h: wrappers for some specialised GConf types. - * - * 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.1 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 library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * Author: - * Mark McLoughlin <mark@skynet.ie> - */ - -#ifndef __GCONF_TYPES_H__ -#define __GCONF_TYPES_H__ - -#include <Python.h> -#include <gconf/gconf.h> - -void pygconf_register_engine_type (PyObject *moddict); -PyObject *pygconf_engine_new (GConfEngine *engine); -GConfEngine *pygconf_engine_from_pyobject (PyObject *object); - -#endif /* __GCONF_TYPES_H__ */ diff --git a/util/gconf/gconf.defs b/util/gconf/gconf.defs deleted file mode 100644 index 7cc0229..0000000 --- a/util/gconf/gconf.defs +++ /dev/null @@ -1,1978 +0,0 @@ -;; -*- scheme -*- - -(define-object Client - (in-module "GConf") - (parent "GObject") - (c-name "GConfClient") - (gtype-id "GCONF_TYPE_CLIENT") -) - -(define-boxed Value - (in-module "GConf") - (c-name "GConfValue") - (gtype-id "GCONF_TYPE_VALUE") - (copy-func "gconf_value_copy") - (release-func "gconf_value_free") - (fields - '("GConfValueType" "type") - ) -) - -(define-boxed Entry - (in-module "GConf") - (c-name "GConfEntry") - (gtype-id "GCONF_TYPE_ENTRY") - (copy-func "gconf_entry_copy") - (release-func "gconf_entry_free") - (fields - '("gchar*" "key") - '("GConfValue*" "value") - ) -) - -(define-boxed Schema - (in-module "GConf") - (c-name "GConfSchema") - (gtype-id "GCONF_TYPE_SCHEMA") - (copy-func "gconf_schema_copy") - (release-func "gconf_schema_free") -) - -(define-boxed MetaInfo - (in-module "GConf") - (c-name "GConfMetaInfo") - (gtype-id "GCONF_TYPE_METAINFO") - (copy-func "gconf_metainfo_copy") - (release-func "gconf_metainfo_free") -) - -(define-boxed ChangeSet - (in-module "GConf") - (c-name "GConfChangeSet") - (gtype-id "GCONF_TYPE_CHANGE_SET") -) - -(define-enum ClientPreloadType - (in-module "GConf") - (c-name "GConfClientPreloadType") - (gtype-id "GCONF_TYPE_CLIENT_PRELOAD_TYPE") - (values - '("none" "GCONF_CLIENT_PRELOAD_NONE") - '("onelevel" "GCONF_CLIENT_PRELOAD_ONELEVEL") - '("recursive" "GCONF_CLIENT_PRELOAD_RECURSIVE") - ) -) - -(define-enum ClientErrorHandlingMode - (in-module "GConf") - (c-name "GConfClientErrorHandlingMode") - (gtype-id "GCONF_TYPE_CLIENT_ERROR_HANDLING_MODE") - (values - '("none" "GCONF_CLIENT_HANDLE_NONE") - '("unreturned" "GCONF_CLIENT_HANDLE_UNRETURNED") - '("all" "GCONF_CLIENT_HANDLE_ALL") - ) -) - -(define-enum Error - (in-module "GConf") - (c-name "GConfError") - (gtype-id "GCONF_TYPE_ERROR") - (values - '("success" "GCONF_ERROR_SUCCESS") - '("failed" "GCONF_ERROR_FAILED") - '("no-server" "GCONF_ERROR_NO_SERVER") - '("no-permission" "GCONF_ERROR_NO_PERMISSION") - '("bad-address" "GCONF_ERROR_BAD_ADDRESS") - '("bad-key" "GCONF_ERROR_BAD_KEY") - '("parse-error" "GCONF_ERROR_PARSE_ERROR") - '("corrupt" "GCONF_ERROR_CORRUPT") - '("type-mismatch" "GCONF_ERROR_TYPE_MISMATCH") - '("is-dir" "GCONF_ERROR_IS_DIR") - '("is-key" "GCONF_ERROR_IS_KEY") - '("overridden" "GCONF_ERROR_OVERRIDDEN") - '("oaf-error" "GCONF_ERROR_OAF_ERROR") - '("local-engine" "GCONF_ERROR_LOCAL_ENGINE") - '("lock-failed" "GCONF_ERROR_LOCK_FAILED") - '("no-writable-database" "GCONF_ERROR_NO_WRITABLE_DATABASE") - '("in-shutdown" "GCONF_ERROR_IN_SHUTDOWN") - ) -) - -(define-enum ValueType - (in-module "GConf") - (c-name "GConfValueType") - (gtype-id "GCONF_TYPE_VALUE_TYPE") - (values - '("invalid" "GCONF_VALUE_INVALID") - '("string" "GCONF_VALUE_STRING") - '("int" "GCONF_VALUE_INT") - '("float" "GCONF_VALUE_FLOAT") - '("bool" "GCONF_VALUE_BOOL") - '("schema" "GCONF_VALUE_SCHEMA") - '("list" "GCONF_VALUE_LIST") - '("pair" "GCONF_VALUE_PAIR") - ) -) - -(define-flags UnsetFlags - (in-module "GConf") - (c-name "GConfUnsetFlags") - (gtype-id "GCONF_TYPE_UNSET_FLAGS") -) - -(define-method commit_change_set - (of-object "GConfEngine") - (c-name "gconf_engine_commit_change_set") - (return-type "gboolean") - (parameters - '("GConfChangeSet*" "cs") - '("gboolean" "remove_committed") - '("GError**" "err") - ) -) - -(define-method reverse_change_set - (of-object "GConfEngine") - (c-name "gconf_engine_reverse_change_set") - (return-type "GConfChangeSet*") - (parameters - '("GConfChangeSet*" "cs") - '("GError**" "err") - ) -) - -(define-method change_set_from_currentv - (of-object "GConfEngine") - (c-name "gconf_engine_change_set_from_currentv") - (return-type "GConfChangeSet*") - (parameters - '("const-gchar**" "keys") - '("GError**" "err") - ) -) - -(define-method change_set_from_current - (of-object "GConfEngine") - (c-name "gconf_engine_change_set_from_current") - (return-type "GConfChangeSet*") - (parameters - '("GError**" "err") - '("const-gchar*" "first_key") - ) - (varargs #t) -) - -(define-function change_set_get_type - (c-name "gconf_change_set_get_type") - (return-type "GType") -) - -(define-function change_set_new - (is-constructor-of "GConfChangeSet") - (c-name "gconf_change_set_new") - (caller-owns-return #t) - (return-type "GConfChangeSet*") -) - -(define-method ref - (of-object "GConfChangeSet") - (c-name "gconf_change_set_ref") - (return-type "none") -) - -(define-method unref - (of-object "GConfChangeSet") - (c-name "gconf_change_set_unref") - (return-type "none") -) - -(define-method clear - (of-object "GConfChangeSet") - (c-name "gconf_change_set_clear") - (return-type "none") -) - -(define-method size - (of-object "GConfChangeSet") - (c-name "gconf_change_set_size") - (return-type "guint") -) - -(define-method remove - (of-object "GConfChangeSet") - (c-name "gconf_change_set_remove") - (return-type "none") - (parameters - '("const-gchar*" "key") - ) -) - -(define-method foreach - (of-object "GConfChangeSet") - (c-name "gconf_change_set_foreach") - (return-type "none") - (parameters - '("GConfChangeSetForeachFunc" "func") - '("gpointer" "user_data") - ) -) - -(define-method check_value - (of-object "GConfChangeSet") - (c-name "gconf_change_set_check_value") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("GConfValue**" "value_retloc") - ) -) - -(define-method set - (of-object "GConfChangeSet") - (c-name "gconf_change_set_set") - (return-type "none") - (parameters - '("const-gchar*" "key") - '("GConfValue*" "value") - ) -) - -(define-method set_nocopy - (of-object "GConfChangeSet") - (c-name "gconf_change_set_set_nocopy") - (return-type "none") - (parameters - '("const-gchar*" "key") - '("GConfValue*" "value") - ) -) - -(define-method unset - (of-object "GConfChangeSet") - (c-name "gconf_change_set_unset") - (return-type "none") - (parameters - '("const-gchar*" "key") - ) -) - -(define-method set_float - (of-object "GConfChangeSet") - (c-name "gconf_change_set_set_float") - (return-type "none") - (parameters - '("const-gchar*" "key") - '("gdouble" "val") - ) -) - -(define-method set_int - (of-object "GConfChangeSet") - (c-name "gconf_change_set_set_int") - (return-type "none") - (parameters - '("const-gchar*" "key") - '("gint" "val") - ) -) - -(define-method set_string - (of-object "GConfChangeSet") - (c-name "gconf_change_set_set_string") - (return-type "none") - (parameters - '("const-gchar*" "key") - '("const-gchar*" "val") - ) -) - -(define-method set_bool - (of-object "GConfChangeSet") - (c-name "gconf_change_set_set_bool") - (return-type "none") - (parameters - '("const-gchar*" "key") - '("gboolean" "val") - ) -) - -(define-method set_schema - (of-object "GConfChangeSet") - (c-name "gconf_change_set_set_schema") - (return-type "none") - (parameters - '("const-gchar*" "key") - '("GConfSchema*" "val") - ) -) - -(define-method set_list - (of-object "GConfChangeSet") - (c-name "gconf_change_set_set_list") - (return-type "none") - (parameters - '("const-gchar*" "key") - '("GConfValueType" "list_type") - '("GSList*" "list") - ) -) - -(define-method set_pair - (of-object "GConfChangeSet") - (c-name "gconf_change_set_set_pair") - (return-type "none") - (parameters - '("const-gchar*" "key") - '("GConfValueType" "car_type") - '("GConfValueType" "cdr_type") - '("gconstpointer" "address_of_car") - '("gconstpointer" "address_of_cdr") - ) -) - -(define-method set_user_data - (of-object "GConfChangeSet") - (c-name "gconf_change_set_set_user_data") - (return-type "none") - (parameters - '("gpointer" "data") - '("GDestroyNotify" "dnotify") - ) -) - -(define-method get_user_data - (of-object "GConfChangeSet") - (c-name "gconf_change_set_get_user_data") - (return-type "gpointer") -) - -(define-function client_get_type - (c-name "gconf_client_get_type") - (return-type "GType") -) - -(define-function client_get_default - (c-name "gconf_client_get_default") - (caller-owns-return #t) - (return-type "GConfClient*") -) - -(define-function client_get_for_engine - (c-name "gconf_client_get_for_engine") - (caller-owns-return #t) - (return-type "GConfClient*") - (parameters - '("GConfEngine*" "engine") - ) -) - -(define-method add_dir - (of-object "GConfClient") - (c-name "gconf_client_add_dir") - (return-type "none") - (parameters - '("const-gchar*" "dir") - '("GConfClientPreloadType" "preload") - '("GError**" "err") - ) -) - -(define-method remove_dir - (of-object "GConfClient") - (c-name "gconf_client_remove_dir") - (return-type "none") - (parameters - '("const-gchar*" "dir") - '("GError**" "err") - ) -) - -(define-method notify_add - (of-object "GConfClient") - (c-name "gconf_client_notify_add") - (return-type "guint") - (parameters - '("const-gchar*" "namespace_section") - '("GConfClientNotifyFunc" "func") - '("gpointer" "user_data") - '("GFreeFunc" "destroy_notify") - '("GError**" "err") - ) -) - -(define-method notify_remove - (of-object "GConfClient") - (c-name "gconf_client_notify_remove") - (return-type "none") - (parameters - '("guint" "cnxn") - ) -) - -(define-method notify - (of-object "GConfClient") - (c-name "gconf_client_notify") - (return-type "none") - (parameters - '("const-char*" "key") - ) -) - -(define-method set_error_handling - (of-object "GConfClient") - (c-name "gconf_client_set_error_handling") - (return-type "none") - (parameters - '("GConfClientErrorHandlingMode" "mode") - ) -) - -(define-function client_set_global_default_error_handler - (c-name "gconf_client_set_global_default_error_handler") - (return-type "none") - (parameters - '("GConfClientErrorHandlerFunc" "func") - ) -) - -(define-method clear_cache - (of-object "GConfClient") - (c-name "gconf_client_clear_cache") - (return-type "none") -) - -(define-method preload - (of-object "GConfClient") - (c-name "gconf_client_preload") - (return-type "none") - (parameters - '("const-gchar*" "dirname") - '("GConfClientPreloadType" "type") - '("GError**" "err") - ) -) - -(define-method set - (of-object "GConfClient") - (c-name "gconf_client_set") - (return-type "none") - (parameters - '("const-gchar*" "key") - '("const-GConfValue*" "val") - '("GError**" "err") - ) -) - -(define-method get - (of-object "GConfClient") - (c-name "gconf_client_get") - (caller-owns-return #t) - (return-type "GConfValue*") - (parameters - '("const-gchar*" "key") - '("GError**" "err") - ) -) - -(define-method get_without_default - (of-object "GConfClient") - (c-name "gconf_client_get_without_default") - (caller-owns-return #t) - (return-type "GConfValue*") - (parameters - '("const-gchar*" "key") - '("GError**" "err") - ) -) - -(define-method get_entry - (of-object "GConfClient") - (c-name "gconf_client_get_entry") - (caller-owns-return #t) - (return-type "GConfEntry*") - (parameters - '("const-gchar*" "key") - '("const-gchar*" "locale") - '("gboolean" "use_schema_default") - '("GError**" "err") - ) -) - -(define-method get_default_from_schema - (of-object "GConfClient") - (c-name "gconf_client_get_default_from_schema") - (caller-owns-return #t) - (return-type "GConfValue*") - (parameters - '("const-gchar*" "key") - '("GError**" "err") - ) -) - -(define-method unset - (of-object "GConfClient") - (c-name "gconf_client_unset") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("GError**" "err") - ) -) - -(define-method recursive_unset - (of-object "GConfClient") - (c-name "gconf_client_recursive_unset") - (return-type "gboolean") - (parameters - '("const-char*" "key") - '("GConfUnsetFlags" "flags") - '("GError**" "err") - ) -) - -(define-method all_entries - (of-object "GConfClient") - (c-name "gconf_client_all_entries") - (return-type "GSList*") - (parameters - '("const-gchar*" "dir") - '("GError**" "err") - ) -) - -(define-method all_dirs - (of-object "GConfClient") - (c-name "gconf_client_all_dirs") - (return-type "GSList*") - (parameters - '("const-gchar*" "dir") - '("GError**" "err") - ) -) - -(define-method suggest_sync - (of-object "GConfClient") - (c-name "gconf_client_suggest_sync") - (return-type "none") - (parameters - '("GError**" "err") - ) -) - -(define-method dir_exists - (of-object "GConfClient") - (c-name "gconf_client_dir_exists") - (return-type "gboolean") - (parameters - '("const-gchar*" "dir") - '("GError**" "err") - ) -) - -(define-method key_is_writable - (of-object "GConfClient") - (c-name "gconf_client_key_is_writable") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("GError**" "err") - ) -) - -(define-method get_float - (of-object "GConfClient") - (c-name "gconf_client_get_float") - (return-type "gdouble") - (parameters - '("const-gchar*" "key") - '("GError**" "err") - ) -) - -(define-method get_int - (of-object "GConfClient") - (c-name "gconf_client_get_int") - (return-type "gint") - (parameters - '("const-gchar*" "key") - '("GError**" "err") - ) -) - -(define-method get_string - (of-object "GConfClient") - (c-name "gconf_client_get_string") - (caller-owns-return #t) - (return-type "gchar*") - (parameters - '("const-gchar*" "key") - '("GError**" "err") - ) -) - -(define-method get_bool - (of-object "GConfClient") - (c-name "gconf_client_get_bool") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("GError**" "err") - ) -) - -(define-method get_schema - (of-object "GConfClient") - (c-name "gconf_client_get_schema") - (caller-owns-return #t) - (return-type "GConfSchema*") - (parameters - '("const-gchar*" "key") - '("GError**" "err") - ) -) - -(define-method get_list - (of-object "GConfClient") - (c-name "gconf_client_get_list") - (caller-owns-return #t) - (return-type "GSList*") - (parameters - '("const-gchar*" "key") - '("GConfValueType" "list_type") - '("GError**" "err") - ) -) - -(define-method get_pair - (of-object "GConfClient") - (c-name "gconf_client_get_pair") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("GConfValueType" "car_type") - '("GConfValueType" "cdr_type") - '("gpointer" "car_retloc") - '("gpointer" "cdr_retloc") - '("GError**" "err") - ) -) - -(define-method set_float - (of-object "GConfClient") - (c-name "gconf_client_set_float") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("gdouble" "val") - '("GError**" "err") - ) -) - -(define-method set_int - (of-object "GConfClient") - (c-name "gconf_client_set_int") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("gint" "val") - '("GError**" "err") - ) -) - -(define-method set_string - (of-object "GConfClient") - (c-name "gconf_client_set_string") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("const-gchar*" "val") - '("GError**" "err") - ) -) - -(define-method set_bool - (of-object "GConfClient") - (c-name "gconf_client_set_bool") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("gboolean" "val") - '("GError**" "err") - ) -) - -(define-method set_schema - (of-object "GConfClient") - (c-name "gconf_client_set_schema") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("const-GConfSchema*" "val") - '("GError**" "err") - ) -) - -(define-method set_list - (of-object "GConfClient") - (c-name "gconf_client_set_list") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("GConfValueType" "list_type") - '("GSList*" "list") - '("GError**" "err") - ) -) - -(define-method set_pair - (of-object "GConfClient") - (c-name "gconf_client_set_pair") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("GConfValueType" "car_type") - '("GConfValueType" "cdr_type") - '("gconstpointer" "address_of_car") - '("gconstpointer" "address_of_cdr") - '("GError**" "err") - ) -) - -(define-method error - (of-object "GConfClient") - (c-name "gconf_client_error") - (return-type "none") - (parameters - '("GError*" "error") - ) -) - -(define-method unreturned_error - (of-object "GConfClient") - (c-name "gconf_client_unreturned_error") - (return-type "none") - (parameters - '("GError*" "error") - ) -) - -(define-method value_changed - (of-object "GConfClient") - (c-name "gconf_client_value_changed") - (return-type "none") - (parameters - '("const-gchar*" "key") - '("GConfValue*" "value") - ) -) - -(define-method commit_change_set - (of-object "GConfClient") - (c-name "gconf_client_commit_change_set") - (return-type "gboolean") - (parameters - '("GConfChangeSet*" "cs") - '("gboolean" "remove_committed") - '("GError**" "err") - ) -) - -(define-method reverse_change_set - (of-object "GConfClient") - (c-name "gconf_client_reverse_change_set") - (return-type "GConfChangeSet*") - (parameters - '("GConfChangeSet*" "cs") - '("GError**" "err") - ) -) - -(define-method change_set_from_currentv - (of-object "GConfClient") - (c-name "gconf_client_change_set_from_currentv") - (return-type "GConfChangeSet*") - (parameters - '("const-gchar**" "keys") - '("GError**" "err") - ) -) - -(define-method change_set_from_current - (of-object "GConfClient") - (c-name "gconf_client_change_set_from_current") - (return-type "GConfChangeSet*") - (parameters - '("GError**" "err") - '("const-gchar*" "first_key") - ) - (varargs #t) -) - -(define-function engine_get_default - (c-name "gconf_engine_get_default") - (return-type "GConfEngine*") -) - -(define-function engine_get_for_address - (c-name "gconf_engine_get_for_address") - (caller-owns-return #t) - (return-type "GConfEngine*") - (parameters - '("const-gchar*" "address") - '("GError**" "err") - ) -) - -(define-function engine_get_for_addresses - (c-name "gconf_engine_get_for_addresses") - (return-type "GConfEngine*") - (parameters - '("GSList*" "addresses") - '("GError**" "err") - ) -) - -(define-method unref - (of-object "GConfEngine") - (c-name "gconf_engine_unref") - (return-type "none") -) - -(define-method ref - (of-object "GConfEngine") - (c-name "gconf_engine_ref") - (return-type "none") -) - -(define-method set_user_data - (of-object "GConfEngine") - (c-name "gconf_engine_set_user_data") - (return-type "none") - (parameters - '("gpointer" "data") - '("GDestroyNotify" "dnotify") - ) -) - -(define-method get_user_data - (of-object "GConfEngine") - (c-name "gconf_engine_get_user_data") - (return-type "gpointer") -) - -(define-function value_type_get_type - (c-name "gconf_value_type_get_type") - (return-type "GType") -) - -(define-function error_get_type - (c-name "gconf_error_get_type") - (return-type "GType") -) - -(define-function client_preload_type_get_type - (c-name "gconf_client_preload_type_get_type") - (return-type "GType") -) - -(define-function client_error_handling_mode_get_type - (c-name "gconf_client_error_handling_mode_get_type") - (return-type "GType") -) - -(define-function error_quark - (c-name "gconf_error_quark") - (return-type "GQuark") -) - -(define-function listeners_new - (is-constructor-of "GConfListeners") - (c-name "gconf_listeners_new") - (caller-owns-return #t) - (return-type "GConfListeners*") -) - -(define-method free - (of-object "GConfListeners") - (c-name "gconf_listeners_free") - (return-type "none") -) - -(define-method add - (of-object "GConfListeners") - (c-name "gconf_listeners_add") - (return-type "guint") - (parameters - '("const-gchar*" "listen_point") - '("gpointer" "listener_data") - '("GFreeFunc" "destroy_notify") - ) -) - -(define-method remove - (of-object "GConfListeners") - (c-name "gconf_listeners_remove") - (return-type "none") - (parameters - '("guint" "cnxn_id") - ) -) - -(define-method notify - (of-object "GConfListeners") - (c-name "gconf_listeners_notify") - (return-type "none") - (parameters - '("const-gchar*" "all_above") - '("GConfListenersCallback" "callback") - '("gpointer" "user_data") - ) -) - -(define-method count - (of-object "GConfListeners") - (c-name "gconf_listeners_count") - (return-type "guint") -) - -(define-method foreach - (of-object "GConfListeners") - (c-name "gconf_listeners_foreach") - (return-type "none") - (parameters - '("GConfListenersForeach" "callback") - '("gpointer" "user_data") - ) -) - -(define-method get_data - (of-object "GConfListeners") - (c-name "gconf_listeners_get_data") - (return-type "gboolean") - (parameters - '("guint" "cnxn_id") - '("gpointer*" "listener_data_p") - '("const-gchar**" "location_p") - ) -) - -(define-method remove_if - (of-object "GConfListeners") - (c-name "gconf_listeners_remove_if") - (return-type "none") - (parameters - '("GConfListenersPredicate" "predicate") - '("gpointer" "user_data") - ) -) - -(define-function schema_new - (is-constructor-of "GConfSchema") - (c-name "gconf_schema_new") - (caller-owns-return #t) - (return-type "GConfSchema*") -) - -(define-method free - (of-object "GConfSchema") - (c-name "gconf_schema_free") - (return-type "none") -) - -(define-method copy - (of-object "GConfSchema") - (c-name "gconf_schema_copy") - (return-type "GConfSchema*") -) - -(define-method set_type - (of-object "GConfSchema") - (c-name "gconf_schema_set_type") - (return-type "none") - (parameters - '("GConfValueType" "type") - ) -) - -(define-method set_list_type - (of-object "GConfSchema") - (c-name "gconf_schema_set_list_type") - (return-type "none") - (parameters - '("GConfValueType" "type") - ) -) - -(define-method set_car_type - (of-object "GConfSchema") - (c-name "gconf_schema_set_car_type") - (return-type "none") - (parameters - '("GConfValueType" "type") - ) -) - -(define-method set_cdr_type - (of-object "GConfSchema") - (c-name "gconf_schema_set_cdr_type") - (return-type "none") - (parameters - '("GConfValueType" "type") - ) -) - -(define-method set_locale - (of-object "GConfSchema") - (c-name "gconf_schema_set_locale") - (return-type "none") - (parameters - '("const-gchar*" "locale") - ) -) - -(define-method set_short_desc - (of-object "GConfSchema") - (c-name "gconf_schema_set_short_desc") - (return-type "none") - (parameters - '("const-gchar*" "desc") - ) -) - -(define-method set_long_desc - (of-object "GConfSchema") - (c-name "gconf_schema_set_long_desc") - (return-type "none") - (parameters - '("const-gchar*" "desc") - ) -) - -(define-method set_owner - (of-object "GConfSchema") - (c-name "gconf_schema_set_owner") - (return-type "none") - (parameters - '("const-gchar*" "owner") - ) -) - -(define-method set_default_value - (of-object "GConfSchema") - (c-name "gconf_schema_set_default_value") - (return-type "none") - (parameters - '("const-GConfValue*" "val") - ) -) - -(define-method set_default_value_nocopy - (of-object "GConfSchema") - (c-name "gconf_schema_set_default_value_nocopy") - (return-type "none") - (parameters - '("GConfValue*" "val") - ) -) - -(define-method get_type - (of-object "GConfSchema") - (c-name "gconf_schema_get_type") - (return-type "GConfValueType") -) - -(define-method get_list_type - (of-object "GConfSchema") - (c-name "gconf_schema_get_list_type") - (return-type "GConfValueType") -) - -(define-method get_car_type - (of-object "GConfSchema") - (c-name "gconf_schema_get_car_type") - (return-type "GConfValueType") -) - -(define-method get_cdr_type - (of-object "GConfSchema") - (c-name "gconf_schema_get_cdr_type") - (return-type "GConfValueType") -) - -(define-method get_locale - (of-object "GConfSchema") - (c-name "gconf_schema_get_locale") - (return-type "const-char*") -) - -(define-method get_short_desc - (of-object "GConfSchema") - (c-name "gconf_schema_get_short_desc") - (return-type "const-char*") -) - -(define-method get_long_desc - (of-object "GConfSchema") - (c-name "gconf_schema_get_long_desc") - (return-type "const-char*") -) - -(define-method get_owner - (of-object "GConfSchema") - (c-name "gconf_schema_get_owner") - (return-type "const-char*") -) - -(define-method get_default_value - (of-object "GConfSchema") - (c-name "gconf_schema_get_default_value") - (return-type "GConfValue*") -) - -(define-method get_string - (of-object "GConfValue") - (c-name "gconf_value_get_string") - (return-type "const-char*") -) - -(define-method get_int - (of-object "GConfValue") - (c-name "gconf_value_get_int") - (return-type "int") -) - -(define-method get_float - (of-object "GConfValue") - (c-name "gconf_value_get_float") - (return-type "double") -) - -(define-method get_list_type - (of-object "GConfValue") - (c-name "gconf_value_get_list_type") - (return-type "GConfValueType") -) - -(define-method get_list - (of-object "GConfValue") - (c-name "gconf_value_get_list") - (return-type "GSList*") -) - -(define-method get_car - (of-object "GConfValue") - (c-name "gconf_value_get_car") - (return-type "GConfValue*") -) - -(define-method get_cdr - (of-object "GConfValue") - (c-name "gconf_value_get_cdr") - (return-type "GConfValue*") -) - -(define-method get_bool - (of-object "GConfValue") - (c-name "gconf_value_get_bool") - (return-type "gboolean") -) - -(define-method get_schema - (of-object "GConfValue") - (c-name "gconf_value_get_schema") - (return-type "GConfSchema*") -) - -(define-function value_new - (is-constructor-of "GConfValue") - (c-name "gconf_value_new") - (caller-owns-return #t) - (return-type "GConfValue*") - (parameters - '("GConfValueType" "type") - ) -) - -(define-function value_new_from_string - (c-name "gconf_value_new_from_string") - (return-type "GConfValue*") - (parameters - '("GConfValueType" "type") - '("const-gchar*" "str") - '("GError**" "err") - ) -) - -(define-method copy - (of-object "GConfValue") - (c-name "gconf_value_copy") - (return-type "GConfValue*") -) - -(define-method free - (of-object "GConfValue") - (c-name "gconf_value_free") - (return-type "none") -) - -(define-method set_int - (of-object "GConfValue") - (c-name "gconf_value_set_int") - (return-type "none") - (parameters - '("gint" "the_int") - ) -) - -(define-method set_string - (of-object "GConfValue") - (c-name "gconf_value_set_string") - (return-type "none") - (parameters - '("const-gchar*" "the_str") - ) -) - -(define-method set_float - (of-object "GConfValue") - (c-name "gconf_value_set_float") - (return-type "none") - (parameters - '("gdouble" "the_float") - ) -) - -(define-method set_bool - (of-object "GConfValue") - (c-name "gconf_value_set_bool") - (return-type "none") - (parameters - '("gboolean" "the_bool") - ) -) - -(define-method set_schema - (of-object "GConfValue") - (c-name "gconf_value_set_schema") - (return-type "none") - (parameters - '("const-GConfSchema*" "sc") - ) -) - -(define-method set_schema_nocopy - (of-object "GConfValue") - (c-name "gconf_value_set_schema_nocopy") - (return-type "none") - (parameters - '("GConfSchema*" "sc") - ) -) - -(define-method set_car - (of-object "GConfValue") - (c-name "gconf_value_set_car") - (return-type "none") - (parameters - '("const-GConfValue*" "car") - ) -) - -(define-method set_car_nocopy - (of-object "GConfValue") - (c-name "gconf_value_set_car_nocopy") - (return-type "none") - (parameters - '("GConfValue*" "car") - ) -) - -(define-method set_cdr - (of-object "GConfValue") - (c-name "gconf_value_set_cdr") - (return-type "none") - (parameters - '("const-GConfValue*" "cdr") - ) -) - -(define-method set_cdr_nocopy - (of-object "GConfValue") - (c-name "gconf_value_set_cdr_nocopy") - (return-type "none") - (parameters - '("GConfValue*" "cdr") - ) -) - -(define-method set_list_type - (of-object "GConfValue") - (c-name "gconf_value_set_list_type") - (return-type "none") - (parameters - '("GConfValueType" "type") - ) -) - -(define-method set_list_nocopy - (of-object "GConfValue") - (c-name "gconf_value_set_list_nocopy") - (return-type "none") - (parameters - '("GSList*" "list") - ) -) - -(define-method set_list - (of-object "GConfValue") - (c-name "gconf_value_set_list") - (return-type "none") - (parameters - '("GSList*" "list") - ) -) - -(define-method to_string - (of-object "GConfValue") - (c-name "gconf_value_to_string") - (caller-owns-return #t) - (return-type "gchar*") -) - -(define-method get_schema - (of-object "GConfMetaInfo") - (c-name "gconf_meta_info_get_schema") - (return-type "const-char*") -) - -(define-method get_mod_user - (of-object "GConfMetaInfo") - (c-name "gconf_meta_info_get_mod_user") - (return-type "const-char*") -) - -(define-method mod_time - (of-object "GConfMetaInfo") - (c-name "gconf_meta_info_mod_time") - (return-type "GTime") -) - -(define-function meta_info_new - (is-constructor-of "GConfMetaInfo") - (c-name "gconf_meta_info_new") - (caller-owns-return #t) - (return-type "GConfMetaInfo*") -) - -(define-method free - (of-object "GConfMetaInfo") - (c-name "gconf_meta_info_free") - (return-type "none") -) - -(define-method set_schema - (of-object "GConfMetaInfo") - (c-name "gconf_meta_info_set_schema") - (return-type "none") - (parameters - '("const-gchar*" "schema_name") - ) -) - -(define-method set_mod_user - (of-object "GConfMetaInfo") - (c-name "gconf_meta_info_set_mod_user") - (return-type "none") - (parameters - '("const-gchar*" "mod_user") - ) -) - -(define-method set_mod_time - (of-object "GConfMetaInfo") - (c-name "gconf_meta_info_set_mod_time") - (return-type "none") - (parameters - '("GTime" "mod_time") - ) -) - -(define-method get_key - (of-object "GConfEntry") - (c-name "gconf_entry_get_key") - (return-type "const-char*") -) - -(define-method get_value - (of-object "GConfEntry") - (c-name "gconf_entry_get_value") - (return-type "GConfValue*") -) - -(define-method get_schema_name - (of-object "GConfEntry") - (c-name "gconf_entry_get_schema_name") - (return-type "const-char*") -) - -(define-method get_is_default - (of-object "GConfEntry") - (c-name "gconf_entry_get_is_default") - (return-type "gboolean") -) - -(define-method get_is_writable - (of-object "GConfEntry") - (c-name "gconf_entry_get_is_writable") - (return-type "gboolean") -) - -(define-function entry_new - (is-constructor-of "GConfEntry") - (c-name "gconf_entry_new") - (caller-owns-return #t) - (return-type "GConfEntry*") - (parameters - '("const-gchar*" "key") - '("const-GConfValue*" "val") - ) -) - -(define-function entry_new_nocopy - (c-name "gconf_entry_new_nocopy") - (return-type "GConfEntry*") - (parameters - '("gchar*" "key") - '("GConfValue*" "val") - ) -) - -(define-method copy - (of-object "GConfEntry") - (c-name "gconf_entry_copy") - (return-type "GConfEntry*") -) - -(define-method free - (of-object "GConfEntry") - (c-name "gconf_entry_free") - (return-type "none") -) - -(define-method ref - (of-object "GConfEntry") - (c-name "gconf_entry_ref") - (return-type "none") -) - -(define-method unref - (of-object "GConfEntry") - (c-name "gconf_entry_unref") - (return-type "none") -) - -(define-method steal_value - (of-object "GConfEntry") - (c-name "gconf_entry_steal_value") - (return-type "GConfValue*") -) - -(define-method set_value - (of-object "GConfEntry") - (c-name "gconf_entry_set_value") - (return-type "none") - (parameters - '("const-GConfValue*" "val") - ) -) - -(define-method set_value_nocopy - (of-object "GConfEntry") - (c-name "gconf_entry_set_value_nocopy") - (return-type "none") - (parameters - '("GConfValue*" "val") - ) -) - -(define-method set_schema_name - (of-object "GConfEntry") - (c-name "gconf_entry_set_schema_name") - (return-type "none") - (parameters - '("const-gchar*" "name") - ) -) - -(define-method set_is_default - (of-object "GConfEntry") - (c-name "gconf_entry_set_is_default") - (return-type "none") - (parameters - '("gboolean" "is_default") - ) -) - -(define-method set_is_writable - (of-object "GConfEntry") - (c-name "gconf_entry_set_is_writable") - (return-type "none") - (parameters - '("gboolean" "is_writable") - ) -) - -(define-method notify_add - (of-object "GConfEngine") - (c-name "gconf_engine_notify_add") - (return-type "guint") - (parameters - '("const-gchar*" "namespace_section") - '("GConfNotifyFunc" "func") - '("gpointer" "user_data") - '("GError**" "err") - ) -) - -(define-method notify_remove - (of-object "GConfEngine") - (c-name "gconf_engine_notify_remove") - (return-type "none") - (parameters - '("guint" "cnxn") - ) -) - -(define-method get - (of-object "GConfEngine") - (c-name "gconf_engine_get") - (return-type "GConfValue*") - (parameters - '("const-gchar*" "key") - '("GError**" "err") - ) -) - -(define-method get_without_default - (of-object "GConfEngine") - (c-name "gconf_engine_get_without_default") - (caller-owns-return #t) - (return-type "GConfValue*") - (parameters - '("const-gchar*" "key") - '("GError**" "err") - ) -) - -(define-method get_entry - (of-object "GConfEngine") - (c-name "gconf_engine_get_entry") - (caller-owns-return #t) - (return-type "GConfEntry*") - (parameters - '("const-gchar*" "key") - '("const-gchar*" "locale") - '("gboolean" "use_schema_default") - '("GError**" "err") - ) -) - -(define-method get_with_locale - (of-object "GConfEngine") - (c-name "gconf_engine_get_with_locale") - (caller-owns-return #t) - (return-type "GConfValue*") - (parameters - '("const-gchar*" "key") - '("const-gchar*" "locale") - '("GError**" "err") - ) -) - -(define-method get_default_from_schema - (of-object "GConfEngine") - (c-name "gconf_engine_get_default_from_schema") - (caller-owns-return #t) - (return-type "GConfValue*") - (parameters - '("const-gchar*" "key") - '("GError**" "err") - ) -) - -(define-method set - (of-object "GConfEngine") - (c-name "gconf_engine_set") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("const-GConfValue*" "value") - '("GError**" "err") - ) -) - -(define-method unset - (of-object "GConfEngine") - (c-name "gconf_engine_unset") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("GError**" "err") - ) -) - -(define-method associate_schema - (of-object "GConfEngine") - (c-name "gconf_engine_associate_schema") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("const-gchar*" "schema_key") - '("GError**" "err") - ) -) - -(define-method all_entries - (of-object "GConfEngine") - (c-name "gconf_engine_all_entries") - (return-type "GSList*") - (parameters - '("const-gchar*" "dir") - '("GError**" "err") - ) -) - -(define-method all_dirs - (of-object "GConfEngine") - (c-name "gconf_engine_all_dirs") - (return-type "GSList*") - (parameters - '("const-gchar*" "dir") - '("GError**" "err") - ) -) - -(define-method suggest_sync - (of-object "GConfEngine") - (c-name "gconf_engine_suggest_sync") - (return-type "none") - (parameters - '("GError**" "err") - ) -) - -(define-method dir_exists - (of-object "GConfEngine") - (c-name "gconf_engine_dir_exists") - (return-type "gboolean") - (parameters - '("const-gchar*" "dir") - '("GError**" "err") - ) -) - -(define-method remove_dir - (of-object "GConfEngine") - (c-name "gconf_engine_remove_dir") - (return-type "none") - (parameters - '("const-gchar*" "dir") - '("GError**" "err") - ) -) - -(define-method key_is_writable - (of-object "GConfEngine") - (c-name "gconf_engine_key_is_writable") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("GError**" "err") - ) -) - -(define-function valid_key - (c-name "gconf_valid_key") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("gchar**" "why_invalid") - ) -) - -(define-function key_is_below - (c-name "gconf_key_is_below") - (return-type "gboolean") - (parameters - '("const-gchar*" "above") - '("const-gchar*" "below") - ) -) - -(define-function concat_dir_and_key - (c-name "gconf_concat_dir_and_key") - (caller-owns-return #t) - (return-type "gchar*") - (parameters - '("const-gchar*" "dir") - '("const-gchar*" "key") - ) -) - -(define-function unique_key - (c-name "gconf_unique_key") - (caller-owns-return #t) - (return-type "gchar*") -) - -(define-function escape_key - (c-name "gconf_escape_key") - (caller-owns-return #t) - (return-type "char*") - (parameters - '("const-char*" "arbitrary_text") - '("int" "len") - ) -) - -(define-function unescape_key - (c-name "gconf_unescape_key") - (caller-owns-return #t) - (return-type "char*") - (parameters - '("const-char*" "escaped_key") - '("int" "len") - ) -) - -(define-method get_float - (of-object "GConfEngine") - (c-name "gconf_engine_get_float") - (return-type "gdouble") - (parameters - '("const-gchar*" "key") - '("GError**" "err") - ) -) - -(define-method get_int - (of-object "GConfEngine") - (c-name "gconf_engine_get_int") - (return-type "gint") - (parameters - '("const-gchar*" "key") - '("GError**" "err") - ) -) - -(define-method get_string - (of-object "GConfEngine") - (c-name "gconf_engine_get_string") - (caller-owns-return #t) - (return-type "gchar*") - (parameters - '("const-gchar*" "key") - '("GError**" "err") - ) -) - -(define-method get_bool - (of-object "GConfEngine") - (c-name "gconf_engine_get_bool") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("GError**" "err") - ) -) - -(define-method get_schema - (of-object "GConfEngine") - (c-name "gconf_engine_get_schema") - (caller-owns-return #t) - (return-type "GConfSchema*") - (parameters - '("const-gchar*" "key") - '("GError**" "err") - ) -) - -(define-method get_list - (of-object "GConfEngine") - (c-name "gconf_engine_get_list") - (caller-owns-return #t) - (return-type "GSList*") - (parameters - '("const-gchar*" "key") - '("GConfValueType" "list_type") - '("GError**" "err") - ) -) - -(define-method get_pair - (of-object "GConfEngine") - (c-name "gconf_engine_get_pair") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("GConfValueType" "car_type") - '("GConfValueType" "cdr_type") - '("gpointer" "car_retloc") - '("gpointer" "cdr_retloc") - '("GError**" "err") - ) -) - -(define-method set_float - (of-object "GConfEngine") - (c-name "gconf_engine_set_float") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("gdouble" "val") - '("GError**" "err") - ) -) - -(define-method set_int - (of-object "GConfEngine") - (c-name "gconf_engine_set_int") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("gint" "val") - '("GError**" "err") - ) -) - -(define-method set_string - (of-object "GConfEngine") - (c-name "gconf_engine_set_string") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("const-gchar*" "val") - '("GError**" "err") - ) -) - -(define-method set_bool - (of-object "GConfEngine") - (c-name "gconf_engine_set_bool") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("gboolean" "val") - '("GError**" "err") - ) -) - -(define-method set_schema - (of-object "GConfEngine") - (c-name "gconf_engine_set_schema") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("const-GConfSchema*" "val") - '("GError**" "err") - ) -) - -(define-method set_list - (of-object "GConfEngine") - (c-name "gconf_engine_set_list") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("GConfValueType" "list_type") - '("GSList*" "list") - '("GError**" "err") - ) -) - -(define-method set_pair - (of-object "GConfEngine") - (c-name "gconf_engine_set_pair") - (return-type "gboolean") - (parameters - '("const-gchar*" "key") - '("GConfValueType" "car_type") - '("GConfValueType" "cdr_type") - '("gconstpointer" "address_of_car") - '("gconstpointer" "address_of_cdr") - '("GError**" "err") - ) -) - -(define-function string_to_enum - (c-name "gconf_string_to_enum") - (return-type "gboolean") - (parameters - '("GConfEnumStringPair[]" "lookup_table") - '("const-gchar*" "str") - '("gint*" "enum_value_retloc") - ) -) - -(define-function enum_to_string - (c-name "gconf_enum_to_string") - (return-type "const-gchar*") - (parameters - '("GConfEnumStringPair[]" "lookup_table") - '("gint" "enum_value") - ) -) - -(define-function debug_shutdown - (c-name "gconf_debug_shutdown") - (return-type "int") -) - -(define-function init - (c-name "gconf_init") - (return-type "gboolean") - (parameters - '("int" "argc") - '("char**" "argv") - '("GError**" "err") - ) -) - -(define-function is_initialized - (c-name "gconf_is_initialized") - (return-type "gboolean") -) - -(define-function preinit - (c-name "gconf_preinit") - (return-type "none") - (parameters - '("gpointer" "app") - '("gpointer" "mod_info") - ) -) - -(define-function postinit - (c-name "gconf_postinit") - (return-type "none") - (parameters - '("gpointer" "app") - '("gpointer" "mod_info") - ) -) - -(define-method get_full - (of-object "GConfEngine") - (c-name "gconf_engine_get_full") - (return-type "GConfValue*") - (parameters - '("const-gchar*" "key") - '("const-gchar*" "locale") - '("gboolean" "use_schema_default") - '("gboolean*" "is_default_p") - '("gboolean*" "is_writable_p") - '("GError**" "err") - ) -) - diff --git a/util/gconf/gconf.override b/util/gconf/gconf.override deleted file mode 100644 index 337653d..0000000 --- a/util/gconf/gconf.override +++ /dev/null @@ -1,920 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4 -*- */ -%% -headers -#include <Python.h> - -#include "gconf-fixes.h" -#include "gconf-types.h" - -#define NO_IMPORT_PYGOBJECT -#include "pygobject.h" -#include <glib.h> -#include <gconf/gconf-client.h> -#include <gconf/gconf-enum-types.h> -#include "config.h" - -static gpointer pygconf_parse_pygvalue(GConfValueType gvalue_type, - PyObject *pyvalue); -%% -modulename gconf -%% -import gobject.GObject as PyGObject_Type -%% -ignore-glob - _* - gconf_*init -%% -ignore - gconf_change_set_get_type - gconf_client_get_type - gconf_value_type_get_type - gconf_error_get_type - gconf_client_preload_type_get_type - gconf_client_error_handling_mode_get_type - gconf_value_set_car_nocopy - gconf_value_set_cdr_nocopy - gconf_client_change_set_from_currentv - gconf_value_set_list_nocopy - -%% -override-slot GConfClient.tp_init - -static int -_wrap_gconf_client_tp_init(PyGObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":gconf.Client.__init__", kwlist)) { - return -1; - } - self->obj = (GObject *) gconf_client_get_default(); - pygobject_register_wrapper((PyObject *)self); - return 0; -} - -%% -override gconf_client_notify_add kwargs -void -pygconf_client_notify_add(GConfClient *client, - guint cnxn_id, - GConfEntry *entry, - gpointer user_data) -{ - PyObject *func; - PyObject *userdata = NULL; - PyObject *ret; - PyObject *tuple = (PyObject*)user_data; - PyGILState_STATE state; - - state = pyg_gil_state_ensure(); - - g_assert(PyTuple_Check(tuple)); - func = PyTuple_GetItem(tuple, 0); - userdata = PyTuple_GetItem(tuple, 1); - - if (!userdata) { - ret = PyObject_CallFunction(func, "NNN", - pygobject_new((GObject *)client), - PyLong_FromUnsignedLong(cnxn_id), - pyg_boxed_new(GCONF_TYPE_ENTRY, - entry, - TRUE, TRUE)); - } else { - ret = PyObject_CallFunction(func, "NNNO", - pygobject_new((GObject *)client), - PyLong_FromUnsignedLong(cnxn_id), - pyg_boxed_new(GCONF_TYPE_ENTRY, - entry, - TRUE, TRUE), - userdata); - } - - if (ret == NULL) - PyErr_Print(); - else - Py_DECREF(ret); - - pyg_gil_state_release(state); -} - -static PyObject * -_wrap_gconf_client_notify_add(PyGObject *self, PyObject *args, - PyObject *kwargs) -{ - static char *kwlist[] = { "namespace_section", "func", - "user_data", NULL }; - gchar *namespace_section; - PyObject *callback; - PyObject *extra = NULL; - PyObject *data; - guint retval; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "sO|O:GConfClient.notify_ad", - kwlist, &namespace_section, - &callback, &extra)) { - return NULL; - } - - if (!PyCallable_Check(callback)) { - PyErr_SetString(PyExc_TypeError, "second arg not callable"); - return NULL; - } - - if (extra) { - Py_INCREF(extra); - } else { - extra = PyTuple_New(0); - } - - data = Py_BuildValue("(ON)", callback, extra); - - retval = gconf_client_notify_add(GCONF_CLIENT(self->obj), - namespace_section, - pygconf_client_notify_add, - data, - (GFreeFunc)pyg_destroy_notify, - NULL); - - return PyLong_FromUnsignedLong((unsigned long) retval); -} - -%% -override gconf_client_all_entries args -static PyObject * -_wrap_gconf_client_all_entries(PyGObject *self, PyObject *args) -{ - gchar *path; - GError *err = NULL; - GSList *values; - GSList *list; - PyObject *pylist; - int i = 0; - - if (!PyArg_ParseTuple(args, "s:GConfClient.all_entries", &path)) { - return NULL; - } - - values = gconf_client_all_entries(GCONF_CLIENT(self->obj), path, &err); - if (pyg_error_check(&err)) { - return NULL; - } - - pylist = PyTuple_New(g_slist_length(values)); - for (list = values; list; list = list->next) { - GConfEntry *entry = list->data; - PyObject *pyentry = pyg_boxed_new(GCONF_TYPE_ENTRY, entry, - FALSE, TRUE); - PyTuple_SetItem(pylist, i++, pyentry); - } - - return pylist; -} - -%% -override gconf_client_all_dirs args -static PyObject * -_wrap_gconf_client_all_dirs(PyGObject *self, PyObject *args) -{ - gchar *path; - GError *err = NULL; - GSList *values; - GSList *list; - PyObject *pylist; - int i = 0; - - if (!PyArg_ParseTuple(args, "s:GConfClient.all_dirs", &path)) { - return NULL; - } - - values = gconf_client_all_dirs(GCONF_CLIENT(self->obj), path, &err); - if (pyg_error_check(&err)) { - return NULL; - } - - pylist = PyTuple_New(g_slist_length(values)); - for (list = values; list; list = list->next) { - PyObject *pystring = PyString_FromString(list->data); - - PyTuple_SetItem(pylist, i++, pystring); - } - - return pylist; -} - -%% -override gconf_client_get_pair kwargs -/* Return a proper PyObject for retloc based on its type. */ -static PyObject * -pygconf_parse_gvalue(GConfValueType gvalue_type, gpointer retloc) -{ - PyObject *retval; - switch(gvalue_type) { - case GCONF_VALUE_INT: - case GCONF_VALUE_BOOL: - retval = PyInt_FromLong(*(gint*)retloc); - break; - case GCONF_VALUE_FLOAT: - retval = PyFloat_FromDouble(*(gdouble*)retloc); - break; - case GCONF_VALUE_STRING: - { - gchar **s = (gchar **) retloc; - if (*s) - retval = PyString_FromString(*s); - else { - Py_INCREF(Py_None); - return Py_None; - } - break; - } - case GCONF_VALUE_SCHEMA: - retval = pyg_boxed_new(GCONF_TYPE_SCHEMA, *(GConfSchema**)retloc, - TRUE, TRUE); - break; - default: - PyErr_SetString(PyExc_TypeError, "Unknown GConfValueType."); - retval = NULL; - break; - } - return retval; -} - -/* Get the value of a PyObject from its type. */ -/* g_new0() on returned pointer, need to free it. */ -static gpointer -pygconf_parse_pygvalue(GConfValueType gvalue_type, PyObject *pyvalue) -{ - gpointer retval; - retval = g_new0(gpointer, 1); - switch(gvalue_type) { - case GCONF_VALUE_INT: - case GCONF_VALUE_BOOL: - *(gint*)retval = (gint) PyInt_AsLong(pyvalue); - break; - case GCONF_VALUE_FLOAT: - *(gdouble*)retval = PyFloat_AsDouble(pyvalue); - break; - case GCONF_VALUE_STRING: - *(gchar**)retval = PyString_AsString(pyvalue); - break; - case GCONF_VALUE_SCHEMA: - if (pyg_boxed_check(pyvalue, GCONF_TYPE_SCHEMA)) { - *(GConfSchema**)retval = pyg_boxed_get(pyvalue, GConfSchema); - } else { - PyErr_SetString(PyExc_TypeError, - "value should be a GConfSchema"); - free(retval); - retval = NULL; - } - break; - default: - PyErr_SetString(PyExc_TypeError, "Unknown GConfValueType."); - free(retval); - retval = NULL; - break; - } - return retval; -} - -static gpointer -pygconf_new_type(GConfValueType t) -{ - gpointer retval; - switch(t) { - case GCONF_VALUE_INT: - case GCONF_VALUE_BOOL: - retval = g_new0(gint, 1); - break; - case GCONF_VALUE_FLOAT: - retval = g_new0(gdouble, 1); - break; - case GCONF_VALUE_STRING: - retval = g_new0(gchar, 1); - break; - case GCONF_VALUE_SCHEMA: - retval = gconf_schema_new(); - break; - default: - PyErr_SetString(PyExc_TypeError, "Unknown GConfValueType."); - retval = NULL; - break; - } - return retval; -} - -static PyObject * -_wrap_gconf_client_get_pair(PyGObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "key", "car_type", "cdr_type", NULL }; - char *key; - PyObject *pycar_type = NULL, *pycdr_type = NULL; - PyObject *retcar = NULL, *retcdr = NULL; - GConfValueType car_type, cdr_type; - gpointer car_retloc = NULL; - gpointer cdr_retloc = NULL; - int ret; - - GError *err = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sOO:GConfClient.get_pair", - kwlist, &key, &pycar_type, &pycdr_type)) - return NULL; - - if (pyg_enum_get_value(GCONF_TYPE_VALUE_TYPE, - pycar_type, (gint *)&car_type)) - return NULL; - if (pyg_enum_get_value(GCONF_TYPE_VALUE_TYPE, - pycdr_type, (gint *)&cdr_type)) - return NULL; - - car_retloc = pygconf_new_type(car_type); - if (!car_retloc) - return NULL; - cdr_retloc = pygconf_new_type(cdr_type); - if (!cdr_retloc) { - if(car_type == GCONF_VALUE_SCHEMA) - gconf_schema_free(car_retloc); - else - g_free(car_retloc); - return NULL; - } - - ret = gconf_client_get_pair(GCONF_CLIENT(self->obj), key, car_type, - cdr_type, car_retloc, cdr_retloc, &err); - if (pyg_error_check(&err)) - return NULL; - retcar = pygconf_parse_gvalue(car_type, car_retloc); - retcdr = pygconf_parse_gvalue(cdr_type, cdr_retloc); - - if (car_type != GCONF_VALUE_SCHEMA) - g_free(car_retloc); - /* FIXME: gconf_schema_free(car_retloc)? */ - else - gconf_schema_free(car_retloc); - - if (cdr_type != GCONF_VALUE_SCHEMA) - g_free(cdr_retloc); - else - gconf_schema_free(cdr_retloc); - - if (!retcar || !retcdr) - return NULL; - return Py_BuildValue("(NN)", retcar, retcdr); -} - -%% -override gconf_client_set_pair kwargs -static PyObject * -_wrap_gconf_client_set_pair(PyGObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "key", "car_type", "cdr_type", - "car", "cdr", NULL }; - char *key; - PyObject *pycar_type = NULL, *pycdr_type = NULL; - PyObject *pycar = NULL, *pycdr = NULL; - - GConfValueType car_type, cdr_type; - gpointer car, cdr; - int ret; - GError *err = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "sOOOO:GConfClient.set_pair", - kwlist, &key, &pycar_type, &pycdr_type, - &pycar, &pycdr)) - return NULL; - - if (pyg_enum_get_value(GCONF_TYPE_VALUE_TYPE, - pycar_type, (gint *)&car_type)) - return NULL; - if (pyg_enum_get_value(GCONF_TYPE_VALUE_TYPE, - pycdr_type, (gint *)&cdr_type)) - return NULL; - car = pygconf_parse_pygvalue(car_type, pycar); - if (!car) - return NULL; - cdr = pygconf_parse_pygvalue(cdr_type, pycdr); - if (!cdr) { - g_free(car); - return NULL; - } - - - ret = gconf_client_set_pair(GCONF_CLIENT(self->obj), - key, car_type, cdr_type, - car, cdr, &err); - - g_free(car); - g_free(cdr); - - if (pyg_error_check(&err)) - return NULL; - return PyInt_FromLong(ret); -} - -%% -override gconf_client_get_list kwargs - static PyObject * -pygconf_parse_listvalue(GConfValueType gvalue_type, gpointer retloc) -{ - PyObject *retval; - switch(gvalue_type) { - case GCONF_VALUE_INT: - case GCONF_VALUE_BOOL: - retval = PyInt_FromLong(GPOINTER_TO_INT(retloc)); - break; - case GCONF_VALUE_FLOAT: - retval = PyFloat_FromDouble(*(gdouble*)retloc); - break; - case GCONF_VALUE_STRING: - retval = PyString_FromString((gchar*)retloc); - break; - case GCONF_VALUE_SCHEMA: - retval = pyg_boxed_new(GCONF_TYPE_SCHEMA, (GConfSchema*)retloc, - TRUE, TRUE); - break; - default: - /* Should not reach here. get_list should always valid. */ - PyErr_SetString(PyExc_TypeError, "Unknown GConfValueType."); - retval = NULL; - break; - } - return retval; -} - -static PyObject * -_wrap_gconf_client_get_list(PyGObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "key", "list_type", NULL }; - char *key; - PyObject *py_type = NULL; - PyObject *py_list = NULL; - GConfValueType lstype; - GSList *retlist, *ilist; - gpointer data; - int lslen, i; - - GError *err = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO:GConfClient.get_list", - kwlist, &key, &py_type)) - return NULL; - - if (pyg_enum_get_value(GCONF_TYPE_VALUE_TYPE, py_type, (gint *)&lstype)) - return NULL; - - retlist = gconf_client_get_list(GCONF_CLIENT(self->obj), key, - lstype, &err); - if (pyg_error_check(&err)) { - return NULL; - } else if (retlist == NULL) { - return PyList_New(0); - } - - lslen = g_slist_length(retlist); - i = 0; - py_list = PyList_New(lslen); - for (ilist = retlist; ilist; ilist = ilist->next) { - PyObject *py_data; - data = ilist->data; - py_data = pygconf_parse_listvalue(lstype, data); - if (!py_data) { - g_slist_free(retlist); - return NULL; - } - PyList_SetItem(py_list, i, py_data); - i++; - if (lstype == GCONF_VALUE_SCHEMA) - gconf_schema_free(data); - else if(lstype == GCONF_VALUE_FLOAT || lstype == GCONF_VALUE_STRING) - g_free(data); - } - g_slist_free(retlist); - return py_list; -} - -%% -override gconf_client_set_list kwargs -static PyObject * -_wrap_gconf_client_set_list(PyGObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "key", "list_type", "list", NULL }; - char *key; - PyObject *py_type = NULL; - PyObject *py_list = NULL; - GSList *clist = NULL; - GSList *tmplist, *pointlist=NULL; - GConfValueType list_type; - int ret, i; - int retdata; /* Error flag. */ - GError *err = NULL; - - ret = 1; - retdata = 1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sOO:GConfClient.set_list", - kwlist, &key, &py_type, &py_list)) - return NULL; - if (!PyTuple_Check(py_list) && !PyList_Check(py_list)) { - PyErr_SetString(PyExc_TypeError, - "3rd argument should be a sequence type."); - return NULL; - } - - if (pyg_enum_get_value(GCONF_TYPE_VALUE_TYPE, py_type, (gint *)&list_type)) - return NULL; - - for (i = 0; i < PySequence_Size(py_list) && retdata; i++) { - gpointer data; - data = pygconf_parse_pygvalue(list_type, - PySequence_GetItem(py_list, i)); - if (data == NULL) { - retdata = 0; - break; - } - /* What to free the list later. */ - pointlist = g_slist_append(pointlist, data); - switch(list_type){ - case GCONF_VALUE_INT: - case GCONF_VALUE_BOOL: - clist = g_slist_append(clist, GINT_TO_POINTER(*(gint*)data)); - break; - case GCONF_VALUE_FLOAT: - clist = g_slist_append(clist, (gdouble*)data); - break; - case GCONF_VALUE_STRING: - clist = g_slist_append(clist, *(gchar**)data); - break; - case GCONF_VALUE_SCHEMA: - clist = g_slist_append(clist, *(GConfSchema**)data); - break; - default: - PyErr_SetString(PyExc_TypeError, "Unknown GConfValueType."); - retdata = 0; - break; - } - } - - if (retdata) - ret = gconf_client_set_list(GCONF_CLIENT(self->obj), key, list_type, - clist, &err); - - for (tmplist = pointlist; tmplist; tmplist = tmplist->next) { - g_free(tmplist->data); - } - g_slist_free(pointlist); - g_slist_free(clist); - - if (pyg_error_check(&err) || !retdata) - return NULL; - return PyInt_FromLong(ret); -} - -%% -override gconf_value_get_car args -static PyObject * -_wrap_gconf_value_get_car(PyGObject *self, PyObject *args, PyObject *kwargs) -{ - GConfValue* vobj; - - vobj = gconf_value_get_car(pyg_boxed_get(self, GConfValue)); - return pyg_boxed_new(GCONF_TYPE_VALUE, vobj, TRUE, TRUE); -} - -%% -override gconf_value_get_cdr args -static PyObject * -_wrap_gconf_value_get_cdr(PyGObject *self, PyObject *args, PyObject *kwargs) -{ - GConfValue* vobj; - - vobj = gconf_value_get_cdr(pyg_boxed_get(self, GConfValue)); - return pyg_boxed_new(GCONF_TYPE_VALUE, vobj, TRUE, TRUE); -} -%% -override gconf_value_get_list args -static PyObject * -_wrap_gconf_value_get_list(PyGObject *self, PyObject *args, PyObject *kwargs) -{ - GConfValue *value; - PyObject *pylist; - GSList *values = NULL, *list; - int i = 0; - - value = pyg_boxed_get(self, GConfValue); - if (value->type != GCONF_VALUE_LIST) { - PyErr_SetString(PyExc_TypeError, "gconf value does not contain a list."); - return NULL; - } - values = gconf_value_get_list(value); - - pylist = PyTuple_New(g_slist_length(values)); - for (list = values; list; list = list->next) { - PyObject *pyvalue; - value = list->data; - pyvalue = pyg_boxed_new(GCONF_TYPE_VALUE, value, TRUE, TRUE); - - PyTuple_SetItem(pylist, i++, pyvalue); - } - - return pylist; -} -%% -override gconf_value_get_int noargs -static PyObject * -_wrap_gconf_value_get_int(PyObject *self) -{ - int ret; - GConfValue *value; - - value = pyg_boxed_get(self, GConfValue); - if (value->type != GCONF_VALUE_INT) { - PyErr_SetString(PyExc_TypeError, "gconf value does not contain an integer."); - return NULL; - } - ret = gconf_value_get_int(value); - return PyInt_FromLong(ret); -} -%% -override gconf_value_get_string noargs -static PyObject * -_wrap_gconf_value_get_string(PyObject *self) -{ - const gchar *ret; - GConfValue *value; - - value = pyg_boxed_get(self, GConfValue); - if (value->type != GCONF_VALUE_STRING) { - PyErr_SetString(PyExc_TypeError, "gconf value does not contain a string."); - return NULL; - } - ret = gconf_value_get_string(value); - if (ret) - return PyString_FromString(ret); - Py_INCREF(Py_None); - return Py_None; -} -%% -override gconf_value_get_float noargs -static PyObject * -_wrap_gconf_value_get_float(PyObject *self) -{ - double ret; - GConfValue *value; - - value = pyg_boxed_get(self, GConfValue); - if (value->type != GCONF_VALUE_FLOAT) { - PyErr_SetString(PyExc_TypeError, "gconf value does not contain a float."); - return NULL; - } - ret = gconf_value_get_float(value); - return PyFloat_FromDouble(ret); -} -%% -override gconf_value_get_bool noargs -static PyObject * -_wrap_gconf_value_get_bool(PyObject *self) -{ - int ret; - PyObject *py_ret; - GConfValue *value; - - value = pyg_boxed_get(self, GConfValue); - if (value->type != GCONF_VALUE_BOOL) { - PyErr_SetString(PyExc_TypeError, "gconf value does not contain a boolean."); - return NULL; - } - ret = gconf_value_get_bool(value); - py_ret = ret ? Py_True : Py_False; - Py_INCREF(py_ret); - return py_ret; -} -%% -override gconf_value_set_list kwargs -static PyObject * -_wrap_gconf_value_set_list(PyObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "list", NULL }; - GSList *list; - PyObject *py_list; - int i, len; - GConfValue *value = pyg_boxed_get(self, GConfValue); - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!:GConfValue.set_list", kwlist, - &PyList_Type, &py_list)) - return NULL; - if (value->type != GCONF_VALUE_LIST) { - PyErr_SetString(PyExc_TypeError, "gconf value type must be list."); - return NULL; - } - - len = PyList_Size(py_list); - for (i = 0, list = NULL; i < len; i++) { - PyObject *item = PyList_GET_ITEM(py_list, i); - if (!pyg_boxed_check(item, GCONF_TYPE_VALUE)) { - PyErr_SetString(PyExc_TypeError, "list elements must be of type gconf.Value"); - g_slist_free(list); - return NULL; - } - list = g_slist_append(list, pyg_boxed_get(item, GConfValue)); - } - gconf_value_set_list(value, list); - g_slist_free(list); - Py_INCREF(Py_None); - return Py_None; -} -%% -override gconf_client_change_set_from_current -static PyObject * -_wrap_gconf_client_change_set_from_current(PyGObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "keys", NULL }; - PyObject *py_list; - const gchar **keys; - GError *err = NULL; - GConfChangeSet *ret; - int len, i; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!:GConfClient.change_set_from_current", - kwlist, &PyList_Type, &py_list)) - return NULL; - len = PyList_Size(py_list); - keys = g_new(const gchar *, len + 1); - for (i = 0; i < len; ++i) { - PyObject *item = PyList_GET_ITEM(py_list, i); - if (!PyString_Check(item)) { - g_free(keys); - PyErr_SetString(PyExc_TypeError, "list elements must be of type str"); - return NULL; - } - keys[i] = PyString_AsString(item); - } - keys[i] = NULL; - ret = gconf_client_change_set_from_currentv(GCONF_CLIENT(self->obj), keys, &err); - g_free(keys); - if (pyg_error_check(&err)) - return NULL; - /* pyg_boxed_new handles NULL checking */ - return pyg_boxed_new(GCONF_TYPE_CHANGE_SET, ret, TRUE, TRUE); -} -%% -override gconf_change_set_set_list kwargs -static PyObject * -_wrap_gconf_change_set_set_list(PyObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "key", "list_type", "list", NULL }; - char *key; - PyObject *py_list_type = NULL, *py_list; - GConfValueType list_type; - int i, len; - GSList *list; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sOO!:GConfChangeSet.set_list" - , kwlist, &key, &py_list_type, - &PyList_Type, &py_list)) - return NULL; - if (pyg_enum_get_value(GCONF_TYPE_VALUE_TYPE, py_list_type, (gint *)&list_type)) - return NULL; - - len = PyList_Size(py_list); - for (i = 0, list = NULL; i < len; i++) { - PyObject *item = PyList_GET_ITEM(py_list, i); - if (!pyg_boxed_check(item, GCONF_TYPE_VALUE)) { - PyErr_SetString(PyExc_TypeError, "list elements must be of type gconf.Value"); - g_slist_free(list); - return NULL; - } - list = g_slist_append(list, pyg_boxed_get(item, GConfValue)); - } - gconf_change_set_set_list(pyg_boxed_get(self, GConfChangeSet), key, list_type, list); - g_slist_free(list); - Py_INCREF(Py_None); - return Py_None; -} - -%% -define GConfClient.get_value kwargs - -static PyObject * -_wrap_g_conf_client_get_value(PyGObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "key", NULL }; - char *key; - GError *err = NULL; - GConfValue *value; - PyObject *py_ret; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs,"s:GConfClient.get_value", kwlist, &key)) - return NULL; - - value = gconf_client_get(GCONF_CLIENT(self->obj), key, &err); - - if (pyg_error_check(&err)) - return NULL; - - if (value == NULL) { - PyErr_Format(PyExc_ValueError, "gconf key %s has no value", key); - return NULL; - } - - switch (value->type) - { - case GCONF_VALUE_INVALID: - PyErr_SetString(PyExc_TypeError, "invalid value"); - py_ret = NULL; - break; - - case GCONF_VALUE_STRING: - py_ret = PyString_FromString(gconf_value_get_string(value)); - break; - case GCONF_VALUE_INT: - py_ret = PyInt_FromLong(gconf_value_get_int(value)); - break; - case GCONF_VALUE_FLOAT: - py_ret = PyFloat_FromDouble(gconf_value_get_float(value)); - break; - case GCONF_VALUE_BOOL: - py_ret = PyBool_FromLong(gconf_value_get_bool(value)); - break; - - case GCONF_VALUE_SCHEMA: - case GCONF_VALUE_LIST: - case GCONF_VALUE_PAIR: - PyErr_SetString(PyExc_TypeError, "value type not supported yet by this API"); - py_ret = NULL; - break; - default: - py_ret = NULL; - } - gconf_value_free(value); - return py_ret; -} - -%% -define GConfClient.set_value kwargs - -static PyObject * -_wrap_g_conf_client_set_value(PyGObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "key", "val", NULL }; - char *key; - PyObject *py_val; - GError *err = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs,"sO:GConfClient.set_value", kwlist, &key, &py_val)) - return NULL; - if (pyg_boxed_check(py_val, GCONF_TYPE_VALUE)) { - gconf_client_set(GCONF_CLIENT(self->obj), key, pyg_boxed_get(py_val, GConfValue), &err); - if (pyg_error_check(&err)) - return NULL; - } else { - if (PyBool_Check(py_val)) { - gconf_client_set_bool(GCONF_CLIENT(self->obj), key, PyInt_AsLong(py_val), &err); - } else if (PyInt_Check(py_val)) { - gconf_client_set_int(GCONF_CLIENT(self->obj), key, PyInt_AsLong(py_val), &err); - } else if (PyFloat_Check(py_val)) { - gconf_client_set_float(GCONF_CLIENT(self->obj), key, PyFloat_AsDouble(py_val), &err); - } else if (PyString_Check(py_val)) { - gconf_client_set_string(GCONF_CLIENT(self->obj), key, PyString_AsString(py_val), &err); - } else { - PyErr_SetString(PyExc_TypeError, "value type not supported yet by this API"); - return NULL; - } - if (pyg_error_check(&err)) - return NULL; - } - - Py_INCREF(Py_None); - return Py_None; -} - -%% -override gconf_value_new_from_string kwargs -static PyObject * -_wrap_gconf_value_new_from_string(PyObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "type", "str", NULL }; - PyObject *py_type = NULL; - char *str; - GConfValueType type; - GError *err = NULL; - GConfValue *ret; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os:value_new_from_string", kwlist, &py_type, &str)) - return NULL; - if (pyg_enum_get_value(GCONF_TYPE_VALUE_TYPE, py_type, (gpointer)&type)) - return NULL; - - if (type == GCONF_VALUE_LIST || type == GCONF_VALUE_PAIR) { - PyErr_SetString(PyExc_ValueError, "GConf value types LIST and PAIR are not valid for this function"); - return NULL; - } - - ret = gconf_value_new_from_string(type, str, &err); - - if (pyg_error_check(&err)) - return NULL; - /* pyg_boxed_new handles NULL checking */ - return pyg_boxed_new(GCONF_TYPE_VALUE, ret, TRUE, TRUE); -} diff --git a/util/gconf/gconfmodule.c b/util/gconf/gconfmodule.c deleted file mode 100644 index 60273fb..0000000 --- a/util/gconf/gconfmodule.c +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4 -*- */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* include this first, before NO_IMPORT_PYGOBJECT is defined */ -#include <pygobject.h> - -#include "gconf-types.h" - -void pygconf_register_classes (PyObject *d); -void pygconf_add_constants(PyObject *module, const gchar *strip_prefix); - -extern PyMethodDef pygconf_functions[]; -extern PyTypeObject PyGConfEngine_Type; - -DL_EXPORT(void) -initgconf (void) -{ - PyObject *m, *d; - - init_pygobject (); - - m = Py_InitModule ("gconf", pygconf_functions); - d = PyModule_GetDict (m); - - pygconf_register_classes (d); - pygconf_add_constants (m, "GCONF_"); - pygconf_register_engine_type (m); - - PyModule_AddObject(m, "Engine", (PyObject *) &PyGConfEngine_Type); -} diff --git a/util/gconf/wscript b/util/gconf/wscript deleted file mode 100644 index 442c629..0000000 --- a/util/gconf/wscript +++ /dev/null @@ -1,47 +0,0 @@ -# -*- python -*- -# encoding: utf-8 - -import os -import Common - -def configure(conf): - conf.env.append_value('MODULES_AVAILABLE', 'gconf') - if 'gconf' in conf.env['ENABLE_MODULES'] or 'all' in conf.env['ENABLE_MODULES']: - if conf.check_pkg('gconf-2.0 >= 2.12 pygobject-2.0', - destvar='GCONF', mandatory=False): - conf.env.append_value('MODULES_TO_BUILD', 'gconf') - - -def codegen(bld, module): - cmd = bld.create_obj('command-output') - cmd.command = 'pygtk-codegen-2.0' - cmd.command_is_external = True - cmd.prio = 5 - cmd.argv = [ - '--py_ssize_t-clean', - '--load-types', cmd.input_file('gconf-arg-types.py'), - '--prefix', 'py'+module, - '--override', cmd.input_file("%s.override" % module), - cmd.input_file("%s.defs" % module), - ] - cmd.stdout = '%s.c' % module - return cmd - - -def build(bld): - - if 'gconf' in bld.env()['MODULES_TO_BUILD']: - codegen(bld, 'gconf') - pyext = bld.create_pyext() - pyext.source = 'gconfmodule.c gconf.c gconf-fixes.c gconf-types.c' - pyext.target = 'gconf' - pyext.uselib = 'GCONF' - pyext.includes = '.' - pyext.inst_var = 'PYTHONDIR' - pyext.inst_dir = 'gtk-2.0' - - Common.install_files('DATADIR', os.path.join('pygtk', '2.0', 'defs'), - ['gconf.defs']) - - Common.install_files('DATADIR', os.path.join('pygtk', '2.0', 'argtypes'), - 'gconf-arg-types.py') diff --git a/xinput-ibus b/xinput-ibus index 7f6737d..be3dc26 100644 --- a/xinput-ibus +++ b/xinput-ibus @@ -1,8 +1,8 @@ XIM=ibus -XIM_PROGRAM="/usr/bin/ibus" +XIM_PROGRAM="/usr/bin/ibus-daemon" ICON="/usr/share/ibus/icons/ibus.svg" # XIM_ARGS="0xffffffff" PREFERENCE_PROGRAM=/usr/bin/ibus-setup -SHORT_DESC="iBus" +SHORT_DESC="IBus" GTK_IM_MODULE=ibus -QT_IM_MODULE=ibus +# QT_IM_MODULE=ibus |