diff options
author | Nelson Benítez León <nbenitezl@gmail.com> | 2022-01-19 15:33:03 -0400 |
---|---|---|
committer | Nelson Benítez León <nbenitezl@gmail.com> | 2022-01-20 21:46:02 -0400 |
commit | 7f7c6b8b1e93440c7abc3045cb90a97e8d051b3d (patch) | |
tree | e04df710f5ec4b115c8d7a76757e94676f0e3787 | |
parent | a10616025195cf9b1928077beda861a55904b91c (diff) | |
download | gtk+-BUG_gtk3_containers_scroll_precedence.tar.gz |
scrolling a container should not scroll child widgetsBUG_gtk3_containers_scroll_precedence
Containers that can be scrolled should have precedence
over child widgets that also react to scrolling
like GtkComboBox, GtkScale and GtkSpinButton,
because otherwise when you're in the middle of
scrolling the view/window you can involuntarily
scroll over the widgets and change its values.
This problem can be seen in applications like
pavucontrol, gnome-tweaks prefs, devhelp prefs,
and so on.
Fixes issue #3092
-rw-r--r-- | gtk/gtkcombobox.c | 8 | ||||
-rw-r--r-- | gtk/gtkrange.c | 5 | ||||
-rw-r--r-- | gtk/gtkspinbutton.c | 8 | ||||
-rw-r--r-- | gtk/gtkwidget.c | 30 | ||||
-rw-r--r-- | gtk/gtkwidgetprivate.h | 1 |
5 files changed, 48 insertions, 4 deletions
diff --git a/gtk/gtkcombobox.c b/gtk/gtkcombobox.c index ef4996c027..57fbbd6e0c 100644 --- a/gtk/gtkcombobox.c +++ b/gtk/gtkcombobox.c @@ -2707,8 +2707,12 @@ gtk_combo_box_scroll_event (GtkWidget *widget, GtkTreeIter iter; GtkTreeIter new_iter; + /* Scrolling the parent window/container takes precedence - Issue #3092 */ + if (gtk_widget_inside_scrollable_container (widget)) + return GDK_EVENT_PROPAGATE; + if (!gtk_combo_box_get_active_iter (combo_box, &iter)) - return TRUE; + return GDK_EVENT_STOP; if (event->direction == GDK_SCROLL_UP) found = tree_prev (combo_box, priv->model, @@ -2720,7 +2724,7 @@ gtk_combo_box_scroll_event (GtkWidget *widget, if (found) gtk_combo_box_set_active_iter (combo_box, &new_iter); - return TRUE; + return GDK_EVENT_STOP; } /* diff --git a/gtk/gtkrange.c b/gtk/gtkrange.c index 774174df52..826e6c4aac 100644 --- a/gtk/gtkrange.c +++ b/gtk/gtkrange.c @@ -3118,6 +3118,11 @@ gtk_range_scroll_event (GtkWidget *widget, GtkRange *range = GTK_RANGE (widget); GtkRangePrivate *priv = range->priv; double delta = _gtk_range_get_wheel_delta (range, event); + + /* Scrolling the parent window/container takes precedence - Issue #3092 */ + if (gtk_widget_inside_scrollable_container (widget)) + return GDK_EVENT_PROPAGATE; + gboolean handled; g_signal_emit (range, signals[CHANGE_VALUE], 0, diff --git a/gtk/gtkspinbutton.c b/gtk/gtkspinbutton.c index 8e65d8a272..878e8c2354 100644 --- a/gtk/gtkspinbutton.c +++ b/gtk/gtkspinbutton.c @@ -1335,6 +1335,10 @@ gtk_spin_button_scroll (GtkWidget *widget, GtkSpinButton *spin = GTK_SPIN_BUTTON (widget); GtkSpinButtonPrivate *priv = spin->priv; + /* Scrolling the parent window/container takes precedence - Issue #3092 */ + if (gtk_widget_inside_scrollable_container (widget)) + return GDK_EVENT_PROPAGATE; + if (event->direction == GDK_SCROLL_UP) { if (!gtk_widget_has_focus (widget)) @@ -1348,9 +1352,9 @@ gtk_spin_button_scroll (GtkWidget *widget, gtk_spin_button_real_spin (spin, -gtk_adjustment_get_step_increment (priv->adjustment)); } else - return FALSE; + return GDK_EVENT_PROPAGATE; - return TRUE; + return GDK_EVENT_STOP; } static gboolean diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index b6e00115bb..f4b14de0ae 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -11661,6 +11661,36 @@ gtk_widget_get_ancestor (GtkWidget *widget, return widget; } +/*< private > + * gtk_widget_inside_scrollable_container: + * @widget: a #GtkWidget + * + * Private function used by GtkComboBox, GtkRange, GtkSpinButton - See issue #3092 + * + * Returns: whether @widget is inside a scrollable container (like eg. + * GtkScrolledWindow, GtkViewPort) and the view can currently be scrolled + * i.e. the scrollbars can move because the content excedes the page_size + */ +gboolean +gtk_widget_inside_scrollable_container (GtkWidget *widget) +{ + GtkWidget *ancestor; + GtkAdjustment *vadj; + gdouble upper, page_size; + + ancestor = gtk_widget_get_ancestor (gtk_widget_get_parent (widget), GTK_TYPE_SCROLLABLE); + if (ancestor) + { + vadj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (ancestor)); + g_object_get (vadj, "upper", &upper, "page_size", &page_size, NULL); + + if (!G_APPROX_VALUE ((upper - page_size), 0.0, DBL_EPSILON)) + return TRUE; + } + + return FALSE; +} + /** * gtk_widget_set_visual: * @widget: a #GtkWidget diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h index 1b7ddf2ff0..722d8f7e1c 100644 --- a/gtk/gtkwidgetprivate.h +++ b/gtk/gtkwidgetprivate.h @@ -282,6 +282,7 @@ GList * _gtk_widget_list_controllers (GtkWidget GtkPropagationPhase phase); gboolean _gtk_widget_consumes_motion (GtkWidget *widget, GdkEventSequence *sequence); +gboolean gtk_widget_inside_scrollable_container (GtkWidget *widget); gboolean gtk_widget_has_tick_callback (GtkWidget *widget); |