summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Berg <bberg@redhat.com>2020-10-22 16:04:10 +0200
committerBenjamin Berg <bberg@redhat.com>2020-10-22 16:04:10 +0200
commitf5b7948c56cfb7c75e2938a5407a08da04b91db7 (patch)
treeec96e8eb5978fd9bcdec9b15e0761652d35c1b1a
parent9f8fe32be3c1c18d6b88d396d9601f64362f7a8b (diff)
downloadgnome-control-center-benzea/fix-scale-after-mode-switching.tar.gz
display: Try harder to select a good and working scalebenzea/fix-scale-after-mode-switching
When swicthing configurations, we should ensure that the selected scale is valid. This is complicated by the fact that it depends on other factors whether we need a single global scale or not. Try to retain the scale that monitors have if possible. If that does not work, try to use the old scale of the primary monitor everywhere. This should result in a good behaviour in most situations. Co-authored-by: Stéphane Travostino <steph@combo.cc> Fixes: #1038
-rw-r--r--panels/display/cc-display-panel.c59
1 files changed, 57 insertions, 2 deletions
diff --git a/panels/display/cc-display-panel.c b/panels/display/cc-display-panel.c
index 949034442..d72bf6d18 100644
--- a/panels/display/cc-display-panel.c
+++ b/panels/display/cc-display-panel.c
@@ -172,6 +172,8 @@ config_ensure_of_type (CcDisplayPanel *panel, CcDisplayConfigType type)
{
CcDisplayConfigType current_type = config_get_current_type (panel);
GList *outputs, *l;
+ CcDisplayMonitor *current_primary = NULL;
+ gdouble old_primary_scale = -1;
/* Do not do anything if the current detected configuration type is
* identitcal to what we expect. */
@@ -181,6 +183,17 @@ config_ensure_of_type (CcDisplayPanel *panel, CcDisplayConfigType type)
reset_current_config (panel);
outputs = cc_display_config_get_ui_sorted_monitors (panel->current_config);
+ for (l = outputs; l; l = l->next)
+ {
+ CcDisplayMonitor *output = l->data;
+
+ if (cc_display_monitor_is_primary (output))
+ {
+ current_primary = output;
+ old_primary_scale = cc_display_monitor_get_scale (current_primary);
+ break;
+ }
+ }
switch (type)
{
@@ -216,15 +229,41 @@ config_ensure_of_type (CcDisplayPanel *panel, CcDisplayConfigType type)
for (l = outputs; l; l = l->next)
{
CcDisplayMonitor *output = l->data;
+ gdouble scale;
+ CcDisplayMode *mode;
+
+ mode = cc_display_monitor_get_preferred_mode (output);
+ /* If the monitor was active, try using the current scale, otherwise
+ * try picking the preferred scale. */
+ if (cc_display_monitor_is_active (output))
+ scale = cc_display_monitor_get_scale (output);
+ else
+ scale = cc_display_mode_get_preferred_scale (mode);
+
+ /* If we cannot use the current/preferred scale, try to fall back to
+ * the previously scale of the primary monitor instead.
+ * This is not guaranteed to result in a valid configuration! */
+ if (!cc_display_config_is_scaled_mode_valid (panel->current_config,
+ mode,
+ scale))
+ {
+ if (current_primary &&
+ cc_display_config_is_scaled_mode_valid (panel->current_config,
+ mode,
+ old_primary_scale))
+ scale = old_primary_scale;
+ }
cc_display_monitor_set_active (output, cc_display_monitor_is_usable (output));
- cc_display_monitor_set_mode (output, cc_display_monitor_get_preferred_mode (output));
+ cc_display_monitor_set_mode (output, mode);
+ cc_display_monitor_set_scale (output, scale);
}
break;
case CC_DISPLAY_CONFIG_CLONE:
{
g_debug ("Creating new clone config");
+ gdouble scale;
GList *modes = cc_display_config_get_cloning_modes (panel->current_config);
gint bw, bh;
CcDisplayMode *best = NULL;
@@ -246,7 +285,23 @@ config_ensure_of_type (CcDisplayPanel *panel, CcDisplayConfigType type)
modes = modes->next;
}
- cc_display_config_set_mode_on_all_outputs (panel->current_config, best);
+
+ /* Take the preferred scale by default, */
+ scale = cc_display_mode_get_preferred_scale (best);
+ /* but prefer the old primary scale if that is valid. */
+ if (current_primary &&
+ cc_display_config_is_scaled_mode_valid (panel->current_config,
+ best,
+ old_primary_scale))
+ scale = old_primary_scale;
+
+ for (l = outputs; l; l = l->next)
+ {
+ CcDisplayMonitor *output = l->data;
+
+ cc_display_monitor_set_mode (output, best);
+ cc_display_monitor_set_scale (output, scale);
+ }
}
break;