[gnome-control-center] display-settings: Show scaling values using a combo-box when more than buttons limit



commit 632cb3c907922d4449e5758d218612ad5d8735c6
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Sat May 29 21:37:33 2021 +0200

    display-settings: Show scaling values using a combo-box when more than buttons limit
    
    In case fractional scaling is enabled, depending on the resolution,
    mutter may advertise many fractional scaling values which are way more
    than MAX_SCALE_BUTTONS, making impossible to use higher fractional
    scaling values in high dpi setups.
    
    So, in case scaling is possible, show them as buttons if they fit the
    buttons limit, otherwise fallback to a combo box that is consistent with
    the rest of the UI and will allow to use any valid scaling value.

 panels/display/cc-display-settings.c  | 103 ++++++++++++++++++++++++++--------
 panels/display/cc-display-settings.ui |  11 +++-
 2 files changed, 89 insertions(+), 25 deletions(-)
---
diff --git a/panels/display/cc-display-settings.c b/panels/display/cc-display-settings.c
index a7bd8a219..1e53dc8f7 100644
--- a/panels/display/cc-display-settings.c
+++ b/panels/display/cc-display-settings.c
@@ -44,12 +44,14 @@ struct _CcDisplaySettings
   GListStore       *orientation_list;
   GListStore       *refresh_rate_list;
   GListStore       *resolution_list;
+  GListStore       *scale_list;
 
   GtkWidget        *orientation_row;
   GtkWidget        *refresh_rate_row;
   GtkWidget        *resolution_row;
   GtkWidget        *scale_bbox;
-  GtkWidget        *scale_row;
+  GtkWidget        *scale_buttons_row;
+  GtkWidget        *scale_combo_row;
   GtkWidget        *underscanning_row;
   GtkWidget        *underscanning_switch;
 };
@@ -243,7 +245,8 @@ cc_display_settings_rebuild_ui (CcDisplaySettings *self)
       gtk_widget_set_visible (self->orientation_row, FALSE);
       gtk_widget_set_visible (self->refresh_rate_row, FALSE);
       gtk_widget_set_visible (self->resolution_row, FALSE);
-      gtk_widget_set_visible (self->scale_row, FALSE);
+      gtk_widget_set_visible (self->scale_combo_row, FALSE);
+      gtk_widget_set_visible (self->scale_buttons_row, FALSE);
       gtk_widget_set_visible (self->underscanning_row, FALSE);
 
       return G_SOURCE_REMOVE;
@@ -252,6 +255,7 @@ cc_display_settings_rebuild_ui (CcDisplaySettings *self)
   g_object_freeze_notify ((GObject*) self->orientation_row);
   g_object_freeze_notify ((GObject*) self->refresh_rate_row);
   g_object_freeze_notify ((GObject*) self->resolution_row);
+  g_object_freeze_notify ((GObject*) self->scale_combo_row);
   g_object_freeze_notify ((GObject*) self->underscanning_switch);
 
   cc_display_monitor_get_geometry (self->selected_output, NULL, NULL, &width, &height);
@@ -388,36 +392,57 @@ cc_display_settings_rebuild_ui (CcDisplaySettings *self)
 
   /* Scale row is usually shown. */
   gtk_container_foreach (GTK_CONTAINER (self->scale_bbox), (GtkCallback) gtk_widget_destroy, NULL);
+  g_list_store_remove_all (self->scale_list);
+  gtk_widget_set_visible (self->scale_buttons_row, FALSE);
+  gtk_widget_set_visible (self->scale_combo_row, FALSE);
   scales = cc_display_mode_get_supported_scales (current_mode);
