monitor-manager/xrandr: Allow configuring scales on X11 too

This commit makes it possible to configure logical monitor scale also
when running on top of an X11 server using Xrandr. An extra property
'requires-globla-scale' is added to the D-Bus API is added to instruct
a configuration application to only allow setting a global logical
monitor scale.

This is needed to let gsd-xsettings use the configured state to set a
XSettings state that respects the explicit monitor configuration.

https://bugzilla.gnome.org/show_bug.cgi?id=777732
This commit is contained in:
Jonas Ådahl 2017-04-21 18:01:15 +08:00
parent 05bc2e2331
commit 1bb0e18042
12 changed files with 436 additions and 69 deletions

View File

@ -107,21 +107,15 @@ MetaLogicalMonitor *
meta_logical_monitor_new_derived (MetaMonitorManager *monitor_manager, meta_logical_monitor_new_derived (MetaMonitorManager *monitor_manager,
MetaMonitor *monitor, MetaMonitor *monitor,
MetaRectangle *layout, MetaRectangle *layout,
int scale,
int monitor_number) int monitor_number)
{ {
MetaLogicalMonitor *logical_monitor; MetaLogicalMonitor *logical_monitor;
MetaOutput *main_output; MetaOutput *main_output;
MetaMonitorMode *monitor_mode;
int scale;
MetaMonitorTransform transform; MetaMonitorTransform transform;
logical_monitor = g_object_new (META_TYPE_LOGICAL_MONITOR, NULL); 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); transform = derive_monitor_transform (monitor);
main_output = meta_monitor_get_main_output (monitor); main_output = meta_monitor_get_main_output (monitor);

View File

@ -68,6 +68,7 @@ MetaLogicalMonitor * meta_logical_monitor_new (MetaMonitorManager *monitor
MetaLogicalMonitor * meta_logical_monitor_new_derived (MetaMonitorManager *monitor_manager, MetaLogicalMonitor * meta_logical_monitor_new_derived (MetaMonitorManager *monitor_manager,
MetaMonitor *monitor, MetaMonitor *monitor,
MetaRectangle *layout, MetaRectangle *layout,
int scale,
int monitor_number); int monitor_number);
void meta_logical_monitor_add_monitor (MetaLogicalMonitor *logical_monitor, void meta_logical_monitor_add_monitor (MetaLogicalMonitor *logical_monitor,

View File

@ -483,6 +483,7 @@ create_preferred_logical_monitor_config (MetaMonitorManager *monitor_ma
MetaMonitor *monitor, MetaMonitor *monitor,
int x, int x,
int y, int y,
MetaLogicalMonitorConfig *primary_logical_monitor_config,
MetaLogicalMonitorLayoutMode layout_mode) MetaLogicalMonitorLayoutMode layout_mode)
{ {
MetaMonitorMode *mode; MetaMonitorMode *mode;
@ -493,9 +494,15 @@ create_preferred_logical_monitor_config (MetaMonitorManager *monitor_ma
mode = meta_monitor_get_preferred_mode (monitor); mode = meta_monitor_get_preferred_mode (monitor);
meta_monitor_mode_get_resolution (mode, &width, &height); meta_monitor_mode_get_resolution (mode, &width, &height);
scale = meta_monitor_manager_calculate_monitor_mode_scale (monitor_manager,
monitor, if ((meta_monitor_manager_get_capabilities (monitor_manager) &
mode); 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) switch (layout_mode)
{ {
@ -546,6 +553,7 @@ meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_mana
create_preferred_logical_monitor_config (monitor_manager, create_preferred_logical_monitor_config (monitor_manager,
primary_monitor, primary_monitor,
0, 0, 0, 0,
NULL,
layout_mode); layout_mode);
primary_logical_monitor_config->is_primary = TRUE; primary_logical_monitor_config->is_primary = TRUE;
logical_monitor_configs = g_list_append (NULL, 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, create_preferred_logical_monitor_config (monitor_manager,
monitor, monitor,
x, 0, x, 0,
primary_logical_monitor_config,
layout_mode); layout_mode);
logical_monitor_configs = g_list_append (logical_monitor_configs, logical_monitor_configs = g_list_append (logical_monitor_configs,
logical_monitor_config); logical_monitor_config);
@ -598,6 +607,7 @@ meta_monitor_config_manager_create_fallback (MetaMonitorConfigManager *config_ma
create_preferred_logical_monitor_config (monitor_manager, create_preferred_logical_monitor_config (monitor_manager,
primary_monitor, primary_monitor,
0, 0, 0, 0,
NULL,
layout_mode); layout_mode);
primary_logical_monitor_config->is_primary = TRUE; primary_logical_monitor_config->is_primary = TRUE;
logical_monitor_configs = g_list_append (NULL, logical_monitor_configs = g_list_append (NULL,
@ -615,6 +625,7 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m
MetaLogicalMonitorLayoutMode layout_mode; MetaLogicalMonitorLayoutMode layout_mode;
GList *logical_monitor_configs; GList *logical_monitor_configs;
GList *region; GList *region;
int x, y;
GList *monitors; GList *monitors;
GList *l; GList *l;
@ -622,16 +633,30 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m
if (!primary_monitor) if (!primary_monitor)
return NULL; 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); layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager);
logical_monitor_configs = NULL; primary_logical_monitor_config =
region = NULL; 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); monitors = meta_monitor_manager_get_monitors (monitor_manager);
for (l = monitors; l; l = l->next) for (l = monitors; l; l = l->next)
{ {
MetaMonitor *monitor = l->data; MetaMonitor *monitor = l->data;
MetaLogicalMonitorConfig *logical_monitor_config; MetaLogicalMonitorConfig *logical_monitor_config;
int x, y;
if (monitor == primary_monitor)
continue;
if (!meta_monitor_get_suggested_position (monitor, &x, &y)) if (!meta_monitor_get_suggested_position (monitor, &x, &y))
continue; continue;
@ -640,6 +665,7 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m
create_preferred_logical_monitor_config (monitor_manager, create_preferred_logical_monitor_config (monitor_manager,
monitor, monitor,
x, y, x, y,
primary_logical_monitor_config,
layout_mode); layout_mode);
logical_monitor_configs = g_list_append (logical_monitor_configs, logical_monitor_configs = g_list_append (logical_monitor_configs,
logical_monitor_config); 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); region = g_list_prepend (region, &logical_monitor_config->layout);
if (monitor == primary_monitor)
primary_logical_monitor_config = logical_monitor_config;
} }
g_list_free (region); g_list_free (region);
@ -665,12 +688,6 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m
if (!logical_monitor_configs) if (!logical_monitor_configs)
return NULL; 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); return meta_monitors_config_new (logical_monitor_configs, layout_mode);
} }
@ -1024,12 +1041,14 @@ has_adjecent_neighbour (MetaMonitorsConfig *config,
gboolean gboolean
meta_verify_monitors_config (MetaMonitorsConfig *config, meta_verify_monitors_config (MetaMonitorsConfig *config,
MetaMonitorManager *monitor_manager,
GError **error) GError **error)
{ {
int min_x, min_y; int min_x, min_y;
gboolean has_primary; gboolean has_primary;
GList *region; GList *region;
GList *l; GList *l;
gboolean global_scale_required;
if (!config->logical_monitor_configs) if (!config->logical_monitor_configs)
{ {
@ -1038,6 +1057,10 @@ meta_verify_monitors_config (MetaMonitorsConfig *config,
return FALSE; return FALSE;
} }
global_scale_required =
!!(meta_monitor_manager_get_capabilities (monitor_manager) &
META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED);
min_x = INT_MAX; min_x = INT_MAX;
min_y = INT_MAX; min_y = INT_MAX;
region = NULL; region = NULL;
@ -1046,6 +1069,21 @@ meta_verify_monitors_config (MetaMonitorsConfig *config,
{ {
MetaLogicalMonitorConfig *logical_monitor_config = l->data; 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, if (meta_rectangle_overlaps_with_region (region,
&logical_monitor_config->layout)) &logical_monitor_config->layout))
{ {

View File

@ -120,6 +120,7 @@ gboolean meta_verify_logical_monitor_config (MetaLogicalMonitorConfig *logica
GError **error); GError **error);
gboolean meta_verify_monitors_config (MetaMonitorsConfig *config, gboolean meta_verify_monitors_config (MetaMonitorsConfig *config,
MetaMonitorManager *monitor_manager,
GError **error); GError **error);
#endif /* META_MONITOR_CONFIG_MANAGER_H */ #endif /* META_MONITOR_CONFIG_MANAGER_H */

View File

@ -640,7 +640,8 @@ handle_end_element (GMarkupParseContext *context,
parser->current_logical_monitor_configs = NULL; 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); g_object_unref (config);
return; return;

View File

@ -357,9 +357,16 @@ meta_monitor_manager_dummy_ensure_initial_config (MetaMonitorManager *manager)
config = meta_monitor_manager_ensure_configured (manager); config = meta_monitor_manager_ensure_configured (manager);
if (meta_is_monitor_config_manager_enabled ()) if (meta_is_monitor_config_manager_enabled ())
meta_monitor_manager_update_logical_state (manager, config); {
meta_monitor_manager_update_logical_state (manager, config);
}
else 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 static void
@ -565,11 +572,14 @@ meta_monitor_manager_dummy_apply_config (MetaMonitorManager *manager,
MetaOutputInfo **outputs, MetaOutputInfo **outputs,
unsigned int n_outputs) unsigned int n_outputs)
{ {
MetaMonitorManagerDeriveFlag flags =
META_MONITOR_MANAGER_DERIVE_FLAG_NONE;
apply_crtc_assignments (manager, crtcs, n_crtcs, outputs, n_outputs); apply_crtc_assignments (manager, crtcs, n_crtcs, outputs, n_outputs);
legacy_calculate_screen_size (manager); legacy_calculate_screen_size (manager);
meta_monitor_manager_rebuild_derived (manager); meta_monitor_manager_rebuild_derived (manager, flags);
} }
static gboolean static gboolean

View File

@ -72,7 +72,8 @@ typedef enum _MetaMonitorManagerCapability
{ {
META_MONITOR_MANAGER_CAPABILITY_NONE = 0, META_MONITOR_MANAGER_CAPABILITY_NONE = 0,
META_MONITOR_MANAGER_CAPABILITY_MIRRORING = (1 << 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; } MetaMonitorManagerCapability;
/* Equivalent to the 'method' enum in org.gnome.Mutter.DisplayConfig */ /* Equivalent to the 'method' enum in org.gnome.Mutter.DisplayConfig */
@ -90,6 +91,12 @@ typedef enum _MetaLogicalMonitorLayoutMode
META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL = 2 META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL = 2
} MetaLogicalMonitorLayoutMode; } MetaLogicalMonitorLayoutMode;
typedef enum _MetaMonitorManagerDeriveFlag
{
META_MONITOR_MANAGER_DERIVE_FLAG_NONE = 0,
META_MONITOR_MANAGER_DERIVE_FLAG_CONFIGURED_SCALE = (1 << 0)
} MetaMonitorManagerDeriveFlag;
typedef enum typedef enum
{ {
META_MONITOR_TRANSFORM_NORMAL, META_MONITOR_TRANSFORM_NORMAL,
@ -404,7 +411,8 @@ gboolean meta_is_monitor_config_manager_enabled (void);
void meta_monitor_manager_rebuild (MetaMonitorManager *manager, void meta_monitor_manager_rebuild (MetaMonitorManager *manager,
MetaMonitorsConfig *config); 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); 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, void meta_monitor_manager_update_logical_state (MetaMonitorManager *manager,
MetaMonitorsConfig *config); 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); gboolean meta_monitor_manager_is_lid_closed (MetaMonitorManager *manager);
@ -499,6 +508,9 @@ int meta_monitor_manager_calculate_monitor_mode_scale (MetaMonito
MetaMonitor *monitor, MetaMonitor *monitor,
MetaMonitorMode *monitor_mode); MetaMonitorMode *monitor_mode);
MetaMonitorManagerCapability
meta_monitor_manager_get_capabilities (MetaMonitorManager *manager);
gboolean meta_monitor_manager_get_max_screen_size (MetaMonitorManager *manager, gboolean meta_monitor_manager_get_max_screen_size (MetaMonitorManager *manager,
int *max_width, int *max_width,
int *max_height); int *max_height);

View File

@ -184,16 +184,95 @@ derive_monitor_layout (MetaMonitor *monitor,
meta_monitor_derive_dimensions (monitor, &layout->width, &layout->height); 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 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 *logical_monitors = NULL;
GList *l; GList *l;
int monitor_number; int monitor_number;
MetaLogicalMonitor *primary_logical_monitor = NULL; MetaLogicalMonitor *primary_logical_monitor = NULL;
gboolean use_configured_scale;
gboolean use_global_scale;
int global_scale = 0;
MetaMonitorManagerCapability capabilities;
monitor_number = 0; 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) for (l = manager->monitors; l; l = l->next)
{ {
MetaMonitor *monitor = l->data; MetaMonitor *monitor = l->data;
@ -212,9 +291,21 @@ meta_monitor_manager_rebuild_logical_monitors_derived (MetaMonitorManager *manag
} }
else 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, logical_monitor = meta_logical_monitor_new_derived (manager,
monitor, monitor,
&layout, &layout,
scale,
monitor_number); monitor_number);
logical_monitors = g_list_append (logical_monitors, logical_monitor); logical_monitors = g_list_append (logical_monitors, logical_monitor);
monitor_number++; monitor_number++;
@ -323,7 +414,7 @@ meta_monitor_manager_get_supported_scales (MetaMonitorManager *manager,
manager_class->get_supported_scales (manager, scales, n_scales); manager_class->get_supported_scales (manager, scales, n_scales);
} }
static MetaMonitorManagerCapability MetaMonitorManagerCapability
meta_monitor_manager_get_capabilities (MetaMonitorManager *manager) meta_monitor_manager_get_capabilities (MetaMonitorManager *manager)
{ {
MetaMonitorManagerClass *manager_class = MetaMonitorManagerClass *manager_class =
@ -1563,6 +1654,13 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
g_variant_new_boolean (TRUE)); 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, if (meta_monitor_manager_get_max_screen_size (manager,
&max_screen_width, &max_screen_width,
&max_screen_height)) &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); 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_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS, G_DBUS_ERROR_INVALID_ARGS,
@ -2729,15 +2827,17 @@ meta_monitor_manager_update_monitor_modes_derived (MetaMonitorManager *manager)
} }
void 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; 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 void
meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager) meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager,
MetaMonitorManagerDeriveFlag flags)
{ {
GList *old_logical_monitors; GList *old_logical_monitors;
@ -2748,7 +2848,7 @@ meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager)
old_logical_monitors = manager->logical_monitors; 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); meta_monitor_manager_notify_monitors_changed (manager);

View File

@ -1259,9 +1259,16 @@ meta_monitor_manager_kms_ensure_initial_config (MetaMonitorManager *manager)
config = meta_monitor_manager_ensure_configured (manager); config = meta_monitor_manager_ensure_configured (manager);
if (meta_is_monitor_config_manager_enabled ()) if (meta_is_monitor_config_manager_enabled ())
meta_monitor_manager_update_logical_state (manager, config); {
meta_monitor_manager_update_logical_state (manager, config);
}
else 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 static void
@ -1492,10 +1499,13 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
MetaOutputInfo **outputs, MetaOutputInfo **outputs,
unsigned int n_outputs) unsigned int n_outputs)
{ {
MetaMonitorManagerDeriveFlag flags =
META_MONITOR_MANAGER_DERIVE_FLAG_NONE;
apply_crtc_assignments (manager, crtcs, n_crtcs, outputs, n_outputs); apply_crtc_assignments (manager, crtcs, n_crtcs, outputs, n_outputs);
legacy_calculate_screen_size (manager); legacy_calculate_screen_size (manager);
meta_monitor_manager_rebuild_derived (manager); meta_monitor_manager_rebuild_derived (manager, flags);
} }
static void static void

View File

@ -55,7 +55,7 @@
#define DPI_FALLBACK 96.0 #define DPI_FALLBACK 96.0
static float supported_scales_xrandr[] = { static float supported_scales_xrandr[] = {
1.0 1.0, 2.0
}; };
struct _MetaMonitorManagerXrandr struct _MetaMonitorManagerXrandr
@ -68,6 +68,8 @@ struct _MetaMonitorManagerXrandr
int rr_error_base; int rr_error_base;
gboolean has_randr15; gboolean has_randr15;
xcb_timestamp_t last_xrandr_set_timestamp;
#ifdef HAVE_XRANDR15 #ifdef HAVE_XRANDR15
GHashTable *tiled_monitor_atoms; GHashTable *tiled_monitor_atoms;
#endif /* HAVE_XRANDR15 */ #endif /* HAVE_XRANDR15 */
@ -1071,6 +1073,7 @@ output_set_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
static gboolean static gboolean
xrandr_set_crtc_config (MetaMonitorManagerXrandr *manager_xrandr, xrandr_set_crtc_config (MetaMonitorManagerXrandr *manager_xrandr,
gboolean save_timestamp,
xcb_randr_crtc_t crtc, xcb_randr_crtc_t crtc,
xcb_timestamp_t timestamp, xcb_timestamp_t timestamp,
int x, int x,
@ -1107,13 +1110,141 @@ xrandr_set_crtc_config (MetaMonitorManagerXrandr *manager_xrandr,
return FALSE; return FALSE;
} }
if (save_timestamp)
manager_xrandr->last_xrandr_set_timestamp = reply->timestamp;
free (reply); free (reply);
return TRUE; 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 static void
apply_crtc_assignments (MetaMonitorManager *manager, apply_crtc_assignments (MetaMonitorManager *manager,
gboolean save_timestamp,
MetaCrtcInfo **crtcs, MetaCrtcInfo **crtcs,
unsigned int n_crtcs, unsigned int n_crtcs,
MetaOutputInfo **outputs, MetaOutputInfo **outputs,
@ -1163,6 +1294,7 @@ apply_crtc_assignments (MetaMonitorManager *manager,
crtc->rect.y + crtc->rect.height > height) crtc->rect.y + crtc->rect.height > height)
{ {
xrandr_set_crtc_config (manager_xrandr, xrandr_set_crtc_config (manager_xrandr,
save_timestamp,
(xcb_randr_crtc_t) crtc->crtc_id, (xcb_randr_crtc_t) crtc->crtc_id,
XCB_CURRENT_TIME, XCB_CURRENT_TIME,
0, 0, XCB_NONE, 0, 0, XCB_NONE,
@ -1191,6 +1323,7 @@ apply_crtc_assignments (MetaMonitorManager *manager,
continue; continue;
xrandr_set_crtc_config (manager_xrandr, xrandr_set_crtc_config (manager_xrandr,
save_timestamp,
(xcb_randr_crtc_t) crtc->crtc_id, (xcb_randr_crtc_t) crtc->crtc_id,
XCB_CURRENT_TIME, XCB_CURRENT_TIME,
0, 0, XCB_NONE, 0, 0, XCB_NONE,
@ -1247,6 +1380,7 @@ apply_crtc_assignments (MetaMonitorManager *manager,
rotation = meta_monitor_transform_to_xrandr (crtc_info->transform); rotation = meta_monitor_transform_to_xrandr (crtc_info->transform);
if (!xrandr_set_crtc_config (manager_xrandr, if (!xrandr_set_crtc_config (manager_xrandr,
save_timestamp,
(xcb_randr_crtc_t) crtc->crtc_id, (xcb_randr_crtc_t) crtc->crtc_id,
XCB_CURRENT_TIME, XCB_CURRENT_TIME,
crtc_info->x, crtc_info->y, crtc_info->x, crtc_info->y,
@ -1329,6 +1463,9 @@ apply_crtc_assignments (MetaMonitorManager *manager,
static void static void
meta_monitor_manager_xrandr_ensure_initial_config (MetaMonitorManager *manager) meta_monitor_manager_xrandr_ensure_initial_config (MetaMonitorManager *manager)
{ {
MetaMonitorManagerDeriveFlag flags =
META_MONITOR_MANAGER_DERIVE_FLAG_NONE;
meta_monitor_manager_ensure_configured (manager); 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_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 static gboolean
@ -1352,7 +1492,10 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *mana
if (!config) 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; return TRUE;
} }
@ -1363,11 +1506,35 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *mana
if (method != META_MONITORS_CONFIG_METHOD_VERIFY) if (method != META_MONITORS_CONFIG_METHOD_VERIFY)
{ {
apply_crtc_assignments (manager, /*
(MetaCrtcInfo **) crtc_infos->pdata, * If the assignment has not changed, we won't get any notification about
crtc_infos->len, * any new configuration from the X server; but we still need to update
(MetaOutputInfo **) output_infos->pdata, * our own configuration, as something not applicable in Xrandr might
output_infos->len); * 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); g_ptr_array_free (crtc_infos, TRUE);
@ -1383,7 +1550,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
MetaOutputInfo **outputs, MetaOutputInfo **outputs,
unsigned int n_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 static void
@ -1629,8 +1796,7 @@ meta_monitor_manager_xrandr_calculate_monitor_mode_scale (MetaMonitorManager *ma
MetaMonitor *monitor, MetaMonitor *monitor,
MetaMonitorMode *monitor_mode) MetaMonitorMode *monitor_mode)
{ {
/* X11 does not support anything other than scale 1. */ return meta_monitor_calculate_mode_scale (monitor, monitor_mode);
return 1;
} }
static void static void
@ -1645,7 +1811,8 @@ meta_monitor_manager_xrandr_get_supported_scales (MetaMonitorManager *manager,
static MetaMonitorManagerCapability static MetaMonitorManagerCapability
meta_monitor_manager_xrandr_get_capabilities (MetaMonitorManager *manager) 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 static gboolean
@ -1665,11 +1832,7 @@ meta_monitor_manager_xrandr_get_max_screen_size (MetaMonitorManager *manager,
static MetaLogicalMonitorLayoutMode static MetaLogicalMonitorLayoutMode
meta_monitor_manager_xrandr_get_default_layout_mode (MetaMonitorManager *manager) meta_monitor_manager_xrandr_get_default_layout_mode (MetaMonitorManager *manager)
{ {
/* return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
* 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;
} }
static void static void
@ -1763,7 +1926,8 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
XEvent *event) XEvent *event)
{ {
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr); 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) if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
return FALSE; return FALSE;
@ -1772,16 +1936,24 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
meta_monitor_manager_read_current_state (manager); 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); meta_monitor_manager_on_hotplug (manager);
} }
else else
{ {
/* Something else changed -- tell the world about it. */ MetaMonitorManagerDeriveFlag flags =
meta_monitor_manager_rebuild_derived (manager); 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; return TRUE;

View File

@ -401,6 +401,10 @@
* "supports-changing-layout-mode" (b): True if the layout mode can be * "supports-changing-layout-mode" (b): True if the layout mode can be
changed. Absence of this means the changed. Absence of this means the
layout mode cannot be changed. 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.
--> -->
<method name="GetCurrentState"> <method name="GetCurrentState">
<arg name="serial" direction="out" type="u" /> <arg name="serial" direction="out" type="u" />

View File

@ -123,9 +123,16 @@ meta_monitor_manager_test_ensure_initial_config (MetaMonitorManager *manager)
config = meta_monitor_manager_ensure_configured (manager); config = meta_monitor_manager_ensure_configured (manager);
if (meta_is_monitor_config_manager_enabled ()) if (meta_is_monitor_config_manager_enabled ())
meta_monitor_manager_update_logical_state (manager, config); {
meta_monitor_manager_update_logical_state (manager, config);
}
else 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 static void
@ -279,9 +286,16 @@ meta_monitor_manager_test_apply_monitors_config (MetaMonitorManager *manage
manager->screen_height = 1; manager->screen_height = 1;
if (meta_is_stage_views_enabled ()) if (meta_is_stage_views_enabled ())
meta_monitor_manager_rebuild (manager, NULL); {
meta_monitor_manager_rebuild (manager, NULL);
}
else 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; return TRUE;
} }
@ -311,9 +325,16 @@ meta_monitor_manager_test_apply_monitors_config (MetaMonitorManager *manage
update_screen_size (manager, config); update_screen_size (manager, config);
if (meta_is_stage_views_enabled ()) if (meta_is_stage_views_enabled ())
meta_monitor_manager_rebuild (manager, config); {
meta_monitor_manager_rebuild (manager, config);
}
else 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; return TRUE;
} }
@ -343,9 +364,12 @@ meta_monitor_manager_test_apply_configuration (MetaMonitorManager *manager,
MetaOutputInfo **outputs, MetaOutputInfo **outputs,
unsigned int n_outputs) unsigned int n_outputs)
{ {
MetaMonitorManagerDeriveFlag flags =
META_MONITOR_MANAGER_DERIVE_FLAG_NONE;
apply_crtc_assignments (manager, crtcs, n_crtcs, outputs, n_outputs); apply_crtc_assignments (manager, crtcs, n_crtcs, outputs, n_outputs);
legacy_calculate_screen_size (manager); legacy_calculate_screen_size (manager);
meta_monitor_manager_rebuild_derived (manager); meta_monitor_manager_rebuild_derived (manager, flags);
} }
static void static void