diff --git a/SOURCES/0001-clutter-avoid-redundant-_clutter_paint_node_init_typ.patch b/SOURCES/0001-clutter-avoid-redundant-_clutter_paint_node_init_typ.patch new file mode 100644 index 0000000..7582a55 --- /dev/null +++ b/SOURCES/0001-clutter-avoid-redundant-_clutter_paint_node_init_typ.patch @@ -0,0 +1,53 @@ +From a9f9f9b36a03535480b31534547bea7c9f7cf4c1 Mon Sep 17 00:00:00 2001 +From: Christian Hergert +Date: Sun, 23 Feb 2020 17:27:08 -0800 +Subject: [PATCH 1/3] clutter: avoid redundant _clutter_paint_node_init_types() + +This only needs to be initialized once but is in the hot path of creating +new paint nodes (for which we create many). Instead, do this as part of +the clutter_init() workflow to keep it out of the hot path. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/1087 +--- + clutter/clutter/clutter-main.c | 4 ++++ + clutter/clutter/clutter-paint-node.c | 2 -- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/clutter/clutter/clutter-main.c b/clutter/clutter/clutter-main.c +index 46537f322..8a465fdc2 100644 +--- a/clutter/clutter/clutter-main.c ++++ b/clutter/clutter/clutter-main.c +@@ -63,6 +63,7 @@ + #include "clutter-main.h" + #include "clutter-master-clock.h" + #include "clutter-mutter.h" ++#include "clutter-paint-node-private.h" + #include "clutter-private.h" + #include "clutter-settings-private.h" + #include "clutter-stage-manager.h" +@@ -1390,6 +1391,9 @@ clutter_init_real (GError **error) + if (clutter_enable_accessibility) + cally_accessibility_init (); + ++ /* Initialize types required for paint nodes */ ++ _clutter_paint_node_init_types (); ++ + return CLUTTER_INIT_SUCCESS; + } + +diff --git a/clutter/clutter/clutter-paint-node.c b/clutter/clutter/clutter-paint-node.c +index 391f48398..db68b7766 100644 +--- a/clutter/clutter/clutter-paint-node.c ++++ b/clutter/clutter/clutter-paint-node.c +@@ -1113,8 +1113,6 @@ _clutter_paint_node_create (GType gtype) + { + g_return_val_if_fail (g_type_is_a (gtype, CLUTTER_TYPE_PAINT_NODE), NULL); + +- _clutter_paint_node_init_types (); +- + return (gpointer) g_type_create_instance (gtype); + } + +-- +2.26.0 + diff --git a/SOURCES/0001-core-Hide-close-dialog-before-destroying.patch b/SOURCES/0001-core-Hide-close-dialog-before-destroying.patch new file mode 100644 index 0000000..8d0e542 --- /dev/null +++ b/SOURCES/0001-core-Hide-close-dialog-before-destroying.patch @@ -0,0 +1,32 @@ +From b5b252af2580c8dad8097037481963f93babfba7 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Wed, 6 Jun 2018 13:26:55 +0200 +Subject: [PATCH] core: Hide close dialog before destroying + +The MetaCloseDialog implementation object may stay artifically alive +for a longer period. This was usually fine till gnome-shell commit +b03bcc85aad, as the check_alive() timeout will keep running even +though the window went unmanaged/destroyed, leading to crashes. + +In order to fix this, forcibly hide the dialog if it is visible and +the window is being unmanaged, so the timeout is stopped in time. +--- + src/core/delete.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/core/delete.c b/src/core/delete.c +index af7cffed9..fd94dc6ca 100644 +--- a/src/core/delete.c ++++ b/src/core/delete.c +@@ -115,5 +115,8 @@ meta_window_kill (MetaWindow *window) + void + meta_window_free_delete_dialog (MetaWindow *window) + { ++ if (window->close_dialog && ++ meta_close_dialog_is_visible (window->close_dialog)) ++ meta_close_dialog_hide (window->close_dialog); + g_clear_object (&window->close_dialog); + } +-- +2.25.1 + diff --git a/SOURCES/0001-display-Make-check-alive-timeout-configureable.patch b/SOURCES/0001-display-Make-check-alive-timeout-configureable.patch new file mode 100644 index 0000000..18613ba --- /dev/null +++ b/SOURCES/0001-display-Make-check-alive-timeout-configureable.patch @@ -0,0 +1,248 @@ +From 8bdcce5328a451c03e240f40a213e5afb11676ea Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Fri, 21 Feb 2020 21:03:16 +0100 +Subject: [PATCH] display: Make check-alive timeout configureable + +The check-alive feature is there for the user to be able to terminate +frozen applications more easily. However, sometimes applications are +implemented in a way where they fail to be reply to ping requests in a +timely manner, resulting in that, to the compositor, they are +indistinguishable from clients that have frozen indefinitely. + +When using an application that has these issues, the GUI showed in +response to the failure to respond to ping requests can become annoying, +as it disrupts the visual presentation of the application. + +To allow users to work-around these issues, add a setting allowing them +to configure the timeout waited until an application is considered +frozen, or disabling the check completely. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/1080 +--- + data/org.gnome.mutter.gschema.xml.in | 10 ++++ + src/core/display.c | 18 ++++---- + src/core/prefs.c | 68 ++++++++++++++++++++++++++++ + src/meta/prefs.h | 3 ++ + 4 files changed, 90 insertions(+), 9 deletions(-) + +diff --git a/data/org.gnome.mutter.gschema.xml.in b/data/org.gnome.mutter.gschema.xml.in +index bec5585bd..06f8288c8 100644 +--- a/data/org.gnome.mutter.gschema.xml.in ++++ b/data/org.gnome.mutter.gschema.xml.in +@@ -127,6 +127,16 @@ + + + ++ ++ 5000 ++ Timeout for check-alive ping ++ ++ Number of milliseconds a client has to respond to a ping request in ++ order to not be detected as frozen. Using 0 will disable the alive check ++ completely. ++ ++ ++ + + + +diff --git a/src/core/display.c b/src/core/display.c +index d4775cec3..5b843fa51 100644 +--- a/src/core/display.c ++++ b/src/core/display.c +@@ -2197,12 +2197,6 @@ meta_set_syncing (gboolean setting) + } + } + +-/* +- * How long, in milliseconds, we should wait after pinging a window +- * before deciding it's not going to get back to us. +- */ +-#define PING_TIMEOUT_DELAY 5000 +- + /** + * meta_display_ping_timeout: + * @data: All the information about this ping. It is a #MetaPingData +@@ -2260,6 +2254,11 @@ meta_display_ping_window (MetaWindow *window, + { + MetaDisplay *display = window->display; + MetaPingData *ping_data; ++ unsigned int check_alive_timeout; ++ ++ check_alive_timeout = meta_prefs_get_check_alive_timeout (); ++ if (check_alive_timeout == 0) ++ return; + + if (serial == 0) + { +@@ -2273,9 +2272,10 @@ meta_display_ping_window (MetaWindow *window, + ping_data = g_new (MetaPingData, 1); + ping_data->window = window; + ping_data->serial = serial; +- ping_data->ping_timeout_id = g_timeout_add (PING_TIMEOUT_DELAY, +- meta_display_ping_timeout, +- ping_data); ++ ping_data->ping_timeout_id = ++ g_timeout_add (check_alive_timeout, ++ meta_display_ping_timeout, ++ ping_data); + g_source_set_name_by_id (ping_data->ping_timeout_id, "[mutter] meta_display_ping_timeout"); + + display->pending_pings = g_slist_prepend (display->pending_pings, ping_data); +diff --git a/src/core/prefs.c b/src/core/prefs.c +index b6a8ab7bf..326db52d2 100644 +--- a/src/core/prefs.c ++++ b/src/core/prefs.c +@@ -95,6 +95,7 @@ static gboolean bell_is_visible = FALSE; + static gboolean bell_is_audible = TRUE; + static gboolean gnome_accessibility = FALSE; + static gboolean gnome_animations = TRUE; ++static unsigned int check_alive_timeout = 5000; + static char *cursor_theme = NULL; + /* cursor_size will, when running as an X11 compositing window manager, be the + * actual cursor size, multiplied with the global window scaling factor. On +@@ -225,6 +226,12 @@ typedef struct + gint *target; + } MetaIntPreference; + ++typedef struct ++{ ++ MetaBasePreference base; ++ unsigned int *target; ++} MetaUintPreference; ++ + + /* All preferences that are not keybindings must be listed here, + * plus in the GSettings schemas and the MetaPreference enum. +@@ -496,6 +503,18 @@ static MetaIntPreference preferences_int[] = + { { NULL, 0, 0 }, NULL }, + }; + ++static MetaUintPreference preferences_uint[] = ++ { ++ { ++ { "check-alive-timeout", ++ SCHEMA_MUTTER, ++ META_PREF_CHECK_ALIVE_TIMEOUT, ++ }, ++ &check_alive_timeout, ++ }, ++ { { NULL, 0, 0 }, NULL }, ++ }; ++ + /* + * This is used to keep track of override schemas used to + * override preferences from the "normal" metacity/mutter +@@ -633,6 +652,21 @@ handle_preference_init_int (void) + } + } + ++static void ++handle_preference_init_uint (void) ++{ ++ MetaUintPreference *cursor = preferences_uint; ++ ++ while (cursor->base.key != NULL) ++ { ++ if (cursor->target) ++ *cursor->target = g_settings_get_uint (SETTINGS (cursor->base.schema), ++ cursor->base.key); ++ ++ ++cursor; ++ } ++} ++ + static void + handle_preference_update_enum (GSettings *settings, + gchar *key) +@@ -808,6 +842,28 @@ handle_preference_update_int (GSettings *settings, + } + } + ++static void ++handle_preference_update_uint (GSettings *settings, ++ char *key) ++{ ++ MetaUintPreference *cursor = preferences_uint; ++ unsigned int new_value; ++ ++ while (cursor->base.key && strcmp (key, cursor->base.key) != 0) ++ ++cursor; ++ ++ if (!cursor->base.key || !cursor->target) ++ return; ++ ++ new_value = g_settings_get_uint (SETTINGS (cursor->base.schema), key); ++ ++ if (*cursor->target != new_value) ++ { ++ *cursor->target = new_value; ++ queue_changed (cursor->base.pref); ++ } ++} ++ + + /****************************************************************************/ + /* Listeners. */ +@@ -1003,6 +1059,7 @@ meta_prefs_init (void) + handle_preference_init_string (); + handle_preference_init_string_array (); + handle_preference_init_int (); ++ handle_preference_init_uint (); + + update_cursor_size (); + shell_shows_app_menu_changed (gtk_settings_get_default (), NULL, NULL); +@@ -1176,6 +1233,8 @@ settings_changed (GSettings *settings, + handle_preference_update_bool (settings, key); + else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32)) + handle_preference_update_int (settings, key); ++ else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32)) ++ handle_preference_update_uint (settings, key); + else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING_ARRAY)) + handle_preference_update_string_array (settings, key); + else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING)) +@@ -1851,6 +1910,9 @@ meta_preference_to_string (MetaPreference pref) + + case META_PREF_AUTO_MAXIMIZE: + return "AUTO_MAXIMIZE"; ++ ++ case META_PREF_CHECK_ALIVE_TIMEOUT: ++ return "CHECK_ALIVE_TIMEOUT"; + } + + return "(unknown)"; +@@ -2177,6 +2239,12 @@ meta_prefs_get_overlay_binding (MetaKeyCombo *combo) + *combo = overlay_key_combo; + } + ++unsigned int ++meta_prefs_get_check_alive_timeout (void) ++{ ++ return check_alive_timeout; ++} ++ + const char * + meta_prefs_get_iso_next_group_option (void) + { +diff --git a/src/meta/prefs.h b/src/meta/prefs.h +index df3cf6c97..f343925f8 100644 +--- a/src/meta/prefs.h ++++ b/src/meta/prefs.h +@@ -103,6 +103,7 @@ typedef enum + META_PREF_AUTO_MAXIMIZE, + META_PREF_CENTER_NEW_WINDOWS, + META_PREF_DRAG_THRESHOLD, ++ META_PREF_CHECK_ALIVE_TIMEOUT, + } MetaPreference; + + typedef void (* MetaPrefsChangedFunc) (MetaPreference pref, +@@ -406,4 +407,6 @@ gboolean meta_prefs_get_visual_bell (void); + gboolean meta_prefs_bell_is_audible (void); + GDesktopVisualBellType meta_prefs_get_visual_bell_type (void); + ++unsigned int meta_prefs_get_check_alive_timeout (void); ++ + #endif +-- +2.24.1 + diff --git a/SOURCES/0001-window-free-close-dialog-before-unmanaging-window-fr.patch b/SOURCES/0001-window-free-close-dialog-before-unmanaging-window-fr.patch new file mode 100644 index 0000000..df3eeae --- /dev/null +++ b/SOURCES/0001-window-free-close-dialog-before-unmanaging-window-fr.patch @@ -0,0 +1,47 @@ +From 376225cea044d050f8fc2923e7149d320150bab7 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 29 Apr 2019 13:46:37 -0400 +Subject: [PATCH] window: free close dialog before unmanaging window from + compositor + +When an application stops responding, the shell darkens its windows. + +If a window from a not-responding application gets unmanaged +then the shell will currently throw an exception trying to retrieve +the now-dissociated window actor. + +That leads to a "stuck window" ghost on screen and a traceback +in the log. + +This commit addresses the problem by making sure the effect is cleaned +up before the actor is disocciated from its window. + +https://gitlab.gnome.org/GNOME/mutter/issues/575 +--- + src/core/window.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/core/window.c b/src/core/window.c +index cc0813ac4..aa85806f1 100644 +--- a/src/core/window.c ++++ b/src/core/window.c +@@ -1388,6 +1388,8 @@ meta_window_unmanage (MetaWindow *window, + meta_verbose ("Unmanaging %s\n", window->desc); + window->unmanaging = TRUE; + ++ meta_window_free_delete_dialog (window); ++ + #ifdef HAVE_WAYLAND + /* This needs to happen for both Wayland and XWayland clients, + * so it can't be in MetaWindowWayland. */ +@@ -1510,7 +1512,6 @@ meta_window_unmanage (MetaWindow *window, + meta_window_unqueue (window, META_QUEUE_CALC_SHOWING | + META_QUEUE_MOVE_RESIZE | + META_QUEUE_UPDATE_ICON); +- meta_window_free_delete_dialog (window); + + set_workspace_state (window, FALSE, NULL); + +-- +2.23.0 + diff --git a/SOURCES/0002-clutter-avoid-g_signal_emit_by_name-from-ClutterActo.patch b/SOURCES/0002-clutter-avoid-g_signal_emit_by_name-from-ClutterActo.patch new file mode 100644 index 0000000..5746804 --- /dev/null +++ b/SOURCES/0002-clutter-avoid-g_signal_emit_by_name-from-ClutterActo.patch @@ -0,0 +1,192 @@ +From 04e5e144ce21c811601e169c13fdef7b8edeae12 Mon Sep 17 00:00:00 2001 +From: Christian Hergert +Date: Mon, 24 Feb 2020 22:36:27 +0000 +Subject: [PATCH 2/3] clutter: avoid g_signal_emit_by_name() from ClutterActor + +g_signal_emit_by_name() is used to emit signals on ClutterContainer when +actors are removed or added. It happens to do various interface lookups +which are a bit unneccessary and can allocate memory. + +Simply using emission wrappers makes all of that go away. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/1083 +--- + clutter/clutter/cally/cally-actor.c | 5 +-- + clutter/clutter/clutter-actor.c | 17 ++++++++-- + clutter/clutter/clutter-actor.h | 5 ++- + clutter/clutter/clutter-container-private.h | 36 +++++++++++++++++++++ + clutter/clutter/clutter-container.c | 21 ++++++++++++ + 5 files changed, 78 insertions(+), 6 deletions(-) + create mode 100644 clutter/clutter/clutter-container-private.h + +diff --git a/clutter/clutter/cally/cally-actor.c b/clutter/clutter/cally/cally-actor.c +index f341d3616..77195c0b0 100644 +--- a/clutter/clutter/cally/cally-actor.c ++++ b/clutter/clutter/cally/cally-actor.c +@@ -606,10 +606,11 @@ cally_actor_real_remove_actor (ClutterActor *container, + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), 0); + + atk_parent = ATK_OBJECT (data); +- atk_child = clutter_actor_get_accessible (actor); + +- if (atk_child) ++ if (clutter_actor_has_accessible (actor)) + { ++ atk_child = clutter_actor_get_accessible (actor); ++ + g_value_init (&values.old_value, G_TYPE_POINTER); + g_value_set_pointer (&values.old_value, atk_parent); + +diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c +index 6954f0396..8da53d3f1 100644 +--- a/clutter/clutter/clutter-actor.c ++++ b/clutter/clutter/clutter-actor.c +@@ -624,7 +624,7 @@ + #include "clutter-color-static.h" + #include "clutter-color.h" + #include "clutter-constraint-private.h" +-#include "clutter-container.h" ++#include "clutter-container-private.h" + #include "clutter-content-private.h" + #include "clutter-debug.h" + #include "clutter-easing.h" +@@ -4310,7 +4310,7 @@ clutter_actor_remove_child_internal (ClutterActor *self, + + /* we need to emit the signal before dropping the reference */ + if (emit_actor_removed) +- g_signal_emit_by_name (self, "actor-removed", child); ++ _clutter_container_emit_actor_removed (CLUTTER_CONTAINER (self), child); + + if (notify_first_last) + { +@@ -12980,7 +12980,7 @@ clutter_actor_add_child_internal (ClutterActor *self, + } + + if (emit_actor_added) +- g_signal_emit_by_name (self, "actor-added", child); ++ _clutter_container_emit_actor_added (CLUTTER_CONTAINER (self), child); + + if (notify_first_last) + { +@@ -21150,3 +21150,14 @@ clutter_actor_create_texture_paint_node (ClutterActor *self, + + return node; + } ++ ++gboolean ++clutter_actor_has_accessible (ClutterActor *actor) ++{ ++ g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), FALSE); ++ ++ if (CLUTTER_ACTOR_GET_CLASS (actor)->has_accessible) ++ return CLUTTER_ACTOR_GET_CLASS (actor)->has_accessible (actor); ++ ++ return TRUE; ++} +diff --git a/clutter/clutter/clutter-actor.h b/clutter/clutter/clutter-actor.h +index 0c5a08c8c..9b0665c72 100644 +--- a/clutter/clutter/clutter-actor.h ++++ b/clutter/clutter/clutter-actor.h +@@ -295,10 +295,11 @@ struct _ClutterActorClass + + gboolean (* touch_event) (ClutterActor *self, + ClutterTouchEvent *event); ++ gboolean (* has_accessible) (ClutterActor *self); + + /*< private >*/ + /* padding for future expansion */ +- gpointer _padding_dummy[26]; ++ gpointer _padding_dummy[25]; + }; + + /** +@@ -368,6 +369,8 @@ CLUTTER_AVAILABLE_IN_ALL + const gchar * clutter_actor_get_name (ClutterActor *self); + CLUTTER_AVAILABLE_IN_ALL + AtkObject * clutter_actor_get_accessible (ClutterActor *self); ++CLUTTER_AVAILABLE_IN_ALL ++gboolean clutter_actor_has_accessible (ClutterActor *self); + + CLUTTER_AVAILABLE_IN_1_24 + gboolean clutter_actor_is_visible (ClutterActor *self); +diff --git a/clutter/clutter/clutter-container-private.h b/clutter/clutter/clutter-container-private.h +new file mode 100644 +index 000000000..d619a6531 +--- /dev/null ++++ b/clutter/clutter/clutter-container-private.h +@@ -0,0 +1,36 @@ ++/* ++ * Clutter. ++ * ++ * An OpenGL based 'interactive canvas' library. ++ * ++ * Copyright 2020 Red Hat, Inc. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library. If not, see . ++ */ ++ ++#ifndef __CLUTTER_CONTAINER_PRIVATE_H__ ++#define __CLUTTER_CONTAINER_PRIVATE_H__ ++ ++#include ++ ++G_BEGIN_DECLS ++ ++void _clutter_container_emit_actor_added (ClutterContainer *container, ++ ClutterActor *actor); ++void _clutter_container_emit_actor_removed (ClutterContainer *container, ++ ClutterActor *actor); ++ ++G_END_DECLS ++ ++#endif /* __CLUTTER_CONTAINER_PRIVATE_H__ */ +diff --git a/clutter/clutter/clutter-container.c b/clutter/clutter/clutter-container.c +index 81fe4dc2e..52942a246 100644 +--- a/clutter/clutter/clutter-container.c ++++ b/clutter/clutter/clutter-container.c +@@ -39,6 +39,7 @@ + + #include "clutter-actor-private.h" + #include "clutter-child-meta.h" ++#include "clutter-container-private.h" + #include "clutter-debug.h" + #include "clutter-main.h" + #include "clutter-marshal.h" +@@ -1448,3 +1449,23 @@ clutter_container_child_notify (ClutterContainer *container, + child, + pspec); + } ++ ++void ++_clutter_container_emit_actor_added (ClutterContainer *container, ++ ClutterActor *actor) ++{ ++ g_return_if_fail (CLUTTER_IS_CONTAINER (container)); ++ g_return_if_fail (CLUTTER_IS_ACTOR (actor)); ++ ++ g_signal_emit (container, container_signals[ACTOR_ADDED], 0, actor); ++} ++ ++void ++_clutter_container_emit_actor_removed (ClutterContainer *container, ++ ClutterActor *actor) ++{ ++ g_return_if_fail (CLUTTER_IS_CONTAINER (container)); ++ g_return_if_fail (CLUTTER_IS_ACTOR (actor)); ++ ++ g_signal_emit (container, container_signals[ACTOR_REMOVED], 0, actor); ++} +-- +2.26.0 + diff --git a/SOURCES/0003-clutter-fix-hole-in-ClutterPaintNode.patch b/SOURCES/0003-clutter-fix-hole-in-ClutterPaintNode.patch new file mode 100644 index 0000000..0440f51 --- /dev/null +++ b/SOURCES/0003-clutter-fix-hole-in-ClutterPaintNode.patch @@ -0,0 +1,167 @@ +From 6d849de8ff486be21ff931bfa63313240b212852 Mon Sep 17 00:00:00 2001 +From: Christian Hergert +Date: Fri, 21 Feb 2020 22:36:31 +0000 +Subject: [PATCH 3/3] clutter: fix hole in ClutterPaintNode + +Fixing the missalignment takes the structure from 80 bytes down to 72. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/1081 +--- + clutter/clutter/clutter-actor.c | 8 +++---- + clutter/clutter/clutter-canvas.c | 2 +- + clutter/clutter/clutter-image.c | 2 +- + clutter/clutter/clutter-paint-node-private.h | 6 ++--- + clutter/clutter/clutter-paint-node.c | 23 +++++++++++++++----- + clutter/clutter/clutter-paint-node.h | 3 +++ + 6 files changed, 30 insertions(+), 14 deletions(-) + +diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c +index 8da53d3f1..995de8c35 100644 +--- a/clutter/clutter/clutter-actor.c ++++ b/clutter/clutter/clutter-actor.c +@@ -3692,7 +3692,7 @@ clutter_actor_paint_node (ClutterActor *actor, + clear_flags |= COGL_BUFFER_BIT_COLOR; + + node = _clutter_root_node_new (fb, &bg_color, clear_flags); +- clutter_paint_node_set_name (node, "stageClear"); ++ clutter_paint_node_set_static_name (node, "stageClear"); + clutter_paint_node_add_rectangle (node, &box); + clutter_paint_node_add_child (root, node); + clutter_paint_node_unref (node); +@@ -3707,7 +3707,7 @@ clutter_actor_paint_node (ClutterActor *actor, + / 255; + + node = clutter_color_node_new (&bg_color); +- clutter_paint_node_set_name (node, "backgroundColor"); ++ clutter_paint_node_set_static_name (node, "backgroundColor"); + clutter_paint_node_add_rectangle (node, &box); + clutter_paint_node_add_child (root, node); + clutter_paint_node_unref (node); +@@ -4014,7 +4014,7 @@ clutter_actor_continue_paint (ClutterActor *self) + * virtual function can then be called directly. + */ + dummy = _clutter_dummy_node_new (self); +- clutter_paint_node_set_name (dummy, "Root"); ++ clutter_paint_node_set_static_name (dummy, "Root"); + + /* XXX - for 1.12, we use the return value of paint_node() to + * decide whether we should emit the ::paint signal. +@@ -21129,7 +21129,7 @@ clutter_actor_create_texture_paint_node (ClutterActor *self, + color.alpha = clutter_actor_get_paint_opacity_internal (self); + + node = clutter_texture_node_new (texture, &color, priv->min_filter, priv->mag_filter); +- clutter_paint_node_set_name (node, "Texture"); ++ clutter_paint_node_set_static_name (node, "Texture"); + + if (priv->content_repeat == CLUTTER_REPEAT_NONE) + clutter_paint_node_add_rectangle (node, &box); +diff --git a/clutter/clutter/clutter-canvas.c b/clutter/clutter/clutter-canvas.c +index 42e54ce9d..512e434ed 100644 +--- a/clutter/clutter/clutter-canvas.c ++++ b/clutter/clutter/clutter-canvas.c +@@ -319,7 +319,7 @@ clutter_canvas_paint_content (ClutterContent *content, + return; + + node = clutter_actor_create_texture_paint_node (actor, priv->texture); +- clutter_paint_node_set_name (node, "Canvas Content"); ++ clutter_paint_node_set_static_name (node, "Canvas Content"); + clutter_paint_node_add_child (root, node); + clutter_paint_node_unref (node); + +diff --git a/clutter/clutter/clutter-image.c b/clutter/clutter/clutter-image.c +index 722b0375d..51e610073 100644 +--- a/clutter/clutter/clutter-image.c ++++ b/clutter/clutter/clutter-image.c +@@ -108,7 +108,7 @@ clutter_image_paint_content (ClutterContent *content, + return; + + node = clutter_actor_create_texture_paint_node (actor, priv->texture); +- clutter_paint_node_set_name (node, "Image Content"); ++ clutter_paint_node_set_static_name (node, "Image Content"); + clutter_paint_node_add_child (root, node); + clutter_paint_node_unref (node); + } +diff --git a/clutter/clutter/clutter-paint-node-private.h b/clutter/clutter/clutter-paint-node-private.h +index 2945b78a4..ea1665ada 100644 +--- a/clutter/clutter/clutter-paint-node-private.h ++++ b/clutter/clutter/clutter-paint-node-private.h +@@ -48,11 +48,11 @@ struct _ClutterPaintNode + ClutterPaintNode *next_sibling; + ClutterPaintNode *last_child; + +- guint n_children; +- + GArray *operations; + +- gchar *name; ++ const gchar *name; ++ ++ guint n_children; + + volatile int ref_count; + }; +diff --git a/clutter/clutter/clutter-paint-node.c b/clutter/clutter/clutter-paint-node.c +index db68b7766..5129e00cf 100644 +--- a/clutter/clutter/clutter-paint-node.c ++++ b/clutter/clutter/clutter-paint-node.c +@@ -173,8 +173,6 @@ clutter_paint_node_real_finalize (ClutterPaintNode *node) + { + ClutterPaintNode *iter; + +- g_free (node->name); +- + if (node->operations != NULL) + { + guint i; +@@ -296,7 +294,8 @@ clutter_paint_node_get_type (void) + * + * The @name will be used for debugging purposes. + * +- * The @node will copy the passed string. ++ * The @node will intern @name using g_intern_string(). If you have access to a ++ * static string, use clutter_paint_node_set_static_name() instead. + * + * Since: 1.10 + */ +@@ -306,8 +305,22 @@ clutter_paint_node_set_name (ClutterPaintNode *node, + { + g_return_if_fail (CLUTTER_IS_PAINT_NODE (node)); + +- g_free (node->name); +- node->name = g_strdup (name); ++ node->name = g_intern_string (name); ++} ++ ++/** ++ * clutter_paint_node_set_static_name: (skip) ++ * ++ * Like clutter_paint_node_set_name() but uses a static or interned string ++ * containing the name. ++ */ ++void ++clutter_paint_node_set_static_name (ClutterPaintNode *node, ++ const char *name) ++{ ++ g_return_if_fail (CLUTTER_IS_PAINT_NODE (node)); ++ ++ node->name = name; + } + + /** +diff --git a/clutter/clutter/clutter-paint-node.h b/clutter/clutter/clutter-paint-node.h +index 5f3e962e4..d3e4e7922 100644 +--- a/clutter/clutter/clutter-paint-node.h ++++ b/clutter/clutter/clutter-paint-node.h +@@ -52,6 +52,9 @@ void clutter_paint_node_unref (Clutter + CLUTTER_AVAILABLE_IN_1_10 + void clutter_paint_node_set_name (ClutterPaintNode *node, + const char *name); ++CLUTTER_AVAILABLE_IN_ALL ++void clutter_paint_node_set_static_name (ClutterPaintNode *node, ++ const char *name); + + CLUTTER_AVAILABLE_IN_1_10 + void clutter_paint_node_add_child (ClutterPaintNode *node, +-- +2.26.0 + diff --git a/SOURCES/idle-monitor-reset-fix.patch b/SOURCES/idle-monitor-reset-fix.patch new file mode 100644 index 0000000..411b625 --- /dev/null +++ b/SOURCES/idle-monitor-reset-fix.patch @@ -0,0 +1,128 @@ +From 23c81629d775fd902e4bee7ec0a182a916f4252b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Mon, 16 Sep 2019 16:17:48 +0200 +Subject: [PATCH 1/3] idle-monitor: Make helper function static + +It wasn't used outside the file, so no reason to not have it static. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/799 +--- + src/backends/meta-idle-monitor-private.h | 1 - + src/backends/meta-idle-monitor.c | 8 ++++---- + 2 files changed, 4 insertions(+), 5 deletions(-) + +diff --git a/src/backends/meta-idle-monitor-private.h b/src/backends/meta-idle-monitor-private.h +index 82f3f87b7..9ce7e743a 100644 +--- a/src/backends/meta-idle-monitor-private.h ++++ b/src/backends/meta-idle-monitor-private.h +@@ -54,7 +54,6 @@ struct _MetaIdleMonitorClass + GObjectClass parent_class; + }; + +-void _meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch); + void meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor); + + #endif /* META_IDLE_MONITOR_PRIVATE_H */ +diff --git a/src/backends/meta-idle-monitor.c b/src/backends/meta-idle-monitor.c +index 2c06ee73c..ce1b87bbb 100644 +--- a/src/backends/meta-idle-monitor.c ++++ b/src/backends/meta-idle-monitor.c +@@ -54,8 +54,8 @@ static GParamSpec *obj_props[PROP_LAST]; + + G_DEFINE_TYPE (MetaIdleMonitor, meta_idle_monitor, G_TYPE_OBJECT) + +-void +-_meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch) ++static void ++meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch) + { + MetaIdleMonitor *monitor; + guint id; +@@ -319,7 +319,7 @@ idle_monitor_dispatch_timeout (GSource *source, + if (ready_time > now) + return G_SOURCE_CONTINUE; + +- _meta_idle_monitor_watch_fire (watch); ++ meta_idle_monitor_watch_fire (watch); + g_source_set_ready_time (watch->timeout_source, -1); + + return G_SOURCE_CONTINUE; +@@ -506,7 +506,7 @@ meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor) + + if (watch->timeout_msec == 0) + { +- _meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch); ++ meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch); + } + else + { +-- +2.23.0 + + +From 0d43bbdae0a08c7618e789fa0d5270615c907a36 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Mon, 16 Sep 2019 16:36:05 +0200 +Subject: [PATCH 2/3] idle-monitor: Remove redundant type cast + +No need to type cast a `MetaIdleMonitorWatch *` to a +`MetaIdleMonitorWatch *`. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/799 +--- + src/backends/meta-idle-monitor.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/backends/meta-idle-monitor.c b/src/backends/meta-idle-monitor.c +index ce1b87bbb..3dbb89944 100644 +--- a/src/backends/meta-idle-monitor.c ++++ b/src/backends/meta-idle-monitor.c +@@ -506,7 +506,7 @@ meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor) + + if (watch->timeout_msec == 0) + { +- meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch); ++ meta_idle_monitor_watch_fire (watch); + } + else + { +-- +2.23.0 + + +From f6c24dd45c14dd16d6878ebf170f8468ad3d47e1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Mon, 16 Sep 2019 16:36:51 +0200 +Subject: [PATCH 3/3] idle-monitor: Reset timeout before firing watch + +The watch might be removed during firing, meaning the source is +destroyed after returning. Avoid use-after-free by unsetting the timeout +before firing. Returning G_SOURCE_CONTINUE in that case is harmless, as +source is destroyed. + +Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/796 + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/799 +--- + src/backends/meta-idle-monitor.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/backends/meta-idle-monitor.c b/src/backends/meta-idle-monitor.c +index 3dbb89944..c6e814468 100644 +--- a/src/backends/meta-idle-monitor.c ++++ b/src/backends/meta-idle-monitor.c +@@ -319,9 +319,10 @@ idle_monitor_dispatch_timeout (GSource *source, + if (ready_time > now) + return G_SOURCE_CONTINUE; + +- meta_idle_monitor_watch_fire (watch); + g_source_set_ready_time (watch->timeout_source, -1); + ++ meta_idle_monitor_watch_fire (watch); ++ + return G_SOURCE_CONTINUE; + } + +-- +2.23.0 + diff --git a/SOURCES/input-after-long-idle-fix.patch b/SOURCES/input-after-long-idle-fix.patch new file mode 100644 index 0000000..d211ff9 --- /dev/null +++ b/SOURCES/input-after-long-idle-fix.patch @@ -0,0 +1,378 @@ +From 388ed4984586f96250934a025b1c78915c4cd856 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Thu, 24 Oct 2019 21:19:36 +0200 +Subject: [PATCH 1/2] display: Move finishing of touch sequence to the backend + +We need to manipulate an X11 grab when a touch sequence ends; move that +logic to where it belongs - in the X11 backend. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/886 +--- + src/backends/meta-backend-private.h | 16 ++++++++++++ + src/backends/meta-backend.c | 14 +++++++++++ + src/backends/x11/meta-backend-x11.c | 23 +++++++++++++++++ + src/core/display.c | 33 +++++++++++-------------- + src/core/meta-gesture-tracker-private.h | 7 +----- + src/core/meta-gesture-tracker.c | 1 + + 6 files changed, 70 insertions(+), 24 deletions(-) + +diff --git a/src/backends/meta-backend-private.h b/src/backends/meta-backend-private.h +index a25275499..7f4a4ea0f 100644 +--- a/src/backends/meta-backend-private.h ++++ b/src/backends/meta-backend-private.h +@@ -51,6 +51,14 @@ + #define META_TYPE_BACKEND (meta_backend_get_type ()) + G_DECLARE_DERIVABLE_TYPE (MetaBackend, meta_backend, META, BACKEND, GObject) + ++typedef enum _MetaSequenceState ++{ ++ META_SEQUENCE_NONE, ++ META_SEQUENCE_ACCEPTED, ++ META_SEQUENCE_REJECTED, ++ META_SEQUENCE_PENDING_END ++} MetaSequenceState; ++ + struct _MetaBackendClass + { + GObjectClass parent_class; +@@ -73,6 +81,10 @@ struct _MetaBackendClass + int device_id, + uint32_t timestamp); + ++ void (* finish_touch_sequence) (MetaBackend *backend, ++ ClutterEventSequence *sequence, ++ MetaSequenceState state); ++ + void (* warp_pointer) (MetaBackend *backend, + int x, + int y); +@@ -134,6 +146,10 @@ gboolean meta_backend_ungrab_device (MetaBackend *backend, + int device_id, + uint32_t timestamp); + ++void meta_backend_finish_touch_sequence (MetaBackend *backend, ++ ClutterEventSequence *sequence, ++ MetaSequenceState state); ++ + void meta_backend_warp_pointer (MetaBackend *backend, + int x, + int y); +diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c +index ce7e385b9..fb4f69fe6 100644 +--- a/src/backends/meta-backend.c ++++ b/src/backends/meta-backend.c +@@ -846,6 +846,20 @@ meta_backend_ungrab_device (MetaBackend *backend, + return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp); + } + ++/** ++ * meta_backend_finish_touch_sequence: (skip) ++ */ ++void ++meta_backend_finish_touch_sequence (MetaBackend *backend, ++ ClutterEventSequence *sequence, ++ MetaSequenceState state) ++{ ++ if (META_BACKEND_GET_CLASS (backend)->finish_touch_sequence) ++ META_BACKEND_GET_CLASS (backend)->finish_touch_sequence (backend, ++ sequence, ++ state); ++} ++ + /** + * meta_backend_warp_pointer: (skip) + */ +diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c +index 2b131d2d0..2835d47d6 100644 +--- a/src/backends/x11/meta-backend-x11.c ++++ b/src/backends/x11/meta-backend-x11.c +@@ -583,6 +583,28 @@ meta_backend_x11_ungrab_device (MetaBackend *backend, + return (ret == Success); + } + ++static void ++meta_backend_x11_finish_touch_sequence (MetaBackend *backend, ++ ClutterEventSequence *sequence, ++ MetaSequenceState state) ++{ ++ MetaBackendX11 *x11 = META_BACKEND_X11 (backend); ++ MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); ++ int event_mode; ++ ++ if (state == META_SEQUENCE_ACCEPTED) ++ event_mode = XIAcceptTouch; ++ else if (state == META_SEQUENCE_REJECTED) ++ event_mode = XIRejectTouch; ++ else ++ g_return_if_reached (); ++ ++ XIAllowTouchEvents (priv->xdisplay, ++ META_VIRTUAL_CORE_POINTER_ID, ++ clutter_x11_event_sequence_get_touch_detail (sequence), ++ DefaultRootWindow (priv->xdisplay), event_mode); ++} ++ + static void + meta_backend_x11_warp_pointer (MetaBackend *backend, + int x, +@@ -768,6 +790,7 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass) + backend_class->post_init = meta_backend_x11_post_init; + backend_class->grab_device = meta_backend_x11_grab_device; + backend_class->ungrab_device = meta_backend_x11_ungrab_device; ++ backend_class->finish_touch_sequence = meta_backend_x11_finish_touch_sequence; + backend_class->warp_pointer = meta_backend_x11_warp_pointer; + backend_class->get_current_logical_monitor = meta_backend_x11_get_current_logical_monitor; + backend_class->get_keymap = meta_backend_x11_get_keymap; +diff --git a/src/core/display.c b/src/core/display.c +index e7dd4534b..d4775cec3 100644 +--- a/src/core/display.c ++++ b/src/core/display.c +@@ -55,6 +55,7 @@ + #include "backends/x11/meta-backend-x11.h" + #include "backends/meta-stage-private.h" + #include "backends/meta-input-settings-private.h" ++#include "backends/meta-backend-private.h" + #include + + #ifdef HAVE_RANDR +@@ -533,27 +534,23 @@ gesture_tracker_state_changed (MetaGestureTracker *tracker, + MetaSequenceState state, + MetaDisplay *display) + { +- if (meta_is_wayland_compositor ()) ++ switch (state) + { +- if (state == META_SEQUENCE_ACCEPTED) +- meta_display_cancel_touch (display); +- } +- else +- { +- MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ()); +- int event_mode; ++ case META_SEQUENCE_NONE: ++ case META_SEQUENCE_PENDING_END: ++ return; ++ case META_SEQUENCE_ACCEPTED: ++ meta_display_cancel_touch (display); + +- if (state == META_SEQUENCE_ACCEPTED) +- event_mode = XIAcceptTouch; +- else if (state == META_SEQUENCE_REJECTED) +- event_mode = XIRejectTouch; +- else +- return; ++ /* Intentional fall-through */ ++ case META_SEQUENCE_REJECTED: ++ { ++ MetaBackend *backend; + +- XIAllowTouchEvents (meta_backend_x11_get_xdisplay (backend), +- META_VIRTUAL_CORE_POINTER_ID, +- clutter_x11_event_sequence_get_touch_detail (sequence), +- DefaultRootWindow (display->xdisplay), event_mode); ++ backend = meta_get_backend (); ++ meta_backend_finish_touch_sequence (backend, sequence, state); ++ break; ++ } + } + } + +diff --git a/src/core/meta-gesture-tracker-private.h b/src/core/meta-gesture-tracker-private.h +index 0e39af27f..b4fb02a1e 100644 +--- a/src/core/meta-gesture-tracker-private.h ++++ b/src/core/meta-gesture-tracker-private.h +@@ -38,12 +38,7 @@ + typedef struct _MetaGestureTracker MetaGestureTracker; + typedef struct _MetaGestureTrackerClass MetaGestureTrackerClass; + +-typedef enum { +- META_SEQUENCE_NONE, +- META_SEQUENCE_ACCEPTED, +- META_SEQUENCE_REJECTED, +- META_SEQUENCE_PENDING_END +-} MetaSequenceState; ++typedef enum _MetaSequenceState MetaSequenceState; + + struct _MetaGestureTracker + { +diff --git a/src/core/meta-gesture-tracker.c b/src/core/meta-gesture-tracker.c +index e3b702f56..1313aad6d 100644 +--- a/src/core/meta-gesture-tracker.c ++++ b/src/core/meta-gesture-tracker.c +@@ -31,6 +31,7 @@ + #include "config.h" + #include "meta-gesture-tracker-private.h" + #include "meta-surface-actor.h" ++#include "meta-backend-private.h" + + #define DISTANCE_THRESHOLD 30 + +-- +2.23.0 + + +From 75cf52ac533675ecf5d3542e9fba2937a56bfefd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Fri, 25 Oct 2019 10:06:55 +0200 +Subject: [PATCH 2/2] x11: Limit touch replay pointer events to when replaying + +When a touch sequence was rejected, the emulated pointer events would be +replayed with old timestamps. This caused issues with grabs as they +would be ignored due to being too old. This was mitigated by making sure +device event timestamps never travelled back in time by tampering with +any event that had a timestamp seemingly in the past. + +This failed when the most recent timestamp that had been received were +much older than the timestamp of the new event. This could for example +happen when a session was left not interacted with for 40+ days or so; +when interacted with again, as any new timestamp would according to +XSERVER_TIME_IS_BEFORE() still be in the past compared to the "most +recent" one. The effect is that we'd always use the `latest_evtime` for +all new device events without ever updating it. + +The end result of this was that passive grabs would become active when +interacted with, but would then newer be released, as the timestamps to +XIAllowEvents() would out of date, resulting in the desktop effectively +freezing, as the Shell would have an active pointer grab. + +To avoid the situation where we get stuck with an old `latest_evtime` +timestamp, limit the tampering with device event timestamp to 1) only +pointer events, and 2) only during the replay sequence. The second part +is implemented by sending an asynchronous message via the X server after +rejecting a touch sequence, only potentially tampering with the device +event timestamps until the reply. This should avoid the stuck timestamp +as in those situations, we'll always have a relatively up to date +`latest_evtime` meaning XSERVER_TIME_IS_BEFORE() will not get confused. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/886 +--- + src/backends/x11/meta-backend-x11.c | 71 +++++++++++++++++++++++------ + 1 file changed, 58 insertions(+), 13 deletions(-) + +diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c +index 2835d47d6..3f8645e93 100644 +--- a/src/backends/x11/meta-backend-x11.c ++++ b/src/backends/x11/meta-backend-x11.c +@@ -60,6 +60,10 @@ struct _MetaBackendX11Private + XSyncAlarm user_active_alarm; + XSyncCounter counter; + ++ int current_touch_replay_sync_serial; ++ int pending_touch_replay_sync_serial; ++ Atom touch_replay_sync_atom; ++ + int xinput_opcode; + int xinput_event_base; + int xinput_error_base; +@@ -168,6 +172,26 @@ meta_backend_x11_translate_device_event (MetaBackendX11 *x11, + backend_x11_class->translate_device_event (x11, device_event); + } + ++static void ++maybe_translate_touch_replay_pointer_event (MetaBackendX11 *x11, ++ XIDeviceEvent *device_event) ++{ ++ MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); ++ ++ if (!device_event->send_event && ++ device_event->time != CurrentTime && ++ priv->current_touch_replay_sync_serial != ++ priv->pending_touch_replay_sync_serial && ++ XSERVER_TIME_IS_BEFORE (device_event->time, priv->latest_evtime)) ++ { ++ /* Emulated pointer events received after XIRejectTouch is received ++ * on a passive touch grab will contain older timestamps, update those ++ * so we dont get InvalidTime at grabs. ++ */ ++ device_event->time = priv->latest_evtime; ++ } ++} ++ + static void + translate_device_event (MetaBackendX11 *x11, + XIDeviceEvent *device_event) +@@ -177,19 +201,7 @@ translate_device_event (MetaBackendX11 *x11, + meta_backend_x11_translate_device_event (x11, device_event); + + if (!device_event->send_event && device_event->time != CurrentTime) +- { +- if (XSERVER_TIME_IS_BEFORE (device_event->time, priv->latest_evtime)) +- { +- /* Emulated pointer events received after XIRejectTouch is received +- * on a passive touch grab will contain older timestamps, update those +- * so we dont get InvalidTime at grabs. +- */ +- device_event->time = priv->latest_evtime; +- } +- +- /* Update the internal latest evtime, for any possible later use */ +- priv->latest_evtime = device_event->time; +- } ++ priv->latest_evtime = device_event->time; + } + + static void +@@ -254,6 +266,9 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11, + case XI_Motion: + case XI_ButtonPress: + case XI_ButtonRelease: ++ maybe_translate_touch_replay_pointer_event (x11, ++ (XIDeviceEvent *) input_event); ++ /* Intentional fall-through */ + case XI_KeyPress: + case XI_KeyRelease: + case XI_TouchBegin: +@@ -321,6 +336,17 @@ handle_host_xevent (MetaBackend *backend, + MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); + gboolean bypass_clutter = FALSE; + ++ switch (event->type) ++ { ++ case ClientMessage: ++ if (event->xclient.window == meta_backend_x11_get_xwindow (x11) && ++ event->xclient.message_type == priv->touch_replay_sync_atom) ++ priv->current_touch_replay_sync_serial = event->xclient.data.l[0]; ++ break; ++ default: ++ break; ++ } ++ + XGetEventData (priv->xdisplay, &event->xcookie); + + { +@@ -528,6 +554,10 @@ meta_backend_x11_post_init (MetaBackend *backend) + monitor_manager = meta_backend_get_monitor_manager (backend); + g_signal_connect (monitor_manager, "monitors-changed-internal", + G_CALLBACK (on_monitors_changed), backend); ++ ++ priv->touch_replay_sync_atom = XInternAtom (priv->xdisplay, ++ "_MUTTER_TOUCH_SEQUENCE_SYNC", ++ False); + } + + static ClutterBackend * +@@ -603,6 +633,21 @@ meta_backend_x11_finish_touch_sequence (MetaBackend *backend, + META_VIRTUAL_CORE_POINTER_ID, + clutter_x11_event_sequence_get_touch_detail (sequence), + DefaultRootWindow (priv->xdisplay), event_mode); ++ ++ if (state == META_SEQUENCE_REJECTED) ++ { ++ XClientMessageEvent ev; ++ ++ ev = (XClientMessageEvent) { ++ .type = ClientMessage, ++ .window = meta_backend_x11_get_xwindow (x11), ++ .message_type = priv->touch_replay_sync_atom, ++ .format = 32, ++ .data.l[0] = ++priv->pending_touch_replay_sync_serial, ++ }; ++ XSendEvent (priv->xdisplay, meta_backend_x11_get_xwindow (x11), ++ False, 0, (XEvent *) &ev); ++ } + } + + static void +-- +2.23.0 + diff --git a/SOURCES/more-performance-backports.patch b/SOURCES/more-performance-backports.patch new file mode 100644 index 0000000..17db38d --- /dev/null +++ b/SOURCES/more-performance-backports.patch @@ -0,0 +1,186 @@ +From f86e33e1ea32c4208809e8de33bed05ddbce9a4c Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Sun, 7 May 2017 03:00:10 +0200 +Subject: [PATCH 1/3] compositor: Avoid changing pipeline/source if shadow is + not being painted + +Avoids some context invalidations in cogl. + +https://bugzilla.gnome.org/show_bug.cgi?id=782344 +--- + src/compositor/meta-shadow-factory.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +diff --git a/src/compositor/meta-shadow-factory.c b/src/compositor/meta-shadow-factory.c +index cd006008b..19147ca9f 100644 +--- a/src/compositor/meta-shadow-factory.c ++++ b/src/compositor/meta-shadow-factory.c +@@ -220,9 +220,7 @@ meta_shadow_paint (MetaShadow *shadow, + int dest_x[4]; + int dest_y[4]; + int n_x, n_y; +- +- cogl_pipeline_set_color4ub (shadow->pipeline, +- opacity, opacity, opacity, opacity); ++ gboolean source_updated = FALSE; + + cogl_set_source (shadow->pipeline); + +@@ -300,6 +298,17 @@ meta_shadow_paint (MetaShadow *shadow, + else + overlap = CAIRO_REGION_OVERLAP_IN; + ++ if (overlap == CAIRO_REGION_OVERLAP_OUT) ++ continue; ++ ++ if (!source_updated) ++ { ++ cogl_pipeline_set_color4ub (shadow->pipeline, ++ opacity, opacity, opacity, opacity); ++ cogl_set_source (shadow->pipeline); ++ source_updated = TRUE; ++ } ++ + /* There's quite a bit of overhead from allocating a new + * region in order to find an exact intersection and + * generating more geometry - we make the assumption that +-- +2.23.0 + + +From f530bc4c3391cabe2b084cd59def00d81c13286c Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Fri, 5 May 2017 14:15:30 +0200 +Subject: [PATCH 2/3] clutter: Avoid rounding compensation when invalidating 2D + actors + +This allows the redraw clip to be more constrained, so MetaCullable doesn't +end up rendering portions of window shadows, frame and background when a +window invalidates (part of) its contents. + +https://bugzilla.gnome.org/show_bug.cgi?id=782344 +--- + clutter/clutter/clutter-paint-volume.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/clutter/clutter/clutter-paint-volume.c b/clutter/clutter/clutter-paint-volume.c +index b48f7f9d6..f3405138b 100644 +--- a/clutter/clutter/clutter-paint-volume.c ++++ b/clutter/clutter/clutter-paint-volume.c +@@ -1166,6 +1166,21 @@ _clutter_paint_volume_get_stage_paint_box (ClutterPaintVolume *pv, + + _clutter_paint_volume_get_bounding_box (&projected_pv, box); + ++ if (pv->is_2d && pv->actor && ++ clutter_actor_get_z_position (pv->actor) == 0) ++ { ++ /* If the volume/actor are perfectly 2D, take the bounding box as ++ * good. We won't need to add any extra room for sub-pixel positioning ++ * in this case. ++ */ ++ clutter_paint_volume_free (&projected_pv); ++ box->x1 = CLUTTER_NEARBYINT (box->x1); ++ box->y1 = CLUTTER_NEARBYINT (box->y1); ++ box->x2 = CLUTTER_NEARBYINT (box->x2); ++ box->y2 = CLUTTER_NEARBYINT (box->y2); ++ return; ++ } ++ + /* The aim here is that for a given rectangle defined with floating point + * coordinates we want to determine a stable quantized size in pixels + * that doesn't vary due to the original box's sub-pixel position. +-- +2.23.0 + + +From 676369000658c6121d0c3b5e1286aa68dc79eb35 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Mon, 8 May 2017 15:10:58 +0200 +Subject: [PATCH 3/3] cogl: Ensure to only clear the depth buffer if depth + testing is enabled + +The depth buffer is marked as invalid when 1) the framebuffer is just created, +and 2) whenever GL_DEPTH_TEST is enabled on it. This will ensure the +framebuffers attached depth buffer (if any) is properly cleared before it's +actually used, while saving needless clears while depth testing is disabled +(the default). + +https://bugzilla.gnome.org/show_bug.cgi?id=782344 +--- + cogl/cogl/cogl-framebuffer-private.h | 5 +++++ + cogl/cogl/cogl-framebuffer.c | 11 +++++++++++ + cogl/cogl/driver/gl/cogl-pipeline-opengl.c | 6 +++++- + 3 files changed, 21 insertions(+), 1 deletion(-) + +diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h +index 99ac2fba9..756e34dfe 100644 +--- a/cogl/cogl/cogl-framebuffer-private.h ++++ b/cogl/cogl/cogl-framebuffer-private.h +@@ -193,6 +193,11 @@ struct _CoglFramebuffer + CoglFramebufferBits bits; + + int samples_per_pixel; ++ ++ /* Whether the depth buffer was enabled for this framebuffer, ++ * usually means it needs to be cleared before being reused next. ++ */ ++ CoglBool depth_buffer_clear_needed; + }; + + typedef enum { +diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c +index 55b9e3756..6b105087d 100644 +--- a/cogl/cogl/cogl-framebuffer.c ++++ b/cogl/cogl/cogl-framebuffer.c +@@ -117,6 +117,7 @@ _cogl_framebuffer_init (CoglFramebuffer *framebuffer, + framebuffer->viewport_age_for_scissor_workaround = -1; + framebuffer->dither_enabled = TRUE; + framebuffer->depth_writing_enabled = TRUE; ++ framebuffer->depth_buffer_clear_needed = TRUE; + + framebuffer->modelview_stack = cogl_matrix_stack_new (ctx); + framebuffer->projection_stack = cogl_matrix_stack_new (ctx); +@@ -268,6 +269,13 @@ cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer, + int scissor_y1; + CoglBool saved_viewport_scissor_workaround; + ++ if (!framebuffer->depth_buffer_clear_needed && ++ (buffers & COGL_BUFFER_BIT_DEPTH)) ++ buffers &= ~(COGL_BUFFER_BIT_DEPTH); ++ ++ if (buffers == 0) ++ return; ++ + _cogl_clip_stack_get_bounds (clip_stack, + &scissor_x0, &scissor_y0, + &scissor_x1, &scissor_y1); +@@ -415,6 +423,9 @@ cleared: + _cogl_framebuffer_mark_mid_scene (framebuffer); + _cogl_framebuffer_mark_clear_clip_dirty (framebuffer); + ++ if (buffers & COGL_BUFFER_BIT_DEPTH) ++ framebuffer->depth_buffer_clear_needed = FALSE; ++ + if (buffers & COGL_BUFFER_BIT_COLOR && buffers & COGL_BUFFER_BIT_DEPTH) + { + /* For our fast-path for reading back a single pixel of simple +diff --git a/cogl/cogl/driver/gl/cogl-pipeline-opengl.c b/cogl/cogl/driver/gl/cogl-pipeline-opengl.c +index 178269646..4f1f69f96 100644 +--- a/cogl/cogl/driver/gl/cogl-pipeline-opengl.c ++++ b/cogl/cogl/driver/gl/cogl-pipeline-opengl.c +@@ -418,7 +418,11 @@ flush_depth_state (CoglContext *ctx, + if (ctx->depth_test_enabled_cache != depth_state->test_enabled) + { + if (depth_state->test_enabled == TRUE) +- GE (ctx, glEnable (GL_DEPTH_TEST)); ++ { ++ GE (ctx, glEnable (GL_DEPTH_TEST)); ++ if (ctx->current_draw_buffer) ++ ctx->current_draw_buffer->depth_buffer_clear_needed = TRUE; ++ } + else + GE (ctx, glDisable (GL_DEPTH_TEST)); + ctx->depth_test_enabled_cache = depth_state->test_enabled; +-- +2.23.0 + diff --git a/SPECS/mutter.spec b/SPECS/mutter.spec index cea0b73..085f9fe 100644 --- a/SPECS/mutter.spec +++ b/SPECS/mutter.spec @@ -10,7 +10,7 @@ Name: mutter Version: 3.28.3 -Release: 16%{?dist} +Release: 23%{?dist} Summary: Window and compositing manager based on Clutter License: GPLv2+ @@ -99,6 +99,27 @@ Patch278: 0002-xprops-Make-sure-text_property_to_utf8-returns-UTF8.patch # Don't loose pointer button grabs (#1657887) Patch279: 0001-events-Sync-pending-pointer-events-without-a-window.patch +# Don't freeze if input happens after many days of inactivity (#1728761) +Patch280: input-after-long-idle-fix.patch + +# More performance backports (#1766501) +Patch281: more-performance-backports.patch + +# Fix invalid read in idle monitor (#1752378) +Patch282: idle-monitor-reset-fix.patch + +# Prevent orphaned animation actors getting stuck on screen (#1753799) +Patch283: 0001-window-free-close-dialog-before-unmanaging-window-fr.patch +Patch284: 0001-core-Hide-close-dialog-before-destroying.patch + +# Add PING_TIMEOUT_DELAY to mutter MetaPreferences #1809164 +Patch285: 0001-display-Make-check-alive-timeout-configureable.patch + +# Improve performance under load (#1824869) +Patch290: 0001-clutter-avoid-redundant-_clutter_paint_node_init_typ.patch +Patch291: 0002-clutter-avoid-g_signal_emit_by_name-from-ClutterActo.patch +Patch292: 0003-clutter-fix-hole-in-ClutterPaintNode.patch + BuildRequires: chrpath BuildRequires: pango-devel BuildRequires: startup-notification-devel @@ -254,6 +275,34 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : %{_libdir}/pkgconfig/* %changelog +* Fri Apr 17 2020 Florian Müllner - 3.28.3-23 +- Improve performance under IO load + Resolves: #1824869 + +* Fri Mar 06 2020 Florian Müllner - 3.28.3-22 +- Include one more close-dialog backport + Related: #1753799 + +* Thu Mar 05 2020 Jonas Ådahl ) - 3.28.3-21 +- Add PING_TIMEOUT_DELAY to mutter MetaPreferences + Resolves: #1809164 + +* Tue Dec 03 2019 Florian Müllner - 3.28.3-20 +- Free close dialog before unmanaging parent + Related: #1753799 + +* Tue Oct 29 2019 Jonas Ådahl ) - 3.28.3-19 +- Fix invalid read in idle monitor + Resolves: #1752378 + +* Tue Oct 29 2019 Jonas Ådahl ) - 3.28.3-18 +- More performance backports + Resolves: #1766501 + +* Tue Oct 29 2019 Jonas Ådahl ) - 3.28.3-17 +- Don't freeze if input happens after many days of inactivity + Resolves: #1728761 + * Wed Oct 02 2019 Jonas Ådahl ) - 3.28.3-16 - Don't loose pointer button grabs Resolves: #1657887