diff --git a/src/backends/meta-logical-monitor.c b/src/backends/meta-logical-monitor.c index 4123165df..fab669807 100644 --- a/src/backends/meta-logical-monitor.c +++ b/src/backends/meta-logical-monitor.c @@ -107,21 +107,15 @@ MetaLogicalMonitor * meta_logical_monitor_new_derived (MetaMonitorManager *monitor_manager, MetaMonitor *monitor, MetaRectangle *layout, + int scale, int monitor_number) { MetaLogicalMonitor *logical_monitor; MetaOutput *main_output; - MetaMonitorMode *monitor_mode; - int scale; MetaMonitorTransform transform; logical_monitor = g_object_new (META_TYPE_LOGICAL_MONITOR, NULL); - monitor_mode = meta_monitor_get_current_mode (monitor); - scale = meta_monitor_manager_calculate_monitor_mode_scale (monitor_manager, - monitor, - monitor_mode); - transform = derive_monitor_transform (monitor); main_output = meta_monitor_get_main_output (monitor); diff --git a/src/backends/meta-logical-monitor.h b/src/backends/meta-logical-monitor.h index c1bd5bece..ce0c7e7bf 100644 --- a/src/backends/meta-logical-monitor.h +++ b/src/backends/meta-logical-monitor.h @@ -68,6 +68,7 @@ MetaLogicalMonitor * meta_logical_monitor_new (MetaMonitorManager *monitor MetaLogicalMonitor * meta_logical_monitor_new_derived (MetaMonitorManager *monitor_manager, MetaMonitor *monitor, MetaRectangle *layout, + int scale, int monitor_number); void meta_logical_monitor_add_monitor (MetaLogicalMonitor *logical_monitor, diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c index 5f80febe6..bad55c732 100644 --- a/src/backends/meta-monitor-config-manager.c +++ b/src/backends/meta-monitor-config-manager.c @@ -483,6 +483,7 @@ create_preferred_logical_monitor_config (MetaMonitorManager *monitor_ma MetaMonitor *monitor, int x, int y, + MetaLogicalMonitorConfig *primary_logical_monitor_config, MetaLogicalMonitorLayoutMode layout_mode) { MetaMonitorMode *mode; @@ -493,9 +494,15 @@ create_preferred_logical_monitor_config (MetaMonitorManager *monitor_ma mode = meta_monitor_get_preferred_mode (monitor); meta_monitor_mode_get_resolution (mode, &width, &height); - scale = meta_monitor_manager_calculate_monitor_mode_scale (monitor_manager, - monitor, - mode); + + if ((meta_monitor_manager_get_capabilities (monitor_manager) & + META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED) && + primary_logical_monitor_config) + scale = primary_logical_monitor_config->scale; + else + scale = meta_monitor_manager_calculate_monitor_mode_scale (monitor_manager, + monitor, + mode); switch (layout_mode) { @@ -546,6 +553,7 @@ meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_mana create_preferred_logical_monitor_config (monitor_manager, primary_monitor, 0, 0, + NULL, layout_mode); primary_logical_monitor_config->is_primary = TRUE; logical_monitor_configs = g_list_append (NULL, @@ -569,6 +577,7 @@ meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_mana create_preferred_logical_monitor_config (monitor_manager, monitor, x, 0, + primary_logical_monitor_config, layout_mode); logical_monitor_configs = g_list_append (logical_monitor_configs, logical_monitor_config); @@ -598,6 +607,7 @@ meta_monitor_config_manager_create_fallback (MetaMonitorConfigManager *config_ma create_preferred_logical_monitor_config (monitor_manager, primary_monitor, 0, 0, + NULL, layout_mode); primary_logical_monitor_config->is_primary = TRUE; logical_monitor_configs = g_list_append (NULL, @@ -615,6 +625,7 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m MetaLogicalMonitorLayoutMode layout_mode; GList *logical_monitor_configs; GList *region; + int x, y; GList *monitors; GList *l; @@ -622,16 +633,30 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m if (!primary_monitor) return NULL; + if (!meta_monitor_get_suggested_position (primary_monitor, &x, &y)) + return NULL; + layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager); - logical_monitor_configs = NULL; - region = NULL; + primary_logical_monitor_config = + create_preferred_logical_monitor_config (monitor_manager, + primary_monitor, + x, y, + NULL, + layout_mode); + primary_logical_monitor_config->is_primary = TRUE; + logical_monitor_configs = g_list_append (NULL, + primary_logical_monitor_config); + region = g_list_prepend (NULL, &primary_logical_monitor_config->layout); + monitors = meta_monitor_manager_get_monitors (monitor_manager); for (l = monitors; l; l = l->next) { MetaMonitor *monitor = l->data; MetaLogicalMonitorConfig *logical_monitor_config; - int x, y; + + if (monitor == primary_monitor) + continue; if (!meta_monitor_get_suggested_position (monitor, &x, &y)) continue; @@ -640,6 +665,7 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m create_preferred_logical_monitor_config (monitor_manager, monitor, x, y, + primary_logical_monitor_config, layout_mode); logical_monitor_configs = g_list_append (logical_monitor_configs, logical_monitor_config); @@ -655,9 +681,6 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m } region = g_list_prepend (region, &logical_monitor_config->layout); - - if (monitor == primary_monitor) - primary_logical_monitor_config = logical_monitor_config; } g_list_free (region); @@ -665,12 +688,6 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m if (!logical_monitor_configs) return NULL; - if (!primary_logical_monitor_config) - primary_logical_monitor_config = - g_list_first (logical_monitor_configs)->data; - - primary_logical_monitor_config->is_primary = TRUE; - return meta_monitors_config_new (logical_monitor_configs, layout_mode); } @@ -1024,12 +1041,14 @@ has_adjecent_neighbour (MetaMonitorsConfig *config, gboolean meta_verify_monitors_config (MetaMonitorsConfig *config, + MetaMonitorManager *monitor_manager, GError **error) { int min_x, min_y; gboolean has_primary; GList *region; GList *l; + gboolean global_scale_required; if (!config->logical_monitor_configs) { @@ -1038,6 +1057,10 @@ meta_verify_monitors_config (MetaMonitorsConfig *config, return FALSE; } + global_scale_required = + !!(meta_monitor_manager_get_capabilities (monitor_manager) & + META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED); + min_x = INT_MAX; min_y = INT_MAX; region = NULL; @@ -1046,6 +1069,21 @@ meta_verify_monitors_config (MetaMonitorsConfig *config, { MetaLogicalMonitorConfig *logical_monitor_config = l->data; + if (global_scale_required) + { + MetaLogicalMonitorConfig *prev_logical_monitor_config = + l->prev ? l->prev->data : NULL; + + if (prev_logical_monitor_config && + (prev_logical_monitor_config->scale != + logical_monitor_config->scale)) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Logical monitor scales must be identical"); + return FALSE; + } + } + if (meta_rectangle_overlaps_with_region (region, &logical_monitor_config->layout)) { diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h index 60b4446ac..7c3dbcd32 100644 --- a/src/backends/meta-monitor-config-manager.h +++ b/src/backends/meta-monitor-config-manager.h @@ -120,6 +120,7 @@ gboolean meta_verify_logical_monitor_config (MetaLogicalMonitorConfig *logica GError **error); gboolean meta_verify_monitors_config (MetaMonitorsConfig *config, + MetaMonitorManager *monitor_manager, GError **error); #endif /* META_MONITOR_CONFIG_MANAGER_H */ diff --git a/src/backends/meta-monitor-config-store.c b/src/backends/meta-monitor-config-store.c index aa7f08a5a..8fc4f61e5 100644 --- a/src/backends/meta-monitor-config-store.c +++ b/src/backends/meta-monitor-config-store.c @@ -640,7 +640,8 @@ handle_end_element (GMarkupParseContext *context, parser->current_logical_monitor_configs = NULL; - if (!meta_verify_monitors_config (config, error)) + if (!meta_verify_monitors_config (config, store->monitor_manager, + error)) { g_object_unref (config); return; diff --git a/src/backends/meta-monitor-manager-dummy.c b/src/backends/meta-monitor-manager-dummy.c index 21608a169..3d181d59b 100644 --- a/src/backends/meta-monitor-manager-dummy.c +++ b/src/backends/meta-monitor-manager-dummy.c @@ -357,9 +357,16 @@ meta_monitor_manager_dummy_ensure_initial_config (MetaMonitorManager *manager) config = meta_monitor_manager_ensure_configured (manager); if (meta_is_monitor_config_manager_enabled ()) - meta_monitor_manager_update_logical_state (manager, config); + { + meta_monitor_manager_update_logical_state (manager, config); + } else - meta_monitor_manager_update_logical_state_derived (manager); + { + MetaMonitorManagerDeriveFlag flags = + META_MONITOR_MANAGER_DERIVE_FLAG_NONE; + + meta_monitor_manager_update_logical_state_derived (manager, flags); + } } static void @@ -565,11 +572,14 @@ meta_monitor_manager_dummy_apply_config (MetaMonitorManager *manager, MetaOutputInfo **outputs, unsigned int n_outputs) { + MetaMonitorManagerDeriveFlag flags = + META_MONITOR_MANAGER_DERIVE_FLAG_NONE; + apply_crtc_assignments (manager, crtcs, n_crtcs, outputs, n_outputs); legacy_calculate_screen_size (manager); - meta_monitor_manager_rebuild_derived (manager); + meta_monitor_manager_rebuild_derived (manager, flags); } static gboolean diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h index 1f12e67c6..d8bc6f87e 100644 --- a/src/backends/meta-monitor-manager-private.h +++ b/src/backends/meta-monitor-manager-private.h @@ -72,7 +72,8 @@ typedef enum _MetaMonitorManagerCapability { META_MONITOR_MANAGER_CAPABILITY_NONE = 0, META_MONITOR_MANAGER_CAPABILITY_MIRRORING = (1 << 0), - META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE = (1 << 1) + META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE = (1 << 1), + META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED = (1 << 2) } MetaMonitorManagerCapability; /* Equivalent to the 'method' enum in org.gnome.Mutter.DisplayConfig */ @@ -90,6 +91,12 @@ typedef enum _MetaLogicalMonitorLayoutMode META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL = 2 } MetaLogicalMonitorLayoutMode; +typedef enum _MetaMonitorManagerDeriveFlag +{ + META_MONITOR_MANAGER_DERIVE_FLAG_NONE = 0, + META_MONITOR_MANAGER_DERIVE_FLAG_CONFIGURED_SCALE = (1 << 0) +} MetaMonitorManagerDeriveFlag; + typedef enum { META_MONITOR_TRANSFORM_NORMAL, @@ -404,7 +411,8 @@ gboolean meta_is_monitor_config_manager_enabled (void); void meta_monitor_manager_rebuild (MetaMonitorManager *manager, MetaMonitorsConfig *config); -void meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager); +void meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager, + MetaMonitorManagerDeriveFlag flags); int meta_monitor_manager_get_num_logical_monitors (MetaMonitorManager *manager); @@ -487,7 +495,8 @@ MetaMonitorsConfig * meta_monitor_manager_ensure_configured (MetaMonitorManager 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_update_logical_state_derived (MetaMonitorManager *manager, + MetaMonitorManagerDeriveFlag flags); gboolean meta_monitor_manager_is_lid_closed (MetaMonitorManager *manager); @@ -499,6 +508,9 @@ int meta_monitor_manager_calculate_monitor_mode_scale (MetaMonito MetaMonitor *monitor, MetaMonitorMode *monitor_mode); +MetaMonitorManagerCapability + meta_monitor_manager_get_capabilities (MetaMonitorManager *manager); + gboolean meta_monitor_manager_get_max_screen_size (MetaMonitorManager *manager, int *max_width, int *max_height); diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c index ba071caca..fa2840c7e 100644 --- a/src/backends/meta-monitor-manager.c +++ b/src/backends/meta-monitor-manager.c @@ -184,16 +184,95 @@ derive_monitor_layout (MetaMonitor *monitor, meta_monitor_derive_dimensions (monitor, &layout->width, &layout->height); } +static int +derive_configured_global_scale (MetaMonitorManager *manager) +{ + MetaMonitorsConfig *config; + MetaLogicalMonitorConfig *logical_monitor_config; + + config = meta_monitor_config_manager_get_current (manager->config_manager); + if (!config) + return 1; + + logical_monitor_config = config->logical_monitor_configs->data; + + return logical_monitor_config->scale; +} + +static int +calculate_monitor_scale (MetaMonitorManager *manager, + MetaMonitor *monitor) +{ + MetaMonitorMode *monitor_mode; + + monitor_mode = meta_monitor_get_current_mode (monitor); + return meta_monitor_manager_calculate_monitor_mode_scale (manager, + monitor, + monitor_mode); +} + +static int +derive_calculated_global_scale (MetaMonitorManager *manager) +{ + MetaMonitor *primary_monitor; + + primary_monitor = meta_monitor_manager_get_primary_monitor (manager); + if (!primary_monitor) + return 1; + + return calculate_monitor_scale (manager, primary_monitor); +} + +static int +derive_scale_from_config (MetaMonitorManager *manager, + MetaRectangle *layout) +{ + MetaMonitorsConfig *config; + GList *l; + + config = meta_monitor_config_manager_get_current (manager->config_manager); + for (l = config->logical_monitor_configs; l; l = l->next) + { + MetaLogicalMonitorConfig *logical_monitor_config = l->data; + + if (meta_rectangle_equal (layout, &logical_monitor_config->layout)) + return logical_monitor_config->scale; + } + + g_warning ("Missing logical monitor, using scale 1"); + return 1; +} + static void -meta_monitor_manager_rebuild_logical_monitors_derived (MetaMonitorManager *manager) +meta_monitor_manager_rebuild_logical_monitors_derived (MetaMonitorManager *manager, + MetaMonitorManagerDeriveFlag flags) { GList *logical_monitors = NULL; GList *l; int monitor_number; MetaLogicalMonitor *primary_logical_monitor = NULL; + gboolean use_configured_scale; + gboolean use_global_scale; + int global_scale = 0; + MetaMonitorManagerCapability capabilities; monitor_number = 0; + capabilities = meta_monitor_manager_get_capabilities (manager); + use_global_scale = + !!(capabilities & META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED); + + use_configured_scale = + !!(flags & META_MONITOR_MANAGER_DERIVE_FLAG_CONFIGURED_SCALE); + + if (use_global_scale) + { + if (use_configured_scale) + global_scale = derive_configured_global_scale (manager); + else + global_scale = derive_calculated_global_scale (manager); + } + for (l = manager->monitors; l; l = l->next) { MetaMonitor *monitor = l->data; @@ -212,9 +291,21 @@ meta_monitor_manager_rebuild_logical_monitors_derived (MetaMonitorManager *manag } else { + int scale; + + if (use_global_scale) + scale = global_scale; + else if (use_configured_scale) + scale = derive_scale_from_config (manager, &layout); + else + scale = calculate_monitor_scale (manager, monitor); + + g_assert (scale > 0); + logical_monitor = meta_logical_monitor_new_derived (manager, monitor, &layout, + scale, monitor_number); logical_monitors = g_list_append (logical_monitors, logical_monitor); monitor_number++; @@ -323,7 +414,7 @@ meta_monitor_manager_get_supported_scales (MetaMonitorManager *manager, manager_class->get_supported_scales (manager, scales, n_scales); } -static MetaMonitorManagerCapability +MetaMonitorManagerCapability meta_monitor_manager_get_capabilities (MetaMonitorManager *manager) { MetaMonitorManagerClass *manager_class = @@ -1563,6 +1654,13 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, g_variant_new_boolean (TRUE)); } + if (capabilities & META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED) + { + g_variant_builder_add (&properties_builder, "{sv}", + "global-scale-required", + g_variant_new_boolean (TRUE)); + } + if (meta_monitor_manager_get_max_screen_size (manager, &max_screen_width, &max_screen_height)) @@ -1997,7 +2095,7 @@ meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skelet } config = meta_monitors_config_new (logical_monitor_configs, layout_mode); - if (!meta_verify_monitors_config (config, &error)) + if (!meta_verify_monitors_config (config, manager, &error)) { g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, @@ -2729,15 +2827,17 @@ meta_monitor_manager_update_monitor_modes_derived (MetaMonitorManager *manager) } void -meta_monitor_manager_update_logical_state_derived (MetaMonitorManager *manager) +meta_monitor_manager_update_logical_state_derived (MetaMonitorManager *manager, + MetaMonitorManagerDeriveFlag flags) { manager->layout_mode = META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL; - meta_monitor_manager_rebuild_logical_monitors_derived (manager); + meta_monitor_manager_rebuild_logical_monitors_derived (manager, flags); } void -meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager) +meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager, + MetaMonitorManagerDeriveFlag flags) { GList *old_logical_monitors; @@ -2748,7 +2848,7 @@ meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager) old_logical_monitors = manager->logical_monitors; - meta_monitor_manager_update_logical_state_derived (manager); + meta_monitor_manager_update_logical_state_derived (manager, flags); meta_monitor_manager_notify_monitors_changed (manager); diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c index 6000a77e9..1856d1092 100644 --- a/src/backends/native/meta-monitor-manager-kms.c +++ b/src/backends/native/meta-monitor-manager-kms.c @@ -1259,9 +1259,16 @@ meta_monitor_manager_kms_ensure_initial_config (MetaMonitorManager *manager) config = meta_monitor_manager_ensure_configured (manager); if (meta_is_monitor_config_manager_enabled ()) - meta_monitor_manager_update_logical_state (manager, config); + { + meta_monitor_manager_update_logical_state (manager, config); + } else - meta_monitor_manager_update_logical_state_derived (manager); + { + MetaMonitorManagerDeriveFlag flags = + META_MONITOR_MANAGER_DERIVE_FLAG_NONE; + + meta_monitor_manager_update_logical_state_derived (manager, flags); + } } static void @@ -1492,10 +1499,13 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager, MetaOutputInfo **outputs, unsigned int n_outputs) { + MetaMonitorManagerDeriveFlag flags = + META_MONITOR_MANAGER_DERIVE_FLAG_NONE; + apply_crtc_assignments (manager, crtcs, n_crtcs, outputs, n_outputs); legacy_calculate_screen_size (manager); - meta_monitor_manager_rebuild_derived (manager); + meta_monitor_manager_rebuild_derived (manager, flags); } static void diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c index 689a97ea6..4c4104191 100644 --- a/src/backends/x11/meta-monitor-manager-xrandr.c +++ b/src/backends/x11/meta-monitor-manager-xrandr.c @@ -55,7 +55,7 @@ #define DPI_FALLBACK 96.0 static float supported_scales_xrandr[] = { - 1.0 + 1.0, 2.0 }; struct _MetaMonitorManagerXrandr @@ -68,6 +68,8 @@ struct _MetaMonitorManagerXrandr int rr_error_base; gboolean has_randr15; + xcb_timestamp_t last_xrandr_set_timestamp; + #ifdef HAVE_XRANDR15 GHashTable *tiled_monitor_atoms; #endif /* HAVE_XRANDR15 */ @@ -1071,6 +1073,7 @@ output_set_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr, static gboolean xrandr_set_crtc_config (MetaMonitorManagerXrandr *manager_xrandr, + gboolean save_timestamp, xcb_randr_crtc_t crtc, xcb_timestamp_t timestamp, int x, @@ -1107,13 +1110,141 @@ xrandr_set_crtc_config (MetaMonitorManagerXrandr *manager_xrandr, return FALSE; } + if (save_timestamp) + manager_xrandr->last_xrandr_set_timestamp = reply->timestamp; + free (reply); return TRUE; } +static gboolean +is_crtc_assignment_changed (MetaCrtc *crtc, + MetaCrtcInfo **crtc_infos, + unsigned int n_crtc_infos) +{ + unsigned int i; + + for (i = 0; i < n_crtc_infos; i++) + { + MetaCrtcInfo *crtc_info = crtc_infos[i]; + unsigned int j; + + if (crtc_info->crtc != crtc) + continue; + + if (crtc->current_mode != crtc_info->mode) + return TRUE; + + if (crtc->rect.x != crtc_info->x) + return TRUE; + + if (crtc->rect.y != crtc_info->y) + return TRUE; + + if (crtc->transform != crtc_info->transform) + return TRUE; + + for (j = 0; j < crtc_info->outputs->len; j++) + { + MetaOutput *output = ((MetaOutput**) crtc_info->outputs->pdata)[j]; + + if (output->crtc != crtc) + return TRUE; + } + + return FALSE; + } + + return crtc->current_mode != NULL; +} + +static gboolean +is_output_assignment_changed (MetaOutput *output, + MetaCrtcInfo **crtc_infos, + unsigned int n_crtc_infos, + MetaOutputInfo **output_infos, + unsigned int n_output_infos) +{ + gboolean output_is_found = FALSE; + unsigned int i; + + for (i = 0; i < n_output_infos; i++) + { + MetaOutputInfo *output_info = output_infos[i]; + + if (output_info->output != output) + continue; + + if (output->is_primary != output_info->is_primary) + return TRUE; + + if (output->is_presentation != output_info->is_presentation) + return TRUE; + + if (output->is_underscanning != output_info->is_underscanning) + return TRUE; + + output_is_found = TRUE; + } + + if (!output_is_found) + return output->crtc != NULL; + + for (i = 0; i < n_crtc_infos; i++) + { + MetaCrtcInfo *crtc_info = crtc_infos[i]; + unsigned int j; + + for (j = 0; j < crtc_info->outputs->len; j++) + { + MetaOutput *crtc_info_output = + ((MetaOutput**) crtc_info->outputs->pdata)[j]; + + if (crtc_info_output == output && + crtc_info->crtc == output->crtc) + return FALSE; + } + } + + return TRUE; +} + +static gboolean +is_assignments_changed (MetaMonitorManager *manager, + MetaCrtcInfo **crtc_infos, + unsigned int n_crtc_infos, + MetaOutputInfo **output_infos, + unsigned int n_output_infos) +{ + unsigned int i; + + for (i = 0; i < manager->n_crtcs; i++) + { + MetaCrtc *crtc = &manager->crtcs[i]; + + if (is_crtc_assignment_changed (crtc, crtc_infos, n_crtc_infos)) + return TRUE; + } + + for (i = 0; i < manager->n_outputs; i++) + { + MetaOutput *output = &manager->outputs[i]; + + if (is_output_assignment_changed (output, + crtc_infos, + n_crtc_infos, + output_infos, + n_output_infos)) + return TRUE; + } + + return FALSE; +} + static void apply_crtc_assignments (MetaMonitorManager *manager, + gboolean save_timestamp, MetaCrtcInfo **crtcs, unsigned int n_crtcs, MetaOutputInfo **outputs, @@ -1163,6 +1294,7 @@ apply_crtc_assignments (MetaMonitorManager *manager, crtc->rect.y + crtc->rect.height > height) { xrandr_set_crtc_config (manager_xrandr, + save_timestamp, (xcb_randr_crtc_t) crtc->crtc_id, XCB_CURRENT_TIME, 0, 0, XCB_NONE, @@ -1191,6 +1323,7 @@ apply_crtc_assignments (MetaMonitorManager *manager, continue; xrandr_set_crtc_config (manager_xrandr, + save_timestamp, (xcb_randr_crtc_t) crtc->crtc_id, XCB_CURRENT_TIME, 0, 0, XCB_NONE, @@ -1247,6 +1380,7 @@ apply_crtc_assignments (MetaMonitorManager *manager, rotation = meta_monitor_transform_to_xrandr (crtc_info->transform); if (!xrandr_set_crtc_config (manager_xrandr, + save_timestamp, (xcb_randr_crtc_t) crtc->crtc_id, XCB_CURRENT_TIME, crtc_info->x, crtc_info->y, @@ -1329,6 +1463,9 @@ apply_crtc_assignments (MetaMonitorManager *manager, static void meta_monitor_manager_xrandr_ensure_initial_config (MetaMonitorManager *manager) { + MetaMonitorManagerDeriveFlag flags = + META_MONITOR_MANAGER_DERIVE_FLAG_NONE; + meta_monitor_manager_ensure_configured (manager); /* @@ -1338,7 +1475,10 @@ meta_monitor_manager_xrandr_ensure_initial_config (MetaMonitorManager *manager) */ meta_monitor_manager_read_current_state (manager); - meta_monitor_manager_update_logical_state_derived (manager); + if (meta_is_monitor_config_manager_enabled ()) + flags |= META_MONITOR_MANAGER_DERIVE_FLAG_CONFIGURED_SCALE; + + meta_monitor_manager_update_logical_state_derived (manager, flags); } static gboolean @@ -1352,7 +1492,10 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *mana if (!config) { - meta_monitor_manager_rebuild_derived (manager); + MetaMonitorManagerDeriveFlag flags = + META_MONITOR_MANAGER_DERIVE_FLAG_NONE; + + meta_monitor_manager_rebuild_derived (manager, flags); return TRUE; } @@ -1363,11 +1506,35 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *mana if (method != META_MONITORS_CONFIG_METHOD_VERIFY) { - apply_crtc_assignments (manager, - (MetaCrtcInfo **) crtc_infos->pdata, - crtc_infos->len, - (MetaOutputInfo **) output_infos->pdata, - output_infos->len); + /* + * If the assignment has not changed, we won't get any notification about + * any new configuration from the X server; but we still need to update + * our own configuration, as something not applicable in Xrandr might + * have changed locally, such as the logical monitors scale. This means we + * must check that our new assignment actually changes anything, otherwise + * just update the logical state. + */ + if (is_assignments_changed (manager, + (MetaCrtcInfo **) crtc_infos->pdata, + crtc_infos->len, + (MetaOutputInfo **) output_infos->pdata, + output_infos->len)) + { + apply_crtc_assignments (manager, + TRUE, + (MetaCrtcInfo **) crtc_infos->pdata, + crtc_infos->len, + (MetaOutputInfo **) output_infos->pdata, + output_infos->len); + } + else + { + MetaMonitorManagerDeriveFlag flags; + + flags = (META_MONITOR_MANAGER_DERIVE_FLAG_NONE | + META_MONITOR_MANAGER_DERIVE_FLAG_CONFIGURED_SCALE); + meta_monitor_manager_rebuild_derived (manager, flags); + } } g_ptr_array_free (crtc_infos, TRUE); @@ -1383,7 +1550,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager, MetaOutputInfo **outputs, unsigned int n_outputs) { - apply_crtc_assignments (manager, crtcs, n_crtcs, outputs, n_outputs); + apply_crtc_assignments (manager, FALSE, crtcs, n_crtcs, outputs, n_outputs); } static void @@ -1629,8 +1796,7 @@ meta_monitor_manager_xrandr_calculate_monitor_mode_scale (MetaMonitorManager *ma MetaMonitor *monitor, MetaMonitorMode *monitor_mode) { - /* X11 does not support anything other than scale 1. */ - return 1; + return meta_monitor_calculate_mode_scale (monitor, monitor_mode); } static void @@ -1645,7 +1811,8 @@ meta_monitor_manager_xrandr_get_supported_scales (MetaMonitorManager *manager, static MetaMonitorManagerCapability meta_monitor_manager_xrandr_get_capabilities (MetaMonitorManager *manager) { - return META_MONITOR_MANAGER_CAPABILITY_MIRRORING; + return (META_MONITOR_MANAGER_CAPABILITY_MIRRORING | + META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED); } static gboolean @@ -1665,11 +1832,7 @@ meta_monitor_manager_xrandr_get_max_screen_size (MetaMonitorManager *manager, static MetaLogicalMonitorLayoutMode meta_monitor_manager_xrandr_get_default_layout_mode (MetaMonitorManager *manager) { - /* - * Under X11, we still use the 'logical' layout mode, but it is - * eqivalent to 'physical' as the scale is always 1. - */ - return META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL; + return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL; } static void @@ -1763,7 +1926,8 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra XEvent *event) { MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr); - gboolean hotplug; + gboolean is_hotplug; + gboolean is_our_configuration; if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify) return FALSE; @@ -1772,16 +1936,24 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra meta_monitor_manager_read_current_state (manager); - hotplug = manager_xrandr->resources->timestamp < manager_xrandr->resources->configTimestamp; - if (hotplug) + + is_hotplug = (manager_xrandr->resources->timestamp < + manager_xrandr->resources->configTimestamp); + is_our_configuration = (manager_xrandr->resources->timestamp == + manager_xrandr->last_xrandr_set_timestamp); + if (is_hotplug) { - /* This is a hotplug event, so go ahead and build a new configuration. */ meta_monitor_manager_on_hotplug (manager); } else { - /* Something else changed -- tell the world about it. */ - meta_monitor_manager_rebuild_derived (manager); + MetaMonitorManagerDeriveFlag flags = + META_MONITOR_MANAGER_DERIVE_FLAG_NONE; + + if (is_our_configuration) + flags |= META_MONITOR_MANAGER_DERIVE_FLAG_CONFIGURED_SCALE; + + meta_monitor_manager_rebuild_derived (manager, flags); } return TRUE; diff --git a/src/org.gnome.Mutter.DisplayConfig.xml b/src/org.gnome.Mutter.DisplayConfig.xml index 30d2eade8..fb1c6c44c 100644 --- a/src/org.gnome.Mutter.DisplayConfig.xml +++ b/src/org.gnome.Mutter.DisplayConfig.xml @@ -401,6 +401,10 @@ * "supports-changing-layout-mode" (b): True if the layout mode can be changed. Absence of this means the layout mode cannot be changed. + * "global-scale-required" (b): True if all the logical monitors must + always use the same scale. Absence of + this means logical monitor scales can + differ. --> diff --git a/src/tests/meta-monitor-manager-test.c b/src/tests/meta-monitor-manager-test.c index ed582f980..ca61514c7 100644 --- a/src/tests/meta-monitor-manager-test.c +++ b/src/tests/meta-monitor-manager-test.c @@ -123,9 +123,16 @@ meta_monitor_manager_test_ensure_initial_config (MetaMonitorManager *manager) config = meta_monitor_manager_ensure_configured (manager); if (meta_is_monitor_config_manager_enabled ()) - meta_monitor_manager_update_logical_state (manager, config); + { + meta_monitor_manager_update_logical_state (manager, config); + } else - meta_monitor_manager_update_logical_state_derived (manager); + { + MetaMonitorManagerDeriveFlag flags = + META_MONITOR_MANAGER_DERIVE_FLAG_NONE; + + meta_monitor_manager_update_logical_state_derived (manager, flags); + } } static void @@ -279,9 +286,16 @@ meta_monitor_manager_test_apply_monitors_config (MetaMonitorManager *manage manager->screen_height = 1; if (meta_is_stage_views_enabled ()) - meta_monitor_manager_rebuild (manager, NULL); + { + meta_monitor_manager_rebuild (manager, NULL); + } else - meta_monitor_manager_rebuild_derived (manager); + { + MetaMonitorManagerDeriveFlag flags = + META_MONITOR_MANAGER_DERIVE_FLAG_CONFIGURED_SCALE; + + meta_monitor_manager_rebuild_derived (manager, flags); + } return TRUE; } @@ -311,9 +325,16 @@ meta_monitor_manager_test_apply_monitors_config (MetaMonitorManager *manage update_screen_size (manager, config); if (meta_is_stage_views_enabled ()) - meta_monitor_manager_rebuild (manager, config); + { + meta_monitor_manager_rebuild (manager, config); + } else - meta_monitor_manager_rebuild_derived (manager); + { + MetaMonitorManagerDeriveFlag flags = + META_MONITOR_MANAGER_DERIVE_FLAG_CONFIGURED_SCALE; + + meta_monitor_manager_rebuild_derived (manager, flags); + } return TRUE; } @@ -343,9 +364,12 @@ meta_monitor_manager_test_apply_configuration (MetaMonitorManager *manager, MetaOutputInfo **outputs, unsigned int n_outputs) { + MetaMonitorManagerDeriveFlag flags = + META_MONITOR_MANAGER_DERIVE_FLAG_NONE; + apply_crtc_assignments (manager, crtcs, n_crtcs, outputs, n_outputs); legacy_calculate_screen_size (manager); - meta_monitor_manager_rebuild_derived (manager); + meta_monitor_manager_rebuild_derived (manager, flags); } static void