From 96f23b4c6436d314ae4272f5f99c51b8e33556eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 15 Jun 2022 18:41:08 +0200 Subject: [PATCH] ime: track IME focus independently from keyboard focus Replace the seat->ime.focused boolean with a terminal instace pointer, seat->ime_focus. Set and reset this on ime::enter() and ime::leave() events, and use this instead of seat->kbd_focus on all other IME events. This fixes two issues: a) buggy compositors that sometimes sends an IME enter event without first having sent a keyboard enter event. b) seats may be IME capable while still lacking the keyboard capability. Such seats will *always* see IME enter events without a corresponding keyboard enter event. --- CHANGELOG.md | 1 + ime.c | 28 +++++++++++++++++----------- render.c | 4 ++-- wayland.h | 2 +- 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ff030d5..7737f108 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,6 +72,7 @@ * Graphical corruption when viewport is at the top of the scrollback, and the output is scrolling. * Improved text reflow of logical lines with trailing empty cells ([#1055][1055]) +* IME focus is now tracked independently from keyboard focus. [1055]: https://codeberg.org/dnkl/foot/issues/1055 diff --git a/ime.c b/ime.c index a3ca19b2..f3a3ec18 100644 --- a/ime.c +++ b/ime.c @@ -56,12 +56,18 @@ enter(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, struct wl_surface *surface) { struct seat *seat = data; + struct wl_window *win = wl_surface_get_user_data(surface); + struct terminal *term = win->term; - LOG_DBG("enter: seat=%s", seat->name); + LOG_DBG("enter: seat=%s, term=%p", seat->name, (const void *)term); + + if (seat->kbd_focus != term) { + LOG_WARN("compositor sent ime::enter() event before the " + "corresponding keyboard_enter() event"); + } /* The main grid is the *only* input-receiving surface we have */ - xassert(seat->kbd_focus != NULL); - seat->ime.focused = true; + seat->ime_focus = term; ime_enable(seat); } @@ -73,7 +79,7 @@ leave(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, LOG_DBG("leave: seat=%s", seat->name); ime_disable(seat); - seat->ime.focused = false; + seat->ime_focus = NULL; } static void @@ -138,7 +144,7 @@ done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, LOG_DBG("done: serial=%u", serial); struct seat *seat = data; - struct terminal *term = seat->kbd_focus; + struct terminal *term = seat->ime_focus; if (seat->ime.serial != serial) { LOG_DBG("IME serial mismatch: expected=0x%08x, got 0x%08x", @@ -364,10 +370,10 @@ ime_send_cursor_rect(struct seat *seat) if (unlikely(seat->wayl->text_input_manager == NULL)) return; - if (!seat->ime.focused) + if (seat->ime_focus == NULL) return; - struct terminal *term = seat->kbd_focus; + struct terminal *term = seat->ime_focus; if (!term->ime_enabled) return; @@ -399,10 +405,10 @@ ime_enable(struct seat *seat) if (unlikely(seat->wayl->text_input_manager == NULL)) return; - if (!seat->ime.focused) + if (seat->ime_focus == NULL) return; - struct terminal *term = seat->kbd_focus; + struct terminal *term = seat->ime_focus; if (term == NULL) return; @@ -437,7 +443,7 @@ ime_disable(struct seat *seat) if (unlikely(seat->wayl->text_input_manager == NULL)) return; - if (!seat->ime.focused) + if (seat->ime_focus == NULL) return; ime_reset_pending(seat); @@ -451,7 +457,7 @@ ime_disable(struct seat *seat) void ime_update_cursor_rect(struct seat *seat) { - struct terminal *term = seat->kbd_focus; + struct terminal *term = seat->ime_focus; /* Set in render_ime_preedit() */ if (seat->ime.preedit.cells != NULL) diff --git a/render.c b/render.c index 27f21bd5..3b281a89 100644 --- a/render.c +++ b/render.c @@ -3576,7 +3576,7 @@ frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_da grid_render(term); tll_foreach(term->wl->seats, it) { - if (it->item.kbd_focus == term) + if (it->item.ime_focus == term) ime_update_cursor_rect(&it->item); } @@ -4058,7 +4058,7 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data) grid_render(term); tll_foreach(term->wl->seats, it) { - if (it->item.kbd_focus == term) + if (it->item.ime_focus == term) ime_update_cursor_rect(&it->item); } diff --git a/wayland.h b/wayland.h index daa3e65d..729a225b 100644 --- a/wayland.h +++ b/wayland.h @@ -81,6 +81,7 @@ struct seat { /* Focused terminals */ struct terminal *kbd_focus; struct terminal *mouse_focus; + struct terminal *ime_focus; /* Keyboard state */ struct wl_keyboard *wl_keyboard; @@ -202,7 +203,6 @@ struct seat { } pending; } surrounding; - bool focused; uint32_t serial; } ime; #endif