diff --git a/src/Makefile.am b/src/Makefile.am index d5af5b2a6..fdccbe682 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 000000000..6445f840c --- /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 000000000..1d0771c13 --- /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 71fb46ce3..bd003e247 100644 --- a/src/backends/meta-monitor-manager-dummy.c +++ b/src/backends/meta-monitor-manager-dummy.c @@ -30,6 +30,7 @@ #include #include +#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 74b1ba2e1..e66b4ee96 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 cb76fd13d..940c5bdb3 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 @@ -1543,6 +1695,79 @@ meta_monitor_manager_notify_monitors_changed (MetaMonitorManager *manager) g_signal_emit_by_name (manager, "monitors-changed"); } +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) { @@ -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 be8f309c0..0fb1063ab 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 c784d0f12..83ca24ee7 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 9b985d017..de8889eaa 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" @@ -1177,24 +1178,6 @@ init_outputs (MetaMonitorManager *manager, detect_and_setup_output_clones (manager, resources); } -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) { @@ -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 b3f0dd4de..df608a3da 100644 --- a/src/backends/x11/meta-monitor-manager-xrandr.c +++ b/src/backends/x11/meta-monitor-manager-xrandr.c @@ -42,6 +42,7 @@ #include #include #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 22b907375..aa1b21f35 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; - 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_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;