diff --git a/data/org.gnome.mutter.gschema.xml.in b/data/org.gnome.mutter.gschema.xml.in
index 56f16cb48..0f2cd4db9 100644
--- a/data/org.gnome.mutter.gschema.xml.in
+++ b/data/org.gnome.mutter.gschema.xml.in
@@ -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.
diff --git a/src/backends/meta-backend-private.h b/src/backends/meta-backend-private.h
index c8d618e3f..9c1f2a0b4 100644
--- a/src/backends/meta-backend-private.h
+++ b/src/backends/meta-backend-private.h
@@ -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 */
diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c
index 0360e327f..822ddc066 100644
--- a/src/backends/meta-backend.c
+++ b/src/backends/meta-backend.c
@@ -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)
{
diff --git a/src/backends/meta-logical-monitor.c b/src/backends/meta-logical-monitor.c
index d69f5c4b3..f1e2a0fd5 100644
--- a/src/backends/meta-logical-monitor.c
+++ b/src/backends/meta-logical-monitor.c
@@ -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;
diff --git a/src/backends/meta-logical-monitor.h b/src/backends/meta-logical-monitor.h
index de1af1bd0..f9f99cf91 100644
--- a/src/backends/meta-logical-monitor.h
+++ b/src/backends/meta-logical-monitor.h
@@ -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,
diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c
index d64c700d2..71652962a 100644
--- a/src/backends/meta-monitor-config-manager.c
+++ b/src/backends/meta-monitor-config-manager.c
@@ -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");
diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h
index baa119e0c..de7911413 100644
--- a/src/backends/meta-monitor-config-manager.h
+++ b/src/backends/meta-monitor-config-manager.h
@@ -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);
diff --git a/src/backends/meta-monitor-config-store.c b/src/backends/meta-monitor-config-store.c
index 44bdce7ea..9b02bc0c9 100644
--- a/src/backends/meta-monitor-config-store.c
+++ b/src/backends/meta-monitor-config-store.c
@@ -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)
{
diff --git a/src/backends/meta-monitor-config-store.h b/src/backends/meta-monitor-config-store.h
index 3dc94dbfd..7451fc11e 100644
--- a/src/backends/meta-monitor-config-store.h
+++ b/src/backends/meta-monitor-config-store.h
@@ -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);
diff --git a/src/backends/meta-monitor-manager-dummy.c b/src/backends/meta-monitor-manager-dummy.c
index 8c8134bcc..2c31d62b1 100644
--- a/src/backends/meta-monitor-manager-dummy.c
+++ b/src/backends/meta-monitor-manager-dummy.c
@@ -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
diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h
index 1e0e61171..4dc113984 100644
--- a/src/backends/meta-monitor-manager-private.h
+++ b/src/backends/meta-monitor-manager-private.h
@@ -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);
diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
index 0af01f1d7..4cd65c38a 100644
--- a/src/backends/meta-monitor-manager.c
+++ b/src/backends/meta-monitor-manager.c
@@ -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);
}
diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c
index 70289975a..5dbfadb8e 100644
--- a/src/backends/native/meta-cursor-renderer-native.c
+++ b/src/backends/native/meta-cursor-renderer-native.c
@@ -35,6 +35,8 @@
#include
#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))
diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c
index a000a7e39..78930b854 100644
--- a/src/backends/native/meta-monitor-manager-kms.c
+++ b/src/backends/native/meta-monitor-manager-kms.c
@@ -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;
}
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
index 9dae6dcd5..ae3381bd8 100644
--- a/src/backends/native/meta-renderer-native.c
+++ b/src/backends/native/meta-renderer-native.c
@@ -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,
diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
index 4083e08db..fd044c8f5 100644
--- a/src/backends/x11/meta-monitor-manager-xrandr.c
+++ b/src/backends/x11/meta-monitor-manager-xrandr.c
@@ -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");
diff --git a/src/backends/x11/meta-renderer-x11.c b/src/backends/x11/meta-renderer-x11.c
index da0613390..5eb81dd39 100644
--- a/src/backends/x11/meta-renderer-x11.c
+++ b/src/backends/x11/meta-renderer-x11.c
@@ -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);
}
diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c
index 8fc4b9e9d..0dfc427ef 100644
--- a/src/compositor/meta-surface-actor-wayland.c
+++ b/src/compositor/meta-surface-actor-wayland.c
@@ -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;
}
diff --git a/src/core/screen.c b/src/core/screen.c
index dfc499c7b..d6b5eac53 100644
--- a/src/core/screen.c
+++ b/src/core/screen.c
@@ -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);
}
diff --git a/src/org.gnome.Mutter.DisplayConfig.xml b/src/org.gnome.Mutter.DisplayConfig.xml
index 2c623c65b..bb48768d3 100644
--- a/src/org.gnome.Mutter.DisplayConfig.xml
+++ b/src/org.gnome.Mutter.DisplayConfig.xml
@@ -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.
-->
@@ -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).
-->
diff --git a/src/tests/meta-monitor-manager-test.c b/src/tests/meta-monitor-manager-test.c
index 6925365ed..cc88dfe9c 100644
--- a/src/tests/meta-monitor-manager-test.c
+++ b/src/tests/meta-monitor-manager-test.c
@@ -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;
}
diff --git a/src/tests/monitor-store-unit-tests.c b/src/tests/monitor-store-unit-tests.c
index 37bd22161..60aa872b5 100644
--- a/src/tests/monitor-store-unit-tests.c
+++ b/src/tests/monitor-store-unit-tests.c
@@ -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,
diff --git a/src/tests/monitor-unit-tests.c b/src/tests/monitor-unit-tests.c
index 1eb384120..3abcc7601 100644
--- a/src/tests/monitor-unit-tests.c
+++ b/src/tests/monitor-unit-tests.c
@@ -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;
diff --git a/src/tests/unit-tests.c b/src/tests/unit-tests.c
index 7e5a1e8d2..efd56f142 100644
--- a/src/tests/unit-tests.c
+++ b/src/tests/unit-tests.c
@@ -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);
diff --git a/src/wayland/meta-wayland-surface-role-cursor.c b/src/wayland/meta-wayland-surface-role-cursor.c
index 6b6c0a002..18b4fe9d3 100644
--- a/src/wayland/meta-wayland-surface-role-cursor.c
+++ b/src/wayland/meta-wayland-surface-role-cursor.c
@@ -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);
}
}
diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c
index 9a21388d1..a1b239b82 100644
--- a/src/wayland/meta-window-wayland.c
+++ b/src/wayland/meta-window-wayland.c
@@ -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);
}
/**