From 0826616da1dacf29e3e08dae6d2ffe4116e5bdff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Thu, 16 Jul 2015 15:07:38 +0200 Subject: [PATCH 1/2] barrier: Guard against X errors --- src/backends/x11/meta-barrier-x11.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/backends/x11/meta-barrier-x11.c b/src/backends/x11/meta-barrier-x11.c index 054e5cdc6..1fc3fd8cc 100644 --- a/src/backends/x11/meta-barrier-x11.c +++ b/src/backends/x11/meta-barrier-x11.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "backends/x11/meta-barrier-x11.h" #include "display-private.h" @@ -107,6 +108,7 @@ meta_barrier_impl_x11_new (MetaBarrier *barrier) MetaDisplay *display = barrier->priv->display; Display *dpy; Window root; + PointerBarrier xbarrier; unsigned int allowed_motion_dirs; if (display == NULL) @@ -119,18 +121,24 @@ meta_barrier_impl_x11_new (MetaBarrier *barrier) priv = meta_barrier_impl_x11_get_instance_private (self); priv->barrier = barrier; + meta_error_trap_push (display); dpy = display->xdisplay; root = DefaultRootWindow (dpy); allowed_motion_dirs = meta_border_get_allows_directions (&barrier->priv->border); - priv->xbarrier = XFixesCreatePointerBarrier (dpy, root, - barrier->priv->border.line.a.x, - barrier->priv->border.line.a.y, - barrier->priv->border.line.b.x, - barrier->priv->border.line.b.y, - allowed_motion_dirs, - 0, NULL); + xbarrier = XFixesCreatePointerBarrier (dpy, root, + barrier->priv->border.line.a.x, + barrier->priv->border.line.a.y, + barrier->priv->border.line.b.x, + barrier->priv->border.line.b.y, + allowed_motion_dirs, + 0, NULL); + + if (meta_error_trap_pop_with_return (display) != Success) + return NULL; + + priv->xbarrier = xbarrier; g_hash_table_insert (display->xids, &priv->xbarrier, barrier); -- 2.12.0 From 2da829399dc79b5c51ca55ab6e633c4a4769c15a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Thu, 16 Jul 2015 15:12:55 +0200 Subject: [PATCH 2/2] Do not crash when starting up with no monitor connected Some parts of Mutter currently assume there's always a monitor connected to the screen. This assumption can be incorrect - e.g. a desktop computer can be powered on and a monitor only plugged in after the desktop session - or the GDM login - has already been reached. Fix the various places that assume so, making the code robust to the above use case. Based on an initial patch by Cosimo Cecchi. --- src/backends/x11/meta-monitor-manager-xrandr.c | 4 +- src/compositor/meta-window-actor.c | 2 +- src/core/constraints.c | 71 +++++++++++++++----------- src/core/place.c | 4 ++ src/core/screen.c | 10 +++- src/core/window.c | 57 ++++++++++++++------- src/core/workspace.c | 3 ++ src/x11/window-x11.c | 3 +- 8 files changed, 100 insertions(+), 54 deletions(-) diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c index b0a77dadb..b82120af9 100644 --- a/src/backends/x11/meta-monitor-manager-xrandr.c +++ b/src/backends/x11/meta-monitor-manager-xrandr.c @@ -1141,7 +1141,9 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager, crtc->current_mode = NULL; } - g_assert (width > 0 && height > 0); + if (width == 0 || height == 0) + return; + /* The 'physical size' of an X screen is meaningless if that screen * can consist of many monitors. So just pick a size that make the * dpi 96. diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index 9395caac5..fb29ca1c9 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -959,7 +959,7 @@ queue_send_frame_messages_timeout (MetaWindowActor *self) outputs = meta_monitor_manager_get_outputs (monitor_manager, &n_outputs); for (i = 0; i < n_outputs; i++) { - if (outputs[i].winsys_id == window->monitor->winsys_id && outputs[i].crtc) + if (window->monitor && outputs[i].winsys_id == window->monitor->winsys_id && outputs[i].crtc) { refresh_rate = outputs[i].crtc->current_mode->refresh_rate; break; diff --git a/src/core/constraints.c b/src/core/constraints.c index 67b52c994..3d1701e88 100644 --- a/src/core/constraints.c +++ b/src/core/constraints.c @@ -29,6 +29,7 @@ #include #include +#include #include #if 0 @@ -337,6 +338,8 @@ setup_constraint_info (ConstraintInfo *info, const MetaMonitorInfo *monitor_info; MetaWorkspace *cur_workspace; + memset (info, 0, sizeof (ConstraintInfo)); + info->orig = *orig; info->current = *new; @@ -382,40 +385,43 @@ setup_constraint_info (ConstraintInfo *info, if (!info->is_user_action) info->fixed_directions = FIXED_DIRECTION_NONE; + cur_workspace = window->screen->active_workspace; monitor_info = meta_screen_get_monitor_for_rect (window->screen, &info->current); - meta_window_get_work_area_for_monitor (window, - monitor_info->number, - &info->work_area_monitor); - if (!window->fullscreen || window->fullscreen_monitors[0] == -1) + if (monitor_info) { - info->entire_monitor = monitor_info->rect; - } - else - { - int i = 0; - long monitor; + meta_window_get_work_area_for_monitor (window, + monitor_info->number, + &info->work_area_monitor); - monitor = window->fullscreen_monitors[i]; - info->entire_monitor = - window->screen->monitor_infos[monitor].rect; - for (i = 1; i <= 3; i++) + if (!window->fullscreen || window->fullscreen_monitors[0] == -1) + { + info->entire_monitor = monitor_info->rect; + } + else { + int i = 0; + long monitor; + monitor = window->fullscreen_monitors[i]; - meta_rectangle_union (&info->entire_monitor, - &window->screen->monitor_infos[monitor].rect, - &info->entire_monitor); + info->entire_monitor = + window->screen->monitor_infos[monitor].rect; + for (i = 1; i <= 3; i++) + { + monitor = window->fullscreen_monitors[i]; + meta_rectangle_union (&info->entire_monitor, + &window->screen->monitor_infos[monitor].rect, + &info->entire_monitor); + } } + info->usable_screen_region = + meta_workspace_get_onscreen_region (cur_workspace); + info->usable_monitor_region = + meta_workspace_get_onmonitor_region (cur_workspace, + monitor_info->number); } - cur_workspace = window->screen->active_workspace; - info->usable_screen_region = - meta_workspace_get_onscreen_region (cur_workspace); - info->usable_monitor_region = - meta_workspace_get_onmonitor_region (cur_workspace, - monitor_info->number); - /* Log all this information for debugging */ meta_topic (META_DEBUG_GEOMETRY, "Setting up constraint info:\n" @@ -489,14 +495,17 @@ place_window_if_needed(MetaWindow *window, */ monitor_info = meta_screen_get_monitor_for_rect (window->screen, &placed_rect); - info->entire_monitor = monitor_info->rect; - meta_window_get_work_area_for_monitor (window, - monitor_info->number, - &info->work_area_monitor); cur_workspace = window->screen->active_workspace; - info->usable_monitor_region = - meta_workspace_get_onmonitor_region (cur_workspace, - monitor_info->number); + if (monitor_info) + { + info->entire_monitor = monitor_info->rect; + meta_window_get_work_area_for_monitor (window, + monitor_info->number, + &info->work_area_monitor); + info->usable_monitor_region = + meta_workspace_get_onmonitor_region (cur_workspace, + monitor_info->number); + } info->current.x = placed_rect.x; info->current.y = placed_rect.y; diff --git a/src/core/place.c b/src/core/place.c index db71b83ce..0f046f046 100644 --- a/src/core/place.c +++ b/src/core/place.c @@ -811,6 +811,8 @@ meta_window_place (MetaWindow *window, /* Warning, this function is a round trip! */ xi = meta_screen_get_current_monitor_info (window->screen); + if (!xi) + goto done; w = xi->rect.width; h = xi->rect.height; @@ -856,6 +858,8 @@ meta_window_place (MetaWindow *window, /* Warning, this is a round trip! */ xi = meta_screen_get_current_monitor_info (window->screen); + if (!xi) + goto done; /* Maximize windows if they are too big for their work area (bit of * a hack here). Assume undecorated windows probably don't intend to diff --git a/src/core/screen.c b/src/core/screen.c index b8ac22f76..54a0b0aba 100644 --- a/src/core/screen.c +++ b/src/core/screen.c @@ -381,7 +381,10 @@ meta_screen_monitor_index_to_xinerama_index (MetaScreen *screen, meta_screen_ensure_xinerama_indices (screen); - return screen->monitor_infos[index].xinerama_index; + if (index >= 0 && index < screen->n_monitor_infos) + return screen->monitor_infos[index].xinerama_index; + + return -1; } int @@ -1395,6 +1398,9 @@ meta_screen_get_monitor_for_rect (MetaScreen *screen, int i; int best_monitor, monitor_score, rect_area; + if (screen->n_monitor_infos == 0) + return NULL; + if (screen->n_monitor_infos == 1) return &screen->monitor_infos[0]; @@ -1448,7 +1454,7 @@ meta_screen_get_monitor_index_for_rect (MetaScreen *screen, MetaRectangle *rect) { const MetaMonitorInfo *monitor = meta_screen_get_monitor_for_rect (screen, rect); - return monitor->number; + return monitor ? monitor->number : -1; } const MetaMonitorInfo * diff --git a/src/core/window.c b/src/core/window.c index e3e15cf26..9745b42e0 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -1029,7 +1029,8 @@ _meta_window_shared_new (MetaDisplay *display, window->monitor = meta_screen_calculate_monitor_for_window (window->screen, window); - window->preferred_output_winsys_id = window->monitor->winsys_id; + window->preferred_output_winsys_id = window->monitor ? window->monitor->winsys_id + : -1; window->tile_match = NULL; @@ -2280,7 +2281,10 @@ meta_window_show (MetaWindow *window) if (meta_prefs_get_auto_maximize() && window->showing_for_first_time && window->has_maximize_func) { MetaRectangle work_area; - meta_window_get_work_area_for_monitor (window, window->monitor->number, &work_area); + if (window->monitor) + meta_window_get_work_area_for_monitor (window, window->monitor->number, &work_area); + else + meta_window_get_work_area_current_monitor (window, &work_area); /* Automaximize windows that map with a size > MAX_UNMAXIMIZED_WINDOW_AREA of the work area */ if (window->rect.width * window->rect.height > work_area.width * work_area.height * MAX_UNMAXIMIZED_WINDOW_AREA) { @@ -2677,7 +2681,7 @@ meta_window_maximize_internal (MetaWindow *window, meta_window_recalc_features (window); set_net_wm_state (window); - if (window->monitor->in_fullscreen) + if (window->monitor && window->monitor->in_fullscreen) meta_screen_queue_check_fullscreen (window->screen); g_object_freeze_notify (G_OBJECT (window)); @@ -2863,6 +2867,9 @@ meta_window_is_monitor_sized (MetaWindow *window) if (meta_window_is_screen_sized (window)) return TRUE; + if (!window->monitor) + return FALSE; + if (window->override_redirect) { MetaRectangle window_rect, monitor_rect; @@ -2886,7 +2893,7 @@ meta_window_is_monitor_sized (MetaWindow *window) gboolean meta_window_is_on_primary_monitor (MetaWindow *window) { - return window->monitor->is_primary; + return window->monitor ? window->monitor->is_primary : FALSE; } /** @@ -3027,7 +3034,10 @@ meta_window_unmaximize (MetaWindow *window, MetaRectangle work_area; MetaRectangle old_frame_rect, old_buffer_rect; - meta_window_get_work_area_for_monitor (window, window->monitor->number, &work_area); + if (window->monitor) + meta_window_get_work_area_for_monitor (window, window->monitor->number, &work_area); + else + meta_window_get_work_area_current_monitor (window, &work_area); meta_window_get_frame_rect (window, &old_frame_rect); meta_window_get_buffer_rect (window, &old_buffer_rect); @@ -3123,7 +3133,7 @@ meta_window_unmaximize (MetaWindow *window, meta_window_recalc_features (window); set_net_wm_state (window); - if (!window->monitor->in_fullscreen) + if (window->monitor && !window->monitor->in_fullscreen) meta_screen_queue_check_fullscreen (window->screen); } @@ -3522,7 +3532,7 @@ maybe_move_attached_dialog (MetaWindow *window, int meta_window_get_monitor (MetaWindow *window) { - return window->monitor->number; + return window->monitor ? window->monitor->number : -1; } static MetaMonitorInfo * @@ -3549,14 +3559,15 @@ meta_window_update_for_monitors_changed (MetaWindow *window) { const MetaMonitorInfo *old, *new; - if (window->override_redirect || window->type == META_WINDOW_DESKTOP) + old = window->monitor; + + if (!old || window->screen->n_monitor_infos == 0 || + window->override_redirect || window->type == META_WINDOW_DESKTOP) { meta_window_update_monitor (window, FALSE); return; } - old = window->monitor; - /* Try the preferred output first */ new = find_monitor_by_winsys_id (window, window->preferred_output_winsys_id); @@ -3643,7 +3654,7 @@ meta_window_move_resize_internal (MetaWindow *window, */ gboolean did_placement; - guint old_output_winsys_id; + guint old_output_winsys_id, new_output_winsys_id; MetaRectangle unconstrained_rect; MetaRectangle constrained_rect; MetaMoveResizeResultFlags result = 0; @@ -3737,13 +3748,15 @@ meta_window_move_resize_internal (MetaWindow *window, did_placement); } - old_output_winsys_id = window->monitor->winsys_id; + old_output_winsys_id = window->monitor ? window->monitor->winsys_id : -1; meta_window_update_monitor (window, flags & META_MOVE_RESIZE_USER_ACTION); - if (old_output_winsys_id != window->monitor->winsys_id && + new_output_winsys_id = window->monitor ? window->monitor->winsys_id : -1; + + if (old_output_winsys_id != new_output_winsys_id && flags & META_MOVE_RESIZE_MOVE_ACTION && flags & META_MOVE_RESIZE_USER_ACTION) - window->preferred_output_winsys_id = window->monitor->winsys_id; + window->preferred_output_winsys_id = new_output_winsys_id; if ((result & META_MOVE_RESIZE_RESULT_FRAME_SHAPE_CHANGED) && window->frame_bounds) { @@ -3849,7 +3862,7 @@ meta_window_move_to_monitor (MetaWindow *window, { MetaRectangle old_area, new_area; - if (monitor == window->monitor->number) + if (!window->monitor || monitor == window->monitor->number) return; meta_window_get_work_area_for_monitor (window, @@ -6104,9 +6117,17 @@ void meta_window_get_work_area_current_monitor (MetaWindow *window, MetaRectangle *area) { - meta_window_get_work_area_for_monitor (window, - window->monitor->number, - area); + if (window->monitor) + { + meta_window_get_work_area_for_monitor (window, + window->monitor->number, + area); + } + else if (area) + { + MetaRectangle empty = { 0, 0, 0, 0 }; + *area = empty; + } } /** diff --git a/src/core/workspace.c b/src/core/workspace.c index cfac7dc48..a73ac6bb7 100644 --- a/src/core/workspace.c +++ b/src/core/workspace.c @@ -765,6 +765,9 @@ ensure_work_areas_validated (MetaWorkspace *workspace) g_assert (workspace->screen_edges == NULL); g_assert (workspace->monitor_edges == NULL); + if (workspace->screen->n_monitor_infos == 0) + return; + /* STEP 1: Get the list of struts */ workspace->all_struts = copy_strut_list (workspace->builtin_struts); diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c index 376d73c78..9b102e589 100644 --- a/src/x11/window-x11.c +++ b/src/x11/window-x11.c @@ -2032,7 +2032,8 @@ meta_window_move_resize_request (MetaWindow *window, rect.width = width; rect.height = height; - meta_screen_get_monitor_geometry (window->screen, window->monitor->number, &monitor_rect); + if (window->monitor) + meta_screen_get_monitor_geometry (window->screen, window->monitor->number, &monitor_rect); /* Workaround braindead legacy apps that don't know how to * fullscreen themselves properly - don't get fooled by -- 2.12.0