Commit baa2326b authored by Marco Trevisan's avatar Marco Trevisan 🎺

x11: Add logical layout mode with randr and UI scaling

Implement a new layout mode where we use both the global UI scaling and logical
sized monitors with inverse randr scaling.

It allows to support fractional scaling in the X11 backend with some good
quality image results also in multi-monitor with multi-DPI.

It works by scaling up the UI to the maximum ceiled scaling value across the
monitors, and then scaling down (via randr transformations) the monitors so
that:
  monitor_scaling = ui_scale * monitor_randr_scaling

In order to do this the layout GLOBAL_UI_LOGICAL is added which is logical mode
where monitor positioning is computed dividing the monitor scale by the maximum
scaling across the displays.

This is known to work at best with modesetting drivers when glamor is used.
parent ae7a77b7
......@@ -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'),
)
<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>
......@@ -656,11 +656,36 @@ create_monitor_config (MetaMonitor *monitor,
return monitor_config;
}
static float
get_preferred_preferred_max_scale (MetaMonitorManager *monitor_manager,
GList *monitors,
MetaLogicalMonitorLayoutMode layout_mode)
{
float scale = 1.0f;
GList *l;
for (l = monitors; l; l = l->next)
{
MetaMonitor *monitor = l->data;
MetaMonitorMode *mode = meta_monitor_get_preferred_mode (monitor);
float s =
meta_monitor_manager_calculate_monitor_mode_scale (monitor_manager,
layout_mode,
monitor,
mode);
scale = MAX (scale, s);
}
return scale;
}
static MetaLogicalMonitorConfig *
create_preferred_logical_monitor_config (MetaMonitor *monitor,
int x,
int y,
float scale,
float max_scale,
MetaLogicalMonitorLayoutMode layout_mode)
{
MetaMonitorMode *mode;
......@@ -677,6 +702,16 @@ create_preferred_logical_monitor_config (MetaMonitor *monitor,
width = (int) roundf (width / scale);
height = (int) roundf (height / scale);
break;
case META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL:
{
float ui_scale = scale;
if (max_scale > 0.0f)
ui_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;
}
......@@ -739,7 +774,7 @@ create_monitor_config_for_monitors (MetaMonitorConfigManager *config_manager,
g_autolist (MetaLogicalMonitorConfig) logical_monitor_configs = NULL;
MetaMonitor *primary_monitor;
MetaLogicalMonitorLayoutMode layout_mode;
float scale;
float scale, max_scale;
GList *l;
int x, y;
......@@ -748,6 +783,7 @@ create_monitor_config_for_monitors (MetaMonitorConfigManager *config_manager,
return NULL;
x = y = 0;
max_scale = 1.0f;
layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager);
if (!(match_rule & MONITOR_MATCH_PRIMARY))
......@@ -758,6 +794,11 @@ create_monitor_config_for_monitors (MetaMonitorConfigManager *config_manager,
monitors = g_list_prepend (g_list_remove (monitors, primary_monitor),
primary_monitor);
if (layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL)
max_scale = get_preferred_preferred_max_scale (monitor_manager,
monitors,
layout_mode);
for (l = monitors; l; l = l->next)
{
MetaMonitor *monitor = l->data;
......@@ -776,7 +817,7 @@ create_monitor_config_for_monitors (MetaMonitorConfigManager *config_manager,
monitor, primary_monitor);
logical_monitor_config =
create_preferred_logical_monitor_config (monitor,
x, y, scale,
x, y, scale, max_scale,
layout_mode);
logical_monitor_config->is_primary = (monitor == primary_monitor);
logical_monitor_configs = g_list_append (logical_monitor_configs,
......@@ -1502,6 +1543,7 @@ meta_verify_logical_monitor_config (MetaLogicalMonitorConfig *logical_monitor
switch (layout_mode)
{
case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
case META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL:
expected_mode_width = roundf (expected_mode_width *
logical_monitor_config->scale);
expected_mode_height = roundf (expected_mode_height *
......
......@@ -534,6 +534,7 @@ derive_logical_monitor_layout (MetaLogicalMonitorConfig *logical_monitor_conf
switch (layout_mode)
{
case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
case META_LOGICAL_MONITOR_LAYOUT_MODE_GLOBAL_UI_LOGICAL:
width = roundf (width / logical_monitor_config->scale);
height = roundf (height / logical_monitor_config->scale);
break;
......
......@@ -681,6 +681,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;
......
......@@ -61,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;
/*
......
......@@ -1520,8 +1520,14 @@ gboolean
meta_monitor_manager_disable_scale_for_monitor (MetaMonitorManager *manager,
MetaLogicalMonitor *monitor)
{
if (manager->layout_mode != META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL)
return FALSE;
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 && monitor->scale != 1.0f)
{
......@@ -2147,6 +2153,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;
......@@ -2269,6 +2276,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;
}
......@@ -2291,6 +2299,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)
{
......@@ -2362,10 +2371,26 @@ 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);
}
}
config = meta_monitors_config_new (manager,
logical_monitor_configs,
layout_mode,
......
......@@ -36,6 +36,12 @@ typedef enum _MetaExperimentalFeature
META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING = (1 << 2),
} MetaExperimentalFeature;
typedef enum _MetaX11ScaleMode
{
META_X11_SCALE_MODE_UP = 1,
META_X11_SCALE_MODE_UI_DOWN,
} MetaX11ScaleMode;
#define META_TYPE_SETTINGS (meta_settings_get_type ())
G_DECLARE_FINAL_TYPE (MetaSettings, meta_settings,
META, SETTINGS, GObject)
......@@ -66,6 +72,8 @@ void meta_settings_get_xwayland_grab_patterns (MetaSettings *settings,
GPtrArray **whitelist_patterns,
GPtrArray **blacklist_patterns);
MetaX11ScaleMode meta_settings_get_x11_scale_mode (MetaSettings *settings);
gboolean meta_settings_are_xwayland_grabs_allowed (MetaSettings *settings);
#endif /* META_SETTINGS_PRIVATE_H */
......@@ -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;
......@@ -68,6 +70,8 @@ struct _MetaSettings
gboolean xwayland_allow_grabs;
GPtrArray *xwayland_grab_whitelist_patterns;
GPtrArray *xwayland_grab_blacklist_patterns;
MetaX11ScaleMode x11_scale_mode;
};
G_DEFINE_TYPE (MetaSettings, meta_settings, G_TYPE_OBJECT)
......@@ -77,14 +81,33 @@ 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 () &&
(settings->experimental_features &
META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING))
{
float scale = 1;
if (monitor_manager &&
settings->x11_scale_mode == META_X11_SCALE_MODE_UI_DOWN)
scale =
ceilf (meta_monitor_manager_get_maximum_crtc_scale (monitor_manager));
return scale;
}
else if (monitor_manager)
{
MetaLogicalMonitor *primary_logical_monitor;
return (int) meta_logical_monitor_get_scale (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 1;
}
static gboolean
......@@ -92,9 +115,7 @@ update_ui_scaling_factor (MetaSettings *settings)
{
int ui_scaling_factor;
if (meta_is_stage_views_scaled () ||
meta_settings_is_experimental_feature_enabled (settings,
META_EXPERIMENTAL_FEATURE_X11_RANDR_FRACTIONAL_SCALING))
if (meta_is_stage_views_scaled ())
ui_scaling_factor = 1;
else
ui_scaling_factor = calculate_ui_scaling_factor (settings);
......@@ -396,6 +417,25 @@ wayland_settings_changed (GSettings *wayland_settings,
}
}
static void
update_x11_scale_mode (MetaSettings *settings)
{
settings->x11_scale_mode =
g_settings_get_enum (settings->x11_settings, "fractional-scale-mode");
}
static void
x11_settings_changed (GSettings *wayland_settings,
gchar *key,
MetaSettings *settings)
{
if (g_str_equal (key, "fractional-scale-mode"))
{
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 **whitelist_patterns,
......@@ -411,6 +451,12 @@ gboolean
return (settings->xwayland_allow_grabs);
}
MetaX11ScaleMode
meta_settings_get_x11_scale_mode (MetaSettings *settings)
{
return settings->x11_scale_mode;
}
MetaSettings *
meta_settings_new (MetaBackend *backend)
{
......@@ -430,6 +476,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_whitelist_patterns,
g_ptr_array_unref);
g_clear_pointer (&settings->xwayland_grab_blacklist_patterns,
......@@ -453,6 +500,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",
......@@ -464,6 +515,7 @@ meta_settings_init (MetaSettings *settings)
update_experimental_features (settings);
update_xwayland_grab_access_rules (settings);
update_xwayland_allow_grabs (settings);
update_x11_scale_mode (settings);
}
static void
......@@ -518,6 +570,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),
......
......@@ -495,6 +495,7 @@ get_monitor_scale_constraints_per_layout_mode (MetaLogicalMonitorLayoutMode layo
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;
......
......@@ -92,6 +92,59 @@ 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 gboolean
meta_gpu_xrandr_read_current (MetaGpu *gpu,
GError **error)
......@@ -111,6 +164,7 @@ meta_gpu_xrandr_read_current (MetaGpu *gpu,
GList *modes = NULL;
GList *crtcs = NULL;
gboolean has_transform;
int dpi_scale = 1;
if (gpu_xrandr->resources)
XRRFreeScreenResources (gpu_xrandr->resources);
......@@ -163,6 +217,12 @@ meta_gpu_xrandr_read_current (MetaGpu *gpu,
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;
......@@ -180,6 +240,7 @@ meta_gpu_xrandr_read_current (MetaGpu *gpu,
crtc = meta_create_xrandr_crtc (gpu_xrandr,
xrandr_crtc, crtc_id, resources,
transform_attributes);
crtc->scale *= dpi_scale;
XFree (transform_attributes);
XRRFreeCrtcInfo (xrandr_crtc);
......
......@@ -109,6 +109,12 @@ meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *manager_xran
return manager_xrandr->xdisplay;
}
uint32_t
meta_monitor_manager_xrandr_get_config_timestamp (MetaMonitorManagerXrandr *manager_xrandr)
{
return manager_xrandr->last_xrandr_set_timestamp;
}
static GBytes *
meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager,
MetaOutput *output)
......@@ -441,9 +447,13 @@ apply_crtc_assignments (MetaMonitorManager *manager,
unsigned int n_outputs)
{
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);
unsigned i, valid_crtcs;
GList *l;
int width, height;
float max_scale;
float avg_screen_scale;
gboolean have_scaling;
......@@ -452,33 +462,52 @@ apply_crtc_assignments (MetaMonitorManager *manager,
have_scaling = meta_monitor_manager_get_capabilities (manager) &
META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING;
/* First compute the new size of the screen (framebuffer) */
valid_crtcs = 0;
max_scale = 1.0f;
for (i = 0; i < n_crtcs; i++)
{
MetaCrtcInfo *crtc_info = crtcs[i];
if (crtc_info->mode == NULL)
continue;
valid_crtcs++;
max_scale = MAX (max_scale, crtc_info->scale);
}
/* Compute the new size of the screen (framebuffer) */
width = 0; height = 0;
avg_screen_scale = 0;
valid_crtcs = 0;
for (i = 0; i < n_crtcs; i++)
{
MetaCrtcInfo *crtc_info = crtcs[i];
MetaCrtc *crtc = crtc_info->crtc;
float scale = 1.0f;
crtc->is_dirty = TRUE;
if (crtc_info->mode == NULL)
continue;
if (have_scaling && scale_mode == META_X11_SCALE_MODE_UI_DOWN)
scale = ceilf (max_scale) / crtc_info->scale;
if (meta_monitor_transform_is_rotated (crtc_info->transform))
{
width = MAX (width, crtc_info->x + crtc_info->mode->height);
height = MAX (height, crtc_info->y + crtc_info->mode->width);
width = MAX (width, crtc_info->x +
roundf (crtc_info->mode->height * scale));
height = MAX (height, crtc_info->y +
roundf (crtc_info->mode->width * scale));
}
else
{
width = MAX (width, crtc_info->x + crtc_info->mode->width);
height = MAX (height, crtc_info->y + crtc_info->mode->height);
width = MAX (width, crtc_info->x +
roundf (crtc_info->mode->width * scale));
height = MAX (height, crtc_info->y +
roundf (crtc_info->mode->height * scale));
}
valid_crtcs++;
avg_screen_scale += (crtc_info->scale - avg_screen_scale) /
(float) valid_crtcs;
avg_screen_scale += crtc_info->scale / (float) valid_crtcs;
}
/* Second disable all newly disabled CRTCs, or CRTCs that in the previous
......@@ -563,13 +592,17 @@ apply_crtc_assignments (MetaMonitorManager *manager,
float scale = 1.0f;
mode = crtc_info->mode;
scale = crtc_info->scale;
n_output_ids = crtc_info->outputs->len;
output_ids = g_new (xcb_randr_output_t, n_output_ids);
if (have_scaling)
scale = crtc_info->scale;
{
scale = crtc_info->scale;
if (scale_mode == META_X11_SCALE_MODE_UI_DOWN)
scale /= ceilf (max_scale);
}
for (j = 0; j < n_output_ids; j++)
{
......@@ -593,6 +626,8 @@ apply_crtc_assignments (MetaMonitorManager *manager,
meta_warning ("Scalig CRTC %d at %f failed\n",
(unsigned)crtc->crtc_id, scale);
}
else if (scale_mode == META_X11_SCALE_MODE_UI_DOWN)
scale = crtc_info->scale;
}
rotation = meta_monitor_transform_to_xrandr (crtc_info->transform);
......@@ -691,25 +726,35 @@ meta_monitor_manager_xrandr_update_screen_size_derived (MetaMonitorManager *mana
{
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 = meta_gpu_get_crtcs (manager_xrandr->gpu); l; l = l->next)
{
float scale;
float scale = 1.0f;
MetaCrtc *crtc = l->data;
if (crtc->current_mode == NULL)
continue;
/* When scaling up we should not reduce the screen size, or X will fail
* miserabily, while we must do it when scaling down, in order to increase
* the available screen area we can use. */
scale = crtc->scale > 1.0f ? crtc->scale : 1.0f;
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->scale > 1.0f ? crtc->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
......@@ -770,12 +815,22 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *mana
(MetaOutputInfo **) output_infos->pdata,
output_infos->len))
{
MetaLogicalMonitorLayoutMode layout_mode =
meta_monitor_manager_get_default_layout_mode (manager);
apply_crtc_assignments (manager,
TRUE,
(MetaCrtcInfo **) crtc_infos->pdata,
crtc_infos->len,
(MetaOutputInfo **) output_infos->pdata,
output_infos->len);
if (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);
}
}
else
{
......@@ -1088,12 +1143,33 @@ 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;
meta_monitor_manager_on_hotplug (manager);
meta_settings_update_ui_scaling_factor (settings);
}
static MetaLogicalMonitorLayoutMode
meta_monitor_manager_xrandr_get_default_layout_mode (MetaMonitorManager *manager)
{
if (meta_monitor_manager_get_capabilities (manager) &
META_MONITOR_MANAGER_CAPABILITY_NATIVE_OUTPUT_SCALING)
return META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL;
{
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;
return META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL;
}
return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
}
......@@ -1104,10 +1180,11 @@ meta_monitor_manager_xrandr_constructed (GObject *object)
MetaMonitorManagerXrandr *manager_xrandr =
META_MONITOR_MANAGER_XRANDR (object);
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
MetaBackendX11 *backend =
META_BACKEND_X11 (meta_monitor_manager_get_backend (manager));
MetaBackend *backend = meta_monitor_manager_get_backend (manager);
MetaSettings *settings = meta_backend_get_settings (backend);