diff --git a/debian/patches/gtk-imwayland-Use-serial-to-control-outbound-messages.patch b/debian/patches/gtk-imwayland-Use-serial-to-control-outbound-messages.patch new file mode 100644 index 0000000000..d9b06f6e09 --- /dev/null +++ b/debian/patches/gtk-imwayland-Use-serial-to-control-outbound-messages.patch @@ -0,0 +1,115 @@ +From: Carlos Garnacho +Date: Tue, 18 Jan 2022 23:31:09 +0100 +Subject: gtk/imwayland: Use serial to control outbound messages + +Following the text-input protocol changes at +https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/115, +use the serial number to have the client push changes to the +zwp_text_input_v3 object only after compositor/client states match. + +This specifically is more lenient to compositors pushing multiple +.done events ahead of the client replying to them. + +(cherry-picked from commit f108f053d4c84dcdedce005a3491cbd503092185) + +Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/4853 +(cherry picked from commit 802a748e5bd4688cd6b6a251fb6f331bd74cf6a5) +--- + modules/input/imwayland.c | 28 +++++++++++++++++----------- + 1 file changed, 17 insertions(+), 11 deletions(-) + +diff --git a/modules/input/imwayland.c b/modules/input/imwayland.c +index 9a12b21..91d27ca 100644 +--- a/modules/input/imwayland.c ++++ b/modules/input/imwayland.c +@@ -47,6 +47,7 @@ struct _GtkIMContextWaylandGlobal + gboolean focused; + + guint serial; ++ guint done_serial; + }; + + struct _GtkIMContextWaylandClass +@@ -205,11 +206,11 @@ text_input_commit (void *data, + } + + static void +-text_input_commit_apply (GtkIMContextWaylandGlobal *global, gboolean valid) ++text_input_commit_apply (GtkIMContextWaylandGlobal *global) + { + GtkIMContextWayland *context; + context = GTK_IM_CONTEXT_WAYLAND (global->current); +- if (context->pending_commit && valid) ++ if (context->pending_commit) + g_signal_emit_by_name (global->current, "commit", context->pending_commit); + g_free (context->pending_commit); + context->pending_commit = NULL; +@@ -234,8 +235,7 @@ text_input_delete_surrounding_text (void *data, + } + + static void +-text_input_delete_surrounding_text_apply (GtkIMContextWaylandGlobal *global, +- gboolean valid) ++text_input_delete_surrounding_text_apply (GtkIMContextWaylandGlobal *global) + { + GtkIMContextWayland *context; + gboolean retval; +@@ -246,7 +246,7 @@ text_input_delete_surrounding_text_apply (GtkIMContextWaylandGlobal *global, + + len = context->pending_surrounding_delete.after_length + + context->pending_surrounding_delete.before_length; +- if (len > 0 && valid) ++ if (len > 0) + g_signal_emit_by_name (global->current, "delete-surrounding", + -context->pending_surrounding_delete.before_length, + len, &retval); +@@ -260,16 +260,16 @@ text_input_done (void *data, + { + GtkIMContextWaylandGlobal *global = data; + gboolean result; +- gboolean valid; +- ++ ++ global->done_serial = serial; ++ + if (!global->current) + return; + +- valid = serial == global->serial; +- text_input_delete_surrounding_text_apply(global, valid); +- text_input_commit_apply(global, valid); ++ text_input_delete_surrounding_text_apply (global); ++ text_input_commit_apply (global); + g_signal_emit_by_name (global->current, "retrieve-surrounding", &result); +- text_input_preedit_apply(global); ++ text_input_preedit_apply (global); + } + + static void +@@ -286,6 +286,8 @@ notify_surrounding_text (GtkIMContextWayland *context) + return; + if (!context->enabled || !context->surrounding.text) + return; ++ if (global->done_serial != global->serial) ++ return; + + len = strlen (context->surrounding.text); + cursor = context->surrounding.cursor_idx; +@@ -361,6 +363,8 @@ notify_cursor_location (GtkIMContextWayland *context) + return; + if (!context->enabled || !context->window) + return; ++ if (global->done_serial != global->serial) ++ return; + + rect = context->cursor_rect; + gdk_window_get_root_coords (context->window, rect.x, rect.y, +@@ -443,6 +447,8 @@ notify_content_type (GtkIMContextWayland *context) + + if (!context->enabled) + return; ++ if (global->done_serial != global->serial) ++ return; + + g_object_get (context, + "input-hints", &hints, diff --git a/debian/patches/imcontextwayland-Ignore-preedit-updates-from-NULL-to-NULL.patch b/debian/patches/imcontextwayland-Ignore-preedit-updates-from-NULL-to-NULL.patch new file mode 100644 index 0000000000..0765e482ac --- /dev/null +++ b/debian/patches/imcontextwayland-Ignore-preedit-updates-from-NULL-to-NULL.patch @@ -0,0 +1,28 @@ +From: Carlos Garnacho +Date: Tue, 26 Apr 2022 12:23:09 +0200 +Subject: imcontextwayland: Ignore preedit updates from NULL to NULL + +If we get consecutive preedit string updates that announce a NULL +string, we still do end up issuing ::preedit-changed with those. +Ignore changes from NULL to NULL, it is the other combinations which +must issue this signal. + +(cherry picked from commit 5321fa25a52f9d91ed0c2f5ec59afbd8fd2f770a) +--- + modules/input/imwayland.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/modules/input/imwayland.c b/modules/input/imwayland.c +index 9b73820..1e93123 100644 +--- a/modules/input/imwayland.c ++++ b/modules/input/imwayland.c +@@ -171,6 +171,9 @@ text_input_preedit_apply (GtkIMContextWaylandGlobal *global) + return; + + context = GTK_IM_CONTEXT_WAYLAND (global->current); ++ if (context->pending_preedit.text == NULL && ++ context->current_preedit.text == NULL) ++ return; + + state_change = ((context->pending_preedit.text == NULL) + != (context->current_preedit.text == NULL)); diff --git a/debian/patches/imwayland-Do-not-defer-commit-after-set_surrounding_text.patch b/debian/patches/imwayland-Do-not-defer-commit-after-set_surrounding_text.patch new file mode 100644 index 0000000000..cdcba070ea --- /dev/null +++ b/debian/patches/imwayland-Do-not-defer-commit-after-set_surrounding_text.patch @@ -0,0 +1,56 @@ +From: Carlos Garnacho +Date: Wed, 6 Apr 2022 13:08:00 +0200 +Subject: imwayland: Do not defer commit() after set_surrounding_text() + +For reasons that only apply to the old serial handling, asking for +the surrounding after IM changes resulted in lazy handling of +commit() afterwards. + +With the recent interpretation of serials, this problem became more +apparent, since it is in fact very likely that the last interaction +step after an IM change is notifying of the changed surrounding +text after the IM change was applied. + +Make handling of surrounding text similar to caret position changes, +always commit() after the state change, but skip through non-changes. + +This makes the compositor state fully up-to-date after an IM change. + +(cherry-picked from commit eb7c78aa4896b1d36fa09a3e68c942730b233f74) + +(cherry picked from commit 49b6410c265727f0b2650b912b1cbc5806107d27) +--- + modules/input/imwayland.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/modules/input/imwayland.c b/modules/input/imwayland.c +index 91d27ca..9b73820 100644 +--- a/modules/input/imwayland.c ++++ b/modules/input/imwayland.c +@@ -876,6 +876,13 @@ gtk_im_context_wayland_set_surrounding (GtkIMContext *context, + + context_wayland = GTK_IM_CONTEXT_WAYLAND (context); + ++ if (context_wayland->surrounding.text && text && ++ (len < 0 || len == strlen (context_wayland->surrounding.text)) && ++ strncmp (context_wayland->surrounding.text, text, len) == 0 && ++ context_wayland->surrounding.cursor_idx == cursor_index && ++ context_wayland->surrounding.anchor_idx == cursor_index) ++ return; ++ + g_free (context_wayland->surrounding.text); + context_wayland->surrounding.text = g_strndup (text, len); + context_wayland->surrounding.cursor_idx = cursor_index; +@@ -883,11 +890,7 @@ gtk_im_context_wayland_set_surrounding (GtkIMContext *context, + context_wayland->surrounding.anchor_idx = cursor_index; + + notify_surrounding_text (context_wayland); +- /* State changes coming from reset don't have any other opportunity to get +- * committed. */ +- if (context_wayland->surrounding_change != +- ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_INPUT_METHOD) +- commit_state (context_wayland); ++ commit_state (context_wayland); + } + + static gboolean diff --git a/debian/patches/series b/debian/patches/series index b241ce874d..e1f7d2ffe6 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -6,3 +6,7 @@ demos-examples-tests-Don-t-distribute-built-files.patch 060_ignore-random-icons.patch reftest-known-fail.patch Disable-accessibility-dump-aka-a11ytests-test.patch +gtk-imwayland-Use-serial-to-control-outbound-messages.patch +imwayland-Do-not-defer-commit-after-set_surrounding_text.patch +imcontextwayland-Ignore-preedit-updates-from-NULL-to-NULL.patch +x11-Trap-errors-happening-when-getting-output-properties.patch diff --git a/debian/patches/x11-Trap-errors-happening-when-getting-output-properties.patch b/debian/patches/x11-Trap-errors-happening-when-getting-output-properties.patch new file mode 100644 index 0000000000..a0de1a357a --- /dev/null +++ b/debian/patches/x11-Trap-errors-happening-when-getting-output-properties.patch @@ -0,0 +1,76 @@ +From: =?utf-8?q?Jonas_=C3=85dahl?= +Date: Mon, 2 May 2022 16:47:18 +0200 +Subject: x11: Trap errors happening when getting output properties + +This is to avoid getting X11 errors (thus aborting/exiting with a +failure) during rapid hotplugs, which may happen during e.g. CI testing. + +(cherry picked from commit 9addb14a834777d754a53a560c8e3489ec1313f6) +--- + gdk/x11/gdkscreen-x11.c | 32 +++++++++++++++++++------------- + 1 file changed, 19 insertions(+), 13 deletions(-) + +diff --git a/gdk/x11/gdkscreen-x11.c b/gdk/x11/gdkscreen-x11.c +index 81499ba..c2b7480 100644 +--- a/gdk/x11/gdkscreen-x11.c ++++ b/gdk/x11/gdkscreen-x11.c +@@ -594,19 +594,6 @@ init_randr15 (GdkScreen *screen, gboolean *changed) + XRRFreeCrtcInfo (crtc); + } + +- monitor = find_monitor_by_output (x11_display, output); +- if (monitor) +- monitor->remove = FALSE; +- else +- { +- monitor = g_object_new (GDK_TYPE_X11_MONITOR, +- "display", display, +- NULL); +- monitor->output = output; +- monitor->add = TRUE; +- g_ptr_array_add (x11_display->monitors, monitor); +- } +- + /* Fetch minimal manufacturer information (PNP ID) from EDID */ + { + #define EDID_LENGTH 128 +@@ -619,6 +606,7 @@ init_randr15 (GdkScreen *screen, gboolean *changed) + + edid_atom = XInternAtom (disp, RR_PROPERTY_RANDR_EDID, FALSE); + ++ gdk_x11_display_error_trap_push (display); + XRRGetOutputProperty (disp, output, + edid_atom, + 0, +@@ -631,6 +619,11 @@ init_randr15 (GdkScreen *screen, gboolean *changed) + &nbytes, + &bytes_left, + &prop); ++ if (gdk_x11_display_error_trap_pop (display)) ++ { ++ XRRFreeOutputInfo (output_info); ++ continue; ++ } + + // Check partial EDID header (whole header: 00 ff ff ff ff ff ff 00) + if (nbytes >= EDID_LENGTH && prop[0] == 0x00 && prop[1] == 0xff) +@@ -651,6 +644,19 @@ init_randr15 (GdkScreen *screen, gboolean *changed) + #undef EDID_LENGTH + } + ++ monitor = find_monitor_by_output (x11_display, output); ++ if (monitor) ++ monitor->remove = FALSE; ++ else ++ { ++ monitor = g_object_new (GDK_TYPE_X11_MONITOR, ++ "display", display, ++ NULL); ++ monitor->output = output; ++ monitor->add = TRUE; ++ g_ptr_array_add (x11_display->monitors, monitor); ++ } ++ + gdk_monitor_get_geometry (GDK_MONITOR (monitor), &geometry); + name = g_strndup (output_info->name, output_info->nameLen); +