You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3785 lines
149 KiB
3785 lines
149 KiB
From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
|
|
Date: Thu, 4 Apr 2019 01:18:03 +0200
|
|
Subject: x11-Add-support-for-fractional-scaling-using-Randr
|
|
|
|
Add scaling support using randr under x11.
|
|
|
|
Origin: https://gitlab.gnome.org/3v1n0/mutter/commits/xrandr-scaling
|
|
Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/mutter/+bug/1820850
|
|
Forwarded: No, forwarding is in progress and planned though
|
|
---
|
|
data/meson.build | 7 +
|
|
data/org.gnome.mutter.gschema.xml.in | 5 +-
|
|
data/org.gnome.mutter.x11.gschema.xml.in | 30 ++
|
|
src/backends/meta-crtc.c | 21 +
|
|
src/backends/meta-crtc.h | 6 +
|
|
src/backends/meta-monitor-config-manager.c | 180 ++++++-
|
|
src/backends/meta-monitor-config-manager.h | 5 +
|
|
src/backends/meta-monitor-config-migration.c | 15 +-
|
|
src/backends/meta-monitor-config-store.c | 17 +
|
|
src/backends/meta-monitor-manager-dummy.c | 24 +-
|
|
src/backends/meta-monitor-manager-private.h | 34 +-
|
|
src/backends/meta-monitor-manager.c | 511 +++++++++++++++++--
|
|
src/backends/meta-monitor.c | 60 ++-
|
|
src/backends/meta-monitor.h | 6 +-
|
|
src/backends/meta-settings-private.h | 13 +
|
|
src/backends/meta-settings.c | 148 +++++-
|
|
src/backends/native/meta-monitor-manager-native.c | 41 +-
|
|
src/backends/x11/meta-crtc-xrandr.c | 100 +++-
|
|
src/backends/x11/meta-crtc-xrandr.h | 14 +-
|
|
src/backends/x11/meta-gpu-xrandr.c | 112 ++++-
|
|
src/backends/x11/meta-gpu-xrandr.h | 4 +
|
|
src/backends/x11/meta-monitor-manager-xrandr.c | 588 +++++++++++++++++-----
|
|
src/backends/x11/meta-monitor-manager-xrandr.h | 4 +-
|
|
src/backends/x11/meta-output-xrandr.c | 3 +-
|
|
src/compositor/meta-compositor-x11.c | 99 +++-
|
|
src/core/boxes-private.h | 4 +
|
|
src/core/boxes.c | 21 +
|
|
src/core/window.c | 19 +
|
|
src/org.gnome.Mutter.DisplayConfig.xml | 5 +
|
|
src/tests/meta-monitor-manager-test.c | 13 +-
|
|
30 files changed, 1839 insertions(+), 270 deletions(-)
|
|
create mode 100644 data/org.gnome.mutter.x11.gschema.xml.in
|
|
|
|
diff --git a/data/meson.build b/data/meson.build
|
|
index b1e81d1..977b340 100644
|
|
--- a/data/meson.build
|
|
+++ b/data/meson.build
|
|
@@ -55,6 +55,13 @@ configure_file(
|
|
install_dir: schemadir
|
|
)
|
|
|
|
+configure_file(
|
|
+ input: 'org.gnome.mutter.x11.gschema.xml.in',
|
|
+ output: 'org.gnome.mutter.x11.gschema.xml',
|
|
+ configuration: gschema_config,
|
|
+ install_dir: schemadir
|
|
+)
|
|
+
|
|
install_data(['mutter-schemas.convert'],
|
|
install_dir: join_paths(datadir, 'GConf/gsettings'),
|
|
)
|
|
diff --git a/data/org.gnome.mutter.gschema.xml.in b/data/org.gnome.mutter.gschema.xml.in
|
|
index 23fa9f3..e64691d 100644
|
|
--- a/data/org.gnome.mutter.gschema.xml.in
|
|
+++ b/data/org.gnome.mutter.gschema.xml.in
|
|
@@ -134,7 +134,10 @@
|
|
• “autoclose-xwayland” — automatically terminates Xwayland if all
|
|
relevant X11 clients are gone. Does not
|
|
require a restart.
|
|
-
|
|
+ • “x11-randr-fractional-scaling” — enable fractional scaling under X11
|
|
+ using xrandr scaling. It might reduce
|
|
+ performances.
|
|
+ Does not require a restart.
|
|
</description>
|
|
</key>
|
|
|
|
diff --git a/data/org.gnome.mutter.x11.gschema.xml.in b/data/org.gnome.mutter.x11.gschema.xml.in
|
|
new file mode 100644
|
|
index 0000000..3696659
|
|
--- /dev/null
|
|
+++ b/data/org.gnome.mutter.x11.gschema.xml.in
|
|
@@ -0,0 +1,30 @@
|
|
+<schemalist>
|
|
+
|
|
+ <enum id="org.gnome.mutter.X11.scale-mode">
|
|
+ <value nick="scale-up" value="1"/>
|
|
+ <value nick="scale-ui-down" value="2"/>
|
|
+ </enum>
|
|
+
|
|
+ <schema id="org.gnome.mutter.x11" path="/org/gnome/mutter/x11/"
|
|
+ gettext-domain="@GETTEXT_DOMAIN@">
|
|
+
|
|
+ <key name="fractional-scale-mode" enum="org.gnome.mutter.X11.scale-mode">
|
|
+ <default>"scale-ui-down"</default>
|
|
+ <description>
|
|
+ Choose the scaling mode to be used under X11 via Randr extension.
|
|
+
|
|
+ Supported methods are:
|
|
+
|
|
+ • “scale-up” — Scale everything up to the requested scale, shrinking
|
|
+ the UI. The applications will look blurry when scaling
|
|
+ at higher values and the resolution will be lowered.
|
|
+ • “scale-ui-down — Scale up the UI toolkits to the closest integer
|
|
+ scaling value upwards, while scale down the display
|
|
+ to match the requested scaling level.
|
|
+ It increases the resolution of the logical display.
|
|
+ </description>
|
|
+ </key>
|
|
+
|
|
+ </schema>
|
|
+
|
|
+</schemalist>
|
|
diff --git a/src/backends/meta-crtc.c b/src/backends/meta-crtc.c
|
|
index 09f9199..df4033d 100644
|
|
--- a/src/backends/meta-crtc.c
|
|
+++ b/src/backends/meta-crtc.c
|
|
@@ -117,6 +117,7 @@ meta_crtc_set_config (MetaCrtc *crtc,
|
|
config->layout = *layout;
|
|
config->mode = mode;
|
|
config->transform = transform;
|
|
+ config->scale = 1.0f;
|
|
|
|
priv->config = config;
|
|
}
|
|
@@ -137,6 +138,26 @@ meta_crtc_get_config (MetaCrtc *crtc)
|
|
return priv->config;
|
|
}
|
|
|
|
+void
|
|
+meta_crtc_set_config_scale (MetaCrtc *crtc,
|
|
+ float scale)
|
|
+{
|
|
+ MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc);
|
|
+
|
|
+ g_return_if_fail (scale > 0);
|
|
+
|
|
+ if (priv->config)
|
|
+ priv->config->scale = scale;
|
|
+}
|
|
+
|
|
+float
|
|
+meta_crtc_get_config_scale (MetaCrtc *crtc)
|
|
+{
|
|
+ MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc);
|
|
+
|
|
+ return priv->config ? priv->config->scale : 1.0f;
|
|
+}
|
|
+
|
|
static void
|
|
meta_crtc_set_property (GObject *object,
|
|
guint prop_id,
|
|
diff --git a/src/backends/meta-crtc.h b/src/backends/meta-crtc.h
|
|
index f6a3bc1..acdc2b7 100644
|
|
--- a/src/backends/meta-crtc.h
|
|
+++ b/src/backends/meta-crtc.h
|
|
@@ -33,6 +33,7 @@ typedef struct _MetaCrtcConfig
|
|
graphene_rect_t layout;
|
|
MetaMonitorTransform transform;
|
|
MetaCrtcMode *mode;
|
|
+ float scale;
|
|
} MetaCrtcConfig;
|
|
|
|
#define META_TYPE_CRTC (meta_crtc_get_type ())
|
|
@@ -68,6 +69,11 @@ void meta_crtc_set_config (MetaCrtc *crtc,
|
|
MetaCrtcMode *mode,
|
|
MetaMonitorTransform transform);
|
|
|
|
+void meta_crtc_set_config_scale (MetaCrtc *crtc,
|
|
+ float scale);
|
|
+
|
|
+float meta_crtc_get_config_scale (MetaCrtc *crtc);
|
|
+
|
|
META_EXPORT_TEST
|
|
void meta_crtc_unset_config (MetaCrtc *crtc);
|
|
|
|
diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c
|
|
index 0253e07..406e247 100644
|
|
--- a/src/backends/meta-monitor-config-manager.c
|
|
+++ b/src/backends/meta-monitor-config-manager.c
|
|
@@ -217,6 +217,18 @@ assign_monitor_crtc (MetaMonitor *monitor,
|
|
else
|
|
crtc_hw_transform = META_MONITOR_TRANSFORM_NORMAL;
|
|
|
|
+ scale = data->logical_monitor_config->scale;
|
|
+ if (!meta_monitor_manager_is_scale_supported (data->monitor_manager,
|
|
+ data->config->layout_mode,
|
|
+ monitor, mode, scale))
|
|
+ {
|
|
+ scale = roundf (scale);
|
|
+ if (!meta_monitor_manager_is_scale_supported (data->monitor_manager,
|
|
+ data->config->layout_mode,
|
|
+ monitor, mode, scale))
|
|
+ scale = 1.0f;
|
|
+ }
|
|
+
|
|
meta_monitor_calculate_crtc_pos (monitor, mode, output, crtc_transform,
|
|
&crtc_x, &crtc_y);
|
|
|
|
@@ -231,6 +243,8 @@ assign_monitor_crtc (MetaMonitor *monitor,
|
|
case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL:
|
|
scale = 1.0;
|
|
break;
|
|
+ case META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL:
|
|
+ break;
|
|
}
|
|
|
|
crtc_mode = monitor_crtc_mode->crtc_mode;
|
|
@@ -258,6 +272,7 @@ assign_monitor_crtc (MetaMonitor *monitor,
|
|
.mode = crtc_mode,
|
|
.layout = crtc_layout,
|
|
.transform = crtc_hw_transform,
|
|
+ .scale = scale,
|
|
.outputs = g_ptr_array_new ()
|
|
};
|
|
g_ptr_array_add (crtc_assignment->outputs, output);
|
|
@@ -542,7 +557,11 @@ meta_monitor_config_manager_get_stored (MetaMonitorConfigManager *config_manager
|
|
typedef enum _MonitorMatchRule
|
|
{
|
|
MONITOR_MATCH_ALL = 0,
|
|
- MONITOR_MATCH_EXTERNAL = (1 << 0)
|
|
+ MONITOR_MATCH_EXTERNAL = (1 << 0),
|
|
+ MONITOR_MATCH_BUILTIN = (1 << 1),
|
|
+ MONITOR_MATCH_PRIMARY = (1 << 2),
|
|
+ MONITOR_MATCH_VISIBLE = (1 << 3),
|
|
+ MONITOR_MATCH_WITH_POSITION = (1 << 4),
|
|
} MonitorMatchRule;
|
|
|
|
static MetaMonitor *
|
|
@@ -696,12 +696,69 @@ get_monitor_transform (MetaMonitorManager *monitor_manager,
|
|
}
|
|
}
|
|
|
|
+static float
|
|
+get_preferred_preferred_max_scale (MetaMonitorManager *monitor_manager,
|
|
+ MetaLogicalMonitorLayoutMode layout_mode,
|
|
+ MonitorMatchRule match_rule)
|
|
+{
|
|
+ float scale = 1.0f;
|
|
+ GList *monitors, *l;
|
|
+
|
|
+ monitors = meta_monitor_manager_get_monitors (monitor_manager);
|
|
+
|
|
+ for (l = monitors; l; l = l->next)
|
|
+ {
|
|
+ float s;
|
|
+ MetaMonitor *monitor = l->data;
|
|
+ MetaMonitorMode *mode = meta_monitor_get_preferred_mode (monitor);
|
|
+
|
|
+ if (match_rule & MONITOR_MATCH_PRIMARY)
|
|
+ {
|
|
+ if (!meta_monitor_is_primary (monitor))
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (match_rule & MONITOR_MATCH_BUILTIN)
|
|
+ {
|
|
+ if (!meta_monitor_is_laptop_panel (monitor))
|
|
+ continue;
|
|
+ }
|
|
+ else if (match_rule & MONITOR_MATCH_EXTERNAL)
|
|
+ {
|
|
+ if (meta_monitor_is_laptop_panel (monitor))
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (match_rule & MONITOR_MATCH_VISIBLE)
|
|
+ {
|
|
+ if (meta_monitor_is_laptop_panel (monitor) &&
|
|
+ is_lid_closed (monitor_manager))
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (match_rule & MONITOR_MATCH_WITH_POSITION)
|
|
+ {
|
|
+ if (!meta_monitor_get_suggested_position (monitor, NULL, NULL))
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ s = meta_monitor_manager_calculate_monitor_mode_scale (monitor_manager,
|
|
+ layout_mode,
|
|
+ monitor,
|
|
+ mode);
|
|
+ scale = MAX (scale, s);
|
|
+ }
|
|
+
|
|
+ return scale;
|
|
+}
|
|
+
|
|
static MetaLogicalMonitorConfig *
|
|
create_logical_monitor_config (MetaMonitorManager *monitor_manager,
|
|
MetaMonitor *monitor,
|
|
MetaMonitorMode *mode,
|
|
int x,
|
|
int y,
|
|
+ float max_scale,
|
|
MetaLogicalMonitorConfig *primary_logical_monitor_config,
|
|
MetaLogicalMonitorLayoutMode layout_mode)
|
|
{
|
|
@@ -700,6 +776,7 @@ create_preferred_logical_monitor_config (MetaMonitorManager *monitor_ma
|
|
scale = primary_logical_monitor_config->scale;
|
|
else
|
|
scale = meta_monitor_manager_calculate_monitor_mode_scale (monitor_manager,
|
|
+ monitor_manager->layout_mode,
|
|
monitor,
|
|
mode);
|
|
|
|
@@ -709,6 +786,13 @@ create_preferred_logical_monitor_config (MetaMonitorManager *monitor_ma
|
|
width = (int) roundf (width / scale);
|
|
height = (int) roundf (height / scale);
|
|
break;
|
|
+ case META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL:
|
|
+ {
|
|
+ float ui_scale = scale / ceilf (max_scale);
|
|
+ width = (int) roundf (width / ui_scale);
|
|
+ height = (int) roundf (height / ui_scale);
|
|
+ }
|
|
+ break;
|
|
case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL:
|
|
break;
|
|
}
|
|
@@ -747,6 +831,7 @@ meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_mana
|
|
MetaMonitor *primary_monitor;
|
|
MetaLogicalMonitorLayoutMode layout_mode;
|
|
MetaLogicalMonitorConfig *primary_logical_monitor_config;
|
|
+ float max_scale = 1.0f;
|
|
int x;
|
|
GList *monitors;
|
|
GList *l;
|
|
@@ -758,10 +843,16 @@ meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_mana
|
|
|
|
layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager);
|
|
|
|
+ if (layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL)
|
|
+ max_scale = get_preferred_preferred_max_scale (monitor_manager,
|
|
+ layout_mode,
|
|
+ MONITOR_MATCH_VISIBLE);
|
|
+
|
|
primary_logical_monitor_config =
|
|
create_preferred_logical_monitor_config (monitor_manager,
|
|
primary_monitor,
|
|
0, 0,
|
|
+ max_scale,
|
|
NULL,
|
|
layout_mode);
|
|
primary_logical_monitor_config->is_primary = TRUE;
|
|
@@ -786,6 +877,7 @@ meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_mana
|
|
create_preferred_logical_monitor_config (monitor_manager,
|
|
monitor,
|
|
x, 0,
|
|
+ max_scale,
|
|
primary_logical_monitor_config,
|
|
layout_mode);
|
|
logical_monitor_configs = g_list_append (logical_monitor_configs,
|
|
@@ -813,6 +905,7 @@ meta_monitor_config_manager_create_fallback (MetaMonitorConfigManager *config_ma
|
|
GList *logical_monitor_configs;
|
|
MetaLogicalMonitorLayoutMode layout_mode;
|
|
MetaLogicalMonitorConfig *primary_logical_monitor_config;
|
|
+ float max_scale = 1.0f;
|
|
|
|
primary_monitor = find_primary_monitor (monitor_manager);
|
|
if (!primary_monitor)
|
|
@@ -820,10 +913,16 @@ meta_monitor_config_manager_create_fallback (MetaMonitorConfigManager *config_ma
|
|
|
|
layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager);
|
|
|
|
+ if (layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL)
|
|
+ max_scale = get_preferred_preferred_max_scale (monitor_manager,
|
|
+ layout_mode,
|
|
+ MONITOR_MATCH_PRIMARY);
|
|
+
|
|
primary_logical_monitor_config =
|
|
create_preferred_logical_monitor_config (monitor_manager,
|
|
primary_monitor,
|
|
0, 0,
|
|
+ max_scale,
|
|
NULL,
|
|
layout_mode);
|
|
primary_logical_monitor_config->is_primary = TRUE;
|
|
@@ -828,6 +828,7 @@ create_preferred_logical_monitor_config (MetaMonitorManager *monitor_m
|
|
MetaMonitor *monitor,
|
|
int x,
|
|
int y,
|
|
+ float max_scale,
|
|
MetaLogicalMonitorConfig *primary_logical_monitor_config,
|
|
MetaLogicalMonitorLayoutMode layout_mode)
|
|
{
|
|
@@ -835,6 +836,7 @@ create_preferred_logical_monitor_config (MetaMonitorManager *monitor_m
|
|
monitor,
|
|
meta_monitor_get_preferred_mode (monitor),
|
|
x, y,
|
|
+ max_scale,
|
|
primary_logical_monitor_config,
|
|
layout_mode);
|
|
}
|
|
@@ -846,6 +945,7 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m
|
|
GList *logical_monitor_configs;
|
|
GList *region;
|
|
int x, y;
|
|
+ float max_scale = 1;
|
|
GList *monitors;
|
|
GList *l;
|
|
|
|
@@ -849,6 +849,7 @@ create_logical_monitor_config_from_monitor (MetaMonitorManager *monito
|
|
{
|
|
MetaRectangle monitor_layout;
|
|
MetaMonitorMode *mode;
|
|
+ float max_scale = 1.0F;
|
|
|
|
meta_monitor_derive_layout (monitor, &monitor_layout);
|
|
mode = meta_monitor_get_current_mode (monitor);
|
|
@@ -858,6 +859,7 @@ create_logical_monitor_config_from_monitor (MetaMonitorManager *monito
|
|
mode,
|
|
monitor_layout.x,
|
|
monitor_layout.y,
|
|
+ max_scale,
|
|
primary_logical_monitor_config,
|
|
layout_mode);
|
|
}
|
|
@@ -858,10 +958,16 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m
|
|
|
|
layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager);
|
|
|
|
+ if (layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL)
|
|
+ max_scale = get_preferred_preferred_max_scale (monitor_manager,
|
|
+ layout_mode,
|
|
+ MONITOR_MATCH_WITH_POSITION);
|
|
+
|
|
primary_logical_monitor_config =
|
|
create_preferred_logical_monitor_config (monitor_manager,
|
|
primary_monitor,
|
|
x, y,
|
|
+ max_scale,
|
|
NULL,
|
|
layout_mode);
|
|
primary_logical_monitor_config->is_primary = TRUE;
|
|
@@ -885,6 +991,7 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m
|
|
create_preferred_logical_monitor_config (monitor_manager,
|
|
monitor,
|
|
x, y,
|
|
+ max_scale,
|
|
primary_logical_monitor_config,
|
|
layout_mode);
|
|
logical_monitor_configs = g_list_append (logical_monitor_configs,
|
|
@@ -903,6 +1010,21 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m
|
|
region = g_list_prepend (region, &logical_monitor_config->layout);
|
|
}
|
|
|
|
+ for (l = region; region->next && l; l = l->next)
|
|
+ {
|
|
+ MetaRectangle *rect = l->data;
|
|
+
|
|
+ if (!meta_rectangle_has_adjacent_in_region (region, rect))
|
|
+ {
|
|
+ g_warning ("Suggested monitor config has monitors with no neighbors, "
|
|
+ "rejecting");
|
|
+ g_list_free (region);
|
|
+ g_list_free_full (logical_monitor_configs,
|
|
+ (GDestroyNotify) meta_logical_monitor_config_free);
|
|
+ return NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
g_list_free (region);
|
|
|
|
if (!logical_monitor_configs)
|
|
@@ -1071,6 +1193,39 @@ meta_monitor_config_manager_create_for_rotate_monitor (MetaMonitorConfigManager
|
|
return create_for_builtin_display_rotation (config_manager, TRUE, META_MONITOR_TRANSFORM_NORMAL);
|
|
}
|
|
|
|
+MetaMonitorsConfig *
|
|
+meta_monitor_config_manager_create_for_layout (MetaMonitorConfigManager *config_manager,
|
|
+ MetaMonitorsConfig *config,
|
|
+ MetaLogicalMonitorLayoutMode layout_mode)
|
|
+{
|
|
+ MetaMonitorManager *monitor_manager = config_manager->monitor_manager;
|
|
+ GList *logical_monitor_configs;
|
|
+ GList *l;
|
|
+
|
|
+ if (!config)
|
|
+ return NULL;
|
|
+
|
|
+ if (config->layout_mode == layout_mode)
|
|
+ return g_object_ref (config);
|
|
+
|
|
+ logical_monitor_configs =
|
|
+ clone_logical_monitor_config_list (config->logical_monitor_configs);
|
|
+
|
|
+ if (layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL)
|
|
+ {
|
|
+ for (l = logical_monitor_configs; l; l = l->next)
|
|
+ {
|
|
+ MetaLogicalMonitorConfig *monitor_config = l->data;
|
|
+ monitor_config->scale = roundf (monitor_config->scale);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return meta_monitors_config_new (monitor_manager,
|
|
+ logical_monitor_configs,
|
|
+ layout_mode,
|
|
+ META_MONITORS_CONFIG_FLAG_NONE);
|
|
+}
|
|
+
|
|
static MetaMonitorsConfig *
|
|
create_for_switch_config_all_mirror (MetaMonitorConfigManager *config_manager)
|
|
{
|
|
@@ -1159,7 +1314,9 @@ create_for_switch_config_all_mirror (MetaMonitorConfigManager *config_manager)
|
|
if (!mode)
|
|
continue;
|
|
|
|
- scale = meta_monitor_manager_calculate_monitor_mode_scale (monitor_manager, monitor, mode);
|
|
+ scale = meta_monitor_manager_calculate_monitor_mode_scale (monitor_manager,
|
|
+ monitor_manager->layout_mode,
|
|
+ monitor, mode);
|
|
best_scale = MAX (best_scale, scale);
|
|
monitor_configs = g_list_prepend (monitor_configs, create_monitor_config (monitor, mode));
|
|
}
|
|
@@ -1195,6 +1352,7 @@ create_for_switch_config_external (MetaMonitorConfigManager *config_manager)
|
|
MetaMonitorManager *monitor_manager = config_manager->monitor_manager;
|
|
GList *logical_monitor_configs = NULL;
|
|
int x = 0;
|
|
+ float max_scale = 1.0f;
|
|
MetaLogicalMonitorLayoutMode layout_mode;
|
|
GList *monitors;
|
|
GList *l;
|
|
@@ -1202,6 +1360,11 @@ create_for_switch_config_external (MetaMonitorConfigManager *config_manager)
|
|
|
|
layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager);
|
|
|
|
+ if (layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL)
|
|
+ max_scale = get_preferred_preferred_max_scale (monitor_manager,
|
|
+ layout_mode,
|
|
+ MONITOR_MATCH_EXTERNAL);
|
|
+
|
|
monitors = meta_monitor_manager_get_monitors (monitor_manager);
|
|
for (l = monitors; l; l = l->next)
|
|
{
|
|
@@ -1215,6 +1378,7 @@ create_for_switch_config_external (MetaMonitorConfigManager *config_manager)
|
|
create_preferred_logical_monitor_config (monitor_manager,
|
|
monitor,
|
|
x, 0,
|
|
+ max_scale,
|
|
NULL,
|
|
layout_mode);
|
|
logical_monitor_configs = g_list_append (logical_monitor_configs,
|
|
@@ -1249,6 +1413,7 @@ create_for_switch_config_builtin (MetaMonitorConfigManager *config_manager)
|
|
MetaLogicalMonitorConfig *primary_logical_monitor_config;
|
|
MetaMonitor *monitor;
|
|
MetaMonitorsConfig *monitors_config;
|
|
+ float max_scale = 1.0f;
|
|
|
|
monitor = meta_monitor_manager_get_laptop_panel (monitor_manager);
|
|
if (!monitor)
|
|
@@ -1256,10 +1421,16 @@ create_for_switch_config_builtin (MetaMonitorConfigManager *config_manager)
|
|
|
|
layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager);
|
|
|
|
+ if (layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL)
|
|
+ max_scale = get_preferred_preferred_max_scale (monitor_manager,
|
|
+ layout_mode,
|
|
+ MONITOR_MATCH_BUILTIN);
|
|
+
|
|
primary_logical_monitor_config =
|
|
create_preferred_logical_monitor_config (monitor_manager,
|
|
monitor,
|
|
0, 0,
|
|
+ max_scale,
|
|
NULL,
|
|
layout_mode);
|
|
primary_logical_monitor_config->is_primary = TRUE;
|
|
@@ -1666,6 +1837,7 @@ gboolean
|
|
meta_verify_logical_monitor_config (MetaLogicalMonitorConfig *logical_monitor_config,
|
|
MetaLogicalMonitorLayoutMode layout_mode,
|
|
MetaMonitorManager *monitor_manager,
|
|
+ float max_scale,
|
|
GError **error)
|
|
{
|
|
GList *l;
|
|
@@ -1702,6 +1874,10 @@ meta_verify_logical_monitor_config (MetaLogicalMonitorConfig *logical_monitor
|
|
|
|
switch (layout_mode)
|
|
{
|
|
+ case META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL:
|
|
+ expected_mode_width /= ceilf (max_scale);
|
|
+ expected_mode_height /= ceilf (max_scale);
|
|
+ /* fall through! */
|
|
case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
|
|
expected_mode_width = roundf (expected_mode_width *
|
|
logical_monitor_config->scale);
|
|
diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h
|
|
index 86756a7..8d9fc6c 100644
|
|
--- a/src/backends/meta-monitor-config-manager.h
|
|
+++ b/src/backends/meta-monitor-config-manager.h
|
|
@@ -110,6 +110,10 @@ MetaMonitorsConfig * meta_monitor_config_manager_create_for_orientation (MetaMon
|
|
META_EXPORT_TEST
|
|
MetaMonitorsConfig * meta_monitor_config_manager_create_for_rotate_monitor (MetaMonitorConfigManager *config_manager);
|
|
|
|
+MetaMonitorsConfig * meta_monitor_config_manager_create_for_layout (MetaMonitorConfigManager *config_manager,
|
|
+ MetaMonitorsConfig *config,
|
|
+ MetaLogicalMonitorLayoutMode layout_mode);
|
|
+
|
|
META_EXPORT_TEST
|
|
MetaMonitorsConfig * meta_monitor_config_manager_create_for_switch_config (MetaMonitorConfigManager *config_manager,
|
|
MetaMonitorSwitchConfigType config_type);
|
|
@@ -191,6 +195,7 @@ META_EXPORT_TEST
|
|
gboolean meta_verify_logical_monitor_config (MetaLogicalMonitorConfig *logical_monitor_config,
|
|
MetaLogicalMonitorLayoutMode layout_mode,
|
|
MetaMonitorManager *monitor_manager,
|
|
+ float max_scale,
|
|
GError **error);
|
|
|
|
META_EXPORT_TEST
|
|
diff --git a/src/backends/meta-monitor-config-migration.c b/src/backends/meta-monitor-config-migration.c
|
|
index d619dc4..69c426c 100644
|
|
--- a/src/backends/meta-monitor-config-migration.c
|
|
+++ b/src/backends/meta-monitor-config-migration.c
|
|
@@ -1190,6 +1190,9 @@ meta_finish_monitors_config_migration (MetaMonitorManager *monitor_manager,
|
|
MetaMonitorConfigStore *config_store =
|
|
meta_monitor_config_manager_get_store (config_manager);
|
|
GList *l;
|
|
+ MetaLogicalMonitorLayoutMode layout_mode;
|
|
+
|
|
+ layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager);
|
|
|
|
for (l = config->logical_monitor_configs; l; l = l->next)
|
|
{
|
|
@@ -1199,7 +1202,6 @@ meta_finish_monitors_config_migration (MetaMonitorManager *monitor_manager,
|
|
MetaMonitor *monitor;
|
|
MetaMonitorModeSpec *monitor_mode_spec;
|
|
MetaMonitorMode *monitor_mode;
|
|
- float scale;
|
|
|
|
monitor_config = logical_monitor_config->monitor_configs->data;
|
|
monitor_spec = monitor_config->monitor_spec;
|
|
@@ -1215,13 +1217,14 @@ meta_finish_monitors_config_migration (MetaMonitorManager *monitor_manager,
|
|
return FALSE;
|
|
}
|
|
|
|
- scale = meta_monitor_calculate_mode_scale (monitor, monitor_mode);
|
|
-
|
|
- logical_monitor_config->scale = scale;
|
|
+ logical_monitor_config->scale =
|
|
+ meta_monitor_manager_calculate_monitor_mode_scale (monitor_manager,
|
|
+ layout_mode,
|
|
+ monitor,
|
|
+ monitor_mode);
|
|
}
|
|
|
|
- config->layout_mode =
|
|
- meta_monitor_manager_get_default_layout_mode (monitor_manager);
|
|
+ config->layout_mode = layout_mode;
|
|
config->flags &= ~META_MONITORS_CONFIG_FLAG_MIGRATED;
|
|
|
|
if (!meta_verify_monitors_config (config, monitor_manager, error))
|
|
diff --git a/src/backends/meta-monitor-config-store.c b/src/backends/meta-monitor-config-store.c
|
|
index 4dd357a..326723e 100644
|
|
--- a/src/backends/meta-monitor-config-store.c
|
|
+++ b/src/backends/meta-monitor-config-store.c
|
|
@@ -496,6 +496,7 @@ handle_start_element (GMarkupParseContext *context,
|
|
static gboolean
|
|
derive_logical_monitor_layout (MetaLogicalMonitorConfig *logical_monitor_config,
|
|
MetaLogicalMonitorLayoutMode layout_mode,
|
|
+ float max_scale,
|
|
GError **error)
|
|
{
|
|
MetaMonitorConfig *monitor_config;
|
|
@@ -533,6 +534,10 @@ derive_logical_monitor_layout (MetaLogicalMonitorConfig *logical_monitor_conf
|
|
|
|
switch (layout_mode)
|
|
{
|
|
+ case META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL:
|
|
+ width *= ceilf (max_scale);
|
|
+ height *= ceilf (max_scale);
|
|
+ /* fall through! */
|
|
case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
|
|
width = roundf (width / logical_monitor_config->scale);
|
|
height = roundf (height / logical_monitor_config->scale);
|
|
@@ -740,6 +745,7 @@ handle_end_element (GMarkupParseContext *context,
|
|
GList *l;
|
|
MetaLogicalMonitorLayoutMode layout_mode;
|
|
MetaMonitorsConfigFlag config_flags = META_MONITORS_CONFIG_FLAG_NONE;
|
|
+ float max_scale = 1.0f;
|
|
|
|
g_assert (g_str_equal (element_name, "configuration"));
|
|
|
|
@@ -749,18 +755,29 @@ handle_end_element (GMarkupParseContext *context,
|
|
layout_mode =
|
|
meta_monitor_manager_get_default_layout_mode (store->monitor_manager);
|
|
|
|
+ if (layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL)
|
|
+ {
|
|
+ for (l = parser->current_logical_monitor_configs; l; l = l->next)
|
|
+ {
|
|
+ MetaLogicalMonitorConfig *logical_monitor_config = l->data;
|
|
+ max_scale = MAX (max_scale, logical_monitor_config->scale);
|
|
+ }
|
|
+ }
|
|
+
|
|
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,
|
|
+ max_scale,
|
|
error))
|
|
return;
|
|
|
|
if (!meta_verify_logical_monitor_config (logical_monitor_config,
|
|
layout_mode,
|
|
store->monitor_manager,
|
|
+ max_scale,
|
|
error))
|
|
return;
|
|
}
|
|
diff --git a/src/backends/meta-monitor-manager-dummy.c b/src/backends/meta-monitor-manager-dummy.c
|
|
index d08fb02..32f3b92 100644
|
|
--- a/src/backends/meta-monitor-manager-dummy.c
|
|
+++ b/src/backends/meta-monitor-manager-dummy.c
|
|
@@ -372,6 +372,15 @@ append_tiled_monitor (MetaMonitorManager *manager,
|
|
}
|
|
}
|
|
|
|
+static gboolean
|
|
+has_tiled_monitors (void)
|
|
+{
|
|
+ const char *tiled_monitors_str;
|
|
+
|
|
+ tiled_monitors_str = g_getenv ("MUTTER_DEBUG_TILED_DUMMY_MONITORS");
|
|
+ return g_strcmp0 (tiled_monitors_str, "1") == 0;
|
|
+}
|
|
+
|
|
static void
|
|
meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
|
|
{
|
|
@@ -380,7 +389,6 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
|
|
float *monitor_scales = NULL;
|
|
const char *num_monitors_str;
|
|
const char *monitor_scales_str;
|
|
- const char *tiled_monitors_str;
|
|
gboolean tiled_monitors;
|
|
unsigned int i;
|
|
GList *outputs;
|
|
@@ -458,8 +466,7 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
|
|
g_strfreev (scales_str_list);
|
|
}
|
|
|
|
- tiled_monitors_str = g_getenv ("MUTTER_DEBUG_TILED_DUMMY_MONITORS");
|
|
- tiled_monitors = g_strcmp0 (tiled_monitors_str, "1") == 0;
|
|
+ tiled_monitors = has_tiled_monitors ();
|
|
|
|
modes = NULL;
|
|
crtcs = NULL;
|
|
@@ -638,9 +645,10 @@ meta_monitor_manager_dummy_is_transform_handled (MetaMonitorManager *manager,
|
|
}
|
|
|
|
static float
|
|
-meta_monitor_manager_dummy_calculate_monitor_mode_scale (MetaMonitorManager *manager,
|
|
- MetaMonitor *monitor,
|
|
- MetaMonitorMode *monitor_mode)
|
|
+meta_monitor_manager_dummy_calculate_monitor_mode_scale (MetaMonitorManager *manager,
|
|
+ MetaLogicalMonitorLayoutMode layout_mode,
|
|
+ MetaMonitor *monitor,
|
|
+ MetaMonitorMode *monitor_mode)
|
|
{
|
|
MetaOutput *output;
|
|
MetaOutputDummy *output_dummy;
|
|
@@ -664,6 +672,7 @@ meta_monitor_manager_dummy_calculate_supported_scales (MetaMonitorManager
|
|
switch (layout_mode)
|
|
{
|
|
case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
|
|
+ case META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL:
|
|
break;
|
|
case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL:
|
|
constraints |= META_MONITOR_SCALES_CONSTRAINT_NO_FRAC;
|
|
@@ -694,6 +703,9 @@ meta_monitor_manager_dummy_get_capabilities (MetaMonitorManager *manager)
|
|
MetaMonitorManagerCapability capabilities =
|
|
META_MONITOR_MANAGER_CAPABILITY_NONE;
|
|
|
|
+ if (has_tiled_monitors ())
|
|
+ capabilities |= META_MONITOR_MANAGER_CAPABILITY_TILING;
|
|
+
|
|
if (meta_settings_is_experimental_feature_enabled (
|
|
settings,
|
|
META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER))
|
|
diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h
|
|
index 60c1e90..4cc666d 100644
|
|
--- a/src/backends/meta-monitor-manager-private.h
|
|
+++ b/src/backends/meta-monitor-manager-private.h
|
|
@@ -45,7 +45,8 @@ typedef enum _MetaMonitorManagerCapability
|
|
META_MONITOR_MANAGER_CAPABILITY_NONE = 0,
|
|
META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE = (1 << 0),
|
|
META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED = (1 << 1),
|
|
- META_MONITOR_MANAGER_CAPABILITY_CAN_DERIVE_CURRENT = (1 << 2),
|
|
+ META_MONITOR_MANAGER_CAPABILITY_TILING = (1 << 2),
|
|
+ META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING = (1 << 3),
|
|
} MetaMonitorManagerCapability;
|
|
|
|
/* Equivalent to the 'method' enum in org.gnome.Mutter.DisplayConfig */
|
|
@@ -59,7 +61,8 @@ typedef enum _MetaMonitorsConfigMethod
|
|
typedef enum _MetaLogicalMonitorLayoutMode
|
|
{
|
|
META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL = 1,
|
|
- META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL = 2
|
|
+ META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL = 2,
|
|
+ META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL = 3
|
|
} MetaLogicalMonitorLayoutMode;
|
|
|
|
/*
|
|
@@ -73,6 +76,7 @@ struct _MetaCrtcAssignment
|
|
MetaCrtc *crtc;
|
|
MetaCrtcMode *mode;
|
|
graphene_rect_t layout;
|
|
+ float scale;
|
|
MetaMonitorTransform transform;
|
|
GPtrArray *outputs;
|
|
};
|
|
@@ -134,6 +138,7 @@ struct _MetaMonitorManager
|
|
int screen_height;
|
|
|
|
GList *monitors;
|
|
+ GList *scale_override_monitors;
|
|
|
|
GList *logical_monitors;
|
|
MetaLogicalMonitor *primary_logical_monitor;
|
|
@@ -165,6 +170,9 @@ struct _MetaMonitorManager
|
|
* @apply_monitors_config: Tries to apply the given config using the given
|
|
* method. Throws an error if something went wrong.
|
|
*
|
|
+ * @update_screen_size_derived: Computes the screen size for derived
|
|
+ * configuration.
|
|
+ *
|
|
* @set_power_save_mode: Sets the #MetaPowerSave mode (for all displays).
|
|
*
|
|
* @change_backlight: Changes the backlight intensity to the given value (in
|
|
@@ -231,6 +239,9 @@ struct _MetaMonitorManagerClass
|
|
unsigned short *green,
|
|
unsigned short *blue);
|
|
|
|
+ void (*update_screen_size_derived) (MetaMonitorManager *,
|
|
+ MetaMonitorsConfig *);
|
|
+
|
|
void (* tiled_monitor_added) (MetaMonitorManager *manager,
|
|
MetaMonitor *monitor);
|
|
|
|
@@ -241,9 +252,10 @@ struct _MetaMonitorManagerClass
|
|
MetaCrtc *crtc,
|
|
MetaMonitorTransform transform);
|
|
|
|
- float (* calculate_monitor_mode_scale) (MetaMonitorManager *manager,
|
|
- MetaMonitor *monitor,
|
|
- MetaMonitorMode *monitor_mode);
|
|
+ float (* calculate_monitor_mode_scale) (MetaMonitorManager *,
|
|
+ MetaLogicalMonitorLayoutMode ,
|
|
+ MetaMonitor *,
|
|
+ MetaMonitorMode *);
|
|
|
|
float * (* calculate_supported_scales) (MetaMonitorManager *manager,
|
|
MetaLogicalMonitorLayoutMode layout_mode,
|
|
@@ -366,9 +378,10 @@ void meta_monitor_manager_lid_is_closed_changed (MetaMonitorManage
|
|
|
|
gboolean meta_monitor_manager_is_headless (MetaMonitorManager *manager);
|
|
|
|
-float meta_monitor_manager_calculate_monitor_mode_scale (MetaMonitorManager *manager,
|
|
- MetaMonitor *monitor,
|
|
- MetaMonitorMode *monitor_mode);
|
|
+float meta_monitor_manager_calculate_monitor_mode_scale (MetaMonitorManager *manager,
|
|
+ MetaLogicalMonitorLayoutMode layout_mode,
|
|
+ MetaMonitor *monitor,
|
|
+ MetaMonitorMode *monitor_mode);
|
|
|
|
float * meta_monitor_manager_calculate_supported_scales (MetaMonitorManager *,
|
|
MetaLogicalMonitorLayoutMode ,
|
|
@@ -382,6 +395,11 @@ gboolean meta_monitor_manager_is_scale_supported (MetaMonitorManager
|
|
MetaMonitorMode *monitor_mode,
|
|
float scale);
|
|
|
|
+float meta_monitor_manager_get_maximum_crtc_scale (MetaMonitorManager *manager);
|
|
+
|
|
+gboolean meta_monitor_manager_disable_scale_for_monitor (MetaMonitorManager *manager,
|
|
+ MetaLogicalMonitor *monitor);
|
|
+
|
|
MetaMonitorManagerCapability
|
|
meta_monitor_manager_get_capabilities (MetaMonitorManager *manager);
|
|
|
|
diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
|
|
index a75da93..6cf4aad 100644
|
|
--- a/src/backends/meta-monitor-manager.c
|
|
+++ b/src/backends/meta-monitor-manager.c
|
|
@@ -120,8 +120,18 @@ static gboolean
|
|
meta_monitor_manager_is_config_complete (MetaMonitorManager *manager,
|
|
MetaMonitorsConfig *config);
|
|
|
|
-static MetaMonitor *
|
|
-meta_monitor_manager_get_active_monitor (MetaMonitorManager *manager);
|
|
+static gboolean
|
|
+is_global_scale_matching_in_config (MetaMonitorsConfig *config,
|
|
+ float scale);
|
|
+
|
|
+static gboolean
|
|
+meta_monitor_manager_is_scale_supported_with_threshold (MetaMonitorManager *manager,
|
|
+ MetaLogicalMonitorLayoutMode layout_mode,
|
|
+ MetaMonitor *monitor,
|
|
+ MetaMonitorMode *monitor_mode,
|
|
+ float scale,
|
|
+ float threshold,
|
|
+ float *out_scale);
|
|
|
|
static void
|
|
meta_monitor_manager_real_read_current_state (MetaMonitorManager *manager);
|
|
@@ -212,15 +222,45 @@ meta_monitor_manager_rebuild_logical_monitors (MetaMonitorManager *manager,
|
|
primary_logical_monitor);
|
|
}
|
|
|
|
+float
|
|
+meta_monitor_manager_get_maximum_crtc_scale (MetaMonitorManager *manager)
|
|
+{
|
|
+ GList *l;
|
|
+ float scale;
|
|
+
|
|
+ scale = 1.0f;
|
|
+ for (l = manager->monitors; l != NULL; l = l->next)
|
|
+ {
|
|
+ MetaMonitor *monitor = l->data;
|
|
+ MetaOutput *output = meta_monitor_get_main_output (monitor);
|
|
+ MetaCrtc *crtc = meta_output_get_assigned_crtc (output);
|
|
+
|
|
+ if (crtc)
|
|
+ {
|
|
+ const MetaCrtcConfig *crtc_config = meta_crtc_get_config (crtc);
|
|
+
|
|
+ scale = MAX (scale, crtc_config ? crtc_config->scale : 1.0f);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return scale;
|
|
+}
|
|
+
|
|
static float
|
|
derive_configured_global_scale (MetaMonitorManager *manager,
|
|
MetaMonitorsConfig *config)
|
|
{
|
|
- MetaLogicalMonitorConfig *logical_monitor_config;
|
|
+ GList *l;
|
|
+
|
|
+ for (l = config->logical_monitor_configs; l; l = l->next)
|
|
+ {
|
|
+ MetaLogicalMonitorConfig *monitor_config = l->data;
|
|
|
|
- logical_monitor_config = config->logical_monitor_configs->data;
|
|
+ if (is_global_scale_matching_in_config (config, monitor_config->scale))
|
|
+ return monitor_config->scale;
|
|
+ }
|
|
|
|
- return logical_monitor_config->scale;
|
|
+ return 1.0f;
|
|
}
|
|
|
|
static float
|
|
@@ -231,24 +271,70 @@ calculate_monitor_scale (MetaMonitorManager *manager,
|
|
|
|
monitor_mode = meta_monitor_get_current_mode (monitor);
|
|
return meta_monitor_manager_calculate_monitor_mode_scale (manager,
|
|
+ manager->layout_mode,
|
|
monitor,
|
|
monitor_mode);
|
|
}
|
|
|
|
+static gboolean
|
|
+meta_monitor_manager_is_scale_supported_by_other_monitors (MetaMonitorManager *manager,
|
|
+ MetaMonitor *not_this_one,
|
|
+ float scale)
|
|
+{
|
|
+ GList *l;
|
|
+
|
|
+ for (l = manager->monitors; l; l = l->next)
|
|
+ {
|
|
+ MetaMonitor *monitor = l->data;
|
|
+ MetaMonitorMode *mode;
|
|
+
|
|
+ if (monitor == not_this_one || !meta_monitor_is_active (monitor))
|
|
+ continue;
|
|
+
|
|
+ mode = meta_monitor_get_current_mode (monitor);
|
|
+ if (!meta_monitor_manager_is_scale_supported (manager, manager->layout_mode,
|
|
+ monitor, mode, scale))
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
static float
|
|
derive_calculated_global_scale (MetaMonitorManager *manager)
|
|
{
|
|
MetaMonitor *monitor = NULL;
|
|
+ float scale;
|
|
+ GList *l;
|
|
|
|
+ scale = 1.0f;
|
|
monitor = meta_monitor_manager_get_primary_monitor (manager);
|
|
|
|
- if (!monitor || !meta_monitor_is_active (monitor))
|
|
- monitor = meta_monitor_manager_get_active_monitor (manager);
|
|
+ if (monitor && meta_monitor_is_active (monitor))
|
|
+ {
|
|
+ scale = calculate_monitor_scale (manager, monitor);
|
|
+ if (meta_monitor_manager_is_scale_supported_by_other_monitors (manager,
|
|
+ monitor,
|
|
+ scale))
|
|
+ return scale;
|
|
+ }
|
|
|
|
- if (!monitor)
|
|
- return 1.0;
|
|
+ for (l = manager->monitors; l; l = l->next)
|
|
+ {
|
|
+ MetaMonitor *other_monitor = l->data;
|
|
+ float monitor_scale;
|
|
+
|
|
+ if (other_monitor == monitor || !meta_monitor_is_active (other_monitor))
|
|
+ continue;
|
|
|
|
- return calculate_monitor_scale (manager, monitor);
|
|
+ monitor_scale = calculate_monitor_scale (manager, other_monitor);
|
|
+ if (meta_monitor_manager_is_scale_supported_by_other_monitors (manager,
|
|
+ other_monitor,
|
|
+ monitor_scale))
|
|
+ scale = MAX (scale, monitor_scale);
|
|
+ }
|
|
+
|
|
+ return scale;
|
|
}
|
|
|
|
static float
|
|
@@ -270,6 +356,51 @@ derive_scale_from_config (MetaMonitorManager *manager,
|
|
return 1.0;
|
|
}
|
|
|
|
+static gboolean
|
|
+derive_scale_from_crtc (MetaMonitorManager *manager,
|
|
+ MetaMonitor *monitor,
|
|
+ float *out_scale)
|
|
+{
|
|
+ MetaMonitorManagerCapability capabilities;
|
|
+ MetaMonitorMode *monitor_mode;
|
|
+ float threshold;
|
|
+ MetaOutput *output;
|
|
+ MetaCrtc *crtc;
|
|
+ float scale;
|
|
+
|
|
+ capabilities = meta_monitor_manager_get_capabilities (manager);
|
|
+
|
|
+ if (!(capabilities & META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING))
|
|
+ return FALSE;
|
|
+
|
|
+ if (!(capabilities & META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE))
|
|
+ return FALSE;
|
|
+
|
|
+ output = meta_monitor_get_main_output (monitor);
|
|
+ crtc = meta_output_get_assigned_crtc (output);
|
|
+
|
|
+ if (!crtc)
|
|
+ return FALSE;
|
|
+
|
|
+ /* Due to integer and possibly inverse scaling applied to the output the
|
|
+ * result could not match exactly, so we apply a more relaxed threshold
|
|
+ * in this case. */
|
|
+ threshold = 0.001f;
|
|
+
|
|
+ scale = meta_crtc_get_config_scale (crtc);
|
|
+ monitor_mode = meta_monitor_get_current_mode (monitor);
|
|
+ if (meta_monitor_manager_is_scale_supported_with_threshold (manager,
|
|
+ manager->layout_mode,
|
|
+ monitor,
|
|
+ monitor_mode,
|
|
+ scale,
|
|
+ threshold,
|
|
+ out_scale))
|
|
+ return TRUE;
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
static void
|
|
meta_monitor_manager_rebuild_logical_monitors_derived (MetaMonitorManager *manager,
|
|
MetaMonitorsConfig *config)
|
|
@@ -317,11 +448,17 @@ meta_monitor_manager_rebuild_logical_monitors_derived (MetaMonitorManager *manag
|
|
float scale;
|
|
|
|
if (use_global_scale)
|
|
- scale = global_scale;
|
|
- else if (config)
|
|
- scale = derive_scale_from_config (manager, config, &layout);
|
|
+ scale = roundf (global_scale);
|
|
else
|
|
- scale = calculate_monitor_scale (manager, monitor);
|
|
+ {
|
|
+ if (!derive_scale_from_crtc (manager, monitor, &scale))
|
|
+ {
|
|
+ if (config)
|
|
+ scale = derive_scale_from_config (manager, config, &layout);
|
|
+ else
|
|
+ scale = calculate_monitor_scale (manager, monitor);
|
|
+ }
|
|
+ }
|
|
|
|
g_assert (scale > 0);
|
|
|
|
@@ -433,16 +570,24 @@ meta_monitor_manager_is_headless (MetaMonitorManager *manager)
|
|
}
|
|
|
|
float
|
|
-meta_monitor_manager_calculate_monitor_mode_scale (MetaMonitorManager *manager,
|
|
- MetaMonitor *monitor,
|
|
- MetaMonitorMode *monitor_mode)
|
|
+meta_monitor_manager_calculate_monitor_mode_scale (MetaMonitorManager *manager,
|
|
+ MetaLogicalMonitorLayoutMode layout_mode,
|
|
+ MetaMonitor *monitor,
|
|
+ MetaMonitorMode *monitor_mode)
|
|
{
|
|
+ float scale;
|
|
MetaMonitorManagerClass *manager_class =
|
|
META_MONITOR_MANAGER_GET_CLASS (manager);
|
|
|
|
- return manager_class->calculate_monitor_mode_scale (manager,
|
|
- monitor,
|
|
- monitor_mode);
|
|
+ scale = manager_class->calculate_monitor_mode_scale (manager,
|
|
+ layout_mode,
|
|
+ monitor,
|
|
+ monitor_mode);
|
|
+
|
|
+ if (g_list_find (manager->scale_override_monitors, monitor))
|
|
+ return ceilf (scale);
|
|
+
|
|
+ return scale;
|
|
}
|
|
|
|
float *
|
|
@@ -622,6 +768,8 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
|
|
MetaMonitorsConfigMethod method;
|
|
MetaMonitorsConfigMethod fallback_method =
|
|
META_MONITORS_CONFIG_METHOD_TEMPORARY;
|
|
+ MetaLogicalMonitorLayoutMode layout_mode =
|
|
+ meta_monitor_manager_get_default_layout_mode (manager);
|
|
|
|
use_stored_config = should_use_stored_config (manager);
|
|
if (use_stored_config)
|
|
@@ -631,7 +779,18 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
|
|
|
|
if (use_stored_config)
|
|
{
|
|
+ g_autoptr(MetaMonitorsConfig) new_config = NULL;
|
|
+
|
|
config = meta_monitor_config_manager_get_stored (manager->config_manager);
|
|
+ if (config && config->layout_mode != layout_mode)
|
|
+ {
|
|
+ new_config =
|
|
+ meta_monitor_config_manager_create_for_layout (manager->config_manager,
|
|
+ config,
|
|
+ layout_mode);
|
|
+ config = new_config;
|
|
+ }
|
|
+
|
|
if (config)
|
|
{
|
|
if (!meta_monitor_manager_apply_monitors_config (manager,
|
|
@@ -676,6 +835,16 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
|
|
{
|
|
config = g_object_ref (config);
|
|
|
|
+ if (config && config->layout_mode != layout_mode)
|
|
+ {
|
|
+ MetaMonitorsConfig *new_config =
|
|
+ meta_monitor_config_manager_create_for_layout (manager->config_manager,
|
|
+ config,
|
|
+ layout_mode);
|
|
+ g_object_unref (config);
|
|
+ config = new_config;
|
|
+ }
|
|
+
|
|
if (meta_monitor_manager_is_config_complete (manager, config))
|
|
{
|
|
if (!meta_monitor_manager_apply_monitors_config (manager,
|
|
@@ -755,7 +755,9 @@ meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager)
|
|
static gboolean
|
|
should_use_stored_config (MetaMonitorManager *manager)
|
|
{
|
|
- return !meta_monitor_manager_has_hotplug_mode_update (manager);
|
|
+ return (manager->in_init ||
|
|
+ (!manager->scale_override_monitors &&
|
|
+ !meta_monitor_manager_has_hotplug_mode_update (manager)));
|
|
}
|
|
|
|
static gboolean
|
|
@@ -764,7 +766,7 @@ can_derive_current_config (MetaMonitorManager *manager)
|
|
MetaMonitorManagerCapability capabilities;
|
|
|
|
capabilities = meta_monitor_manager_get_capabilities (manager);
|
|
- return !!(capabilities & META_MONITOR_MANAGER_CAPABILITY_CAN_DERIVE_CURRENT);
|
|
+ return !!(capabilities & META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE);
|
|
}
|
|
|
|
MetaMonitorsConfig *
|
|
@@ -859,6 +1028,66 @@ orientation_changed (MetaOrientationManager *orientation_manager,
|
|
handle_orientation_change (orientation_manager, manager);
|
|
}
|
|
|
|
+static gboolean
|
|
+apply_x11_fractional_scaling_config (MetaMonitorManager *manager)
|
|
+{
|
|
+ g_autoptr(GError) error = NULL;
|
|
+ g_autoptr(MetaMonitorsConfig) config = NULL;
|
|
+ MetaMonitorsConfig *applied_config;
|
|
+ MetaLogicalMonitorLayoutMode layout_mode =
|
|
+ meta_monitor_manager_get_default_layout_mode (manager);
|
|
+
|
|
+ if (!META_IS_MONITOR_MANAGER_XRANDR (manager))
|
|
+ return TRUE;
|
|
+
|
|
+ applied_config =
|
|
+ meta_monitor_config_manager_get_current (manager->config_manager);
|
|
+ config =
|
|
+ meta_monitor_config_manager_create_for_layout (manager->config_manager,
|
|
+ applied_config,
|
|
+ layout_mode);
|
|
+ if (!config)
|
|
+ return FALSE;
|
|
+
|
|
+ if (meta_monitor_manager_apply_monitors_config (manager,
|
|
+ config,
|
|
+ META_MONITORS_CONFIG_METHOD_PERSISTENT,
|
|
+ &error))
|
|
+ {
|
|
+ if (config != applied_config && manager->persistent_timeout_id)
|
|
+ {
|
|
+ if (G_UNLIKELY (applied_config !=
|
|
+ meta_monitor_config_manager_get_previous (manager->config_manager)))
|
|
+ {
|
|
+ g_warning ("The removed configuration doesn't match the "
|
|
+ "previously applied one, reverting may not work");
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ g_autoptr(MetaMonitorsConfig) previous_config = NULL;
|
|
+
|
|
+ /* The previous config we applied was just a temporary one that
|
|
+ * GNOME control center passed us while toggling the fractional
|
|
+ * scaling. So, in such case, once the configuration with the
|
|
+ * correct layout has been applied, we need to ignore the
|
|
+ * temporary one. */
|
|
+ previous_config =
|
|
+ meta_monitor_config_manager_pop_previous (manager->config_manager);
|
|
+
|
|
+ g_assert_true (applied_config == previous_config);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ g_warning ("Impossible to apply the layout config %s\n",
|
|
+ error->message);
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
static void
|
|
experimental_features_changed (MetaSettings *settings,
|
|
MetaExperimentalFeature old_experimental_features,
|
|
@@ -866,6 +1095,8 @@ experimental_features_changed (MetaSettings *settings,
|
|
{
|
|
gboolean was_stage_views_scaled;
|
|
gboolean is_stage_views_scaled;
|
|
+ gboolean was_x11_scaling;
|
|
+ gboolean x11_scaling;
|
|
gboolean should_reconfigure = FALSE;
|
|
|
|
was_stage_views_scaled =
|
|
@@ -875,10 +1106,23 @@ experimental_features_changed (MetaSettings *settings,
|
|
meta_settings_is_experimental_feature_enabled (
|
|
settings,
|
|
META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER);
|
|
+ was_x11_scaling =
|
|
+ !!(old_experimental_features &
|
|
+ META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING);
|
|
+ x11_scaling =
|
|
+ meta_settings_is_experimental_feature_enabled (
|
|
+ settings,
|
|
+ META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING);
|
|
|
|
if (is_stage_views_scaled != was_stage_views_scaled)
|
|
should_reconfigure = TRUE;
|
|
|
|
+ if (was_x11_scaling != x11_scaling)
|
|
+ {
|
|
+ if (!apply_x11_fractional_scaling_config (manager))
|
|
+ should_reconfigure = TRUE;
|
|
+ }
|
|
+
|
|
if (should_reconfigure)
|
|
meta_monitor_manager_reconfigure (manager);
|
|
|
|
@@ -1421,6 +1665,33 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
|
return TRUE;
|
|
}
|
|
|
|
+static void
|
|
+restore_previous_experimental_config (MetaMonitorManager *manager,
|
|
+ MetaMonitorsConfig *previous_config)
|
|
+{
|
|
+ MetaBackend *backend = manager->backend;
|
|
+ MetaSettings *settings = meta_backend_get_settings (backend);
|
|
+ gboolean was_fractional;
|
|
+
|
|
+ if (!META_IS_MONITOR_MANAGER_XRANDR (manager))
|
|
+ return;
|
|
+
|
|
+ was_fractional =
|
|
+ previous_config->layout_mode != META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
|
|
+
|
|
+ if (meta_settings_is_experimental_feature_enabled (settings,
|
|
+ META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING) == was_fractional)
|
|
+ return;
|
|
+
|
|
+ g_signal_handler_block (settings,
|
|
+ manager->experimental_features_changed_handler_id);
|
|
+
|
|
+ meta_settings_enable_x11_fractional_scaling (settings, was_fractional);
|
|
+
|
|
+ g_signal_handler_unblock (settings,
|
|
+ manager->experimental_features_changed_handler_id);
|
|
+}
|
|
+
|
|
static void
|
|
restore_previous_config (MetaMonitorManager *manager)
|
|
{
|
|
@@ -1434,6 +1705,8 @@ restore_previous_config (MetaMonitorManager *manager)
|
|
{
|
|
MetaMonitorsConfigMethod method;
|
|
|
|
+ restore_previous_experimental_config (manager, previous_config);
|
|
+
|
|
method = META_MONITORS_CONFIG_METHOD_TEMPORARY;
|
|
if (meta_monitor_manager_apply_monitors_config (manager,
|
|
previous_config,
|
|
@@ -1490,6 +1763,41 @@ request_persistent_confirmation (MetaMonitorManager *manager)
|
|
g_signal_emit (manager, signals[CONFIRM_DISPLAY_CHANGE], 0);
|
|
}
|
|
|
|
+gboolean
|
|
+meta_monitor_manager_disable_scale_for_monitor (MetaMonitorManager *manager,
|
|
+ MetaLogicalMonitor *monitor)
|
|
+{
|
|
+ switch (manager->layout_mode)
|
|
+ {
|
|
+ case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
|
|
+ case META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL:
|
|
+ break;
|
|
+ default:
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ if (monitor && fmodf (monitor->scale, 1.0) != 0.0f)
|
|
+ {
|
|
+ if (manager->scale_override_monitors)
|
|
+ {
|
|
+ g_clear_pointer (&manager->scale_override_monitors, g_list_free);
|
|
+ g_object_unref (meta_monitor_config_manager_pop_previous (manager->config_manager));
|
|
+ }
|
|
+
|
|
+ manager->scale_override_monitors = g_list_copy (monitor->monitors);
|
|
+ meta_monitor_manager_ensure_configured (manager);
|
|
+ return TRUE;
|
|
+ }
|
|
+
|
|
+ if (manager->scale_override_monitors)
|
|
+ {
|
|
+ g_clear_pointer (&manager->scale_override_monitors, g_list_free);
|
|
+ restore_previous_config (manager);
|
|
+ }
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
#define META_DISPLAY_CONFIG_MODE_FLAGS_PREFERRED (1 << 0)
|
|
#define META_DISPLAY_CONFIG_MODE_FLAGS_CURRENT (1 << 1)
|
|
|
|
@@ -1517,6 +1825,7 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
|
|
MetaMonitorManagerCapability capabilities;
|
|
int ui_scaling_factor;
|
|
int max_screen_width, max_screen_height;
|
|
+ char *renderer;
|
|
|
|
g_variant_builder_init (&monitors_builder,
|
|
G_VARIANT_TYPE (MONITORS_FORMAT));
|
|
@@ -1563,6 +1872,7 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
|
|
|
|
preferred_scale =
|
|
meta_monitor_manager_calculate_monitor_mode_scale (manager,
|
|
+ manager->layout_mode,
|
|
monitor,
|
|
monitor_mode);
|
|
|
|
@@ -1670,6 +1980,14 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
|
|
}
|
|
|
|
g_variant_builder_init (&properties_builder, G_VARIANT_TYPE ("a{sv}"));
|
|
+
|
|
+ renderer = g_ascii_strdown (G_OBJECT_TYPE_NAME (manager) +
|
|
+ strlen (g_type_name (g_type_parent (G_OBJECT_TYPE (manager)))),
|
|
+ -1);
|
|
+ g_variant_builder_add (&properties_builder, "{sv}",
|
|
+ "renderer",
|
|
+ g_variant_new_take_string (renderer));
|
|
+
|
|
capabilities = meta_monitor_manager_get_capabilities (manager);
|
|
|
|
g_variant_builder_add (&properties_builder, "{sv}",
|
|
@@ -1688,6 +2006,14 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
|
|
"global-scale-required",
|
|
g_variant_new_boolean (TRUE));
|
|
}
|
|
+ else if (META_IS_MONITOR_MANAGER_XRANDR (manager) &&
|
|
+ (capabilities & META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING) &&
|
|
+ (capabilities & META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE))
|
|
+ {
|
|
+ g_variant_builder_add (&properties_builder, "{sv}",
|
|
+ "x11-fractional-scaling",
|
|
+ g_variant_new_boolean (TRUE));
|
|
+ }
|
|
|
|
ui_scaling_factor = meta_settings_get_ui_scaling_factor (settings);
|
|
g_variant_builder_add (&properties_builder, "{sv}",
|
|
@@ -1732,12 +2058,14 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
|
|
#undef LOGICAL_MONITOR_FORMAT
|
|
#undef LOGICAL_MONITORS_FORMAT
|
|
|
|
-gboolean
|
|
-meta_monitor_manager_is_scale_supported (MetaMonitorManager *manager,
|
|
- MetaLogicalMonitorLayoutMode layout_mode,
|
|
- MetaMonitor *monitor,
|
|
- MetaMonitorMode *monitor_mode,
|
|
- float scale)
|
|
+static gboolean
|
|
+meta_monitor_manager_is_scale_supported_with_threshold (MetaMonitorManager *manager,
|
|
+ MetaLogicalMonitorLayoutMode layout_mode,
|
|
+ MetaMonitor *monitor,
|
|
+ MetaMonitorMode *monitor_mode,
|
|
+ float scale,
|
|
+ float threshold,
|
|
+ float *out_scale)
|
|
{
|
|
g_autofree float *supported_scales = NULL;
|
|
int n_supported_scales;
|
|
@@ -1751,8 +2079,66 @@ meta_monitor_manager_is_scale_supported (MetaMonitorManager *manager,
|
|
&n_supported_scales);
|
|
for (i = 0; i < n_supported_scales; i++)
|
|
{
|
|
- if (supported_scales[i] == scale)
|
|
- return TRUE;
|
|
+ if (fabs (supported_scales[i] - scale) < threshold)
|
|
+ {
|
|
+ if (out_scale)
|
|
+ *out_scale = supported_scales[i];
|
|
+
|
|
+ return TRUE;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+gboolean
|
|
+meta_monitor_manager_is_scale_supported (MetaMonitorManager *manager,
|
|
+ MetaLogicalMonitorLayoutMode layout_mode,
|
|
+ MetaMonitor *monitor,
|
|
+ MetaMonitorMode *monitor_mode,
|
|
+ float scale)
|
|
+{
|
|
+ return meta_monitor_manager_is_scale_supported_with_threshold (manager,
|
|
+ layout_mode,
|
|
+ monitor,
|
|
+ monitor_mode,
|
|
+ scale,
|
|
+ FLT_EPSILON,
|
|
+ NULL);
|
|
+}
|
|
+
|
|
+static gboolean
|
|
+is_global_scale_matching_in_config (MetaMonitorsConfig *config,
|
|
+ float scale)
|
|
+{
|
|
+ GList *l;
|
|
+
|
|
+ for (l = config->logical_monitor_configs; l; l = l->next)
|
|
+ {
|
|
+ MetaLogicalMonitorConfig *logical_monitor_config = l->data;
|
|
+
|
|
+ if (fabs (logical_monitor_config->scale - scale) > FLT_EPSILON)
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static gboolean
|
|
+meta_monitor_manager_is_scale_supported_for_config (MetaMonitorManager *manager,
|
|
+ MetaMonitorsConfig *config,
|
|
+ MetaMonitor *monitor,
|
|
+ MetaMonitorMode *monitor_mode,
|
|
+ float scale)
|
|
+{
|
|
+ if (meta_monitor_manager_is_scale_supported (manager, config->layout_mode,
|
|
+ monitor, monitor_mode, scale))
|
|
+ {
|
|
+ if (meta_monitor_manager_get_capabilities (manager) &
|
|
+ META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED)
|
|
+ return is_global_scale_matching_in_config (config, scale);
|
|
+
|
|
+ return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
@@ -1796,11 +2182,11 @@ meta_monitor_manager_is_config_applicable (MetaMonitorManager *manager,
|
|
return FALSE;
|
|
}
|
|
|
|
- if (!meta_monitor_manager_is_scale_supported (manager,
|
|
- config->layout_mode,
|
|
- monitor,
|
|
- monitor_mode,
|
|
- scale))
|
|
+ if (!meta_monitor_manager_is_scale_supported_for_config (manager,
|
|
+ config,
|
|
+ monitor,
|
|
+ monitor_mode,
|
|
+ scale))
|
|
{
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
"Scale not supported by backend");
|
|
@@ -2021,6 +2407,7 @@ derive_logical_monitor_size (MetaMonitorConfig *monitor_config,
|
|
switch (layout_mode)
|
|
{
|
|
case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
|
|
+ case META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL:
|
|
width = roundf (width / scale);
|
|
height = roundf (height / scale);
|
|
break;
|
|
@@ -2120,9 +2507,11 @@ create_logical_monitor_config_from_variant (MetaMonitorManager *manager
|
|
.monitor_configs = monitor_configs
|
|
};
|
|
|
|
- if (!meta_verify_logical_monitor_config (logical_monitor_config,
|
|
+ if (layout_mode != META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL &&
|
|
+ !meta_verify_logical_monitor_config (logical_monitor_config,
|
|
layout_mode,
|
|
manager,
|
|
+ 1.0f,
|
|
error))
|
|
{
|
|
meta_logical_monitor_config_free (logical_monitor_config);
|
|
@@ -2143,6 +2532,7 @@ is_valid_layout_mode (MetaLogicalMonitorLayoutMode layout_mode)
|
|
{
|
|
case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
|
|
case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL:
|
|
+ case META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL:
|
|
return TRUE;
|
|
}
|
|
|
|
@@ -2165,6 +2555,7 @@ meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skelet
|
|
MetaMonitorsConfig *config;
|
|
GList *logical_monitor_configs = NULL;
|
|
GError *error = NULL;
|
|
+ float max_scale = 1.0f;
|
|
|
|
if (serial != manager->serial)
|
|
{
|
|
@@ -2236,10 +2627,42 @@ meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skelet
|
|
return TRUE;
|
|
}
|
|
|
|
+ max_scale = MAX (max_scale, logical_monitor_config->scale);
|
|
logical_monitor_configs = g_list_append (logical_monitor_configs,
|
|
logical_monitor_config);
|
|
}
|
|
|
|
+ if (manager->layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL)
|
|
+ {
|
|
+ GList *l;
|
|
+ int ui_scale = ceilf (max_scale);
|
|
+
|
|
+ for (l = logical_monitor_configs; l; l = l->next)
|
|
+ {
|
|
+ MetaLogicalMonitorConfig *logical_monitor_config = l->data;
|
|
+
|
|
+ logical_monitor_config->layout.width =
|
|
+ roundf (logical_monitor_config->layout.width * ui_scale);
|
|
+ logical_monitor_config->layout.height =
|
|
+ roundf (logical_monitor_config->layout.height * ui_scale);
|
|
+
|
|
+ if (!meta_verify_logical_monitor_config (logical_monitor_config,
|
|
+ manager->layout_mode,
|
|
+ manager,
|
|
+ ui_scale,
|
|
+ &error))
|
|
+ {
|
|
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
+ G_DBUS_ERROR_INVALID_ARGS,
|
|
+ "%s", error->message);
|
|
+ g_error_free (error);
|
|
+ g_list_free_full (logical_monitor_configs,
|
|
+ (GDestroyNotify) meta_logical_monitor_config_free);
|
|
+ return TRUE;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
config = meta_monitors_config_new (manager,
|
|
logical_monitor_configs,
|
|
layout_mode,
|
|
@@ -2746,12 +3169,6 @@ meta_monitor_manager_get_laptop_panel (MetaMonitorManager *manager)
|
|
return find_monitor (manager, meta_monitor_is_laptop_panel);
|
|
}
|
|
|
|
-static MetaMonitor *
|
|
-meta_monitor_manager_get_active_monitor (MetaMonitorManager *manager)
|
|
-{
|
|
- return find_monitor (manager, meta_monitor_is_active);
|
|
-}
|
|
-
|
|
MetaMonitor *
|
|
meta_monitor_manager_get_monitor_from_connector (MetaMonitorManager *manager,
|
|
const char *connector)
|
|
@@ -2934,6 +3351,10 @@ rebuild_monitors (MetaMonitorManager *manager)
|
|
{
|
|
GList *gpus;
|
|
GList *l;
|
|
+ gboolean has_tiling;
|
|
+
|
|
+ has_tiling = meta_monitor_manager_get_capabilities (manager) &
|
|
+ META_MONITOR_MANAGER_CAPABILITY_TILING;
|
|
|
|
if (manager->monitors)
|
|
{
|
|
@@ -2952,7 +3373,7 @@ rebuild_monitors (MetaMonitorManager *manager)
|
|
MetaOutput *output = k->data;
|
|
const MetaOutputInfo *output_info = meta_output_get_info (output);
|
|
|
|
- if (output_info->tile_info.group_id)
|
|
+ if (has_tiling && output_info->tile_info.group_id)
|
|
{
|
|
if (is_main_tiled_monitor_output (output))
|
|
{
|
|
@@ -3170,7 +3591,7 @@ meta_monitor_manager_update_logical_state_derived (MetaMonitorManager *manager,
|
|
else
|
|
manager->current_switch_config = META_MONITOR_SWITCH_CONFIG_UNKNOWN;
|
|
|
|
- manager->layout_mode = META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
|
|
+ manager->layout_mode = meta_monitor_manager_get_default_layout_mode (manager);
|
|
|
|
meta_monitor_manager_rebuild_logical_monitors_derived (manager, config);
|
|
}
|
|
@@ -3179,10 +3600,14 @@ void
|
|
meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager,
|
|
MetaMonitorsConfig *config)
|
|
{
|
|
+ MetaMonitorManagerClass *klass = META_MONITOR_MANAGER_GET_CLASS (manager);
|
|
GList *old_logical_monitors;
|
|
|
|
meta_monitor_manager_update_monitor_modes_derived (manager);
|
|
|
|
+ if (klass->update_screen_size_derived)
|
|
+ klass->update_screen_size_derived (manager, config);
|
|
+
|
|
if (manager->in_init)
|
|
return;
|
|
|
|
diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c
|
|
index e02f8ed..d3ad030 100644
|
|
--- a/src/backends/meta-monitor.c
|
|
+++ b/src/backends/meta-monitor.c
|
|
@@ -730,8 +730,11 @@ meta_monitor_normal_get_suggested_position (MetaMonitor *monitor,
|
|
if (output_info->suggested_x < 0 && output_info->suggested_y < 0)
|
|
return FALSE;
|
|
|
|
- *x = output_info->suggested_x;
|
|
- *y = output_info->suggested_y;
|
|
+ if (x)
|
|
+ *x = output_info->suggested_x;
|
|
+
|
|
+ if (y)
|
|
+ *y = output_info->suggested_y;
|
|
|
|
return TRUE;
|
|
}
|
|
@@ -1657,8 +1660,9 @@ meta_monitor_calculate_crtc_pos (MetaMonitor *monitor,
|
|
#define SMALLEST_4K_WIDTH 3656
|
|
|
|
static float
|
|
-calculate_scale (MetaMonitor *monitor,
|
|
- MetaMonitorMode *monitor_mode)
|
|
+calculate_scale (MetaMonitor *monitor,
|
|
+ MetaMonitorMode *monitor_mode,
|
|
+ MetaMonitorScalesConstraint constraints)
|
|
{
|
|
int resolution_width, resolution_height;
|
|
int width_mm, height_mm;
|
|
@@ -1714,8 +1718,9 @@ out:
|
|
}
|
|
|
|
float
|
|
-meta_monitor_calculate_mode_scale (MetaMonitor *monitor,
|
|
- MetaMonitorMode *monitor_mode)
|
|
+meta_monitor_calculate_mode_scale (MetaMonitor *monitor,
|
|
+ MetaMonitorMode *monitor_mode,
|
|
+ MetaMonitorScalesConstraint constraints)
|
|
{
|
|
MetaBackend *backend = meta_get_backend ();
|
|
MetaSettings *settings = meta_backend_get_settings (backend);
|
|
@@ -1725,7 +1730,7 @@ meta_monitor_calculate_mode_scale (MetaMonitor *monitor,
|
|
&global_scaling_factor))
|
|
return global_scaling_factor;
|
|
|
|
- return calculate_scale (monitor, monitor_mode);
|
|
+ return calculate_scale (monitor, monitor_mode, constraints);
|
|
}
|
|
|
|
static gboolean
|
|
@@ -1735,6 +1740,16 @@ is_logical_size_large_enough (int width,
|
|
return width * height >= MINIMUM_LOGICAL_AREA;
|
|
}
|
|
|
|
+static gboolean
|
|
+is_scale_valid_for_size (float width,
|
|
+ float height,
|
|
+ float scale)
|
|
+{
|
|
+ return scale >= MINIMUM_SCALE_FACTOR &&
|
|
+ scale <= MAXIMUM_SCALE_FACTOR &&
|
|
+ is_logical_size_large_enough (floorf (width/scale), floorf (width/scale));
|
|
+}
|
|
+
|
|
gboolean
|
|
meta_monitor_mode_should_be_advertised (MetaMonitorMode *monitor_mode)
|
|
{
|
|
@@ -1764,21 +1779,16 @@ get_closest_scale_factor_for_resolution (float width,
|
|
gboolean found_one;
|
|
|
|
best_scale = 0;
|
|
- scaled_w = width / scale;
|
|
- scaled_h = height / scale;
|
|
|
|
- if (scale < MINIMUM_SCALE_FACTOR ||
|
|
- scale > MAXIMUM_SCALE_FACTOR ||
|
|
- !is_logical_size_large_enough (floorf (scaled_w), floorf (scaled_h)))
|
|
+ if (!is_scale_valid_for_size (width, height, scale))
|
|
goto out;
|
|
|
|
- if (floorf (scaled_w) == scaled_w && floorf (scaled_h) == scaled_h)
|
|
+ if (fmodf (width, scale) == 0.0 && fmodf (height, scale) == 0.0)
|
|
return scale;
|
|
|
|
i = 0;
|
|
found_one = FALSE;
|
|
- base_scaled_w = floorf (scaled_w);
|
|
-
|
|
+ base_scaled_w = floorf (width / scale);
|
|
do
|
|
{
|
|
for (j = 0; j < 2; j++)
|
|
@@ -1838,16 +1848,24 @@ meta_monitor_calculate_supported_scales (MetaMonitor *monitor,
|
|
float scale;
|
|
float scale_value = i + j * SCALE_FACTORS_STEPS;
|
|
|
|
- if ((constraints & META_MONITOR_SCALES_CONSTRAINT_NO_FRAC) &&
|
|
- fmodf (scale_value, 1.0) != 0.0)
|
|
+ if (constraints & META_MONITOR_SCALES_CONSTRAINT_NO_FRAC)
|
|
{
|
|
- continue;
|
|
+ if (fmodf (scale_value, 1.0) != 0.0)
|
|
+ continue;
|
|
}
|
|
|
|
- scale = get_closest_scale_factor_for_resolution (width,
|
|
- height,
|
|
- scale_value);
|
|
+ if ((constraints & META_MONITOR_SCALES_CONSTRAINT_NO_FRAC) ||
|
|
+ (constraints & META_MONITOR_SCALES_CONSTRAINT_NO_LOGICAL))
|
|
+ {
|
|
+ if (!is_scale_valid_for_size (width, height, scale_value))
|
|
+ continue;
|
|
|
|
+ scale = scale_value;
|
|
+ }
|
|
+ else
|
|
+ scale = get_closest_scale_factor_for_resolution (width,
|
|
+ height,
|
|
+ scale_value);
|
|
if (scale > 0.0f)
|
|
g_array_append_val (supported_scales, scale);
|
|
}
|
|
diff --git a/src/backends/meta-monitor.h b/src/backends/meta-monitor.h
|
|
index 341657a..234a6f9 100644
|
|
--- a/src/backends/meta-monitor.h
|
|
+++ b/src/backends/meta-monitor.h
|
|
@@ -62,6 +62,7 @@ typedef enum _MetaMonitorScalesConstraint
|
|
{
|
|
META_MONITOR_SCALES_CONSTRAINT_NONE = 0,
|
|
META_MONITOR_SCALES_CONSTRAINT_NO_FRAC = (1 << 0),
|
|
+ META_MONITOR_SCALES_CONSTRAINT_NO_LOGICAL = (1 << 1),
|
|
} MetaMonitorScalesConstraint;
|
|
|
|
#define META_TYPE_MONITOR (meta_monitor_get_type ())
|
|
@@ -211,8 +212,9 @@ void meta_monitor_calculate_crtc_pos (MetaMonitor *monitor,
|
|
int *out_y);
|
|
|
|
META_EXPORT_TEST
|
|
-float meta_monitor_calculate_mode_scale (MetaMonitor *monitor,
|
|
- MetaMonitorMode *monitor_mode);
|
|
+float meta_monitor_calculate_mode_scale (MetaMonitor *monitor,
|
|
+ MetaMonitorMode *monitor_mode,
|
|
+ MetaMonitorScalesConstraint constraints);
|
|
|
|
META_EXPORT_TEST
|
|
float * meta_monitor_calculate_supported_scales (MetaMonitor *monitor,
|
|
diff --git a/src/backends/meta-settings-private.h b/src/backends/meta-settings-private.h
|
|
index cde7e04..4b8b4c5 100644
|
|
--- a/src/backends/meta-settings-private.h
|
|
+++ b/src/backends/meta-settings-private.h
|
|
@@ -36,6 +36,7 @@ typedef enum _MetaExperimentalFeature
|
|
META_EXPERIMENTAL_FEATURE_RT_SCHEDULER = (1 << 2),
|
|
META_EXPERIMENTAL_FEATURE_DMA_BUF_SCREEN_SHARING = (1 << 3),
|
|
META_EXPERIMENTAL_FEATURE_AUTOCLOSE_XWAYLAND = (1 << 4),
|
|
+ META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING = (1 << 5),
|
|
} MetaExperimentalFeature;
|
|
|
|
typedef enum _MetaXwaylandExtension
|
|
@@ -44,6 +45,13 @@ typedef enum _MetaXwaylandExtension
|
|
META_XWAYLAND_EXTENSION_XTEST = (1 << 1),
|
|
} MetaXwaylandExtension;
|
|
|
|
+typedef enum _MetaX11ScaleMode
|
|
+{
|
|
+ META_X11_SCALE_MODE_NONE = 0,
|
|
+ META_X11_SCALE_MODE_UP = 1,
|
|
+ META_X11_SCALE_MODE_UI_DOWN = 2,
|
|
+} MetaX11ScaleMode;
|
|
+
|
|
#define META_TYPE_SETTINGS (meta_settings_get_type ())
|
|
G_DECLARE_FINAL_TYPE (MetaSettings, meta_settings,
|
|
META, SETTINGS, GObject)
|
|
@@ -78,4 +86,9 @@ gboolean meta_settings_are_xwayland_grabs_allowed (MetaSettings *settings);
|
|
|
|
int meta_settings_get_xwayland_disable_extensions (MetaSettings *settings);
|
|
|
|
+MetaX11ScaleMode meta_settings_get_x11_scale_mode (MetaSettings *settings);
|
|
+
|
|
+void meta_settings_enable_x11_fractional_scaling (MetaSettings *settings,
|
|
+ gboolean enabled);
|
|
+
|
|
#endif /* META_SETTINGS_PRIVATE_H */
|
|
diff --git a/src/backends/meta-settings.c b/src/backends/meta-settings.c
|
|
index 6a754d4..b2a6408 100644
|
|
--- a/src/backends/meta-settings.c
|
|
+++ b/src/backends/meta-settings.c
|
|
@@ -40,6 +40,7 @@ enum
|
|
UI_SCALING_FACTOR_CHANGED,
|
|
GLOBAL_SCALING_FACTOR_CHANGED,
|
|
FONT_DPI_CHANGED,
|
|
+ X11_SCALE_MODE_CHANGED,
|
|
EXPERIMENTAL_FEATURES_CHANGED,
|
|
|
|
N_SIGNALS
|
|
@@ -56,6 +57,7 @@ struct _MetaSettings
|
|
GSettings *interface_settings;
|
|
GSettings *mutter_settings;
|
|
GSettings *wayland_settings;
|
|
+ GSettings *x11_settings;
|
|
|
|
int ui_scaling_factor;
|
|
int global_scaling_factor;
|
|
@@ -71,6 +73,8 @@ struct _MetaSettings
|
|
|
|
/* A bitmask of MetaXwaylandExtension enum */
|
|
int xwayland_disable_extensions;
|
|
+
|
|
+ MetaX11ScaleMode x11_scale_mode;
|
|
};
|
|
|
|
G_DEFINE_TYPE (MetaSettings, meta_settings, G_TYPE_OBJECT)
|
|
@@ -80,14 +84,39 @@ calculate_ui_scaling_factor (MetaSettings *settings)
|
|
{
|
|
MetaMonitorManager *monitor_manager =
|
|
meta_backend_get_monitor_manager (settings->backend);
|
|
- MetaLogicalMonitor *primary_logical_monitor;
|
|
|
|
- primary_logical_monitor =
|
|
- meta_monitor_manager_get_primary_logical_monitor (monitor_manager);
|
|
- if (!primary_logical_monitor)
|
|
- return 1;
|
|
+ if (!meta_is_wayland_compositor () &&
|
|
+ monitor_manager &&
|
|
+ (meta_monitor_manager_get_capabilities (monitor_manager) &
|
|
+ META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE))
|
|
+ {
|
|
+ MetaLogicalMonitorLayoutMode layout_mode =
|
|
+ meta_monitor_manager_get_default_layout_mode (monitor_manager);
|
|
+
|
|
+ if (layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL)
|
|
+ {
|
|
+ return
|
|
+ ceilf (meta_monitor_manager_get_maximum_crtc_scale (monitor_manager));
|
|
+ }
|
|
+ else if (layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL)
|
|
+ {
|
|
+ return 1.0f;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (monitor_manager)
|
|
+ {
|
|
+ MetaLogicalMonitor *primary_logical_monitor;
|
|
+
|
|
+ primary_logical_monitor =
|
|
+ meta_monitor_manager_get_primary_logical_monitor (monitor_manager);
|
|
+ if (!primary_logical_monitor)
|
|
+ return 1;
|
|
+
|
|
+ return (int) meta_logical_monitor_get_scale (primary_logical_monitor);
|
|
+ }
|
|
|
|
- return (int) meta_logical_monitor_get_scale (primary_logical_monitor);
|
|
+ return 1;
|
|
}
|
|
|
|
static gboolean
|
|
@@ -235,6 +264,76 @@ meta_settings_override_experimental_features (MetaSettings *settings)
|
|
settings->experimental_features_overridden = TRUE;
|
|
}
|
|
|
|
+static gboolean
|
|
+update_x11_scale_mode (MetaSettings *settings)
|
|
+{
|
|
+ MetaX11ScaleMode scale_mode;
|
|
+
|
|
+ if (!(settings->experimental_features &
|
|
+ META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING))
|
|
+ {
|
|
+ scale_mode = META_X11_SCALE_MODE_NONE;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ scale_mode =
|
|
+ g_settings_get_enum (settings->x11_settings, "fractional-scale-mode");
|
|
+ }
|
|
+
|
|
+ if (settings->x11_scale_mode != scale_mode)
|
|
+ {
|
|
+ settings->x11_scale_mode = scale_mode;
|
|
+ return TRUE;
|
|
+ }
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+void meta_settings_enable_x11_fractional_scaling (MetaSettings *settings,
|
|
+ gboolean enable)
|
|
+{
|
|
+ g_auto(GStrv) existing_features = NULL;
|
|
+ gboolean have_fractional_scaling = FALSE;
|
|
+ g_autoptr(GVariantBuilder) builder = NULL;
|
|
+ MetaExperimentalFeature old_experimental_features;
|
|
+
|
|
+ if (enable == meta_settings_is_experimental_feature_enabled (settings,
|
|
+ META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING))
|
|
+ return;
|
|
+
|
|
+ /* Change the internal value now, as we don't want to wait for gsettings */
|
|
+ old_experimental_features = settings->experimental_features;
|
|
+ settings->experimental_features |=
|
|
+ META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING;
|
|
+
|
|
+ update_x11_scale_mode (settings);
|
|
+
|
|
+ g_signal_emit (settings, signals[EXPERIMENTAL_FEATURES_CHANGED], 0,
|
|
+ (unsigned int) old_experimental_features);
|
|
+
|
|
+ /* Add or remove the fractional scaling feature from mutter */
|
|
+ existing_features = g_settings_get_strv (settings->mutter_settings,
|
|
+ "experimental-features");
|
|
+ builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
|
|
+ for (int i = 0; existing_features[i] != NULL; i++)
|
|
+ {
|
|
+ if (g_strcmp0 (existing_features[i], "x11-randr-fractional-scaling") == 0)
|
|
+ {
|
|
+ if (enable)
|
|
+ have_fractional_scaling = TRUE;
|
|
+ else
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ g_variant_builder_add (builder, "s", existing_features[i]);
|
|
+ }
|
|
+ if (enable && !have_fractional_scaling)
|
|
+ g_variant_builder_add (builder, "s", "x11-randr-fractional-scaling");
|
|
+
|
|
+ g_settings_set_value (settings->mutter_settings, "experimental-features",
|
|
+ g_variant_builder_end (builder));
|
|
+}
|
|
+
|
|
void
|
|
meta_settings_enable_experimental_feature (MetaSettings *settings,
|
|
MetaExperimentalFeature feature)
|
|
@@ -242,6 +341,9 @@ meta_settings_enable_experimental_feature (MetaSettings *settings,
|
|
g_assert (settings->experimental_features_overridden);
|
|
|
|
settings->experimental_features |= feature;
|
|
+
|
|
+ if (update_x11_scale_mode (settings))
|
|
+ g_signal_emit (settings, signals[X11_SCALE_MODE_CHANGED], 0, NULL);
|
|
}
|
|
|
|
static gboolean
|
|
@@ -275,6 +377,8 @@ experimental_features_handler (GVariant *features_variant,
|
|
feature = META_EXPERIMENTAL_FEATURE_DMA_BUF_SCREEN_SHARING;
|
|
else if (g_str_equal (feature_str, "autoclose-xwayland"))
|
|
feature = META_EXPERIMENTAL_FEATURE_AUTOCLOSE_XWAYLAND;
|
|
+ else if (g_str_equal (feature_str, "x11-randr-fractional-scaling"))
|
|
+ feature = META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING;
|
|
|
|
if (feature)
|
|
g_message ("Enabling experimental feature '%s'", feature_str);
|
|
@@ -287,6 +391,7 @@ experimental_features_handler (GVariant *features_variant,
|
|
if (features != settings->experimental_features)
|
|
{
|
|
settings->experimental_features = features;
|
|
+ update_x11_scale_mode (settings);
|
|
*result = GINT_TO_POINTER (TRUE);
|
|
}
|
|
else
|
|
@@ -420,6 +525,18 @@ wayland_settings_changed (GSettings *wayland_settings,
|
|
}
|
|
}
|
|
|
|
+static void
|
|
+x11_settings_changed (GSettings *wayland_settings,
|
|
+ gchar *key,
|
|
+ MetaSettings *settings)
|
|
+{
|
|
+ if (g_str_equal (key, "fractional-scale-mode"))
|
|
+ {
|
|
+ if (update_x11_scale_mode (settings))
|
|
+ g_signal_emit (settings, signals[X11_SCALE_MODE_CHANGED], 0, NULL);
|
|
+ }
|
|
+}
|
|
+
|
|
void
|
|
meta_settings_get_xwayland_grab_patterns (MetaSettings *settings,
|
|
GPtrArray **allow_list_patterns,
|
|
@@ -441,6 +558,12 @@ meta_settings_get_xwayland_disable_extensions (MetaSettings *settings)
|
|
return (settings->xwayland_disable_extensions);
|
|
}
|
|
|
|
+MetaX11ScaleMode
|
|
+meta_settings_get_x11_scale_mode (MetaSettings *settings)
|
|
+{
|
|
+ return settings->x11_scale_mode;
|
|
+}
|
|
+
|
|
MetaSettings *
|
|
meta_settings_new (MetaBackend *backend)
|
|
{
|
|
@@ -460,6 +583,7 @@ meta_settings_dispose (GObject *object)
|
|
g_clear_object (&settings->mutter_settings);
|
|
g_clear_object (&settings->interface_settings);
|
|
g_clear_object (&settings->wayland_settings);
|
|
+ g_clear_object (&settings->x11_settings);
|
|
g_clear_pointer (&settings->xwayland_grab_allow_list_patterns,
|
|
g_ptr_array_unref);
|
|
g_clear_pointer (&settings->xwayland_grab_deny_list_patterns,
|
|
@@ -483,6 +607,10 @@ meta_settings_init (MetaSettings *settings)
|
|
g_signal_connect (settings->wayland_settings, "changed",
|
|
G_CALLBACK (wayland_settings_changed),
|
|
settings);
|
|
+ settings->x11_settings = g_settings_new ("org.gnome.mutter.x11");
|
|
+ g_signal_connect (settings->x11_settings, "changed",
|
|
+ G_CALLBACK (x11_settings_changed),
|
|
+ settings);
|
|
|
|
/* Chain up inter-dependent settings. */
|
|
g_signal_connect (settings, "global-scaling-factor-changed",
|
|
@@ -549,6 +677,14 @@ meta_settings_class_init (MetaSettingsClass *klass)
|
|
NULL, NULL, NULL,
|
|
G_TYPE_NONE, 0);
|
|
|
|
+ signals[X11_SCALE_MODE_CHANGED] =
|
|
+ g_signal_new ("x11-scale-mode-changed",
|
|
+ G_TYPE_FROM_CLASS (object_class),
|
|
+ G_SIGNAL_RUN_LAST,
|
|
+ 0,
|
|
+ NULL, NULL, NULL,
|
|
+ G_TYPE_NONE, 0);
|
|
+
|
|
signals[EXPERIMENTAL_FEATURES_CHANGED] =
|
|
g_signal_new ("experimental-features-changed",
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
diff --git a/src/backends/native/meta-monitor-manager-native.c b/src/backends/native/meta-monitor-manager-native.c
|
|
index fd5e778..3864474 100644
|
|
--- a/src/backends/native/meta-monitor-manager-native.c
|
|
+++ b/src/backends/native/meta-monitor-manager-native.c
|
|
@@ -571,20 +571,9 @@ meta_monitor_manager_native_is_transform_handled (MetaMonitorManager *manager,
|
|
transform);
|
|
}
|
|
|
|
-static float
|
|
-meta_monitor_manager_native_calculate_monitor_mode_scale (MetaMonitorManager *manager,
|
|
- MetaMonitor *monitor,
|
|
- MetaMonitorMode *monitor_mode)
|
|
-{
|
|
- return meta_monitor_calculate_mode_scale (monitor, monitor_mode);
|
|
-}
|
|
+static MetaMonitorScalesConstraint
|
|
+get_monitor_scale_constraints_per_layout_mode (MetaLogicalMonitorLayoutMode layout_mode)
|
|
|
|
-static float *
|
|
-meta_monitor_manager_native_calculate_supported_scales (MetaMonitorManager *manager,
|
|
- MetaLogicalMonitorLayoutMode layout_mode,
|
|
- MetaMonitor *monitor,
|
|
- MetaMonitorMode *monitor_mode,
|
|
- int *n_supported_scales)
|
|
{
|
|
MetaMonitorScalesConstraint constraints =
|
|
META_MONITOR_SCALES_CONSTRAINT_NONE;
|
|
@@ -598,6 +587,32 @@ meta_monitor_manager_native_calculate_supported_scales (MetaMonitorManager
|
|
break;
|
|
}
|
|
|
|
+ return constraints;
|
|
+}
|
|
+
|
|
+static float
|
|
+meta_monitor_manager_native_calculate_monitor_mode_scale (MetaMonitorManager *manager,
|
|
+ MetaLogicalMonitorLayoutMode layout_mode,
|
|
+ MetaMonitor *monitor,
|
|
+ MetaMonitorMode *monitor_mode)
|
|
+{
|
|
+ MetaMonitorScalesConstraint constraints =
|
|
+ get_monitor_scale_constraints_per_layout_mode (layout_mode);
|
|
+
|
|
+ return meta_monitor_calculate_mode_scale (monitor, monitor_mode, constraints);
|
|
+}
|
|
+
|
|
+static float *
|
|
+meta_monitor_manager_native_calculate_supported_scales (MetaMonitorManager *manager,
|
|
+ MetaLogicalMonitorLayoutMode layout_mode,
|
|
+ MetaMonitor *monitor,
|
|
+ MetaMonitorMode *monitor_mode,
|
|
+ int *n_supported_scales)
|
|
+{
|
|
+ MetaMonitorScalesConstraint constraints =
|
|
+ get_monitor_scale_constraints_per_layout_mode (layout_mode);
|
|
+
|
|
+
|
|
return meta_monitor_calculate_supported_scales (monitor, monitor_mode,
|
|
constraints,
|
|
n_supported_scales);
|
|
diff --git a/src/backends/x11/meta-crtc-xrandr.c b/src/backends/x11/meta-crtc-xrandr.c
|
|
index e06448b6..e17d3ea 100644
|
|
--- a/src/backends/x11/meta-crtc-xrandr.c
|
|
+++ b/src/backends/x11/meta-crtc-xrandr.c
|
|
@@ -36,6 +36,7 @@
|
|
#include "backends/x11/meta-crtc-xrandr.h"
|
|
|
|
#include <X11/Xlib-xcb.h>
|
|
+#include <X11/extensions/Xrender.h>
|
|
#include <stdlib.h>
|
|
#include <xcb/randr.h>
|
|
|
|
@@ -46,6 +47,9 @@
|
|
#include "backends/x11/meta-gpu-xrandr.h"
|
|
#include "backends/x11/meta-monitor-manager-xrandr.h"
|
|
|
|
+#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
|
+#define DOUBLE_TO_FIXED(d) ((xcb_render_fixed_t) ((d) * 65536))
|
|
+
|
|
struct _MetaCrtcXrandr
|
|
{
|
|
MetaCrtc parent;
|
|
@@ -110,6 +114,63 @@ meta_crtc_xrandr_set_config (MetaCrtcXrandr *crtc_xrandr,
|
|
*out_timestamp = reply->timestamp;
|
|
free (reply);
|
|
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+gboolean
|
|
+meta_crtc_xrandr_set_scale (MetaCrtc *crtc,
|
|
+ xcb_randr_crtc_t xrandr_crtc,
|
|
+ float scale)
|
|
+{
|
|
+ MetaGpu *gpu = meta_crtc_get_gpu (crtc);
|
|
+ MetaBackend *backend = meta_gpu_get_backend (gpu);
|
|
+ MetaMonitorManager *monitor_manager =
|
|
+ meta_backend_get_monitor_manager (backend);
|
|
+ MetaMonitorManagerXrandr *monitor_manager_xrandr =
|
|
+ META_MONITOR_MANAGER_XRANDR (monitor_manager);
|
|
+ Display *xdisplay;
|
|
+ const char *scale_filter;
|
|
+ xcb_connection_t *xcb_conn;
|
|
+ xcb_void_cookie_t transform_cookie;
|
|
+ xcb_generic_error_t *xcb_error = NULL;
|
|
+ xcb_render_transform_t transformation = {
|
|
+ DOUBLE_TO_FIXED (1), DOUBLE_TO_FIXED (0), DOUBLE_TO_FIXED (0),
|
|
+ DOUBLE_TO_FIXED (0), DOUBLE_TO_FIXED (1), DOUBLE_TO_FIXED (0),
|
|
+ DOUBLE_TO_FIXED (0), DOUBLE_TO_FIXED (0), DOUBLE_TO_FIXED (1)
|
|
+ };
|
|
+
|
|
+ if (!(meta_monitor_manager_get_capabilities (monitor_manager) &
|
|
+ META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING))
|
|
+ return FALSE;
|
|
+
|
|
+ xdisplay = meta_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr);
|
|
+ xcb_conn = XGetXCBConnection (xdisplay);
|
|
+
|
|
+ if (fabsf (scale - 1.0f) > 0.001)
|
|
+ {
|
|
+ scale_filter = FilterGood;
|
|
+ transformation.matrix11 = DOUBLE_TO_FIXED (1.0 / scale);
|
|
+ transformation.matrix22 = DOUBLE_TO_FIXED (1.0 / scale);
|
|
+ }
|
|
+ else
|
|
+ scale_filter = FilterFast;
|
|
+
|
|
+ transform_cookie =
|
|
+ xcb_randr_set_crtc_transform_checked (xcb_conn, xrandr_crtc, transformation,
|
|
+ strlen (scale_filter), scale_filter,
|
|
+ 0, NULL);
|
|
+
|
|
+ xcb_error = xcb_request_check (xcb_conn, transform_cookie);
|
|
+ if (xcb_error)
|
|
+ {
|
|
+ g_warning ("Impossible to set scaling on crtc %u to %f, error id %u",
|
|
+ xrandr_crtc, scale, xcb_error->error_code);
|
|
+ g_clear_pointer (&xcb_error, free);
|
|
+
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
return TRUE;
|
|
}
|
|
|
|
@@ -221,11 +282,34 @@ meta_crtc_xrandr_get_current_mode (MetaCrtcXrandr *crtc_xrandr)
|
|
return crtc_xrandr->current_mode;
|
|
}
|
|
|
|
+static float
|
|
+meta_monitor_scale_from_transformation (XRRCrtcTransformAttributes *transformation)
|
|
+{
|
|
+ XTransform *xt;
|
|
+ float scale;
|
|
+
|
|
+ if (!transformation)
|
|
+ return 1.0f;
|
|
+
|
|
+ xt = &transformation->currentTransform;
|
|
+
|
|
+ if (xt->matrix[0][0] == xt->matrix[1][1])
|
|
+ scale = XFixedToDouble (xt->matrix[0][0]);
|
|
+ else
|
|
+ scale = XFixedToDouble (xt->matrix[0][0] + xt->matrix[1][1]) / 2.0;
|
|
+
|
|
+ g_return_val_if_fail (scale > 0.0f, 1.0f);
|
|
+
|
|
+ return 1.0f / scale;
|
|
+}
|
|
+
|
|
MetaCrtcXrandr *
|
|
-meta_crtc_xrandr_new (MetaGpuXrandr *gpu_xrandr,
|
|
- XRRCrtcInfo *xrandr_crtc,
|
|
- RRCrtc crtc_id,
|
|
- XRRScreenResources *resources)
|
|
+meta_crtc_xrandr_new (MetaGpuXrandr *gpu_xrandr,
|
|
+ XRRCrtcInfo *xrandr_crtc,
|
|
+ RRCrtc crtc_id,
|
|
+ XRRScreenResources *resources,
|
|
+ XRRCrtcTransformAttributes *transform_attributes,
|
|
+ float scale_multiplier)
|
|
{
|
|
MetaGpu *gpu = META_GPU (gpu_xrandr);
|
|
MetaBackend *backend = meta_gpu_get_backend (gpu);
|
|
@@ -285,6 +369,9 @@ meta_crtc_xrandr_new (MetaGpuXrandr *gpu_xrandr,
|
|
|
|
if (crtc_xrandr->current_mode)
|
|
{
|
|
+ float crtc_scale =
|
|
+ meta_monitor_scale_from_transformation (transform_attributes);
|
|
+
|
|
meta_crtc_set_config (META_CRTC (crtc_xrandr),
|
|
&GRAPHENE_RECT_INIT (crtc_xrandr->rect.x,
|
|
crtc_xrandr->rect.y,
|
|
@@ -292,6 +379,11 @@ meta_crtc_xrandr_new (MetaGpuXrandr *gpu_xrandr,
|
|
crtc_xrandr->rect.height),
|
|
crtc_xrandr->current_mode,
|
|
crtc_xrandr->transform);
|
|
+
|
|
+ if (scale_multiplier > 0.0f)
|
|
+ crtc_scale *= scale_multiplier;
|
|
+
|
|
+ meta_crtc_set_config_scale (META_CRTC (crtc_xrandr), crtc_scale);
|
|
}
|
|
|
|
return crtc_xrandr;
|
|
diff --git a/src/backends/x11/meta-crtc-xrandr.h b/src/backends/x11/meta-crtc-xrandr.h
|
|
index dbf5da0..dbaeb26 100644
|
|
--- a/src/backends/x11/meta-crtc-xrandr.h
|
|
+++ b/src/backends/x11/meta-crtc-xrandr.h
|
|
@@ -44,14 +44,20 @@ gboolean meta_crtc_xrandr_set_config (MetaCrtcXrandr *crtc_xrandr,
|
|
int n_outputs,
|
|
xcb_timestamp_t *out_timestamp);
|
|
|
|
+gboolean meta_crtc_xrandr_set_scale (MetaCrtc *crtc,
|
|
+ xcb_randr_crtc_t xrandr_crtc,
|
|
+ float scale);
|
|
+
|
|
gboolean meta_crtc_xrandr_is_assignment_changed (MetaCrtcXrandr *crtc_xrandr,
|
|
MetaCrtcAssignment *crtc_assignment);
|
|
|
|
MetaCrtcMode * meta_crtc_xrandr_get_current_mode (MetaCrtcXrandr *crtc_xrandr);
|
|
|
|
-MetaCrtcXrandr * meta_crtc_xrandr_new (MetaGpuXrandr *gpu_xrandr,
|
|
- XRRCrtcInfo *xrandr_crtc,
|
|
- RRCrtc crtc_id,
|
|
- XRRScreenResources *resources);
|
|
+MetaCrtcXrandr * meta_crtc_xrandr_new (MetaGpuXrandr *gpu_xrandr,
|
|
+ XRRCrtcInfo *xrandr_crtc,
|
|
+ RRCrtc crtc_id,
|
|
+ XRRScreenResources *resources,
|
|
+ XRRCrtcTransformAttributes *transform_attributes,
|
|
+ float scale_multiplier);
|
|
|
|
#endif /* META_CRTC_XRANDR_H */
|
|
diff --git a/src/backends/x11/meta-gpu-xrandr.c b/src/backends/x11/meta-gpu-xrandr.c
|
|
index bc3292d..0e9d55a 100644
|
|
--- a/src/backends/x11/meta-gpu-xrandr.c
|
|
+++ b/src/backends/x11/meta-gpu-xrandr.c
|
|
@@ -23,6 +23,7 @@
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
+#include "backends/meta-crtc.h"
|
|
#include "config.h"
|
|
|
|
#include "backends/x11/meta-gpu-xrandr.h"
|
|
@@ -45,6 +45,8 @@ struct _MetaGpuXrandr
|
|
|
|
XRRScreenResources *resources;
|
|
|
|
+ int min_screen_width;
|
|
+ int min_screen_height;
|
|
int max_screen_width;
|
|
int max_screen_height;
|
|
|
|
@@ -56,6 +59,15 @@ meta_gpu_xrandr_get_resources (MetaGpuXrandr *gpu_xrandr)
|
|
return gpu_xrandr->resources;
|
|
}
|
|
|
|
+void
|
|
+meta_gpu_xrandr_get_min_screen_size (MetaGpuXrandr *gpu_xrandr,
|
|
+ int *min_width,
|
|
+ int *min_height)
|
|
+{
|
|
+ *min_width = gpu_xrandr->min_screen_width;
|
|
+ *min_height = gpu_xrandr->min_screen_height;
|
|
+}
|
|
+
|
|
void
|
|
meta_gpu_xrandr_get_max_screen_size (MetaGpuXrandr *gpu_xrandr,
|
|
int *max_width,
|
|
@@ -98,6 +100,60 @@ get_xmode_name (XRRModeInfo *xmode)
|
|
return g_strdup_printf ("%dx%d", width, height);
|
|
}
|
|
|
|
+static int
|
|
+get_current_dpi_scale (MetaMonitorManagerXrandr *manager_xrandr,
|
|
+ MetaGpuXrandr *gpu_xrandr)
|
|
+{
|
|
+ Atom actual;
|
|
+ int result, format;
|
|
+ unsigned long n, left;
|
|
+ g_autofree unsigned char *data = NULL;
|
|
+ g_auto(GStrv) resources = NULL;
|
|
+ Display *dpy;
|
|
+ int i;
|
|
+
|
|
+ if (gpu_xrandr->resources->timestamp ==
|
|
+ meta_monitor_manager_xrandr_get_config_timestamp (manager_xrandr))
|
|
+ {
|
|
+ MetaMonitorManager *monitor_manager = META_MONITOR_MANAGER (manager_xrandr);
|
|
+ MetaBackend *backend = meta_monitor_manager_get_backend (monitor_manager);
|
|
+ MetaSettings *settings = meta_backend_get_settings (backend);
|
|
+
|
|
+ return meta_settings_get_ui_scaling_factor (settings);
|
|
+ }
|
|
+
|
|
+ dpy = meta_monitor_manager_xrandr_get_xdisplay (manager_xrandr);
|
|
+ result = XGetWindowProperty (dpy, DefaultRootWindow (dpy),
|
|
+ XA_RESOURCE_MANAGER, 0L, 65536, False,
|
|
+ XA_STRING, &actual, &format,
|
|
+ &n, &left, &data);
|
|
+
|
|
+ if (result != Success || !data || actual != XA_STRING)
|
|
+ return 1;
|
|
+
|
|
+ resources = g_strsplit ((char *) data, "\n", -1);
|
|
+
|
|
+ for (i = 0; resources && resources[i]; ++i)
|
|
+ {
|
|
+ if (g_str_has_prefix (resources[i], "Xft.dpi:"))
|
|
+ {
|
|
+ g_auto(GStrv) res = g_strsplit (resources[i], "\t", 2);
|
|
+
|
|
+ if (res && res[0] && res[1])
|
|
+ {
|
|
+ guint64 dpi;
|
|
+ dpi = g_ascii_strtoull (res[1], NULL, 10);
|
|
+
|
|
+ if (dpi > 0 && dpi < 96 * 10)
|
|
+ return MAX (1, roundf ((float) dpi / 96.0f));
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+
|
|
static float
|
|
calculate_xrandr_refresh_rate (XRRModeInfo *xmode)
|
|
{
|
|
@@ -135,12 +191,13 @@ update_screen_size (MetaGpuXrandr *gpu_xrandr)
|
|
META_MONITOR_MANAGER_XRANDR (monitor_manager);
|
|
Display *xdisplay =
|
|
meta_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr);
|
|
- int min_width, min_height;
|
|
+ gboolean has_transform;
|
|
+ int dpi_scale = 1;
|
|
Screen *screen;
|
|
|
|
XRRGetScreenSizeRange (xdisplay, DefaultRootWindow (xdisplay),
|
|
- &min_width,
|
|
- &min_height,
|
|
+ &gpu_xrandr->min_screen_width,
|
|
+ &gpu_xrandr->min_screen_height,
|
|
&gpu_xrandr->max_screen_width,
|
|
&gpu_xrandr->max_screen_height);
|
|
|
|
@@ -162,22 +228,60 @@ meta_gpu_xrandr_read_current (MetaGpu *gpu,
|
|
}
|
|
meta_gpu_take_modes (gpu, modes);
|
|
|
|
+ has_transform = !!(meta_monitor_manager_get_capabilities (monitor_manager) &
|
|
+ META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING);
|
|
+
|
|
+ if (has_transform &&
|
|
+ meta_monitor_manager_get_default_layout_mode (monitor_manager) ==
|
|
+ META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL)
|
|
+ dpi_scale = get_current_dpi_scale (monitor_manager_xrandr, gpu_xrandr);
|
|
+
|
|
for (i = 0; i < (unsigned)resources->ncrtc; i++)
|
|
{
|
|
XRRCrtcInfo *xrandr_crtc;
|
|
+ XRRCrtcTransformAttributes *transform_attributes;
|
|
RRCrtc crtc_id;
|
|
MetaCrtcXrandr *crtc_xrandr;
|
|
|
|
crtc_id = resources->crtcs[i];
|
|
xrandr_crtc = XRRGetCrtcInfo (xdisplay,
|
|
resources, crtc_id);
|
|
+
|
|
+ if (!has_transform ||
|
|
+ !XRRGetCrtcTransform (xdisplay, crtc_id, &transform_attributes))
|
|
+ transform_attributes = NULL;
|
|
+
|
|
crtc_xrandr = meta_crtc_xrandr_new (gpu_xrandr,
|
|
- xrandr_crtc, crtc_id, resources);
|
|
+ xrandr_crtc, crtc_id, resources,
|
|
+ transform_attributes, dpi_scale);
|
|
+ XFree (transform_attributes);
|
|
XRRFreeCrtcInfo (xrandr_crtc);
|
|
|
|
crtcs = g_list_append (crtcs, crtc_xrandr);
|
|
}
|
|
|
|
+ if (has_transform && dpi_scale == 1 &&
|
|
+ meta_monitor_manager_get_default_layout_mode (monitor_manager) ==
|
|
+ META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL)
|
|
+ {
|
|
+ dpi_scale =
|
|
+ ceilf (meta_monitor_manager_get_maximum_crtc_scale (monitor_manager));
|
|
+
|
|
+ if (dpi_scale > 1)
|
|
+ {
|
|
+ for (l = crtcs; l; l = l->next)
|
|
+ {
|
|
+ MetaCrtc *crtc = l->data;
|
|
+ const MetaCrtcConfig *crtc_config = meta_crtc_get_config (crtc);
|
|
+
|
|
+ if (!crtc_config)
|
|
+ continue;
|
|
+
|
|
+ meta_crtc_set_config_scale (crtc, crtc_config->scale * dpi_scale);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
meta_gpu_take_crtcs (gpu, crtcs);
|
|
|
|
primary_output = XRRGetOutputPrimary (xdisplay,
|
|
@@ -252,6 +309,8 @@ meta_gpu_xrandr_read_current (MetaGpu *gpu,
|
|
GList *outputs = NULL;
|
|
GList *modes = NULL;
|
|
GList *crtcs = NULL;
|
|
+ gboolean has_transform;
|
|
+ int dpi_scale = 1;
|
|
|
|
if (!meta_monitor_manager_xrandr_has_randr (monitor_manager_xrandr))
|
|
return read_current_fallback (gpu_xrandr, monitor_manager_xrandr);
|
|
diff --git a/src/backends/x11/meta-gpu-xrandr.h b/src/backends/x11/meta-gpu-xrandr.h
|
|
index 2086f86..a1f3b48 100644
|
|
--- a/src/backends/x11/meta-gpu-xrandr.h
|
|
+++ b/src/backends/x11/meta-gpu-xrandr.h
|
|
@@ -33,6 +33,10 @@ G_DECLARE_FINAL_TYPE (MetaGpuXrandr, meta_gpu_xrandr, META, GPU_XRANDR, MetaGpu)
|
|
|
|
XRRScreenResources * meta_gpu_xrandr_get_resources (MetaGpuXrandr *gpu_xrandr);
|
|
|
|
+void meta_gpu_xrandr_get_min_screen_size (MetaGpuXrandr *gpu_xrandr,
|
|
+ int *min_width,
|
|
+ int *min_height);
|
|
+
|
|
void meta_gpu_xrandr_get_max_screen_size (MetaGpuXrandr *gpu_xrandr,
|
|
int *max_width,
|
|
int *max_height);
|
|
diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
|
|
index 489a9b4..f2ddbfe 100644
|
|
--- a/src/backends/x11/meta-monitor-manager-xrandr.c
|
|
+++ b/src/backends/x11/meta-monitor-manager-xrandr.c
|
|
@@ -36,6 +36,7 @@
|
|
* and udev.
|
|
*/
|
|
|
|
+#include "backends/meta-backend-types.h"
|
|
#include "config.h"
|
|
|
|
#include "backends/x11/meta-monitor-manager-xrandr.h"
|
|
@@ -64,6 +65,9 @@
|
|
* http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/xsettings/gsd-xsettings-manager.c
|
|
* for the reasoning */
|
|
#define DPI_FALLBACK 96.0
|
|
+#define RANDR_VERSION_FORMAT(major, minor) ((major * 100) + minor)
|
|
+#define RANDR_TILING_MIN_VERSION RANDR_VERSION_FORMAT (1, 5)
|
|
+#define RANDR_TRANSFORM_MIN_VERSION RANDR_VERSION_FORMAT (1, 3)
|
|
|
|
struct _MetaMonitorManagerXrandr
|
|
{
|
|
@@ -81,16 +81,16 @@ struct _MetaMonitorManagerXrandr
|
|
guint logind_signal_sub_id;
|
|
|
|
gboolean has_randr;
|
|
- gboolean has_randr15;
|
|
+ int randr_version;
|
|
|
|
xcb_timestamp_t last_xrandr_set_timestamp;
|
|
|
|
GHashTable *tiled_monitor_atoms;
|
|
|
|
- float *supported_scales;
|
|
- int n_supported_scales;
|
|
};
|
|
|
|
+static MetaGpu * meta_monitor_manager_xrandr_get_gpu (MetaMonitorManagerXrandr *manager_xrandr);
|
|
+
|
|
struct _MetaMonitorManagerXrandrClass
|
|
{
|
|
MetaMonitorManagerClass parent_class;
|
|
@@ -119,10 +119,10 @@ meta_monitor_manager_xrandr_has_randr (MetaMonitorManagerXrandr *manager_xrandr)
|
|
return manager_xrandr->has_randr;
|
|
}
|
|
|
|
-gboolean
|
|
-meta_monitor_manager_xrandr_has_randr15 (MetaMonitorManagerXrandr *manager_xrandr)
|
|
+uint32_t
|
|
+meta_monitor_manager_xrandr_get_config_timestamp (MetaMonitorManagerXrandr *manager_xrandr)
|
|
{
|
|
- return manager_xrandr->has_randr15;
|
|
+ return manager_xrandr->last_xrandr_set_timestamp;
|
|
}
|
|
|
|
static GBytes *
|
|
@@ -187,6 +191,81 @@ meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager,
|
|
DPMSSetTimeouts (manager_xrandr->xdisplay, 0, 0, 0);
|
|
}
|
|
|
|
+static void
|
|
+meta_monitor_manager_xrandr_update_screen_size (MetaMonitorManagerXrandr *manager_xrandr,
|
|
+ int width,
|
|
+ int height,
|
|
+ float scale)
|
|
+{
|
|
+ MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
|
|
+ MetaGpu *gpu = meta_monitor_manager_xrandr_get_gpu (manager_xrandr);
|
|
+ xcb_connection_t *xcb_conn;
|
|
+ xcb_generic_error_t *xcb_error;
|
|
+ xcb_void_cookie_t xcb_cookie;
|
|
+ Screen *screen;
|
|
+ int min_width;
|
|
+ int min_height;
|
|
+ int max_width;
|
|
+ int max_height;
|
|
+ int width_mm;
|
|
+ int height_mm;
|
|
+
|
|
+ g_assert (width > 0 && height > 0 && scale > 0);
|
|
+
|
|
+ if (manager->screen_width == width && manager->screen_height == height)
|
|
+ return;
|
|
+
|
|
+ screen = ScreenOfDisplay (manager_xrandr->xdisplay,
|
|
+ DefaultScreen (manager_xrandr->xdisplay));
|
|
+ meta_gpu_xrandr_get_min_screen_size (META_GPU_XRANDR (gpu),
|
|
+ &min_width, &min_height);
|
|
+ meta_gpu_xrandr_get_max_screen_size (META_GPU_XRANDR (gpu),
|
|
+ &max_width, &max_height);
|
|
+ width = MIN (MAX (min_width, width), max_width);
|
|
+ height = MIN (MAX (min_height, height), max_height);
|
|
+
|
|
+ /* The 'physical size' of an X screen is meaningless if that screen can
|
|
+ * consist of many monitors. So just pick a size that make the dpi 96.
|
|
+ *
|
|
+ * Firefox and Evince apparently believe what X tells them.
|
|
+ */
|
|
+ width_mm = (width / (DPI_FALLBACK * scale)) * 25.4 + 0.5;
|
|
+ height_mm = (height / (DPI_FALLBACK * scale)) * 25.4 + 0.5;
|
|
+
|
|
+ if (width == WidthOfScreen (screen) && height == HeightOfScreen (screen) &&
|
|
+ width_mm == WidthMMOfScreen (screen) && height_mm == HeightMMOfScreen (screen))
|
|
+ return;
|
|
+
|
|
+ xcb_conn = XGetXCBConnection (manager_xrandr->xdisplay);
|
|
+
|
|
+ xcb_grab_server (xcb_conn);
|
|
+
|
|
+ /* Some drivers (nvidia I look at you!) might no advertise some CRTCs, so in
|
|
+ * such case, we may ignore X errors here */
|
|
+ xcb_cookie = xcb_randr_set_screen_size_checked (xcb_conn,
|
|
+ DefaultRootWindow (manager_xrandr->xdisplay),
|
|
+ width, height,
|
|
+ width_mm, height_mm);
|
|
+ xcb_error = xcb_request_check (xcb_conn, xcb_cookie);
|
|
+ if (!xcb_error)
|
|
+ {
|
|
+ manager->screen_width = width;
|
|
+ manager->screen_height = height;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ gchar buf[64];
|
|
+
|
|
+ XGetErrorText (manager_xrandr->xdisplay, xcb_error->error_code, buf,
|
|
+ sizeof (buf) - 1);
|
|
+ g_warning ("Impossible to resize screen at size %dx%d, error id %u: %s",
|
|
+ width, height, xcb_error->error_code, buf);
|
|
+ g_clear_pointer (&xcb_error, free);
|
|
+ }
|
|
+
|
|
+ xcb_ungrab_server (xcb_conn);
|
|
+}
|
|
+
|
|
static xcb_randr_rotation_t
|
|
meta_monitor_transform_to_xrandr (MetaMonitorTransform transform)
|
|
{
|
|
@@ -242,13 +321,50 @@ xrandr_set_crtc_config (MetaMonitorManagerXrandr *manager_xrandr,
|
|
return TRUE;
|
|
}
|
|
|
|
+static float
|
|
+get_maximum_crtc_assignments_scale (MetaCrtcAssignment **crtc_assignments,
|
|
+ unsigned int n_crtc_assignments)
|
|
+{
|
|
+ float max_scale = 1.0f;
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < n_crtc_assignments; i++)
|
|
+ {
|
|
+ MetaCrtcAssignment *crtc_assignment = crtc_assignments[i];
|
|
+
|
|
+ if (crtc_assignment->mode)
|
|
+ max_scale = MAX (max_scale, crtc_assignment->scale);
|
|
+ }
|
|
+
|
|
+ return max_scale;
|
|
+}
|
|
+
|
|
static gboolean
|
|
-is_crtc_assignment_changed (MetaCrtc *crtc,
|
|
+is_crtc_assignment_changed (MetaMonitorManager *monitor_manager,
|
|
+ MetaCrtc *crtc,
|
|
MetaCrtcAssignment **crtc_assignments,
|
|
- unsigned int n_crtc_assignments)
|
|
+ unsigned int n_crtc_assignments,
|
|
+ gboolean *weak_change)
|
|
{
|
|
+ MetaLogicalMonitorLayoutMode layout_mode;
|
|
+ gboolean have_scaling;
|
|
+ float max_crtc_scale = 1.0f;
|
|
+ float max_req_scale = 1.0f;
|
|
unsigned int i;
|
|
|
|
+ layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager);
|
|
+ have_scaling = meta_monitor_manager_get_capabilities (monitor_manager) &
|
|
+ META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING;
|
|
+
|
|
+ if (have_scaling &&
|
|
+ layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL)
|
|
+ {
|
|
+ max_crtc_scale =
|
|
+ meta_monitor_manager_get_maximum_crtc_scale (monitor_manager);
|
|
+ max_req_scale =
|
|
+ get_maximum_crtc_assignments_scale (crtc_assignments, n_crtc_assignments);
|
|
+ }
|
|
+
|
|
for (i = 0; i < n_crtc_assignments; i++)
|
|
{
|
|
MetaCrtcAssignment *crtc_assignment = crtc_assignments[i];
|
|
@@ -256,8 +372,44 @@ is_crtc_assignment_changed (MetaCrtc *crtc,
|
|
if (crtc_assignment->crtc != crtc)
|
|
continue;
|
|
|
|
- return meta_crtc_xrandr_is_assignment_changed (META_CRTC_XRANDR (crtc),
|
|
- crtc_assignment);
|
|
+ if (meta_crtc_xrandr_is_assignment_changed (META_CRTC_XRANDR (crtc),
|
|
+ crtc_assignment))
|
|
+ return TRUE;
|
|
+
|
|
+ if (have_scaling)
|
|
+ {
|
|
+ const MetaCrtcConfig *crtc_config = meta_crtc_get_config (crtc);
|
|
+ float crtc_scale = crtc_config ? crtc_config->scale : 1.0f;
|
|
+ float req_output_scale = crtc_assignment->scale;
|
|
+
|
|
+ if (layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL)
|
|
+ {
|
|
+ if (fmodf (crtc_scale, 1.0) == 0.0f)
|
|
+ {
|
|
+ *weak_change = fabsf (crtc_scale - req_output_scale) > 0.001;
|
|
+ return FALSE;
|
|
+ }
|
|
+ }
|
|
+ else if (layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL)
|
|
+ {
|
|
+ /* In scale ui-down mode we need to check if the actual output
|
|
+ * scale that will be applied to the crtc has actually changed
|
|
+ * from the current value, so we need to compare the current crtc
|
|
+ * scale with the scale that will be applied taking care of the
|
|
+ * UI scale (max crtc scale) and of the requested maximum scale.
|
|
+ * If we don't do this, we'd try to call randr calls which won't
|
|
+ * ever trigger a RRScreenChangeNotify, as no actual change is
|
|
+ * needed, and thus we won't ever emit a monitors-changed signal.
|
|
+ */
|
|
+ crtc_scale /= ceilf (max_crtc_scale);
|
|
+ req_output_scale /= ceilf (max_req_scale);
|
|
+ }
|
|
+
|
|
+ if (fabsf (crtc_scale - req_output_scale) > 0.001)
|
|
+ return TRUE;
|
|
+ }
|
|
+
|
|
+ return FALSE;
|
|
}
|
|
|
|
return !!meta_crtc_xrandr_get_current_mode (META_CRTC_XRANDR (crtc));
|
|
@@ -333,7 +485,8 @@ is_assignments_changed (MetaMonitorManager *manager,
|
|
MetaCrtcAssignment **crtc_assignments,
|
|
unsigned int n_crtc_assignments,
|
|
MetaOutputAssignment **output_assignments,
|
|
- unsigned int n_output_assignments)
|
|
+ unsigned int n_output_assignments,
|
|
+ gboolean *weak_change)
|
|
{
|
|
MetaMonitorManagerXrandr *manager_xrandr =
|
|
META_MONITOR_MANAGER_XRANDR (manager);
|
|
@@ -344,7 +497,9 @@ is_assignments_changed (MetaMonitorManager *manager,
|
|
{
|
|
MetaCrtc *crtc = l->data;
|
|
|
|
- if (is_crtc_assignment_changed (crtc, crtc_assignments, n_crtc_assignments))
|
|
+ if (is_crtc_assignment_changed (manager, crtc,
|
|
+ crtc_assignments, n_crtc_assignments,
|
|
+ weak_change))
|
|
return TRUE;
|
|
}
|
|
|
|
@@ -360,6 +515,32 @@ is_assignments_changed (MetaMonitorManager *manager,
|
|
return TRUE;
|
|
}
|
|
|
|
+ if (meta_monitor_manager_get_default_layout_mode (manager) ==
|
|
+ META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL)
|
|
+ {
|
|
+ /* If nothing has changed, ensure that the crtc logical scaling matches
|
|
+ * with the requested one, as in case of global UI logical layout we might
|
|
+ * assume that it is in fact equal, while it's techincally different.
|
|
+ * Not doing this would then cause a wrong computation of the max crtc
|
|
+ * scale and thus of the UI scaling. */
|
|
+ for (l = meta_gpu_get_crtcs (gpu); l; l = l->next)
|
|
+ {
|
|
+ MetaCrtc *crtc = l->data;
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < n_crtc_assignments; i++)
|
|
+ {
|
|
+ MetaCrtcAssignment *crtc_assignment = crtc_assignments[i];
|
|
+
|
|
+ if (crtc_assignment->crtc == crtc)
|
|
+ {
|
|
+ meta_crtc_set_config_scale (crtc, crtc_assignment->scale);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
return FALSE;
|
|
}
|
|
|
|
@@ -375,31 +556,55 @@ apply_crtc_assignments (MetaMonitorManager *manager,
|
|
MetaGpu *gpu = meta_monitor_manager_xrandr_get_gpu (manager_xrandr);
|
|
g_autoptr (GList) to_configure_outputs = NULL;
|
|
g_autoptr (GList) to_disable_crtcs = NULL;
|
|
- unsigned i;
|
|
+ MetaBackend *backend = meta_monitor_manager_get_backend (manager);
|
|
+ MetaSettings *settings = meta_backend_get_settings (backend);
|
|
+ MetaX11ScaleMode scale_mode = meta_settings_get_x11_scale_mode (settings);
|
|
+ unsigned i, valid_crtcs;
|
|
GList *l;
|
|
- int width, height, width_mm, height_mm;
|
|
+ int width, height;
|
|
+ float max_scale;
|
|
+ float avg_screen_scale;
|
|
+ gboolean have_scaling;
|
|
|
|
to_configure_outputs = g_list_copy (meta_gpu_get_outputs (gpu));
|
|
to_disable_crtcs = g_list_copy (meta_gpu_get_crtcs (gpu));
|
|
|
|
XGrabServer (manager_xrandr->xdisplay);
|
|
|
|
- /* First compute the new size of the screen (framebuffer) */
|
|
+ have_scaling = meta_monitor_manager_get_capabilities (manager) &
|
|
+ META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING;
|
|
+
|
|
+ /* Compute the new size of the screen (framebuffer) */
|
|
+ max_scale = get_maximum_crtc_assignments_scale (crtcs, n_crtcs);
|
|
width = 0; height = 0;
|
|
+ avg_screen_scale = 0;
|
|
+ valid_crtcs = 0;
|
|
for (i = 0; i < n_crtcs; i++)
|
|
{
|
|
MetaCrtcAssignment *crtc_assignment = crtcs[i];
|
|
MetaCrtc *crtc = crtc_assignment->crtc;
|
|
+ float scale = 1.0f;
|
|
|
|
if (crtc_assignment->mode == NULL)
|
|
continue;
|
|
|
|
to_disable_crtcs = g_list_remove (to_disable_crtcs, crtc);
|
|
|
|
- width = MAX (width, (int) roundf (crtc_assignment->layout.origin.x +
|
|
- crtc_assignment->layout.size.width));
|
|
- height = MAX (height, (int) roundf (crtc_assignment->layout.origin.y +
|
|
- crtc_assignment->layout.size.height));
|
|
+ if (have_scaling && scale_mode == META_X11_SCALE_MODE_UI_DOWN)
|
|
+ {
|
|
+ scale = (ceilf (max_scale) / crtc_assignment->scale) *
|
|
+ crtc_assignment->scale;
|
|
+ }
|
|
+
|
|
+ width = MAX (width,
|
|
+ (int) roundf (crtc_assignment->layout.origin.x +
|
|
+ crtc_assignment->layout.size.width * scale));
|
|
+ height = MAX (height,
|
|
+ (int) roundf (crtc_assignment->layout.origin.y +
|
|
+ crtc_assignment->layout.size.height * scale));
|
|
+
|
|
+ avg_screen_scale += (crtc_assignment->scale - avg_screen_scale) /
|
|
+ (float) (++valid_crtcs);
|
|
}
|
|
|
|
/* Second disable all newly disabled CRTCs, or CRTCs that in the previous
|
|
@@ -433,6 +638,10 @@ apply_crtc_assignments (MetaMonitorManager *manager,
|
|
0, 0, XCB_NONE,
|
|
XCB_RANDR_ROTATION_ROTATE_0,
|
|
NULL, 0);
|
|
+ if (have_scaling)
|
|
+ meta_crtc_xrandr_set_scale (crtc,
|
|
+ (xcb_randr_crtc_t) meta_crtc_get_id (crtc),
|
|
+ 1.0f);
|
|
|
|
meta_crtc_unset_config (crtc);
|
|
}
|
|
@@ -453,6 +662,10 @@ apply_crtc_assignments (MetaMonitorManager *manager,
|
|
0, 0, XCB_NONE,
|
|
XCB_RANDR_ROTATION_ROTATE_0,
|
|
NULL, 0);
|
|
+ if (have_scaling)
|
|
+ meta_crtc_xrandr_set_scale (crtc,
|
|
+ (xcb_randr_crtc_t) meta_crtc_get_id (crtc),
|
|
+ 1.0f);
|
|
|
|
meta_crtc_unset_config (crtc);
|
|
}
|
|
@@ -460,17 +673,12 @@ apply_crtc_assignments (MetaMonitorManager *manager,
|
|
if (!n_crtcs)
|
|
goto out;
|
|
|
|
- g_assert (width > 0 && height > 0);
|
|
- /* The 'physical size' of an X screen is meaningless if that screen
|
|
- * can consist of many monitors. So just pick a size that make the
|
|
- * dpi 96.
|
|
- *
|
|
- * Firefox and Evince apparently believe what X tells them.
|
|
- */
|
|
- width_mm = (width / DPI_FALLBACK) * 25.4 + 0.5;
|
|
- height_mm = (height / DPI_FALLBACK) * 25.4 + 0.5;
|
|
- XRRSetScreenSize (manager_xrandr->xdisplay, DefaultRootWindow (manager_xrandr->xdisplay),
|
|
- width, height, width_mm, height_mm);
|
|
+ if (width > manager->screen_width || height > manager->screen_height)
|
|
+ {
|
|
+ meta_monitor_manager_xrandr_update_screen_size (manager_xrandr,
|
|
+ width, height,
|
|
+ avg_screen_scale);
|
|
+ }
|
|
|
|
for (i = 0; i < n_crtcs; i++)
|
|
{
|
|
@@ -486,12 +694,21 @@ apply_crtc_assignments (MetaMonitorManager *manager,
|
|
int x, y;
|
|
xcb_randr_rotation_t rotation;
|
|
xcb_randr_mode_t mode;
|
|
+ float scale = 1.0f;
|
|
|
|
crtc_mode = crtc_assignment->mode;
|
|
|
|
n_output_ids = crtc_assignment->outputs->len;
|
|
output_ids = g_new (xcb_randr_output_t, n_output_ids);
|
|
|
|
+ if (have_scaling && scale_mode != META_X11_SCALE_MODE_NONE)
|
|
+ {
|
|
+ scale = crtc_assignment->scale;
|
|
+
|
|
+ if (scale_mode == META_X11_SCALE_MODE_UI_DOWN)
|
|
+ scale /= ceilf (max_scale);
|
|
+ }
|
|
+
|
|
for (j = 0; j < n_output_ids; j++)
|
|
{
|
|
MetaOutput *output;
|
|
@@ -516,6 +733,14 @@ apply_crtc_assignments (MetaMonitorManager *manager,
|
|
rotation =
|
|
meta_monitor_transform_to_xrandr (crtc_assignment->transform);
|
|
mode = meta_crtc_mode_get_id (crtc_mode);
|
|
+
|
|
+ if (have_scaling &&
|
|
+ !meta_crtc_xrandr_set_scale (crtc, crtc_id, scale))
|
|
+ {
|
|
+ meta_warning ("Scalig CRTC %d at %f failed\n",
|
|
+ (unsigned) crtc_id, scale);
|
|
+ }
|
|
+
|
|
if (!xrandr_set_crtc_config (manager_xrandr,
|
|
crtc,
|
|
save_timestamp,
|
|
@@ -544,6 +769,20 @@ apply_crtc_assignments (MetaMonitorManager *manager,
|
|
&crtc_assignment->layout,
|
|
crtc_mode,
|
|
crtc_assignment->transform);
|
|
+ meta_crtc_set_config_scale (crtc, crtc_assignment->scale);
|
|
+
|
|
+ if (have_scaling && scale_mode == META_X11_SCALE_MODE_UI_DOWN)
|
|
+ {
|
|
+ const MetaCrtcConfig *crtc_config = meta_crtc_get_config (crtc);
|
|
+ graphene_size_t *crtc_size =
|
|
+ (graphene_size_t *) &crtc_config->layout.size;
|
|
+
|
|
+ scale = (ceilf (max_scale) / crtc_assignment->scale) *
|
|
+ crtc_assignment->scale;
|
|
+
|
|
+ crtc_size->width = roundf (crtc_size->width * scale);
|
|
+ crtc_size->height = roundf (crtc_size->height * scale);
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -559,6 +798,13 @@ apply_crtc_assignments (MetaMonitorManager *manager,
|
|
(GFunc) meta_output_unassign_crtc,
|
|
NULL);
|
|
|
|
+ if (width > 0 && height > 0)
|
|
+ {
|
|
+ meta_monitor_manager_xrandr_update_screen_size (manager_xrandr,
|
|
+ width, height,
|
|
+ avg_screen_scale);
|
|
+ }
|
|
+
|
|
out:
|
|
XUngrabServer (manager_xrandr->xdisplay);
|
|
XFlush (manager_xrandr->xdisplay);
|
|
@@ -585,14 +831,88 @@ meta_monitor_manager_xrandr_ensure_initial_config (MetaMonitorManager *manager)
|
|
}
|
|
|
|
static void
|
|
-meta_monitor_manager_xrandr_rebuild_derived (MetaMonitorManager *manager,
|
|
- MetaMonitorsConfig *config)
|
|
+meta_monitor_manager_xrandr_update_screen_size_derived (MetaMonitorManager *manager,
|
|
+ MetaMonitorsConfig *config)
|
|
{
|
|
MetaMonitorManagerXrandr *manager_xrandr =
|
|
META_MONITOR_MANAGER_XRANDR (manager);
|
|
+ MetaBackend *backend = meta_monitor_manager_get_backend (manager);
|
|
+ MetaSettings *settings = meta_backend_get_settings (backend);
|
|
+ MetaX11ScaleMode scale_mode = meta_settings_get_x11_scale_mode (settings);
|
|
+ int screen_width = 0;
|
|
+ int screen_height = 0;
|
|
+ unsigned n_crtcs = 0;
|
|
+ float average_scale = 0;
|
|
+ gboolean have_scaling;
|
|
+ GList *l;
|
|
+
|
|
+ have_scaling = meta_monitor_manager_get_capabilities (manager) &
|
|
+ META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING;
|
|
+
|
|
+ /* Compute the new size of the screen (framebuffer) */
|
|
+ for (l = manager->monitors; l != NULL; l = l->next)
|
|
+ {
|
|
+ MetaMonitor *monitor = l->data;
|
|
+ MetaOutput *output = meta_monitor_get_main_output (monitor);
|
|
+ MetaCrtc *crtc = meta_output_get_assigned_crtc (output);
|
|
+ const MetaCrtcConfig *crtc_config;
|
|
+ const graphene_rect_t *crtc_layout;
|
|
+ float scale = 1.0f;
|
|
+
|
|
+ if (!crtc)
|
|
+ continue;
|
|
|
|
- g_clear_pointer (&manager_xrandr->supported_scales, g_free);
|
|
- meta_monitor_manager_rebuild_derived (manager, config);
|
|
+ crtc_config = meta_crtc_get_config (crtc);
|
|
+
|
|
+ if (!crtc_config)
|
|
+ continue;
|
|
+
|
|
+ if (!have_scaling || scale_mode != META_X11_SCALE_MODE_UI_DOWN)
|
|
+ {
|
|
+ /* When scaling up we should not reduce the screen size, or X will
|
|
+ * fail miserably, while we must do it when scaling down, in order to
|
|
+ * increase the available screen area we can use. */
|
|
+ scale = crtc_config->scale > 1.0f ? crtc_config->scale : 1.0f;
|
|
+ }
|
|
+
|
|
+ /* When computing the screen size from the crtc rects we don't have to
|
|
+ * use inverted values when monitors are rotated, because this is already
|
|
+ * taken in account in the crtc rectangles */
|
|
+ crtc_layout = &crtc_config->layout;
|
|
+ screen_width = MAX (screen_width, crtc_layout->origin.x +
|
|
+ roundf (crtc_layout->size.width * scale));
|
|
+ screen_height = MAX (screen_height, crtc_layout->origin.y +
|
|
+ roundf (crtc_layout->size.height * scale));
|
|
+ ++n_crtcs;
|
|
+
|
|
+ /* This value isn't completely exact, since it doesn't take care of the
|
|
+ * actual crtc sizes, however, since w're going to use this only to set
|
|
+ * the MM size of the screen, and given that this value is just an
|
|
+ * estimation, we don't need to be super precise. */
|
|
+ average_scale += (crtc_config->scale - average_scale) / (float) n_crtcs;
|
|
+ }
|
|
+
|
|
+ if (screen_width > 0 && screen_height > 0)
|
|
+ {
|
|
+ meta_monitor_manager_xrandr_update_screen_size (manager_xrandr,
|
|
+ screen_width,
|
|
+ screen_height,
|
|
+ average_scale);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+maybe_update_ui_scaling_factor (MetaMonitorManager *manager,
|
|
+ MetaMonitorsConfig *config)
|
|
+{
|
|
+ if (config->layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL ||
|
|
+ manager->layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL)
|
|
+ {
|
|
+ MetaBackend *backend = meta_monitor_manager_get_backend (manager);
|
|
+ MetaSettings *settings = meta_backend_get_settings (backend);
|
|
+
|
|
+ meta_settings_update_ui_scaling_factor (settings);
|
|
+ }
|
|
}
|
|
|
|
static gboolean
|
|
@@ -609,7 +929,7 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *mana
|
|
if (!manager->in_init)
|
|
apply_crtc_assignments (manager, TRUE, NULL, 0, NULL, 0);
|
|
|
|
- meta_monitor_manager_xrandr_rebuild_derived (manager, NULL);
|
|
+ meta_monitor_manager_rebuild_derived (manager, NULL);
|
|
return TRUE;
|
|
}
|
|
|
|
@@ -621,6 +941,8 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *mana
|
|
|
|
if (method != META_MONITORS_CONFIG_METHOD_VERIFY)
|
|
{
|
|
+ gboolean weak_change = FALSE;
|
|
+
|
|
/*
|
|
* If the assignment has not changed, we won't get any notification about
|
|
* any new configuration from the X server; but we still need to update
|
|
@@ -628,12 +950,16 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *mana
|
|
* have changed locally, such as the logical monitors scale. This means we
|
|
* must check that our new assignment actually changes anything, otherwise
|
|
* just update the logical state.
|
|
+ * If we record a weak change it means that only UI scaling needs to be
|
|
+ * updated and so that we don't have to reconfigure the CRTCs, but still
|
|
+ * need to update the logical state.
|
|
*/
|
|
if (is_assignments_changed (manager,
|
|
(MetaCrtcAssignment **) crtc_assignments->pdata,
|
|
crtc_assignments->len,
|
|
(MetaOutputAssignment **) output_assignments->pdata,
|
|
- output_assignments->len))
|
|
+ output_assignments->len,
|
|
+ &weak_change))
|
|
{
|
|
apply_crtc_assignments (manager,
|
|
TRUE,
|
|
@@ -641,10 +967,14 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *mana
|
|
crtc_assignments->len,
|
|
(MetaOutputAssignment **) output_assignments->pdata,
|
|
output_assignments->len);
|
|
+ maybe_update_ui_scaling_factor (manager, config);
|
|
}
|
|
else
|
|
{
|
|
- meta_monitor_manager_xrandr_rebuild_derived (manager, config);
|
|
+ if (weak_change)
|
|
+ maybe_update_ui_scaling_factor (manager, config);
|
|
+
|
|
+ meta_monitor_manager_rebuild_derived (manager, config);
|
|
}
|
|
}
|
|
|
|
@@ -777,7 +1107,8 @@ meta_monitor_manager_xrandr_tiled_monitor_added (MetaMonitorManager *manager,
|
|
GList *l;
|
|
int i;
|
|
|
|
- if (manager_xrandr->has_randr15 == FALSE)
|
|
+ if (!(meta_monitor_manager_get_capabilities (manager) &
|
|
+ META_MONITOR_MANAGER_CAPABILITY_TILING))
|
|
return;
|
|
|
|
product = meta_monitor_get_product (monitor);
|
|
@@ -826,7 +1157,8 @@ meta_monitor_manager_xrandr_tiled_monitor_removed (MetaMonitorManager *manager,
|
|
|
|
int monitor_count;
|
|
|
|
- if (manager_xrandr->has_randr15 == FALSE)
|
|
+ if (!(meta_monitor_manager_get_capabilities (manager) &
|
|
+ META_MONITOR_MANAGER_CAPABILITY_TILING))
|
|
return;
|
|
|
|
monitor_xrandr_data = meta_monitor_xrandr_data_from_monitor (monitor);
|
|
@@ -844,10 +1176,12 @@ meta_monitor_manager_xrandr_tiled_monitor_removed (MetaMonitorManager *manager,
|
|
static void
|
|
meta_monitor_manager_xrandr_init_monitors (MetaMonitorManagerXrandr *manager_xrandr)
|
|
{
|
|
+ MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
|
|
XRRMonitorInfo *m;
|
|
int n, i;
|
|
|
|
- if (manager_xrandr->has_randr15 == FALSE)
|
|
+ if (!(meta_monitor_manager_get_capabilities (manager) &
|
|
+ META_MONITOR_MANAGER_CAPABILITY_TILING))
|
|
return;
|
|
|
|
/* delete any tiled monitors setup, as mutter will want to recreate
|
|
@@ -879,83 +1213,26 @@ meta_monitor_manager_xrandr_is_transform_handled (MetaMonitorManager *manager,
|
|
return TRUE;
|
|
}
|
|
|
|
-static float
|
|
-meta_monitor_manager_xrandr_calculate_monitor_mode_scale (MetaMonitorManager *manager,
|
|
- MetaMonitor *monitor,
|
|
- MetaMonitorMode *monitor_mode)
|
|
-{
|
|
- return meta_monitor_calculate_mode_scale (monitor, monitor_mode);
|
|
-}
|
|
-
|
|
-static void
|
|
-add_supported_scale (GArray *supported_scales,
|
|
- float scale)
|
|
+static MetaMonitorScalesConstraint
|
|
+get_scale_constraints (MetaMonitorManager *manager)
|
|
{
|
|
- unsigned int i;
|
|
+ MetaMonitorScalesConstraint constraints = 0;
|
|
|
|
- for (i = 0; i < supported_scales->len; i++)
|
|
- {
|
|
- float supported_scale = g_array_index (supported_scales, float, i);
|
|
-
|
|
- if (scale == supported_scale)
|
|
- return;
|
|
- }
|
|
-
|
|
- g_array_append_val (supported_scales, scale);
|
|
-}
|
|
-
|
|
-static int
|
|
-compare_scales (gconstpointer a,
|
|
- gconstpointer b)
|
|
-{
|
|
- float f = *(float *) a - *(float *) b;
|
|
+ if (meta_monitor_manager_get_capabilities (manager) &
|
|
+ META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED)
|
|
+ constraints |= META_MONITOR_SCALES_CONSTRAINT_NO_FRAC;
|
|
|
|
- if (f < 0)
|
|
- return -1;
|
|
- if (f > 0)
|
|
- return 1;
|
|
- return 0;
|
|
+ return constraints;
|
|
}
|
|
|
|
-static void
|
|
-ensure_supported_monitor_scales (MetaMonitorManager *manager)
|
|
+static float
|
|
+meta_monitor_manager_xrandr_calculate_monitor_mode_scale (MetaMonitorManager *manager,
|
|
+ MetaLogicalMonitorLayoutMode layout_mode,
|
|
+ MetaMonitor *monitor,
|
|
+ MetaMonitorMode *monitor_mode)
|
|
{
|
|
- MetaMonitorManagerXrandr *manager_xrandr =
|
|
- META_MONITOR_MANAGER_XRANDR (manager);
|
|
- MetaMonitorScalesConstraint constraints;
|
|
- GList *l;
|
|
- GArray *supported_scales;
|
|
-
|
|
- if (manager_xrandr->supported_scales)
|
|
- return;
|
|
-
|
|
- constraints = META_MONITOR_SCALES_CONSTRAINT_NO_FRAC;
|
|
- supported_scales = g_array_new (FALSE, FALSE, sizeof (float));
|
|
-
|
|
- for (l = manager->monitors; l; l = l->next)
|
|
- {
|
|
- MetaMonitor *monitor = l->data;
|
|
- MetaMonitorMode *monitor_mode;
|
|
- float *monitor_scales;
|
|
- int n_monitor_scales;
|
|
- int i;
|
|
-
|
|
- monitor_mode = meta_monitor_get_preferred_mode (monitor);
|
|
- monitor_scales =
|
|
- meta_monitor_calculate_supported_scales (monitor,
|
|
- monitor_mode,
|
|
- constraints,
|
|
- &n_monitor_scales);
|
|
-
|
|
- for (i = 0; i < n_monitor_scales; i++)
|
|
- add_supported_scale (supported_scales, monitor_scales[i]);
|
|
- g_array_sort (supported_scales, compare_scales);
|
|
- g_free (monitor_scales);
|
|
- }
|
|
-
|
|
- manager_xrandr->supported_scales = (float *) supported_scales->data;
|
|
- manager_xrandr->n_supported_scales = supported_scales->len;
|
|
- g_array_free (supported_scales, FALSE);
|
|
+ return meta_monitor_calculate_mode_scale (monitor, monitor_mode,
|
|
+ get_scale_constraints (manager));
|
|
}
|
|
|
|
static float *
|
|
@@ -996,9 +1291,41 @@ meta_monitor_manager_xrandr_get_max_screen_size (MetaMonitorManager *manager,
|
|
return TRUE;
|
|
}
|
|
|
|
+static void
|
|
+scale_mode_changed (MetaSettings *settings,
|
|
+ MetaMonitorManager *manager)
|
|
+{
|
|
+ if (!(meta_monitor_manager_get_capabilities (manager) &
|
|
+ META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING))
|
|
+ return;
|
|
+
|
|
+ if (!meta_settings_is_experimental_feature_enabled (settings,
|
|
+ META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING))
|
|
+ return;
|
|
+
|
|
+ meta_monitor_manager_reconfigure (manager);
|
|
+ meta_settings_update_ui_scaling_factor (settings);
|
|
+}
|
|
+
|
|
static MetaLogicalMonitorLayoutMode
|
|
meta_monitor_manager_xrandr_get_default_layout_mode (MetaMonitorManager *manager)
|
|
{
|
|
+ MetaMonitorManagerCapability capabilities =
|
|
+ meta_monitor_manager_get_capabilities (manager);
|
|
+
|
|
+ if ((capabilities & META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING) &&
|
|
+ (capabilities & META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE))
|
|
+ {
|
|
+ MetaBackend *backend = meta_monitor_manager_get_backend (manager);
|
|
+ MetaSettings *settings = meta_backend_get_settings (backend);
|
|
+ MetaX11ScaleMode scale_mode = meta_settings_get_x11_scale_mode (settings);
|
|
+
|
|
+ if (scale_mode == META_X11_SCALE_MODE_UI_DOWN)
|
|
+ return META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL;
|
|
+ else if (scale_mode == META_X11_SCALE_MODE_UP)
|
|
+ return META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL;
|
|
+ }
|
|
+
|
|
return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
|
|
}
|
|
|
|
@@ -1017,6 +1344,7 @@ meta_monitor_manager_xrandr_constructed (GObject *object)
|
|
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
|
|
MetaBackend *backend = meta_monitor_manager_get_backend (manager);
|
|
MetaBackendX11 *backend_x11 = META_BACKEND_X11 (backend);
|
|
+ MetaSettings *settings = meta_backend_get_settings (backend);
|
|
|
|
manager_xrandr->xdisplay = meta_backend_x11_get_xdisplay (backend_x11);
|
|
|
|
@@ -1037,19 +1365,19 @@ meta_monitor_manager_xrandr_constructed (GObject *object)
|
|
| RRCrtcChangeNotifyMask
|
|
| RROutputPropertyNotifyMask);
|
|
|
|
- manager_xrandr->has_randr15 = FALSE;
|
|
XRRQueryVersion (manager_xrandr->xdisplay, &major_version,
|
|
&minor_version);
|
|
- if (major_version > 1 ||
|
|
- (major_version == 1 &&
|
|
- minor_version >= 5))
|
|
- {
|
|
- manager_xrandr->has_randr15 = TRUE;
|
|
- manager_xrandr->tiled_monitor_atoms = g_hash_table_new (NULL, NULL);
|
|
- }
|
|
+ manager_xrandr->randr_version = RANDR_VERSION_FORMAT (major_version,
|
|
+ minor_version);
|
|
+ if (manager_xrandr->randr_version >= RANDR_TILING_MIN_VERSION)
|
|
+ manager_xrandr->tiled_monitor_atoms = g_hash_table_new (NULL, NULL);
|
|
+
|
|
meta_monitor_manager_xrandr_init_monitors (manager_xrandr);
|
|
}
|
|
|
|
+ g_signal_connect_object (settings, "x11-scale-mode-changed",
|
|
+ G_CALLBACK (scale_mode_changed), manager_xrandr, 0);
|
|
+
|
|
G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->constructed (object);
|
|
}
|
|
|
|
@@ -1082,6 +1409,7 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
|
|
manager_class->read_current_state = meta_monitor_manager_xrandr_read_current_state;
|
|
manager_class->ensure_initial_config = meta_monitor_manager_xrandr_ensure_initial_config;
|
|
manager_class->apply_monitors_config = meta_monitor_manager_xrandr_apply_monitors_config;
|
|
+ manager_class->update_screen_size_derived = meta_monitor_manager_xrandr_update_screen_size_derived;
|
|
manager_class->set_power_save_mode = meta_monitor_manager_xrandr_set_power_save_mode;
|
|
manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight;
|
|
manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma;
|
|
@@ -1275,21 +1275,38 @@ meta_monitor_manager_xrandr_calculate_supported_scales (MetaMonitorManager
|
|
MetaMonitorMode *monitor_mode,
|
|
int *n_supported_scales)
|
|
{
|
|
- MetaMonitorManagerXrandr *manager_xrandr =
|
|
- META_MONITOR_MANAGER_XRANDR (manager);
|
|
-
|
|
- ensure_supported_monitor_scales (manager);
|
|
-
|
|
- *n_supported_scales = manager_xrandr->n_supported_scales;
|
|
- return g_memdup2 (manager_xrandr->supported_scales,
|
|
- manager_xrandr->n_supported_scales * sizeof (float));
|
|
+ return meta_monitor_calculate_supported_scales (monitor, monitor_mode,
|
|
+ get_scale_constraints (manager),
|
|
+ n_supported_scales);
|
|
}
|
|
|
|
static MetaMonitorManagerCapability
|
|
meta_monitor_manager_xrandr_get_capabilities (MetaMonitorManager *manager)
|
|
{
|
|
- return (META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED |
|
|
- META_MONITOR_MANAGER_CAPABILITY_CAN_DERIVE_CURRENT);
|
|
+ MetaMonitorManagerCapability capabilities;
|
|
+ MetaMonitorManagerXrandr *xrandr_manager = META_MONITOR_MANAGER_XRANDR (manager);
|
|
+ MetaBackend *backend = meta_monitor_manager_get_backend (manager);
|
|
+ MetaSettings *settings = meta_backend_get_settings (backend);
|
|
+
|
|
+ capabilities = META_MONITOR_MANAGER_CAPABILITY_NONE;
|
|
+
|
|
+ if (xrandr_manager->randr_version >= RANDR_TILING_MIN_VERSION)
|
|
+ capabilities |= META_MONITOR_MANAGER_CAPABILITY_TILING;
|
|
+
|
|
+ if (xrandr_manager->randr_version >= RANDR_TRANSFORM_MIN_VERSION)
|
|
+ capabilities |= META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING;
|
|
+
|
|
+ if (meta_settings_is_experimental_feature_enabled (settings,
|
|
+ META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING))
|
|
+ {
|
|
+ capabilities |= META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ capabilities |= META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED;
|
|
+ }
|
|
+
|
|
+ return capabilities;
|
|
}
|
|
|
|
static gboolean
|
|
@@ -1465,7 +1482,7 @@ meta_monitor_manager_xrandr_finalize (GObject *object)
|
|
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (object);
|
|
|
|
g_hash_table_destroy (manager_xrandr->tiled_monitor_atoms);
|
|
- g_free (manager_xrandr->supported_scales);
|
|
+
|
|
|
|
if (manager_xrandr->logind_watch_id > 0)
|
|
g_bus_unwatch_name (manager_xrandr->logind_watch_id);
|
|
@@ -1575,7 +1592,7 @@ meta_monitor_manager_xrandr_update (MetaMonitorManagerXrandr *manager_xrandr)
|
|
config = NULL;
|
|
}
|
|
|
|
- meta_monitor_manager_xrandr_rebuild_derived (manager, config);
|
|
+ meta_monitor_manager_rebuild_derived (manager, config);
|
|
}
|
|
}
|
|
|
|
diff --git a/src/backends/x11/meta-monitor-manager-xrandr.h b/src/backends/x11/meta-monitor-manager-xrandr.h
|
|
index dc75134..aa385f9 100644
|
|
--- a/src/backends/x11/meta-monitor-manager-xrandr.h
|
|
+++ b/src/backends/x11/meta-monitor-manager-xrandr.h
|
|
@@ -35,11 +35,13 @@ Display * meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *ma
|
|
|
|
gboolean meta_monitor_manager_xrandr_has_randr (MetaMonitorManagerXrandr *manager_xrandr);
|
|
|
|
-gboolean meta_monitor_manager_xrandr_has_randr15 (MetaMonitorManagerXrandr *manager_xrandr);
|
|
-
|
|
gboolean meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager,
|
|
XEvent *event);
|
|
+
|
|
+uint32_t meta_monitor_manager_xrandr_get_config_timestamp (MetaMonitorManagerXrandr *manager);
|
|
|
|
void meta_monitor_manager_xrandr_update_dpms_state (MetaMonitorManagerXrandr *manager_xrandr);
|
|
|
|
+
|
|
+
|
|
#endif /* META_MONITOR_MANAGER_XRANDR_H */
|
|
diff --git a/src/backends/x11/meta-output-xrandr.c b/src/backends/x11/meta-output-xrandr.c
|
|
index 7265624..1d3da34 100644
|
|
--- a/src/backends/x11/meta-output-xrandr.c
|
|
+++ b/src/backends/x11/meta-output-xrandr.c
|
|
@@ -915,7 +915,8 @@ meta_output_xrandr_new (MetaGpuXrandr *gpu_xrandr,
|
|
output_info->height_mm = xrandr_output->mm_height;
|
|
}
|
|
|
|
- if (meta_monitor_manager_xrandr_has_randr15 (monitor_manager_xrandr))
|
|
+ if ((meta_monitor_manager_get_capabilities (monitor_manager) &
|
|
+ META_MONITOR_MANAGER_CAPABILITY_TILING))
|
|
output_info_init_tile_info (output_info, xdisplay, output_id);
|
|
output_info_init_modes (output_info, gpu, xrandr_output);
|
|
output_info_init_crtcs (output_info, gpu, xrandr_output);
|
|
diff --git a/src/compositor/meta-compositor-x11.c b/src/compositor/meta-compositor-x11.c
|
|
index 1d0ba4c..70017ca 100644
|
|
--- a/src/compositor/meta-compositor-x11.c
|
|
+++ b/src/compositor/meta-compositor-x11.c
|
|
@@ -31,6 +31,8 @@
|
|
#include "compositor/meta-sync-ring.h"
|
|
#include "compositor/meta-window-actor-x11.h"
|
|
#include "core/display-private.h"
|
|
+#include "core/window-private.h"
|
|
+#include "core/window-private.h"
|
|
#include "core/stack-tracker.h"
|
|
#include "core/stereo.h"
|
|
#include "x11/meta-x11-display-private.h"
|
|
@@ -52,6 +54,8 @@ struct _MetaCompositorX11
|
|
gboolean xserver_uses_monotonic_clock;
|
|
int64_t xserver_time_query_time_us;
|
|
int64_t xserver_time_offset_us;
|
|
+
|
|
+ gboolean randr_scale_disabled;
|
|
|
|
int glx_opcode;
|
|
gboolean stereo_tree_ext;
|
|
@@ -267,20 +270,91 @@ shape_cow_for_window (MetaCompositorX11 *compositor_x11,
|
|
}
|
|
}
|
|
|
|
+static void
|
|
+on_redirected_monitor_changed (MetaWindow *window,
|
|
+ int old_monitor,
|
|
+ MetaCompositorX11 *compositor_x11)
|
|
+{
|
|
+ MetaBackend *backend = meta_get_backend ();
|
|
+ MetaMonitorManager *monitor_manager =
|
|
+ meta_backend_get_monitor_manager (backend);
|
|
+
|
|
+ if (old_monitor >= 0 && window->monitor &&
|
|
+ window->monitor->number != old_monitor)
|
|
+ {
|
|
+ g_signal_handlers_block_by_func (window,
|
|
+ on_redirected_monitor_changed,
|
|
+ compositor_x11);
|
|
+
|
|
+ if (!compositor_x11->randr_scale_disabled)
|
|
+ {
|
|
+ compositor_x11->randr_scale_disabled =
|
|
+ meta_monitor_manager_disable_scale_for_monitor (monitor_manager,
|
|
+ window->monitor);
|
|
+ }
|
|
+
|
|
+ g_signal_handlers_unblock_by_func (window,
|
|
+ on_redirected_monitor_changed,
|
|
+ compositor_x11);
|
|
+ }
|
|
+ else
|
|
+ shape_cow_for_window (META_COMPOSITOR_X11 (compositor_x11), window);
|
|
+}
|
|
+
|
|
+static MetaWindow *
|
|
+get_unredirectable_window (MetaCompositorX11 *compositor_x11)
|
|
+{
|
|
+ MetaCompositor *compositor = META_COMPOSITOR (compositor_x11);
|
|
+ MetaWindowActor *window_actor;
|
|
+ MetaWindowActorX11 *window_actor_x11;
|
|
+
|
|
+ window_actor = meta_compositor_get_top_window_actor (compositor);
|
|
+ if (!window_actor)
|
|
+ return NULL;
|
|
+
|
|
+ window_actor_x11 = META_WINDOW_ACTOR_X11 (window_actor);
|
|
+ if (!meta_window_actor_x11_should_unredirect (window_actor_x11))
|
|
+ return NULL;
|
|
+
|
|
+ return meta_window_actor_get_meta_window (window_actor);
|
|
+}
|
|
+
|
|
static void
|
|
set_unredirected_window (MetaCompositorX11 *compositor_x11,
|
|
MetaWindow *window)
|
|
{
|
|
+ MetaBackend *backend;
|
|
+ MetaMonitorManager *monitor_manager;
|
|
MetaWindow *prev_unredirected_window = compositor_x11->unredirected_window;
|
|
|
|
if (prev_unredirected_window == window)
|
|
- return;
|
|
+ {
|
|
+ if (!window && compositor_x11->randr_scale_disabled &&
|
|
+ !get_unredirectable_window (compositor_x11))
|
|
+ {
|
|
+ backend = meta_get_backend ();
|
|
+ monitor_manager = meta_backend_get_monitor_manager (backend);
|
|
+
|
|
+ compositor_x11->randr_scale_disabled =
|
|
+ meta_monitor_manager_disable_scale_for_monitor (monitor_manager,
|
|
+ NULL);
|
|
+ }
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ backend = meta_get_backend ();
|
|
+ monitor_manager = meta_backend_get_monitor_manager (backend);
|
|
|
|
if (prev_unredirected_window)
|
|
{
|
|
MetaWindowActor *window_actor;
|
|
MetaWindowActorX11 *window_actor_x11;
|
|
|
|
+ g_signal_handlers_disconnect_by_func (prev_unredirected_window,
|
|
+ on_redirected_monitor_changed,
|
|
+ compositor_x11);
|
|
+
|
|
window_actor = meta_window_actor_from_window (prev_unredirected_window);
|
|
window_actor_x11 = META_WINDOW_ACTOR_X11 (window_actor);
|
|
meta_window_actor_x11_set_unredirected (window_actor_x11, FALSE);
|
|
@@ -294,6 +368,17 @@ set_unredirected_window (MetaCompositorX11 *compositor_x11,
|
|
MetaWindowActor *window_actor;
|
|
MetaWindowActorX11 *window_actor_x11;
|
|
|
|
+ if (!compositor_x11->randr_scale_disabled)
|
|
+ {
|
|
+ compositor_x11->randr_scale_disabled =
|
|
+ meta_monitor_manager_disable_scale_for_monitor (monitor_manager,
|
|
+ window->monitor);
|
|
+ }
|
|
+
|
|
+ g_signal_connect_object (window, "monitor-changed",
|
|
+ G_CALLBACK (on_redirected_monitor_changed),
|
|
+ compositor_x11, 0);
|
|
+
|
|
window_actor = meta_window_actor_from_window (window);
|
|
window_actor_x11 = META_WINDOW_ACTOR_X11 (window_actor);
|
|
meta_window_actor_x11_set_unredirected (window_actor_x11, TRUE);
|
|
@@ -305,21 +390,11 @@ maybe_unredirect_top_window (MetaCompositorX11 *compositor_x11)
|
|
{
|
|
MetaCompositor *compositor = META_COMPOSITOR (compositor_x11);
|
|
MetaWindow *window_to_unredirect = NULL;
|
|
- MetaWindowActor *window_actor;
|
|
- MetaWindowActorX11 *window_actor_x11;
|
|
|
|
if (meta_compositor_is_unredirect_inhibited (compositor))
|
|
goto out;
|
|
|
|
- window_actor = meta_compositor_get_top_window_actor (compositor);
|
|
- if (!window_actor)
|
|
- goto out;
|
|
-
|
|
- window_actor_x11 = META_WINDOW_ACTOR_X11 (window_actor);
|
|
- if (!meta_window_actor_x11_should_unredirect (window_actor_x11))
|
|
- goto out;
|
|
-
|
|
- window_to_unredirect = meta_window_actor_get_meta_window (window_actor);
|
|
+ window_to_unredirect = get_unredirectable_window (compositor_x11);
|
|
|
|
out:
|
|
set_unredirected_window (compositor_x11, window_to_unredirect);
|
|
diff --git a/src/core/boxes-private.h b/src/core/boxes-private.h
|
|
index d398164..482b0e5 100644
|
|
--- a/src/core/boxes-private.h
|
|
+++ b/src/core/boxes-private.h
|
|
@@ -158,6 +158,10 @@ gboolean meta_rectangle_overlaps_with_region (
|
|
const GList *spanning_rects,
|
|
const MetaRectangle *rect);
|
|
|
|
+gboolean meta_rectangle_has_adjacent_in_region (
|
|
+ const GList *spanning_rects,
|
|
+ const MetaRectangle *rect);
|
|
+
|
|
/* Make the rectangle small enough to fit into one of the spanning_rects,
|
|
* but make it no smaller than min_size.
|
|
*/
|
|
diff --git a/src/core/boxes.c b/src/core/boxes.c
|
|
index 9a9633e..afefba7 100644
|
|
--- a/src/core/boxes.c
|
|
+++ b/src/core/boxes.c
|
|
@@ -899,6 +899,27 @@ meta_rectangle_overlaps_with_region (const GList *spanning_rects,
|
|
return overlaps;
|
|
}
|
|
|
|
+gboolean
|
|
+meta_rectangle_has_adjacent_in_region (const GList *spanning_rects,
|
|
+ const MetaRectangle *rect)
|
|
+{
|
|
+ const GList *l;
|
|
+
|
|
+ for (l = spanning_rects; l; l = l->next)
|
|
+ {
|
|
+ MetaRectangle *other = (MetaRectangle *) l->data;
|
|
+
|
|
+ if (rect == other || meta_rectangle_equal (rect, other))
|
|
+ continue;
|
|
+
|
|
+ if (meta_rectangle_is_adjacent_to ((MetaRectangle *) rect, other))
|
|
+ {
|
|
+ return TRUE;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
|
|
void
|
|
meta_rectangle_clamp_to_fit_into_region (const GList *spanning_rects,
|
|
diff --git a/src/core/window.c b/src/core/window.c
|
|
index ea56f33..d2e7698 100644
|
|
--- a/src/core/window.c
|
|
+++ b/src/core/window.c
|
|
@@ -227,6 +227,7 @@ enum
|
|
UNMANAGED,
|
|
SIZE_CHANGED,
|
|
POSITION_CHANGED,
|
|
+ MONITOR_CHANGED,
|
|
SHOWN,
|
|
|
|
LAST_SIGNAL
|
|
@@ -683,6 +684,21 @@ meta_window_class_init (MetaWindowClass *klass)
|
|
NULL, NULL, NULL,
|
|
G_TYPE_NONE, 0);
|
|
|
|
+ /**
|
|
+ * MetaWindow::monitor-changed:
|
|
+ * @window: a #MetaWindow
|
|
+ * @old_monitor: the old monitor index or -1 if not known
|
|
+ *
|
|
+ * This is emitted when the window has changed monitor
|
|
+ */
|
|
+ window_signals[MONITOR_CHANGED] =
|
|
+ g_signal_new ("monitor-changed",
|
|
+ G_TYPE_FROM_CLASS (object_class),
|
|
+ G_SIGNAL_RUN_LAST,
|
|
+ 0,
|
|
+ NULL, NULL, NULL,
|
|
+ G_TYPE_NONE, 1, G_TYPE_INT);
|
|
+
|
|
/**
|
|
* MetaWindow::shown:
|
|
* @window: a #MetaWindow
|
|
@@ -936,6 +952,9 @@ meta_window_main_monitor_changed (MetaWindow *window,
|
|
{
|
|
META_WINDOW_GET_CLASS (window)->main_monitor_changed (window, old);
|
|
|
|
+ g_signal_emit (window, window_signals[MONITOR_CHANGED], 0,
|
|
+ old ? old->number : -1);
|
|
+
|
|
if (old)
|
|
g_signal_emit_by_name (window->display, "window-left-monitor",
|
|
old->number, window);
|
|
diff --git a/src/org.gnome.Mutter.DisplayConfig.xml b/src/org.gnome.Mutter.DisplayConfig.xml
|
|
index 7522652..0843e3a 100644
|
|
--- a/src/org.gnome.Mutter.DisplayConfig.xml
|
|
+++ b/src/org.gnome.Mutter.DisplayConfig.xml
|
|
@@ -393,6 +393,11 @@
|
|
using the logical monitor scale.
|
|
* 2 : physical - the dimension of a logical monitor is derived from
|
|
the monitor modes associated with it.
|
|
+ * 3 : logical with ui scaling - the dimension of a logical monitor
|
|
+ is derived from the monitor modes associated with it,
|
|
+ then scaled using the logical monitor scale that is also
|
|
+ scaled by the global UI scaling (computed using the maximum
|
|
+ ceiled scaling value across the displays).
|
|
* "supports-changing-layout-mode" (b): True if the layout mode can be
|
|
changed. Absence of this means the
|
|
layout mode cannot be changed.
|
|
diff --git a/src/tests/meta-monitor-manager-test.c b/src/tests/meta-monitor-manager-test.c
|
|
index 5a672c5..31e112a 100644
|
|
--- a/src/tests/meta-monitor-manager-test.c
|
|
+++ b/src/tests/meta-monitor-manager-test.c
|
|
@@ -290,9 +290,10 @@ meta_monitor_manager_test_is_transform_handled (MetaMonitorManager *manager,
|
|
}
|
|
|
|
static float
|
|
-meta_monitor_manager_test_calculate_monitor_mode_scale (MetaMonitorManager *manager,
|
|
- MetaMonitor *monitor,
|
|
- MetaMonitorMode *monitor_mode)
|
|
+meta_monitor_manager_test_calculate_monitor_mode_scale (MetaMonitorManager *manager,
|
|
+ MetaLogicalMonitorLayoutMode layout_mode,
|
|
+ MetaMonitor *monitor,
|
|
+ MetaMonitorMode *monitor_mode)
|
|
{
|
|
MetaOutput *output;
|
|
MetaOutputTest *output_test;
|
|
@@ -319,6 +320,7 @@ meta_monitor_manager_test_calculate_supported_scales (MetaMonitorManager
|
|
switch (layout_mode)
|
|
{
|
|
case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
|
|
+ case META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL:
|
|
break;
|
|
case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL:
|
|
constraints |= META_MONITOR_SCALES_CONSTRAINT_NO_FRAC;
|
|
@@ -344,8 +346,9 @@ is_monitor_framebuffer_scaled (void)
|
|
static MetaMonitorManagerCapability
|
|
meta_monitor_manager_test_get_capabilities (MetaMonitorManager *manager)
|
|
{
|
|
- MetaMonitorManagerCapability capabilities =
|
|
- META_MONITOR_MANAGER_CAPABILITY_NONE;
|
|
+ MetaMonitorManagerCapability capabilities;
|
|
+
|
|
+ capabilities = META_MONITOR_MANAGER_CAPABILITY_TILING;
|
|
|
|
if (is_monitor_framebuffer_scaled ())
|
|
capabilities |= META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE;
|