wayland: Flush text_input.done event after IM key event

We set an idle to coalesce multiple IM events together, as the protocol
requires us to send them in one frame, and unfortunately there is no
idea about whether more IM events are upcoming.

One good hint though are key events generated from the IM, we want to
apply all IM changes before the key event is processed, so make it sure
that the .done event is flushed before the key event is handled.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1286
This commit is contained in:
Carlos Garnacho 2020-07-06 12:13:58 +02:00
parent 98c1a469ad
commit 35680ee7c6

View File

@ -118,10 +118,9 @@ increment_serial (MetaWaylandTextInput *text_input,
GUINT_TO_POINTER (serial + 1)); GUINT_TO_POINTER (serial + 1));
} }
static gboolean static void
done_idle_cb (gpointer user_data) clutter_input_focus_send_done (ClutterInputFocus *focus)
{ {
ClutterInputFocus *focus = user_data;
MetaWaylandTextInput *text_input; MetaWaylandTextInput *text_input;
struct wl_resource *resource; struct wl_resource *resource;
@ -132,6 +131,16 @@ done_idle_cb (gpointer user_data)
zwp_text_input_v3_send_done (resource, zwp_text_input_v3_send_done (resource,
lookup_serial (text_input, resource)); lookup_serial (text_input, resource));
} }
}
static gboolean
done_idle_cb (gpointer user_data)
{
ClutterInputFocus *focus = user_data;
MetaWaylandTextInput *text_input;
text_input = META_WAYLAND_TEXT_INPUT_FOCUS (focus)->text_input;
clutter_input_focus_send_done (focus);
text_input->done_idle_id = 0; text_input->done_idle_id = 0;
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
@ -164,6 +173,20 @@ meta_wayland_text_input_focus_defer_done (ClutterInputFocus *focus)
done_idle_cb, focus, NULL); done_idle_cb, focus, NULL);
} }
static void
meta_wayland_text_input_focus_flush_done (ClutterInputFocus *focus)
{
MetaWaylandTextInput *text_input;
text_input = META_WAYLAND_TEXT_INPUT_FOCUS (focus)->text_input;
if (text_input->done_idle_id == 0)
return;
g_clear_handle_id (&text_input->done_idle_id, g_source_remove);
clutter_input_focus_send_done (focus);
}
static void static void
meta_wayland_text_input_focus_delete_surrounding (ClutterInputFocus *focus, meta_wayland_text_input_focus_delete_surrounding (ClutterInputFocus *focus,
int offset, int offset,
@ -737,5 +760,10 @@ meta_wayland_text_input_handle_event (MetaWaylandTextInput *text_input,
!clutter_input_focus_is_focused (text_input->input_focus)) !clutter_input_focus_is_focused (text_input->input_focus))
return FALSE; return FALSE;
if ((event->type == CLUTTER_KEY_PRESS ||
event->type == CLUTTER_KEY_RELEASE) &&
clutter_event_get_flags (event) & CLUTTER_EVENT_FLAG_INPUT_METHOD)
meta_wayland_text_input_focus_flush_done (text_input->input_focus);
return clutter_input_focus_filter_event (text_input->input_focus, event); return clutter_input_focus_filter_event (text_input->input_focus, event);
} }