Compare commits
5 Commits
async-colo
...
wip/scroll
Author | SHA1 | Date | |
---|---|---|---|
|
880fcf199a | ||
|
ebfc5814f0 | ||
|
69c0de7938 | ||
|
59482c41df | ||
|
479935f441 |
@@ -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
|
||||
|
||||
@@ -174,6 +174,7 @@ typedef struct
|
||||
gint64 start_time;
|
||||
gint64 end_time;
|
||||
guint tick_id;
|
||||
guint over_timeout_id;
|
||||
} Indicator;
|
||||
|
||||
struct _GtkScrolledWindowPrivate
|
||||
@@ -339,6 +340,10 @@ 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 void indicator_set_over (Indicator *indicator,
|
||||
gboolean over);
|
||||
|
||||
|
||||
static guint signals[LAST_SIGNAL] = {0};
|
||||
@@ -377,6 +382,20 @@ add_tab_bindings (GtkBindingSet *binding_set,
|
||||
GTK_TYPE_DIRECTION_TYPE, direction);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_scrolled_window_leave_notify (GtkWidget *widget,
|
||||
GdkEventCrossing *event)
|
||||
{
|
||||
GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW (widget)->priv;
|
||||
|
||||
indicator_set_over (&priv->hindicator, FALSE);
|
||||
indicator_start_fade (&priv->hindicator, 0.0);
|
||||
indicator_set_over (&priv->vindicator, FALSE);
|
||||
indicator_start_fade (&priv->vindicator, 0.0);
|
||||
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_scrolled_window_class_init (GtkScrolledWindowClass *class)
|
||||
{
|
||||
@@ -405,6 +424,7 @@ gtk_scrolled_window_class_init (GtkScrolledWindowClass *class)
|
||||
widget_class->grab_notify = gtk_scrolled_window_grab_notify;
|
||||
widget_class->realize = gtk_scrolled_window_realize;
|
||||
widget_class->unrealize = gtk_scrolled_window_unrealize;
|
||||
widget_class->leave_notify_event = gtk_scrolled_window_leave_notify;
|
||||
|
||||
container_class->add = gtk_scrolled_window_add;
|
||||
container_class->remove = gtk_scrolled_window_remove;
|
||||
@@ -906,6 +926,163 @@ gtk_scrolled_window_check_attach_pan_gesture (GtkScrolledWindow *sw)
|
||||
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (priv->pan_gesture), phase);
|
||||
}
|
||||
|
||||
static void
|
||||
indicator_set_over (Indicator *indicator,
|
||||
gboolean over)
|
||||
{
|
||||
GtkStyleContext *context;
|
||||
|
||||
if (indicator->over_timeout_id)
|
||||
{
|
||||
g_source_remove (indicator->over_timeout_id);
|
||||
indicator->over_timeout_id = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
GtkScrolledWindowPrivate *priv;
|
||||
GtkWidget *event_widget;
|
||||
gint win_x, win_y;
|
||||
gdouble x, y;
|
||||
|
||||
priv = sw->priv;
|
||||
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 ((indicator == &priv->hindicator &&
|
||||
y >= win_y - 50 &&
|
||||
y < win_y + indicator_alloc.height + 50) ||
|
||||
(indicator == &priv->vindicator &&
|
||||
x >= win_x - 50 &&
|
||||
x < win_x + indicator_alloc.width + 50))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
enable_over_timeout_cb (gpointer user_data)
|
||||
{
|
||||
Indicator *indicator = user_data;
|
||||
|
||||
indicator_set_over (indicator, TRUE);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_update_scrollbar_proximity (GtkScrolledWindow *sw,
|
||||
Indicator *indicator,
|
||||
GdkEvent *event)
|
||||
{
|
||||
gboolean indicator_close;
|
||||
|
||||
indicator_close = event_close_to_indicator (sw, indicator, event);
|
||||
|
||||
if (indicator->over_timeout_id)
|
||||
{
|
||||
g_source_remove (indicator->over_timeout_id);
|
||||
indicator->over_timeout_id = 0;
|
||||
}
|
||||
|
||||
if (indicator_close)
|
||||
indicator->over_timeout_id = gdk_threads_add_timeout (30, enable_over_timeout_cb, indicator);
|
||||
else
|
||||
indicator_set_over (indicator, FALSE);
|
||||
|
||||
return indicator_close;
|
||||
}
|
||||
|
||||
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 vertical scrollbar */
|
||||
indicator_close = check_update_scrollbar_proximity (sw, &priv->vindicator,
|
||||
event);
|
||||
|
||||
if (!indicator_close)
|
||||
{
|
||||
/* Otherwise check the vertical scrollbar */
|
||||
check_update_scrollbar_proximity (sw, &priv->hindicator, event);
|
||||
}
|
||||
else
|
||||
indicator_set_over (&priv->hindicator, FALSE);
|
||||
}
|
||||
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)
|
||||
check_update_scrollbar_proximity (sw, &priv->hindicator, event);
|
||||
else if (scrollbar == priv->vindicator.scrollbar)
|
||||
check_update_scrollbar_proximity (sw, &priv->vindicator, event);
|
||||
}
|
||||
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window)
|
||||
{
|
||||
@@ -915,7 +1092,7 @@ gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window)
|
||||
scrolled_window->priv = priv =
|
||||
gtk_scrolled_window_get_instance_private (scrolled_window);
|
||||
|
||||
gtk_widget_set_has_window (widget, FALSE);
|
||||
gtk_widget_set_has_window (widget, TRUE);
|
||||
gtk_widget_set_can_focus (widget, TRUE);
|
||||
|
||||
/* Instantiated by gtk_scrolled_window_set_[hv]adjustment
|
||||
@@ -968,6 +1145,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2168,8 +2347,8 @@ gtk_scrolled_window_allocate_child (GtkScrolledWindow *swindow,
|
||||
|
||||
gtk_scrolled_window_relative_allocation (widget, relative_allocation);
|
||||
|
||||
child_allocation.x = relative_allocation->x + allocation.x;
|
||||
child_allocation.y = relative_allocation->y + allocation.y;
|
||||
child_allocation.x = relative_allocation->x;
|
||||
child_allocation.y = relative_allocation->y;
|
||||
child_allocation.width = relative_allocation->width;
|
||||
child_allocation.height = relative_allocation->height;
|
||||
|
||||
@@ -2198,6 +2377,13 @@ gtk_scrolled_window_size_allocate (GtkWidget *widget,
|
||||
bin = GTK_BIN (scrolled_window);
|
||||
priv = scrolled_window->priv;
|
||||
|
||||
if (gtk_widget_get_realized (widget))
|
||||
{
|
||||
gdk_window_move_resize (gtk_widget_get_window (widget),
|
||||
allocation->x, allocation->y,
|
||||
allocation->width, allocation->height);
|
||||
}
|
||||
|
||||
/* Get possible scrollbar dimensions */
|
||||
sb_spacing = _gtk_scrolled_window_get_scrollbar_spacing (scrolled_window);
|
||||
gtk_widget_get_preferred_height (priv->hscrollbar, &sb_height, NULL);
|
||||
@@ -2445,8 +2631,6 @@ gtk_scrolled_window_size_allocate (GtkWidget *widget,
|
||||
|
||||
child_allocation.width = relative_allocation.width;
|
||||
child_allocation.height = sb_height;
|
||||
child_allocation.x += allocation->x;
|
||||
child_allocation.y += allocation->y;
|
||||
|
||||
if (priv->shadow_type != GTK_SHADOW_NONE)
|
||||
{
|
||||
@@ -2502,8 +2686,6 @@ gtk_scrolled_window_size_allocate (GtkWidget *widget,
|
||||
child_allocation.y = relative_allocation.y;
|
||||
child_allocation.width = sb_width;
|
||||
child_allocation.height = relative_allocation.height;
|
||||
child_allocation.x += allocation->x;
|
||||
child_allocation.y += allocation->y;
|
||||
|
||||
if (priv->shadow_type != GTK_SHADOW_NONE)
|
||||
{
|
||||
@@ -3470,6 +3652,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 +3701,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 +3737,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 +3764,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;
|
||||
|
||||
@@ -3625,6 +3773,12 @@ remove_indicator (GtkScrolledWindow *scrolled_window,
|
||||
indicator->conceil_timer = 0;
|
||||
}
|
||||
|
||||
if (indicator->over_timeout_id)
|
||||
{
|
||||
g_source_remove (indicator->over_timeout_id);
|
||||
indicator->over_timeout_id = 0;
|
||||
}
|
||||
|
||||
if (indicator->tick_id)
|
||||
{
|
||||
gtk_widget_remove_tick_callback (scrollbar, indicator->tick_id);
|
||||
@@ -3747,8 +3901,31 @@ gtk_scrolled_window_realize (GtkWidget *widget)
|
||||
GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
|
||||
GtkScrolledWindowPrivate *priv = scrolled_window->priv;
|
||||
GdkDeviceManager *dm;
|
||||
GdkWindow *window;
|
||||
GtkAllocation allocation;
|
||||
GdkWindowAttr attributes;
|
||||
gint attributes_mask;
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_scrolled_window_parent_class)->realize (widget);
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
attributes.window_type = GDK_WINDOW_CHILD;
|
||||
attributes.wclass = GDK_INPUT_OUTPUT;
|
||||
|
||||
attributes.width = allocation.width;
|
||||
attributes.height = allocation.height;
|
||||
attributes.x = allocation.x;
|
||||
attributes.y = allocation.y;
|
||||
attributes.visual = gtk_widget_get_visual (widget);
|
||||
attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
|
||||
attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK |
|
||||
GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK;
|
||||
|
||||
window = gdk_window_new (gtk_widget_get_parent_window (widget),
|
||||
&attributes, attributes_mask);
|
||||
|
||||
gtk_widget_set_window (widget, window);
|
||||
gtk_widget_register_window (widget, window);
|
||||
gtk_widget_set_realized (widget, TRUE);
|
||||
|
||||
priv->hindicator.window = create_indicator_window (scrolled_window, priv->hscrollbar);
|
||||
priv->vindicator.window = create_indicator_window (scrolled_window, priv->vscrollbar);
|
||||
|
Reference in New Issue
Block a user