summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2014-11-29 16:53:05 +0100
committerCarlos Garnacho <carlosg@gnome.org>2014-11-29 17:00:33 +0100
commit479935f441e1e7964d87ead753267477eb78a041 (patch)
tree00c2981e2916009b8f585338b75eff98f55951d5
parentf85093a13695f21ade5e3a6c1bc2d71eee4629c3 (diff)
downloadgtk+-479935f441e1e7964d87ead753267477eb78a041.tar.gz
scrolledwindow: Show scrollbars upon captured motion events
On mice, scrollbars are always triggered temporarily. On proximity to an scrollbar, it will be switched to full-width.
-rw-r--r--gtk/gtkscrolledwindow.c168
1 files changed, 129 insertions, 39 deletions
diff --git a/gtk/gtkscrolledwindow.c b/gtk/gtkscrolledwindow.c
index 86a53d75fb..4dadbadcc4 100644
--- a/gtk/gtkscrolledwindow.c
+++ b/gtk/gtkscrolledwindow.c
@@ -154,7 +154,7 @@
#define ANIMATION_DURATION 200
/* Overlay scrollbars */
-#define INDICATOR_FADE_OUT_DELAY 1000
+#define INDICATOR_FADE_OUT_DELAY 2000
#define INDICATOR_FADE_OUT_DURATION 1000
#define INDICATOR_FADE_OUT_TIME 500
@@ -339,7 +339,8 @@ static void remove_indicator (GtkScrolledWindow *sw,
static void indicator_stop_fade (Indicator *indicator);
static gboolean maybe_hide_indicator (gpointer data);
-
+static void indicator_start_fade (Indicator *indicator,
+ gdouble pos);
static guint signals[LAST_SIGNAL] = {0};
@@ -907,6 +908,127 @@ gtk_scrolled_window_check_attach_pan_gesture (GtkScrolledWindow *sw)
}
static void
+indicator_set_over (Indicator *indicator,
+ gboolean over)
+{
+ GtkStyleContext *context;
+
+ if (indicator->over == over)
+ return;
+
+ context = gtk_widget_get_style_context (indicator->scrollbar);
+ indicator->over = over;
+
+ if (indicator->over)
+ gtk_style_context_add_class (context, "hovering");
+ else
+ gtk_style_context_remove_class (context, "hovering");
+
+ gtk_widget_queue_resize (indicator->scrollbar);
+}
+
+static gboolean
+event_close_to_indicator (GtkScrolledWindow *sw,
+ Indicator *indicator,
+ GdkEvent *event)
+{
+ GtkAllocation alloc, indicator_alloc;
+ GtkWidget *event_widget;
+ gint win_x, win_y;
+ gdouble x, y;
+
+ event_widget = gtk_get_event_widget (event);
+ gdk_event_get_coords (event, &x, &y);
+
+ gtk_widget_get_allocation (GTK_WIDGET (sw), &alloc);
+ gtk_widget_get_allocation (indicator->scrollbar, &indicator_alloc);
+ gdk_window_get_position (indicator->window, &win_x, &win_y);
+
+ if (event->any.window == indicator->window ||
+ event_widget == indicator->scrollbar)
+ {
+ gint xcoord = x, ycoord = y;
+
+ gtk_widget_translate_coordinates (indicator->scrollbar,
+ GTK_WIDGET (sw),
+ xcoord, ycoord,
+ &xcoord, &ycoord);
+ x = xcoord;
+ y = ycoord;
+ }
+
+ if (x < 0 || x > alloc.width ||
+ y < 0 || y > alloc.height)
+ return FALSE;
+
+ if (x > win_x - alloc.x - 50 &&
+ x < win_x - alloc.x + indicator_alloc.width + 50 &&
+ y > win_y - alloc.y - 50 &&
+ y < win_y - alloc.y + indicator_alloc.height + 50)
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean
+captured_event_cb (GtkWidget *widget,
+ GdkEvent *event)
+{
+ GtkScrolledWindowPrivate *priv;
+ GtkScrolledWindow *sw;
+ GdkInputSource input_source;
+ GdkDevice *source_device;
+ gboolean indicator_close;
+
+ if (event->type != GDK_MOTION_NOTIFY &&
+ event->type != GDK_LEAVE_NOTIFY)
+ return GDK_EVENT_PROPAGATE;
+
+ sw = GTK_SCROLLED_WINDOW (widget);
+ priv = sw->priv;
+ source_device = gdk_event_get_source_device (event);
+ input_source = gdk_device_get_source (source_device);
+
+ if (input_source != GDK_SOURCE_MOUSE &&
+ input_source != GDK_SOURCE_TOUCHPAD)
+ return GDK_EVENT_PROPAGATE;
+
+ if (event->type == GDK_MOTION_NOTIFY)
+ {
+ indicator_start_fade (&priv->hindicator, 1.0);
+ indicator_start_fade (&priv->vindicator, 1.0);
+
+ /* Check whether we're hovering close to the horizontal scrollbar */
+ indicator_close = event_close_to_indicator (sw, &priv->hindicator, event);
+ indicator_set_over (&priv->hindicator, indicator_close);
+
+ /* Same for the vertical scrollbar */
+ indicator_close = event_close_to_indicator (sw, &priv->vindicator, event);
+ indicator_set_over (&priv->vindicator, indicator_close);
+ }
+ else if (event->type == GDK_LEAVE_NOTIFY &&
+ event->crossing.mode == GDK_CROSSING_UNGRAB)
+ {
+ GtkWidget *scrollbar;
+
+ scrollbar = gtk_get_event_widget (event);
+
+ if (scrollbar == priv->hindicator.scrollbar)
+ {
+ indicator_close = event_close_to_indicator (sw, &priv->hindicator, event);
+ indicator_set_over (&priv->hindicator, indicator_close);
+ }
+ else if (scrollbar == priv->vindicator.scrollbar)
+ {
+ indicator_close = event_close_to_indicator (sw, &priv->vindicator, event);
+ indicator_set_over (&priv->vindicator, indicator_close);
+ }
+ }
+
+ return GDK_EVENT_PROPAGATE;
+}
+
+static void
gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window)
{
GtkWidget *widget = GTK_WIDGET (scrolled_window);
@@ -968,6 +1090,8 @@ gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window)
gtk_scrolled_window_set_kinetic_scrolling (scrolled_window, TRUE);
gtk_scrolled_window_set_capture_button_press (scrolled_window, TRUE);
+
+ _gtk_widget_set_captured_event_handler (widget, captured_event_cb);
}
/**
@@ -3470,6 +3594,9 @@ indicator_start_fade (Indicator *indicator,
"gtk-enable-animations", &animations_enabled,
NULL);
+ if (target != 0.0)
+ indicator->last_scroll_time = g_get_monotonic_time ();
+
if (gtk_widget_get_mapped (indicator->scrollbar) && animations_enabled)
{
indicator->source_pos = indicator->current_pos;
@@ -3516,37 +3643,6 @@ indicator_value_changed (GtkAdjustment *adjustment,
indicator_start_fade (indicator, 1.0);
}
-static gboolean
-indicator_enter_notify (GtkWidget *scrollbar,
- GdkEventCrossing *event,
- Indicator *indicator)
-{
- GtkStyleContext *context;
-
- context = gtk_widget_get_style_context (scrollbar);
- gtk_style_context_add_class (context, "hovering");
- gtk_widget_queue_resize (scrollbar);
- indicator->over = TRUE;
- indicator_start_fade (indicator, 1.0);
-
- return G_SOURCE_CONTINUE;
-}
-
-static gboolean
-indicator_leave_notify (GtkWidget *scrollbar,
- GdkEventCrossing *event,
- Indicator *indicator)
-{
- GtkStyleContext *context;
-
- context = gtk_widget_get_style_context (scrollbar);
- gtk_style_context_remove_class (context, "hovering");
- gtk_widget_queue_resize (scrollbar);
- indicator->over = FALSE;
-
- return G_SOURCE_CONTINUE;
-}
-
static void
indicator_style_changed (GtkStyleContext *context,
Indicator *indicator)
@@ -3583,10 +3679,6 @@ setup_indicator (GtkScrolledWindow *scrolled_window,
gtk_style_context_add_class (context, "overlay-indicator");
g_signal_connect (context, "changed",
G_CALLBACK (indicator_style_changed), indicator);
- g_signal_connect (scrollbar, "enter-notify-event",
- G_CALLBACK (indicator_enter_notify), indicator);
- g_signal_connect (scrollbar, "leave-notify-event",
- G_CALLBACK (indicator_leave_notify), indicator);
g_signal_connect (adjustment, "value-changed",
G_CALLBACK (indicator_value_changed), indicator);
@@ -3614,8 +3706,6 @@ remove_indicator (GtkScrolledWindow *scrolled_window,
gtk_style_context_remove_class (context, "overlay-indicator");
g_signal_handlers_disconnect_by_func (context, indicator_style_changed, indicator);
- g_signal_handlers_disconnect_by_func (scrollbar, indicator_enter_notify, indicator);
- g_signal_handlers_disconnect_by_func (scrollbar, indicator_leave_notify, indicator);
g_signal_handlers_disconnect_by_func (adjustment, indicator_value_changed, indicator);
indicator->enabled = FALSE;