6bdd276d05
Former-commit-id: fd56571888259555122d8a0f58c68838229cea2b
419 lines
13 KiB
Diff
419 lines
13 KiB
Diff
From ab426801023babba7513d9e27a4dbdd44bdbc318 Mon Sep 17 00:00:00 2001
|
|
From: Michael Natterer <mitch@gimp.org>
|
|
Date: Tue, 8 May 2012 14:11:50 +0200
|
|
Subject: [PATCH 08/68] Smooth scrolling
|
|
|
|
---
|
|
gdk/gdkevents.c | 32 +++++++++++++++++
|
|
gdk/gdkevents.h | 6 ++++
|
|
gdk/gdkwindow.c | 3 ++
|
|
gdk/quartz/gdkevents-quartz.c | 80 +++++++++++++++++++++++++++++++----------
|
|
gtk/gtkrange.c | 51 +++++++++++++++++++-------
|
|
gtk/gtkrange.h | 4 +--
|
|
gtk/gtkscrolledwindow.c | 74 ++++++++++++++++++++++++++++++--------
|
|
7 files changed, 203 insertions(+), 47 deletions(-)
|
|
|
|
diff --git a/gdk/gdkevents.c b/gdk/gdkevents.c
|
|
index 53833a0..0f8bba2 100644
|
|
--- a/gdk/gdkevents.c
|
|
+++ b/gdk/gdkevents.c
|
|
@@ -392,6 +392,8 @@ gdk_event_new (GdkEventType type)
|
|
new_event->scroll.y = 0.;
|
|
new_event->scroll.x_root = 0.;
|
|
new_event->scroll.y_root = 0.;
|
|
+ new_event->scroll.delta_x = 0.;
|
|
+ new_event->scroll.delta_y = 0.;
|
|
break;
|
|
case GDK_ENTER_NOTIFY:
|
|
case GDK_LEAVE_NOTIFY:
|
|
@@ -845,6 +847,36 @@ gdk_event_get_root_coords (const GdkEvent *event,
|
|
return fetched;
|
|
}
|
|
|
|
+gboolean
|
|
+gdk_event_get_scroll_deltas (const GdkEvent *event,
|
|
+ gdouble *delta_x,
|
|
+ gdouble *delta_y)
|
|
+{
|
|
+ gboolean fetched = TRUE;
|
|
+ gdouble dx = 0.0;
|
|
+ gdouble dy = 0.0;
|
|
+
|
|
+ switch (event->type)
|
|
+ {
|
|
+ case GDK_SCROLL:
|
|
+ fetched = event->scroll.has_deltas;
|
|
+ dx = event->scroll.delta_x;
|
|
+ dy = event->scroll.delta_y;
|
|
+ break;
|
|
+ default:
|
|
+ fetched = FALSE;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (delta_x)
|
|
+ *delta_x = dx;
|
|
+
|
|
+ if (delta_y)
|
|
+ *delta_y = dy;
|
|
+
|
|
+ return fetched;
|
|
+}
|
|
+
|
|
/**
|
|
* gdk_event_get_axis:
|
|
* @event: a #GdkEvent
|
|
diff --git a/gdk/gdkevents.h b/gdk/gdkevents.h
|
|
index 0602bd0..f6b4e04 100644
|
|
--- a/gdk/gdkevents.h
|
|
+++ b/gdk/gdkevents.h
|
|
@@ -337,6 +337,9 @@ struct _GdkEventScroll
|
|
GdkScrollDirection direction;
|
|
GdkDevice *device;
|
|
gdouble x_root, y_root;
|
|
+ gboolean has_deltas;
|
|
+ gdouble delta_x;
|
|
+ gdouble delta_y;
|
|
};
|
|
|
|
struct _GdkEventKey
|
|
@@ -537,6 +540,9 @@ gboolean gdk_event_get_coords (const GdkEvent *event,
|
|
gboolean gdk_event_get_root_coords (const GdkEvent *event,
|
|
gdouble *x_root,
|
|
gdouble *y_root);
|
|
+gboolean gdk_event_get_scroll_deltas (const GdkEvent *event,
|
|
+ gdouble *delta_x,
|
|
+ gdouble *delta_y);
|
|
gboolean gdk_event_get_axis (const GdkEvent *event,
|
|
GdkAxisUse axis_use,
|
|
gdouble *value);
|
|
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
|
|
index f5f0339..d48751e 100644
|
|
--- a/gdk/gdkwindow.c
|
|
+++ b/gdk/gdkwindow.c
|
|
@@ -10800,6 +10800,9 @@ proxy_button_event (GdkEvent *source_event,
|
|
event->scroll.y_root = source_event->scroll.y_root;
|
|
event->scroll.state = state;
|
|
event->scroll.device = source_event->scroll.device;
|
|
+ event->scroll.has_deltas = source_event->scroll.has_deltas;
|
|
+ event->scroll.delta_x = source_event->scroll.delta_x;
|
|
+ event->scroll.delta_y = source_event->scroll.delta_y;
|
|
return TRUE;
|
|
|
|
default:
|
|
diff --git a/gdk/quartz/gdkevents-quartz.c b/gdk/quartz/gdkevents-quartz.c
|
|
index c99a2c9..e7d97dc 100644
|
|
--- a/gdk/quartz/gdkevents-quartz.c
|
|
+++ b/gdk/quartz/gdkevents-quartz.c
|
|
@@ -57,6 +57,13 @@ static GdkWindow *find_toplevel_under_pointer (GdkDisplay *display,
|
|
gint *x,
|
|
gint *y);
|
|
|
|
+/* Protocol to build cleanly for OSX < 10.7 */
|
|
+@protocol PreciseDeltas
|
|
+- (BOOL) hasPreciseScrollingDeltas;
|
|
+- (CGFloat) scrollingDeltaX;
|
|
+- (CGFloat) scrollingDeltaY;
|
|
+@end
|
|
+
|
|
|
|
NSEvent *
|
|
gdk_quartz_event_get_nsevent (GdkEvent *event)
|
|
@@ -980,6 +987,9 @@ fill_scroll_event (GdkWindow *window,
|
|
gint y,
|
|
gint x_root,
|
|
gint y_root,
|
|
+ gboolean has_deltas,
|
|
+ gdouble delta_x,
|
|
+ gdouble delta_y,
|
|
GdkScrollDirection direction)
|
|
{
|
|
GdkWindowObject *private;
|
|
@@ -999,6 +1009,9 @@ fill_scroll_event (GdkWindow *window,
|
|
event->scroll.state = get_keyboard_modifiers_from_ns_event (nsevent);
|
|
event->scroll.direction = direction;
|
|
event->scroll.device = _gdk_display->core_pointer;
|
|
+ event->scroll.has_deltas = has_deltas;
|
|
+ event->scroll.delta_x = delta_x;
|
|
+ event->scroll.delta_y = delta_y;
|
|
}
|
|
|
|
static void
|
|
@@ -1471,28 +1484,59 @@ gdk_event_translate (GdkEvent *event,
|
|
|
|
case NSScrollWheel:
|
|
{
|
|
- float dx = [nsevent deltaX];
|
|
- float dy = [nsevent deltaY];
|
|
- GdkScrollDirection direction;
|
|
-
|
|
- if (dy != 0)
|
|
- {
|
|
- if (dy < 0.0)
|
|
- direction = GDK_SCROLL_DOWN;
|
|
- else
|
|
- direction = GDK_SCROLL_UP;
|
|
+ GdkScrollDirection direction;
|
|
+ float dx;
|
|
+ float dy;
|
|
|
|
- fill_scroll_event (window, event, nsevent, x, y, x_root, y_root, direction);
|
|
- }
|
|
+ if (gdk_quartz_osx_version() >= GDK_OSX_LION &&
|
|
+ [(id <PreciseDeltas>) nsevent hasPreciseScrollingDeltas])
|
|
+ {
|
|
+ dx = [(id <PreciseDeltas>) nsevent scrollingDeltaX];
|
|
+ dy = [(id <PreciseDeltas>) nsevent scrollingDeltaY];
|
|
|
|
- if (dx != 0)
|
|
- {
|
|
- if (dx < 0.0)
|
|
- direction = GDK_SCROLL_RIGHT;
|
|
+ if (fabs (dy) > fabs (dx))
|
|
+ {
|
|
+ if (dy < 0.0)
|
|
+ direction = GDK_SCROLL_DOWN;
|
|
+ else
|
|
+ direction = GDK_SCROLL_UP;
|
|
+ }
|
|
else
|
|
- direction = GDK_SCROLL_LEFT;
|
|
+ {
|
|
+ if (dx < 0.0)
|
|
+ direction = GDK_SCROLL_RIGHT;
|
|
+ else
|
|
+ direction = GDK_SCROLL_LEFT;
|
|
+ }
|
|
|
|
- fill_scroll_event (window, event, nsevent, x, y, x_root, y_root, direction);
|
|
+ fill_scroll_event (window, event, nsevent, x, y, x_root, y_root,
|
|
+ TRUE, -dx, -dy, direction);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ dx = [nsevent deltaX];
|
|
+ dy = [nsevent deltaY];
|
|
+
|
|
+ if (dy != 0.0)
|
|
+ {
|
|
+ if (dy < 0.0)
|
|
+ direction = GDK_SCROLL_DOWN;
|
|
+ else
|
|
+ direction = GDK_SCROLL_UP;
|
|
+
|
|
+ fill_scroll_event (window, event, nsevent, x, y, x_root, y_root,
|
|
+ FALSE, 0.0, fabs (dy), direction);
|
|
+ }
|
|
+ else if (dx != 0.0)
|
|
+ {
|
|
+ if (dx < 0.0)
|
|
+ direction = GDK_SCROLL_RIGHT;
|
|
+ else
|
|
+ direction = GDK_SCROLL_LEFT;
|
|
+
|
|
+ fill_scroll_event (window, event, nsevent, x, y, x_root, y_root,
|
|
+ FALSE, fabs (dx), 0.0, direction);
|
|
+ }
|
|
}
|
|
}
|
|
break;
|
|
diff --git a/gtk/gtkrange.c b/gtk/gtkrange.c
|
|
index 245fbf6..d39f045 100644
|
|
--- a/gtk/gtkrange.c
|
|
+++ b/gtk/gtkrange.c
|
|
@@ -2561,7 +2561,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.
|
|
*
|
|
@@ -2570,27 +2570,52 @@ 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)
|
|
{
|
|
GtkAdjustment *adj = range->adjustment;
|
|
+ gdouble dx, dy;
|
|
gdouble delta;
|
|
|
|
- if (GTK_IS_SCROLLBAR (range))
|
|
- delta = pow (adj->page_size, 2.0 / 3.0);
|
|
+ if (gdk_event_get_scroll_deltas ((GdkEvent *) event, &dx, &dy))
|
|
+ {
|
|
+ GtkAllocation allocation;
|
|
+
|
|
+ gtk_widget_get_allocation (GTK_WIDGET (range), &allocation);
|
|
+
|
|
+ if (gtk_orientable_get_orientation (GTK_ORIENTABLE (range)) == GTK_ORIENTATION_HORIZONTAL)
|
|
+ {
|
|
+ if (GTK_IS_SCROLLBAR (range) && adj->page_size > 0)
|
|
+ delta = dx * adj->page_size / allocation.width;
|
|
+ else
|
|
+ delta = dx * (adj->upper - adj->lower) / allocation.width;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (GTK_IS_SCROLLBAR (range) && adj->page_size > 0)
|
|
+ delta = dy * adj->page_size / allocation.height;
|
|
+ else
|
|
+ delta = dy * (adj->upper - adj->lower) / allocation.height;
|
|
+ }
|
|
+ }
|
|
else
|
|
- delta = adj->step_increment * 2;
|
|
-
|
|
- if (direction == GDK_SCROLL_UP ||
|
|
- direction == GDK_SCROLL_LEFT)
|
|
- delta = - delta;
|
|
-
|
|
+ {
|
|
+ if (GTK_IS_SCROLLBAR (range))
|
|
+ delta = pow (adj->page_size, 2.0 / 3.0);
|
|
+ else
|
|
+ delta = adj->step_increment * 2;
|
|
+
|
|
+ if (event->direction == GDK_SCROLL_UP ||
|
|
+ event->direction == GDK_SCROLL_LEFT)
|
|
+ delta = - delta;
|
|
+ }
|
|
+
|
|
if (range->inverted)
|
|
delta = - delta;
|
|
|
|
return delta;
|
|
}
|
|
-
|
|
+
|
|
static gboolean
|
|
gtk_range_scroll_event (GtkWidget *widget,
|
|
GdkEventScroll *event)
|
|
@@ -2603,7 +2628,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, adj->value + delta,
|
|
diff --git a/gtk/gtkrange.h b/gtk/gtkrange.h
|
|
index 5463140..c672acb 100644
|
|
--- a/gtk/gtkrange.h
|
|
+++ b/gtk/gtkrange.h
|
|
@@ -199,8 +199,8 @@ 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_stop_values (GtkRange *range,
|
|
gdouble *values,
|
|
diff --git a/gtk/gtkscrolledwindow.c b/gtk/gtkscrolledwindow.c
|
|
index 1704d3c..2288b2f 100644
|
|
--- a/gtk/gtkscrolledwindow.c
|
|
+++ b/gtk/gtkscrolledwindow.c
|
|
@@ -1565,31 +1565,77 @@ static gboolean
|
|
gtk_scrolled_window_scroll_event (GtkWidget *widget,
|
|
GdkEventScroll *event)
|
|
{
|
|
- GtkWidget *range;
|
|
+ GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
|
|
+ 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);
|
|
|
|
- if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_DOWN)
|
|
- range = GTK_SCROLLED_WINDOW (widget)->vscrollbar;
|
|
- else
|
|
- range = GTK_SCROLLED_WINDOW (widget)->hscrollbar;
|
|
+ if (gdk_event_get_scroll_deltas ((GdkEvent *) event, &delta_x, &delta_y))
|
|
+ {
|
|
+ if (delta_x != 0.0 && scrolled_window->hscrollbar &&
|
|
+ gtk_widget_get_visible (scrolled_window->hscrollbar))
|
|
+ {
|
|
+ GtkAdjustment *adj;
|
|
+ gdouble new_value;
|
|
+
|
|
+ adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->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 && scrolled_window->vscrollbar &&
|
|
+ gtk_widget_get_visible (scrolled_window->vscrollbar))
|
|
+ {
|
|
+ GtkAdjustment *adj;
|
|
+ gdouble new_value;
|
|
+
|
|
+ adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->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));
|
|
|
|
- if (range && gtk_widget_get_visible (range))
|
|
+ gtk_adjustment_set_value (adj, new_value);
|
|
+
|
|
+ handled = TRUE;
|
|
+ }
|
|
+ }
|
|
+ else
|
|
{
|
|
- GtkAdjustment *adj = GTK_RANGE (range)->adjustment;
|
|
- gdouble delta, new_value;
|
|
+ GtkWidget *range;
|
|
|
|
- delta = _gtk_range_get_wheel_delta (GTK_RANGE (range), event->direction);
|
|
+ if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_DOWN)
|
|
+ range = scrolled_window->vscrollbar;
|
|
+ else
|
|
+ range = scrolled_window->hscrollbar;
|
|
|
|
- new_value = CLAMP (adj->value + delta, adj->lower, adj->upper - adj->page_size);
|
|
-
|
|
- gtk_adjustment_set_value (adj, new_value);
|
|
+ if (range && gtk_widget_get_visible (range))
|
|
+ {
|
|
+ GtkAdjustment *adj = GTK_RANGE (range)->adjustment;
|
|
+ gdouble delta, new_value;
|
|
|
|
- return TRUE;
|
|
+ delta = _gtk_range_get_wheel_delta (GTK_RANGE (range), event);
|
|
+
|
|
+ new_value = CLAMP (adj->value + delta, adj->lower, adj->upper - adj->page_size);
|
|
+
|
|
+ gtk_adjustment_set_value (adj, new_value);
|
|
+
|
|
+ handled = TRUE;
|
|
+ }
|
|
}
|
|
|
|
- return FALSE;
|
|
+ return handled;
|
|
}
|
|
|
|
static gboolean
|
|
--
|
|
1.7.10.2 (Apple Git-33)
|