[mutter] Introduce new monitor configuration system
- From: Jonas Ådahl <jadahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] Introduce new monitor configuration system
- Date: Wed, 25 Jan 2017 08:37:25 +0000 (UTC)
commit 644ee666f6750081b140e46b43367a7be2efe3a9
Author: Jonas Ådahl <jadahl gmail com>
Date: Mon Jan 9 14:31:18 2017 +0800
Introduce new monitor configuration system
The new monitor configuration system (MetaMonitorConfigManager) aims to
replace the current MetaMonitorConfig. The main difference between the
two is that MetaMonitorConfigManager works with higher level input
(MetaMonitor, MetaMonitorMode) instead of directly looking at the CRTC
and connector state. It still produces CRTC and connector configuration
later applied by the respective backends.
Other difference the new system aims to introduce is that the
configuration system doesn't manipulate the monitor manager state; that
responsibility is left for the monitor manager to handle (it only
manages configuration and creates CRTC/connector assignments, it
doesn't apply anything).
The new configuration system allows backends to not rely on deriving the
current configuration from the CRTC/connector state, as this may no longer be
possible (i.e. when using KMS and multiple framebuffers).
The MetaMonitorConfigManager system is so far disabled by default, as
it does not yet have all the features of the old system, but eventually
it will replace MetaMonitorConfig which will at that point be removed.
This will make it possible to remove old hacks introduced due to
limitations in the old system.
https://bugzilla.gnome.org/show_bug.cgi?id=777732
src/Makefile.am | 2 +
src/backends/meta-monitor-config-manager.c | 525 ++++++++++++++++++++++++
src/backends/meta-monitor-config-manager.h | 74 ++++
src/backends/meta-monitor-manager-dummy.c | 62 +++-
src/backends/meta-monitor-manager-private.h | 14 +-
src/backends/meta-monitor-manager.c | 243 +++++++++++-
src/backends/meta-monitor.c | 20 +
src/backends/meta-monitor.h | 5 +
src/backends/native/meta-monitor-manager-kms.c | 129 +++++--
src/backends/x11/meta-monitor-manager-xrandr.c | 47 ++-
src/tests/meta-monitor-manager-test.c | 109 +++++-
11 files changed, 1166 insertions(+), 64 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index d5af5b2..fdccbe6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -105,6 +105,8 @@ libmutter_la_SOURCES = \
backends/meta-logical-monitor.h \
backends/meta-monitor-config.c \
backends/meta-monitor-config.h \
+ backends/meta-monitor-config-manager.c \
+ backends/meta-monitor-config-manager.h \
backends/meta-monitor.c \
backends/meta-monitor.h \
backends/meta-monitor-private.h \
diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c
new file mode 100644
index 0000000..6445f84
--- /dev/null
+++ b/src/backends/meta-monitor-config-manager.c
@@ -0,0 +1,525 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/*
+ * Copyright (C) 2016 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "backends/meta-monitor-config-manager.h"
+
+#include "backends/meta-monitor-manager-private.h"
+
+struct _MetaMonitorConfigManager
+{
+ GObject parent;
+
+ MetaMonitorManager *monitor_manager;
+
+ MetaMonitorsConfig *current_config;
+};
+
+G_DEFINE_TYPE (MetaMonitorConfigManager, meta_monitor_config_manager,
+ G_TYPE_OBJECT)
+
+G_DEFINE_TYPE (MetaMonitorsConfig, meta_monitors_config,
+ G_TYPE_OBJECT)
+
+MetaMonitorConfigManager *
+meta_monitor_config_manager_new (MetaMonitorManager *monitor_manager)
+{
+ MetaMonitorConfigManager *config_manager;
+
+ config_manager = g_object_new (META_TYPE_MONITOR_CONFIG_MANAGER, NULL);
+ config_manager->monitor_manager = monitor_manager;
+
+ return config_manager;
+}
+
+static gboolean
+is_crtc_assigned (MetaCrtc *crtc,
+ GPtrArray *crtc_infos)
+{
+ unsigned int i;
+
+ for (i = 0; i < crtc_infos->len; i++)
+ {
+ MetaCrtcInfo *assigned_crtc_info = g_ptr_array_index (crtc_infos, i);
+
+ if (assigned_crtc_info->crtc == crtc)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static MetaCrtc *
+find_unassigned_crtc (MetaOutput *output,
+ GPtrArray *crtc_infos)
+{
+ unsigned int i;
+
+ for (i = 0; i < output->n_possible_crtcs; i++)
+ {
+ MetaCrtc *crtc = output->possible_crtcs[i];
+
+ if (is_crtc_assigned (crtc, crtc_infos))
+ continue;
+
+ return crtc;
+ }
+
+ return NULL;
+}
+
+typedef struct
+{
+ MetaLogicalMonitorConfig *logical_monitor_config;
+ MetaMonitorConfig *monitor_config;
+ GPtrArray *crtc_infos;
+ GPtrArray *output_infos;
+} MonitorAssignmentData;
+
+static gboolean
+assign_monitor_crtc (MetaMonitor *monitor,
+ MetaMonitorMode *mode,
+ MetaMonitorCrtcMode *monitor_crtc_mode,
+ gpointer user_data,
+ GError **error)
+{
+ MonitorAssignmentData *data = user_data;
+ MetaOutput *output;
+ MetaCrtc *crtc;
+ MetaCrtcInfo *crtc_info;
+ MetaOutputInfo *output_info;
+ MetaMonitorConfig *first_monitor_config;
+ gboolean assign_output_as_primary;
+ gboolean assign_output_as_presentation;
+
+ output = monitor_crtc_mode->output;
+
+ crtc = find_unassigned_crtc (output, data->crtc_infos);
+ if (!crtc)
+ {
+ MetaMonitorSpec *monitor_spec = meta_monitor_get_spec (monitor);
+
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "No available CRTC for monitor '%s %s' not found",
+ monitor_spec->vendor, monitor_spec->product);
+ return FALSE;
+ }
+
+ crtc_info = g_slice_new0 (MetaCrtcInfo);
+ *crtc_info = (MetaCrtcInfo) {
+ .crtc = crtc,
+ .mode = monitor_crtc_mode->crtc_mode,
+ .x = monitor_crtc_mode->x,
+ .y = monitor_crtc_mode->y,
+ .transform = META_MONITOR_TRANSFORM_NORMAL,
+ .outputs = g_ptr_array_new ()
+ };
+ g_ptr_array_add (crtc_info->outputs, output);
+
+ /*
+ * Currently, MetaCrtcInfo are deliberately offset incorrectly to carry over
+ * logical monitor location inside the MetaCrtc struct, when in fact this
+ * depends on the framebuffer configuration. This will eventually be negated
+ * when setting the actual KMS mode.
+ *
+ * TODO: Remove this hack when we don't need to rely on MetaCrtc to pass
+ * logical monitor state.
+ */
+ crtc_info->x += data->logical_monitor_config->layout.x;
+ crtc_info->y += data->logical_monitor_config->layout.y;
+
+ /*
+ * Only one output can be marked as primary (due to Xrandr limitation),
+ * so only mark the main output of the first monitor in the logical monitor
+ * as such.
+ */
+ first_monitor_config = data->logical_monitor_config->monitor_configs->data;
+ if (data->monitor_config == first_monitor_config &&
+ meta_monitor_get_main_output (monitor) == output)
+ assign_output_as_primary = TRUE;
+ else
+ assign_output_as_primary = FALSE;
+
+ if (data->logical_monitor_config->is_presentation)
+ assign_output_as_presentation = TRUE;
+ else
+ assign_output_as_presentation = FALSE;
+
+ output_info = g_slice_new0 (MetaOutputInfo);
+ *output_info = (MetaOutputInfo) {
+ .output = output,
+ .is_primary = assign_output_as_primary,
+ .is_presentation = assign_output_as_presentation,
+ .is_underscanning = output->is_underscanning
+ };
+
+ g_ptr_array_add (data->crtc_infos, crtc_info);
+ g_ptr_array_add (data->output_infos, output_info);
+
+ return TRUE;
+}
+
+static gboolean
+assign_monitor_crtcs (MetaMonitorManager *manager,
+ MetaLogicalMonitorConfig *logical_monitor_config,
+ MetaMonitorConfig *monitor_config,
+ GPtrArray *crtc_infos,
+ GPtrArray *output_infos,
+ GError **error)
+{
+ MetaMonitorSpec *monitor_spec = monitor_config->monitor_spec;
+ MetaMonitorModeSpec *monitor_mode_spec = monitor_config->mode_spec;
+ MetaMonitor *monitor;
+ MetaMonitorMode *monitor_mode;
+ MonitorAssignmentData data;
+
+ monitor = meta_monitor_manager_get_monitor_from_spec (manager, monitor_spec);
+ if (!monitor)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Configured monitor '%s %s' not found",
+ monitor_spec->vendor, monitor_spec->product);
+ return FALSE;
+ }
+
+ monitor_mode = meta_monitor_get_mode_from_spec (monitor, monitor_mode_spec);
+ if (!monitor_mode)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Invalid mode %dx%d (%f) for monitor '%s %s'",
+ monitor_mode_spec->width, monitor_mode_spec->height,
+ monitor_mode_spec->refresh_rate,
+ monitor_spec->vendor, monitor_spec->product);
+ return FALSE;
+ }
+
+ data = (MonitorAssignmentData) {
+ .logical_monitor_config = logical_monitor_config,
+ .monitor_config = monitor_config,
+ .crtc_infos = crtc_infos,
+ .output_infos = output_infos
+ };
+ if (!meta_monitor_mode_foreach_crtc (monitor, monitor_mode,
+ assign_monitor_crtc,
+ &data,
+ error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+assign_logical_monitor_crtcs (MetaMonitorManager *manager,
+ MetaLogicalMonitorConfig *logical_monitor_config,
+ GPtrArray *crtc_infos,
+ GPtrArray *output_infos,
+ GError **error)
+{
+ GList *l;
+
+ for (l = logical_monitor_config->monitor_configs; l; l = l->next)
+ {
+ MetaMonitorConfig *monitor_config = l->data;
+
+ if (!assign_monitor_crtcs (manager,
+ logical_monitor_config,
+ monitor_config,
+ crtc_infos, output_infos,
+ error))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+meta_monitor_config_manager_assign (MetaMonitorManager *manager,
+ MetaMonitorsConfig *config,
+ GPtrArray **out_crtc_infos,
+ GPtrArray **out_output_infos,
+ GError **error)
+{
+ GPtrArray *crtc_infos;
+ GPtrArray *output_infos;
+ GList *l;
+
+ crtc_infos =
+ g_ptr_array_new_with_free_func ((GDestroyNotify) meta_crtc_info_free);
+ output_infos =
+ g_ptr_array_new_with_free_func ((GDestroyNotify) meta_output_info_free);
+
+ for (l = config->logical_monitor_configs; l; l = l->next)
+ {
+ MetaLogicalMonitorConfig *logical_monitor_config = l->data;
+
+ if (!assign_logical_monitor_crtcs (manager, logical_monitor_config,
+ crtc_infos, output_infos,
+ error))
+ {
+ g_ptr_array_free (crtc_infos, TRUE);
+ g_ptr_array_free (output_infos, TRUE);
+ return FALSE;
+ }
+ }
+
+ *out_crtc_infos = crtc_infos;
+ *out_output_infos = output_infos;
+
+ return TRUE;
+}
+
+static MetaMonitor *
+find_monitor_with_highest_preferred_resolution (MetaMonitorManager *monitor_manager)
+{
+ GList *monitors;
+ GList *l;
+ int largest_area = 0;
+ MetaMonitor *largest_monitor = NULL;
+
+ monitors = meta_monitor_manager_get_monitors (monitor_manager);
+ for (l = monitors; l; l = l->next)
+ {
+ MetaMonitor *monitor = l->data;
+ MetaMonitorMode *mode;
+ int width, height;
+ int area;
+
+ mode = meta_monitor_get_preferred_mode (monitor);
+ meta_monitor_mode_get_resolution (mode, &width, &height);
+ area = width * height;
+
+ if (area > largest_area)
+ {
+ largest_area = area;
+ largest_monitor = monitor;
+ }
+ }
+
+ return largest_monitor;
+}
+
+/*
+ * Tries to find the primary monitor as reported by the underlying system;
+ * or failing that, a monitor looks to be the laptop panel; or failing that, the
+ * monitor with the highest preferred resolution.
+ */
+static MetaMonitor *
+find_primary_monitor (MetaMonitorManager *monitor_manager)
+{
+ MetaMonitor *monitor;
+
+ monitor = meta_monitor_manager_get_primary_monitor (monitor_manager);
+ if (monitor)
+ return monitor;
+
+ monitor = meta_monitor_manager_get_laptop_panel (monitor_manager);
+ if (monitor)
+ return monitor;
+
+ return find_monitor_with_highest_preferred_resolution (monitor_manager);
+}
+
+static MetaMonitorConfig *
+create_monitor_config (MetaMonitor *monitor,
+ MetaMonitorMode *mode)
+{
+ MetaMonitorSpec *monitor_spec;
+ MetaMonitorModeSpec *mode_spec;
+ MetaMonitorConfig *monitor_config;
+
+ monitor_spec = meta_monitor_get_spec (monitor);
+ mode_spec = meta_monitor_mode_get_spec (mode);
+
+ monitor_config = g_new0 (MetaMonitorConfig, 1);
+ *monitor_config = (MetaMonitorConfig) {
+ .monitor_spec = meta_monitor_spec_clone (monitor_spec),
+ .mode_spec = g_memdup (mode_spec, sizeof (MetaMonitorModeSpec))
+ };
+
+ return monitor_config;
+}
+
+static MetaLogicalMonitorConfig *
+create_preferred_logical_monitor_config (MetaMonitor *monitor,
+ int x,
+ int y)
+{
+ MetaMonitorMode *mode;
+ int width, height;
+ MetaMonitorConfig *monitor_config;
+ MetaLogicalMonitorConfig *logical_monitor_config;
+
+ mode = meta_monitor_get_preferred_mode (monitor);
+ meta_monitor_mode_get_resolution (mode, &width, &height);
+ monitor_config = create_monitor_config (monitor, mode);
+
+ logical_monitor_config = g_new0 (MetaLogicalMonitorConfig, 1);
+ *logical_monitor_config = (MetaLogicalMonitorConfig) {
+ .layout = (MetaRectangle) {
+ .x = x,
+ .y = y,
+ .width = width,
+ .height = height
+ },
+ .monitor_configs = g_list_append (NULL, monitor_config)
+ };
+
+ return logical_monitor_config;
+}
+
+MetaMonitorsConfig *
+meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_manager)
+{
+ MetaMonitorManager *monitor_manager = config_manager->monitor_manager;
+ MetaMonitor *primary_monitor;
+ MetaMonitorsConfig *config;
+ MetaLogicalMonitorConfig *primary_logical_monitor_config;
+ int x;
+ GList *monitors;
+ GList *l;
+
+ primary_monitor = find_primary_monitor (monitor_manager);
+
+ config = g_object_new (META_TYPE_MONITORS_CONFIG, NULL);
+
+ primary_logical_monitor_config =
+ create_preferred_logical_monitor_config (primary_monitor, 0, 0);
+ primary_logical_monitor_config->is_primary = TRUE;
+ config->logical_monitor_configs =
+ g_list_append (NULL, primary_logical_monitor_config);
+
+ x = primary_logical_monitor_config->layout.width;
+ monitors = meta_monitor_manager_get_monitors (monitor_manager);
+ for (l = monitors; l; l = l->next)
+ {
+ MetaMonitor *monitor = l->data;
+ MetaLogicalMonitorConfig *logical_monitor_config;
+
+ if (monitor == primary_monitor)
+ continue;
+
+ logical_monitor_config =
+ create_preferred_logical_monitor_config (monitor, x, 0);
+ config->logical_monitor_configs =
+ g_list_append (config->logical_monitor_configs, logical_monitor_config);
+
+ x += logical_monitor_config->layout.width;
+ }
+
+ return config;
+}
+
+MetaMonitorsConfig *
+meta_monitor_config_manager_create_fallback (MetaMonitorConfigManager *config_manager)
+{
+ MetaMonitorManager *monitor_manager = config_manager->monitor_manager;
+ MetaMonitor *primary_monitor;
+ MetaMonitorsConfig *config;
+ MetaLogicalMonitorConfig *primary_logical_monitor_config;
+
+ primary_monitor = find_primary_monitor (monitor_manager);
+
+ config = g_object_new (META_TYPE_MONITORS_CONFIG, NULL);
+
+ primary_logical_monitor_config =
+ create_preferred_logical_monitor_config (primary_monitor, 0, 0);
+ primary_logical_monitor_config->is_primary = TRUE;
+ config->logical_monitor_configs =
+ g_list_append (NULL, primary_logical_monitor_config);
+
+ return config;
+}
+
+void
+meta_monitor_config_manager_set_current (MetaMonitorConfigManager *config_manager,
+ MetaMonitorsConfig *config)
+{
+ g_set_object (&config_manager->current_config, config);
+}
+
+MetaMonitorsConfig *
+meta_monitor_config_manager_get_current (MetaMonitorConfigManager *config_manager)
+{
+ return config_manager->current_config;
+}
+
+static void
+meta_monitor_config_manager_dispose (GObject *object)
+{
+ MetaMonitorConfigManager *config_manager =
+ META_MONITOR_CONFIG_MANAGER (object);
+
+ g_clear_object (&config_manager->current_config);
+
+ G_OBJECT_CLASS (meta_monitor_config_manager_parent_class)->dispose (object);
+}
+
+static void
+meta_monitor_config_manager_init (MetaMonitorConfigManager *config_manager)
+{
+}
+
+static void
+meta_monitor_config_manager_class_init (MetaMonitorConfigManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = meta_monitor_config_manager_dispose;
+}
+
+static void
+meta_monitor_config_free (MetaMonitorConfig *monitor_config)
+{
+ meta_monitor_spec_free (monitor_config->monitor_spec);
+ g_free (monitor_config->mode_spec);
+ g_free (monitor_config);
+}
+
+static void
+meta_logical_monitor_config_free (MetaLogicalMonitorConfig *logical_monitor_config)
+{
+ g_list_free_full (logical_monitor_config->monitor_configs,
+ (GDestroyNotify) meta_monitor_config_free);
+ g_free (logical_monitor_config);
+}
+
+static void
+meta_monitors_config_finalize (GObject *object)
+{
+ MetaMonitorsConfig *config = META_MONITORS_CONFIG (object);
+
+ g_list_free_full (config->logical_monitor_configs,
+ (GDestroyNotify) meta_logical_monitor_config_free);
+}
+
+static void
+meta_monitors_config_init (MetaMonitorsConfig *config)
+{
+}
+
+static void
+meta_monitors_config_class_init (MetaMonitorsConfigClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = meta_monitors_config_finalize;
+}
diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h
new file mode 100644
index 0000000..1d0771c
--- /dev/null
+++ b/src/backends/meta-monitor-config-manager.h
@@ -0,0 +1,74 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/*
+ * Copyright (C) 2016 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef META_MONITOR_CONFIG_MANAGER_H
+#define META_MONITOR_CONFIG_MANAGER_H
+
+#include "backends/meta-monitor.h"
+#include "backends/meta-monitor-manager-private.h"
+
+#define META_TYPE_MONITOR_CONFIG_MANAGER (meta_monitor_config_manager_get_type ())
+G_DECLARE_FINAL_TYPE (MetaMonitorConfigManager, meta_monitor_config_manager,
+ META, MONITOR_CONFIG_MANAGER, GObject)
+
+typedef struct _MetaMonitorConfig
+{
+ MetaMonitorSpec *monitor_spec;
+ MetaMonitorModeSpec *mode_spec;
+} MetaMonitorConfig;
+
+typedef struct _MetaLogicalMonitorConfig
+{
+ MetaRectangle layout;
+ GList *monitor_configs;
+ gboolean is_primary;
+ gboolean is_presentation;
+} MetaLogicalMonitorConfig;
+
+struct _MetaMonitorsConfig
+{
+ GObject parent;
+
+ GList *logical_monitor_configs;
+};
+
+#define META_TYPE_MONITORS_CONFIG (meta_monitors_config_get_type ())
+G_DECLARE_FINAL_TYPE (MetaMonitorsConfig, meta_monitors_config,
+ META, MONITORS_CONFIG, GObject)
+
+MetaMonitorConfigManager * meta_monitor_config_manager_new (MetaMonitorManager *monitor_manager);
+
+gboolean meta_monitor_config_manager_assign (MetaMonitorManager *manager,
+ MetaMonitorsConfig *config,
+ GPtrArray **crtc_infos,
+ GPtrArray **output_infos,
+ GError **error);
+
+MetaMonitorsConfig * meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_manager);
+
+MetaMonitorsConfig * meta_monitor_config_manager_create_fallback (MetaMonitorConfigManager *config_manager);
+
+void meta_monitor_config_manager_set_current (MetaMonitorConfigManager *config_manager,
+ MetaMonitorsConfig *config);
+
+MetaMonitorsConfig * meta_monitor_config_manager_get_current (MetaMonitorConfigManager *config_manager);
+
+#endif /* META_MONITOR_CONFIG_MANAGER_H */
diff --git a/src/backends/meta-monitor-manager-dummy.c b/src/backends/meta-monitor-manager-dummy.c
index 71fb46c..bd003e2 100644
--- a/src/backends/meta-monitor-manager-dummy.c
+++ b/src/backends/meta-monitor-manager-dummy.c
@@ -30,6 +30,7 @@
#include <stdlib.h>
#include <meta/util.h>
+#include "backends/meta-monitor-config-manager.h"
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
@@ -172,20 +173,25 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
static void
meta_monitor_manager_dummy_ensure_initial_config (MetaMonitorManager *manager)
{
- meta_monitor_manager_ensure_configured (manager);
+ MetaMonitorsConfig *config;
- meta_monitor_manager_update_logical_state_derived (manager);
+ config = meta_monitor_manager_ensure_configured (manager);
+
+ if (manager->config_manager)
+ meta_monitor_manager_update_logical_state (manager, config);
+ else
+ meta_monitor_manager_update_logical_state_derived (manager);
}
static void
-meta_monitor_manager_dummy_apply_config (MetaMonitorManager *manager,
- MetaCrtcInfo **crtcs,
- unsigned int n_crtcs,
- MetaOutputInfo **outputs,
- unsigned int n_outputs)
+apply_crtc_assignments (MetaMonitorManager *manager,
+ MetaCrtcInfo **crtcs,
+ unsigned int n_crtcs,
+ MetaOutputInfo **outputs,
+ unsigned int n_outputs)
{
- unsigned i;
- int screen_width = 0, screen_height = 0;
+ unsigned i;
+ int screen_width = 0, screen_height = 0;
for (i = 0; i < n_crtcs; i++)
{
@@ -287,6 +293,43 @@ meta_monitor_manager_dummy_apply_config (MetaMonitorManager *manager,
manager->screen_width = screen_width;
manager->screen_height = screen_height;
+}
+
+static gboolean
+meta_monitor_manager_dummy_apply_monitors_config (MetaMonitorManager *manager,
+ MetaMonitorsConfig *config,
+ GError **error)
+{
+ GPtrArray *crtc_infos;
+ GPtrArray *output_infos;
+
+ if (!meta_monitor_config_manager_assign (manager, config,
+ &crtc_infos, &output_infos,
+ error))
+ return FALSE;
+
+ apply_crtc_assignments (manager,
+ (MetaCrtcInfo **) crtc_infos->pdata,
+ crtc_infos->len,
+ (MetaOutputInfo **) output_infos->pdata,
+ output_infos->len);
+
+ g_ptr_array_free (crtc_infos, TRUE);
+ g_ptr_array_free (output_infos, TRUE);
+
+ meta_monitor_manager_rebuild (manager, config);
+
+ return TRUE;
+}
+
+static void
+meta_monitor_manager_dummy_apply_config (MetaMonitorManager *manager,
+ MetaCrtcInfo **crtcs,
+ unsigned int n_crtcs,
+ MetaOutputInfo **outputs,
+ unsigned int n_outputs)
+{
+ apply_crtc_assignments (manager, crtcs, n_crtcs, outputs, n_outputs);
meta_monitor_manager_rebuild_derived (manager);
}
@@ -298,6 +341,7 @@ meta_monitor_manager_dummy_class_init (MetaMonitorManagerDummyClass *klass)
manager_class->read_current = meta_monitor_manager_dummy_read_current;
manager_class->ensure_initial_config = meta_monitor_manager_dummy_ensure_initial_config;
+ manager_class->apply_monitors_config = meta_monitor_manager_dummy_apply_monitors_config;
manager_class->apply_configuration = meta_monitor_manager_dummy_apply_config;
}
diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h
index 74b1ba2..e66b4ee 100644
--- a/src/backends/meta-monitor-manager-private.h
+++ b/src/backends/meta-monitor-manager-private.h
@@ -48,6 +48,8 @@
#include "meta-cursor.h"
typedef struct _MetaMonitorConfig MetaMonitorConfig;
+typedef struct _MetaMonitorConfigManager MetaMonitorConfigManager;
+typedef struct _MetaMonitorsConfig MetaMonitorsConfig;
typedef struct _MetaMonitor MetaMonitor;
typedef struct _MetaMonitorNormal MetaMonitorNormal;
@@ -284,6 +286,8 @@ struct _MetaMonitorManager
int persistent_timeout_id;
MetaMonitorConfig *legacy_config;
+ MetaMonitorConfigManager *config_manager;
+
GnomePnpIds *pnp_ids;
};
@@ -300,6 +304,10 @@ struct _MetaMonitorManagerClass
void (*ensure_initial_config) (MetaMonitorManager *);
+ gboolean (*apply_monitors_config) (MetaMonitorManager *,
+ MetaMonitorsConfig *,
+ GError **);
+
void (*apply_configuration) (MetaMonitorManager *,
MetaCrtcInfo **,
unsigned int ,
@@ -334,6 +342,8 @@ struct _MetaMonitorManagerClass
};
+void meta_monitor_manager_rebuild (MetaMonitorManager *manager,
+ MetaMonitorsConfig *config);
void meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager);
int meta_monitor_manager_get_num_logical_monitors (MetaMonitorManager *manager);
@@ -413,8 +423,10 @@ void meta_monitor_manager_tiled_monitor_added (MetaMonitorManager
void meta_monitor_manager_tiled_monitor_removed (MetaMonitorManager *manager,
MetaMonitor *monitor);
-void meta_monitor_manager_ensure_configured (MetaMonitorManager *manager);
+MetaMonitorsConfig * meta_monitor_manager_ensure_configured (MetaMonitorManager *manager);
+void meta_monitor_manager_update_logical_state (MetaMonitorManager *manager,
+ MetaMonitorsConfig *config);
void meta_monitor_manager_update_logical_state_derived (MetaMonitorManager *manager);
void meta_monitor_manager_clear_output (MetaOutput *output);
diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
index cb76fd1..940c5bd 100644
--- a/src/backends/meta-monitor-manager.c
+++ b/src/backends/meta-monitor-manager.c
@@ -39,6 +39,7 @@
#include "meta-monitor-config.h"
#include "backends/meta-logical-monitor.h"
#include "backends/meta-monitor.h"
+#include "backends/meta-monitor-config-manager.h"
#include "backends/x11/meta-monitor-manager-xrandr.h"
#include "meta-backend-private.h"
@@ -106,6 +107,85 @@ logical_monitor_from_layout (MetaMonitorManager *manager,
return NULL;
}
+static MetaLogicalMonitor *
+create_logical_monitor_from_config (MetaMonitorManager *manager,
+ MetaLogicalMonitorConfig *logical_monitor_config,
+ int monitor_number)
+{
+ MetaLogicalMonitor *logical_monitor;
+ GList *monitor_configs;
+ MetaMonitorConfig *first_monitor_config;
+ MetaMonitorSpec *first_monitor_spec;
+ MetaMonitor *first_monitor;
+ GList *l;
+
+ monitor_configs = logical_monitor_config->monitor_configs;
+ first_monitor_config = g_list_first (monitor_configs)->data;
+ first_monitor_spec = first_monitor_config->monitor_spec;
+ first_monitor =
+ meta_monitor_manager_get_monitor_from_spec (manager, first_monitor_spec);
+
+ /* Create logical monitor from the first monitor. */
+ logical_monitor = meta_logical_monitor_new (first_monitor,
+ logical_monitor_config->layout.x,
+ logical_monitor_config->layout.y,
+ monitor_number);
+
+ /* Add the other monitors. */
+ for (l = monitor_configs->next; l; l = l->next)
+ {
+ MetaMonitorConfig *monitor_config = l->data;
+ MetaMonitorSpec *monitor_spec;
+ MetaMonitor *monitor;
+
+ monitor_spec = monitor_config->monitor_spec;
+ monitor = meta_monitor_manager_get_monitor_from_spec (manager,
+ monitor_spec);
+
+ meta_logical_monitor_add_monitor (logical_monitor, monitor);
+ }
+
+ return logical_monitor;
+}
+
+static void
+meta_monitor_manager_rebuild_logical_monitors (MetaMonitorManager *manager,
+ MetaMonitorsConfig *config)
+{
+ GList *logical_monitors = NULL;
+ GList *l;
+ int monitor_number = 0;
+ MetaLogicalMonitor *primary_logical_monitor = NULL;
+
+ for (l = config->logical_monitor_configs; l; l = l->next)
+ {
+ MetaLogicalMonitorConfig *logical_monitor_config = l->data;
+ MetaLogicalMonitor *logical_monitor;
+
+ logical_monitor =
+ create_logical_monitor_from_config (manager,
+ logical_monitor_config,
+ monitor_number);
+ monitor_number++;
+
+ if (logical_monitor_config->is_primary)
+ primary_logical_monitor = logical_monitor;
+
+ logical_monitors = g_list_append (logical_monitors, logical_monitor);
+ }
+
+ /*
+ * If no monitor was marked as primary, fall back on marking the first
+ * logical monitor the primary one.
+ */
+ if (!primary_logical_monitor && logical_monitors)
+ primary_logical_monitor = g_list_first (logical_monitors)->data;
+
+ manager->logical_monitors = logical_monitors;
+ meta_monitor_manager_set_primary_logical_monitor (manager,
+ primary_logical_monitor);
+}
+
static void
derive_monitor_position (MetaMonitor *monitor,
int *x,
@@ -206,6 +286,17 @@ meta_monitor_manager_ensure_initial_config (MetaMonitorManager *manager)
META_MONITOR_MANAGER_GET_CLASS (manager)->ensure_initial_config (manager);
}
+static gboolean
+meta_monitor_manager_apply_monitors_config (MetaMonitorManager *manager,
+ MetaMonitorsConfig *config,
+ GError **error)
+{
+ MetaMonitorManagerClass *manager_class =
+ META_MONITOR_MANAGER_GET_CLASS (manager);
+
+ return manager_class->apply_monitors_config (manager, config, error);
+}
+
gboolean
meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager)
{
@@ -229,10 +320,52 @@ legacy_ensure_configured (MetaMonitorManager *manager)
meta_monitor_config_make_default (manager->legacy_config, manager);
}
-void
+MetaMonitorsConfig *
meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
{
- legacy_ensure_configured (manager);
+ MetaMonitorsConfig *config = NULL;
+ GError *error = NULL;
+
+ if (!manager->config_manager)
+ {
+ legacy_ensure_configured (manager);
+ return NULL;
+ }
+
+ config = meta_monitor_config_manager_create_linear (manager->config_manager);
+ if (!meta_monitor_manager_apply_monitors_config (manager, config, &error))
+ {
+ g_clear_object (&config);
+ g_warning ("Failed to use linear monitor configuration: %s",
+ error->message);
+ g_clear_error (&error);
+ }
+ else
+ {
+ goto done;
+ }
+
+ config = meta_monitor_config_manager_create_fallback (manager->config_manager);
+ if (!meta_monitor_manager_apply_monitors_config (manager, config, &error))
+ {
+ g_clear_object (&config);
+ g_warning ("Failed to use fallback monitor configuration: %s",
+ error->message);
+ g_clear_error (&error);
+ }
+ else
+ {
+ goto done;
+ }
+
+done:
+ if (!config)
+ meta_fatal ("Failed to find any working monitor configuration, giving up");
+
+ meta_monitor_config_manager_set_current (manager->config_manager, config);
+ g_object_unref (config);
+
+ return config;
}
static void
@@ -245,7 +378,10 @@ meta_monitor_manager_constructed (GObject *object)
manager->in_init = TRUE;
- manager->legacy_config = meta_monitor_config_new ();
+ if (g_strcmp0 (g_getenv ("MUTTER_USE_CONFIG_MANAGER"), "1") == 0)
+ manager->config_manager = meta_monitor_config_manager_new (manager);
+ else
+ manager->legacy_config = meta_monitor_config_new ();
meta_monitor_manager_read_current_state (manager);
@@ -353,6 +489,8 @@ meta_monitor_manager_dispose (GObject *object)
manager->dbus_name_id = 0;
}
+ g_clear_object (&manager->config_manager);
+
G_OBJECT_CLASS (meta_monitor_manager_parent_class)->dispose (object);
}
@@ -704,7 +842,10 @@ save_config_timeout (gpointer user_data)
{
MetaMonitorManager *manager = user_data;
- legacy_restore_previous_config (manager);
+ if (manager->config_manager)
+ g_assert (!"missing implementation");
+ else
+ legacy_restore_previous_config (manager);
manager->persistent_timeout_id = 0;
return G_SOURCE_REMOVE;
@@ -728,6 +869,14 @@ meta_monitor_manager_legacy_handle_apply_configuration (MetaDBusDisplayConfig *
guint output_index;
GPtrArray *crtc_infos, *output_infos;
+ if (manager->config_manager)
+ {
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
+ G_DBUS_ERROR_ACCESS_DENIED,
+ "Used old configuration API with new configuration system");
+ return TRUE;
+ }
+
if (serial != manager->serial)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
@@ -968,7 +1117,10 @@ meta_monitor_manager_confirm_configuration (MetaMonitorManager *manager,
g_source_remove (manager->persistent_timeout_id);
manager->persistent_timeout_id = 0;
- legacy_confirm_configuration (manager, ok);
+ if (manager->config_manager)
+ g_assert (!"not implemented");
+ else
+ legacy_confirm_configuration (manager, ok);
}
static gboolean
@@ -1544,6 +1696,79 @@ meta_monitor_manager_notify_monitors_changed (MetaMonitorManager *manager)
}
static void
+set_logical_monitor_modes (MetaMonitorManager *manager,
+ MetaLogicalMonitorConfig *logical_monitor_config)
+{
+ GList *l;
+
+ for (l = logical_monitor_config->monitor_configs; l; l = l->next)
+ {
+ MetaMonitorConfig *monitor_config = l->data;
+ MetaMonitorSpec *monitor_spec;
+ MetaMonitor *monitor;
+ MetaMonitorModeSpec *monitor_mode_spec;
+ MetaMonitorMode *monitor_mode;
+
+ monitor_spec = monitor_config->monitor_spec;
+ monitor = meta_monitor_manager_get_monitor_from_spec (manager,
+ monitor_spec);
+ monitor_mode_spec = monitor_config->mode_spec;
+ monitor_mode = meta_monitor_get_mode_from_spec (monitor,
+ monitor_mode_spec);
+
+ meta_monitor_set_current_mode (monitor, monitor_mode);
+ }
+}
+
+static void
+meta_monitor_manager_update_monitor_modes (MetaMonitorManager *manager,
+ MetaMonitorsConfig *config)
+{
+ GList *l;
+
+ for (l = config->logical_monitor_configs; l; l = l->next)
+ {
+ MetaLogicalMonitorConfig *logical_monitor_config = l->data;
+
+ set_logical_monitor_modes (manager, logical_monitor_config);
+ }
+
+ for (l = manager->monitors; l; l = l->next)
+ {
+ MetaMonitor *monitor = l->data;
+
+ if (!meta_monitor_get_logical_monitor (monitor))
+ meta_monitor_set_current_mode (monitor, NULL);
+ }
+}
+
+void
+meta_monitor_manager_update_logical_state (MetaMonitorManager *manager,
+ MetaMonitorsConfig *config)
+{
+ meta_monitor_manager_rebuild_logical_monitors (manager, config);
+ meta_monitor_manager_update_monitor_modes (manager, config);
+}
+
+void
+meta_monitor_manager_rebuild (MetaMonitorManager *manager,
+ MetaMonitorsConfig *config)
+{
+ GList *old_logical_monitors;
+
+ if (manager->in_init)
+ return;
+
+ old_logical_monitors = manager->logical_monitors;
+
+ meta_monitor_manager_update_logical_state (manager, config);
+
+ meta_monitor_manager_notify_monitors_changed (manager);
+
+ g_list_free_full (old_logical_monitors, g_object_unref);
+}
+
+static void
meta_monitor_manager_update_monitor_modes_derived (MetaMonitorManager *manager)
{
GList *l;
@@ -1664,7 +1889,13 @@ legacy_on_hotplug (MetaMonitorManager *manager)
void
meta_monitor_manager_on_hotplug (MetaMonitorManager *manager)
{
- legacy_on_hotplug (manager);
+ if (manager->legacy_config)
+ {
+ legacy_on_hotplug (manager);
+ return;
+ }
+
+ meta_monitor_manager_ensure_configured (manager);
}
static gboolean
diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c
index be8f309..0fb1063 100644
--- a/src/backends/meta-monitor.c
+++ b/src/backends/meta-monitor.c
@@ -581,6 +581,17 @@ meta_monitor_get_spec (MetaMonitor *monitor)
return priv->spec;
}
+MetaLogicalMonitor *
+meta_monitor_get_logical_monitor (MetaMonitor *monitor)
+{
+ MetaOutput *output = meta_monitor_get_main_output (monitor);
+
+ if (output->crtc)
+ return output->crtc->logical_monitor;
+ else
+ return NULL;
+}
+
static gboolean
meta_monitor_mode_spec_equals (MetaMonitorModeSpec *monitor_mode_spec,
MetaMonitorModeSpec *other_monitor_mode_spec)
@@ -668,6 +679,15 @@ meta_monitor_derive_current_mode (MetaMonitor *monitor)
priv->current_mode = current_mode;
}
+void
+meta_monitor_set_current_mode (MetaMonitor *monitor,
+ MetaMonitorMode *mode)
+{
+ MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
+
+ priv->current_mode = mode;
+}
+
GList *
meta_monitor_get_modes (MetaMonitor *monitor)
{
diff --git a/src/backends/meta-monitor.h b/src/backends/meta-monitor.h
index c784d0f..83ca24e 100644
--- a/src/backends/meta-monitor.h
+++ b/src/backends/meta-monitor.h
@@ -115,6 +115,8 @@ const char * meta_monitor_get_serial (MetaMonitor *monitor);
uint32_t meta_monitor_tiled_get_tile_group_id (MetaMonitorTiled *monitor_tiled);
+MetaLogicalMonitor * meta_monitor_get_logical_monitor (MetaMonitor *monitor);
+
MetaMonitorMode * meta_monitor_get_mode_from_spec (MetaMonitor *monitor,
MetaMonitorModeSpec *monitor_mode_spec);
@@ -124,6 +126,9 @@ MetaMonitorMode * meta_monitor_get_current_mode (MetaMonitor *monitor);
void meta_monitor_derive_current_mode (MetaMonitor *monitor);
+void meta_monitor_set_current_mode (MetaMonitor *monitor,
+ MetaMonitorMode *mode);
+
GList * meta_monitor_get_modes (MetaMonitor *monitor);
MetaMonitorModeSpec * meta_monitor_mode_get_spec (MetaMonitorMode *monitor_mode);
diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c
index 9b985d0..de8889e 100644
--- a/src/backends/native/meta-monitor-manager-kms.c
+++ b/src/backends/native/meta-monitor-manager-kms.c
@@ -25,6 +25,7 @@
#include "meta-monitor-manager-kms.h"
#include "meta-monitor-config.h"
+#include "meta-monitor-config-manager.h"
#include "meta-backend-private.h"
#include "meta-renderer-native.h"
@@ -1178,24 +1179,6 @@ init_outputs (MetaMonitorManager *manager,
}
static void
-calculate_screen_size (MetaMonitorManager *manager)
-{
- unsigned int i;
- int width = 0, height = 0;
-
- for (i = 0; i < manager->n_crtcs; i++)
- {
- MetaCrtc *crtc = &manager->crtcs[i];
-
- width = MAX (width, crtc->rect.x + crtc->rect.width);
- height = MAX (height, crtc->rect.y + crtc->rect.height);
- }
-
- manager->screen_width = width;
- manager->screen_height = height;
-}
-
-static void
meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
@@ -1220,8 +1203,6 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
init_crtcs (manager, resources);
init_outputs (manager, resources);
- calculate_screen_size (manager);
-
drmModeFreeResources (resources);
}
@@ -1340,23 +1321,26 @@ set_underscan (MetaMonitorManagerKms *manager_kms,
static void
meta_monitor_manager_kms_ensure_initial_config (MetaMonitorManager *manager)
{
- meta_monitor_manager_ensure_configured (manager);
+ MetaMonitorsConfig *config;
- meta_monitor_manager_update_logical_state_derived (manager);
+ config = meta_monitor_manager_ensure_configured (manager);
+
+ if (manager->config_manager)
+ meta_monitor_manager_update_logical_state (manager, config);
+ else
+ meta_monitor_manager_update_logical_state_derived (manager);
}
static void
-meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
- MetaCrtcInfo **crtcs,
- unsigned int n_crtcs,
- MetaOutputInfo **outputs,
- unsigned int n_outputs)
+apply_crtc_assignments (MetaMonitorManager *manager,
+ MetaCrtcInfo **crtcs,
+ unsigned int n_crtcs,
+ MetaOutputInfo **outputs,
+ unsigned int n_outputs)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
unsigned i;
- int screen_width, screen_height;
- screen_width = 0; screen_height = 0;
for (i = 0; i < n_crtcs; i++)
{
MetaCrtcInfo *crtc_info = crtcs[i];
@@ -1393,9 +1377,6 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
height = mode->height;
}
- screen_width = MAX (screen_width, crtc_info->x + width);
- screen_height = MAX (screen_height, crtc_info->y + height);
-
crtc->rect.x = crtc_info->x;
crtc->rect.y = crtc_info->y;
crtc->rect.width = width;
@@ -1479,10 +1460,93 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
output->crtc = NULL;
output->is_primary = FALSE;
}
+}
+
+static void
+update_screen_size (MetaMonitorManager *manager,
+ MetaMonitorsConfig *config)
+{
+ GList *l;
+ int screen_width = 0;
+ int screen_height = 0;
+
+ for (l = config->logical_monitor_configs; l; l = l->next)
+ {
+ MetaLogicalMonitorConfig *logical_monitor_config = l->data;
+ int right_edge;
+ int bottom_edge;
+
+ right_edge = (logical_monitor_config->layout.width +
+ logical_monitor_config->layout.x);
+ if (right_edge > screen_width)
+ screen_width = right_edge;
+
+ bottom_edge = (logical_monitor_config->layout.height +
+ logical_monitor_config->layout.y);
+ if (bottom_edge > screen_height)
+ screen_height = bottom_edge;
+ }
manager->screen_width = screen_width;
manager->screen_height = screen_height;
+}
+
+static gboolean
+meta_monitor_manager_kms_apply_monitors_config (MetaMonitorManager *manager,
+ MetaMonitorsConfig *config,
+ GError **error)
+{
+ GPtrArray *crtc_infos;
+ GPtrArray *output_infos;
+
+ if (!meta_monitor_config_manager_assign (manager, config,
+ &crtc_infos, &output_infos,
+ error))
+ return FALSE;
+
+ apply_crtc_assignments (manager,
+ (MetaCrtcInfo **) crtc_infos->pdata,
+ crtc_infos->len,
+ (MetaOutputInfo **) output_infos->pdata,
+ output_infos->len);
+
+ g_ptr_array_free (crtc_infos, TRUE);
+ g_ptr_array_free (output_infos, TRUE);
+
+ update_screen_size (manager, config);
+ meta_monitor_manager_rebuild (manager, config);
+
+ return TRUE;
+}
+
+static void
+legacy_calculate_screen_size (MetaMonitorManager *manager)
+{
+ unsigned int i;
+ int width = 0, height = 0;
+
+ for (i = 0; i < manager->n_crtcs; i++)
+ {
+ MetaCrtc *crtc = &manager->crtcs[i];
+
+ width = MAX (width, crtc->rect.x + crtc->rect.width);
+ height = MAX (height, crtc->rect.y + crtc->rect.height);
+ }
+
+ manager->screen_width = width;
+ manager->screen_height = height;
+}
+
+static void
+meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
+ MetaCrtcInfo **crtcs,
+ unsigned int n_crtcs,
+ MetaOutputInfo **outputs,
+ unsigned int n_outputs)
+{
+ apply_crtc_assignments (manager, crtcs, n_crtcs, outputs, n_outputs);
+ legacy_calculate_screen_size (manager);
meta_monitor_manager_rebuild_derived (manager);
}
@@ -1931,6 +1995,7 @@ meta_monitor_manager_kms_class_init (MetaMonitorManagerKmsClass *klass)
manager_class->read_current = meta_monitor_manager_kms_read_current;
manager_class->read_edid = meta_monitor_manager_kms_read_edid;
manager_class->ensure_initial_config = meta_monitor_manager_kms_ensure_initial_config;
+ manager_class->apply_monitors_config = meta_monitor_manager_kms_apply_monitors_config;
manager_class->apply_configuration = meta_monitor_manager_kms_apply_configuration;
manager_class->set_power_save_mode = meta_monitor_manager_kms_set_power_save_mode;
manager_class->get_crtc_gamma = meta_monitor_manager_kms_get_crtc_gamma;
diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
index b3f0dd4..df608a3 100644
--- a/src/backends/x11/meta-monitor-manager-xrandr.c
+++ b/src/backends/x11/meta-monitor-manager-xrandr.c
@@ -42,6 +42,7 @@
#include <meta/main.h>
#include <meta/errors.h>
#include "meta-monitor-config.h"
+#include "backends/meta-monitor-config-manager.h"
#include "backends/meta-logical-monitor.h"
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
@@ -1060,11 +1061,11 @@ output_set_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
}
static void
-meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
- MetaCrtcInfo **crtcs,
- unsigned int n_crtcs,
- MetaOutputInfo **outputs,
- unsigned int n_outputs)
+apply_crtc_assignments (MetaMonitorManager *manager,
+ MetaCrtcInfo **crtcs,
+ unsigned int n_crtcs,
+ MetaOutputInfo **outputs,
+ unsigned int n_outputs)
{
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
unsigned i;
@@ -1294,6 +1295,41 @@ meta_monitor_manager_xrandr_ensure_initial_config (MetaMonitorManager *manager)
meta_monitor_manager_update_logical_state_derived (manager);
}
+static gboolean
+meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *manager,
+ MetaMonitorsConfig *config,
+ GError **error)
+{
+ GPtrArray *crtc_infos;
+ GPtrArray *output_infos;
+
+ if (!meta_monitor_config_manager_assign (manager, config,
+ &crtc_infos, &output_infos,
+ error))
+ return FALSE;
+
+ apply_crtc_assignments (manager,
+ (MetaCrtcInfo **) crtc_infos->pdata,
+ crtc_infos->len,
+ (MetaOutputInfo **) output_infos->pdata,
+ output_infos->len);
+
+ g_ptr_array_free (crtc_infos, TRUE);
+ g_ptr_array_free (output_infos, TRUE);
+
+ return TRUE;
+}
+
+static void
+meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
+ MetaCrtcInfo **crtcs,
+ unsigned int n_crtcs,
+ MetaOutputInfo **outputs,
+ unsigned int n_outputs)
+{
+ apply_crtc_assignments (manager, crtcs, n_crtcs, outputs, n_outputs);
+}
+
static void
meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
MetaOutput *output,
@@ -1587,6 +1623,7 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
manager_class->read_current = meta_monitor_manager_xrandr_read_current;
manager_class->read_edid = meta_monitor_manager_xrandr_read_edid;
manager_class->ensure_initial_config = meta_monitor_manager_xrandr_ensure_initial_config;
+ manager_class->apply_monitors_config = meta_monitor_manager_xrandr_apply_monitors_config;
manager_class->apply_configuration = meta_monitor_manager_xrandr_apply_configuration;
manager_class->set_power_save_mode = meta_monitor_manager_xrandr_set_power_save_mode;
manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight;
diff --git a/src/tests/meta-monitor-manager-test.c b/src/tests/meta-monitor-manager-test.c
index 22b9073..aa1b21f 100644
--- a/src/tests/meta-monitor-manager-test.c
+++ b/src/tests/meta-monitor-manager-test.c
@@ -21,6 +21,8 @@
#include "tests/meta-monitor-manager-test.h"
+#include "backends/meta-monitor-config-manager.h"
+
struct _MetaMonitorManagerTest
{
MetaMonitorManager parent;
@@ -86,20 +88,24 @@ meta_monitor_manager_test_read_current (MetaMonitorManager *manager)
static void
meta_monitor_manager_test_ensure_initial_config (MetaMonitorManager *manager)
{
- meta_monitor_manager_ensure_configured (manager);
+ MetaMonitorsConfig *config;
+
+ config = meta_monitor_manager_ensure_configured (manager);
- meta_monitor_manager_update_logical_state_derived (manager);
+ if (manager->config_manager)
+ meta_monitor_manager_update_logical_state (manager, config);
+ else
+ meta_monitor_manager_update_logical_state_derived (manager);
}
static void
-meta_monitor_manager_test_apply_configuration (MetaMonitorManager *manager,
- MetaCrtcInfo **crtcs,
- unsigned int n_crtcs,
- MetaOutputInfo **outputs,
- unsigned int n_outputs)
+apply_crtc_assignments (MetaMonitorManager *manager,
+ MetaCrtcInfo **crtcs,
+ unsigned int n_crtcs,
+ MetaOutputInfo **outputs,
+ unsigned int n_outputs)
{
unsigned int i;
- int screen_width = 0, screen_height = 0;
for (i = 0; i < n_crtcs; i++)
{
@@ -142,9 +148,6 @@ meta_monitor_manager_test_apply_configuration (MetaMonitorManager *manager,
crtc->current_mode = mode;
crtc->transform = crtc_info->transform;
- screen_width = MAX (screen_width, crtc_info->x + width);
- screen_height = MAX (screen_height, crtc_info->y + height);
-
for (j = 0; j < crtc_info->outputs->len; j++)
{
output = ((MetaOutput**)crtc_info->outputs->pdata)[j];
@@ -198,10 +201,93 @@ meta_monitor_manager_test_apply_configuration (MetaMonitorManager *manager,
output->crtc = NULL;
output->is_primary = FALSE;
}
+}
+
+static void
+update_screen_size (MetaMonitorManager *manager,
+ MetaMonitorsConfig *config)
+{
+ GList *l;
+ int screen_width = 0;
+ int screen_height = 0;
+
+ for (l = config->logical_monitor_configs; l; l = l->next)
+ {
+ MetaLogicalMonitorConfig *logical_monitor_config = l->data;
+ int right_edge;
+ int bottom_edge;
+
+ right_edge = (logical_monitor_config->layout.width +
+ logical_monitor_config->layout.x);
+ if (right_edge > screen_width)
+ screen_width = right_edge;
+
+ bottom_edge = (logical_monitor_config->layout.height +
+ logical_monitor_config->layout.y);
+ if (bottom_edge > screen_height)
+ screen_height = bottom_edge;
+ }
manager->screen_width = screen_width;
manager->screen_height = screen_height;
+}
+
+static gboolean
+meta_monitor_manager_test_apply_monitors_config (MetaMonitorManager *manager,
+ MetaMonitorsConfig *config,
+ GError **error)
+{
+ GPtrArray *crtc_infos;
+ GPtrArray *output_infos;
+
+ if (!meta_monitor_config_manager_assign (manager, config,
+ &crtc_infos,
+ &output_infos,
+ error))
+ return FALSE;
+
+ apply_crtc_assignments (manager,
+ (MetaCrtcInfo **) crtc_infos->pdata,
+ crtc_infos->len,
+ (MetaOutputInfo **) output_infos->pdata,
+ output_infos->len);
+
+ g_ptr_array_free (crtc_infos, TRUE);
+ g_ptr_array_free (output_infos, TRUE);
+
+ update_screen_size (manager, config);
+ meta_monitor_manager_rebuild (manager, config);
+ return TRUE;
+}
+
+static void
+legacy_calculate_screen_size (MetaMonitorManager *manager)
+{
+ unsigned int i;
+ int width = 0, height = 0;
+
+ for (i = 0; i < manager->n_crtcs; i++)
+ {
+ MetaCrtc *crtc = &manager->crtcs[i];
+
+ width = MAX (width, crtc->rect.x + crtc->rect.width);
+ height = MAX (height, crtc->rect.y + crtc->rect.height);
+ }
+
+ manager->screen_width = width;
+ manager->screen_height = height;
+}
+
+static void
+meta_monitor_manager_test_apply_configuration (MetaMonitorManager *manager,
+ MetaCrtcInfo **crtcs,
+ unsigned int n_crtcs,
+ MetaOutputInfo **outputs,
+ unsigned int n_outputs)
+{
+ apply_crtc_assignments (manager, crtcs, n_crtcs, outputs, n_outputs);
+ legacy_calculate_screen_size (manager);
meta_monitor_manager_rebuild_derived (manager);
}
@@ -249,6 +335,7 @@ meta_monitor_manager_test_class_init (MetaMonitorManagerTestClass *klass)
manager_class->read_current = meta_monitor_manager_test_read_current;
manager_class->ensure_initial_config = meta_monitor_manager_test_ensure_initial_config;
+ manager_class->apply_monitors_config = meta_monitor_manager_test_apply_monitors_config;
manager_class->apply_configuration = meta_monitor_manager_test_apply_configuration;
manager_class->tiled_monitor_added = meta_monitor_manager_test_tiled_monitor_added;
manager_class->tiled_monitor_removed = meta_monitor_manager_test_tiled_monitor_removed;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]