diff --git a/2901.patch b/2901.patch new file mode 100644 index 0000000..ee33e51 --- /dev/null +++ b/2901.patch @@ -0,0 +1,247 @@ +From 74b3c9c09cc9389fffd8fae7c5af781f548e3cbc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Mon, 6 Mar 2023 23:47:02 +0100 +Subject: [PATCH 1/4] clutter/frame-clock: Warn if frame clock is disposed + while dispatching + +This shouldn't happen, but warn anyway to be a bit more helpful if +things go bad. +--- + clutter/clutter/clutter-frame-clock.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c +index e5d1a44e2e..eeba108e15 100644 +--- a/clutter/clutter/clutter-frame-clock.c ++++ b/clutter/clutter/clutter-frame-clock.c +@@ -957,6 +957,8 @@ clutter_frame_clock_dispose (GObject *object) + { + ClutterFrameClock *frame_clock = CLUTTER_FRAME_CLOCK (object); + ++ g_warn_if_fail (frame_clock->state != CLUTTER_FRAME_CLOCK_STATE_DISPATCHING); ++ + if (frame_clock->source) + { + g_signal_emit (frame_clock, signals[DESTROY], 0); +-- +GitLab + + +From 607d45d24fe672efc7cae755da4ec643b9a377ad Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Mon, 6 Mar 2023 23:48:36 +0100 +Subject: [PATCH 2/4] monitor-manager: Use guint for handle IDs + +To follow convention. +--- + src/backends/meta-monitor-manager-private.h | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h +index d6a92bf2ac..56431ba600 100644 +--- a/src/backends/meta-monitor-manager-private.h ++++ b/src/backends/meta-monitor-manager-private.h +@@ -153,9 +153,8 @@ struct _MetaMonitorManager + GList *logical_monitors; + MetaLogicalMonitor *primary_logical_monitor; + +- int dbus_name_id; +- +- int persistent_timeout_id; ++ guint dbus_name_id; ++ guint persistent_timeout_id; + + guint panel_orientation_managed : 1; + +-- +GitLab + + +From f8dc4809322da31a68643fdf698d877703589e23 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Mon, 6 Mar 2023 23:49:39 +0100 +Subject: [PATCH 3/4] monitor-manager: Use g_clear_handle() to clean up D-Bus + name owning + +--- + src/backends/meta-monitor-manager.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c +index 19cbb263d2..d3a794ea6c 100644 +--- a/src/backends/meta-monitor-manager.c ++++ b/src/backends/meta-monitor-manager.c +@@ -1357,11 +1357,7 @@ meta_monitor_manager_dispose (GObject *object) + { + MetaMonitorManager *manager = META_MONITOR_MANAGER (object); + +- if (manager->dbus_name_id != 0) +- { +- g_bus_unown_name (manager->dbus_name_id); +- manager->dbus_name_id = 0; +- } ++ g_clear_handle_id (&manager->dbus_name_id, g_bus_unown_name); + + g_clear_object (&manager->display_config); + g_clear_object (&manager->config_manager); +-- +GitLab + + +From 45ba864f2d5489225a6a1b5e915061c2aad289ab Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Tue, 7 Mar 2023 00:06:30 +0100 +Subject: [PATCH 4/4] monitor-manager: Restore old config in idle callback when + unconfirmed + +We might get told to restore the old monitor configuration by the +monitor configuration prompt, in case the user pressed "revert" or +equivalent. This might be in response to a button press, and those +happen during frame clock dispatch. If we would restore an old +configuration during dispatch, it means we would reconfigure the +monitors including their stage views while dispatching, which means we'd +destroy the frame clock while it's dispatching. + +Doing that causes problems, as the frame clock isn't expecting to be +destroyed mid-function. Specifically, + +We'd enter + + clutter_frame_clock_dispatch (clutter-frame-clock.c:811) + frame_clock_source_dispatch (clutter-frame-clock.c:839) + g_main_dispatch (gmain.c:3454) + g_main_context_dispatch (gmain.c:4172) + g_main_context_iterate.constprop.0 (gmain.c:4248) + g_main_loop_run (gmain.c:4448) + meta_context_run_main_loop (meta-context.c:482) + main (main.c:663) + +which would first call + + _clutter_process_event (clutter-main.c:920) + _clutter_stage_process_queued_events (clutter-stage.c:757) + handle_frame_clock_before_frame (clutter-stage-view.c:1150) + +which would emit e.g. a button event all the way to a button press +handler, which would e.g. deny the new configuration: + + restore_previous_config (meta-monitor-manager.c:1931) + confirm_configuration (meta-monitor-manager.c:2866) + meta_monitor_manager_confirm_configuration (meta-monitor-manager.c:2880) + meta_plugin_complete_display_change (meta-plugin.c:172) + +That would then regenerate the monitor configuration and stage view +layout, which would destroy the old stage view and frame clock. + + meta_stage_native_rebuild_views (meta-stage-native.c:68) + meta_backend_native_update_screen_size (meta-backend-native.c:457) + meta_backend_sync_screen_size (meta-backend.c:266) + meta_backend_monitors_changed (meta-backend.c:337) + meta_monitor_manager_notify_monitors_changed (meta-monitor-manager.c:3595) + meta_monitor_manager_rebuild (meta-monitor-manager.c:3683) + meta_monitor_manager_native_apply_monitors_config (meta-monitor-manager-native.c:343) + meta_monitor_manager_apply_monitors_config (meta-monitor-manager.c:704) + +After returning back to the original clutter_frame_clock_dispatch() +frame, various state in the frame clock will be gone and we'd crash. +--- + src/backends/meta-monitor-manager-private.h | 1 + + src/backends/meta-monitor-manager.c | 42 +++++++++------------ + 2 files changed, 19 insertions(+), 24 deletions(-) + +diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h +index 56431ba600..f9cd9ae312 100644 +--- a/src/backends/meta-monitor-manager-private.h ++++ b/src/backends/meta-monitor-manager-private.h +@@ -154,6 +154,7 @@ struct _MetaMonitorManager + MetaLogicalMonitor *primary_logical_monitor; + + guint dbus_name_id; ++ guint restore_config_id; + guint persistent_timeout_id; + + guint panel_orientation_managed : 1; +diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c +index d3a794ea6c..e6df876307 100644 +--- a/src/backends/meta-monitor-manager.c ++++ b/src/backends/meta-monitor-manager.c +@@ -1363,6 +1363,7 @@ meta_monitor_manager_dispose (GObject *object) + g_clear_object (&manager->config_manager); + + g_clear_handle_id (&manager->persistent_timeout_id, g_source_remove); ++ g_clear_handle_id (&manager->restore_config_id, g_source_remove); + + G_OBJECT_CLASS (meta_monitor_manager_parent_class)->dispose (object); + } +@@ -1961,12 +1962,6 @@ save_config_timeout (gpointer user_data) + return G_SOURCE_REMOVE; + } + +-static void +-cancel_persistent_confirmation (MetaMonitorManager *manager) +-{ +- g_clear_handle_id (&manager->persistent_timeout_id, g_source_remove); +-} +- + static void + request_persistent_confirmation (MetaMonitorManager *manager) + { +@@ -2822,9 +2817,11 @@ meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skelet + return TRUE; + } + +- if (manager->persistent_timeout_id && +- method != META_MONITORS_CONFIG_METHOD_VERIFY) +- cancel_persistent_confirmation (manager); ++ if (method != META_MONITORS_CONFIG_METHOD_VERIFY) ++ { ++ g_clear_handle_id (&manager->restore_config_id, g_source_remove); ++ g_clear_handle_id (&manager->persistent_timeout_id, g_source_remove); ++ } + + if (!meta_monitor_manager_apply_monitors_config (manager, + config, +@@ -2852,28 +2849,25 @@ meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skelet + #undef MONITOR_CONFIGS_FORMAT + #undef LOGICAL_MONITOR_CONFIG_FORMAT + +-static void +-confirm_configuration (MetaMonitorManager *manager, +- gboolean confirmed) +-{ +- if (confirmed) +- meta_monitor_config_manager_save_current (manager->config_manager); +- else +- restore_previous_config (manager); +-} +- + void + meta_monitor_manager_confirm_configuration (MetaMonitorManager *manager, + gboolean ok) + { + if (!manager->persistent_timeout_id) ++ return; ++ ++ g_clear_handle_id (&manager->restore_config_id, g_source_remove); ++ g_clear_handle_id (&manager->persistent_timeout_id, g_source_remove); ++ ++ if (ok) + { +- /* too late */ +- return; ++ meta_monitor_config_manager_save_current (manager->config_manager); ++ } ++ else ++ { ++ manager->restore_config_id = ++ g_idle_add_once ((GSourceOnceFunc) restore_previous_config, manager); + } +- +- cancel_persistent_confirmation (manager); +- confirm_configuration (manager, ok); + } + + static gboolean +-- +GitLab + diff --git a/2912-rebased.patch b/2912-rebased.patch new file mode 100644 index 0000000..8945439 --- /dev/null +++ b/2912-rebased.patch @@ -0,0 +1,277 @@ +From 670c7cf4ccb1bd1ffa6e44507a8ffd734b0f72e4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Tue, 14 Mar 2023 17:28:24 +0100 +Subject: [PATCH] monitor-manager: Apply switch-config in idle callback + +Just as with restoring the previous monitor configuration in case the +user clicked "revert" in GNOME Shell's monitor configuration +confirmation dialog, we need to do switch configs in an idle callback as +well. + +Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2694 +--- + src/backends/meta-monitor-manager.c | 61 +++++++++++--- + src/tests/native-kms-hotplug.c | 119 ++++++++++++++++++++++++++++ + 2 files changed, 167 insertions(+), 13 deletions(-) + +diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c +index 19cbb263d2..9b24294e89 100644 +--- a/src/backends/meta-monitor-manager.c ++++ b/src/backends/meta-monitor-manager.c +@@ -116,6 +116,8 @@ typedef struct _MetaMonitorManagerPrivate + gboolean has_builtin_panel; + gboolean night_light_supported; + const char *experimental_hdr; ++ ++ guint switch_config_handle_id; + } MetaMonitorManagerPrivate; + + G_DEFINE_TYPE_WITH_PRIVATE (MetaMonitorManager, meta_monitor_manager, +@@ -1356,6 +1358,8 @@ static void + meta_monitor_manager_dispose (GObject *object) + { + MetaMonitorManager *manager = META_MONITOR_MANAGER (object); ++ MetaMonitorManagerPrivate *priv = ++ meta_monitor_manager_get_instance_private (manager); + + g_clear_handle_id (&manager->dbus_name_id, g_bus_unown_name); + +@@ -1367,6 +1371,7 @@ meta_monitor_manager_dispose (GObject *object) + + g_clear_handle_id (&manager->persistent_timeout_id, g_source_remove); + g_clear_handle_id (&manager->restore_config_id, g_source_remove); ++ g_clear_handle_id (&priv->switch_config_handle_id, g_source_remove); + + G_OBJECT_CLASS (meta_monitor_manager_parent_class)->dispose (object); + } +@@ -3873,35 +3878,65 @@ meta_monitor_manager_rotate_monitor (MetaMonitorManager *manager) + g_object_unref (config); + } + +-void +-meta_monitor_manager_switch_config (MetaMonitorManager *manager, +- MetaMonitorSwitchConfigType config_type) ++typedef struct + { +- GError *error = NULL; +- MetaMonitorsConfig *config; ++ MetaMonitorManager *monitor_manager; ++ MetaMonitorSwitchConfigType config_type; ++} SwitchConfigData; + +- g_return_if_fail (config_type != META_MONITOR_SWITCH_CONFIG_UNKNOWN); ++static gboolean ++switch_config_idle_cb (gpointer user_data) ++{ ++ SwitchConfigData *data = user_data; ++ MetaMonitorManager *monitor_manager = data->monitor_manager; ++ MetaMonitorManagerPrivate *priv = ++ meta_monitor_manager_get_instance_private (monitor_manager); ++ MetaMonitorConfigManager *config_manager = monitor_manager->config_manager; ++ MetaMonitorsConfig *config; ++ g_autoptr (GError) error = NULL; + + config = +- meta_monitor_config_manager_create_for_switch_config (manager->config_manager, +- config_type); ++ meta_monitor_config_manager_create_for_switch_config (config_manager, ++ data->config_type); + if (!config) +- return; ++ return G_SOURCE_REMOVE; + +- if (!meta_monitor_manager_apply_monitors_config (manager, ++ if (!meta_monitor_manager_apply_monitors_config (monitor_manager, + config, + META_MONITORS_CONFIG_METHOD_TEMPORARY, + &error)) + { + g_warning ("Failed to use switch monitor configuration: %s", + error->message); +- g_error_free (error); + } + else + { +- manager->current_switch_config = config_type; ++ monitor_manager->current_switch_config = data->config_type; + } +- g_object_unref (config); ++ ++ priv->switch_config_handle_id = 0; ++ return G_SOURCE_REMOVE; ++} ++ ++void ++meta_monitor_manager_switch_config (MetaMonitorManager *manager, ++ MetaMonitorSwitchConfigType config_type) ++{ ++ MetaMonitorManagerPrivate *priv = ++ meta_monitor_manager_get_instance_private (manager); ++ SwitchConfigData *data; ++ ++ g_return_if_fail (config_type != META_MONITOR_SWITCH_CONFIG_UNKNOWN); ++ ++ data = g_new0 (SwitchConfigData, 1); ++ data->monitor_manager = manager; ++ data->config_type = config_type; ++ ++ g_clear_handle_id (&priv->switch_config_handle_id, g_source_remove); ++ priv->switch_config_handle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, ++ switch_config_idle_cb, ++ data, ++ g_free); + } + + gboolean +diff --git a/src/tests/native-kms-hotplug.c b/src/tests/native-kms-hotplug.c +index 4a6f2e0aac..3c60aa10a5 100644 +--- a/src/tests/native-kms-hotplug.c ++++ b/src/tests/native-kms-hotplug.c +@@ -17,11 +17,16 @@ + + #include "config.h" + ++#include ++ ++#include "backends/meta-logical-monitor.h" + #include "backends/meta-monitor-manager-private.h" ++#include "backends/meta-virtual-monitor.h" + #include "backends/native/meta-backend-native.h" + #include "backends/native/meta-udev.h" + #include "meta-test/meta-context-test.h" + #include "tests/drm-mock/drm-mock.h" ++#include "tests/meta-test-utils.h" + + typedef enum _State + { +@@ -207,6 +212,118 @@ meta_test_disconnect_connect (void) + g_signal_handler_disconnect (stage, presented_handler_id); + } + ++static gboolean ++on_key_release (ClutterActor *actor, ++ const ClutterEvent *event, ++ MetaMonitorManager *monitor_manager) ++{ ++ if (clutter_event_get_key_symbol (event) == CLUTTER_KEY_a) ++ { ++ g_debug ("Switching config"); ++ meta_monitor_manager_switch_config (monitor_manager, ++ META_MONITOR_SWITCH_CONFIG_ALL_MIRROR); ++ } ++ ++ return TRUE; ++} ++ ++static void ++on_monitors_changed (MetaMonitorManager *monitor_manager, ++ gboolean *monitors_changed) ++{ ++ *monitors_changed = TRUE; ++} ++ ++static void ++meta_test_switch_config (void) ++{ ++ MetaBackend *backend = meta_context_get_backend (test_context); ++ MetaMonitorManager *monitor_manager = ++ meta_backend_get_monitor_manager (backend); ++ ClutterActor *stage = meta_backend_get_stage (backend); ++ ClutterSeat *seat = meta_backend_get_default_seat (backend); ++ g_autoptr (ClutterVirtualInputDevice) virtual_keyboard = NULL; ++ g_autoptr (MetaVirtualMonitor) virtual_monitor = NULL; ++ GList *logical_monitors; ++ MetaRectangle logical_monitor_layout; ++ gulong after_paint_handler_id; ++ gulong presented_handler_id; ++ gboolean monitors_changed; ++ g_autoptr (GError) error = NULL; ++ ClutterActor *actor; ++ State state; ++ ++ after_paint_handler_id = g_signal_connect (stage, "after-paint", ++ G_CALLBACK (on_after_paint), ++ &state); ++ presented_handler_id = g_signal_connect (stage, "presented", ++ G_CALLBACK (on_presented), ++ &state); ++ g_signal_connect (monitor_manager, "monitors-changed", ++ G_CALLBACK (on_monitors_changed), ++ &monitors_changed); ++ ++ logical_monitors = ++ meta_monitor_manager_get_logical_monitors (monitor_manager); ++ g_assert_cmpuint (g_list_length (logical_monitors), ==, 1); ++ logical_monitor_layout = ++ meta_logical_monitor_get_layout (logical_monitors->data); ++ ++ virtual_monitor = meta_create_test_monitor (test_context, ++ logical_monitor_layout.width, ++ logical_monitor_layout.height, ++ 60.0); ++ ++ actor = clutter_actor_new (); ++ g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); ++ clutter_actor_insert_child_above (stage, ++ actor, ++ clutter_actor_get_first_child (stage)); ++ clutter_actor_set_size (actor, ++ logical_monitor_layout.width, ++ logical_monitor_layout.height); ++ clutter_actor_set_position (actor, 0, 0); ++ clutter_actor_set_reactive (actor, TRUE); ++ clutter_actor_show (actor); ++ clutter_actor_grab_key_focus (actor); ++ g_signal_connect (actor, "key-press-event", ++ G_CALLBACK (on_key_release), ++ monitor_manager); ++ ++ monitors_changed = FALSE; ++ g_signal_connect (monitor_manager, "monitors-changed", ++ G_CALLBACK (on_monitors_changed), ++ &monitors_changed); ++ ++ g_debug ("Sending virtual keyboard event"); ++ virtual_keyboard = ++ clutter_seat_create_virtual_device (seat, CLUTTER_KEYBOARD_DEVICE); ++ clutter_virtual_input_device_notify_key (virtual_keyboard, ++ CLUTTER_CURRENT_TIME, ++ KEY_A, ++ CLUTTER_KEY_STATE_PRESSED); ++ clutter_virtual_input_device_notify_key (virtual_keyboard, ++ CLUTTER_CURRENT_TIME, ++ KEY_A, ++ CLUTTER_KEY_STATE_RELEASED); ++ ++ g_debug ("Waiting for monitors changed"); ++ while (!monitors_changed) ++ g_main_context_iteration (NULL, TRUE); ++ ++ g_debug ("Waiting for being repainted"); ++ state = INIT; ++ clutter_actor_queue_redraw (stage); ++ while (state != PRESENTED) ++ g_main_context_iteration (NULL, TRUE); ++ ++ clutter_actor_destroy (actor); ++ g_assert_null (actor); ++ ++ g_signal_handler_disconnect (stage, after_paint_handler_id); ++ g_signal_handler_disconnect (stage, presented_handler_id); ++} ++ + static void + init_tests (void) + { +@@ -214,6 +331,8 @@ init_tests (void) + meta_test_reload); + g_test_add_func ("/hotplug/disconnect-connect", + meta_test_disconnect_connect); ++ g_test_add_func ("/hotplug/switch-config", ++ meta_test_switch_config); + } + + int +-- +GitLab + diff --git a/mutter.spec b/mutter.spec index 1f153f3..1a69a8c 100644 --- a/mutter.spec +++ b/mutter.spec @@ -13,7 +13,7 @@ Name: mutter Version: 44~rc -Release: 4%{?dist} +Release: 5%{?dist} Summary: Window and compositing manager based on Clutter License: GPLv2+ @@ -36,6 +36,18 @@ Patch3: 0001-place-Always-center-initial-setup-fedora-welcome.patch # https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2906 Patch4: 2906.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=2175809 +# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2901 +# Fix a crash when reverting Display settings +Patch5: 2901.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=2177982 +# https://gitlab.gnome.org/GNOME/mutter/-/issues/2694 +# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2912 +# Fix a crash when using win+P to change display configuration +# Rebased on 2901.patch +Patch6: 2912-rebased.patch + BuildRequires: pkgconfig(gobject-introspection-1.0) >= 1.41.0 BuildRequires: pkgconfig(sm) BuildRequires: pkgconfig(libwacom) @@ -179,6 +191,10 @@ the functionality of the installed %{name} package. %{_datadir}/mutter-%{mutter_api_version}/tests %changelog +* Thu Mar 16 2023 Adam Williamson - 44~rc-5 +- Backport MR #2901 to fix crash when reverting Display settings +- Backport MR #2912 to fix crash when using win+P shortcut + * Fri Mar 10 2023 Florian Müllner - 44~rc-4 - Fix typo in centering patch - Also check for possible future fedora-welcome ID