|
|
2c033f |
From 9fa99a888d9d9b84cabf419d321f0223e0d5ab7e Mon Sep 17 00:00:00 2001
|
|
|
2c033f |
From: Jonathon Jongsma <jjongsma@redhat.com>
|
|
|
2c033f |
Date: Mon, 17 Nov 2014 15:13:15 -0600
|
|
|
2c033f |
Subject: [PATCH 1/4] monitor-config: refactor make_default_config()
|
|
|
2c033f |
|
|
|
2c033f |
Move logic for creating different types of configurations into separate
|
|
|
2c033f |
functions. This keeps things a bit cleaner and allows us to add alternate
|
|
|
2c033f |
configuration types more easily.
|
|
|
2c033f |
|
|
|
2c033f |
Conflicts:
|
|
|
2c033f |
src/backends/meta-monitor-config.c
|
|
|
2c033f |
|
|
|
2c033f |
https://bugzilla.redhat.com/show_bug.cgi?id=1166319
|
|
|
2c033f |
---
|
|
|
2c033f |
src/backends/meta-monitor-config.c | 172 +++++++++++++++++++++----------------
|
|
|
2c033f |
1 file changed, 100 insertions(+), 72 deletions(-)
|
|
|
2c033f |
|
|
|
2c033f |
diff --git a/src/backends/meta-monitor-config.c b/src/backends/meta-monitor-config.c
|
|
|
2c033f |
index 399e9f0..99042d7 100644
|
|
|
2c033f |
--- a/src/backends/meta-monitor-config.c
|
|
|
2c033f |
+++ b/src/backends/meta-monitor-config.c
|
|
|
2c033f |
@@ -1081,47 +1081,78 @@ find_primary_output (MetaOutput *outputs,
|
|
|
2c033f |
return best;
|
|
|
2c033f |
}
|
|
|
2c033f |
|
|
|
2c033f |
-static MetaConfiguration *
|
|
|
2c033f |
-make_default_config (MetaMonitorConfig *self,
|
|
|
2c033f |
- MetaOutput *outputs,
|
|
|
2c033f |
- unsigned n_outputs,
|
|
|
2c033f |
- int max_width,
|
|
|
2c033f |
- int max_height)
|
|
|
2c033f |
+static void
|
|
|
2c033f |
+init_config_from_preferred_mode (MetaOutputConfig *config,
|
|
|
2c033f |
+ MetaOutput *output)
|
|
|
2c033f |
+{
|
|
|
2c033f |
+ config->enabled = TRUE;
|
|
|
2c033f |
+ config->rect.x = 0;
|
|
|
2c033f |
+ config->rect.y = 0;
|
|
|
2c033f |
+ config->rect.width = output->preferred_mode->width;
|
|
|
2c033f |
+ config->rect.height = output->preferred_mode->height;
|
|
|
2c033f |
+ config->refresh_rate = output->preferred_mode->refresh_rate;
|
|
|
2c033f |
+ config->transform = META_MONITOR_TRANSFORM_NORMAL;
|
|
|
2c033f |
+ config->is_primary = FALSE;
|
|
|
2c033f |
+ config->is_presentation = FALSE;
|
|
|
2c033f |
+}
|
|
|
2c033f |
+
|
|
|
2c033f |
+static void
|
|
|
2c033f |
+make_linear_config (MetaMonitorConfig *self,
|
|
|
2c033f |
+ MetaOutput *outputs,
|
|
|
2c033f |
+ unsigned n_outputs,
|
|
|
2c033f |
+ int max_width,
|
|
|
2c033f |
+ int max_height,
|
|
|
2c033f |
+ MetaConfiguration *config)
|
|
|
2c033f |
{
|
|
|
2c033f |
- unsigned i, j;
|
|
|
2c033f |
- int x, y;
|
|
|
2c033f |
- MetaConfiguration *ret;
|
|
|
2c033f |
MetaOutput *primary;
|
|
|
2c033f |
+ unsigned i;
|
|
|
2c033f |
+ int x;
|
|
|
2c033f |
|
|
|
2c033f |
- ret = g_slice_new (MetaConfiguration);
|
|
|
2c033f |
- make_config_key (ret, outputs, n_outputs, -1);
|
|
|
2c033f |
- ret->outputs = g_new0 (MetaOutputConfig, n_outputs);
|
|
|
2c033f |
+ g_return_if_fail (config != NULL);
|
|
|
2c033f |
|
|
|
2c033f |
- /* Special case the simple case: one output, primary at preferred mode,
|
|
|
2c033f |
- nothing else to do */
|
|
|
2c033f |
- if (n_outputs == 1)
|
|
|
2c033f |
+ primary = find_primary_output (outputs, n_outputs);
|
|
|
2c033f |
+
|
|
|
2c033f |
+ x = primary->preferred_mode->width;
|
|
|
2c033f |
+ for (i = 0; i < n_outputs; i++)
|
|
|
2c033f |
{
|
|
|
2c033f |
- ret->outputs[0].enabled = TRUE;
|
|
|
2c033f |
- ret->outputs[0].rect.x = 0;
|
|
|
2c033f |
- ret->outputs[0].rect.y = 0;
|
|
|
2c033f |
- ret->outputs[0].rect.width = outputs[0].preferred_mode->width;
|
|
|
2c033f |
- ret->outputs[0].rect.height = outputs[0].preferred_mode->height;
|
|
|
2c033f |
- ret->outputs[0].refresh_rate = outputs[0].preferred_mode->refresh_rate;
|
|
|
2c033f |
- ret->outputs[0].transform = META_MONITOR_TRANSFORM_NORMAL;
|
|
|
2c033f |
- ret->outputs[0].is_primary = TRUE;
|
|
|
2c033f |
+ gboolean is_primary = (&outputs[i] == primary);
|
|
|
2c033f |
|
|
|
2c033f |
- return ret;
|
|
|
2c033f |
- }
|
|
|
2c033f |
+ init_config_from_preferred_mode (&config->outputs[i], &outputs[i]);
|
|
|
2c033f |
+ config->outputs[i].is_primary = is_primary;
|
|
|
2c033f |
|
|
|
2c033f |
- /* If we reach this point, this is either the first time mutter runs
|
|
|
2c033f |
- on this system ever, or we just hotplugged a new screen.
|
|
|
2c033f |
- In the latter case, search for a configuration that includes one
|
|
|
2c033f |
- less screen, then add the new one as a presentation screen
|
|
|
2c033f |
- in preferred mode.
|
|
|
2c033f |
+ if (is_primary)
|
|
|
2c033f |
+ {
|
|
|
2c033f |
+ config->outputs[i].rect.x = 0;
|
|
|
2c033f |
+ }
|
|
|
2c033f |
+ else
|
|
|
2c033f |
+ {
|
|
|
2c033f |
+ config->outputs[i].rect.x = x;
|
|
|
2c033f |
+ x += config->outputs[i].rect.width;
|
|
|
2c033f |
+ }
|
|
|
2c033f |
+
|
|
|
2c033f |
+ /* Disable outputs that would go beyond framebuffer limits */
|
|
|
2c033f |
+ if (config->outputs[i].rect.x + config->outputs[i].rect.width > max_width)
|
|
|
2c033f |
+ config->outputs[i].enabled = FALSE;
|
|
|
2c033f |
+ }
|
|
|
2c033f |
+}
|
|
|
2c033f |
|
|
|
2c033f |
- XXX: but presentation mode is not implemented in the control-center
|
|
|
2c033f |
- or in mutter core, so let's do extended for now.
|
|
|
2c033f |
+/* Search for a configuration that includes one less screen, then add the new
|
|
|
2c033f |
+ * one as a presentation screen in preferred mode.
|
|
|
2c033f |
+ *
|
|
|
2c033f |
+ * XXX: but presentation mode is not implemented in the control-center or in
|
|
|
2c033f |
+ * mutter core, so let's do extended for now.
|
|
|
2c033f |
*/
|
|
|
2c033f |
+static gboolean
|
|
|
2c033f |
+extend_stored_config (MetaMonitorConfig *self,
|
|
|
2c033f |
+ MetaOutput *outputs,
|
|
|
2c033f |
+ unsigned n_outputs,
|
|
|
2c033f |
+ int max_width,
|
|
|
2c033f |
+ int max_height,
|
|
|
2c033f |
+ MetaConfiguration *config)
|
|
|
2c033f |
+{
|
|
|
2c033f |
+ int x, y;
|
|
|
2c033f |
+ unsigned i, j;
|
|
|
2c033f |
+
|
|
|
2c033f |
x = 0;
|
|
|
2c033f |
y = 0;
|
|
|
2c033f |
for (i = 0; i < n_outputs; i++)
|
|
|
2c033f |
@@ -1139,71 +1170,68 @@ make_default_config (MetaMonitorConfig *self,
|
|
|
2c033f |
{
|
|
|
2c033f |
if (j < i)
|
|
|
2c033f |
{
|
|
|
2c033f |
- g_assert (output_key_equal (&ret->keys[j], &ref->keys[j]));
|
|
|
2c033f |
- ret->outputs[j] = ref->outputs[j];
|
|
|
2c033f |
+ g_assert (output_key_equal (&config->keys[j], &ref->keys[j]));
|
|
|
2c033f |
+ config->outputs[j] = ref->outputs[j];
|
|
|
2c033f |
x = MAX (x, ref->outputs[j].rect.x + ref->outputs[j].rect.width);
|
|
|
2c033f |
y = MAX (y, ref->outputs[j].rect.y + ref->outputs[j].rect.height);
|
|
|
2c033f |
}
|
|
|
2c033f |
else if (j > i)
|
|
|
2c033f |
{
|
|
|
2c033f |
- g_assert (output_key_equal (&ret->keys[j], &ref->keys[j - 1]));
|
|
|
2c033f |
- ret->outputs[j] = ref->outputs[j - 1];
|
|
|
2c033f |
+ g_assert (output_key_equal (&config->keys[j], &ref->keys[j - 1]));
|
|
|
2c033f |
+ config->outputs[j] = ref->outputs[j - 1];
|
|
|
2c033f |
x = MAX (x, ref->outputs[j - 1].rect.x + ref->outputs[j - 1].rect.width);
|
|
|
2c033f |
y = MAX (y, ref->outputs[j - 1].rect.y + ref->outputs[j - 1].rect.height);
|
|
|
2c033f |
}
|
|
|
2c033f |
else
|
|
|
2c033f |
{
|
|
|
2c033f |
- ret->outputs[j].enabled = TRUE;
|
|
|
2c033f |
- ret->outputs[j].rect.x = 0;
|
|
|
2c033f |
- ret->outputs[j].rect.y = 0;
|
|
|
2c033f |
- ret->outputs[j].rect.width = outputs[0].preferred_mode->width;
|
|
|
2c033f |
- ret->outputs[j].rect.height = outputs[0].preferred_mode->height;
|
|
|
2c033f |
- ret->outputs[j].refresh_rate = outputs[0].preferred_mode->refresh_rate;
|
|
|
2c033f |
- ret->outputs[j].transform = META_MONITOR_TRANSFORM_NORMAL;
|
|
|
2c033f |
- ret->outputs[j].is_primary = FALSE;
|
|
|
2c033f |
- ret->outputs[j].is_presentation = FALSE;
|
|
|
2c033f |
+ init_config_from_preferred_mode (&ref->outputs[j], &outputs[0]);
|
|
|
2c033f |
}
|
|
|
2c033f |
}
|
|
|
2c033f |
|
|
|
2c033f |
/* Place the new output at the right end of the screen, if it fits,
|
|
|
2c033f |
otherwise below it, otherwise disable it (or apply_configuration will fail) */
|
|
|
2c033f |
- if (x + ret->outputs[i].rect.width <= max_width)
|
|
|
2c033f |
- ret->outputs[i].rect.x = x;
|
|
|
2c033f |
- else if (y + ret->outputs[i].rect.height <= max_height)
|
|
|
2c033f |
- ret->outputs[i].rect.y = y;
|
|
|
2c033f |
+ if (x + config->outputs[i].rect.width <= max_width)
|
|
|
2c033f |
+ config->outputs[i].rect.x = x;
|
|
|
2c033f |
+ else if (y + config->outputs[i].rect.height <= max_height)
|
|
|
2c033f |
+ config->outputs[i].rect.y = y;
|
|
|
2c033f |
else
|
|
|
2c033f |
- ret->outputs[i].enabled = FALSE;
|
|
|
2c033f |
+ config->outputs[i].enabled = FALSE;
|
|
|
2c033f |
|
|
|
2c033f |
- return ret;
|
|
|
2c033f |
+ return TRUE;
|
|
|
2c033f |
}
|
|
|
2c033f |
}
|
|
|
2c033f |
|
|
|
2c033f |
- /* No previous configuration found, try with a really default one, which
|
|
|
2c033f |
- is one primary that goes first and the rest to the right of it, extended.
|
|
|
2c033f |
- */
|
|
|
2c033f |
- primary = find_primary_output (outputs, n_outputs);
|
|
|
2c033f |
+ return FALSE;
|
|
|
2c033f |
+}
|
|
|
2c033f |
|
|
|
2c033f |
- x = primary->preferred_mode->width;
|
|
|
2c033f |
- for (i = 0; i < n_outputs; i++)
|
|
|
2c033f |
- {
|
|
|
2c033f |
- MetaOutput *output = &outputs[i];
|
|
|
2c033f |
+static MetaConfiguration *
|
|
|
2c033f |
+make_default_config (MetaMonitorConfig *self,
|
|
|
2c033f |
+ MetaOutput *outputs,
|
|
|
2c033f |
+ unsigned n_outputs,
|
|
|
2c033f |
+ int max_width,
|
|
|
2c033f |
+ int max_height)
|
|
|
2c033f |
+{
|
|
|
2c033f |
+ MetaConfiguration *ret = NULL;
|
|
|
2c033f |
|
|
|
2c033f |
- ret->outputs[i].enabled = TRUE;
|
|
|
2c033f |
- ret->outputs[i].rect.x = (output == primary) ? 0 : x;
|
|
|
2c033f |
- ret->outputs[i].rect.y = 0;
|
|
|
2c033f |
- ret->outputs[i].rect.width = output->preferred_mode->width;
|
|
|
2c033f |
- ret->outputs[i].rect.height = output->preferred_mode->height;
|
|
|
2c033f |
- ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate;
|
|
|
2c033f |
- ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
|
|
|
2c033f |
- ret->outputs[i].is_primary = (output == primary);
|
|
|
2c033f |
+ ret = g_slice_new (MetaConfiguration);
|
|
|
2c033f |
+ make_config_key (ret, outputs, n_outputs, -1);
|
|
|
2c033f |
+ ret->outputs = g_new0 (MetaOutputConfig, n_outputs);
|
|
|
2c033f |
|
|
|
2c033f |
- /* Disable outputs that would go beyond framebuffer limits */
|
|
|
2c033f |
- if (ret->outputs[i].rect.x + ret->outputs[i].rect.width > max_width)
|
|
|
2c033f |
- ret->outputs[i].enabled = FALSE;
|
|
|
2c033f |
- else if (output != primary)
|
|
|
2c033f |
- x += output->preferred_mode->width;
|
|
|
2c033f |
+ /* Special case the simple case: one output, primary at preferred mode,
|
|
|
2c033f |
+ nothing else to do */
|
|
|
2c033f |
+ if (n_outputs == 1)
|
|
|
2c033f |
+ {
|
|
|
2c033f |
+
|
|
|
2c033f |
+ init_config_from_preferred_mode (&ret->outputs[0], &outputs[0]);
|
|
|
2c033f |
+ ret->outputs[0].is_primary = TRUE;
|
|
|
2c033f |
+ return ret;
|
|
|
2c033f |
}
|
|
|
2c033f |
|
|
|
2c033f |
+ if (extend_stored_config (self, outputs, n_outputs, max_width, max_height, ret))
|
|
|
2c033f |
+ return ret;
|
|
|
2c033f |
+
|
|
|
2c033f |
+ make_linear_config (self, outputs, n_outputs, max_width, max_height, ret);
|
|
|
2c033f |
+
|
|
|
2c033f |
return ret;
|
|
|
2c033f |
}
|
|
|
2c033f |
|
|
|
2c033f |
--
|
|
|
2c033f |
2.3.6
|
|
|
2c033f |
|
|
|
2c033f |
|
|
|
2c033f |
From 76566a956eaf7b905dbfd851ee63ebe6236ab872 Mon Sep 17 00:00:00 2001
|
|
|
2c033f |
From: Jonathon Jongsma <jjongsma@redhat.com>
|
|
|
2c033f |
Date: Wed, 12 Nov 2014 10:25:55 -0600
|
|
|
2c033f |
Subject: [PATCH 2/4] monitor-config: ignore stored config when
|
|
|
2c033f |
hotplug_mode_update is set
|
|
|
2c033f |
|
|
|
2c033f |
When the output device has hotplug_mode_update (e.g. the qxl driver used in
|
|
|
2c033f |
vms), the displays can be dynamically resized, so the current display
|
|
|
2c033f |
configuration does not often match a stored configuration. When a new
|
|
|
2c033f |
monitor is added, make_default_config() tries to create a new display
|
|
|
2c033f |
configuration by choosing a stored configuration with N-1 monitors, and then
|
|
|
2c033f |
adding a new monitor to the end of the layout. Because the stored config
|
|
|
2c033f |
doesn't match the current outputs, apply_configuration() will routinely
|
|
|
2c033f |
fail, leaving the additional display unconfigured. In this case, it's more
|
|
|
2c033f |
useful to just fall back to creating a new default configuration from
|
|
|
2c033f |
scratch so that all outputs get configured to their preferred mode.
|
|
|
2c033f |
|
|
|
2c033f |
Conflicts:
|
|
|
2c033f |
src/backends/meta-monitor-config.c
|
|
|
2c033f |
|
|
|
2c033f |
https://bugzilla.redhat.com/show_bug.cgi?id=1166319
|
|
|
2c033f |
---
|
|
|
2c033f |
src/backends/meta-monitor-config.c | 17 ++++++++++++++---
|
|
|
2c033f |
1 file changed, 14 insertions(+), 3 deletions(-)
|
|
|
2c033f |
|
|
|
2c033f |
diff --git a/src/backends/meta-monitor-config.c b/src/backends/meta-monitor-config.c
|
|
|
2c033f |
index 99042d7..3e57215 100644
|
|
|
2c033f |
--- a/src/backends/meta-monitor-config.c
|
|
|
2c033f |
+++ b/src/backends/meta-monitor-config.c
|
|
|
2c033f |
@@ -1209,7 +1209,8 @@ make_default_config (MetaMonitorConfig *self,
|
|
|
2c033f |
MetaOutput *outputs,
|
|
|
2c033f |
unsigned n_outputs,
|
|
|
2c033f |
int max_width,
|
|
|
2c033f |
- int max_height)
|
|
|
2c033f |
+ int max_height,
|
|
|
2c033f |
+ gboolean use_stored_config)
|
|
|
2c033f |
{
|
|
|
2c033f |
MetaConfiguration *ret = NULL;
|
|
|
2c033f |
|
|
|
2c033f |
@@ -1227,7 +1228,8 @@ make_default_config (MetaMonitorConfig *self,
|
|
|
2c033f |
return ret;
|
|
|
2c033f |
}
|
|
|
2c033f |
|
|
|
2c033f |
- if (extend_stored_config (self, outputs, n_outputs, max_width, max_height, ret))
|
|
|
2c033f |
+ if (use_stored_config &&
|
|
|
2c033f |
+ extend_stored_config (self, outputs, n_outputs, max_width, max_height, ret))
|
|
|
2c033f |
return ret;
|
|
|
2c033f |
|
|
|
2c033f |
make_linear_config (self, outputs, n_outputs, max_width, max_height, ret);
|
|
|
2c033f |
@@ -1292,6 +1294,7 @@ meta_monitor_config_make_default (MetaMonitorConfig *self,
|
|
|
2c033f |
unsigned n_outputs;
|
|
|
2c033f |
gboolean ok;
|
|
|
2c033f |
int max_width, max_height;
|
|
|
2c033f |
+ gboolean use_stored_config;
|
|
|
2c033f |
|
|
|
2c033f |
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
|
|
|
2c033f |
meta_monitor_manager_get_screen_limits (manager, &max_width, &max_height);
|
|
|
2c033f |
@@ -1302,7 +1305,15 @@ meta_monitor_config_make_default (MetaMonitorConfig *self,
|
|
|
2c033f |
return;
|
|
|
2c033f |
}
|
|
|
2c033f |
|
|
|
2c033f |
- default_config = make_default_config (self, outputs, n_outputs, max_width, max_height);
|
|
|
2c033f |
+ /* if the device has hotplug_mode_update, it's possible that the
|
|
|
2c033f |
+ * current display configuration does not match a stored configuration.
|
|
|
2c033f |
+ * Since extend_existing_config() tries to build a configuration that is
|
|
|
2c033f |
+ * based on a previously-stored configuration, it's quite likely that the
|
|
|
2c033f |
+ * resulting config will fail. Even if it doesn't fail, it may result in
|
|
|
2c033f |
+ * an unexpected configuration, so don't attempt to use a stored config
|
|
|
2c033f |
+ * in this situation. */
|
|
|
2c033f |
+ use_stored_config = !meta_monitor_manager_has_hotplug_mode_update (manager);
|
|
|
2c033f |
+ default_config = make_default_config (self, outputs, n_outputs, max_width, max_height, use_stored_config);
|
|
|
2c033f |
|
|
|
2c033f |
if (default_config != NULL)
|
|
|
2c033f |
{
|
|
|
2c033f |
--
|
|
|
2c033f |
2.3.6
|
|
|
2c033f |
|
|
|
2c033f |
|
|
|
2c033f |
From f357ed24e24efa26b2d65ca307db8c20e20238b9 Mon Sep 17 00:00:00 2001
|
|
|
2c033f |
From: Jonathon Jongsma <jjongsma@redhat.com>
|
|
|
2c033f |
Date: Mon, 10 Nov 2014 15:36:47 -0600
|
|
|
2c033f |
Subject: [PATCH 3/4] monitor-manager: Add support for suggested position for
|
|
|
2c033f |
outputs
|
|
|
2c033f |
|
|
|
2c033f |
In recent versions of the QXL driver, it may set "suggested X|Y" connector
|
|
|
2c033f |
properties. These properties are used to indicate the position at which
|
|
|
2c033f |
multiple displays should be aligned. If all outputs have a suggested position,
|
|
|
2c033f |
the displays are arranged according to these positions, otherwise we fall back
|
|
|
2c033f |
to the default configuration.
|
|
|
2c033f |
|
|
|
2c033f |
At the moment, we trust that the driver has chosen sane values for the
|
|
|
2c033f |
suggested position.
|
|
|
2c033f |
|
|
|
2c033f |
https://bugzilla.redhat.com/show_bug.cgi?id=1166319
|
|
|
2c033f |
---
|
|
|
2c033f |
src/backends/meta-monitor-config.c | 53 ++++++++++++++++++++++++++
|
|
|
2c033f |
src/backends/meta-monitor-manager.h | 2 +
|
|
|
2c033f |
src/backends/native/meta-monitor-manager-kms.c | 2 +
|
|
|
2c033f |
src/backends/x11/meta-monitor-manager-xrandr.c | 52 +++++++++++++++++++++++++
|
|
|
2c033f |
4 files changed, 109 insertions(+)
|
|
|
2c033f |
|
|
|
2c033f |
diff --git a/src/backends/meta-monitor-config.c b/src/backends/meta-monitor-config.c
|
|
|
2c033f |
index 3e57215..a65c241 100644
|
|
|
2c033f |
--- a/src/backends/meta-monitor-config.c
|
|
|
2c033f |
+++ b/src/backends/meta-monitor-config.c
|
|
|
2c033f |
@@ -34,6 +34,7 @@
|
|
|
2c033f |
|
|
|
2c033f |
#include "config.h"
|
|
|
2c033f |
|
|
|
2c033f |
+#include "boxes-private.h"
|
|
|
2c033f |
#include "meta-monitor-config.h"
|
|
|
2c033f |
|
|
|
2c033f |
#include <string.h>
|
|
|
2c033f |
@@ -1096,6 +1097,55 @@ init_config_from_preferred_mode (MetaOutputConfig *config,
|
|
|
2c033f |
config->is_presentation = FALSE;
|
|
|
2c033f |
}
|
|
|
2c033f |
|
|
|
2c033f |
+/* This function handles configuring the outputs when the driver provides a
|
|
|
2c033f |
+ * suggested layout position for each output. This is done in recent versions
|
|
|
2c033f |
+ * of qxl and allows displays to be aligned on the guest in the same order as
|
|
|
2c033f |
+ * they are aligned on the client.
|
|
|
2c033f |
+ */
|
|
|
2c033f |
+static gboolean
|
|
|
2c033f |
+make_suggested_config (MetaMonitorConfig *self,
|
|
|
2c033f |
+ MetaOutput *outputs,
|
|
|
2c033f |
+ unsigned n_outputs,
|
|
|
2c033f |
+ int max_width,
|
|
|
2c033f |
+ int max_height,
|
|
|
2c033f |
+ MetaConfiguration *config)
|
|
|
2c033f |
+{
|
|
|
2c033f |
+ unsigned int i;
|
|
|
2c033f |
+ MetaOutput *primary;
|
|
|
2c033f |
+ GList *region = NULL;
|
|
|
2c033f |
+
|
|
|
2c033f |
+ g_return_val_if_fail (config != NULL, FALSE);
|
|
|
2c033f |
+ primary = find_primary_output (outputs, n_outputs);
|
|
|
2c033f |
+
|
|
|
2c033f |
+ for (i = 0; i < n_outputs; i++)
|
|
|
2c033f |
+ {
|
|
|
2c033f |
+ gboolean is_primary = (&outputs[i] == primary);
|
|
|
2c033f |
+
|
|
|
2c033f |
+ if (outputs[i].suggested_x < 0 || outputs[i].suggested_y < 0)
|
|
|
2c033f |
+ return FALSE;
|
|
|
2c033f |
+
|
|
|
2c033f |
+ init_config_from_preferred_mode (&config->outputs[i], &outputs[i]);
|
|
|
2c033f |
+ config->outputs[i].is_primary = is_primary;
|
|
|
2c033f |
+
|
|
|
2c033f |
+ config->outputs[i].rect.x = outputs[i].suggested_x;
|
|
|
2c033f |
+ config->outputs[i].rect.y = outputs[i].suggested_y;
|
|
|
2c033f |
+
|
|
|
2c033f |
+ /* Reject the configuration if the suggested positions result in
|
|
|
2c033f |
+ * overlapping displays */
|
|
|
2c033f |
+ if (meta_rectangle_overlaps_with_region (region, &config->outputs[i].rect))
|
|
|
2c033f |
+ {
|
|
|
2c033f |
+ g_warning ("Overlapping outputs, rejecting suggested configuration");
|
|
|
2c033f |
+ g_list_free (region);
|
|
|
2c033f |
+ return FALSE;
|
|
|
2c033f |
+ }
|
|
|
2c033f |
+
|
|
|
2c033f |
+ region = g_list_prepend (region, &config->outputs[i].rect);
|
|
|
2c033f |
+ }
|
|
|
2c033f |
+
|
|
|
2c033f |
+ g_list_free (region);
|
|
|
2c033f |
+ return TRUE;
|
|
|
2c033f |
+}
|
|
|
2c033f |
+
|
|
|
2c033f |
static void
|
|
|
2c033f |
make_linear_config (MetaMonitorConfig *self,
|
|
|
2c033f |
MetaOutput *outputs,
|
|
|
2c033f |
@@ -1228,6 +1278,9 @@ make_default_config (MetaMonitorConfig *self,
|
|
|
2c033f |
return ret;
|
|
|
2c033f |
}
|
|
|
2c033f |
|
|
|
2c033f |
+ if (make_suggested_config (self, outputs, n_outputs, max_width, max_height, ret))
|
|
|
2c033f |
+ return ret;
|
|
|
2c033f |
+
|
|
|
2c033f |
if (use_stored_config &&
|
|
|
2c033f |
extend_stored_config (self, outputs, n_outputs, max_width, max_height, ret))
|
|
|
2c033f |
return ret;
|
|
|
2c033f |
diff --git a/src/backends/meta-monitor-manager.h b/src/backends/meta-monitor-manager.h
|
|
|
2c033f |
index 77ab938..0b81a4e 100644
|
|
|
2c033f |
--- a/src/backends/meta-monitor-manager.h
|
|
|
2c033f |
+++ b/src/backends/meta-monitor-manager.h
|
|
|
2c033f |
@@ -116,6 +116,8 @@ struct _MetaOutput
|
|
|
2c033f |
|
|
|
2c033f |
/* get a new preferred mode on hotplug events, to handle dynamic guest resizing */
|
|
|
2c033f |
gboolean hotplug_mode_update;
|
|
|
2c033f |
+ gint suggested_x;
|
|
|
2c033f |
+ gint suggested_y;
|
|
|
2c033f |
};
|
|
|
2c033f |
|
|
|
2c033f |
struct _MetaCRTC
|
|
|
2c033f |
diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c
|
|
|
2c033f |
index ad37df6..2e46276 100644
|
|
|
2c033f |
--- a/src/backends/native/meta-monitor-manager-kms.c
|
|
|
2c033f |
+++ b/src/backends/native/meta-monitor-manager-kms.c
|
|
|
2c033f |
@@ -410,6 +410,8 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
|
|
|
2c033f |
meta_output->name = make_output_name (connector);
|
|
|
2c033f |
meta_output->width_mm = connector->mmWidth;
|
|
|
2c033f |
meta_output->height_mm = connector->mmHeight;
|
|
|
2c033f |
+ meta_output->suggested_x = -1;
|
|
|
2c033f |
+ meta_output->suggested_y = -1;
|
|
|
2c033f |
|
|
|
2c033f |
switch (connector->subpixel)
|
|
|
2c033f |
{
|
|
|
2c033f |
diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
|
|
|
2c033f |
index 4c1b16c..2c6d65e 100644
|
|
|
2c033f |
--- a/src/backends/x11/meta-monitor-manager-xrandr.c
|
|
|
2c033f |
+++ b/src/backends/x11/meta-monitor-manager-xrandr.c
|
|
|
2c033f |
@@ -141,6 +141,34 @@ meta_monitor_transform_from_xrandr_all (Rotation rotation)
|
|
|
2c033f |
}
|
|
|
2c033f |
|
|
|
2c033f |
static gboolean
|
|
|
2c033f |
+output_get_integer_property (MetaMonitorManagerXrandr *manager_xrandr,
|
|
|
2c033f |
+ MetaOutput *output, const char *propname,
|
|
|
2c033f |
+ gint *value)
|
|
|
2c033f |
+{
|
|
|
2c033f |
+ gboolean exists = FALSE;
|
|
|
2c033f |
+ Atom atom, actual_type;
|
|
|
2c033f |
+ int actual_format;
|
|
|
2c033f |
+ unsigned long nitems, bytes_after;
|
|
|
2c033f |
+ unsigned char *buffer;
|
|
|
2c033f |
+
|
|
|
2c033f |
+ atom = XInternAtom (manager_xrandr->xdisplay, propname, False);
|
|
|
2c033f |
+ XRRGetOutputProperty (manager_xrandr->xdisplay,
|
|
|
2c033f |
+ (XID)output->winsys_id,
|
|
|
2c033f |
+ atom,
|
|
|
2c033f |
+ 0, G_MAXLONG, False, False, XA_INTEGER,
|
|
|
2c033f |
+ &actual_type, &actual_format,
|
|
|
2c033f |
+ &nitems, &bytes_after, &buffer);
|
|
|
2c033f |
+
|
|
|
2c033f |
+ exists = (actual_type == XA_INTEGER && actual_format == 32 && nitems == 1);
|
|
|
2c033f |
+
|
|
|
2c033f |
+ if (exists && value != NULL)
|
|
|
2c033f |
+ *value = ((int*)buffer)[0];
|
|
|
2c033f |
+
|
|
|
2c033f |
+ XFree (buffer);
|
|
|
2c033f |
+ return exists;
|
|
|
2c033f |
+}
|
|
|
2c033f |
+
|
|
|
2c033f |
+static gboolean
|
|
|
2c033f |
output_get_property_exists (MetaMonitorManagerXrandr *manager_xrandr,
|
|
|
2c033f |
MetaOutput *output, const char *propname)
|
|
|
2c033f |
{
|
|
|
2c033f |
@@ -357,6 +385,28 @@ output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
|
|
|
2c033f |
return output_get_property_exists (manager_xrandr, output, "hotplug_mode_update");
|
|
|
2c033f |
}
|
|
|
2c033f |
|
|
|
2c033f |
+static gint
|
|
|
2c033f |
+output_get_suggested_x (MetaMonitorManagerXrandr *manager_xrandr,
|
|
|
2c033f |
+ MetaOutput *output)
|
|
|
2c033f |
+{
|
|
|
2c033f |
+ gint val;
|
|
|
2c033f |
+ if (output_get_integer_property (manager_xrandr, output, "suggested X", &val))
|
|
|
2c033f |
+ return val;
|
|
|
2c033f |
+
|
|
|
2c033f |
+ return -1;
|
|
|
2c033f |
+}
|
|
|
2c033f |
+
|
|
|
2c033f |
+static gint
|
|
|
2c033f |
+output_get_suggested_y (MetaMonitorManagerXrandr *manager_xrandr,
|
|
|
2c033f |
+ MetaOutput *output)
|
|
|
2c033f |
+{
|
|
|
2c033f |
+ gint val;
|
|
|
2c033f |
+ if (output_get_integer_property (manager_xrandr, output, "suggested Y", &val))
|
|
|
2c033f |
+ return val;
|
|
|
2c033f |
+
|
|
|
2c033f |
+ return -1;
|
|
|
2c033f |
+}
|
|
|
2c033f |
+
|
|
|
2c033f |
static char *
|
|
|
2c033f |
get_xmode_name (XRRModeInfo *xmode)
|
|
|
2c033f |
{
|
|
|
2c033f |
@@ -545,6 +595,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
|
|
2c033f |
meta_output->height_mm = output->mm_height;
|
|
|
2c033f |
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
|
|
|
2c033f |
meta_output->hotplug_mode_update = output_get_hotplug_mode_update (manager_xrandr, meta_output);
|
|
|
2c033f |
+ meta_output->suggested_x = output_get_suggested_x (manager_xrandr, meta_output);
|
|
|
2c033f |
+ meta_output->suggested_y = output_get_suggested_y (manager_xrandr, meta_output);
|
|
|
2c033f |
|
|
|
2c033f |
meta_output->n_modes = output->nmode;
|
|
|
2c033f |
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
|
|
|
2c033f |
--
|
|
|
2c033f |
2.3.6
|
|
|
2c033f |
|
|
|
2c033f |
|
|
|
2c033f |
From d0607177b47d2e499ec822fb7aa4c55224f4c85a Mon Sep 17 00:00:00 2001
|
|
|
2c033f |
From: Jonathon Jongsma <jjongsma@redhat.com>
|
|
|
2c033f |
Date: Wed, 19 Nov 2014 10:56:27 -0600
|
|
|
2c033f |
Subject: [PATCH 4/4] monitor-manager: check framebuffer limits for all configs
|
|
|
2c033f |
|
|
|
2c033f |
Refactor make_default_config() to always sanity-check the configuration to
|
|
|
2c033f |
ensure that it fits within the framebuffer. Previously, this was only done
|
|
|
2c033f |
for the default linear configuration.
|
|
|
2c033f |
|
|
|
2c033f |
https://bugzilla.redhat.com/show_bug.cgi?id=1166319
|
|
|
2c033f |
---
|
|
|
2c033f |
src/backends/meta-monitor-config.c | 21 +++++++++++++--------
|
|
|
2c033f |
1 file changed, 13 insertions(+), 8 deletions(-)
|
|
|
2c033f |
|
|
|
2c033f |
diff --git a/src/backends/meta-monitor-config.c b/src/backends/meta-monitor-config.c
|
|
|
2c033f |
index a65c241..9e15989 100644
|
|
|
2c033f |
--- a/src/backends/meta-monitor-config.c
|
|
|
2c033f |
+++ b/src/backends/meta-monitor-config.c
|
|
|
2c033f |
@@ -1179,10 +1179,6 @@ make_linear_config (MetaMonitorConfig *self,
|
|
|
2c033f |
config->outputs[i].rect.x = x;
|
|
|
2c033f |
x += config->outputs[i].rect.width;
|
|
|
2c033f |
}
|
|
|
2c033f |
-
|
|
|
2c033f |
- /* Disable outputs that would go beyond framebuffer limits */
|
|
|
2c033f |
- if (config->outputs[i].rect.x + config->outputs[i].rect.width > max_width)
|
|
|
2c033f |
- config->outputs[i].enabled = FALSE;
|
|
|
2c033f |
}
|
|
|
2c033f |
}
|
|
|
2c033f |
|
|
|
2c033f |
@@ -1263,6 +1259,7 @@ make_default_config (MetaMonitorConfig *self,
|
|
|
2c033f |
gboolean use_stored_config)
|
|
|
2c033f |
{
|
|
|
2c033f |
MetaConfiguration *ret = NULL;
|
|
|
2c033f |
+ unsigned i;
|
|
|
2c033f |
|
|
|
2c033f |
ret = g_slice_new (MetaConfiguration);
|
|
|
2c033f |
make_config_key (ret, outputs, n_outputs, -1);
|
|
|
2c033f |
@@ -1272,21 +1269,29 @@ make_default_config (MetaMonitorConfig *self,
|
|
|
2c033f |
nothing else to do */
|
|
|
2c033f |
if (n_outputs == 1)
|
|
|
2c033f |
{
|
|
|
2c033f |
-
|
|
|
2c033f |
init_config_from_preferred_mode (&ret->outputs[0], &outputs[0]);
|
|
|
2c033f |
ret->outputs[0].is_primary = TRUE;
|
|
|
2c033f |
- return ret;
|
|
|
2c033f |
+ goto check_limits;
|
|
|
2c033f |
}
|
|
|
2c033f |
|
|
|
2c033f |
if (make_suggested_config (self, outputs, n_outputs, max_width, max_height, ret))
|
|
|
2c033f |
- return ret;
|
|
|
2c033f |
+ goto check_limits;
|
|
|
2c033f |
|
|
|
2c033f |
if (use_stored_config &&
|
|
|
2c033f |
extend_stored_config (self, outputs, n_outputs, max_width, max_height, ret))
|
|
|
2c033f |
- return ret;
|
|
|
2c033f |
+ goto check_limits;
|
|
|
2c033f |
|
|
|
2c033f |
make_linear_config (self, outputs, n_outputs, max_width, max_height, ret);
|
|
|
2c033f |
|
|
|
2c033f |
+check_limits:
|
|
|
2c033f |
+ /* Disable outputs that would go beyond framebuffer limits */
|
|
|
2c033f |
+ for (i = 0; i < n_outputs; i++)
|
|
|
2c033f |
+ {
|
|
|
2c033f |
+ if ((ret->outputs[i].rect.x + ret->outputs[i].rect.width > max_width)
|
|
|
2c033f |
+ || (ret->outputs[i].rect.y + ret->outputs[i].rect.height > max_height))
|
|
|
2c033f |
+ ret->outputs[i].enabled = FALSE;
|
|
|
2c033f |
+ }
|
|
|
2c033f |
+
|
|
|
2c033f |
return ret;
|
|
|
2c033f |
}
|
|
|
2c033f |
|
|
|
2c033f |
--
|
|
|
2c033f |
2.3.6
|
|
|
2c033f |
|