diff --git a/glfw/dbus_glfw.c b/glfw/dbus_glfw.c index 235a29636..38b49f5d9 100644 --- a/glfw/dbus_glfw.c +++ b/glfw/dbus_glfw.c @@ -273,3 +273,18 @@ glfw_dbus_call_method_no_reply(DBusConnection *conn, const char *node, const cha va_end(ap); return retval; } + +int +glfw_dbus_match_signal(DBusMessage *msg, const char *interface, ...) { + va_list ap; + va_start(ap, interface); + int ans = -1, num = -1; + while(1) { + num++; + const char *name = va_arg(ap, const char*); + if (!name) break; + if (dbus_message_is_signal(msg, interface, name)) { ans = num; break; } + } + va_end(ap); + return ans; +} diff --git a/glfw/dbus_glfw.h b/glfw/dbus_glfw.h index e391bf703..bb358e353 100644 --- a/glfw/dbus_glfw.h +++ b/glfw/dbus_glfw.h @@ -47,3 +47,4 @@ GLFWbool glfw_dbus_call_method_with_reply(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, dbus_pending_callback callback, void *user_data, ...); void glfw_dbus_dispatch(DBusConnection *); GLFWbool glfw_dbus_get_args(DBusMessage *msg, const char *failmsg, ...); +int glfw_dbus_match_signal(DBusMessage *msg, const char *interface, ...); diff --git a/glfw/ibus_glfw.c b/glfw/ibus_glfw.c index 4d4a3dad7..86e8badb9 100644 --- a/glfw/ibus_glfw.c +++ b/glfw/ibus_glfw.c @@ -58,14 +58,78 @@ MIN(size_t a, size_t b) { return a < b ? a : b; } +static const char* +get_ibus_text_from_message(DBusMessage *msg) { + /* The message structure is (from dbus-monitor) + variant struct { + string "IBusText" + array [ + ] + string "ash " + variant struct { + string "IBusAttrList" + array [ + ] + array [ + ] + } + } + */ + const char *text = NULL; + const char *struct_id = NULL; + DBusMessageIter iter, sub1, sub2; + dbus_message_iter_init(msg, &iter); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) return NULL; + + dbus_message_iter_recurse(&iter, &sub1); + + if (dbus_message_iter_get_arg_type(&sub1) != DBUS_TYPE_STRUCT) return NULL; + + dbus_message_iter_recurse(&sub1, &sub2); + + if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) return NULL; + + dbus_message_iter_get_basic(&sub2, &struct_id); + if (!struct_id || strncmp(struct_id, "IBusText", sizeof("IBusText")) != 0) return NULL; + + dbus_message_iter_next(&sub2); + dbus_message_iter_next(&sub2); + + if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) return NULL; + + dbus_message_iter_get_basic(&sub2, &text); + + return text; +} + // Connection handling {{{ static void set_cursor_geometry(_GLFWIBUSData *ibus, int x, int y, int w, int h); static DBusHandlerResult message_handler(DBusConnection *conn, DBusMessage *msg, void *user_data) { + // To monitor signals from IBUS, use + //  dbus-monitor --address `ibus address` "type='signal',interface='org.freedesktop.IBus.InputContext'" _GLFWIBUSData *ibus = (_GLFWIBUSData*)user_data; (void)ibus; + const char *text; + switch(glfw_dbus_match_signal(msg, IBUS_INPUT_INTERFACE, "CommitText", "UpdatePreeditText", "HidePreeditText", "ShowPreeditText")) { + case 0: + text = get_ibus_text_from_message(msg); + debug("IBUS: CommitText: '%s'\n", text ? text : "(nil)"); + break; + case 1: + text = get_ibus_text_from_message(msg); + debug("IBUS: UpdatePreeditText: '%s'\n", text ? text : "(nil)"); + break; + case 2: + debug("IBUS: HidePreeditText\n"); + break; + case 3: + debug("IBUS: ShowPreeditText\n"); + break; + } return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; }