From 26a6d6bef92e676d5e589cebdf3aabf60b02c24e Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 9 Jul 2018 10:07:11 +0530 Subject: [PATCH] Set startup IBUS cursor and focus state --- glfw/ibus_glfw.c | 72 ++++++++++++++++++++++++++++++++++++++++-------- glfw/ibus_glfw.h | 1 + 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/glfw/ibus_glfw.c b/glfw/ibus_glfw.c index a0e305202..cd674d735 100644 --- a/glfw/ibus_glfw.c +++ b/glfw/ibus_glfw.c @@ -58,7 +58,10 @@ MIN(size_t a, size_t b) { return a < b ? a : b; } + // 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) { _GLFWIBUSData *ibus = (_GLFWIBUSData*)user_data; @@ -115,14 +118,14 @@ get_ibus_address_file_name(void) { } -static inline const char* +static inline GLFWbool read_ibus_address(_GLFWIBUSData *ibus) { static char buf[1024]; struct stat s; FILE *addr_file = fopen(ibus->address_file_name, "r"); if (!addr_file) { _glfwInputError(GLFW_PLATFORM_ERROR, "Failed to open IBUS address file: %s with error: %s", ibus->address_file_name, strerror(errno)); - return NULL; + return GLFW_FALSE; } int stat_result = fstat(fileno(addr_file), &s); GLFWbool found = GLFW_FALSE; @@ -138,12 +141,16 @@ read_ibus_address(_GLFWIBUSData *ibus) { fclose(addr_file); addr_file = NULL; if (stat_result != 0) { _glfwInputError(GLFW_PLATFORM_ERROR, "Failed to stat IBUS address file: %s with error: %s", ibus->address_file_name, strerror(errno)); - return NULL; + return GLFW_FALSE; } ibus->address_file_mtime = s.st_mtime; - if (found) return buf + sizeof("IBUS_ADDRESS=") - 1; + if (found) { + free((void*)ibus->address); + ibus->address = strdup(buf + sizeof("IBUS_ADDRESS=") - 1); + return GLFW_TRUE; + } _glfwInputError(GLFW_PLATFORM_ERROR, "Could not find IBUS_ADDRESS in %s", ibus->address_file_name); - return NULL; + return GLFW_FALSE; } GLFWbool @@ -154,11 +161,12 @@ setup_connection(_GLFWIBUSData *ibus) { if (!address_file_name) return GLFW_FALSE; free((void*)ibus->address_file_name); ibus->address_file_name = strdup(address_file_name); - const char *address = read_ibus_address(ibus); - if (!address) return GLFW_FALSE; - free((void*)ibus->address); - ibus->address = strdup(address); - debug("Connecting to IBUS daemon for IME input management\n"); + if (!read_ibus_address(ibus)) return GLFW_FALSE; + if (ibus->conn) { + glfw_dbus_close_connection(ibus->conn); + ibus->conn = NULL; + } + debug("Connecting to IBUS daemon @ %s for IME input management\n", ibus->address); ibus->conn = glfw_dbus_connect_to(ibus->address, "Failed to connect to the IBUS daemon, with error"); if (!ibus->conn) return GLFW_FALSE; if (!glfw_dbus_call_method(ibus->conn, IBUS_SERVICE, IBUS_PATH, IBUS_INTERFACE, "CreateInputContext", @@ -175,6 +183,8 @@ setup_connection(_GLFWIBUSData *ibus) { DBusObjectPathVTable ibus_vtable = {.message_function = message_handler}; dbus_connection_try_register_object_path(ibus->conn, ibus->input_ctx_path, &ibus_vtable, ibus, NULL); dbus_connection_flush(ibus->conn); + glfw_ibus_set_focused(ibus, GLFW_FALSE); + set_cursor_geometry(ibus, 0, 0, 0, 0); debug("Connected to IBUS daemon for IME input management\n"); ibus->ok = GLFW_TRUE; @@ -185,11 +195,11 @@ setup_connection(_GLFWIBUSData *ibus) { void glfw_connect_to_ibus(_GLFWIBUSData *ibus, _GLFWDBUSData *dbus) { if (ibus->inited) return; - ibus->inited = GLFW_TRUE; if (!has_env_var("XMODIFIERS", "@im=ibus") && !has_env_var("GTK_IM_MODULE", "ibus") && !has_env_var("QT_IM_MODULE", "ibus")) return; if (!glfw_dbus_init(dbus)) { _glfwInputError(GLFW_PLATFORM_ERROR, "Cannot connect to IBUS as connection to DBUS session bus failed"); } + ibus->inited = GLFW_TRUE; setup_connection(ibus); } @@ -200,9 +210,47 @@ glfw_ibus_terminate(_GLFWIBUSData *ibus) { ibus->conn = NULL; } #define F(x) if (ibus->x) { free((void*)ibus->x); ibus->x = NULL; } - F(input_ctx_path); F(address); F(address_file_name); + F(input_ctx_path); + F(address); + F(address_file_name); #undef F ibus->ok = GLFW_FALSE; } + +static GLFWbool +check_connection(_GLFWIBUSData *ibus) { + if (!ibus->inited) return GLFW_FALSE; + if (ibus->conn && dbus_connection_get_is_connected(ibus->conn)) { + return GLFW_TRUE; + } + struct stat s; + if (stat(ibus->address_file_name, &s) != 0 || s.st_mtime != ibus->address_file_mtime) { + if (!read_ibus_address(ibus)) return GLFW_FALSE; + return setup_connection(ibus); + } + return GLFW_FALSE; +} + + // }}} + +static void +simple_message(_GLFWIBUSData *ibus, const char *method) { + if (check_connection(ibus)) { + glfw_dbus_call_void_method(ibus->conn, IBUS_SERVICE, ibus->input_ctx_path, IBUS_INPUT_INTERFACE, method, DBUS_TYPE_INVALID); + } +} + +void +glfw_ibus_set_focused(_GLFWIBUSData *ibus, GLFWbool focused) { + simple_message(ibus, focused ? "FocusIn" : "FocusOut"); +} + +static void +set_cursor_geometry(_GLFWIBUSData *ibus, int x, int y, int w, int h) { + if (check_connection(ibus)) { + glfw_dbus_call_method(ibus->conn, IBUS_SERVICE, ibus->input_ctx_path, IBUS_INPUT_INTERFACE, "SetCursorLocation", + DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y, DBUS_TYPE_INT32, &w, DBUS_TYPE_INT32, &h, DBUS_TYPE_INVALID); + } +} diff --git a/glfw/ibus_glfw.h b/glfw/ibus_glfw.h index 6b9bb922e..7ed634faa 100644 --- a/glfw/ibus_glfw.h +++ b/glfw/ibus_glfw.h @@ -38,3 +38,4 @@ typedef struct { void glfw_connect_to_ibus(_GLFWIBUSData *ibus, _GLFWDBUSData *dbus); void glfw_ibus_terminate(_GLFWIBUSData *ibus); +void glfw_ibus_set_focused(_GLFWIBUSData *ibus, GLFWbool focused);