From f76a835e33cddb38ff90f6ee58baa5cfac687bee Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 8 Jun 2011 17:11:01 +0900 Subject: [PATCH] Implement IBus based activation. --- configure.ac | 21 ++++++++ src/Makefile.am | 7 +++ src/client-main.c | 53 +++++++++++++++++--- src/client.c | 125 ++++++++++++++++++++++++++++++++++++++++++---- src/client.h | 5 ++ 5 files changed, 194 insertions(+), 17 deletions(-) diff --git a/configure.ac b/configure.ac index 14eb6cef..a9119d42 100644 --- a/configure.ac +++ b/configure.ac @@ -136,6 +136,26 @@ fi AC_MSG_RESULT($enable_atspi) AM_CONDITIONAL(ENABLE_ATSPI, [test x$enable_atspi = xyes]) +dnl use IBus to capture focus events +AC_MSG_CHECKING([whether you enable IBus focus tracking]) +AC_ARG_ENABLE(ibus, + AS_HELP_STRING([--enable-ibus=no/yes], + [Enable IBus focus tracking default=no]),, + enable_atspi=yes) + +if test x$enable_ibus = xyes; then + PKG_CHECK_MODULES([IBUS], [ibus-1.0 >= 1.3.99], , enable_ibus=no) + if test x$enable_ibus = xyes; then + AC_DEFINE([HAVE_IBUS], [1], [Define if IBus is found]) + fi +fi +AC_MSG_RESULT($enable_ibus) +AM_CONDITIONAL(ENABLE_IBUS, [test x$enable_ibus = xyes]) + +if test x$enable_atspi = xyes -o x$enable_ibus = xyes; then + AC_DEFINE(ENABLE_FOCUS_LISTENER, [1], [Define if eekboard can follow focus changes]) +fi + dnl Python language binding AC_MSG_CHECKING([whether you enable Python language support]) AC_ARG_ENABLE(python, @@ -292,4 +312,5 @@ Build options: Build Python binding $enable_python Build document $enable_gtk_doc Support accessibility $enable_atspi + Support IBus focus events $enable_ibus ]) diff --git a/src/Makefile.am b/src/Makefile.am index 41b51cf2..6ed0491d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -55,6 +55,13 @@ eekboard_LDADD += \ $(ATSPI2_LIBS) endif +if ENABLE_IBUS +eekboard_CFLAGS += \ + $(IBUS_CFLAGS) +eekboard_LDADD += \ + $(IBUS_LIBS) +endif + eekboard_headers = client.h eekboard_SOURCES = client.c client-main.c diff --git a/src/client-main.c b/src/client-main.c index 82d44177..9811f9a6 100644 --- a/src/client-main.c +++ b/src/client-main.c @@ -24,6 +24,9 @@ #include #include #endif /* HAVE_ATSPI */ +#ifdef HAVE_IBUS +#include +#endif /* HAVE_IBUS */ #include #include #include "eekboard/eekboard.h" @@ -37,6 +40,7 @@ static gchar *opt_address = NULL; static gboolean opt_use_system_layout = FALSE; static gboolean opt_focus = FALSE; +static gchar *opt_focus_method = NULL; static gboolean opt_keystroke = FALSE; static gchar *opt_keyboard = NULL; @@ -56,9 +60,13 @@ static const GOptionEntry options[] = { N_("Connect to the given D-Bus address")}, {"use-system-layout", 'x', 0, G_OPTION_ARG_NONE, &opt_use_system_layout, N_("Use system keyboard layout")}, -#ifdef HAVE_ATSPI +#if ENABLE_FOCUS_LISTENER {"listen-focus", 'f', 0, G_OPTION_ARG_NONE, &opt_focus, - N_("Listen focus change events with AT-SPI")}, + N_("Listen focus change events")}, + {"focus-method", '\0', 0, G_OPTION_ARG_STRING, &opt_focus_method, + N_("Use the given focus method (\"atspi\" or \"ibus\")")}, +#endif /* ENABLE_FOCUS_LISTENER */ +#ifdef HAVE_ATSPI {"listen-keystroke", 's', 0, G_OPTION_ARG_NONE, &opt_keystroke, N_("Listen keystroke events with AT-SPI")}, #endif /* HAVE_ATSPI */ @@ -108,6 +116,12 @@ on_destroyed (EekboardEekboard *eekboard, g_main_loop_quit (loop); } +enum { + FOCUS_NONE, + FOCUS_ATSPI, + FOCUS_IBUS +}; + int main (int argc, char **argv) { @@ -119,6 +133,7 @@ main (int argc, char **argv) GError *error; GOptionContext *option_context; GMainLoop *loop; + gint focus; if (!gtk_init_check (&argc, &argv)) { g_printerr ("Can't init GTK\n"); @@ -172,8 +187,22 @@ main (int argc, char **argv) exit (1); } + focus = FOCUS_NONE; + if (opt_focus) { + if (opt_focus_method == NULL || + g_strcmp0 (opt_focus_method, "atspi") == 0) + focus = FOCUS_ATSPI; + else if (g_strcmp0 (opt_focus_method, "ibus") == 0) + focus = FOCUS_IBUS; + else { + g_printerr ("Unknown focus method \"%s\". " + "Try \"atspi\" or \"ibus\"\n", opt_focus_method); + exit (1); + } + } + #ifdef HAVE_ATSPI - if (opt_focus || opt_keystroke) { + if (focus == FOCUS_ATSPI || opt_keystroke) { GSettings *settings = g_settings_new ("org.gnome.desktop.interface"); if (g_settings_get_boolean (settings, "toolkit-accessibility")) { @@ -182,15 +211,15 @@ main (int argc, char **argv) exit (1); } - if (opt_focus && + if (focus == FOCUS_ATSPI && !eekboard_client_enable_atspi_focus (client)) { - g_printerr ("Can't register focus change event listeners\n"); + g_printerr ("Can't register AT-SPI focus change event listeners\n"); exit (1); } if (opt_keystroke && !eekboard_client_enable_atspi_keystroke (client)) { - g_printerr ("Can't register keystroke event listeners\n"); + g_printerr ("Can't register AT-SPI keystroke event listeners\n"); exit (1); } } else { @@ -200,6 +229,18 @@ main (int argc, char **argv) } #endif /* HAVE_ATSPI */ +#ifdef HAVE_IBUS + if (focus == FOCUS_IBUS) { + ibus_init (); + + if (focus == FOCUS_IBUS && + !eekboard_client_enable_ibus_focus (client)) { + g_printerr ("Can't register IBus focus change event listeners\n"); + exit (1); + } + } +#endif /* HAVE_IBUS */ + if (opt_use_system_layout && (opt_keyboard || opt_model || opt_layouts || opt_options)) { g_printerr ("Can't use --use-system-layout option with keyboard options\n"); exit (1); diff --git a/src/client.c b/src/client.c index 27003258..957ebbc2 100644 --- a/src/client.c +++ b/src/client.c @@ -32,6 +32,10 @@ #include #endif /* HAVE_FAKEKEY */ +#ifdef HAVE_IBUS +#include +#endif /* HAVE_IBUS */ + #include "eek/eek.h" #include "eek/eek-xkl.h" #include "eekboard/eekboard.h" @@ -68,12 +72,20 @@ struct _EekboardClient { gulong key_pressed_handler; gulong key_released_handler; +#if ENABLE_FOCUS_LISTENER + gboolean follows_focus; +#endif /* ENABLE_FOCUS_LISTENER */ + #ifdef HAVE_ATSPI AtspiAccessible *acc; - gboolean follows_focus; AtspiDeviceListener *keystroke_listener; #endif /* HAVE_ATSPI */ +#ifdef HAVE_IBUS + IBusBus *ibus_bus; + guint ibus_focus_message_filter; +#endif /* HAVE_IBUS */ + #ifdef HAVE_FAKEKEY FakeKey *fakekey; #endif /* HAVE_FAKEKEY */ @@ -184,6 +196,14 @@ eekboard_client_dispose (GObject *object) eekboard_client_disable_atspi_keystroke (client); #endif /* HAVE_ATSPI */ +#ifdef HAVE_IBUS + eekboard_client_disable_ibus_focus (client); + if (client->ibus_bus) { + g_object_unref (client->ibus_bus); + client->ibus_bus = NULL; + } +#endif /* HAVE_IBUS */ + #ifdef HAVE_FAKEKEY eekboard_client_disable_fakekey (client); #endif /* HAVE_FAKEKEY */ @@ -272,10 +292,16 @@ eekboard_client_init (EekboardClient *client) client->key_released_handler = 0; client->xkl_config_changed_handler = 0; client->xkl_state_changed_handler = 0; -#ifdef HAVE_ATSPI +#if ENABLE_FOCUS_LISTENER client->follows_focus = FALSE; +#endif /* ENABLE_FOCUS_LISTENER */ +#ifdef HAVE_ATSPI client->keystroke_listener = NULL; #endif /* HAVE_ATSPI */ +#ifdef HAVE_IBUS + client->ibus_bus = NULL; + client->ibus_focus_message_filter = 0; +#endif /* HAVE_IBUS */ #ifdef HAVE_FAKEKEY client->fakekey = NULL; #endif /* HAVE_FAKEKEY */ @@ -287,19 +313,19 @@ eekboard_client_set_xkl_config (EekboardClient *client, const gchar *layouts, const gchar *options) { -#ifdef HAVE_ATSPI +#if ENABLE_FOCUS_LISTENER return set_xkl_keyboard (client, !client->follows_focus, model, layouts, options); -#else +#else /* ENABLE_FOCUS_LISTENER */ return set_xkl_keyboard (client, TRUE, model, layouts, options); -#endif +#endif /* !ENABLE_FOCUS_LISTENER */ } gboolean @@ -338,15 +364,15 @@ eekboard_client_enable_xkl (EekboardClient *client) xkl_engine_start_listen (client->xkl_engine, XKLL_TRACK_KEYBOARD_STATE); -#ifdef HAVE_ATSPI +#if ENABLE_FOCUS_LISTENER return set_xkl_keyboard (client, !client->follows_focus, NULL, NULL, NULL); -#else +#else /* ENABLE_FOCUS_LISTENER */ return set_xkl_keyboard (client, TRUE, NULL, NULL, NULL); -#endif +#endif /* !ENABLE_FOCUS_LISTENER */ } void @@ -546,6 +572,83 @@ keystroke_listener_cb (const AtspiDeviceEvent *stroke, } #endif /* HAVE_ATSPI */ +#ifdef HAVE_IBUS +static void +add_match_rule (GDBusConnection *connection, + const gchar *match_rule) +{ + GError *error; + GDBusMessage *message; + + message = g_dbus_message_new_method_call ("org.freedesktop.DBus", /* name */ + "/org/freedesktop/DBus", /* path */ + "org.freedesktop.DBus", /* interface */ + "AddMatch"); + g_dbus_message_set_body (message, g_variant_new ("(s)", match_rule)); + error = NULL; + g_dbus_connection_send_message (connection, + message, + G_DBUS_SEND_MESSAGE_FLAGS_NONE, + NULL, + &error); + g_object_unref (message); +} + +static GDBusMessage * +focus_message_filter (GDBusConnection *connection, + GDBusMessage *message, + gboolean incoming, + gpointer user_data) +{ + EekboardClient *client = user_data; + + if (incoming && + g_strcmp0 (g_dbus_message_get_interface (message), + IBUS_INTERFACE_INPUT_CONTEXT) == 0) { + const gchar *member = g_dbus_message_get_member (message); + + if (g_strcmp0 (member, "FocusIn") == 0) { + eekboard_context_show_keyboard (client->context, NULL); + } + } + + return message; +} + +gboolean +eekboard_client_enable_ibus_focus (EekboardClient *client) +{ + GDBusConnection *connection; + GError *error; + + client->ibus_bus = ibus_bus_new (); + connection = ibus_bus_get_connection (client->ibus_bus); + add_match_rule (connection, + "type='method_call'," + "interface='" IBUS_INTERFACE_INPUT_CONTEXT "'," + "member='FocusIn'"); + client->ibus_focus_message_filter = + g_dbus_connection_add_filter (connection, + focus_message_filter, + client, + NULL); + client->follows_focus = TRUE; + return TRUE; +} + +void +eekboard_client_disable_ibus_focus (EekboardClient *client) +{ + GDBusConnection *connection; + + client->follows_focus = FALSE; + + connection = ibus_bus_get_connection (client->ibus_bus); + g_dbus_connection_remove_filter (connection, + client->ibus_focus_message_filter); +} +#endif /* HAVE_ATSPI */ + EekboardClient * eekboard_client_new (GDBusConnection *connection) { @@ -810,11 +913,11 @@ eekboard_client_load_keyboard_from_file (EekboardClient *client, layout = eek_xml_layout_new (G_INPUT_STREAM(input)); g_object_unref (input); -#ifdef HAVE_ATSPI +#if ENABLE_FOCUS_LISTENER retval = set_keyboard (client, !client->follows_focus, layout); -#else +#else /* ENABLE_FOCUS_LISTENER */ retval = set_keyboard (client, TRUE, layout); -#endif +#endif /* !ENABLE_FOCUS_LISTENER */ g_object_unref (layout); return retval; } diff --git a/src/client.h b/src/client.h index f795ec19..ca5f082c 100644 --- a/src/client.h +++ b/src/client.h @@ -57,5 +57,10 @@ void eekboard_client_disable_atspi_keystroke gboolean eekboard_client_enable_fakekey (EekboardClient *client); void eekboard_client_disable_fakekey (EekboardClient *client); +gboolean eekboard_client_enable_ibus_focus + (EekboardClient *client); +void eekboard_client_disable_ibus_focus + (EekboardClient *client); + G_END_DECLS #endif /* EEKBOARD_CLIENT_H */