-  for (i = 0; i < MIN (MAX_SCALE_BUTTONS, scales->len); i++)
+  for (i = 0; i < scales->len; i++)
     {
       g_autofree gchar *scale_str = NULL;
       double scale = g_array_index (scales, double, i);
-      GtkWidget *scale_btn;
+      gboolean is_selected;
 
       scale_str = make_scale_string (scale);
+      is_selected = G_APPROX_VALUE (cc_display_monitor_get_scale (self->selected_output),
+                                    scale, DBL_EPSILON);
 
-      scale_btn = gtk_radio_button_new_with_label_from_widget (group, scale_str);
-      if (!group)
-        group = GTK_RADIO_BUTTON (scale_btn);
-      gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (scale_btn), FALSE);
-      g_object_set_data_full (G_OBJECT (scale_btn),
-                              "scale",
-                              g_memdup (&scale, sizeof (gdouble)),
-                              g_free);
-      gtk_widget_show (scale_btn);
-      gtk_container_add (GTK_CONTAINER (self->scale_bbox), scale_btn);
-      g_signal_connect_object (scale_btn,
-                               "notify::active",
-                               G_CALLBACK (on_scale_btn_active_changed_cb),
-                               self, 0);
-
-      if (G_APPROX_VALUE (cc_display_monitor_get_scale (self->selected_output),
-                          scale, DBL_EPSILON))
-        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scale_btn), TRUE);
+      if (scales->len > MAX_SCALE_BUTTONS)
+        {
+          g_autoptr(HdyValueObject) value_object = NULL;
+
+          value_object = hdy_value_object_new_collect (G_TYPE_STRING, scale_str);
+          g_list_store_append (self->scale_list, value_object);
+          g_object_set_data_full (G_OBJECT (value_object), "scale",
+                                  g_memdup (&scale, sizeof (double)), g_free);
+          if (is_selected)
+            hdy_combo_row_set_selected_index (HDY_COMBO_ROW (self->scale_combo_row),
+                                              g_list_model_get_n_items (G_LIST_MODEL (self->scale_list)) - 
1);
+        }
+      else
+        {
+          GtkWidget *scale_btn = gtk_radio_button_new_with_label_from_widget (group, scale_str);
+          g_object_set_data_full (G_OBJECT (scale_btn), "scale",
+                                  g_memdup (&scale, sizeof (double)), g_free);
+
+          if (!group)
+            group = GTK_RADIO_BUTTON (scale_btn);
+          gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (scale_btn), FALSE);
+          gtk_widget_show (scale_btn);
+          gtk_container_add (GTK_CONTAINER (self->scale_bbox), scale_btn);
+          g_signal_connect_object (scale_btn,
+                                   "notify::active",
+                                   G_CALLBACK (on_scale_btn_active_changed_cb),
+                                   self, 0);
+
+          if (is_selected)
+            gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scale_btn), TRUE);
+        }
     }
 
-  gtk_widget_set_visible (self->scale_row, scales->len > 1);
+  if (scales->len > MAX_SCALE_BUTTONS)
+    gtk_widget_set_visible (self->scale_combo_row, TRUE);
+  else
+    gtk_widget_set_visible (self->scale_buttons_row, scales->len > 1);
 
   gtk_widget_set_visible (self->underscanning_row,
                           cc_display_monitor_supports_underscanning (self->selected_output) &&
@@ -429,6 +454,7 @@ cc_display_settings_rebuild_ui (CcDisplaySettings *self)
   g_object_thaw_notify ((GObject*) self->orientation_row);
   g_object_thaw_notify ((GObject*) self->refresh_rate_row);
   g_object_thaw_notify ((GObject*) self->resolution_row);
+  g_object_thaw_notify ((GObject*) self->scale_combo_row);
   g_object_thaw_notify ((GObject*) self->underscanning_switch);
   self->updating = FALSE;
 
@@ -530,6 +556,27 @@ on_scale_btn_active_changed_cb (GtkWidget         *widget,
   g_signal_emit_by_name (G_OBJECT (self), "updated", self->selected_output);
 }
 
+static void
+on_scale_selection_changed_cb (GtkWidget         *widget,
+                               GParamSpec        *pspec,
+                               CcDisplaySettings *self)
+{
+  int idx;
+  double scale;
+  g_autoptr(HdyValueObject) obj = NULL;
+
+  if (self->updating)
+    return;
+
+  idx = hdy_combo_row_get_selected_index (HDY_COMBO_ROW (self->scale_combo_row));
+  obj = g_list_model_get_item (G_LIST_MODEL (self->scale_list), idx);
+  scale = *(gdouble*) g_object_get_data (G_OBJECT (obj), "scale");
+
+  cc_display_monitor_set_scale (self->selected_output, scale);
+
+  g_signal_emit_by_name (G_OBJECT (self), "updated", self->selected_output);
+}
+
 static void
 on_underscanning_switch_active_changed_cb (GtkWidget         *widget,
                                            GParamSpec        *pspec,
@@ -608,6 +655,7 @@ cc_display_settings_finalize (GObject *object)
   g_clear_object (&self->orientation_list);
   g_clear_object (&self->refresh_rate_list);
   g_clear_object (&self->resolution_list);
+  g_clear_object (&self->scale_list);
 
   if (self->idle_udpate_id)
     g_source_remove (self->idle_udpate_id);
@@ -660,13 +708,15 @@ cc_display_settings_class_init (CcDisplaySettingsClass *klass)
   gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, refresh_rate_row);
   gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, resolution_row);
   gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, scale_bbox);
