From 9604fb36121d40a7440e3dea49f907f426146e71 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/core/barrier.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/src/core/barrier.c b/src/core/barrier.c
index b869d2e..1d372e9 100644
--- a/src/core/barrier.c
+++ b/src/core/barrier.c
@@ -14,6 +14,7 @@
#include <X11/extensions/Xfixes.h>
#include <meta/util.h>
#include <meta/barrier.h>
+#include <meta/errors.h>
#include "display-private.h"
#include "mutter-enum-types.h"
#include "core.h"
@@ -183,6 +184,7 @@ meta_barrier_constructed (GObject *object)
MetaBarrierPrivate *priv = barrier->priv;
Display *dpy;
Window root;
+ PointerBarrier xbarrier;
g_return_if_fail (priv->x1 == priv->x2 || priv->y1 == priv->y2);
@@ -192,13 +194,18 @@ meta_barrier_constructed (GObject *object)
return;
}
+ meta_error_trap_push (priv->display);
dpy = priv->display->xdisplay;
root = DefaultRootWindow (dpy);
- priv->xbarrier = XFixesCreatePointerBarrier (dpy, root,
- priv->x1, priv->y1,
- priv->x2, priv->y2,
- priv->directions, 0, NULL);
+ xbarrier = XFixesCreatePointerBarrier (dpy, root,
+ priv->x1, priv->y1,
+ priv->x2, priv->y2,
+ priv->directions, 0, NULL);
+ if (meta_error_trap_pop_with_return (priv->display) != Success)
+ return NULL;
+
+ priv->xbarrier = xbarrier;
/* Take a ref that we'll release when the XID dies inside destroy(),
* so that the object stays alive and doesn't get GC'd. */
--
2.5.0
From 4485e49f3f7d1232b7bd3c312f26117f5827e816 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/compositor.c | 3 +-
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 | 62 ++++++++++++++--------
src/core/workspace.c | 3 ++
src/x11/window-x11.c | 3 +-
9 files changed, 105 insertions(+), 57 deletions(-)
diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
index 2c6d65e..3abe413 100644
--- a/src/backends/x11/meta-monitor-manager-xrandr.c
+++ b/src/backends/x11/meta-monitor-manager-xrandr.c
@@ -866,7 +866,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/compositor.c b/src/compositor/compositor.c
index 250d489..8bf469f 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -1105,7 +1105,8 @@ static gboolean
meta_repaint_func (gpointer data)
{
MetaCompositor *compositor = data;
- pre_paint_windows (compositor);
+ if (meta_screen_get_n_monitors (compositor->display->screen) > 0)
+ pre_paint_windows (compositor);
return TRUE;
}
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 3d6fab1..476abbf 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -956,7 +956,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 9f5f127..1cff417 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
@@ -331,6 +332,8 @@ setup_constraint_info (ConstraintInfo *info,
const MetaMonitorInfo *monitor_info;
MetaWorkspace *cur_workspace;
+ memset (info, 0, sizeof (ConstraintInfo));
+
info->orig = *orig;
info->current = *new;
@@ -376,40 +379,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"
@@ -478,14 +484,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 56befbd..7f21556 100644
--- a/src/core/place.c
+++ b/src/core/place.c
@@ -746,6 +746,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;
@@ -791,6 +793,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 b26137e..6eaf04f 100644
--- a/src/core/screen.c
+++ b/src/core/screen.c
@@ -385,7 +385,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
@@ -1410,6 +1413,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];
@@ -1463,7 +1469,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 0bc85d8..694a11e 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -962,7 +962,8 @@ _meta_window_shared_new (MetaDisplay *display,
window->compositor_private = NULL;
window->monitor = meta_screen_get_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;
@@ -1130,7 +1131,8 @@ _meta_window_shared_new (MetaDisplay *display,
meta_window_update_struts (window);
}
- g_signal_emit_by_name (window->screen, "window-entered-monitor", window->monitor->number, window);
+ if (window->monitor)
+ g_signal_emit_by_name (window->screen, "window-entered-monitor", window->monitor->number, window);
/* Must add window to stack before doing move/resize, since the
* window might have fullscreen size (i.e. should have been
@@ -2225,7 +2227,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)
{
@@ -2622,7 +2627,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));
@@ -2802,6 +2807,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;
@@ -2825,7 +2833,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;
}
/**
@@ -2978,7 +2986,10 @@ meta_window_unmaximize_internal (MetaWindow *window,
MetaRectangle work_area;
MetaRectangle old_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_rect);
meta_topic (META_DEBUG_WINDOW_OPS,
@@ -3069,7 +3080,7 @@ meta_window_unmaximize_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);
}
@@ -3476,7 +3487,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 *
@@ -3506,14 +3517,14 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
if (window->type == META_WINDOW_DESKTOP)
return;
- if (window->override_redirect)
+ old = window->monitor;
+
+ if (!old || window->screen->n_monitor_infos == 0 || window->override_redirect)
{
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);
@@ -3568,7 +3579,8 @@ meta_window_update_monitor (MetaWindow *window,
if (old)
g_signal_emit_by_name (window->screen, "window-left-monitor", old->number, window);
- g_signal_emit_by_name (window->screen, "window-entered-monitor", window->monitor->number, window);
+ if (window->monitor)
+ g_signal_emit_by_name (window->screen, "window-entered-monitor", window->monitor->number, window);
/* If we're changing monitors, we need to update the has_maximize_func flag,
* as the working area has changed. */
@@ -3602,7 +3614,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;
@@ -3696,13 +3708,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_IS_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_IS_MOVE_ACTION && flags & META_IS_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)
{
@@ -3808,7 +3822,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,
@@ -6198,9 +6212,17 @@ meta_window_get_work_area_current_monitor (MetaWindow *window,
monitor = meta_screen_get_monitor_for_window (window->screen,
window);
- meta_window_get_work_area_for_monitor (window,
- monitor->number,
- area);
+ if (monitor)
+ {
+ meta_window_get_work_area_for_monitor (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 f275c00..d4077d7 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 1e2580c..879f229 100644
--- a/src/x11/window-x11.c
+++ b/src/x11/window-x11.c
@@ -1990,7 +1990,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.5.0