From d0529b7482770c7d9ae3dcd581be3a3e65ac9748 Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Wed, 24 Jul 2013 18:01:31 +0200 Subject: [PATCH] MonitorConfig: add CRTC assignment Ripped off libgnome-desktop, trimming the parts that checked that the configuration was plausible, as that should be done in gnome-control-center before asking mutter for a change. https://bugzilla.gnome.org/show_bug.cgi?id=705670 --- src/core/monitor-config.c | 381 +++++++++++++++++++++++++++++++++++-- src/core/monitor-private.h | 48 ++++- src/core/monitor.c | 176 ++++++++++------- 3 files changed, 510 insertions(+), 95 deletions(-) diff --git a/src/core/monitor-config.c b/src/core/monitor-config.c index da4f8a080..d6ab967f0 100644 --- a/src/core/monitor-config.c +++ b/src/core/monitor-config.c @@ -25,6 +25,15 @@ * 02111-1307, USA. */ +/* + * Portions of this file are derived from gnome-desktop/libgnome-desktop/gnome-rr-config.c + * + * Copyright 2007, 2008, Red Hat, Inc. + * Copyright 2010 Giovanni Campagna + * + * Author: Soren Sandmann + */ + #include "config.h" #include @@ -90,6 +99,11 @@ struct _MetaMonitorConfigClass { G_DEFINE_TYPE (MetaMonitorConfig, meta_monitor_config, G_TYPE_OBJECT); +static gboolean meta_monitor_config_assign_crtcs (MetaConfiguration *config, + MetaMonitorManager *manager, + GPtrArray *crtcs, + GPtrArray *outputs); + static void free_output_key (MetaOutputKey *key) { @@ -774,35 +788,37 @@ meta_monitor_config_get_stored (MetaMonitorConfig *self, return stored; } -static void -make_crtcs (MetaConfiguration *config, - MetaMonitorManager *manager, - GVariant **crtcs, - GVariant **outputs) -{ - *crtcs = NULL; - *outputs = NULL; - /* FIXME */ -} - -static void +static gboolean apply_configuration (MetaMonitorConfig *self, MetaConfiguration *config, MetaMonitorManager *manager, gboolean stored) { - GVariant *crtcs, *outputs; - - make_crtcs (config, manager, &crtcs, &outputs); - meta_monitor_manager_apply_configuration (manager, crtcs, outputs); + GPtrArray *crtcs, *outputs; + + crtcs = g_ptr_array_new_full (config->n_outputs, (GDestroyNotify)meta_crtc_info_free); + outputs = g_ptr_array_new_full (config->n_outputs, (GDestroyNotify)meta_output_info_free); + + if (!meta_monitor_config_assign_crtcs (config, manager, crtcs, outputs)) + { + g_ptr_array_unref (crtcs); + g_ptr_array_unref (outputs); + + return FALSE; + } + + meta_monitor_manager_apply_configuration (manager, + (MetaCRTCInfo**)crtcs->pdata, crtcs->len, + (MetaOutputInfo**)outputs->pdata, outputs->len); if (self->current && !self->current_is_stored) config_free (self->current); self->current = config; self->current_is_stored = stored; - g_variant_unref (crtcs); - g_variant_unref (outputs); + g_ptr_array_unref (crtcs); + g_ptr_array_unref (outputs); + return TRUE; } gboolean @@ -818,8 +834,7 @@ meta_monitor_config_apply_stored (MetaMonitorConfig *self, if (stored) { - apply_configuration (self, stored, manager, TRUE); - return TRUE; + return apply_configuration (self, stored, manager, TRUE); } else return FALSE; @@ -1039,3 +1054,329 @@ meta_monitor_config_make_persistent (MetaMonitorConfig *self) meta_monitor_config_save (self); } + +/* + * CRTC assignment + */ +typedef struct +{ + MetaConfiguration *config; + MetaMonitorManager *manager; + GHashTable *info; +} CrtcAssignment; + +static gboolean +output_can_clone (MetaOutput *output, + MetaOutput *clone) +{ + unsigned int i; + + for (i = 0; i < output->n_possible_clones; i++) + if (output->possible_clones[i] == clone) + return TRUE; + + return FALSE; +} + +static gboolean +can_clone (MetaCRTCInfo *info, + MetaOutput *output) +{ + unsigned int i; + + for (i = 0; i < info->outputs->len; ++i) + { + MetaOutput *clone = info->outputs->pdata[i]; + + if (!output_can_clone (clone, output)) + return FALSE; + } + + return TRUE; +} + +static gboolean +crtc_can_drive_output (MetaCRTC *crtc, + MetaOutput *output) +{ + unsigned int i; + + for (i = 0; i < output->n_possible_crtcs; i++) + if (output->possible_crtcs[i] == crtc) + return TRUE; + + return FALSE; +} + +static gboolean +output_supports_mode (MetaOutput *output, + MetaMonitorMode *mode) +{ + unsigned int i; + + for (i = 0; i < output->n_modes; i++) + if (output->modes[i] == mode) + return TRUE; + + return FALSE; +} + +static gboolean +crtc_assignment_assign (CrtcAssignment *assign, + MetaCRTC *crtc, + MetaMonitorMode *mode, + int x, + int y, + enum wl_output_transform transform, + MetaOutput *output) +{ + MetaCRTCInfo *info = g_hash_table_lookup (assign->info, crtc); + + if (!crtc_can_drive_output (crtc, output)) + return FALSE; + + if (!output_supports_mode (output, mode)) + return FALSE; + + if ((crtc->all_transforms & (1 << transform)) == 0) + return FALSE; + + if (info) + { + if (!(info->mode == mode && + info->x == x && + info->y == y && + info->transform == transform)) + return FALSE; + + if (!can_clone (info, output)) + return FALSE; + + g_ptr_array_add (info->outputs, output); + return TRUE; + } + else + { + MetaCRTCInfo *info = g_slice_new0 (MetaCRTCInfo); + + info->crtc = crtc; + info->mode = mode; + info->x = x; + info->y = y; + info->transform = transform; + info->outputs = g_ptr_array_new (); + + g_ptr_array_add (info->outputs, output); + g_hash_table_insert (assign->info, crtc, info); + + return TRUE; + } +} + +static void +crtc_assignment_unassign (CrtcAssignment *assign, + MetaCRTC *crtc, + MetaOutput *output) +{ + MetaCRTCInfo *info = g_hash_table_lookup (assign->info, crtc); + + if (info) + { + g_ptr_array_remove (info->outputs, output); + + if (info->outputs->len == 0) + g_hash_table_remove (assign->info, crtc); + } +} + +static MetaOutput * +find_output_by_key (MetaOutput *outputs, + unsigned int n_outputs, + MetaOutputKey *key) +{ + unsigned int i; + + for (i = 0; i < n_outputs; i++) + { + if (strcmp (outputs[i].name, key->connector) == 0) + { + /* This should be checked a lot earlier! */ + + g_warn_if_fail (strcmp (outputs[i].vendor, key->vendor) == 0 && + strcmp (outputs[i].product, key->product) == 0 && + strcmp (outputs[i].serial, key->serial) == 0); + return &outputs[i]; + } + } + + /* Just to satisfy GCC - this is a fatal error if occurs */ + return NULL; +} + +/* Check whether the given set of settings can be used + * at the same time -- ie. whether there is an assignment + * of CRTC's to outputs. + * + * Brute force - the number of objects involved is small + * enough that it doesn't matter. + */ +static gboolean +real_assign_crtcs (CrtcAssignment *assignment, + unsigned int output_num) +{ + MetaMonitorMode *modes; + MetaCRTC *crtcs; + MetaOutput *outputs; + unsigned int n_crtcs, n_modes, n_outputs; + MetaOutputKey *output_key; + MetaOutputConfig *output_config; + unsigned int i; + gboolean success; + + if (output_num == assignment->config->n_outputs) + return TRUE; + + output_key = &assignment->config->keys[output_num]; + output_config = &assignment->config->outputs[output_num]; + + /* It is always allowed for an output to be turned off */ + if (!output_config->enabled) + return real_assign_crtcs (assignment, output_num + 1); + + meta_monitor_manager_get_resources (assignment->manager, + &modes, &n_modes, + &crtcs, &n_crtcs, + &outputs, &n_outputs); + + success = FALSE; + + for (i = 0; i < n_crtcs; i++) + { + MetaCRTC *crtc = &crtcs[i]; + unsigned int pass; + + /* Make two passes, one where frequencies must match, then + * one where they don't have to + */ + for (pass = 0; pass < 2; pass++) + { + MetaOutput *output = find_output_by_key (outputs, n_outputs, output_key); + unsigned int j; + + for (j = 0; j < n_modes; j++) + { + MetaMonitorMode *mode = &modes[j]; + int width, height; + + if (meta_monitor_transform_is_rotated (output_config->transform)) + { + width = mode->height; + height = mode->width; + } + else + { + width = mode->width; + height = mode->height; + } + + if (width == output_config->rect.width && + height == output_config->rect.height && + (pass == 1 || mode->refresh_rate == output_config->refresh_rate)) + { + meta_verbose ("CRTC %ld: trying mode %dx%d@%fHz with output at %dx%d@%fHz (transform %d) (pass %d)\n", + crtc->crtc_id, + mode->width, mode->height, mode->refresh_rate, + output_config->rect.width, output_config->rect.height, output_config->refresh_rate, + output_config->transform, + pass); + + + if (crtc_assignment_assign (assignment, crtc, &modes[j], + output_config->rect.x, output_config->rect.y, + output_config->transform, + output)) + { + if (real_assign_crtcs (assignment, output_num + 1)) + { + success = TRUE; + goto out; + } + + crtc_assignment_unassign (assignment, crtc, output); + } + } + } + } + } + +out: + if (!success) + meta_warning ("Could not assign CRTC to outputs, ignoring configuration\n"); + + return success; +} + +static gboolean +meta_monitor_config_assign_crtcs (MetaConfiguration *config, + MetaMonitorManager *manager, + GPtrArray *crtcs, + GPtrArray *outputs) +{ + CrtcAssignment assignment; + GHashTableIter iter; + MetaCRTC *crtc; + MetaCRTCInfo *info; + unsigned int i; + MetaOutput *all_outputs; + unsigned int n_outputs; + + assignment.config = config; + assignment.manager = manager; + assignment.info = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)meta_crtc_info_free); + + if (!real_assign_crtcs (&assignment, 0)) + { + g_hash_table_destroy (assignment.info); + return FALSE; + } + + g_hash_table_iter_init (&iter, assignment.info); + while (g_hash_table_iter_next (&iter, (void**)&crtc, (void**)&info)) + { + g_hash_table_iter_steal (&iter); + g_ptr_array_add (crtcs, info); + } + + all_outputs = meta_monitor_manager_get_outputs (manager, + &n_outputs); + g_assert (n_outputs == config->n_outputs); + + for (i = 0; i < n_outputs; i++) + { + MetaOutputInfo *output_info = g_slice_new (MetaOutputInfo); + MetaOutputConfig *output_config = &config->outputs[0]; + + output_info->output = find_output_by_key (all_outputs, n_outputs, + &config->keys[0]); + output_info->is_primary = output_config->is_primary; + output_info->is_presentation = output_config->is_presentation; + + g_ptr_array_add (outputs, output_info); + } + + g_hash_table_destroy (assignment.info); + return TRUE; +} + +void +meta_crtc_info_free (MetaCRTCInfo *info) +{ + g_ptr_array_free (info->outputs, TRUE); + g_slice_free (MetaCRTCInfo, info); +} + +void +meta_output_info_free (MetaOutputInfo *info) +{ + g_slice_free (MetaOutputInfo, info); +} diff --git a/src/core/monitor-private.h b/src/core/monitor-private.h index 1576182f3..efbafd726 100644 --- a/src/core/monitor-private.h +++ b/src/core/monitor-private.h @@ -65,6 +65,8 @@ typedef struct _MetaOutput MetaOutput; typedef struct _MetaCRTC MetaCRTC; typedef struct _MetaMonitorMode MetaMonitorMode; typedef struct _MetaMonitorInfo MetaMonitorInfo; +typedef struct _MetaCRTCInfo MetaCRTCInfo; +typedef struct _MetaOutputInfo MetaOutputInfo; struct _MetaOutput { @@ -161,6 +163,33 @@ struct _MetaMonitorInfo glong output_id; }; +/* + * MetaCRTCInfo: + * This represents the writable part of a CRTC, as deserialized from DBus + * or built by MetaMonitorConfig + * + * Note: differently from the other structures in this file, MetaCRTCInfo + * is handled by pointer. This is to accomodate the usage in MetaMonitorConfig + */ +struct _MetaCRTCInfo { + MetaCRTC *crtc; + MetaMonitorMode *mode; + int x; + int y; + enum wl_output_transform transform; + GPtrArray *outputs; +}; + +/* + * MetaOutputInfo: + * this is the same as MetaOutputInfo, but for CRTCs + */ +struct _MetaOutputInfo { + MetaOutput *output; + gboolean is_primary; + gboolean is_presentation; +}; + #define META_TYPE_MONITOR_MANAGER (meta_monitor_manager_get_type ()) #define META_MONITOR_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER, MetaMonitorManager)) #define META_MONITOR_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER, MetaMonitorManagerClass)) @@ -182,6 +211,14 @@ MetaMonitorInfo *meta_monitor_manager_get_monitor_infos (MetaMonitorManager * MetaOutput *meta_monitor_manager_get_outputs (MetaMonitorManager *manager, unsigned int *n_outputs); +void meta_monitor_manager_get_resources (MetaMonitorManager *manager, + MetaMonitorMode **modes, + unsigned int *n_modes, + MetaCRTC **crtcs, + unsigned int *n_crtcs, + MetaOutput **outputs, + unsigned int *n_outputs); + int meta_monitor_manager_get_primary_index (MetaMonitorManager *manager); gboolean meta_monitor_manager_handle_xevent (MetaMonitorManager *manager, @@ -191,9 +228,11 @@ void meta_monitor_manager_get_screen_size (MetaMonitorManager * int *width, int *height); -void meta_monitor_manager_apply_configuration (MetaMonitorManager *manager, - GVariant *crtcs, - GVariant *outputs); +void meta_monitor_manager_apply_configuration (MetaMonitorManager *manager, + MetaCRTCInfo **crtcs, + unsigned int n_crtcs, + MetaOutputInfo **outputs, + unsigned int n_outputs); #define META_TYPE_MONITOR_CONFIG (meta_monitor_config_get_type ()) #define META_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfig)) @@ -222,6 +261,9 @@ void meta_monitor_config_update_current (MetaMonitorConfig *confi MetaMonitorManager *manager); void meta_monitor_config_make_persistent (MetaMonitorConfig *config); +void meta_crtc_info_free (MetaCRTCInfo *info); +void meta_output_info_free (MetaOutputInfo *info); + /* Returns true if transform causes width and height to be inverted This is true for the odd transforms in the enum */ static inline gboolean diff --git a/src/core/monitor.c b/src/core/monitor.c index 867a1e81e..3c34b916a 100644 --- a/src/core/monitor.c +++ b/src/core/monitor.c @@ -1160,22 +1160,20 @@ wl_transform_to_xrandr (enum wl_output_transform transform) static void apply_config_xrandr (MetaMonitorManager *manager, - GVariantIter *crtcs, - GVariantIter *outputs) + MetaCRTCInfo **crtcs, + unsigned int n_crtcs, + MetaOutputInfo **outputs, + unsigned int n_outputs) { - GVariant *nested_outputs, *properties; - guint crtc_id, output_id, transform; - int new_mode, x, y; unsigned i; - while (g_variant_iter_loop (crtcs, "(uiiiu@aua{sv})", - &crtc_id, &new_mode, &x, &y, - &transform, &nested_outputs, NULL)) + for (i = 0; i < n_crtcs; i++) { - MetaCRTC *crtc = &manager->crtcs[crtc_id]; + MetaCRTCInfo *crtc_info = crtcs[i]; + MetaCRTC *crtc = crtc_info->crtc; crtc->is_dirty = TRUE; - if (new_mode == -1) + if (crtc_info->mode == NULL) { XRRSetCrtcConfig (manager->xdisplay, manager->resources, @@ -1190,54 +1188,47 @@ apply_config_xrandr (MetaMonitorManager *manager, { MetaMonitorMode *mode; XID *outputs; - int i, n_outputs; - guint output_id; + int j, n_outputs; Status ok; - mode = &manager->modes[new_mode]; + mode = crtc_info->mode; - n_outputs = g_variant_n_children (nested_outputs); + n_outputs = crtc_info->outputs->len; outputs = g_new (XID, n_outputs); - for (i = 0; i < n_outputs; i++) - { - g_variant_get_child (nested_outputs, i, "u", &output_id); - - outputs[i] = manager->outputs[output_id].output_id; - } + for (j = 0; j < n_outputs; j++) + outputs[i] = ((MetaOutput**)crtc_info->outputs->pdata)[i]->output_id; meta_error_trap_push (meta_get_display ()); ok = XRRSetCrtcConfig (manager->xdisplay, manager->resources, (XID)crtc->crtc_id, manager->time, - x, y, + crtc_info->x, crtc_info->y, (XID)mode->mode_id, - wl_transform_to_xrandr (transform), + wl_transform_to_xrandr (crtc_info->transform), outputs, n_outputs); meta_error_trap_pop (meta_get_display ()); if (ok != Success) meta_warning ("Configuring CRTC %d with mode %d (%d x %d @ %f) at position %d, %d and transfrom %u failed\n", (unsigned)(crtc->crtc_id), (unsigned)(mode->mode_id), - mode->width, mode->height, (float)mode->refresh_rate, x, y, transform); + mode->width, mode->height, (float)mode->refresh_rate, + crtc_info->x, crtc_info->y, crtc_info->transform); g_free (outputs); } } - while (g_variant_iter_loop (outputs, "(u@a{sv})", - &output_id, &properties)) + for (i = 0; i < n_outputs; i++) { - gboolean primary; + MetaOutputInfo *output_info = outputs[i]; - if (g_variant_lookup (properties, "primary", "b", &primary) && primary) + if (output_info->is_primary) { - MetaOutput *output = &manager->outputs[output_id]; - XRRSetOutputPrimary (manager->xdisplay, DefaultRootWindow (manager->xdisplay), - (XID)output->output_id); + (XID)output_info->output->output_id); } } @@ -1268,23 +1259,21 @@ apply_config_xrandr (MetaMonitorManager *manager, static void apply_config_dummy (MetaMonitorManager *manager, - GVariantIter *crtcs, - GVariantIter *outputs) + MetaCRTCInfo **crtcs, + unsigned int n_crtcs, + MetaOutputInfo **outputs, + unsigned int n_outputs) { - GVariant *nested_outputs, *properties; - guint crtc_id, output_id, transform; - int new_mode, x, y; unsigned i; int screen_width = 0, screen_height = 0; - while (g_variant_iter_loop (crtcs, "(uiiiu@aua{sv})", - &crtc_id, &new_mode, &x, &y, - &transform, &nested_outputs, NULL)) + for (i = 0; i < n_crtcs; i++) { - MetaCRTC *crtc = &manager->crtcs[crtc_id]; + MetaCRTCInfo *crtc_info = crtcs[i]; + MetaCRTC *crtc = crtc_info->crtc; crtc->is_dirty = TRUE; - if (new_mode == -1) + if (crtc_info->mode == NULL) { crtc->rect.x = 0; crtc->rect.y = 0; @@ -1297,12 +1286,11 @@ apply_config_dummy (MetaMonitorManager *manager, MetaMonitorMode *mode; MetaOutput *output; int i, n_outputs; - guint output_id; int width, height; - mode = &manager->modes[new_mode]; + mode = crtc_info->mode; - if (meta_monitor_transform_is_rotated (transform)) + if (meta_monitor_transform_is_rotated (crtc_info->transform)) { width = mode->height; height = mode->width; @@ -1313,22 +1301,20 @@ apply_config_dummy (MetaMonitorManager *manager, height = mode->height; } - crtc->rect.x = x; - crtc->rect.y = y; + crtc->rect.x = crtc_info->x; + crtc->rect.y = crtc_info->y; crtc->rect.width = width; crtc->rect.height = height; crtc->current_mode = mode; - crtc->transform = transform; + crtc->transform = crtc_info->transform; - screen_width = MAX (screen_width, x + width); - screen_height = MAX (screen_height, y + height); + screen_width = MAX (screen_width, crtc_info->x + width); + screen_height = MAX (screen_height, crtc_info->y + height); - n_outputs = g_variant_n_children (nested_outputs); + n_outputs = crtc_info->outputs->len; for (i = 0; i < n_outputs; i++) { - g_variant_get_child (nested_outputs, i, "u", &output_id); - - output = &manager->outputs[output_id]; + output = ((MetaOutput**)crtc_info->outputs->pdata)[i]; output->is_dirty = TRUE; output->crtc = crtc; @@ -1336,17 +1322,13 @@ apply_config_dummy (MetaMonitorManager *manager, } } - while (g_variant_iter_loop (outputs, "(u@a{sv})", - &output_id, &properties)) + for (i = 0; i < n_outputs; i++) { - MetaOutput *output = &manager->outputs[output_id]; - gboolean primary, presentation; + MetaOutputInfo *output_info = outputs[i]; + MetaOutput *output = output_info->output; - if (g_variant_lookup (properties, "primary", "b", &primary)) - output->is_primary = primary; - - if (g_variant_lookup (properties, "presentation", "b", &presentation)) - output->is_presentation = presentation; + output->is_primary = output_info->is_primary; + output->is_presentation = output_info->is_presentation; } /* Disable CRTCs not mentioned in the list */ @@ -1392,18 +1374,15 @@ apply_config_dummy (MetaMonitorManager *manager, void meta_monitor_manager_apply_configuration (MetaMonitorManager *manager, - GVariant *crtcs, - GVariant *outputs) + MetaCRTCInfo **crtcs, + unsigned int n_crtcs, + MetaOutputInfo **outputs, + unsigned int n_outputs) { - GVariantIter crtc_iter, output_iter; - - g_variant_iter_init (&crtc_iter, crtcs); - g_variant_iter_init (&output_iter, outputs); - if (manager->backend == META_BACKEND_XRANDR) - apply_config_xrandr (manager, &crtc_iter, &output_iter); + apply_config_xrandr (manager, crtcs, n_crtcs, outputs, n_outputs); else - apply_config_dummy (manager, &crtc_iter, &output_iter); + apply_config_dummy (manager, crtcs, n_crtcs, outputs, n_outputs); } static gboolean @@ -1426,10 +1405,12 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto { MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton); GVariantIter crtc_iter, output_iter, *nested_outputs; + GVariant *properties; guint crtc_id; int new_mode, x, y; guint transform; guint output_id; + GPtrArray *crtc_infos, *output_infos; if (serial != manager->serial) { @@ -1439,17 +1420,26 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto return TRUE; } + crtc_infos = g_ptr_array_new_full (g_variant_n_children (crtcs), + (GDestroyNotify) meta_crtc_info_free); + output_infos = g_ptr_array_new_full (g_variant_n_children (outputs), + (GDestroyNotify) meta_output_info_free); + /* Validate all arguments */ g_variant_iter_init (&crtc_iter, crtcs); while (g_variant_iter_loop (&crtc_iter, "(uiiiuaua{sv})", &crtc_id, &new_mode, &x, &y, &transform, &nested_outputs, NULL)) { + MetaCRTCInfo *crtc_info; MetaOutput *first_output; MetaCRTC *crtc; MetaMonitorMode *mode; guint output_id; + crtc_info = g_slice_new (MetaCRTCInfo); + crtc_info->outputs = g_ptr_array_new (); + if (crtc_id >= manager->n_crtcs) { g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, @@ -1458,6 +1448,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto return TRUE; } crtc = &manager->crtcs[crtc_id]; + crtc_info->crtc = crtc; if (new_mode != -1 && (new_mode < 0 || (unsigned)new_mode >= manager->n_modes)) { @@ -1467,6 +1458,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto return TRUE; } mode = new_mode != -1 ? &manager->modes[new_mode] : NULL; + crtc_info->mode = mode; if (mode) { @@ -1494,6 +1486,8 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto return TRUE; } } + crtc_info->x = x; + crtc_info->y = y; if (transform < WL_OUTPUT_TRANSFORM_NORMAL || transform > WL_OUTPUT_TRANSFORM_FLIPPED_270 || @@ -1504,6 +1498,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto "Invalid transform"); return TRUE; } + crtc_info->transform = transform; first_output = NULL; while (g_variant_iter_loop (nested_outputs, "u", &output_id)) @@ -1526,6 +1521,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto "Output cannot be assigned to this CRTC or mode"); return TRUE; } + g_ptr_array_add (crtc_info->outputs, output); if (first_output) { @@ -1551,8 +1547,11 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto } g_variant_iter_init (&output_iter, outputs); - while (g_variant_iter_loop (&output_iter, "(ua{sv})", &output_id, NULL)) + while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_id, &properties)) { + MetaOutputInfo *output_info; + gboolean primary, presentation; + if (output_id >= manager->n_outputs) { g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, @@ -1560,6 +1559,15 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto "Invalid output id"); return TRUE; } + + output_info = g_slice_new0 (MetaOutputInfo); + output_info->output = &manager->outputs[output_id]; + + if (g_variant_lookup (properties, "primary", "b", &primary)) + output_info->is_primary = primary; + + if (g_variant_lookup (properties, "presentation", "b", &presentation)) + output_info->is_presentation = presentation; } /* If we were in progress of making a persistent change and we see a @@ -1572,7 +1580,14 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto manager->persistent_timeout_id = 0; } - meta_monitor_manager_apply_configuration (manager, crtcs, outputs); + meta_monitor_manager_apply_configuration (manager, + (MetaCRTCInfo**)crtc_infos->pdata, + crtc_infos->len, + (MetaOutputInfo**)output_infos->pdata, + output_infos->len); + + g_ptr_array_unref (crtc_infos); + g_ptr_array_unref (output_infos); /* Update MetaMonitorConfig data structures immediately so that we don't revert the change at the next XRandR event, then wait 20 @@ -1671,6 +1686,23 @@ meta_monitor_manager_get_outputs (MetaMonitorManager *manager, return manager->outputs; } +void +meta_monitor_manager_get_resources (MetaMonitorManager *manager, + MetaMonitorMode **modes, + unsigned int *n_modes, + MetaCRTC **crtcs, + unsigned int *n_crtcs, + MetaOutput **outputs, + unsigned int *n_outputs) +{ + *modes = manager->modes; + *n_modes = manager->n_modes; + *crtcs = manager->crtcs; + *n_crtcs = manager->n_crtcs; + *outputs = manager->outputs; + *n_outputs = manager->n_outputs; +} + int meta_monitor_manager_get_primary_index (MetaMonitorManager *manager) {