wayland: Ignore text_input requests from unfocused clients

This is what the protocol says we should do, and even though normally
an out of focus client should not have any reason to create IM requests,
there is a bit of a grey area around focus changes, as both the client
losing focus and the client gaining focus may respectively try to
disable/enable in an undetermined order.

Anyways, since in that situation the client losing focus is not aware
of the requests being ignored, the serial should always be incremented
in order not to break accounting of .done/.commit for that specific
client.

Fixes the IM focus being possibly "lost" after changing focus between
clients, if the race condition turned the odds in that direction.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2585>
This commit is contained in:
Carlos Garnacho 2022-08-18 18:53:52 +02:00 committed by Marge Bot
parent cc729def90
commit a9ae43ff43

View File

@ -412,12 +412,25 @@ text_input_destroy (struct wl_client *client,
wl_resource_destroy (resource); wl_resource_destroy (resource);
} }
static gboolean
client_matches_focus (MetaWaylandTextInput *text_input,
struct wl_client *client)
{
if (!text_input->surface)
return FALSE;
return client == wl_resource_get_client (text_input->surface->resource);
}
static void static void
text_input_enable (struct wl_client *client, text_input_enable (struct wl_client *client,
struct wl_resource *resource) struct wl_resource *resource)
{ {
MetaWaylandTextInput *text_input = wl_resource_get_user_data (resource); MetaWaylandTextInput *text_input = wl_resource_get_user_data (resource);
if (!client_matches_focus (text_input, client))
return;
text_input->enabled = TRUE; text_input->enabled = TRUE;
text_input->pending_state |= META_WAYLAND_PENDING_STATE_ENABLED; text_input->pending_state |= META_WAYLAND_PENDING_STATE_ENABLED;
} }
@ -428,6 +441,9 @@ text_input_disable (struct wl_client *client,
{ {
MetaWaylandTextInput *text_input = wl_resource_get_user_data (resource); MetaWaylandTextInput *text_input = wl_resource_get_user_data (resource);
if (!client_matches_focus (text_input, client))
return;
text_input->enabled = FALSE; text_input->enabled = FALSE;
text_input->pending_state |= META_WAYLAND_PENDING_STATE_ENABLED; text_input->pending_state |= META_WAYLAND_PENDING_STATE_ENABLED;
} }
@ -441,6 +457,9 @@ text_input_set_surrounding_text (struct wl_client *client,
{ {
MetaWaylandTextInput *text_input = wl_resource_get_user_data (resource); MetaWaylandTextInput *text_input = wl_resource_get_user_data (resource);
if (!client_matches_focus (text_input, client))
return;
g_free (text_input->surrounding.text); g_free (text_input->surrounding.text);
text_input->surrounding.text = g_strdup (text); text_input->surrounding.text = g_strdup (text);
text_input->surrounding.cursor = cursor; text_input->surrounding.cursor = cursor;
@ -455,6 +474,9 @@ text_input_set_text_change_cause (struct wl_client *client,
{ {
MetaWaylandTextInput *text_input = wl_resource_get_user_data (resource); MetaWaylandTextInput *text_input = wl_resource_get_user_data (resource);
if (!client_matches_focus (text_input, client))
return;
text_input->text_change_cause = cause; text_input->text_change_cause = cause;
text_input->pending_state |= META_WAYLAND_PENDING_STATE_CHANGE_CAUSE; text_input->pending_state |= META_WAYLAND_PENDING_STATE_CHANGE_CAUSE;
} }
@ -533,7 +555,7 @@ text_input_set_content_type (struct wl_client *client,
{ {
MetaWaylandTextInput *text_input = wl_resource_get_user_data (resource); MetaWaylandTextInput *text_input = wl_resource_get_user_data (resource);
if (!text_input->surface) if (!client_matches_focus (text_input, client))
return; return;
text_input->content_type_hint = hint; text_input->content_type_hint = hint;
@ -551,7 +573,7 @@ text_input_set_cursor_rectangle (struct wl_client *client,
{ {
MetaWaylandTextInput *text_input = wl_resource_get_user_data (resource); MetaWaylandTextInput *text_input = wl_resource_get_user_data (resource);
if (!text_input->surface) if (!client_matches_focus (text_input, client))
return; return;
text_input->cursor_rect = (cairo_rectangle_int_t) { x, y, width, height }; text_input->cursor_rect = (cairo_rectangle_int_t) { x, y, width, height };
@ -580,7 +602,7 @@ text_input_commit_state (struct wl_client *client,
increment_serial (text_input, resource); increment_serial (text_input, resource);
if (text_input->surface == NULL) if (!client_matches_focus (text_input, client))
return; return;
input_method = clutter_backend_get_input_method (clutter_get_default_backend ()); input_method = clutter_backend_get_input_method (clutter_get_default_backend ());