diff --git a/glfw/glfw3.h b/glfw/glfw3.h index 13d74e69b..116927990 100644 --- a/glfw/glfw3.h +++ b/glfw/glfw3.h @@ -1399,7 +1399,9 @@ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * @param[in] text UTF-8 encoded text generated by this key event or empty string. - * @param[in] reserved Reserved for future use. + * @param[in] Used for Input Method events. Zero for normal key events. + * A value of 1 means the pre-edit text for the input event has been changed. + * A value of 2 means the text should be committed. * * @note On X11/Wayland if a modifier other than the modifiers GLFW reports * (ctrl/shift/alt/super) is used, GLFW will report the shifted key rather diff --git a/glfw/ibus_glfw.c b/glfw/ibus_glfw.c index 90e254228..65a987432 100644 --- a/glfw/ibus_glfw.c +++ b/glfw/ibus_glfw.c @@ -103,6 +103,13 @@ get_ibus_text_from_message(DBusMessage *msg) { return text; } +static inline void +send_text(const char *text, int state) { + _GLFWwindow *w = _glfwFocusedWindow(); + if (w && w->callbacks.keyboard) { + w->callbacks.keyboard((GLFWwindow*) w, GLFW_KEY_UNKNOWN, 0, GLFW_PRESS, 0, text, state); + } +} // Connection handling {{{ @@ -117,9 +124,11 @@ message_handler(DBusConnection *conn, DBusMessage *msg, void *user_data) { case 0: text = get_ibus_text_from_message(msg); debug("IBUS: CommitText: '%s'\n", text ? text : "(nil)"); + send_text(text, 2); break; case 1: text = get_ibus_text_from_message(msg); + send_text(text, 1); debug("IBUS: UpdatePreeditText: '%s'\n", text ? text : "(nil)"); break; case 2: diff --git a/glfw/internal.h b/glfw/internal.h index 1351f7c4c..824cee5ed 100644 --- a/glfw/internal.h +++ b/glfw/internal.h @@ -59,6 +59,7 @@ #define _GLFW_MESSAGE_SIZE 1024 typedef int GLFWbool; +typedef unsigned long long GLFWid; typedef struct _GLFWerror _GLFWerror; typedef struct _GLFWinitconfig _GLFWinitconfig; @@ -377,6 +378,7 @@ struct _GLFWwindow GLFWbool focusOnShow; GLFWbool shouldClose; void* userPointer; + GLFWid id; GLFWvidmode videoMode; _GLFWmonitor* monitor; _GLFWcursor* cursor; @@ -525,6 +527,7 @@ struct _GLFWlibrary _GLFWerror* errorListHead; _GLFWcursor* cursorListHead; _GLFWwindow* windowListHead; + GLFWid focusedWindowId; _GLFWmonitor** monitors; int monitorCount; @@ -702,6 +705,7 @@ void _glfwPlatformUnlockMutex(_GLFWmutex* mutex); ////////////////////////////////////////////////////////////////////////// void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused); +_GLFWwindow* _glfwFocusedWindow(); void _glfwInputWindowPos(_GLFWwindow* window, int xpos, int ypos); void _glfwInputWindowSize(_GLFWwindow* window, int width, int height); void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height); diff --git a/glfw/window.c b/glfw/window.c index 53aba5dad..d1ee20bd2 100644 --- a/glfw/window.c +++ b/glfw/window.c @@ -48,6 +48,7 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused) if (!focused) { int key, button; + _glfw.focusedWindowId = 0; for (key = 0; key <= GLFW_KEY_LAST; key++) { @@ -63,7 +64,19 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused) if (window->mouseButtons[button] == GLFW_PRESS) _glfwInputMouseClick(window, button, GLFW_RELEASE, 0); } + } else + _glfw.focusedWindowId = window->id; +} + +_GLFWwindow* _glfwFocusedWindow() { + if (_glfw.focusedWindowId) { + _GLFWwindow *w = _glfw.windowListHead; + while (w) { + if (w->id == _glfw.focusedWindowId) return w; + w = w->next; + } } + return NULL; } // Notifies shared code that a window has moved @@ -185,8 +198,10 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, if (!_glfwIsValidContextConfig(&ctxconfig)) return NULL; + static GLFWid windowIdCounter = 0; window = calloc(1, sizeof(_GLFWwindow)); window->next = _glfw.windowListHead; + window->id = ++windowIdCounter; _glfw.windowListHead = window; window->videoMode.width = width; diff --git a/kitty/keys.c b/kitty/keys.c index 5afaee898..84fe72aa9 100644 --- a/kitty/keys.c +++ b/kitty/keys.c @@ -114,9 +114,23 @@ check_if_special(int key, int mods, int scancode) { } void -on_key_input(int key, int scancode, int action, int mods, const char* text, int state UNUSED) { +on_key_input(int key, int scancode, int action, int mods, const char* text, int state) { Window *w = active_window(); if (!w) return; + Screen *screen = w->render_data.screen; + switch(state) { + case 1: // update pre-edit text + return; + case 2: // commit text + if (text && *text) { + schedule_write_to_child(w->id, text, strlen(text)); + } + return; + case 0: + break; + default: + return; + } if (global_state.in_sequence_mode) { if ( action != GLFW_RELEASE && @@ -124,7 +138,6 @@ on_key_input(int key, int scancode, int action, int mods, const char* text, int ) call_boss(process_sequence, "iiii", key, scancode, action, mods); return; } - Screen *screen = w->render_data.screen; bool has_text = text && !is_ascii_control_char(text[0]); if (action == GLFW_PRESS || action == GLFW_REPEAT) { if (check_if_special(key, mods, scancode)) {