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 /lib/gtk2/ibusimclient.c | |
parent | 41ad46305a88637dd99f00a2d2a3f455505d357b (diff) | |
download | ibus-aedad1ea0a7fef604aa27f4b58433fd8f2ece29e.tar.gz ibus-aedad1ea0a7fef604aa27f4b58433fd8f2ece29e.tar.xz ibus-aedad1ea0a7fef604aa27f4b58433fd8f2ece29e.zip |
re-implement ibus in c language.
Diffstat (limited to 'lib/gtk2/ibusimclient.c')
-rw-r--r-- | lib/gtk2/ibusimclient.c | 1536 |
1 files changed, 0 insertions, 1536 deletions
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); - } -} - - |