From 6c628bc594c982ae134bc713d2e99e67b87f1c08 Mon Sep 17 00:00:00 2001 From: pagedown Date: Mon, 21 Mar 2022 18:36:25 +0800 Subject: [PATCH] Wayland: Fix IME is not enabled after switching the focus --- glfw/wl_text_input.c | 7 ++++++- kitty/fast_data_types.pyi | 2 +- kitty/screen.c | 2 +- kitty/state.c | 17 ++++++++++------- kitty/state.h | 2 +- kitty/window.py | 6 +++--- 6 files changed, 22 insertions(+), 14 deletions(-) diff --git a/glfw/wl_text_input.c b/glfw/wl_text_input.c index 4325176cd..d77a08909 100644 --- a/glfw/wl_text_input.c +++ b/glfw/wl_text_input.c @@ -139,7 +139,12 @@ _glfwPlatformUpdateIMEState(_GLFWwindow *w, const GLFWIMEUpdateEvent *ev) { switch(ev->type) { case GLFW_IME_UPDATE_FOCUS: debug("\ntext-input: updating IME focus state, focused: %d\n", ev->focused); - if (ev->focused) zwp_text_input_v3_enable(text_input); else zwp_text_input_v3_disable(text_input); + if (ev->focused) { + zwp_text_input_v3_enable(text_input); + zwp_text_input_v3_set_content_type(text_input, ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE, ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TERMINAL); + } else { + zwp_text_input_v3_disable(text_input); + } commit(); break; case GLFW_IME_UPDATE_CURSOR_POSITION: { diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index bd6f9215e..24a174359 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -1361,7 +1361,7 @@ def set_os_window_title(os_window_id: int, title: str) -> None: pass -def update_ime_position_for_window(window_id: int, force: bool = False, lost_focus: bool = False) -> bool: +def update_ime_position_for_window(window_id: int, force: bool = False, update_focus: int = 0) -> bool: pass diff --git a/kitty/screen.c b/kitty/screen.c index 9daaa0f43..408871933 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -764,7 +764,7 @@ restore_overlay_line(struct SaveOverlayLine *sol) { debug("Received input from child (%s) while overlay active. Overlay contents: %s\n", sol->func_name, PyUnicode_AsUTF8(sol->overlay_text)); screen_draw_overlay_text(sol->screen, PyUnicode_AsUTF8(sol->overlay_text)); Py_DECREF(sol->overlay_text); - update_ime_position_for_window(sol->screen->window_id, false, false); + update_ime_position_for_window(sol->screen->window_id, false, 0); } } diff --git a/kitty/state.c b/kitty/state.c index e32522967..6de00cf5e 100644 --- a/kitty/state.c +++ b/kitty/state.c @@ -602,7 +602,7 @@ send_pending_click_to_window_id(id_type timer_id UNUSED, void *data) { } bool -update_ime_position_for_window(id_type window_id, bool force, bool lost_focus) { +update_ime_position_for_window(id_type window_id, bool force, int update_focus) { for (size_t o = 0; o < global_state.num_os_windows; o++) { OSWindow *osw = global_state.os_windows + o; for (size_t t = 0; t < osw->num_tabs; t++) { @@ -610,11 +610,14 @@ update_ime_position_for_window(id_type window_id, bool force, bool lost_focus) { for (size_t w = 0; w < qtab->num_windows; w++) { Window *window = qtab->windows + w; if (window->id == window_id) { - if (window->render_data.screen && (force || osw->is_focused)) { + // The screen may not be ready after the new window is created and focused, and still needs to enable IME. + if ((window->render_data.screen && (force || osw->is_focused)) || update_focus > 0) { OSWindow *orig = global_state.callback_os_window; global_state.callback_os_window = osw; - if (lost_focus) update_ime_focus(osw, false); - else update_ime_position(window, window->render_data.screen); + if (update_focus) update_ime_focus(osw, update_focus > 0); + if (update_focus >= 0 && window->render_data.screen) { + update_ime_position(window, window->render_data.screen); + } global_state.callback_os_window = orig; return true; } @@ -653,9 +656,9 @@ update_ime_position_for_window(id_type window_id, bool force, bool lost_focus) { PYWRAP1(update_ime_position_for_window) { id_type window_id; int force = 0; - int lost_focus = 0; - PA("K|pp", &window_id, &force, &lost_focus); - if (update_ime_position_for_window(window_id, force, lost_focus)) Py_RETURN_TRUE; + int update_focus = 0; + PA("K|pi", &window_id, &force, &update_focus); + if (update_ime_position_for_window(window_id, force, update_focus)) Py_RETURN_TRUE; Py_RETURN_FALSE; } diff --git a/kitty/state.h b/kitty/state.h index 446f2a462..15c5ac66c 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -342,6 +342,6 @@ uint8_t* draw_single_ascii_char(const char ch, size_t *result_width, size_t *res bool is_os_window_fullscreen(OSWindow *); void update_ime_focus(OSWindow* osw, bool focused); void update_ime_position(Window* w, Screen *screen); -bool update_ime_position_for_window(id_type window_id, bool force, bool lost_focus); +bool update_ime_position_for_window(id_type window_id, bool force, int update_focus); void set_ignore_os_keyboard_processing(bool enabled); void update_menu_bar_title(PyObject *title UNUSED); diff --git a/kitty/window.py b/kitty/window.py index c0a9a6117..ba34e80cc 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -780,7 +780,7 @@ class Window: self.screen.focus_changed(focused) if focused: self.last_focused_at = monotonic() - update_ime_position_for_window(self.id) + update_ime_position_for_window(self.id, False, 1) changed = self.needs_attention self.needs_attention = False if changed: @@ -789,7 +789,7 @@ class Window: tab.relayout_borders() elif self.os_window_id == current_os_window(): # Cancel IME composition after loses focus - update_ime_position_for_window(self.id, False, True) + update_ime_position_for_window(self.id, False, -1) def title_changed(self, new_title: Optional[str], is_base64: bool = False) -> None: self.child_title = process_title_from_child(new_title or self.default_title, is_base64) @@ -1163,7 +1163,7 @@ class Window: if hasattr(self, 'screen'): if self.is_active and self.os_window_id == current_os_window(): # Cancel IME composition when window is destroyed - update_ime_position_for_window(self.id, False, True) + update_ime_position_for_window(self.id, False, -1) # Remove cycles so that screen is de-allocated immediately self.screen.reset_callbacks() del self.screen