[gtk+] gtk: Implement smooth scrolling in scrolledwindow/range
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] gtk: Implement smooth scrolling in scrolledwindow/range
- Date: Thu, 1 Mar 2012 21:33:41 +0000 (UTC)
commit 2a72e7b7b86d1bdb3a6a818b94cb21bc8f611127
Author: Michael Natterer <mitch lanedo com>
Date: Tue Jan 24 12:12:34 2012 +0100
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.
gtk/gtkrange.c | 65 ++++++++++++++++++++++++++++++----------
gtk/gtkrange.h | 4 +-
gtk/gtkscrolledwindow.c | 75 +++++++++++++++++++++++++++++++++++++++-------
3 files changed, 114 insertions(+), 30 deletions(-)
---
diff --git a/gtk/gtkrange.c b/gtk/gtkrange.c
index b920d00..b38fa89 100644
--- a/gtk/gtkrange.c
+++ b/gtk/gtkrange.c
@@ -1728,9 +1728,11 @@ gtk_range_realize (GtkWidget *widget)
attributes.wclass = GDK_INPUT_ONLY;
attributes.event_mask = gtk_widget_get_events (widget);
attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
- GDK_BUTTON_RELEASE_MASK |
- GDK_ENTER_NOTIFY_MASK |
- GDK_LEAVE_NOTIFY_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_SCROLL_MASK |
+ GDK_SMOOTH_SCROLL_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK |
GDK_POINTER_MOTION_MASK |
GDK_POINTER_MOTION_HINT_MASK);
@@ -2784,7 +2786,7 @@ gtk_range_button_release (GtkWidget *widget,
/**
* _gtk_range_get_wheel_delta:
* @range: a #GtkRange
- * @direction: A #GdkScrollDirection
+ * @event: A #GdkEventScroll
*
* Returns a good step value for the mouse wheel.
*
@@ -2793,28 +2795,59 @@ gtk_range_button_release (GtkWidget *widget,
* Since: 2.4
**/
gdouble
-_gtk_range_get_wheel_delta (GtkRange *range,
- GdkScrollDirection direction)
+_gtk_range_get_wheel_delta (GtkRange *range,
+ GdkEventScroll *event)
{
GtkRangePrivate *priv = range->priv;
GtkAdjustment *adjustment = priv->adjustment;
+ gdouble dx, dy;
gdouble delta;
+ gdouble page_size;
- if (GTK_IS_SCROLLBAR (range))
- delta = pow (gtk_adjustment_get_page_size (adjustment), 2.0 / 3.0);
+ page_size = gtk_adjustment_get_page_size (adjustment);
+
+ if (gdk_event_get_scroll_deltas ((GdkEvent *) event, &dx, &dy))
+ {
+ GtkAllocation allocation;
+
+ gtk_widget_get_allocation (GTK_WIDGET (range), &allocation);
+
+ if (dx != 0 &&
+ gtk_orientable_get_orientation (GTK_ORIENTABLE (range)) == GTK_ORIENTATION_HORIZONTAL)
+ {
+ if (GTK_IS_SCROLLBAR (range) && page_size > 0)
+ delta = dx * page_size / allocation.width;
+ else
+ delta = dx * (gtk_adjustment_get_upper (adjustment) -
+ gtk_adjustment_get_lower (adjustment)) / allocation.width;
+ }
+ else
+ {
+ if (GTK_IS_SCROLLBAR (range) && page_size > 0)
+ delta = dy * page_size / allocation.height;
+ else
+ delta = dy * (gtk_adjustment_get_upper (adjustment) -
+ gtk_adjustment_get_lower (adjustment)) / allocation.height;
+ }
+ }
else
- delta = gtk_adjustment_get_step_increment (adjustment) * 2;
-
- if (direction == GDK_SCROLL_UP ||
- direction == GDK_SCROLL_LEFT)
- delta = - delta;
-
+ {
+ if (GTK_IS_SCROLLBAR (range))
+ delta = pow (page_size, 2.0 / 3.0);
+ else
+ delta = gtk_adjustment_get_page_increment (adjustment) * 2;
+
+ if (event->direction == GDK_SCROLL_UP ||
+ event->direction == GDK_SCROLL_LEFT)
+ delta = - delta;
+ }
+
if (priv->inverted)
delta = - delta;
return delta;
}
-
+
static gboolean
gtk_range_scroll_event (GtkWidget *widget,
GdkEventScroll *event)
@@ -2827,7 +2860,7 @@ gtk_range_scroll_event (GtkWidget *widget,
gdouble delta;
gboolean handled;
- delta = _gtk_range_get_wheel_delta (range, event->direction);
+ delta = _gtk_range_get_wheel_delta (range, event);
g_signal_emit (range, signals[CHANGE_VALUE], 0,
GTK_SCROLL_JUMP, gtk_adjustment_get_value (priv->adjustment) + delta,
diff --git a/gtk/gtkrange.h b/gtk/gtkrange.h
index 0f52554..c4d9e9e 100644
--- a/gtk/gtkrange.h
+++ b/gtk/gtkrange.h
@@ -146,8 +146,8 @@ void gtk_range_set_round_digits (GtkRange *range
gint gtk_range_get_round_digits (GtkRange *range);
/* internal API */
-gdouble _gtk_range_get_wheel_delta (GtkRange *range,
- GdkScrollDirection direction);
+gdouble _gtk_range_get_wheel_delta (GtkRange *range,
+ GdkEventScroll *event);
void _gtk_range_set_has_origin (GtkRange *range,
gboolean has_origin);
gboolean _gtk_range_get_has_origin (GtkRange *range);
diff --git a/gtk/gtkscrolledwindow.c b/gtk/gtkscrolledwindow.c
index 7c73994..05bad81 100644
--- a/gtk/gtkscrolledwindow.c
+++ b/gtk/gtkscrolledwindow.c
@@ -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 (gdk_event_get_scroll_deltas ((GdkEvent *) event, &delta_x, &delta_y))
+ {
+ if (delta_x != 0.0 && priv->hscrollbar &&
+ gtk_widget_get_visible (priv->hscrollbar))
+ {
+ GtkAdjustment *adj;
+ gdouble new_value;
+
+ adj = gtk_range_get_adjustment (GTK_RANGE (priv->hscrollbar));
+
+ 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);
- if (range && gtk_widget_get_visible (range))
+ handled = TRUE;
+ }
+ }
+ else
{
- GtkAdjustment *adjustment = gtk_range_get_adjustment (GTK_RANGE (range));
- gdouble delta;
+ GtkWidget *range;
- delta = _gtk_range_get_wheel_delta (GTK_RANGE (range), event->direction);
- gtk_adjustment_set_value (adjustment, gtk_adjustment_get_value (adjustment) + delta);
+ if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_DOWN)
+ range = priv->vscrollbar;
+ else
+ range = priv->hscrollbar;
- return TRUE;
+ 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
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]