summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNelson Benítez León <nbenitezl@gmail.com>2022-01-19 15:33:03 -0400
committerNelson Benítez León <nbenitezl@gmail.com>2022-01-20 21:46:02 -0400
commit7f7c6b8b1e93440c7abc3045cb90a97e8d051b3d (patch)
treee04df710f5ec4b115c8d7a76757e94676f0e3787
parenta10616025195cf9b1928077beda861a55904b91c (diff)
downloadgtk+-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.c8
-rw-r--r--gtk/gtkrange.c5
-rw-r--r--gtk/gtkspinbutton.c8
-rw-r--r--gtk/gtkwidget.c30
-rw-r--r--gtk/gtkwidgetprivate.h1
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);