From 342164ede15219c510719748fe32ab97b28d5120 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 11 Jul 2018 10:13:38 +0530 Subject: [PATCH] Add API for the application to notify the IME system of state changes --- glfw/glfw3.h | 17 +++++++++++++++++ glfw/ibus_glfw.c | 7 +++---- glfw/ibus_glfw.h | 1 + glfw/input.c | 10 ++++++++++ glfw/internal.h | 1 + glfw/wl_window.c | 5 +++++ glfw/x11_window.c | 4 ++++ glfw/xkb_glfw.c | 15 +++++++++++++++ glfw/xkb_glfw.h | 1 + kitty/glfw-wrapper.c | 3 +++ kitty/glfw-wrapper.h | 4 ++++ 11 files changed, 64 insertions(+), 4 deletions(-) diff --git a/glfw/glfw3.h b/glfw/glfw3.h index eba72a141..13d74e69b 100644 --- a/glfw/glfw3.h +++ b/glfw/glfw3.h @@ -4228,6 +4228,23 @@ GLFWAPI void glfwSetCursor(GLFWwindow* window, GLFWcursor* cursor); */ GLFWAPI GLFWkeyboardfun glfwSetKeyboardCallback(GLFWwindow* window, GLFWkeyboardfun cbfun); +/*! @brief Notifies the OS Input Method Event system of changes to application input state + * + * Used to notify the IME system of changes in state such as focus gained/lost + * and text cursor position. + * + * @param which: What data to notify. 1 means focus and 2 means cursor position. + * @param a, b, c, d: Interpreted based on the value of which. When which is 1 + * a is interpreted as a boolean indicating focus gained/lost. When which is 2 + * a, b, c, d are the cursor x, y, width and height values (in the window co-ordinate + * system). + * + * @ingroup input + * @since Added in version 4.0 + */ +GLFWAPI void glfwUpdateIMEState(GLFWwindow* window, int which, int a, int b, int c, int d); + + /*! @brief Sets the mouse button callback. * * This function sets the mouse button callback of the specified window, which diff --git a/glfw/ibus_glfw.c b/glfw/ibus_glfw.c index db33d54c4..90e254228 100644 --- a/glfw/ibus_glfw.c +++ b/glfw/ibus_glfw.c @@ -105,7 +105,6 @@ get_ibus_text_from_message(DBusMessage *msg) { // 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) { @@ -236,7 +235,7 @@ input_context_created(DBusMessage *msg, const char* errmsg, void *data) { if (!glfw_dbus_call_method_no_reply(ibus->conn, IBUS_SERVICE, ibus->input_ctx_path, IBUS_INPUT_INTERFACE, "SetCapabilities", DBUS_TYPE_UINT32, &caps, DBUS_TYPE_INVALID)) return; ibus->ok = GLFW_TRUE; glfw_ibus_set_focused(ibus, GLFW_FALSE); - set_cursor_geometry(ibus, 0, 0, 0, 0); + glfw_ibus_set_cursor_geometry(ibus, 0, 0, 0, 0); debug("Connected to IBUS daemon for IME input management\n"); } @@ -324,8 +323,8 @@ 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) { +void +glfw_ibus_set_cursor_geometry(_GLFWIBUSData *ibus, int x, int y, int w, int h) { if (check_connection(ibus)) { glfw_dbus_call_method_no_reply(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 c1a8510a9..ac43e1784 100644 --- a/glfw/ibus_glfw.h +++ b/glfw/ibus_glfw.h @@ -50,3 +50,4 @@ void glfw_ibus_terminate(_GLFWIBUSData *ibus); void glfw_ibus_set_focused(_GLFWIBUSData *ibus, GLFWbool focused); void glfw_ibus_dispatch(_GLFWIBUSData *ibus); GLFWbool ibus_process_key(const KeyEvent *ev_); +void glfw_ibus_set_cursor_geometry(_GLFWIBUSData *ibus, int x, int y, int w, int h); diff --git a/glfw/input.c b/glfw/input.c index 9161c0a1d..f87d3ff2a 100644 --- a/glfw/input.c +++ b/glfw/input.c @@ -909,6 +909,16 @@ GLFWAPI GLFWkeyboardfun glfwSetKeyboardCallback(GLFWwindow* handle, GLFWkeyboard return cbfun; } +GLFWAPI void glfwUpdateIMEState(GLFWwindow* handle, int which, int a, int b, int c, int d) { + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + + _GLFW_REQUIRE_INIT(); +#if defined(_GLFW_X11) || defined(_GLFW_WAYLAND) + _glfwPlatformUpdateIMEState(window, which, a, b, c, d); +#endif +} + GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* handle, GLFWmousebuttonfun cbfun) { diff --git a/glfw/internal.h b/glfw/internal.h index f6a792d6a..1351f7c4c 100644 --- a/glfw/internal.h +++ b/glfw/internal.h @@ -670,6 +670,7 @@ void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled); void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled); void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled); void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity); +void _glfwPlatformUpdateIMEState(_GLFWwindow *w, int which, int a, int b, int c, int d); void _glfwPlatformPollEvents(void); void _glfwPlatformWaitEvents(void); diff --git a/glfw/wl_window.c b/glfw/wl_window.c index 596af916a..a5f06ac4c 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -1509,6 +1509,11 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, return err; } +void +_glfwPlatformUpdateIMEState(_GLFWwindow *w, int which, int a, int b, int c, int d) { + glfw_xkb_update_ime_state(w, &_glfw.wl.xkb, which, a, b, c, d); +} + ////////////////////////////////////////////////////////////////////////// ////// GLFW native API ////// diff --git a/glfw/x11_window.c b/glfw/x11_window.c index 643cad407..cea7478b5 100644 --- a/glfw/x11_window.c +++ b/glfw/x11_window.c @@ -2872,6 +2872,10 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, } } +void +_glfwPlatformUpdateIMEState(_GLFWwindow *w, int which, int a, int b, int c, int d) { + glfw_xkb_update_ime_state(w, &_glfw.x11.xkb, which, a, b, c, d); +} ////////////////////////////////////////////////////////////////////////// ////// GLFW native API ////// diff --git a/glfw/xkb_glfw.c b/glfw/xkb_glfw.c index 5afb12b4a..d4e6e1566 100644 --- a/glfw/xkb_glfw.c +++ b/glfw/xkb_glfw.c @@ -405,6 +405,21 @@ format_xkb_mods(_GLFWXKBData *xkb, const char* name, xkb_mod_mask_t mods) { return buf; } +void +glfw_xkb_update_ime_state(_GLFWwindow *w, _GLFWXKBData *xkb, int which, int a, int b, int c, int d) { + int x = 0, y = 0; + switch(which) { + case 1: + glfw_ibus_set_focused(&xkb->ibus, a ? GLFW_TRUE : GLFW_FALSE); + break; + case 2: + _glfwPlatformGetWindowPos(w, &x, &y); + x += a; y += b; + glfw_ibus_set_cursor_geometry(&xkb->ibus, x, y, c, d); + break; + } +} + void glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t scancode, int action) { const xkb_keysym_t *syms, *clean_syms, *default_syms; diff --git a/glfw/xkb_glfw.h b/glfw/xkb_glfw.h index 870e037ec..01f978fac 100644 --- a/glfw/xkb_glfw.h +++ b/glfw/xkb_glfw.h @@ -87,3 +87,4 @@ const char* glfw_xkb_keysym_name(xkb_keysym_t sym); xkb_keysym_t glfw_xkb_sym_for_key(int key); void glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t scancode, int action); int glfw_xkb_keysym_from_name(const char *name, GLFWbool case_sensitive); +void glfw_xkb_update_ime_state(_GLFWwindow *w, _GLFWXKBData *xkb, int which, int a, int b, int c, int d); diff --git a/kitty/glfw-wrapper.c b/kitty/glfw-wrapper.c index 071ac0bf4..78377181d 100644 --- a/kitty/glfw-wrapper.c +++ b/kitty/glfw-wrapper.c @@ -257,6 +257,9 @@ load_glfw(const char* path) { *(void **) (&glfwSetKeyboardCallback_impl) = dlsym(handle, "glfwSetKeyboardCallback"); if (glfwSetKeyboardCallback_impl == NULL) fail("Failed to load glfw function glfwSetKeyboardCallback with error: %s", dlerror()); + *(void **) (&glfwUpdateIMEState_impl) = dlsym(handle, "glfwUpdateIMEState"); + if (glfwUpdateIMEState_impl == NULL) fail("Failed to load glfw function glfwUpdateIMEState with error: %s", dlerror()); + *(void **) (&glfwSetMouseButtonCallback_impl) = dlsym(handle, "glfwSetMouseButtonCallback"); if (glfwSetMouseButtonCallback_impl == NULL) fail("Failed to load glfw function glfwSetMouseButtonCallback with error: %s", dlerror()); diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index 88a7d87ac..7bf8ca427 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -1699,6 +1699,10 @@ typedef GLFWkeyboardfun (*glfwSetKeyboardCallback_func)(GLFWwindow*, GLFWkeyboar glfwSetKeyboardCallback_func glfwSetKeyboardCallback_impl; #define glfwSetKeyboardCallback glfwSetKeyboardCallback_impl +typedef void (*glfwUpdateIMEState_func)(GLFWwindow*, int, int, int, int, int); +glfwUpdateIMEState_func glfwUpdateIMEState_impl; +#define glfwUpdateIMEState glfwUpdateIMEState_impl + typedef GLFWmousebuttonfun (*glfwSetMouseButtonCallback_func)(GLFWwindow*, GLFWmousebuttonfun); glfwSetMouseButtonCallback_func glfwSetMouseButtonCallback_impl; #define glfwSetMouseButtonCallback glfwSetMouseButtonCallback_impl