monitor-manager/xrandr: Use a single supported scales list for all

Under X11 we can only ever have the same scale configured on all
monitors. In order to use e.g. scale 2 when there is a HiDPI monitor
connected, we must not disallow it because there is a monitor that does
not support scale 2. Thus we must show the same scale for every monitor
and monitor mode, even though it might result in a bad experience.

Do this by iterating through all the monitors adding all supported
scales by the preferred mode, combining all the supported scales. This
supported scales list is then used for all monitor and modes no matter
what.

https://bugzilla.gnome.org/show_bug.cgi?id=788901
This commit is contained in:
Jonas Ådahl 2017-10-13 14:34:19 +08:00
parent 2e99963087
commit 1a78557e0b

View File

@ -74,6 +74,9 @@ struct _MetaMonitorManagerXrandr
#ifdef HAVE_XRANDR15 #ifdef HAVE_XRANDR15
GHashTable *tiled_monitor_atoms; GHashTable *tiled_monitor_atoms;
#endif /* HAVE_XRANDR15 */ #endif /* HAVE_XRANDR15 */
float *supported_scales;
int n_supported_scales;
}; };
struct _MetaMonitorManagerXrandrClass struct _MetaMonitorManagerXrandrClass
@ -546,6 +549,17 @@ meta_monitor_manager_xrandr_ensure_initial_config (MetaMonitorManager *manager)
meta_monitor_manager_update_logical_state_derived (manager, config); meta_monitor_manager_update_logical_state_derived (manager, config);
} }
static void
meta_monitor_manager_xrandr_rebuild_derived (MetaMonitorManager *manager,
MetaMonitorsConfig *config)
{
MetaMonitorManagerXrandr *manager_xrandr =
META_MONITOR_MANAGER_XRANDR (manager);
g_clear_pointer (&manager_xrandr->supported_scales, g_free);
meta_monitor_manager_rebuild_derived (manager, config);
}
static gboolean static gboolean
meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *manager, meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *manager,
MetaMonitorsConfig *config, MetaMonitorsConfig *config,
@ -557,7 +571,7 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *mana
if (!config) if (!config)
{ {
meta_monitor_manager_rebuild_derived (manager, NULL); meta_monitor_manager_xrandr_rebuild_derived (manager, NULL);
return TRUE; return TRUE;
} }
@ -591,7 +605,7 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *mana
} }
else else
{ {
meta_monitor_manager_rebuild_derived (manager, config); meta_monitor_manager_xrandr_rebuild_derived (manager, config);
} }
} }
@ -832,6 +846,76 @@ meta_monitor_manager_xrandr_calculate_monitor_mode_scale (MetaMonitorManager *ma
return meta_monitor_calculate_mode_scale (monitor, monitor_mode); return meta_monitor_calculate_mode_scale (monitor, monitor_mode);
} }
static void
add_supported_scale (GArray *supported_scales,
float scale)
{
unsigned int i;
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 (f < 0)
return -1;
if (f > 0)
return 1;
return 0;
}
static void
ensure_supported_monitor_scales (MetaMonitorManager *manager)
{
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);
}
manager_xrandr->supported_scales = (float *) supported_scales->data;
manager_xrandr->n_supported_scales = supported_scales->len;
g_array_free (supported_scales, FALSE);
}
static float * static float *
meta_monitor_manager_xrandr_calculate_supported_scales (MetaMonitorManager *manager, meta_monitor_manager_xrandr_calculate_supported_scales (MetaMonitorManager *manager,
MetaLogicalMonitorLayoutMode layout_mode, MetaLogicalMonitorLayoutMode layout_mode,
@ -839,12 +923,14 @@ meta_monitor_manager_xrandr_calculate_supported_scales (MetaMonitorManager
MetaMonitorMode *monitor_mode, MetaMonitorMode *monitor_mode,
int *n_supported_scales) int *n_supported_scales)
{ {
MetaMonitorScalesConstraint constraints; MetaMonitorManagerXrandr *manager_xrandr =
META_MONITOR_MANAGER_XRANDR (manager);
constraints = META_MONITOR_SCALES_CONSTRAINT_NO_FRAC; ensure_supported_monitor_scales (manager);
return meta_monitor_calculate_supported_scales (monitor, monitor_mode,
constraints, *n_supported_scales = manager_xrandr->n_supported_scales;
n_supported_scales); return g_memdup (manager_xrandr->supported_scales,
manager_xrandr->n_supported_scales * sizeof (float));
} }
static MetaMonitorManagerCapability static MetaMonitorManagerCapability
@ -929,8 +1015,8 @@ meta_monitor_manager_xrandr_finalize (GObject *object)
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (object); MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (object);
g_clear_object (&manager_xrandr->gpu); g_clear_object (&manager_xrandr->gpu);
g_hash_table_destroy (manager_xrandr->tiled_monitor_atoms); g_hash_table_destroy (manager_xrandr->tiled_monitor_atoms);
g_free (manager_xrandr->supported_scales);
G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object); G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object);
} }
@ -1014,7 +1100,7 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
config = NULL; config = NULL;
} }
meta_monitor_manager_rebuild_derived (manager, config); meta_monitor_manager_xrandr_rebuild_derived (manager, config);
} }
return TRUE; return TRUE;