gtk: Implement smooth scrolling in scrolledwindow/range

If delta_x/y information is provided in scroll events, use it
to modify the underlying adjustment in steps proportional to
the deltas provided.

If the child widget of a scrolledwindow doesn't set
GDK_SMOOTH_SCROLL_MASK, regular scroll events will be dispatched,
and still handled by these 2 widgets.
This commit is contained in:
Michael Natterer
2012-01-24 12:12:34 +01:00
committed by Matthias Clasen
parent 147cdd8465
commit 2a72e7b7b8
3 changed files with 115 additions and 31 deletions

View File

@ -2248,7 +2248,9 @@ gtk_scrolled_window_scroll_event (GtkWidget *widget,
{
GtkScrolledWindowPrivate *priv;
GtkScrolledWindow *scrolled_window;
GtkWidget *range;
gboolean handled = FALSE;
gdouble delta_x;
gdouble delta_y;
g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
@ -2256,23 +2258,72 @@ gtk_scrolled_window_scroll_event (GtkWidget *widget,
scrolled_window = GTK_SCROLLED_WINDOW (widget);
priv = scrolled_window->priv;
if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_DOWN)
range = priv->vscrollbar;
else
range = priv->hscrollbar;
if (range && gtk_widget_get_visible (range))
if (gdk_event_get_scroll_deltas ((GdkEvent *) event, &delta_x, &delta_y))
{
GtkAdjustment *adjustment = gtk_range_get_adjustment (GTK_RANGE (range));
gdouble delta;
if (delta_x != 0.0 && priv->hscrollbar &&
gtk_widget_get_visible (priv->hscrollbar))
{
GtkAdjustment *adj;
gdouble new_value;
delta = _gtk_range_get_wheel_delta (GTK_RANGE (range), event->direction);
gtk_adjustment_set_value (adjustment, gtk_adjustment_get_value (adjustment) + delta);
adj = gtk_range_get_adjustment (GTK_RANGE (priv->hscrollbar));
return TRUE;
new_value = CLAMP (gtk_adjustment_get_value (adj) + delta_x,
gtk_adjustment_get_lower (adj),
gtk_adjustment_get_upper (adj) -
gtk_adjustment_get_page_size (adj));
gtk_adjustment_set_value (adj, new_value);
handled = TRUE;
}
if (delta_y != 0.0 && priv->vscrollbar &&
gtk_widget_get_visible (priv->vscrollbar))
{
GtkAdjustment *adj;
gdouble new_value;
adj = gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar));
new_value = CLAMP (gtk_adjustment_get_value (adj) + delta_y,
gtk_adjustment_get_lower (adj),
gtk_adjustment_get_upper (adj) -
gtk_adjustment_get_page_size (adj));
gtk_adjustment_set_value (adj, new_value);
handled = TRUE;
}
}
else
{
GtkWidget *range;
if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_DOWN)
range = priv->vscrollbar;
else
range = priv->hscrollbar;
if (range && gtk_widget_get_visible (range))
{
GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (range));
gdouble delta, new_value;
delta = _gtk_range_get_wheel_delta (GTK_RANGE (range), event);
new_value = CLAMP (gtk_adjustment_get_value (adj) + delta,
gtk_adjustment_get_lower (adj),
gtk_adjustment_get_upper (adj) -
gtk_adjustment_get_page_size (adj));
gtk_adjustment_set_value (adj, new_value);
handled = TRUE;
}
}
return FALSE;
return handled;
}
static gboolean