|
|
776610 |
From 83b7b17b64b3e42a87f524ac3504be81789ec0fc Mon Sep 17 00:00:00 2001
|
|
|
776610 |
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
|
776610 |
Date: Fri, 24 Aug 2018 12:56:31 +0200
|
|
|
776610 |
Subject: [PATCH 2/2] window: Force update monitor on hot plugs
|
|
|
776610 |
|
|
|
776610 |
Commit a3da4b8d5bd217c0262fd9361036877d155a300f changed updating of
|
|
|
776610 |
window monitors to always use take affect when it was done from a
|
|
|
776610 |
non-user operation. This could cause feed back loops when a non-user
|
|
|
776610 |
driven operation would trigger the changing of a monitor, which itself
|
|
|
776610 |
would trigger changing of the monitor again due to a window scale
|
|
|
776610 |
change.
|
|
|
776610 |
|
|
|
776610 |
The reason for the change, was that when the window monitor changed due
|
|
|
776610 |
to a hot plug, if it didn't actually change, eventually the window
|
|
|
776610 |
monitor pointer would be pointing to freed memory.
|
|
|
776610 |
|
|
|
776610 |
Instead of force updating the monitor on all non-user operations, just
|
|
|
776610 |
do it on hot plugs. This allows for the feedback loop preventing logic
|
|
|
776610 |
to still do what its supposed to do, without risking dangling pointers
|
|
|
776610 |
on hot plugs.
|
|
|
776610 |
|
|
|
776610 |
Related: https://gitlab.gnome.org/GNOME/mutter/issues/189
|
|
|
776610 |
Closes: https://gitlab.gnome.org/GNOME/mutter/issues/192
|
|
|
776610 |
|
|
|
776610 |
(cherry picked from commit 8d3e053059cd202e740076caedfc8e3ac149066a)
|
|
|
776610 |
---
|
|
|
776610 |
src/core/window-private.h | 1 +
|
|
|
776610 |
src/core/window.c | 4 ++--
|
|
|
776610 |
2 files changed, 3 insertions(+), 2 deletions(-)
|
|
|
776610 |
|
|
|
776610 |
diff --git a/src/core/window-private.h b/src/core/window-private.h
|
|
|
776610 |
index bed2fc7f6..8552829b2 100644
|
|
|
776610 |
--- a/src/core/window-private.h
|
|
|
776610 |
+++ b/src/core/window-private.h
|
|
|
776610 |
@@ -98,60 +98,61 @@ typedef enum
|
|
|
776610 |
META_PLACEMENT_GRAVITY_TOP = 1 << 0,
|
|
|
776610 |
META_PLACEMENT_GRAVITY_BOTTOM = 1 << 1,
|
|
|
776610 |
META_PLACEMENT_GRAVITY_LEFT = 1 << 2,
|
|
|
776610 |
META_PLACEMENT_GRAVITY_RIGHT = 1 << 3,
|
|
|
776610 |
} MetaPlacementGravity;
|
|
|
776610 |
|
|
|
776610 |
typedef enum
|
|
|
776610 |
{
|
|
|
776610 |
META_PLACEMENT_ANCHOR_NONE = 0,
|
|
|
776610 |
META_PLACEMENT_ANCHOR_TOP = 1 << 0,
|
|
|
776610 |
META_PLACEMENT_ANCHOR_BOTTOM = 1 << 1,
|
|
|
776610 |
META_PLACEMENT_ANCHOR_LEFT = 1 << 2,
|
|
|
776610 |
META_PLACEMENT_ANCHOR_RIGHT = 1 << 3,
|
|
|
776610 |
} MetaPlacementAnchor;
|
|
|
776610 |
|
|
|
776610 |
typedef enum
|
|
|
776610 |
{
|
|
|
776610 |
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_NONE = 0,
|
|
|
776610 |
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_X = 1 << 0,
|
|
|
776610 |
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_Y = 1 << 1,
|
|
|
776610 |
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X = 1 << 2,
|
|
|
776610 |
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y = 1 << 3,
|
|
|
776610 |
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_RESIZE_X = 1 << 4,
|
|
|
776610 |
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_RESIZE_Y = 1 << 5,
|
|
|
776610 |
} MetaPlacementConstraintAdjustment;
|
|
|
776610 |
|
|
|
776610 |
typedef enum _MetaWindowUpdateMonitorFlags
|
|
|
776610 |
{
|
|
|
776610 |
META_WINDOW_UPDATE_MONITOR_FLAGS_NONE = 0,
|
|
|
776610 |
META_WINDOW_UPDATE_MONITOR_FLAGS_USER_OP = 1 << 0,
|
|
|
776610 |
+ META_WINDOW_UPDATE_MONITOR_FLAGS_FORCE = 1 << 1,
|
|
|
776610 |
} MetaWindowUpdateMonitorFlags;
|
|
|
776610 |
|
|
|
776610 |
typedef struct _MetaPlacementRule
|
|
|
776610 |
{
|
|
|
776610 |
MetaRectangle anchor_rect;
|
|
|
776610 |
MetaPlacementGravity gravity;
|
|
|
776610 |
MetaPlacementAnchor anchor;
|
|
|
776610 |
MetaPlacementConstraintAdjustment constraint_adjustment;
|
|
|
776610 |
int offset_x;
|
|
|
776610 |
int offset_y;
|
|
|
776610 |
int width;
|
|
|
776610 |
int height;
|
|
|
776610 |
} MetaPlacementRule;
|
|
|
776610 |
|
|
|
776610 |
typedef enum
|
|
|
776610 |
{
|
|
|
776610 |
META_EDGE_CONSTRAINT_NONE = 0,
|
|
|
776610 |
META_EDGE_CONSTRAINT_WINDOW = 1,
|
|
|
776610 |
META_EDGE_CONSTRAINT_MONITOR = 2,
|
|
|
776610 |
} MetaEdgeConstraint;
|
|
|
776610 |
|
|
|
776610 |
struct _MetaWindow
|
|
|
776610 |
{
|
|
|
776610 |
GObject parent_instance;
|
|
|
776610 |
|
|
|
776610 |
MetaDisplay *display;
|
|
|
776610 |
MetaScreen *screen;
|
|
|
776610 |
guint64 stamp;
|
|
|
776610 |
MetaLogicalMonitor *monitor;
|
|
|
776610 |
MetaWorkspace *workspace;
|
|
|
776610 |
diff --git a/src/core/window.c b/src/core/window.c
|
|
|
776610 |
index ad4059704..07f826bb5 100644
|
|
|
776610 |
--- a/src/core/window.c
|
|
|
776610 |
+++ b/src/core/window.c
|
|
|
776610 |
@@ -3776,97 +3776,97 @@ find_monitor_by_winsys_id (MetaWindow *window,
|
|
|
776610 |
logical_monitors =
|
|
|
776610 |
meta_monitor_manager_get_logical_monitors (monitor_manager);
|
|
|
776610 |
|
|
|
776610 |
for (l = logical_monitors; l; l = l->next)
|
|
|
776610 |
{
|
|
|
776610 |
MetaLogicalMonitor *logical_monitor = l->data;
|
|
|
776610 |
|
|
|
776610 |
if (logical_monitor->winsys_id == winsys_id)
|
|
|
776610 |
return logical_monitor;
|
|
|
776610 |
}
|
|
|
776610 |
|
|
|
776610 |
return NULL;
|
|
|
776610 |
}
|
|
|
776610 |
|
|
|
776610 |
/* This is called when the monitor setup has changed. The window->monitor
|
|
|
776610 |
* reference is still "valid", but refer to the previous monitor setup */
|
|
|
776610 |
void
|
|
|
776610 |
meta_window_update_for_monitors_changed (MetaWindow *window)
|
|
|
776610 |
{
|
|
|
776610 |
MetaBackend *backend = meta_get_backend ();
|
|
|
776610 |
MetaMonitorManager *monitor_manager =
|
|
|
776610 |
meta_backend_get_monitor_manager (backend);
|
|
|
776610 |
const MetaLogicalMonitor *old, *new;
|
|
|
776610 |
|
|
|
776610 |
if (meta_window_has_fullscreen_monitors (window))
|
|
|
776610 |
meta_window_clear_fullscreen_monitors (window);
|
|
|
776610 |
|
|
|
776610 |
if (window->override_redirect || window->type == META_WINDOW_DESKTOP)
|
|
|
776610 |
{
|
|
|
776610 |
meta_window_update_monitor (window,
|
|
|
776610 |
- META_WINDOW_UPDATE_MONITOR_FLAGS_NONE);
|
|
|
776610 |
+ META_WINDOW_UPDATE_MONITOR_FLAGS_FORCE);
|
|
|
776610 |
return;
|
|
|
776610 |
}
|
|
|
776610 |
|
|
|
776610 |
old = window->monitor;
|
|
|
776610 |
|
|
|
776610 |
/* Try the preferred output first */
|
|
|
776610 |
new = find_monitor_by_winsys_id (window, window->preferred_output_winsys_id);
|
|
|
776610 |
|
|
|
776610 |
/* Otherwise, try to find the old output on a new monitor */
|
|
|
776610 |
if (old && !new)
|
|
|
776610 |
new = find_monitor_by_winsys_id (window, old->winsys_id);
|
|
|
776610 |
|
|
|
776610 |
/* Fall back to primary if everything else failed */
|
|
|
776610 |
if (!new)
|
|
|
776610 |
new = meta_monitor_manager_get_primary_logical_monitor (monitor_manager);
|
|
|
776610 |
|
|
|
776610 |
if (new && old)
|
|
|
776610 |
{
|
|
|
776610 |
if (window->tile_mode != META_TILE_NONE)
|
|
|
776610 |
window->tile_monitor_number = new->number;
|
|
|
776610 |
|
|
|
776610 |
/* This will eventually reach meta_window_update_monitor that
|
|
|
776610 |
* will send leave/enter-monitor events. The old != new monitor
|
|
|
776610 |
* check will always fail (due to the new logical_monitors set) so
|
|
|
776610 |
* we will always send the events, even if the new and old monitor
|
|
|
776610 |
* index is the same. That is right, since the enumeration of the
|
|
|
776610 |
* monitors changed and the same index could be refereing
|
|
|
776610 |
* to a different monitor. */
|
|
|
776610 |
meta_window_move_between_rects (window,
|
|
|
776610 |
&old->rect,
|
|
|
776610 |
&new->rect);
|
|
|
776610 |
}
|
|
|
776610 |
else
|
|
|
776610 |
{
|
|
|
776610 |
meta_window_update_monitor (window,
|
|
|
776610 |
- META_WINDOW_UPDATE_MONITOR_FLAGS_NONE);
|
|
|
776610 |
+ META_WINDOW_UPDATE_MONITOR_FLAGS_FORCE);
|
|
|
776610 |
}
|
|
|
776610 |
}
|
|
|
776610 |
|
|
|
776610 |
void
|
|
|
776610 |
meta_window_update_monitor (MetaWindow *window,
|
|
|
776610 |
MetaWindowUpdateMonitorFlags flags)
|
|
|
776610 |
{
|
|
|
776610 |
const MetaLogicalMonitor *old;
|
|
|
776610 |
|
|
|
776610 |
old = window->monitor;
|
|
|
776610 |
META_WINDOW_GET_CLASS (window)->update_main_monitor (window, flags);
|
|
|
776610 |
if (old != window->monitor)
|
|
|
776610 |
{
|
|
|
776610 |
meta_window_on_all_workspaces_changed (window);
|
|
|
776610 |
|
|
|
776610 |
/* If workspaces only on primary and we moved back to primary due to a user action,
|
|
|
776610 |
* ensure that the window is now in that workspace. We do this because while
|
|
|
776610 |
* the window is on a non-primary monitor it is always visible, so it would be
|
|
|
776610 |
* very jarring if it disappeared when it crossed the monitor border.
|
|
|
776610 |
* The one time we want it to both change to the primary monitor and a non-active
|
|
|
776610 |
* workspace is when dropping the window on some other workspace thumbnail directly.
|
|
|
776610 |
* That should be handled by explicitly moving the window before changing the
|
|
|
776610 |
* workspace.
|
|
|
776610 |
*/
|
|
|
776610 |
if (meta_prefs_get_workspaces_only_on_primary () &&
|
|
|
776610 |
flags & META_WINDOW_UPDATE_MONITOR_FLAGS_USER_OP &&
|
|
|
776610 |
meta_window_is_on_primary_monitor (window) &&
|
|
|
776610 |
window->screen->active_workspace != window->workspace)
|
|
|
776610 |
meta_window_change_workspace (window, window->screen->active_workspace);
|
|
|
776610 |
|
|
|
776610 |
--
|
|
|
776610 |
2.18.1
|
|
|
776610 |
|