summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Trevisan (Treviño) <mail@3v1n0.net>2017-06-07 20:36:17 +0800
committerMarco Trevisan (Treviño) <mail@3v1n0.net>2017-06-07 20:36:17 +0800
commit5689bb7f99a47790b08958929b4b06a21e8aecf9 (patch)
tree83faa08deb4fa7543d4fab8c94a416276e176beb
parent31c09339b636d28d424483c7c4cfcaaa9259cc42 (diff)
downloadgnome-control-center-fractional-scaling.tar.gz
Display: adapt display config to new Mutter interface with scaling per modefractional-scaling
New Mutter GetCurrentState now provides a list of available scales, we need to use these values in order to define an UI that shows them all.
-rw-r--r--panels/display/cc-display-config-dbus.c84
-rw-r--r--panels/display/cc-display-config-rr.c19
-rw-r--r--panels/display/cc-display-config.c12
-rw-r--r--panels/display/cc-display-config.h9
-rw-r--r--panels/display/cc-display-panel.c135
5 files changed, 165 insertions, 94 deletions
diff --git a/panels/display/cc-display-config-dbus.c b/panels/display/cc-display-config-dbus.c
index 29114ffce..08d08d48a 100644
--- a/panels/display/cc-display-config-dbus.c
+++ b/panels/display/cc-display-config-dbus.c
@@ -21,17 +21,17 @@
#include "cc-display-config-dbus.h"
-#define MODE_FORMAT "(iiddu)"
+#define MODE_FORMAT "(iiddadu)"
#define MODES_FORMAT "a" MODE_FORMAT
-
#define MONITOR_SPEC_FORMAT "(ssss)"
#define MONITOR_FORMAT "(" MONITOR_SPEC_FORMAT MODES_FORMAT "a{sv})"
#define MONITORS_FORMAT "a" MONITOR_FORMAT
-#define LOGICAL_MONITOR_FORMAT "(iiduba" MONITOR_SPEC_FORMAT "a{sv})"
+#define LOGICAL_MONITOR_MONITORS_FORMAT "a" MONITOR_SPEC_FORMAT
+#define LOGICAL_MONITOR_FORMAT "(iidub" LOGICAL_MONITOR_MONITORS_FORMAT "a{sv})"
#define LOGICAL_MONITORS_FORMAT "a" LOGICAL_MONITOR_FORMAT
-#define CURRENT_STATE_FORMAT "(u" MONITORS_FORMAT LOGICAL_MONITORS_FORMAT "ad" "a{sv})"
+#define CURRENT_STATE_FORMAT "(u" MONITORS_FORMAT LOGICAL_MONITORS_FORMAT "a{sv})"
typedef enum _CcDisplayModeFlags
{
@@ -47,6 +47,7 @@ struct _CcDisplayModeDBus
int height;
double refresh_rate;
double preferred_scale;
+ GArray *supported_scales;
guint32 flags;
};
@@ -80,6 +81,28 @@ cc_display_mode_dbus_get_resolution (CcDisplayMode *pself,
*h = self->height;
}
+static const double *
+cc_display_mode_dbus_get_supported_scales (CcDisplayMode *pself)
+{
+ CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself);
+
+ return (const double *) self->supported_scales->data;
+}
+
+static gboolean
+cc_display_mode_dbus_is_supported_scale (CcDisplayMode *pself,
+ double scale)
+{
+ CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself);
+
+ guint i;
+ for (i = 0; i < self->supported_scales->len; i++)
+ if (g_array_index (self->supported_scales, double, i) == scale)
+ return TRUE;
+ return FALSE;
+}
+
+
static gboolean
cc_display_mode_dbus_is_interlaced (CcDisplayMode *pself)
{
@@ -106,11 +129,16 @@ cc_display_mode_dbus_get_freq_f (CcDisplayMode *pself)
static void
cc_display_mode_dbus_init (CcDisplayModeDBus *self)
{
+ self->supported_scales = g_array_new (TRUE, TRUE, sizeof (double));
}
static void
cc_display_mode_dbus_finalize (GObject *object)
{
+ CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (object);
+
+ g_array_free (self->supported_scales, TRUE);
+
G_OBJECT_CLASS (cc_display_mode_dbus_parent_class)->finalize (object);
}
@@ -123,6 +151,7 @@ cc_display_mode_dbus_class_init (CcDisplayModeDBusClass *klass)
gobject_class->finalize = cc_display_mode_dbus_finalize;
parent_class->get_resolution = cc_display_mode_dbus_get_resolution;
+ parent_class->get_supported_scales = cc_display_mode_dbus_get_supported_scales;
parent_class->is_interlaced = cc_display_mode_dbus_is_interlaced;
parent_class->get_freq = cc_display_mode_dbus_get_freq;
parent_class->get_freq_f = cc_display_mode_dbus_get_freq_f;
@@ -131,6 +160,8 @@ cc_display_mode_dbus_class_init (CcDisplayModeDBusClass *klass)
static CcDisplayModeDBus *
cc_display_mode_dbus_new (GVariant *variant)
{
+ double d;
+ GVariantIter *scales_iter;
CcDisplayModeDBus *self = g_object_new (CC_TYPE_DISPLAY_MODE_DBUS, NULL);
g_variant_get (variant, MODE_FORMAT,
@@ -138,8 +169,14 @@ cc_display_mode_dbus_new (GVariant *variant)
&self->height,
&self->refresh_rate,
&self->preferred_scale,
+ &scales_iter,
&self->flags);
+ while (g_variant_iter_next (scales_iter, "d", &d))
+ g_array_append_val (self->supported_scales, d);
+
+ g_variant_iter_free (scales_iter);
+
return self;
}
@@ -262,9 +299,6 @@ static void
cc_display_config_dbus_ensure_gapless (CcDisplayConfigDBus *self);
static void
cc_display_config_dbus_make_linear (CcDisplayConfigDBus *self);
-static gboolean
-cc_display_config_dbus_is_supported_scale (CcDisplayConfigDBus *self,
- double scale);
static const char *
@@ -623,7 +657,10 @@ cc_display_monitor_dbus_set_scale (CcDisplayMonitor *pself,
{
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself);
- if (!cc_display_config_dbus_is_supported_scale (self->config, scale))
+ if (!self->current_mode)
+ return;
+
+ if (!cc_display_mode_dbus_is_supported_scale (self->current_mode, scale))
return;
if (!self->logical_monitor)
@@ -812,8 +849,6 @@ struct _CcDisplayConfigDBus
gboolean supports_changing_layout_mode;
CcDisplayLayoutMode layout_mode;
- GArray *supported_scales;
-
GList *monitors;
CcDisplayMonitorDBus *primary;
@@ -1115,14 +1150,6 @@ cc_display_config_dbus_apply (CcDisplayConfig *pself,
return config_apply (self, CC_DISPLAY_CONFIG_METHOD_PERSISTENT, error);
}
-static const double *
-cc_display_config_dbus_get_supported_scales (CcDisplayConfig *pself)
-{
- CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself);
-
- return (const double *) self->supported_scales->data;
-}
-
static gboolean
cc_display_config_dbus_is_layout_logical (CcDisplayConfig *pself)
{
@@ -1138,7 +1165,6 @@ cc_display_config_dbus_init (CcDisplayConfigDBus *self)
self->supports_mirroring = TRUE;
self->supports_changing_layout_mode = FALSE;
self->layout_mode = CC_DISPLAY_LAYOUT_MODE_LOGICAL;
- self->supported_scales = g_array_new (TRUE, TRUE, sizeof (double));
self->logical_monitors = g_hash_table_new (NULL, NULL);
}
@@ -1265,9 +1291,7 @@ cc_display_config_dbus_constructed (GObject *object)
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (object);
GVariantIter *monitors;
GVariantIter *logical_monitors;
- GVariantIter *scales;
GVariantIter *props;
- double d;
const char *s;
GVariant *v;
@@ -1276,12 +1300,8 @@ cc_display_config_dbus_constructed (GObject *object)
&self->serial,
&monitors,
&logical_monitors,
- &scales,
&props);
- while (g_variant_iter_next (scales, "d", &d))
- g_array_append_val (self->supported_scales, d);
-
while (g_variant_iter_next (props, "{&sv}", &s, &v))
{
if (g_str_equal (s, "supports-mirroring"))
@@ -1308,7 +1328,6 @@ cc_display_config_dbus_constructed (GObject *object)
g_variant_iter_free (monitors);
g_variant_iter_free (logical_monitors);
- g_variant_iter_free (scales);
g_variant_iter_free (props);
G_OBJECT_CLASS (cc_display_config_dbus_parent_class)->constructed (object);
@@ -1364,7 +1383,6 @@ cc_display_config_dbus_finalize (GObject *object)
g_clear_pointer (&self->state, g_variant_unref);
g_clear_object (&self->connection);
- g_array_free (self->supported_scales, TRUE);
g_list_foreach (self->monitors, (GFunc) g_object_unref, NULL);
g_clear_pointer (&self->monitors, g_list_free);
g_clear_pointer (&self->logical_monitors, g_hash_table_destroy);
@@ -1392,7 +1410,6 @@ cc_display_config_dbus_class_init (CcDisplayConfigDBusClass *klass)
parent_class->is_cloning = cc_display_config_dbus_is_cloning;
parent_class->set_cloning = cc_display_config_dbus_set_cloning;
parent_class->get_cloning_modes = cc_display_config_dbus_get_cloning_modes;
- parent_class->get_supported_scales = cc_display_config_dbus_get_supported_scales;
parent_class->is_layout_logical = cc_display_config_dbus_is_layout_logical;
pspec = g_param_spec_variant ("state",
@@ -1632,14 +1649,3 @@ cc_display_config_dbus_make_linear (CcDisplayConfigDBus *self)
g_list_free (logical_monitors);
}
-
-static gboolean
-cc_display_config_dbus_is_supported_scale (CcDisplayConfigDBus *self,
- double scale)
-{
- guint i;
- for (i = 0; i < self->supported_scales->len; i++)
- if (g_array_index (self->supported_scales, double, i) == scale)
- return TRUE;
- return FALSE;
-}
diff --git a/panels/display/cc-display-config-rr.c b/panels/display/cc-display-config-rr.c
index 805d44e67..1d979a1dd 100644
--- a/panels/display/cc-display-config-rr.c
+++ b/panels/display/cc-display-config-rr.c
@@ -46,6 +46,14 @@ cc_display_mode_rr_get_resolution (CcDisplayMode *pself,
*h = gnome_rr_mode_get_height (self->rr_mode);
}
+static double rr_supported_scales[] = { 1.0, 0.0 };
+
+static const double *
+cc_display_mode_rr_get_supported_scales (CcDisplayMode *pself)
+{
+ return rr_supported_scales;
+}
+
static gboolean
cc_display_mode_rr_is_interlaced (CcDisplayMode *pself)
{
@@ -90,6 +98,7 @@ cc_display_mode_rr_class_init (CcDisplayModeRRClass *klass)
gobject_class->finalize = cc_display_mode_rr_finalize;
parent_class->get_resolution = cc_display_mode_rr_get_resolution;
+ parent_class->get_supported_scales = cc_display_mode_rr_get_supported_scales;
parent_class->is_interlaced = cc_display_mode_rr_is_interlaced;
parent_class->get_freq = cc_display_mode_rr_get_freq;
parent_class->get_freq_f = cc_display_mode_rr_get_freq_f;
@@ -429,9 +438,6 @@ cc_display_monitor_rr_new (GnomeRROutput *output,
return CC_DISPLAY_MONITOR (self);
}
-
-static double rr_supported_scales[] = { 1.0, 0.0 };
-
struct _CcDisplayConfigRR
{
CcDisplayConfig parent_instance;
@@ -556,12 +562,6 @@ cc_display_config_rr_get_cloning_modes (CcDisplayConfig *pself)
return self->clone_modes;
}
-static const double *
-cc_display_config_rr_get_supported_scales (CcDisplayConfig *pself)
-{
- return rr_supported_scales;
-}
-
static gboolean
cc_display_config_rr_is_layout_logical (CcDisplayConfig *pself)
{
@@ -687,7 +687,6 @@ cc_display_config_rr_class_init (CcDisplayConfigRRClass *klass)
parent_class->is_cloning = cc_display_config_rr_is_cloning;
parent_class->set_cloning = cc_display_config_rr_set_cloning;
parent_class->get_cloning_modes = cc_display_config_rr_get_cloning_modes;
- parent_class->get_supported_scales = cc_display_config_rr_get_supported_scales;
parent_class->is_layout_logical = cc_display_config_rr_is_layout_logical;
pspec = g_param_spec_object ("gnome-rr-screen",
diff --git a/panels/display/cc-display-config.c b/panels/display/cc-display-config.c
index 237ff6b66..a70289738 100644
--- a/panels/display/cc-display-config.c
+++ b/panels/display/cc-display-config.c
@@ -39,6 +39,12 @@ cc_display_mode_get_resolution (CcDisplayMode *self, int *w, int *h)
return CC_DISPLAY_MODE_GET_CLASS (self)->get_resolution (self, w, h);
}
+const double *
+cc_display_mode_get_supported_scales (CcDisplayMode *self)
+{
+ return CC_DISPLAY_MODE_GET_CLASS (self)->get_supported_scales (self);
+}
+
gboolean
cc_display_mode_is_interlaced (CcDisplayMode *self)
{
@@ -272,12 +278,6 @@ cc_display_config_get_cloning_modes (CcDisplayConfig *self)
return CC_DISPLAY_CONFIG_GET_CLASS (self)->get_cloning_modes (self);
}
-const double *
-cc_display_config_get_supported_scales (CcDisplayConfig *self)
-{
- return CC_DISPLAY_CONFIG_GET_CLASS (self)->get_supported_scales (self);
-}
-
gboolean
cc_display_config_is_layout_logical (CcDisplayConfig *self)
{
diff --git a/panels/display/cc-display-config.h b/panels/display/cc-display-config.h
index b126a8a08..785f92a74 100644
--- a/panels/display/cc-display-config.h
+++ b/panels/display/cc-display-config.h
@@ -79,6 +79,7 @@ struct _CcDisplayModeClass
GObjectClass parent_class;
void (*get_resolution) (CcDisplayMode *self, int *w, int *h);
+ const double * (*get_supported_scales) (CcDisplayMode *self);
gboolean (*is_interlaced) (CcDisplayMode *self);
int (*get_freq) (CcDisplayMode *self);
double (*get_freq_f) (CcDisplayMode *self);
@@ -134,7 +135,6 @@ struct _CcDisplayConfigClass
gboolean (*is_cloning) (CcDisplayConfig *self);
void (*set_cloning) (CcDisplayConfig *self, gboolean clone);
GList * (*get_cloning_modes) (CcDisplayConfig *self);
- const double * (*get_supported_scales) (CcDisplayConfig *self);
gboolean (*is_layout_logical) (CcDisplayConfig *self);
};
@@ -147,7 +147,6 @@ gboolean cc_display_config_apply (CcDisplayConfig *config, GError **error);
gboolean cc_display_config_is_cloning (CcDisplayConfig *config);
void cc_display_config_set_cloning (CcDisplayConfig *config, gboolean clone);
GList *cc_display_config_get_cloning_modes (CcDisplayConfig *config);
-const double *cc_display_config_get_supported_scales (CcDisplayConfig *self);
gboolean cc_display_config_is_layout_logical (CcDisplayConfig *self);
const char * cc_display_monitor_get_display_name (CcDisplayMonitor *monitor);
@@ -186,11 +185,9 @@ void cc_display_monitor_set_position (CcDisplayMonitor *monitor,
int x, int y);
void cc_display_mode_get_resolution (CcDisplayMode *mode,
- int *width,
- int *height);
-void cc_display_mode_get_dimensions (CcDisplayMode *mode,
int *width,
- int *hegiht);
+ int *height);
+const double *cc_display_mode_get_supported_scales (CcDisplayMode *self);
gboolean cc_display_mode_is_interlaced (CcDisplayMode *mode);
int cc_display_mode_get_freq (CcDisplayMode *mode);
double cc_display_mode_get_freq_f (CcDisplayMode *mode);
diff --git a/panels/display/cc-display-panel.c b/panels/display/cc-display-panel.c
index 9847b94db..10ce278db 100644
--- a/panels/display/cc-display-panel.c
+++ b/panels/display/cc-display-panel.c
@@ -82,6 +82,7 @@ struct _CcDisplayPanelPrivate
GtkWidget *arrange_button;
GtkWidget *res_combo;
GtkWidget *freq_combo;
+ GtkWidget *scale_slider;
GHashTable *res_freqs;
GtkWidget *scaling_switch;
GtkWidget *rotate_left_button;
@@ -1698,6 +1699,72 @@ setup_frequency_combo_box (CcDisplayPanel *panel,
gtk_combo_box_set_active (GTK_COMBO_BOX (priv->freq_combo), 0);
}
+static guint
+n_supported_scales (CcDisplayMode *mode)
+{
+ const double *scales = cc_display_mode_get_supported_scales (mode);
+ guint n = 0;
+
+ while (scales[n] != 0.0)
+ n++;
+
+ return n;
+}
+
+static void
+setup_scaling_slider (CcDisplayPanel *panel,
+ CcDisplayMode *resolution_mode)
+{
+ CcDisplayPanelPrivate *priv = panel->priv;
+ guint i;
+ guint n;
+ const double *scales;
+
+ scales = cc_display_mode_get_supported_scales (resolution_mode);
+ n = n_supported_scales (resolution_mode);
+
+ if (n > 0)
+ {
+ GtkAdjustment *adj;
+ double current_scale;
+ int current_index = -1;
+
+ current_scale = cc_display_monitor_get_scale (priv->current_output);
+ adj = gtk_range_get_adjustment (GTK_RANGE (priv->scale_slider));
+
+ gtk_scale_clear_marks (GTK_SCALE (priv->scale_slider));
+
+ gtk_adjustment_set_step_increment (adj, 1);
+ gtk_adjustment_set_lower (adj, 0);
+ gtk_adjustment_set_upper (adj, n-1);
+ gtk_scale_set_digits (GTK_SCALE (priv->scale_slider), 0);
+
+ for (i = 0; i < n; ++i)
+ {
+ double rounded_scale = round (scales[i] * 10) / 10;
+ double integral;
+ double fractional = modf (rounded_scale, &integral);
+
+ if (scales[i] == current_scale || (current_index < 0 && scales[i] == 1.0))
+ current_index = i;
+
+ if (fractional != 0 && (fractional != 0.5 || integral > 0))
+ continue;
+
+ gchar *s = g_strdup_printf ("%.2lg×", scales[i]);
+ gtk_scale_add_mark (GTK_SCALE (priv->scale_slider), i, GTK_POS_TOP, s);
+ g_free (s);
+ }
+
+ gtk_widget_show (priv->scale_slider);
+ gtk_range_set_value (GTK_RANGE (priv->scale_slider), current_index);
+ }
+ else
+ {
+ gtk_widget_hide (priv->scale_slider);
+ }
+}
+
static void
free_mode_list (gpointer key,
gpointer value,
@@ -1782,6 +1849,7 @@ setup_resolution_combo_box (CcDisplayPanel *panel,
gtk_combo_box_set_active (GTK_COMBO_BOX (priv->res_combo), 0);
setup_frequency_combo_box (panel, current_mode);
+ setup_scaling_slider (panel, current_mode);
}
@@ -1988,6 +2056,7 @@ res_combo_changed (GtkComboBox *combo,
update_apply_button (panel);
setup_frequency_combo_box (panel, mode);
+ setup_scaling_slider (panel, mode);
}
}
@@ -2041,16 +2110,17 @@ underscan_switch_toggled (CcDisplayPanel *panel)
update_apply_button (panel);
}
-static guint
-n_supported_scales (CcDisplayConfig *config)
+static double
+scale_slider_get_selected_scale (CcDisplayPanel *panel)
{
- const double *scales = cc_display_config_get_supported_scales (config);
- guint n = 0;
+ CcDisplayPanelPrivate *priv = panel->priv;
+ CcDisplayMode *mode = cc_display_monitor_get_mode (priv->current_output);
+ const double *scales = cc_display_mode_get_supported_scales (mode);
+ int selected = gtk_range_get_value (GTK_RANGE (priv->scale_slider));
- while (scales[n] != 0.0)
- n++;
+ g_return_val_if_fail (selected < n_supported_scales (mode), 1.0);
- return n;
+ return scales[selected];
}
static void
@@ -2058,10 +2128,18 @@ scale_slider_changed (GtkRange *slider,
CcDisplayPanel *panel)
{
cc_display_monitor_set_scale (panel->priv->current_output,
- gtk_range_get_value (slider));
+ scale_slider_get_selected_scale (panel));
update_apply_button (panel);
}
+static char *
+scale_slider_format_value (GtkScale *slider,
+ double value,
+ CcDisplayPanel *panel)
+{
+ return g_strdup_printf ("%.3g", scale_slider_get_selected_scale (panel));
+}
+
static void
show_setup_dialog (CcDisplayPanel *panel)
{
@@ -2298,31 +2376,22 @@ show_setup_dialog (CcDisplayPanel *panel)
grid_pos++;
/* scale */
- if (n_supported_scales (priv->current_config) > 1)
- {
- GtkWidget *slider;
- const double *scales = cc_display_config_get_supported_scales (priv->current_config);
- guint n = n_supported_scales (priv->current_config);
- guint i = 0;
-
- slider = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL,
- scales[0], scales[n - 1],
- scales[1] - scales[0]);
- gtk_scale_set_draw_value (GTK_SCALE (slider), FALSE);
- gtk_scale_set_has_origin (GTK_SCALE (slider), FALSE);
- for (i = 0; i < n; i++)
- {
- gchar *s = g_strdup_printf ("%.1lg×", scales[i]);
- gtk_scale_add_mark (GTK_SCALE (slider), scales[i], GTK_POS_TOP, s);
- g_free (s);
- }
- gtk_range_set_value (GTK_RANGE (slider), cc_display_monitor_get_scale (priv->current_output));
- g_signal_connect (slider, "value-changed", G_CALLBACK (scale_slider_changed), panel);
-
- gtk_grid_attach (GTK_GRID (priv->config_grid), slider, 1, grid_pos, 1, 1);
- gtk_widget_set_halign (priv->freq_combo, GTK_ALIGN_CENTER);
- grid_pos++;
- }
+ priv->scale_slider = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, NULL);
+ gtk_widget_set_no_show_all (priv->scale_slider, TRUE);
+
+ g_signal_connect (priv->scale_slider, "format-value",
+ G_CALLBACK (scale_slider_format_value), panel);
+ g_signal_connect (priv->scale_slider, "value-changed",
+ G_CALLBACK (scale_slider_changed), panel);
+
+ gtk_scale_set_draw_value (GTK_SCALE (priv->scale_slider), TRUE);
+ gtk_range_set_round_digits (GTK_RANGE (priv->scale_slider), 2);
+ gtk_scale_set_value_pos (GTK_SCALE (priv->scale_slider), GTK_POS_BOTTOM);
+ gtk_scale_set_has_origin (GTK_SCALE (priv->scale_slider), FALSE);
+ gtk_grid_attach (GTK_GRID (priv->config_grid),
+ priv->scale_slider, 1, grid_pos, 1, 1);
+ gtk_widget_set_halign (priv->freq_combo, GTK_ALIGN_CENTER);
+ grid_pos++;
was_clone = clone = cc_display_config_is_cloning (priv->current_config);
primary = cc_display_monitor_is_primary (priv->current_output);