summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonas Ådahl <jadahl@gmail.com>2017-01-09 06:31:18 (GMT)
committerJonas Ådahl <jadahl@gmail.com>2017-01-25 08:28:55 (GMT)
commit644ee666f6750081b140e46b43367a7be2efe3a9 (patch)
tree613d2a30adcdca06f3f81a1d58ea7e9dcfb504e7
parentee0677a02121da4541a5897d0c5c26aef45a96f8 (diff)
downloadmutter-644ee666f6750081b140e46b43367a7be2efe3a9.zip
mutter-644ee666f6750081b140e46b43367a7be2efe3a9.tar.xz
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
-rw-r--r--src/Makefile.am2
-rw-r--r--src/backends/meta-monitor-config-manager.c525
-rw-r--r--src/backends/meta-monitor-config-manager.h74
-rw-r--r--src/backends/meta-monitor-manager-dummy.c62
-rw-r--r--src/backends/meta-monitor-manager-private.h14
-rw-r--r--src/backends/meta-monitor-manager.c243
-rw-r--r--src/backends/meta-monitor.c20
-rw-r--r--src/backends/meta-monitor.h5
-rw-r--r--src/backends/native/meta-monitor-manager-kms.c129
-rw-r--r--src/backends/x11/meta-monitor-manager-xrandr.c47
-rw-r--r--src/tests/meta-monitor-manager-test.c109
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;