From be5f225022eefe3824d3f272eb009feca7baf209 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Thu, 20 Apr 2023 17:31:57 +0200 Subject: [PATCH 1/5] testsuite: Be less verbose in accessor-apis test Only print the tried names when --verbose is passed to the test. --- testsuite/gtk/accessor-apis.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/testsuite/gtk/accessor-apis.c b/testsuite/gtk/accessor-apis.c index aae3c17821..63b2942d7a 100644 --- a/testsuite/gtk/accessor-apis.c +++ b/testsuite/gtk/accessor-apis.c @@ -218,9 +218,12 @@ check_function_name (GType type, } g_test_message ("No %s for property %s::%s", get ? "getter" : "setter", g_type_name (type), property_name); - for (i = 0; names[i] != NULL; i++) + if (g_test_verbose ()) { - g_test_message (" %s", names[i]); + for (i = 0; names[i] != NULL; i++) + { + g_test_message (" %s", names[i]); + } } g_test_fail (); From 39583e40efd2e22302f05b727f2965c13084a53e Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Thu, 20 Apr 2023 17:32:36 +0200 Subject: [PATCH 2/5] testsuite: Allow accessors in interfaces There are a lot of cases where properties are implemented in classes but the getters for these exist in an interface that class implements. A common Example is g_list_model_get_n_items() being the getter for GtkWhateverListModel::n-items. But also property implementations that don't use override_property() (usually because they have a different default) are handled by this. --- testsuite/gtk/accessor-apis.c | 42 ++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/testsuite/gtk/accessor-apis.c b/testsuite/gtk/accessor-apis.c index 63b2942d7a..c5f3fdf1ae 100644 --- a/testsuite/gtk/accessor-apis.c +++ b/testsuite/gtk/accessor-apis.c @@ -126,6 +126,22 @@ property_name_mangle (GString *symbol_name, } } +static void +add_type_name (GPtrArray *type_names, + GType type) +{ + char *options[2]; + + options[0] = type_name_mangle (g_type_name (type), FALSE); + g_ptr_array_add (type_names, options[0]); + + options[1] = type_name_mangle (g_type_name (type), TRUE); + if (g_str_equal (options[0], options[1])) + g_free (options[1]); + else + g_ptr_array_add (type_names, options[1]); +} + const char *getters[] = { "get", "is", "ref" }; const char *setters[] = { "set" }; @@ -135,8 +151,9 @@ get_potential_names (GType type, const char *property_name) { GPtrArray *options; - char *type_name_options[2]; - guint n_type_name_options, n_verbs; + GPtrArray *type_names; + GType *interfaces; + guint n_verbs, n_interfaces; const char **verbs; guint i, j; @@ -151,22 +168,22 @@ get_potential_names (GType type, n_verbs = G_N_ELEMENTS (setters); } - type_name_options[0] = type_name_mangle (g_type_name (type), FALSE); - type_name_options[1] = type_name_mangle (g_type_name (type), TRUE); - if (g_str_equal (type_name_options[0], type_name_options[1])) - n_type_name_options = 1; - else - n_type_name_options = 2; + type_names = g_ptr_array_new_with_free_func (g_free); + add_type_name (type_names, type); + interfaces = g_type_interfaces (type, &n_interfaces); + for (i = 0; i < n_interfaces; i++) + add_type_name (type_names, interfaces[i]); + g_free (interfaces); options = g_ptr_array_new (); - for (i = 0; i < n_type_name_options; i++) + for (i = 0; i < type_names->len; i++) { for (j = 0; j < n_verbs; j++) { GString *str; - str = g_string_new (type_name_options[i]); + str = g_string_new (g_ptr_array_index (type_names, i)); g_string_append_c (str, '_'); g_string_append (str, verbs[j]); g_string_append_c (str, '_'); @@ -182,7 +199,7 @@ get_potential_names (GType type, GString *str; /* try without a verb */ - str = g_string_new (type_name_options[i]); + str = g_string_new (g_ptr_array_index (type_names, i)); g_string_append_c (str, '_'); property_name_mangle (str, property_name); @@ -190,8 +207,7 @@ get_potential_names (GType type, } } - g_free (type_name_options[0]); - g_free (type_name_options[1]); + g_ptr_array_free (type_names, TRUE); g_ptr_array_add (options, NULL); From e47c0760480b0bda9c85dce4968459fcecbf6fc5 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Thu, 20 Apr 2023 18:52:49 +0200 Subject: [PATCH 3/5] adjustment: Split out a function --- gtk/gtkadjustment.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/gtk/gtkadjustment.c b/gtk/gtkadjustment.c index 1e0bae6f6b..2516d43cfd 100644 --- a/gtk/gtkadjustment.c +++ b/gtk/gtkadjustment.c @@ -352,6 +352,21 @@ gtk_adjustment_dispatch_properties_changed (GObject *object, } } +static double +gtk_adjustment_sanitize_value (GtkAdjustment *self, + double value) +{ + GtkAdjustmentPrivate *priv = gtk_adjustment_get_instance_private (self); + + /* don't use CLAMP() so we don't end up below lower if upper - page_size + * is smaller than lower + */ + value = MIN (value, priv->upper - priv->page_size); + value = MAX (value, priv->lower); + + return value; +} + /** * gtk_adjustment_new: * @value: the initial value @@ -497,11 +512,7 @@ gtk_adjustment_set_value_internal (GtkAdjustment *adjustment, { GtkAdjustmentPrivate *priv = gtk_adjustment_get_instance_private (adjustment); - /* don't use CLAMP() so we don't end up below lower if upper - page_size - * is smaller than lower - */ - value = MIN (value, priv->upper - priv->page_size); - value = MAX (value, priv->lower); + value = gtk_adjustment_sanitize_value (adjustment, value); if (animate && priv->duration != 0 && priv->clock != NULL) { @@ -825,11 +836,7 @@ gtk_adjustment_configure (GtkAdjustment *adjustment, gtk_adjustment_set_page_increment (adjustment, page_increment); gtk_adjustment_set_page_size (adjustment, page_size); - /* don't use CLAMP() so we don't end up below lower if upper - page_size - * is smaller than lower - */ - value = MIN (value, upper - page_size); - value = MAX (value, lower); + value = gtk_adjustment_sanitize_value (adjustment, value); if (value != priv->value) { From 75c47755e38b77e2b066ce55783c1de3143f5120 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Thu, 20 Apr 2023 19:00:08 +0200 Subject: [PATCH 4/5] adjustment: sanity-check values when setting them It's not enough to sanitize values when starting an animation, as the adjustment can reconfigure itself while the animation runs. So as a simple way to handle this, we sanitize every value right before setting it, too. In the future we might also want to look at sanitizing start/end values of the animation. Fixes #5763 --- gtk/gtkadjustment.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gtk/gtkadjustment.c b/gtk/gtkadjustment.c index 2516d43cfd..fc41931069 100644 --- a/gtk/gtkadjustment.c +++ b/gtk/gtkadjustment.c @@ -434,6 +434,8 @@ adjustment_set_value (GtkAdjustment *adjustment, { GtkAdjustmentPrivate *priv = gtk_adjustment_get_instance_private (adjustment); + value = gtk_adjustment_sanitize_value (adjustment, value); + if (priv->value != value) { priv->value = value; From f393f70ee23a807d0a4f8c65f0df1407fe87b331 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Thu, 20 Apr 2023 19:07:08 +0200 Subject: [PATCH 5/5] listbase: Don't warn on scroll in empty list Empty lists can still be scrolled if the scroll happens in the same frame as the emptying of the list. Related: #5763 --- gtk/gtklistbase.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gtk/gtklistbase.c b/gtk/gtklistbase.c index 0c7df53aa0..0a7dbb0b02 100644 --- a/gtk/gtklistbase.c +++ b/gtk/gtklistbase.c @@ -214,6 +214,11 @@ gtk_list_base_adjustment_value_changed_cb (GtkAdjustment *adjustment, &pos, &cell_area)) { + /* If we get here with n-items == 0, then somebody cleared the list but + * GC hasn't run. So no item to be found. */ + if (gtk_list_base_get_n_items (self) == 0) + return; + g_warning ("%s failed to scroll to given position. Ignoring...", G_OBJECT_TYPE_NAME (self)); return; }