display-config: Filter invalid modes and scales when setting minimum size
In the front-end we define a minimum size and then we check every time we iterate through resolutions or scales if such mode is valid. Since the configuration won't change, we can just filter the invalid values once when the minimum allowed size is set, so that we can be sure that the returned scales list is always matching the ones appliable for the current mode. The only edge case is when using a cloned configuration, as in this case the values need to be applied to all the monitors. However, since we already return a reffed GArray we can just create a temporary one in this case where unappliable scales are skipped. As per this we can just use around the scales array length as the number of visible buttons.
This commit is contained in:
parent
a3392176a9
commit
266622e99e
2 changed files with 105 additions and 39 deletions
|
@ -46,6 +46,7 @@ typedef enum _CcDisplayModeFlags
|
||||||
struct _CcDisplayModeDBus
|
struct _CcDisplayModeDBus
|
||||||
{
|
{
|
||||||
CcDisplayMode parent_instance;
|
CcDisplayMode parent_instance;
|
||||||
|
CcDisplayMonitorDBus *monitor;
|
||||||
|
|
||||||
char *id;
|
char *id;
|
||||||
int width;
|
int width;
|
||||||
|
@ -87,13 +88,7 @@ cc_display_mode_dbus_get_resolution (CcDisplayMode *pself,
|
||||||
*h = self->height;
|
*h = self->height;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GArray *
|
static GArray * cc_display_mode_dbus_get_supported_scales (CcDisplayMode *pself);
|
||||||
cc_display_mode_dbus_get_supported_scales (CcDisplayMode *pself)
|
|
||||||
{
|
|
||||||
CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself);
|
|
||||||
|
|
||||||
return g_array_ref (self->supported_scales);
|
|
||||||
}
|
|
||||||
|
|
||||||
static double
|
static double
|
||||||
cc_display_mode_dbus_get_preferred_scale (CcDisplayMode *pself)
|
cc_display_mode_dbus_get_preferred_scale (CcDisplayMode *pself)
|
||||||
|
@ -179,7 +174,8 @@ cc_display_mode_dbus_class_init (CcDisplayModeDBusClass *klass)
|
||||||
}
|
}
|
||||||
|
|
||||||
static CcDisplayModeDBus *
|
static CcDisplayModeDBus *
|
||||||
cc_display_mode_dbus_new (GVariant *variant)
|
cc_display_mode_dbus_new (CcDisplayMonitorDBus *monitor,
|
||||||
|
GVariant *variant)
|
||||||
{
|
{
|
||||||
double d;
|
double d;
|
||||||
g_autoptr(GVariantIter) scales_iter = NULL;
|
g_autoptr(GVariantIter) scales_iter = NULL;
|
||||||
|
@ -189,6 +185,8 @@ cc_display_mode_dbus_new (GVariant *variant)
|
||||||
gboolean is_interlaced;
|
gboolean is_interlaced;
|
||||||
CcDisplayModeDBus *self = g_object_new (CC_TYPE_DISPLAY_MODE_DBUS, NULL);
|
CcDisplayModeDBus *self = g_object_new (CC_TYPE_DISPLAY_MODE_DBUS, NULL);
|
||||||
|
|
||||||
|
self->monitor = monitor;
|
||||||
|
|
||||||
g_variant_get (variant, "(" MODE_BASE_FORMAT "@a{sv})",
|
g_variant_get (variant, "(" MODE_BASE_FORMAT "@a{sv})",
|
||||||
&self->id,
|
&self->id,
|
||||||
&self->width,
|
&self->width,
|
||||||
|
@ -732,8 +730,7 @@ cc_display_monitor_dbus_finalize (GObject *object)
|
||||||
g_free (self->product_serial);
|
g_free (self->product_serial);
|
||||||
g_free (self->display_name);
|
g_free (self->display_name);
|
||||||
|
|
||||||
g_list_foreach (self->modes, (GFunc) g_object_unref, NULL);
|
g_list_free_full (self->modes, g_object_unref);
|
||||||
g_clear_pointer (&self->modes, g_list_free);
|
|
||||||
|
|
||||||
if (self->logical_monitor)
|
if (self->logical_monitor)
|
||||||
{
|
{
|
||||||
|
@ -790,7 +787,7 @@ construct_modes (CcDisplayMonitorDBus *self,
|
||||||
if (!g_variant_iter_next (modes, "@"MODE_FORMAT, &variant))
|
if (!g_variant_iter_next (modes, "@"MODE_FORMAT, &variant))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
mode = cc_display_mode_dbus_new (variant);
|
mode = cc_display_mode_dbus_new (self, variant);
|
||||||
self->modes = g_list_prepend (self->modes, mode);
|
self->modes = g_list_prepend (self->modes, mode);
|
||||||
|
|
||||||
if (mode->flags & MODE_PREFERRED)
|
if (mode->flags & MODE_PREFERRED)
|
||||||
|
@ -1210,23 +1207,30 @@ cc_display_config_dbus_is_layout_logical (CcDisplayConfig *pself)
|
||||||
return self->layout_mode == CC_DISPLAY_LAYOUT_MODE_LOGICAL;
|
return self->layout_mode == CC_DISPLAY_LAYOUT_MODE_LOGICAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
is_scale_allowed_by_active_monitors (CcDisplayConfigDBus *self,
|
||||||
|
CcDisplayMode *mode,
|
||||||
|
double scale);
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
is_scaled_mode_allowed (CcDisplayConfigDBus *self,
|
is_scaled_mode_allowed (CcDisplayConfigDBus *self,
|
||||||
CcDisplayMode *pmode,
|
CcDisplayModeDBus *mode,
|
||||||
double scale)
|
double scale)
|
||||||
{
|
{
|
||||||
gint width, height;
|
gint width, height;
|
||||||
CcDisplayModeDBus *mode = CC_DISPLAY_MODE_DBUS (pmode);
|
|
||||||
|
|
||||||
if (!cc_display_mode_dbus_is_supported_scale (pmode, scale))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* Do the math as if the monitor is always in landscape mode. */
|
/* Do the math as if the monitor is always in landscape mode. */
|
||||||
width = round (mode->width / scale);
|
width = round (mode->width / scale);
|
||||||
height = round (mode->height / scale);
|
height = round (mode->height / scale);
|
||||||
|
|
||||||
return (MAX (width, height) >= self->min_width &&
|
if (MAX (width, height) < self->min_width ||
|
||||||
MIN (width, height) >= self->min_height);
|
MIN (width, height) < self->min_height)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!self->global_scale_required)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return is_scale_allowed_by_active_monitors (self, CC_DISPLAY_MODE (mode), scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -1243,13 +1247,85 @@ is_scale_allowed_by_active_monitors (CcDisplayConfigDBus *self,
|
||||||
if (!cc_display_monitor_is_active (CC_DISPLAY_MONITOR (m)))
|
if (!cc_display_monitor_is_active (CC_DISPLAY_MONITOR (m)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!is_scaled_mode_allowed (self, mode, scale))
|
if (!cc_display_mode_dbus_is_supported_scale (mode, scale))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GArray *
|
||||||
|
cc_display_mode_dbus_get_supported_scales (CcDisplayMode *pself)
|
||||||
|
{
|
||||||
|
CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself);
|
||||||
|
CcDisplayConfig *config = CC_DISPLAY_CONFIG (self->monitor->config);
|
||||||
|
|
||||||
|
if (cc_display_config_is_cloning (config))
|
||||||
|
{
|
||||||
|
GArray *scales = g_array_copy (self->supported_scales);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = scales->len - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
double scale = g_array_index (scales, double, i);
|
||||||
|
|
||||||
|
if (!is_scale_allowed_by_active_monitors (self->monitor->config,
|
||||||
|
pself, scale))
|
||||||
|
g_array_remove_index (scales, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_steal_pointer (&scales);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_array_ref (self->supported_scales);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
filter_out_invalid_scaled_modes (CcDisplayConfigDBus *self)
|
||||||
|
{
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
for (l = self->monitors; l; l = l->next)
|
||||||
|
{
|
||||||
|
CcDisplayMonitorDBus *monitor = l->data;
|
||||||
|
GList *ll = monitor->modes;
|
||||||
|
|
||||||
|
while (ll != NULL)
|
||||||
|
{
|
||||||
|
CcDisplayModeDBus *mode = ll->data;
|
||||||
|
GList *current = ll;
|
||||||
|
double current_scale = -1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ll = ll->next;
|
||||||
|
|
||||||
|
if (monitor->current_mode != CC_DISPLAY_MODE (mode) &&
|
||||||
|
monitor->preferred_mode != CC_DISPLAY_MODE (mode) &&
|
||||||
|
!is_scaled_mode_allowed (self, mode, 1.0))
|
||||||
|
{
|
||||||
|
g_clear_object (&mode);
|
||||||
|
monitor->modes = g_list_delete_link (monitor->modes, current);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (monitor->current_mode == CC_DISPLAY_MODE (mode))
|
||||||
|
current_scale = cc_display_monitor_dbus_get_scale (CC_DISPLAY_MONITOR (monitor));
|
||||||
|
|
||||||
|
for (i = mode->supported_scales->len - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
float scale = g_array_index (mode->supported_scales, double, i);
|
||||||
|
|
||||||
|
if (!G_APPROX_VALUE (scale, current_scale, DBL_EPSILON) &&
|
||||||
|
!G_APPROX_VALUE (scale, mode->preferred_scale, DBL_EPSILON) &&
|
||||||
|
!is_scaled_mode_allowed (self, mode, scale))
|
||||||
|
{
|
||||||
|
g_array_remove_index (mode->supported_scales, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cc_display_config_dbus_set_minimum_size (CcDisplayConfig *pself,
|
cc_display_config_dbus_set_minimum_size (CcDisplayConfig *pself,
|
||||||
int width,
|
int width,
|
||||||
|
@ -1258,9 +1334,14 @@ cc_display_config_dbus_set_minimum_size (CcDisplayConfig *pself,
|
||||||
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself);
|
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself);
|
||||||
|
|
||||||
g_assert (width >= 0 && height >= 0);
|
g_assert (width >= 0 && height >= 0);
|
||||||
|
g_assert (((self->min_width == 0 && self->min_height == 0) ||
|
||||||
|
(self->min_width >= width && self->min_height >= height)) &&
|
||||||
|
"Minimum size can't be set again to higher values");
|
||||||
|
|
||||||
self->min_width = width;
|
self->min_width = width;
|
||||||
self->min_height = height;
|
self->min_height = height;
|
||||||
|
|
||||||
|
filter_out_invalid_scaled_modes (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -1270,10 +1351,10 @@ cc_display_config_dbus_is_scaled_mode_valid (CcDisplayConfig *pself,
|
||||||
{
|
{
|
||||||
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself);
|
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself);
|
||||||
|
|
||||||
if (self->global_scale_required || cc_display_config_is_cloning (pself))
|
if (cc_display_config_is_cloning (pself))
|
||||||
return is_scale_allowed_by_active_monitors (self, mode, scale);
|
return is_scale_allowed_by_active_monitors (self, mode, scale);
|
||||||
|
|
||||||
return is_scaled_mode_allowed (self, mode, scale);
|
return cc_display_mode_dbus_is_supported_scale (mode, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -1520,6 +1601,7 @@ cc_display_config_dbus_constructed (GObject *object)
|
||||||
}
|
}
|
||||||
|
|
||||||
construct_monitors (self, monitors, logical_monitors);
|
construct_monitors (self, monitors, logical_monitors);
|
||||||
|
filter_out_invalid_scaled_modes (self);
|
||||||
|
|
||||||
self->proxy = g_dbus_proxy_new_sync (self->connection,
|
self->proxy = g_dbus_proxy_new_sync (self->connection,
|
||||||
G_DBUS_PROXY_FLAGS_NONE,
|
G_DBUS_PROXY_FLAGS_NONE,
|
||||||
|
|
|
@ -233,7 +233,6 @@ cc_display_settings_rebuild_ui (CcDisplaySettings *self)
|
||||||
gint width, height;
|
gint width, height;
|
||||||
CcDisplayMode *current_mode;
|
CcDisplayMode *current_mode;
|
||||||
GtkRadioButton *group = NULL;
|
GtkRadioButton *group = NULL;
|
||||||
gint buttons = 0;
|
|
||||||
g_autoptr(GArray) scales = NULL;
|
g_autoptr(GArray) scales = NULL;
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
|
@ -359,10 +358,6 @@ cc_display_settings_rebuild_ui (CcDisplaySettings *self)
|
||||||
gint w, h;
|
gint w, h;
|
||||||
CcDisplayMode *mode = CC_DISPLAY_MODE (item->data);
|
CcDisplayMode *mode = CC_DISPLAY_MODE (item->data);
|
||||||
|
|
||||||
/* Exclude unusable low resolutions */
|
|
||||||
if (!cc_display_config_is_scaled_mode_valid (self->config, mode, 1.0))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
cc_display_mode_get_resolution (mode, &w, &h);
|
cc_display_mode_get_resolution (mode, &w, &h);
|
||||||
|
|
||||||
/* Find the appropriate insertion point. */
|
/* Find the appropriate insertion point. */
|
||||||
|
@ -394,19 +389,12 @@ cc_display_settings_rebuild_ui (CcDisplaySettings *self)
|
||||||
/* Scale row is usually shown. */
|
/* Scale row is usually shown. */
|
||||||
gtk_container_foreach (GTK_CONTAINER (self->scale_bbox), (GtkCallback) gtk_widget_destroy, NULL);
|
gtk_container_foreach (GTK_CONTAINER (self->scale_bbox), (GtkCallback) gtk_widget_destroy, NULL);
|
||||||
scales = cc_display_mode_get_supported_scales (current_mode);
|
scales = cc_display_mode_get_supported_scales (current_mode);
|
||||||
for (i = 0; i < scales->len; i++)
|
for (i = 0; i < MIN (MAX_SCALE_BUTTONS, scales->len); i++)
|
||||||
{
|
{
|
||||||
g_autofree gchar *scale_str = NULL;
|
g_autofree gchar *scale_str = NULL;
|
||||||
double scale = g_array_index (scales, double, i);
|
double scale = g_array_index (scales, double, i);
|
||||||
GtkWidget *scale_btn;
|
GtkWidget *scale_btn;
|
||||||
|
|
||||||
if (!cc_display_config_is_scaled_mode_valid (self->config,
|
|
||||||
current_mode,
|
|
||||||
scale) &&
|
|
||||||
!G_APPROX_VALUE (cc_display_monitor_get_scale (self->selected_output),
|
|
||||||
scale, DBL_EPSILON))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
scale_str = make_scale_string (scale);
|
scale_str = make_scale_string (scale);
|
||||||
|
|
||||||
scale_btn = gtk_radio_button_new_with_label_from_widget (group, scale_str);
|
scale_btn = gtk_radio_button_new_with_label_from_widget (group, scale_str);
|
||||||
|
@ -427,13 +415,9 @@ cc_display_settings_rebuild_ui (CcDisplaySettings *self)
|
||||||
if (G_APPROX_VALUE (cc_display_monitor_get_scale (self->selected_output),
|
if (G_APPROX_VALUE (cc_display_monitor_get_scale (self->selected_output),
|
||||||
scale, DBL_EPSILON))
|
scale, DBL_EPSILON))
|
||||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scale_btn), TRUE);
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scale_btn), TRUE);
|
||||||
|
|
||||||
buttons += 1;
|
|
||||||
if (buttons >= MAX_SCALE_BUTTONS)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_widget_set_visible (self->scale_row, buttons > 1);
|
gtk_widget_set_visible (self->scale_row, scales->len > 1);
|
||||||
|
|
||||||
gtk_widget_set_visible (self->underscanning_row,
|
gtk_widget_set_visible (self->underscanning_row,
|
||||||
cc_display_monitor_supports_underscanning (self->selected_output) &&
|
cc_display_monitor_supports_underscanning (self->selected_output) &&
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue