Add support for scaled logical monitor framebuffers

This commit adds support for rendering onto enlarged per logical
monitor framebuffers, using the scaled clutter stage views, for HiDPI
enabled logical monitors.

This works by scaling the mode of the monitors in a logical monitors by
the scale, no longer relying on scaling the window actors and window
geometry for making windows have the correct size on HiDPI monitors.

It is disabled by default, as in automatically created configurations
will still use the old mode. This is partly because Xwayland clients
will not yet work good enough to make it feasible.

To enable, add the 'scale-monitor-framebuffer' keyword to the
org.gnome.mutter.experimental-features gsettings array.

It is still possible to specify the mode via the new D-Bus API, which
has been adapted.

The adaptations to the D-Bus API means the caller need to be aware of
how to position logical monitors on the stage grid. This depends on the
'layout-mode' property that is used (see the DisplayConfig D-Bus
documentation).

https://bugzilla.gnome.org/show_bug.cgi?id=777732
This commit is contained in:
Jonas Ådahl 2017-02-24 18:10:52 +08:00
parent 094e0356e8
commit 8163ca6821
26 changed files with 721 additions and 118 deletions

View File

@ -112,7 +112,14 @@
available, or configurable. Don't expect adding anything in this
setting to be future proof.
Currently possible keywords: (none)
Currently possible keywords:
* "scale-monitor-framebuffer" - makes mutter default to layout logical
monitors in a logical pixel coordinate
space, while scaling monitor
framebuffers instead of window content,
to manage HiDPI monitors. Does not
require a restart.
</description>
</key>

View File

