Implement the handler for ibus signals

This commit is contained in:
Kovid Goyal 2018-07-10 15:04:32 +05:30
parent 9c48e4965c
commit d875d7baed
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 80 additions and 0 deletions

15
glfw/dbus_glfw.c vendored
View File

@ -273,3 +273,18 @@ glfw_dbus_call_method_no_reply(DBusConnection *conn, const char *node, const cha
va_end(ap); va_end(ap);
return retval; 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;
}

1
glfw/dbus_glfw.h vendored
View File

@ -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, ...); 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 *); void glfw_dbus_dispatch(DBusConnection *);
GLFWbool glfw_dbus_get_args(DBusMessage *msg, const char *failmsg, ...); GLFWbool glfw_dbus_get_args(DBusMessage *msg, const char *failmsg, ...);
int glfw_dbus_match_signal(DBusMessage *msg, const char *interface, ...);

64
glfw/ibus_glfw.c vendored
View File

@ -58,14 +58,78 @@ MIN(size_t a, size_t b) {
return a < b ? a : 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 {{{ // Connection handling {{{
static void set_cursor_geometry(_GLFWIBUSData *ibus, int x, int y, int w, int h); static void set_cursor_geometry(_GLFWIBUSData *ibus, int x, int y, int w, int h);
static DBusHandlerResult static DBusHandlerResult
message_handler(DBusConnection *conn, DBusMessage *msg, void *user_data) { 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; _GLFWIBUSData *ibus = (_GLFWIBUSData*)user_data;
(void)ibus; (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; return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
} }