-  gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, scale_row);
+  gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, scale_buttons_row);
+  gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, scale_combo_row);
   gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, underscanning_row);
   gtk_widget_class_bind_template_child (widget_class, CcDisplaySettings, underscanning_switch);
 
   gtk_widget_class_bind_template_callback (widget_class, on_orientation_selection_changed_cb);
   gtk_widget_class_bind_template_callback (widget_class, on_refresh_rate_selection_changed_cb);
   gtk_widget_class_bind_template_callback (widget_class, on_resolution_selection_changed_cb);
+  gtk_widget_class_bind_template_callback (widget_class, on_scale_selection_changed_cb);
   gtk_widget_class_bind_template_callback (widget_class, on_underscanning_switch_active_changed_cb);
 }
 
@@ -682,6 +732,7 @@ cc_display_settings_init (CcDisplaySettings *self)
   self->orientation_list = g_list_store_new (HDY_TYPE_VALUE_OBJECT);
   self->refresh_rate_list = g_list_store_new (CC_TYPE_DISPLAY_MODE);
   self->resolution_list = g_list_store_new (CC_TYPE_DISPLAY_MODE);
+  self->scale_list = g_list_store_new (HDY_TYPE_VALUE_OBJECT);
 
   self->updating = TRUE;
 
@@ -697,6 +748,10 @@ cc_display_settings_init (CcDisplaySettings *self)
                                  G_LIST_MODEL (self->resolution_list),
                                  (HdyComboRowGetNameFunc) make_resolution_string,
                                  NULL, NULL);
+  hdy_combo_row_bind_name_model (HDY_COMBO_ROW (self->scale_combo_row),
+                                 G_LIST_MODEL (self->scale_list),
+                                 (HdyComboRowGetNameFunc) hdy_value_object_dup_string,
+                                 NULL, NULL);
 
   self->updating = FALSE;
 }
diff --git a/panels/display/cc-display-settings.ui b/panels/display/cc-display-settings.ui
index 7715ba394..647e6838f 100644
--- a/panels/display/cc-display-settings.ui
+++ b/panels/display/cc-display-settings.ui
@@ -52,7 +52,7 @@
       </object>
     </child>
     <child>
-      <object class="HdyActionRow" id="scale_row">
+      <object class="HdyActionRow" id="scale_buttons_row">
         <property name="width_request">100</property>
         <property name="visible">True</property>
         <property name="can_focus">True</property>
@@ -68,5 +68,14 @@
         </child>
       </object>
     </child>
+    <child>
+      <object class="HdyComboRow" id="scale_combo_row">
+        <property name="width_request">100</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="title" translatable="yes" context="display setting">Scale</property>
+        <signal name="notify::selected-index" handler="on_scale_selection_changed_cb" swapped="no"/>
+      </object>
+    </child>
   </template>
 </interface>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]