@ -100,6 +100,7 @@ struct _MetaBackendClass
typedef enum _MetaExperimentalFeature
{
META_EXPERIMENTAL_FEATURE_NONE = 0,
META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER = (1 << 0)
} MetaExperimentalFeature;
void meta_init_backend (GType backend_gtype);
@ -161,6 +162,8 @@ void meta_backend_enable_experimental_feature (MetaBackend *backend,
gboolean meta_is_stage_views_enabled (void);
gboolean meta_is_stage_views_scaled (void);
MetaInputSettings *meta_backend_get_input_settings (MetaBackend *backend);
#endif /* META_BACKEND_PRIVATE_H */

View File

@ -428,7 +428,10 @@ experimental_features_handler (GVariant *features_variant,
while (g_variant_iter_loop (&features_iter, "s", &feature))
{
/* So far no experimental features defined. */
g_info ("Unknown experimental feature '%s'\n", feature);
if (g_str_equal (feature, "scale-monitor-framebuffer"))
features |= META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER;
else
g_info ("Unknown experimental feature '%s'\n", feature);
}
if (features != priv->experimental_features)
@ -968,6 +971,22 @@ meta_is_stage_views_enabled (void)
return !g_str_equal (mutter_stage_views, "0");
}
gboolean
meta_is_stage_views_scaled (void)
{
MetaBackend *backend = meta_get_backend ();
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
MetaLogicalMonitorLayoutMode layout_mode;
if (!meta_is_stage_views_enabled ())
return FALSE;
layout_mode = monitor_manager->layout_mode;
return layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL;
}
MetaInputSettings *
meta_backend_get_input_settings (MetaBackend *backend)
{

View File

@ -78,7 +78,7 @@ meta_logical_monitor_new (MetaMonitorManager *monitor_manager,
logical_monitor->number = monitor_number;
logical_monitor->winsys_id = main_output->winsys_id;
logical_monitor->scale = logical_monitor_config->scale,
logical_monitor->scale = logical_monitor_config->scale;
logical_monitor->in_fullscreen = -1;
logical_monitor->rect = logical_monitor_config->layout;

View File

@ -60,9 +60,9 @@ G_DECLARE_FINAL_TYPE (MetaLogicalMonitor, meta_logical_monitor,
META, LOGICAL_MONITOR,
GObject)
MetaLogicalMonitor * meta_logical_monitor_new (MetaMonitorManager *monitor_manager,
MetaLogicalMonitorConfig *logical_monitor_config,
int monitor_number);
MetaLogicalMonitor * meta_logical_monitor_new (MetaMonitorManager *monitor_manager,
MetaLogicalMonitorConfig *logical_monitor_config,
int monitor_number);
MetaLogicalMonitor * meta_logical_monitor_new_derived (MetaMonitorManager *monitor_manager,
MetaMonitor *monitor,

View File

@ -51,8 +51,8 @@ meta_monitor_config_manager_new (MetaMonitorManager *monitor_manager)
config_manager = g_object_new (META_TYPE_MONITOR_CONFIG_MANAGER, NULL);
config_manager->monitor_manager = monitor_manager;
config_manager->config_store = g_object_new (META_TYPE_MONITOR_CONFIG_STORE,
NULL);
config_manager->config_store =
meta_monitor_config_store_new (monitor_manager);
return config_manager;
}
@ -461,10 +461,11 @@ create_monitor_config (MetaMonitor *monitor,
}
static MetaLogicalMonitorConfig *
create_preferred_logical_monitor_config (MetaMonitorManager *monitor_manager,
MetaMonitor *monitor,
int x,
int y)
create_preferred_logical_monitor_config (MetaMonitorManager *monitor_manager,
MetaMonitor *monitor,
int x,
int y,
MetaLogicalMonitorLayoutMode layout_mode)
{
MetaMonitorMode *mode;
int width, height;
@ -478,6 +479,16 @@ create_preferred_logical_monitor_config (MetaMonitorManager *monitor_manager,
monitor,
mode);
switch (layout_mode)
{
case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
width /= scale;
height /= scale;
break;
case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL:
break;
}
monitor_config = create_monitor_config (monitor, mode);
logical_monitor_config = g_new0 (MetaLogicalMonitorConfig, 1);
@ -501,6 +512,7 @@ meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_mana
MetaMonitorManager *monitor_manager = config_manager->monitor_manager;
GList *logical_monitor_configs;
MetaMonitor *primary_monitor;
MetaLogicalMonitorLayoutMode layout_mode;
MetaLogicalMonitorConfig *primary_logical_monitor_config;
int x;
GList *monitors;
@ -510,10 +522,13 @@ meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_mana
if (!primary_monitor)
return NULL;
layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager);
primary_logical_monitor_config =
create_preferred_logical_monitor_config (monitor_manager,
primary_monitor,
0, 0);
0, 0,
layout_mode);
primary_logical_monitor_config->is_primary = TRUE;
logical_monitor_configs = g_list_append (NULL,
primary_logical_monitor_config);
@ -535,14 +550,15 @@ meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_mana
logical_monitor_config =
create_preferred_logical_monitor_config (monitor_manager,
monitor,
x, 0);
x, 0,
layout_mode);
logical_monitor_configs = g_list_append (logical_monitor_configs,
logical_monitor_config);
x += logical_monitor_config->layout.width;
}
return meta_monitors_config_new (logical_monitor_configs);
return meta_monitors_config_new (logical_monitor_configs, layout_mode);
}
MetaMonitorsConfig *
@ -551,21 +567,25 @@ meta_monitor_config_manager_create_fallback (MetaMonitorConfigManager *config_ma
MetaMonitorManager *monitor_manager = config_manager->monitor_manager;
MetaMonitor *primary_monitor;
GList *logical_monitor_configs;
MetaLogicalMonitorLayoutMode layout_mode;
MetaLogicalMonitorConfig *primary_logical_monitor_config;
primary_monitor = find_primary_monitor (monitor_manager);
if (!primary_monitor)
return NULL;
layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager);
primary_logical_monitor_config =
create_preferred_logical_monitor_config (monitor_manager,
primary_monitor,
0, 0);
0, 0,
layout_mode);
primary_logical_monitor_config->is_primary = TRUE;
logical_monitor_configs = g_list_append (NULL,
primary_logical_monitor_config);
return meta_monitors_config_new (logical_monitor_configs);
return meta_monitors_config_new (logical_monitor_configs, layout_mode);
}
MetaMonitorsConfig *
@ -574,6 +594,7 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m
MetaMonitorManager *monitor_manager = config_manager->monitor_manager;
MetaLogicalMonitorConfig *primary_logical_monitor_config = NULL;
MetaMonitor *primary_monitor;
MetaLogicalMonitorLayoutMode layout_mode;
GList *logical_monitor_configs;
GList *region;
GList *monitors;
@ -583,6 +604,8 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m
if (!primary_monitor)
return NULL;
layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager);
logical_monitor_configs = NULL;
region = NULL;
monitors = meta_monitor_manager_get_monitors (monitor_manager);
@ -598,7 +621,8 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m
logical_monitor_config =
create_preferred_logical_monitor_config (monitor_manager,
monitor,
x, y);
x, y,
layout_mode);
logical_monitor_configs = g_list_append (logical_monitor_configs,
logical_monitor_config);
@ -629,7 +653,7 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m
primary_logical_monitor_config->is_primary = TRUE;
return meta_monitors_config_new (logical_monitor_configs);
return meta_monitors_config_new (logical_monitor_configs, layout_mode);
}
void
@ -774,13 +798,15 @@ meta_monitors_config_key_equal (gconstpointer data_a,
}
MetaMonitorsConfig *
meta_monitors_config_new (GList *logical_monitor_configs)
meta_monitors_config_new (GList *logical_monitor_configs,
MetaLogicalMonitorLayoutMode layout_mode)
{
MetaMonitorsConfig *config;
config = g_object_new (META_TYPE_MONITORS_CONFIG, NULL);
config->logical_monitor_configs = logical_monitor_configs;
config->key = meta_monitors_config_key_new (logical_monitor_configs);
config->layout_mode = layout_mode;
return config;
}
@ -862,12 +888,13 @@ meta_verify_monitor_config (MetaMonitorConfig *monitor_config,
}
gboolean
meta_verify_logical_monitor_config (MetaLogicalMonitorConfig *logical_monitor_config,
GError **error)
meta_verify_logical_monitor_config (MetaLogicalMonitorConfig *logical_monitor_config,
MetaLogicalMonitorLayoutMode layout_mode,
GError **error)
{
GList *l;
int layout_width;
int layout_height;
int expected_mode_width = 0;
int expected_mode_height = 0;
if (logical_monitor_config->scale < 1)
{
@ -894,14 +921,26 @@ meta_verify_logical_monitor_config (MetaLogicalMonitorConfig *logical_monitor_co
return FALSE;
}
layout_width = logical_monitor_config->layout.width;
layout_height = logical_monitor_config->layout.height;
switch (layout_mode)
{
case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
expected_mode_width = (logical_monitor_config->layout.width *
logical_monitor_config->scale);
expected_mode_height = (logical_monitor_config->layout.height *
logical_monitor_config->scale);
break;
case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL:
expected_mode_width = logical_monitor_config->layout.width;
expected_mode_height = logical_monitor_config->layout.height;
break;
}
for (l = logical_monitor_config->monitor_configs; l; l = l->next)
{
MetaMonitorConfig *monitor_config = l->data;
if (monitor_config->mode_spec->width != layout_width ||
monitor_config->mode_spec->height != layout_height)
if (monitor_config->mode_spec->width != expected_mode_width ||
monitor_config->mode_spec->height != expected_mode_height)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Monitor modes in logical monitor conflict");

View File

@ -56,6 +56,8 @@ struct _MetaMonitorsConfig
MetaMonitorsConfigKey *key;
GList *logical_monitor_configs;
MetaLogicalMonitorLayoutMode layout_mode;
};
#define META_TYPE_MONITORS_CONFIG (meta_monitors_config_get_type ())
@ -85,7 +87,8 @@ void meta_monitor_config_manager_set_current (MetaMonitorConfigManager *config_m
MetaMonitorsConfig * meta_monitor_config_manager_get_current (MetaMonitorConfigManager *config_manager);
MetaMonitorsConfig * meta_monitors_config_new (GList *logical_monitor_configs);
MetaMonitorsConfig * meta_monitors_config_new (GList *logical_monitor_configs,
MetaLogicalMonitorLayoutMode layout_mode);
unsigned int meta_monitors_config_key_hash (gconstpointer config_key);
@ -107,8 +110,9 @@ gboolean meta_verify_monitor_spec (MetaMonitorSpec *monitor_spec,
gboolean meta_verify_monitor_config (MetaMonitorConfig *monitor_config,
GError **error);
gboolean meta_verify_logical_monitor_config (MetaLogicalMonitorConfig *logical_monitor_config,
GError **error);
gboolean meta_verify_logical_monitor_config (MetaLogicalMonitorConfig *logical_monitor_config,
MetaLogicalMonitorLayoutMode layout_mode,
GError **error);
gboolean meta_verify_monitors_config (MetaMonitorsConfig *config,
GError **error);

View File

@ -81,6 +81,8 @@ struct _MetaMonitorConfigStore
{
GObject parent;
MetaMonitorManager *monitor_manager;
GHashTable *configs;
};
@ -355,11 +357,13 @@ handle_start_element (GMarkupParseContext *context,
}
static gboolean
derive_logical_monitor_layout (MetaLogicalMonitorConfig *logical_monitor_config,
GError **error)
derive_logical_monitor_layout (MetaLogicalMonitorConfig *logical_monitor_config,
MetaLogicalMonitorLayoutMode layout_mode,
GError **error)
{
MetaMonitorConfig *monitor_config;
int mode_width, mode_height;
int width = 0, height = 0;
GList *l;
monitor_config = logical_monitor_config->monitor_configs->data;
@ -379,8 +383,19 @@ derive_logical_monitor_layout (MetaLogicalMonitorConfig *logical_monitor_config,
}
}
logical_monitor_config->layout.width = mode_width;
logical_monitor_config->layout.height = mode_height;
switch (layout_mode)
{
case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
width = mode_width / logical_monitor_config->scale;
height = mode_height / logical_monitor_config->scale;
break;
case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL:
width = mode_width;
height = mode_height;
}
logical_monitor_config->layout.width = width;
logical_monitor_config->layout.height = height;
return TRUE;
}
@ -491,12 +506,6 @@ handle_end_element (GMarkupParseContext *context,
if (logical_monitor_config->scale == 0)
logical_monitor_config->scale = 1;
if (!derive_logical_monitor_layout (logical_monitor_config, error))
return;
if (!meta_verify_logical_monitor_config (logical_monitor_config, error))
return;
parser->current_logical_monitor_configs =
g_list_append (parser->current_logical_monitor_configs,
logical_monitor_config);
@ -508,12 +517,34 @@ handle_end_element (GMarkupParseContext *context,
case STATE_CONFIGURATION:
{
MetaMonitorConfigStore *store = parser->config_store;
MetaMonitorsConfig *config;
GList *l;
MetaLogicalMonitorLayoutMode layout_mode;
g_assert (g_str_equal (element_name, "configuration"));
layout_mode =
meta_monitor_manager_get_default_layout_mode (store->monitor_manager);
for (l = parser->current_logical_monitor_configs; l; l = l->next)
{
MetaLogicalMonitorConfig *logical_monitor_config = l->data;
if (!derive_logical_monitor_layout (logical_monitor_config,
layout_mode,
error))
return;
if (!meta_verify_logical_monitor_config (logical_monitor_config,
layout_mode,
error))
return;
}
config =
meta_monitors_config_new (parser->current_logical_monitor_configs);
meta_monitors_config_new (parser->current_logical_monitor_configs,
layout_mode);
if (!meta_verify_monitors_config (config, error))
{
@ -852,6 +883,17 @@ meta_monitor_config_store_get_config_count (MetaMonitorConfigStore *config_store
return (int) g_hash_table_size (config_store->configs);
}
MetaMonitorConfigStore *
meta_monitor_config_store_new (MetaMonitorManager *monitor_manager)
{
MetaMonitorConfigStore *store;
store = g_object_new (META_TYPE_MONITOR_CONFIG_STORE, NULL);
store->monitor_manager = monitor_manager;
return store;
}
static void
meta_monitor_config_store_dispose (GObject *object)
{

View File

@ -30,6 +30,8 @@
G_DECLARE_FINAL_TYPE (MetaMonitorConfigStore, meta_monitor_config_store,
META, MONITOR_CONFIG_STORE, GObject)
MetaMonitorConfigStore * meta_monitor_config_store_new (MetaMonitorManager *monitor_manager);
MetaMonitorsConfig * meta_monitor_config_store_lookup (MetaMonitorConfigStore *config_store,
MetaMonitorsConfigKey *key);

View File

@ -605,10 +605,30 @@ meta_monitor_manager_dummy_get_supported_scales (MetaMonitorManager *manager,
*n_scales = G_N_ELEMENTS (supported_scales_dummy);
}
static gboolean
is_monitor_framebuffers_scaled (void)
{
MetaBackend *backend = meta_get_backend ();
return meta_backend_is_experimental_feature_enabled (
backend,
META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER);
}
static MetaMonitorManagerCapability
meta_monitor_manager_dummy_get_capabilities (MetaMonitorManager *manager)
{
return META_MONITOR_MANAGER_CAPABILITY_MIRRORING;
MetaMonitorManagerCapability capabilities =
META_MONITOR_MANAGER_CAPABILITY_NONE;
capabilities |= META_MONITOR_MANAGER_CAPABILITY_MIRRORING;
if (meta_backend_is_experimental_feature_enabled (
meta_get_backend (),
META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER))
capabilities |= META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE;
return capabilities;
}
static gboolean
@ -625,6 +645,18 @@ meta_monitor_manager_dummy_get_max_screen_size (MetaMonitorManager *manager,
return TRUE;
}
static MetaLogicalMonitorLayoutMode
meta_monitor_manager_dummy_get_default_layout_mode (MetaMonitorManager *manager)
{
if (!meta_is_stage_views_enabled ())
return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
if (is_monitor_framebuffers_scaled ())
return META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL;
else
return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
}
static void
meta_monitor_manager_dummy_class_init (MetaMonitorManagerDummyClass *klass)
{
@ -639,6 +671,7 @@ meta_monitor_manager_dummy_class_init (MetaMonitorManagerDummyClass *klass)
manager_class->get_supported_scales = meta_monitor_manager_dummy_get_supported_scales;
manager_class->get_capabilities = meta_monitor_manager_dummy_get_capabilities;
manager_class->get_max_screen_size = meta_monitor_manager_dummy_get_max_screen_size;
manager_class->get_default_layout_mode = meta_monitor_manager_dummy_get_default_layout_mode;
}
static void

View File

@ -71,7 +71,8 @@ typedef struct _MetaTileInfo MetaTileInfo;
typedef enum _MetaMonitorManagerCapability
{
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)
} MetaMonitorManagerCapability;
/* Equivalent to the 'method' enum in org.gnome.Mutter.DisplayConfig */
@ -82,6 +83,13 @@ typedef enum _MetaMonitorsConfigMethod
META_MONITORS_CONFIG_METHOD_PERSISTENT = 2
} MetaMonitorsConfigMethod;
/* Equivalent to the 'layout-mode' enum in org.gnome.Mutter.DisplayConfig */
typedef enum _MetaLogicalMonitorLayoutMode
{
META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL = 1,
META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL = 2
} MetaLogicalMonitorLayoutMode;
typedef enum
{
META_MONITOR_TRANSFORM_NORMAL,
@ -274,6 +282,8 @@ struct _MetaMonitorManager
MetaPowerSave power_save_mode;
MetaLogicalMonitorLayoutMode layout_mode;
int screen_width;
int screen_height;
@ -376,6 +386,8 @@ struct _MetaMonitorManagerClass
gboolean (*get_max_screen_size) (MetaMonitorManager *,
int *,
int *);
MetaLogicalMonitorLayoutMode (*get_default_layout_mode) (MetaMonitorManager *);
};
void meta_monitor_manager_rebuild (MetaMonitorManager *manager,
@ -479,6 +491,9 @@ gboolean meta_monitor_manager_get_max_screen_size (MetaMonitorManager
int *max_width,
int *max_height);
MetaLogicalMonitorLayoutMode
meta_monitor_manager_get_default_layout_mode (MetaMonitorManager *manager);
void meta_monitor_manager_clear_output (MetaOutput *output);
void meta_monitor_manager_clear_mode (MetaCrtcMode *mode);
void meta_monitor_manager_clear_crtc (MetaCrtc *crtc);

View File

@ -319,6 +319,16 @@ meta_monitor_manager_get_max_screen_size (MetaMonitorManager *manager,
return manager_class->get_max_screen_size (manager, max_width, max_height);
}
MetaLogicalMonitorLayoutMode
meta_monitor_manager_get_default_layout_mode (MetaMonitorManager *manager)
{
MetaMonitorManagerClass *manager_class =
META_MONITOR_MANAGER_GET_CLASS (manager);
return manager_class->get_default_layout_mode (manager);
}
static void
meta_monitor_manager_ensure_initial_config (MetaMonitorManager *manager)
{
@ -1397,6 +1407,13 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
g_variant_new_boolean (FALSE));
}
if (capabilities & META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE)
{
g_variant_builder_add (&properties_builder, "{sv}",
"layout-mode",
g_variant_new_uint32 (manager->layout_mode));
}
if (meta_monitor_manager_get_max_screen_size (manager,
&max_screen_width,
&max_screen_height))
@ -1593,10 +1610,12 @@ create_monitor_config_from_variant (MetaMonitorManager *manager,
}
static gboolean
derive_logical_monitor_size (GList *monitor_configs,
int *width,
int *height,
GError **error)
derive_logical_monitor_size (GList *monitor_configs,
int *width,
int *height,
double scale,
MetaLogicalMonitorLayoutMode layout_mode,
GError **error)
{
MetaMonitorConfig *monitor_config;
@ -1608,16 +1627,27 @@ derive_logical_monitor_size (GList *monitor_configs,
}
monitor_config = monitor_configs->data;
*width = monitor_config->mode_spec->width;
*height = monitor_config->mode_spec->height;
return TRUE;
switch (layout_mode)
{
case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
*width = monitor_config->mode_spec->width / scale;
*height = monitor_config->mode_spec->height / scale;
return TRUE;
case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL:
*width = monitor_config->mode_spec->width;
*height = monitor_config->mode_spec->height;
return TRUE;
}
g_assert_not_reached ();
}
static MetaLogicalMonitorConfig *
create_logical_monitor_config_from_variant (MetaMonitorManager *manager,
GVariant *logical_monitor_config_variant,
GError **error)
create_logical_monitor_config_from_variant (MetaMonitorManager *manager,
GVariant *logical_monitor_config_variant,
MetaLogicalMonitorLayoutMode layout_mode,
GError **error)
{
MetaLogicalMonitorConfig *logical_monitor_config;
int x, y, width, height;
@ -1658,7 +1688,8 @@ create_logical_monitor_config_from_variant (MetaMonitorManager *manager,
}
g_variant_iter_free (monitor_configs_iter);
if (!derive_logical_monitor_size (monitor_configs, &width, &height, error))
if (!derive_logical_monitor_size (monitor_configs, &width, &height,
scale, layout_mode, error))
goto err;
logical_monitor_config = g_new0 (MetaLogicalMonitorConfig, 1);
@ -1674,7 +1705,9 @@ create_logical_monitor_config_from_variant (MetaMonitorManager *manager,
.monitor_configs = monitor_configs
};
if (!meta_verify_logical_monitor_config (logical_monitor_config, error))
if (!meta_verify_logical_monitor_config (logical_monitor_config,
layout_mode,
error))
{
meta_logical_monitor_config_free (logical_monitor_config);
return NULL;
@ -1687,6 +1720,19 @@ err:
return NULL;
}
static gboolean
is_valid_layout_mode (MetaLogicalMonitorLayoutMode layout_mode)
{
switch (layout_mode)
{
case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL:
return TRUE;
}
return FALSE;
}
static gboolean
meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skeleton,
GDBusMethodInvocation *invocation,
@ -1696,6 +1742,9 @@ meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skelet
GVariant *properties_variant)
{
MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton);
MetaMonitorManagerCapability capabilities;
GVariant *layout_mode_variant = NULL;
MetaLogicalMonitorLayoutMode layout_mode;
GVariantIter logical_monitor_configs_iter;
MetaMonitorsConfig *config;
GList *logical_monitor_configs = NULL;
@ -1717,6 +1766,39 @@ meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skelet
return TRUE;
}
capabilities = meta_monitor_manager_get_capabilities (manager);
if (properties_variant)
layout_mode_variant = g_variant_lookup_value (properties_variant,
"layout-mode",
G_VARIANT_TYPE ("u"));
if (layout_mode_variant &&
capabilities & META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE)
{
g_variant_get (layout_mode_variant, "u", &layout_mode);
}
else if (!layout_mode_variant)
{
layout_mode =
meta_monitor_manager_get_default_layout_mode (manager);
}
else
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
"Can't set layout mode");
return TRUE;
}
if (!is_valid_layout_mode (layout_mode))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Invalid layout mode specified");
return TRUE;
}
g_variant_iter_init (&logical_monitor_configs_iter,
logical_monitor_configs_variant);
while (TRUE)
@ -1731,6 +1813,7 @@ meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skelet
logical_monitor_config =
create_logical_monitor_config_from_variant (manager,
logical_monitor_config_variant,
layout_mode,
&error);
if (!logical_monitor_config)
{
@ -1747,7 +1830,7 @@ meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skelet
logical_monitor_config);
}
config = meta_monitors_config_new (logical_monitor_configs);
config = meta_monitors_config_new (logical_monitor_configs, layout_mode);
if (!meta_verify_monitors_config (config, &error))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
@ -2416,6 +2499,12 @@ void
meta_monitor_manager_update_logical_state (MetaMonitorManager *manager,
MetaMonitorsConfig *config)
{
if (config)
manager->layout_mode = config->layout_mode;
else
manager->layout_mode =
meta_monitor_manager_get_default_layout_mode (manager);
meta_monitor_manager_rebuild_logical_monitors (manager, config);
}
@ -2455,6 +2544,8 @@ meta_monitor_manager_update_monitor_modes_derived (MetaMonitorManager *manager)
void
meta_monitor_manager_update_logical_state_derived (MetaMonitorManager *manager)
{
manager->layout_mode = META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
meta_monitor_manager_rebuild_logical_monitors_derived (manager);
}

View File

@ -35,6 +35,8 @@
#include <meta/meta-backend.h>
#include "backends/meta-backend-private.h"
#include "backends/meta-logical-monitor.h"
#include "backends/meta-monitor.h"
#include "backends/meta-monitor-manager-private.h"
#include "backends/native/meta-renderer-native.h"
#include "meta/boxes.h"
@ -214,50 +216,125 @@ set_crtc_cursor (MetaCursorRendererNative *native,
}
}
typedef struct
{
MetaCursorRendererNative *in_cursor_renderer_native;
MetaLogicalMonitor *in_logical_monitor;
MetaRectangle in_local_cursor_rect;
MetaCursorSprite *in_cursor_sprite;
gboolean out_painted;
} UpdateCrtcCursorData;
static gboolean
update_monitor_crtc_cursor (MetaMonitor *monitor,
MetaMonitorMode *monitor_mode,
MetaMonitorCrtcMode *monitor_crtc_mode,
gpointer user_data,
GError **error)
{
UpdateCrtcCursorData *data = user_data;
MetaCursorRendererNative *cursor_renderer_native =
data->in_cursor_renderer_native;
MetaCursorRendererNativePrivate *priv =
meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
MetaRectangle scaled_crtc_rect;
int scale;
if (meta_is_stage_views_scaled ())
scale = meta_logical_monitor_get_scale (data->in_logical_monitor);
else
scale = 1;
scaled_crtc_rect = (MetaRectangle) {
.x = monitor_crtc_mode->x / scale,
.y = monitor_crtc_mode->y / scale,
.width = monitor_crtc_mode->crtc_mode->width / scale,
.height = monitor_crtc_mode->crtc_mode->height / scale
};
if (priv->has_hw_cursor &&
meta_rectangle_overlap (&scaled_crtc_rect,
&data->in_local_cursor_rect))
{
int crtc_cursor_x, crtc_cursor_y;
set_crtc_cursor (data->in_cursor_renderer_native,
monitor_crtc_mode->output->crtc,
data->in_cursor_sprite);
crtc_cursor_x = (data->in_local_cursor_rect.x - scaled_crtc_rect.x) * scale;
crtc_cursor_y = (data->in_local_cursor_rect.y - scaled_crtc_rect.y) * scale;
drmModeMoveCursor (priv->drm_fd,
monitor_crtc_mode->output->crtc->crtc_id,
crtc_cursor_x,
crtc_cursor_y);
data->out_painted = data->out_painted || TRUE;
}
else
{
set_crtc_cursor (data->in_cursor_renderer_native,
monitor_crtc_mode->output->crtc, NULL);
}
return TRUE;
}
static void
update_hw_cursor (MetaCursorRendererNative *native,
MetaCursorSprite *cursor_sprite)
{
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
MetaMonitorManager *monitors;
MetaCrtc *crtcs;
unsigned int i, n_crtcs;
MetaBackend *backend = meta_get_backend ();
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
GList *logical_monitors;
GList *l;
MetaRectangle rect;
gboolean painted = FALSE;
monitors = meta_monitor_manager_get ();
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
if (cursor_sprite)
rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
else
rect = (MetaRectangle) { 0 };
for (i = 0; i < n_crtcs; i++)
logical_monitors =
meta_monitor_manager_get_logical_monitors (monitor_manager);
for (l = logical_monitors; l; l = l->next)
{
gboolean crtc_should_use_cursor;
MetaCursorSprite *crtc_cursor;
MetaRectangle *crtc_rect;
MetaLogicalMonitor *logical_monitor = l->data;
UpdateCrtcCursorData data;
GList *monitors;
GList *k;
crtc_rect = &crtcs[i].rect;
data = (UpdateCrtcCursorData) {
.in_cursor_renderer_native = native,
.in_logical_monitor = logical_monitor,
.in_local_cursor_rect = (MetaRectangle) {
.x = rect.x - logical_monitor->rect.x,
.y = rect.y - logical_monitor->rect.y,
.width = rect.width,
.height = rect.height
},
.in_cursor_sprite = cursor_sprite
};
crtc_should_use_cursor = (priv->has_hw_cursor &&
meta_rectangle_overlap (&rect, crtc_rect));
if (crtc_should_use_cursor)
crtc_cursor = cursor_sprite;
else
crtc_cursor = NULL;
set_crtc_cursor (native, &crtcs[i], crtc_cursor);
if (crtc_cursor)
monitors = meta_logical_monitor_get_monitors (logical_monitor);
for (k = monitors; k; k = k->next)
{
drmModeMoveCursor (priv->drm_fd, crtcs[i].crtc_id,
rect.x - crtc_rect->x,
rect.y - crtc_rect->y);
painted = TRUE;
MetaMonitor *monitor = k->data;
MetaMonitorMode *monitor_mode;
monitor_mode = meta_monitor_get_current_mode (monitor);
meta_monitor_mode_foreach_crtc (monitor, monitor_mode,
update_monitor_crtc_cursor,
&data,
NULL);
}
painted = painted || data.out_painted;
}
priv->hw_state_invalidated = FALSE;
@ -316,6 +393,55 @@ cursor_over_transformed_crtc (MetaCursorRenderer *renderer,
return FALSE;
}
static float
calculate_cursor_crtc_sprite_scale (MetaCursorSprite *cursor_sprite,
MetaLogicalMonitor *logical_monitor)
{
return (meta_logical_monitor_get_scale (logical_monitor) *
meta_cursor_sprite_get_texture_scale (cursor_sprite));
}
static gboolean
can_draw_cursor_unscaled (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite)
{
MetaBackend *backend;
MetaMonitorManager *monitor_manager;
MetaRectangle cursor_rect;
GList *logical_monitors;
GList *l;
gboolean has_visible_crtc_sprite = FALSE;
if (!meta_is_stage_views_scaled ())
return meta_cursor_sprite_get_texture_scale (cursor_sprite) == 1.0;
backend = meta_get_backend ();
monitor_manager = meta_backend_get_monitor_manager (backend);
logical_monitors =
meta_monitor_manager_get_logical_monitors (monitor_manager);
if (!logical_monitors)
return FALSE;
cursor_rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
for (l = logical_monitors; l; l = l->next)
{
MetaLogicalMonitor *logical_monitor = l->data;
if (!meta_rectangle_overlap (&cursor_rect, &logical_monitor->rect))
continue;
if (calculate_cursor_crtc_sprite_scale (cursor_sprite,
logical_monitor) != 1.0)
return FALSE;
has_visible_crtc_sprite = TRUE;
}
return has_visible_crtc_sprite;
}
static gboolean
should_have_hw_cursor (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite)
@ -337,7 +463,7 @@ should_have_hw_cursor (MetaCursorRenderer *renderer,
if (!texture)
return FALSE;
if (meta_cursor_sprite_get_texture_scale (cursor_sprite) != 1)
if (!can_draw_cursor_unscaled (renderer, cursor_sprite))
return FALSE;
if (!has_valid_cursor_sprite_gbm_bo (cursor_sprite))

View File

@ -1937,6 +1937,11 @@ meta_monitor_manager_kms_get_capabilities (MetaMonitorManager *manager)
MetaMonitorManagerCapability capabilities =
META_MONITOR_MANAGER_CAPABILITY_NONE;
if (meta_backend_is_experimental_feature_enabled (
backend,
META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER))
capabilities |= META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE;
switch (meta_renderer_native_get_mode (renderer_native))
{
case META_RENDERER_NATIVE_MODE_GBM:
@ -1967,6 +1972,20 @@ meta_monitor_manager_kms_get_max_screen_size (MetaMonitorManager *manager,
return TRUE;
}
static MetaLogicalMonitorLayoutMode
meta_monitor_manager_kms_get_default_layout_mode (MetaMonitorManager *manager)
{
if (!meta_is_stage_views_enabled ())
return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
if (meta_backend_is_experimental_feature_enabled (
meta_get_backend (),
META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER))
return META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL;
else
return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
}
static void
meta_monitor_manager_kms_dispose (GObject *object)
{
@ -2011,4 +2030,5 @@ meta_monitor_manager_kms_class_init (MetaMonitorManagerKmsClass *klass)
manager_class->get_supported_scales = meta_monitor_manager_kms_get_supported_scales;
manager_class->get_capabilities = meta_monitor_manager_kms_get_capabilities;
manager_class->get_max_screen_size = meta_monitor_manager_kms_get_max_screen_size;
manager_class->get_default_layout_mode = meta_monitor_manager_kms_get_default_layout_mode;
}

View File

@ -1707,16 +1707,26 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
MetaMonitorTransform view_transform;
CoglOnscreen *onscreen = NULL;
CoglOffscreen *offscreen = NULL;
int scale;
int width, height;
MetaRendererView *view;
GError *error = NULL;
view_transform = calculate_view_transform (monitor_manager, logical_monitor);
if (meta_is_stage_views_scaled ())
scale = logical_monitor->scale;
else
scale = 1;
width = logical_monitor->rect.width * scale;
height = logical_monitor->rect.height * scale;
onscreen = meta_renderer_native_create_onscreen (META_RENDERER_NATIVE (renderer),
cogl_context,
view_transform,
logical_monitor->rect.width,
logical_monitor->rect.height);
width,
height);
if (!onscreen)
meta_fatal ("Failed to allocate onscreen framebuffer\n");
@ -1725,14 +1735,15 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
offscreen = meta_renderer_native_create_offscreen (META_RENDERER_NATIVE (renderer),
cogl_context,
view_transform,
logical_monitor->rect.width,
logical_monitor->rect.height);
width,
height);
if (!offscreen)
meta_fatal ("Failed to allocate back buffer texture\n");
}
view = g_object_new (META_TYPE_RENDERER_VIEW,
"layout", &logical_monitor->rect,
"scale", scale,
"framebuffer", onscreen,
"offscreen", offscreen,
"logical-monitor", logical_monitor,

View File

@ -1623,6 +1623,16 @@ meta_monitor_manager_xrandr_get_max_screen_size (MetaMonitorManager *manager,
return TRUE;
}
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;
}
static void
meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
{
@ -1703,6 +1713,7 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
manager_class->get_supported_scales = meta_monitor_manager_xrandr_get_supported_scales;
manager_class->get_capabilities = meta_monitor_manager_xrandr_get_capabilities;
manager_class->get_max_screen_size = meta_monitor_manager_xrandr_get_max_screen_size;
manager_class->get_default_layout_mode = meta_monitor_manager_xrandr_get_default_layout_mode;
quark_meta_monitor_xrandr_data =
g_quark_from_static_string ("-meta-monitor-xrandr-data");

View File

@ -122,6 +122,7 @@ meta_renderer_x11_create_view (MetaRenderer *renderer,
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
MetaMonitorTransform view_transform;
int view_scale;
int width, height;
CoglTexture2D *texture_2d;
CoglOffscreen *fake_onscreen;
@ -130,11 +131,16 @@ meta_renderer_x11_create_view (MetaRenderer *renderer,
g_assert (meta_is_wayland_compositor ());
width = logical_monitor->rect.width;
height = logical_monitor->rect.height;
view_transform = calculate_view_transform (monitor_manager, logical_monitor);
if (meta_is_stage_views_scaled ())
view_scale = logical_monitor->scale;
else
view_scale = 1;
width = logical_monitor->rect.width * view_scale;
height = logical_monitor->rect.height * view_scale;
texture_2d = cogl_texture_2d_new_with_size (cogl_context, width, height);
fake_onscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (texture_2d));
@ -158,6 +164,7 @@ meta_renderer_x11_create_view (MetaRenderer *renderer,
"framebuffer", COGL_FRAMEBUFFER (fake_onscreen),
"offscreen", COGL_FRAMEBUFFER (offscreen),
"transform", view_transform,
"scale", view_scale,
NULL);
}

View File

@ -35,6 +35,7 @@
#include "wayland/meta-wayland-private.h"
#include "wayland/meta-window-wayland.h"
#include "backends/meta-backend-private.h"
#include "compositor/region-utils.h"
enum {
@ -104,9 +105,12 @@ meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *self)
window = meta_wayland_surface_get_toplevel_window (surface);
/* XXX: We do not handle x11 clients yet */
if (window && window->client_type != META_WINDOW_CLIENT_TYPE_X11)
geometry_scale = meta_window_wayland_get_geometry_scale (window);
if (!meta_is_stage_views_scaled ())
{
/* XXX: We do not handle x11 clients yet */
if (window && window->client_type != META_WINDOW_CLIENT_TYPE_X11)
geometry_scale = meta_window_wayland_get_geometry_scale (window);
}
return (double) geometry_scale / (double) surface->scale;
}

