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.
This commit is contained in:
Daniel Eklöf 2022-06-15 18:41:08 +02:00
parent d852178540
commit 96f23b4c64
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
4 changed files with 21 additions and 14 deletions

28
ime.c
View file

@ -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)