From aa5d787cdc2e16287511bab760e94e0b87d7b383 Mon Sep 17 00:00:00 2001 From: Felipe Borges Date: Wed, 6 Apr 2022 13:05:24 +0200 Subject: [PATCH] Fix printer setting preventing from scrolling media size list Upstream https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1704 https://gitlab.gnome.org/GNOME/gnome-control-center/-/merge_requests/1268 Related: rhbz#2063410 --- gnome-control-center.spec | 3 + printers-use-gtkdropdown.patch | 587 +++++++++++++++++++++++++++++++++ 2 files changed, 590 insertions(+) create mode 100644 printers-use-gtkdropdown.patch diff --git a/gnome-control-center.spec b/gnome-control-center.spec index e0a936c..2b165fa 100644 --- a/gnome-control-center.spec +++ b/gnome-control-center.spec @@ -29,6 +29,9 @@ Patch1: prettify-info.patch # https://bugzilla.redhat.com/show_bug.cgi?id=2064462 Patch2: 0001-online-accounts-Fix-goa-helper-on-X11.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=2063410 +Patch3: printers-use-gtkdropdown.patch + BuildRequires: chrpath BuildRequires: cups-devel BuildRequires: desktop-file-utils diff --git a/printers-use-gtkdropdown.patch b/printers-use-gtkdropdown.patch new file mode 100644 index 0000000..46035b6 --- /dev/null +++ b/printers-use-gtkdropdown.patch @@ -0,0 +1,587 @@ +From 7c5beecc97145962fa844f1d102b5a780ca55f7a Mon Sep 17 00:00:00 2001 +From: Brandon Nielsen +Date: Fri, 25 Mar 2022 20:54:47 -0500 +Subject: [PATCH] printers: Use a GtkDropDown in PpOptionsDialog + +PpPpdOptionWidget and PpIppOptionWidget both use combo boxes for +certain types of selections. With GTK4, combo boxes no longer +support scrolling[0], which in turn causes problems setting some +things in the PpOptionsDialog[1]. + +This replaces instances of GtkComboBox with GtkDropDown which do +support scrolling. This change was applied to both PpIppOptionWidget +and PpPpdOptionWidget as both are used in PpOptions dialog. + +Since the configuration values passed to CUPS can no longer be stored +in a GtkTreeModel alongside the displayed values, some logic changes +to update_widget_real in PpPpdOptionWidget to maintain the reference +to the ppd_option_t so the selected index can be mapped to the +configuration value. + +[0] - https://gitlab.gnome.org/GNOME/gtk/-/issues/3674 +[1] - https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1704 +--- + panels/printers/pp-ipp-option-widget.c | 165 ++++++++++-------------- + panels/printers/pp-ppd-option-widget.c | 167 +++++++++---------------- + 2 files changed, 125 insertions(+), 207 deletions(-) + +diff --git a/panels/printers/pp-ipp-option-widget.c b/panels/printers/pp-ipp-option-widget.c +index 8ab7ea06f..ea27ad737 100644 +--- a/panels/printers/pp-ipp-option-widget.c ++++ b/panels/printers/pp-ipp-option-widget.c +@@ -40,7 +40,7 @@ struct _PpIPPOptionWidget + + GtkWidget *switch_button; + GtkWidget *spin_button; +- GtkWidget *combo; ++ GtkWidget *dropdown; + + IPPAttribute *option_supported; + IPPAttribute *option_default; +@@ -85,8 +85,10 @@ ipp_choice_translate (const gchar *option, + for (i = 0; i < G_N_ELEMENTS (ipp_choice_translations); i++) + { + if (g_strcmp0 (ipp_choice_translations[i].keyword, option) == 0 && +- g_strcmp0 (ipp_choice_translations[i].choice, choice) == 0) +- return _(ipp_choice_translations[i].translation); ++ g_strcmp0 (ipp_choice_translations[i].choice, choice) == 0) ++ { ++ return _(ipp_choice_translations[i].translation); ++ } + } + + return choice; +@@ -158,101 +160,68 @@ pp_ipp_option_widget_new (IPPAttribute *attr_supported, + return (GtkWidget *) self; + } + +-enum { +- NAME_COLUMN, +- VALUE_COLUMN, +- N_COLUMNS +-}; +- + static GtkWidget * +-combo_box_new (void) ++dropdown_new (void) + { +- GtkCellRenderer *cell; +- g_autoptr(GtkListStore) store = NULL; +- GtkWidget *combo_box; +- +- combo_box = gtk_combo_box_new (); ++ GtkStringList *store = NULL; ++ GtkWidget *dropdown; + +- store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING); +- gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box), GTK_TREE_MODEL (store)); ++ store = gtk_string_list_new (NULL); + +- cell = gtk_cell_renderer_text_new (); +- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), cell, TRUE); +- gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), cell, +- "text", NAME_COLUMN, +- NULL); ++ dropdown = gtk_drop_down_new (G_LIST_MODEL (store), NULL); + +- return combo_box; ++ return dropdown; + } + + static void +-combo_box_append (GtkWidget *combo, +- const gchar *display_text, +- const gchar *value) ++dropdown_append (GtkWidget *dropdown, ++ const gchar *display_text) + { +- GtkTreeModel *model; +- GtkListStore *store; +- GtkTreeIter iter; +- +- model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)); +- store = GTK_LIST_STORE (model); +- +- gtk_list_store_append (store, &iter); +- gtk_list_store_set (store, &iter, +- NAME_COLUMN, display_text, +- VALUE_COLUMN, value, +- -1); +-} ++ GtkStringList *store; + +-struct ComboSet { +- GtkComboBox *combo; +- const gchar *value; +-}; ++ store = GTK_STRING_LIST (gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown))); + +-static gboolean +-set_cb (GtkTreeModel *model, +- GtkTreePath *path, +- GtkTreeIter *iter, +- gpointer data) +-{ +- struct ComboSet *set_data = data; +- g_autofree gchar *value = NULL; +- +- gtk_tree_model_get (model, iter, VALUE_COLUMN, &value, -1); +- if (strcmp (value, set_data->value) == 0) +- { +- gtk_combo_box_set_active_iter (set_data->combo, iter); +- return TRUE; +- } +- +- return FALSE; ++ gtk_string_list_append (store, display_text); + } + + static void +-combo_box_set (GtkWidget *combo, +- const gchar *value) ++dropdown_set (GtkWidget *dropdown, ++ IPPAttribute *option, ++ const gchar *value) + { +- struct ComboSet set_data; +- GtkTreeModel *model; ++ g_autofree gchar *attribute_value = NULL; + +- model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)); ++ for (guint i = 0; i < option->num_of_values; i++) ++ { ++ if (option->attribute_type == IPP_ATTRIBUTE_TYPE_INTEGER) ++ attribute_value = g_strdup_printf ("%d", option->attribute_values[i].integer_value); ++ else ++ attribute_value = g_strdup (option->attribute_values[i].string_value); + +- set_data.combo = GTK_COMBO_BOX (combo); +- set_data.value = value; +- gtk_tree_model_foreach (model, set_cb, &set_data); ++ if (g_strcmp0 (attribute_value, value) == 0) ++ { ++ gtk_drop_down_set_selected (GTK_DROP_DOWN (dropdown), i); ++ break; ++ } ++ } + } + + static char * +-combo_box_get (GtkWidget *combo) ++dropdown_get (GtkWidget *dropdown, ++ IPPAttribute *option) + { +- GtkTreeModel *model; +- GtkTreeIter iter; +- gchar *value = NULL; ++ guint selected_item; ++ gchar *value = NULL; + +- model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)); ++ selected_item = gtk_drop_down_get_selected (GTK_DROP_DOWN (dropdown)); + +- if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter)) +- gtk_tree_model_get (model, &iter, VALUE_COLUMN, &value, -1); ++ if (selected_item != GTK_INVALID_LIST_POSITION) ++ { ++ if (option->attribute_type == IPP_ATTRIBUTE_TYPE_INTEGER) ++ value = g_strdup_printf ("%d", option->attribute_values[selected_item].integer_value); ++ else ++ value = option->attribute_values[selected_item].string_value; ++ } + + return value; + } +@@ -295,12 +264,12 @@ switch_changed_cb (PpIPPOptionWidget *self) + } + + static void +-combo_changed_cb (PpIPPOptionWidget *self) ++dropdown_changed_cb (PpIPPOptionWidget *self) + { + gchar **values; + + values = g_new0 (gchar *, 2); +- values[0] = combo_box_get (self->combo); ++ values[0] = g_strdup (dropdown_get (self->dropdown, self->option_supported)); + + g_cancellable_cancel (self->cancellable); + g_clear_object (&self->cancellable); +@@ -380,34 +349,32 @@ construct_widget (PpIPPOptionWidget *self) + break; + + case IPP_ATTRIBUTE_TYPE_INTEGER: +- self->combo = combo_box_new (); ++ self->dropdown = dropdown_new (); + + for (i = 0; i < self->option_supported->num_of_values; i++) + { + g_autofree gchar *value = NULL; + + value = g_strdup_printf ("%d", self->option_supported->attribute_values[i].integer_value); +- combo_box_append (self->combo, +- ipp_choice_translate (self->option_name, +- value), +- value); ++ dropdown_append (self->dropdown, ++ ipp_choice_translate (self->option_name, ++ value)); + } + +- gtk_box_append (GTK_BOX (self), self->combo); +- g_signal_connect_object (self->combo, "changed", G_CALLBACK (combo_changed_cb), self, G_CONNECT_SWAPPED); ++ gtk_box_append (GTK_BOX (self), self->dropdown); ++ g_signal_connect_object (self->dropdown, "notify::selected", G_CALLBACK (dropdown_changed_cb), self, G_CONNECT_SWAPPED); + break; + + case IPP_ATTRIBUTE_TYPE_STRING: +- self->combo = combo_box_new (); ++ self->dropdown = dropdown_new (); + + for (i = 0; i < self->option_supported->num_of_values; i++) +- combo_box_append (self->combo, +- ipp_choice_translate (self->option_name, +- self->option_supported->attribute_values[i].string_value), +- self->option_supported->attribute_values[i].string_value); ++ dropdown_append (self->dropdown, ++ ipp_choice_translate (self->option_name, ++ self->option_supported->attribute_values[i].string_value)); + +- gtk_box_append (GTK_BOX (self), self->combo); +- g_signal_connect_object (self->combo, "changed", G_CALLBACK (combo_changed_cb), self, G_CONNECT_SWAPPED); ++ gtk_box_append (GTK_BOX (self), self->dropdown); ++ g_signal_connect_object (self->dropdown, "notify::selected", G_CALLBACK (dropdown_changed_cb), self, G_CONNECT_SWAPPED); + break; + + case IPP_ATTRIBUTE_TYPE_RANGE: +@@ -468,37 +435,37 @@ update_widget_real (PpIPPOptionWidget *self) + break; + + case IPP_ATTRIBUTE_TYPE_INTEGER: +- g_signal_handlers_block_by_func (self->combo, combo_changed_cb, self); ++ g_signal_handlers_block_by_func (self->dropdown, dropdown_changed_cb, self); + + if (attr && attr->num_of_values > 0 && + attr->attribute_type == IPP_ATTRIBUTE_TYPE_INTEGER) + { + g_autofree gchar *value = g_strdup_printf ("%d", attr->attribute_values[0].integer_value); +- combo_box_set (self->combo, value); ++ dropdown_set (self->dropdown, self->option_supported, value); + } + else + { + g_autofree gchar *value = g_strdup_printf ("%d", self->option_supported->attribute_values[0].integer_value); +- combo_box_set (self->combo, value); ++ dropdown_set (self->dropdown, self->option_supported, value); + } + +- g_signal_handlers_unblock_by_func (self->combo, combo_changed_cb, self); ++ g_signal_handlers_unblock_by_func (self->dropdown, dropdown_changed_cb, self); + break; + + case IPP_ATTRIBUTE_TYPE_STRING: +- g_signal_handlers_block_by_func (self->combo, combo_changed_cb, self); ++ g_signal_handlers_block_by_func (self->dropdown, dropdown_changed_cb, self); + + if (attr && attr->num_of_values > 0 && + attr->attribute_type == IPP_ATTRIBUTE_TYPE_STRING) + { +- combo_box_set (self->combo, attr->attribute_values[0].string_value); ++ dropdown_set (self->dropdown, self->option_supported, attr->attribute_values[0].string_value); + } + else + { +- combo_box_set (self->combo, self->option_supported->attribute_values[0].string_value); ++ dropdown_set (self->dropdown, self->option_supported, self->option_supported->attribute_values[0].string_value); + } + +- g_signal_handlers_unblock_by_func (self->combo, combo_changed_cb, self); ++ g_signal_handlers_unblock_by_func (self->dropdown, dropdown_changed_cb, self); + break; + + case IPP_ATTRIBUTE_TYPE_RANGE: +diff --git a/panels/printers/pp-ppd-option-widget.c b/panels/printers/pp-ppd-option-widget.c +index 2f3962090..0375b16cb 100644 +--- a/panels/printers/pp-ppd-option-widget.c ++++ b/panels/printers/pp-ppd-option-widget.c +@@ -40,7 +40,7 @@ struct _PpPPDOptionWidget + GtkBox parent_instance; + + GtkWidget *switch_button; +- GtkWidget *combo; ++ GtkWidget *dropdown; + GtkWidget *image; + GtkWidget *box; + +@@ -180,8 +180,10 @@ ppd_choice_translate (ppd_choice_t *choice) + for (i = 0; i < G_N_ELEMENTS (ppd_choice_translations); i++) + { + if (g_strcmp0 (ppd_choice_translations[i].keyword, keyword) == 0 && +- g_strcmp0 (ppd_choice_translations[i].choice, choice->choice) == 0) +- return _(ppd_choice_translations[i].translation); ++ g_strcmp0 (ppd_choice_translations[i].choice, choice->choice) == 0) ++ { ++ return _(ppd_choice_translations[i].translation); ++ } + } + + return choice->text; +@@ -216,102 +218,58 @@ pp_ppd_option_widget_new (ppd_option_t *option, + return (GtkWidget *) self; + } + +-enum { +- NAME_COLUMN, +- VALUE_COLUMN, +- N_COLUMNS +-}; +- + static GtkWidget * +-combo_box_new (void) ++dropdown_new (void) + { +- GtkCellRenderer *cell; +- g_autoptr(GtkListStore) store = NULL; +- GtkWidget *combo_box; ++ GtkStringList *store = NULL; ++ GtkWidget *dropdown; + +- combo_box = gtk_combo_box_new (); ++ store = gtk_string_list_new (NULL); + +- store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING); +- gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box), GTK_TREE_MODEL (store)); ++ dropdown = gtk_drop_down_new (G_LIST_MODEL (store), NULL); + +- cell = gtk_cell_renderer_text_new (); +- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), cell, TRUE); +- gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), cell, +- "text", NAME_COLUMN, +- NULL); +- +- return combo_box; ++ return dropdown; + } + + static void +-combo_box_append (GtkWidget *combo, +- const gchar *display_text, +- const gchar *value) +-{ +- GtkTreeModel *model; +- GtkListStore *store; +- GtkTreeIter iter; +- +- model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)); +- store = GTK_LIST_STORE (model); +- +- gtk_list_store_append (store, &iter); +- gtk_list_store_set (store, &iter, +- NAME_COLUMN, display_text, +- VALUE_COLUMN, value, +- -1); +-} +- +-struct ComboSet { +- GtkComboBox *combo; +- const gchar *value; +-}; +- +-static gboolean +-set_cb (GtkTreeModel *model, +- GtkTreePath *path, +- GtkTreeIter *iter, +- gpointer data) ++dropdown_append (GtkWidget *dropdown, ++ const gchar *display_text) + { +- struct ComboSet *set_data = data; +- g_autofree gchar *value = NULL; ++ GtkStringList *store; + +- gtk_tree_model_get (model, iter, VALUE_COLUMN, &value, -1); ++ store = GTK_STRING_LIST (gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown))); + +- if (strcmp (value, set_data->value) == 0) +- { +- gtk_combo_box_set_active_iter (set_data->combo, iter); +- return TRUE; +- } +- +- return FALSE; ++ gtk_string_list_append (store, display_text); + } + + static void +-combo_box_set (GtkWidget *combo, +- const gchar *value) ++dropdown_set (GtkWidget *dropdown, ++ ppd_option_t *option, ++ const gchar *value) + { +- struct ComboSet set_data; +- GtkTreeModel *model; +- +- model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)); +- +- set_data.combo = GTK_COMBO_BOX (combo); +- set_data.value = value; +- gtk_tree_model_foreach (model, set_cb, &set_data); ++ for (guint i = 0; i < option->num_choices; i++) ++ { ++ if (g_strcmp0 (option->choices[i].choice, value) == 0) ++ { ++ gtk_drop_down_set_selected (GTK_DROP_DOWN (dropdown), i); ++ break; ++ } ++ } + } + + static char * +-combo_box_get (GtkWidget *combo) ++dropdown_get (GtkWidget *dropdown, ++ ppd_option_t *option) + { +- GtkTreeModel *model; +- GtkTreeIter iter; +- gchar *value = NULL; ++ guint selected_item; ++ gchar *value = NULL; + +- model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)); ++ selected_item = gtk_drop_down_get_selected (GTK_DROP_DOWN (dropdown)); + +- if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter)) +- gtk_tree_model_get (model, &iter, VALUE_COLUMN, &value, -1); ++ if (selected_item != GTK_INVALID_LIST_POSITION) ++ { ++ value = option->choices[selected_item].choice; ++ } + + return value; + } +@@ -354,12 +312,12 @@ switch_changed_cb (PpPPDOptionWidget *self) + } + + static void +-combo_changed_cb (PpPPDOptionWidget *self) ++dropdown_changed_cb (PpPPDOptionWidget *self) + { + gchar **values; + + values = g_new0 (gchar *, 2); +- values[0] = combo_box_get (self->combo); ++ values[0] = g_strdup (dropdown_get (self->dropdown, self->option)); + + g_cancellable_cancel (self->cancellable); + g_clear_object (&self->cancellable); +@@ -394,31 +352,29 @@ construct_widget (PpPPDOptionWidget *self) + break; + + case PPD_UI_PICKONE: +- self->combo = combo_box_new (); ++ self->dropdown = dropdown_new (); + + for (i = 0; i < self->option->num_choices; i++) + { +- combo_box_append (self->combo, +- ppd_choice_translate (&self->option->choices[i]), +- self->option->choices[i].choice); ++ dropdown_append (self->dropdown, ++ ppd_choice_translate (&self->option->choices[i])); + } + +- gtk_box_append (GTK_BOX (self), self->combo); +- g_signal_connect_object (self->combo, "changed", G_CALLBACK (combo_changed_cb), self, G_CONNECT_SWAPPED); ++ gtk_box_append (GTK_BOX (self), self->dropdown); ++ g_signal_connect_object (self->dropdown, "notify::selected", G_CALLBACK (dropdown_changed_cb), self, G_CONNECT_SWAPPED); + break; + + case PPD_UI_PICKMANY: +- self->combo = combo_box_new (); ++ self->dropdown = dropdown_new (); + + for (i = 0; i < self->option->num_choices; i++) + { +- combo_box_append (self->combo, +- ppd_choice_translate (&self->option->choices[i]), +- self->option->choices[i].choice); ++ dropdown_append (self->dropdown, ++ ppd_choice_translate (&self->option->choices[i])); + } + +- gtk_box_append (GTK_BOX (self), self->combo); +- g_signal_connect_object (self->combo, "changed", G_CALLBACK (combo_changed_cb), self, G_CONNECT_SWAPPED); ++ gtk_box_append (GTK_BOX (self), self->dropdown); ++ g_signal_connect_object (self->dropdown, "notify::selected", G_CALLBACK (dropdown_changed_cb), self, G_CONNECT_SWAPPED); + break; + + default: +@@ -445,13 +401,7 @@ update_widget_real (PpPPDOptionWidget *self) + ppd_file_t *ppd_file; + gint i; + +- if (self->option) +- { +- option = cups_option_copy (self->option); +- cups_option_free (self->option); +- self->option = NULL; +- } +- else if (self->ppd_filename) ++ if (self->ppd_filename_set && self->ppd_filename) + { + ppd_file = ppdOpenFile (self->ppd_filename); + ppdLocalize (ppd_file); +@@ -464,7 +414,8 @@ update_widget_real (PpPPDOptionWidget *self) + { + if (g_str_equal (iter->keyword, self->option_name)) + { +- option = cups_option_copy (iter); ++ g_clear_pointer (&self->option, cups_option_free); ++ self->option = cups_option_copy (iter); + break; + } + } +@@ -477,6 +428,8 @@ update_widget_real (PpPPDOptionWidget *self) + self->ppd_filename = NULL; + } + ++ option = self->option; ++ + if (option) + { + g_autofree gchar *value = NULL; +@@ -502,15 +455,15 @@ update_widget_real (PpPPDOptionWidget *self) + break; + + case PPD_UI_PICKONE: +- g_signal_handlers_block_by_func (self->combo, combo_changed_cb, self); +- combo_box_set (self->combo, value); +- g_signal_handlers_unblock_by_func (self->combo, combo_changed_cb, self); ++ g_signal_handlers_block_by_func (self->dropdown, dropdown_changed_cb, self); ++ dropdown_set (self->dropdown, option, value); ++ g_signal_handlers_unblock_by_func (self->dropdown, dropdown_changed_cb, self); + break; + + case PPD_UI_PICKMANY: +- g_signal_handlers_block_by_func (self->combo, combo_changed_cb, self); +- combo_box_set (self->combo, value); +- g_signal_handlers_unblock_by_func (self->combo, combo_changed_cb, self); ++ g_signal_handlers_block_by_func (self->dropdown, dropdown_changed_cb, self); ++ dropdown_set (self->dropdown, option, value); ++ g_signal_handlers_unblock_by_func (self->dropdown, dropdown_changed_cb, self); + break; + + default: +@@ -523,8 +476,6 @@ update_widget_real (PpPPDOptionWidget *self) + else + gtk_widget_hide (self->image); + } +- +- cups_option_free (option); + } + + static void +-- +GitLab +