View File

@ -1279,6 +1279,37 @@ update_num_workspaces (MetaScreen *screen,
g_object_notify (G_OBJECT (screen), "n-workspaces");
}
static int
find_highest_logical_monitor_scale (MetaBackend *backend,
MetaCursorSprite *cursor_sprite)
{
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
MetaCursorRenderer *cursor_renderer =
meta_backend_get_cursor_renderer (backend);
MetaRectangle cursor_rect;
GList *logical_monitors;
GList *l;
int highest_scale = 0.0;
cursor_rect = meta_cursor_renderer_calculate_rect (cursor_renderer,
cursor_sprite);
logical_monitors =
meta_monitor_manager_get_logical_monitors (monitor_manager);
for (l = logical_monitors; l; l = l->next)
{
MetaLogicalMonitor *logical_monitor = l->data;
if (!meta_rectangle_overlap (&cursor_rect, &logical_monitor->rect))
continue;
highest_scale = MAX (highest_scale, logical_monitor->scale);
}
return highest_scale;
}
static void
root_cursor_prepare_at (MetaCursorSprite *cursor_sprite,
int x,
@ -1286,16 +1317,35 @@ root_cursor_prepare_at (MetaCursorSprite *cursor_sprite,
MetaScreen *screen)
{
MetaBackend *backend = meta_get_backend ();
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
MetaLogicalMonitor *logical_monitor;
logical_monitor =
meta_monitor_manager_get_logical_monitor_at (monitor_manager, x, y);
if (meta_is_stage_views_scaled ())
{
int scale;
/* Reload the cursor texture if the scale has changed. */
if (logical_monitor)
meta_cursor_sprite_set_theme_scale (cursor_sprite, logical_monitor->scale);
scale = find_highest_logical_monitor_scale (backend, cursor_sprite);
if (scale != 0.0)
{
meta_cursor_sprite_set_theme_scale (cursor_sprite, scale);
meta_cursor_sprite_set_texture_scale (cursor_sprite, 1.0 / scale);
}
}
else
{
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
MetaLogicalMonitor *logical_monitor;
logical_monitor =
meta_monitor_manager_get_logical_monitor_at (monitor_manager, x, y);
/* Reload the cursor texture if the scale has changed. */
if (logical_monitor)
{
meta_cursor_sprite_set_theme_scale (cursor_sprite,
logical_monitor->scale);
meta_cursor_sprite_set_texture_scale (cursor_sprite, 1.0);
}
}
}
static void
@ -2206,6 +2256,9 @@ static void
on_monitors_changed (MetaMonitorManager *manager,
MetaScreen *screen)
{
MetaBackend *backend;
MetaCursorRenderer *cursor_renderer;
meta_monitor_manager_get_screen_size (manager,
&screen->rect.width,
&screen->rect.height);
@ -2237,6 +2290,10 @@ on_monitors_changed (MetaMonitorManager *manager,
meta_screen_queue_check_fullscreen (screen);
backend = meta_get_backend ();
cursor_renderer = meta_backend_get_cursor_renderer (backend);
meta_cursor_renderer_force_update (cursor_renderer);
g_signal_emit (screen, screen_signals[MONITORS_CHANGED], 0);
}

View File

@ -344,10 +344,34 @@
scale factors of logical monitors supported by the display server.
@layout_mode current layout mode represents the way logical monitors
are layed out on the screen. Possible modes include:
1 : physical
2 : logical
With physical layout mode, each logical monitor has the same dimensions
an the monitor modes of the associated monitors assigned to it, no
matter what scale is in use.
With logical mode, the dimension of a logical monitor is the dimension
of the monitor mode, divided by the logical monitor scale.
Possible @properties are:
* "supports-mirroring" (b): FALSE if mirroring not supported; TRUE or not
present if mirroring is supported.
* "layout-mode" (u): Represents in what way logical monitors are laid
out on the screen. The layout mode can be either
of the ones listed below. Absence of this property
means the layout mode cannot be changed, and that
"logical" mode is assumed to be used.
* 1 : logical - the dimension of a logical monitor is derived from
the monitor modes associated with it, then scaled
using the logical monitor scale.
* 2 : physical - the dimension of a logical monitor is derived from
the monitor modes associated with it.
-->
<method name="GetCurrentState">
<arg name="serial" direction="out" type="u" />
@ -386,6 +410,13 @@
- "enable_underscanning" (b): enable monitor underscanning;
may only be set when underscanning
is supported (see GetCurrentState).
@properties may effect the global monitor configuration state. Possible
properties are:
* "layout-mode" (u): layout mode the passed configuration is in; may
only be set when changing the layout mode is
supported (see GetCurrentState).
-->
<method name="ApplyMonitorsConfig">
<arg name="serial" direction="in" type="u" />

View File

@ -380,10 +380,28 @@ meta_monitor_manager_test_get_supported_scales (MetaMonitorManager *manager,
*n_scales = G_N_ELEMENTS (supported_scales_test);
}
static gboolean
is_monitor_framebuffer_scaled (void)
{
MetaBackend *backend = meta_get_backend ();
return meta_backend_is_experimental_feature_enabled (
backend,
META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER);
}
static MetaMonitorManagerCapability
meta_monitor_manager_test_get_capabilities (MetaMonitorManager *manager)
{
return META_MONITOR_MANAGER_CAPABILITY_MIRRORING;
MetaMonitorManagerCapability capabilities =
META_MONITOR_MANAGER_CAPABILITY_NONE;
capabilities |= META_MONITOR_MANAGER_CAPABILITY_MIRRORING;
if (is_monitor_framebuffer_scaled ())
capabilities |= META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE;
return capabilities;
}
static gboolean
@ -400,6 +418,18 @@ meta_monitor_manager_test_get_max_screen_size (MetaMonitorManager *manager,
return TRUE;
}
static MetaLogicalMonitorLayoutMode
meta_monitor_manager_test_get_default_layout_mode (MetaMonitorManager *manager)
{
if (!meta_is_stage_views_enabled ())
return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
if (is_monitor_framebuffer_scaled ())
return META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL;
else
return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
}
static void
meta_monitor_manager_test_dispose (GObject *object)
{
@ -436,4 +466,5 @@ meta_monitor_manager_test_class_init (MetaMonitorManagerTestClass *klass)
manager_class->get_supported_scales = meta_monitor_manager_test_get_supported_scales;
manager_class->get_capabilities = meta_monitor_manager_test_get_capabilities;
manager_class->get_max_screen_size = meta_monitor_manager_test_get_max_screen_size;
manager_class->get_default_layout_mode = meta_monitor_manager_test_get_default_layout_mode;
}

View File

@ -472,8 +472,8 @@ meta_test_monitor_store_scale (void)
.layout = {
.x = 0,
.y = 0,
.width = 1920,
.height = 1080
.width = 960,
.height = 540
},
.scale = 2,
.is_primary = TRUE,

View File

@ -1354,13 +1354,13 @@ meta_test_monitor_hidpi_linear_config (void)
{
.monitors = { 0 },
.n_monitors = 1,
.layout = { .x = 0, .y = 0, .width = 1280, .height = 720 },
.layout = { .x = 0, .y = 0, .width = 640, .height = 360 },
.scale = 2
},
{
.monitors = { 1 },
.n_monitors = 1,
.layout = { .x = 1280, .y = 0, .width = 1024, .height = 768 },
.layout = { .x = 640, .y = 0, .width = 1024, .height = 768 },
.scale = 1
}
},
@ -1376,12 +1376,18 @@ meta_test_monitor_hidpi_linear_config (void)
}
},
.n_crtcs = 2,
.screen_width = 1280 + 1024,
.screen_width = 640 + 1024,
.screen_height = 768
}
};
MetaMonitorTestSetup *test_setup;
if (!is_using_monitor_config_manager ())
{
g_test_skip ("Not using MetaMonitorConfigManager");
return;
}
test_setup = create_monitor_test_setup (&test_case,
MONITOR_TEST_FLAG_NO_STORED);
emulate_hotplug (test_setup);
@ -2689,7 +2695,7 @@ meta_test_monitor_custom_scale_config (void)
{
.monitors = { 0 },
.n_monitors = 1,
.layout = { .x = 0, .y = 0, .width = 1920, .height = 1080 },
.layout = { .x = 0, .y = 0, .width = 960, .height = 540 },
.scale = 2
}
},
@ -2703,8 +2709,8 @@ meta_test_monitor_custom_scale_config (void)
},
.n_crtcs = 1,
.n_tiled_monitors = 0,
.screen_width = 1920,
.screen_height = 1080
.screen_width = 960,
.screen_height = 540
}
};
MetaMonitorTestSetup *test_setup;
@ -2824,7 +2830,7 @@ meta_test_monitor_custom_tiled_config (void)
{
.monitors = { 0 },
.n_monitors = 1,
.layout = { .x = 0, .y = 0, .width = 800, .height = 600 },
.layout = { .x = 0, .y = 0, .width = 400, .height = 300 },
.scale = 2
}
},
@ -2841,8 +2847,8 @@ meta_test_monitor_custom_tiled_config (void)
},
.n_crtcs = 2,
.n_tiled_monitors = 1,
.screen_width = 800,
.screen_height = 600
.screen_width = 400,
.screen_height = 300
}
};
MetaMonitorTestSetup *test_setup;

