From 0826616da1dacf29e3e08dae6d2ffe4116e5bdff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
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 <X11/extensions/XInput2.h>
#include <X11/extensions/Xfixes.h>
#include <meta/barrier.h>
+#include <meta/errors.h>
#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?= <fmuellner@gnome.org>
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 <meta/prefs.h>
#include <stdlib.h>
+#include <string.h>
#include <math.h>
#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