File mutter-bnc879109-no-monitors-crash.patch of Package mutter
commit a8e4253b56d8f1310087c8f80ba6e54935d2fa30
Author: Federico Mena Quintero <federico@gnome.org>
Date: Sat May 31 12:32:26 2014 -0500
MonitorManager: generate a null configuration if no real outputs are usable
diff --git a/src/core/monitor-private.h b/src/core/monitor-private.h
index bbe73f5..1710dd6 100644
--- a/src/core/monitor-private.h
+++ b/src/core/monitor-private.h
@@ -256,6 +256,12 @@ struct _MetaMonitorManager
MetaMonitorConfig *config;
GnomePnpIds *pnp_ids;
+
+ /* When there are no usable outputs/modes/crtcs, we use the following */
+ gboolean using_null_configuration;
+ MetaOutput null_output;
+ MetaMonitorMode null_mode;
+ MetaCRTC null_crtc;
};
struct _MetaMonitorManagerClass
diff --git a/src/core/monitor.c b/src/core/monitor.c
index a07571d..349cc9d 100644
--- a/src/core/monitor.c
+++ b/src/core/monitor.c
@@ -41,6 +41,12 @@
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
+#define NULL_CONFIGURATION_WIDTH 1024
+#define NULL_CONFIGURATION_HEIGHT 768
+#define NULL_OUTPUT_ID 0
+#define NULL_MODE_ID 0
+#define NULL_CRTC_ID 0
+
enum {
CONFIRM_DISPLAY_CHANGE,
SIGNALS_LAST
@@ -364,8 +370,76 @@ get_edid_file_dummy (MetaMonitorManager *manager,
}
static void
+init_null_output (MetaMonitorManager *manager)
+{
+ MetaOutput *o = &manager->null_output;
+
+ o->crtc = &manager->null_crtc;
+ o->output_id = NULL_OUTPUT_ID;
+ o->name = g_strdup ("META-NULL");
+ o->vendor = g_strdup ("MetaProducts Inc.");
+ o->product = g_strdup ("unknown");
+ o->serial = g_strdup ("0xC0FFEE");
+ o->width_mm = 222;
+ o->height_mm = 125;
+ o->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
+ o->preferred_mode = &manager->null_mode;
+ o->n_modes = 1;
+ o->modes = g_new0 (MetaMonitorMode *, 1);
+ o->modes[0] = &manager->null_mode;
+ o->n_possible_crtcs = 1;
+ o->possible_crtcs = g_new0 (MetaCRTC *, 1);
+ o->possible_crtcs[0] = &manager->null_crtc;
+ o->n_possible_clones = 0;
+ o->possible_clones = NULL;
+ o->backlight = -1;
+ o->backlight_min = 0;
+ o->backlight_max = 0;
+}
+
+static void
+free_null_output (MetaMonitorManager *manager)
+{
+ g_free (manager->null_output.name);
+ g_free (manager->null_output.vendor);
+ g_free (manager->null_output.product);
+ g_free (manager->null_output.serial);
+ g_free (manager->null_output.modes);
+ g_free (manager->null_output.possible_crtcs);
+}
+
+static void
+init_null_mode (MetaMonitorManager *manager)
+{
+ MetaMonitorMode *m = &manager->null_mode;
+
+ m->mode_id = NULL_MODE_ID;
+ m->width = NULL_CONFIGURATION_WIDTH;
+ m->height = NULL_CONFIGURATION_HEIGHT;
+ m->refresh_rate = 60.0;
+}
+
+static void
+init_null_crtc (MetaMonitorManager *manager)
+{
+ MetaCRTC *c = &manager->null_crtc;
+
+ c->crtc_id = NULL_CRTC_ID;
+ c->rect.x = 0;
+ c->rect.y = 0;
+ c->rect.width = NULL_CONFIGURATION_WIDTH;
+ c->rect.height = NULL_CONFIGURATION_HEIGHT;
+ c->current_mode = &manager->null_mode;
+ c->transform = WL_OUTPUT_TRANSFORM_NORMAL;
+ c->all_transforms = ALL_WL_TRANSFORMS;
+}
+
+static void
meta_monitor_manager_init (MetaMonitorManager *manager)
{
+ init_null_output (manager);
+ init_null_mode (manager);
+ init_null_crtc (manager);
}
static void
@@ -376,6 +450,55 @@ read_current_config (MetaMonitorManager *manager)
META_MONITOR_MANAGER_GET_CLASS (manager)->read_current (manager);
}
+static gboolean
+monitor_infos_are_valid (GArray *monitor_infos)
+{
+ return monitor_infos->len > 0;
+}
+
+static MetaMonitorInfo *
+make_null_monitor_info (void)
+{
+ MetaMonitorInfo *null_monitor_info;
+
+ null_monitor_info = g_new0 (MetaMonitorInfo, 1);
+
+ null_monitor_info->number = 0;
+ null_monitor_info->xinerama_index = 0; /* set in meta_screen_ensure_xinerama_indices() */
+ null_monitor_info->rect.x = 0;
+ null_monitor_info->rect.y = 0;
+ null_monitor_info->rect.width = NULL_CONFIGURATION_WIDTH;
+ null_monitor_info->rect.height = NULL_CONFIGURATION_HEIGHT;
+ null_monitor_info->is_primary = TRUE;
+ null_monitor_info->is_presentation = TRUE;
+ null_monitor_info->in_fullscreen = -1; /* as from make_logical_config() */
+ null_monitor_info->output_id = NULL_OUTPUT_ID;
+
+ return null_monitor_info;
+}
+
+/* This function generates a "null" configuration that has one dummy but usable
+ * output, which in turn has a dummy but usable CRTC. All of this is used, for
+ * example, when all the real outputs are off, or when they have no usable
+ * modes. A laptop may be turned on in a docking station, with the lid closed,
+ * and the external monitor may not have been plugged in yet. Or the only
+ * monitor on a machine may be unplugged, and replugged later - while there are
+ * no usable outputs, we just use a dummy output.
+ *
+ * (This is not called make_dummy_configuration() to avoid confusion with
+ * read_current_dummy() and related functions above.)
+ */
+static void
+make_null_configuration (MetaMonitorManager *manager)
+{
+ manager->monitor_infos = make_null_monitor_info ();
+ manager->n_monitor_infos = 1;
+
+ manager->primary_monitor_index = 0;
+
+ manager->using_null_configuration = TRUE;
+}
+
/*
* make_logical_config:
*
@@ -467,8 +590,17 @@ make_logical_config (MetaMonitorManager *manager)
manager->primary_monitor_index = info->number;
}
- manager->n_monitor_infos = monitor_infos->len;
- manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE);
+ if (monitor_infos_are_valid (monitor_infos))
+ {
+ manager->n_monitor_infos = monitor_infos->len;
+ manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE);
+ manager->using_null_configuration = FALSE;
+ }
+ else
+ {
+ g_array_free (monitor_infos, TRUE);
+ make_null_configuration (manager);
+ }
}
static MetaMonitorManager *
@@ -582,6 +714,8 @@ meta_monitor_manager_finalize (GObject *object)
g_free (manager->modes);
g_free (manager->crtcs);
+ free_null_output (manager);
+
G_OBJECT_CLASS (meta_monitor_manager_parent_class)->finalize (object);
}
@@ -1425,8 +1559,16 @@ MetaOutput *
meta_monitor_manager_get_outputs (MetaMonitorManager *manager,
unsigned int *n_outputs)
{
- *n_outputs = manager->n_outputs;
- return manager->outputs;
+ if (manager->using_null_configuration)
+ {
+ *n_outputs = 1;
+ return &manager->null_output;
+ }
+ else
+ {
+ *n_outputs = manager->n_outputs;
+ return manager->outputs;
+ }
}
void