View File

@ -214,8 +214,15 @@ meta_test_adjecent_to (void)
static gboolean
run_tests (gpointer data)
{
MetaBackend *backend = meta_get_backend ();
gboolean ret;
meta_backend_override_experimental_features (backend);
meta_backend_enable_experimental_feature (
backend,
META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER);
ret = g_test_run ();
meta_quit (ret != 0);

View File

@ -112,7 +112,11 @@ cursor_sprite_prepare_at (MetaCursorSprite *cursor_sprite,
{
float texture_scale;
texture_scale = (float) logical_monitor->scale / surface->scale;
if (meta_is_stage_views_scaled ())
texture_scale = 1.0 / surface->scale;
else
texture_scale = (float) logical_monitor->scale / surface->scale;
meta_cursor_sprite_set_texture_scale (cursor_sprite, texture_scale);
}
}

View File

@ -38,11 +38,14 @@
#include "backends/meta-backend-private.h"
#include "backends/meta-logical-monitor.h"
#include "compositor/meta-surface-actor-wayland.h"
#include "backends/meta-backend-private.h"
struct _MetaWindowWayland
{
MetaWindow parent;
int geometry_scale;
MetaWaylandSerial pending_configure_serial;
gboolean has_pending_move;
int pending_move_x;
@ -61,11 +64,24 @@ struct _MetaWindowWaylandClass
G_DEFINE_TYPE (MetaWindowWayland, meta_window_wayland, META_TYPE_WINDOW)
static int
get_window_geometry_scale_for_logical_monitor (MetaLogicalMonitor *logical_monitor)
{
if (meta_is_stage_views_scaled ())
return 1;
else
return logical_monitor->scale;
}
static void
meta_window_wayland_manage (MetaWindow *window)
{
MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window);
MetaDisplay *display = window->display;
wl_window->geometry_scale =
get_window_geometry_scale_for_logical_monitor (window->monitor);
meta_display_register_wayland_window (display, window);
{
@ -375,6 +391,12 @@ meta_window_wayland_update_main_monitor (MetaWindow *window)
return;
}
if (meta_is_stage_views_scaled ())
{
window->monitor = to;
return;
}
/* To avoid a window alternating between two main monitors because scaling
* changes the main monitor, wait until both the current and the new scale
* will result in the same main monitor. */
@ -393,16 +415,24 @@ static void
meta_window_wayland_main_monitor_changed (MetaWindow *window,
const MetaLogicalMonitor *old)
{
MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window);
int old_geometry_scale = wl_window->geometry_scale;
int geometry_scale;
float scale_factor;
MetaWaylandSurface *surface;
if (!window->monitor)
return;
geometry_scale = meta_window_wayland_get_geometry_scale (window);
/* This function makes sure that window geometry, window actor geometry and
* surface actor geometry gets set according the old and current main monitor
* scale. If there either is no past or current main monitor, or if the scale
* didn't change, there is nothing to do. */
if (old == NULL ||
window->monitor == NULL ||
old->scale == window->monitor->scale)
old_geometry_scale == geometry_scale)
return;
/* MetaWindow keeps its rectangles in the physical pixel coordinate space.
@ -410,7 +440,7 @@ meta_window_wayland_main_monitor_changed (MetaWindow *window,
* window surfaces to be scaled given the monitor scale, so we need to scale
* the rectangles in MetaWindow accordingly. */
scale_factor = (float)window->monitor->scale / old->scale;
scale_factor = (float) geometry_scale / old_geometry_scale;
/* Window size. */
scale_rect_size (&window->rect, scale_factor);
@ -419,7 +449,6 @@ meta_window_wayland_main_monitor_changed (MetaWindow *window,
scale_size (&window->size_hints.min_width, &window->size_hints.min_height, scale_factor);
scale_size (&window->size_hints.max_width, &window->size_hints.max_height, scale_factor);
/* Window geometry offset (XXX: Need a better place, see
* meta_window_wayland_move_resize). */
window->custom_frame_extents.left =
@ -449,6 +478,8 @@ meta_window_wayland_main_monitor_changed (MetaWindow *window,
meta_surface_actor_wayland_sync_state_recursive (actor);
}
wl_window->geometry_scale = geometry_scale;
meta_window_emit_size_changed (window);
}
@ -477,6 +508,8 @@ meta_window_wayland_init (MetaWindowWayland *wl_window)
{
MetaWindow *window = META_WINDOW (wl_window);
wl_window->geometry_scale = 1;
g_signal_connect (window, "notify::appears-focused",
G_CALLBACK (appears_focused_changed), NULL);
}
@ -571,7 +604,7 @@ should_do_pending_move (MetaWindowWayland *wl_window,
int
meta_window_wayland_get_geometry_scale (MetaWindow *window)
{
return window->monitor->scale;
return get_window_geometry_scale_for_logical_monitor (window->monitor);
}
/**