wayland/window: Update toplevel main monitor before non-toplevel

When updating the main monitor, make sure to update the toplevel main
monitor before trying to use that as the main monitor for non-toplevel
windows (such as popups). Without this, when the main monitor is
updated as a side effect to monitors being changed (for example due to
a hot plug event, or coming back from being suspended) the
main monitor pointer may, after 'monitors-changed' has completed, point to
freed memory resulting in undefined behaviour.

https://bugzilla.gnome.org/show_bug.cgi?id=784867
This commit is contained in:
Jonas Ådahl 2017-07-13 12:38:02 +08:00
parent cdb5ead795
commit 5d7b94abb8
4 changed files with 8 additions and 4 deletions

View File

@ -530,7 +530,8 @@ struct _MetaWindowClass
cairo_surface_t **icon, cairo_surface_t **icon,
cairo_surface_t **mini_icon); cairo_surface_t **mini_icon);
uint32_t (*get_client_pid) (MetaWindow *window); uint32_t (*get_client_pid) (MetaWindow *window);
void (*update_main_monitor) (MetaWindow *window); void (*update_main_monitor) (MetaWindow *window,
gboolean user_op);
void (*main_monitor_changed) (MetaWindow *window, void (*main_monitor_changed) (MetaWindow *window,
const MetaLogicalMonitor *old); const MetaLogicalMonitor *old);
}; };

View File

@ -3592,7 +3592,7 @@ meta_window_update_monitor (MetaWindow *window,
const MetaLogicalMonitor *old; const MetaLogicalMonitor *old;
old = window->monitor; old = window->monitor;
META_WINDOW_GET_CLASS (window)->update_main_monitor (window); META_WINDOW_GET_CLASS (window)->update_main_monitor (window, user_op);
if (old != window->monitor) if (old != window->monitor)
{ {
meta_window_on_all_workspaces_changed (window); meta_window_on_all_workspaces_changed (window);

View File

@ -334,7 +334,8 @@ scale_rect_size (MetaRectangle *rect,
} }
static void static void
meta_window_wayland_update_main_monitor (MetaWindow *window) meta_window_wayland_update_main_monitor (MetaWindow *window,
gboolean user_op)
{ {
MetaBackend *backend = meta_get_backend (); MetaBackend *backend = meta_get_backend ();
MetaMonitorManager *monitor_manager = MetaMonitorManager *monitor_manager =
@ -353,6 +354,7 @@ meta_window_wayland_update_main_monitor (MetaWindow *window)
toplevel_window = meta_wayland_surface_get_toplevel_window (window->surface); toplevel_window = meta_wayland_surface_get_toplevel_window (window->surface);
if (toplevel_window != window) if (toplevel_window != window)
{ {
meta_window_update_monitor (toplevel_window, user_op);
window->monitor = toplevel_window->monitor; window->monitor = toplevel_window->monitor;
return; return;
} }

View File

@ -1456,7 +1456,8 @@ meta_window_x11_update_icon (MetaWindow *window,
} }
static void static void
meta_window_x11_update_main_monitor (MetaWindow *window) meta_window_x11_update_main_monitor (MetaWindow *window,
gboolean user_op)
{ {
window->monitor = meta_window_calculate_main_logical_monitor (window); window->monitor = meta_window_calculate_main_logical_monitor (window);
} }