mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-14 04:31:09 +00:00
gtkscrolledwindow: Use controller for motion capturing
Perform scrollbar visibility checks through a motion controller, always based on GtkScrolledView-relative coordinates. The captured event handler remains though, for a tiny bit of GDK_SCROLL event handling.
This commit is contained in:
parent
f15224926a
commit
71762d3b28
@ -1052,17 +1052,16 @@ indicator_set_over (Indicator *indicator,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
event_close_to_indicator (GtkScrolledWindow *sw,
|
||||
Indicator *indicator,
|
||||
GdkEvent *event)
|
||||
coords_close_to_indicator (GtkScrolledWindow *sw,
|
||||
Indicator *indicator,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
GtkScrolledWindowPrivate *priv = gtk_scrolled_window_get_instance_private (sw);
|
||||
graphene_rect_t indicator_bounds;
|
||||
gdouble x, y;
|
||||
gint distance;
|
||||
|
||||
gtk_widget_compute_bounds (indicator->scrollbar, GTK_WIDGET (sw), &indicator_bounds);
|
||||
gdk_event_get_coords (event, &x, &y);
|
||||
|
||||
if (indicator->over)
|
||||
distance = INDICATOR_FAR_DISTANCE;
|
||||
@ -1099,25 +1098,18 @@ enable_over_timeout_cb (gpointer user_data)
|
||||
static gboolean
|
||||
check_update_scrollbar_proximity (GtkScrolledWindow *sw,
|
||||
Indicator *indicator,
|
||||
GdkEvent *event)
|
||||
GtkWidget *target,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
GtkScrolledWindowPrivate *priv = gtk_scrolled_window_get_instance_private (sw);
|
||||
gboolean indicator_close, on_scrollbar, on_other_scrollbar;
|
||||
GtkWidget *event_target;
|
||||
GtkWidget *event_target_ancestor;
|
||||
GdkEventType event_type;
|
||||
|
||||
event_target = gtk_get_event_target (event);
|
||||
event_target_ancestor = gtk_widget_get_ancestor (event_target, GTK_TYPE_SCROLLBAR);
|
||||
event_type = gdk_event_get_event_type (event);
|
||||
|
||||
indicator_close = event_close_to_indicator (sw, indicator, event);
|
||||
on_scrollbar = (event_target_ancestor == indicator->scrollbar &&
|
||||
event_type != GDK_LEAVE_NOTIFY);
|
||||
indicator_close = coords_close_to_indicator (sw, indicator, x, y);
|
||||
on_scrollbar = (target == indicator->scrollbar);
|
||||
on_other_scrollbar = (!on_scrollbar &&
|
||||
event_type != GDK_LEAVE_NOTIFY &&
|
||||
(event_target_ancestor == priv->hindicator.scrollbar ||
|
||||
event_target_ancestor == priv->vindicator.scrollbar));
|
||||
(target == priv->hindicator.scrollbar ||
|
||||
target == priv->vindicator.scrollbar));
|
||||
|
||||
if (indicator->over_timeout_id)
|
||||
{
|
||||
@ -1173,85 +1165,66 @@ captured_event_cb (GtkWidget *widget,
|
||||
GdkEvent *event)
|
||||
{
|
||||
GtkScrolledWindow *sw = GTK_SCROLLED_WINDOW (widget);
|
||||
GtkScrolledWindowPrivate *priv = gtk_scrolled_window_get_instance_private (sw);
|
||||
GdkInputSource input_source;
|
||||
GdkDevice *source_device;
|
||||
GtkWidget *event_target;
|
||||
GtkWidget *event_target_ancestor;
|
||||
gboolean on_scrollbar;
|
||||
GdkEventType event_type;
|
||||
guint state;
|
||||
GdkCrossingMode mode;
|
||||
|
||||
source_device = gdk_event_get_source_device (event);
|
||||
event_type = gdk_event_get_event_type (event);
|
||||
|
||||
if (event_type == GDK_SCROLL)
|
||||
{
|
||||
gtk_scrolled_window_cancel_deceleration (sw);
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
if (!priv->use_indicators)
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
|
||||
if (event_type != GDK_MOTION_NOTIFY &&
|
||||
event_type != GDK_LEAVE_NOTIFY)
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
|
||||
input_source = gdk_device_get_source (source_device);
|
||||
|
||||
if (input_source == GDK_SOURCE_KEYBOARD ||
|
||||
input_source == GDK_SOURCE_TOUCHSCREEN)
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
|
||||
event_target = gtk_get_event_target (event);
|
||||
event_target_ancestor = gtk_widget_get_ancestor (event_target, GTK_TYPE_SCROLLBAR);
|
||||
on_scrollbar = (event_target_ancestor == priv->hindicator.scrollbar ||
|
||||
event_target_ancestor == priv->vindicator.scrollbar);
|
||||
gdk_event_get_crossing_mode (event, &mode);
|
||||
|
||||
if (event_type == GDK_MOTION_NOTIFY)
|
||||
{
|
||||
if (priv->hscrollbar_visible)
|
||||
indicator_start_fade (&priv->hindicator, 1.0);
|
||||
if (priv->vscrollbar_visible)
|
||||
indicator_start_fade (&priv->vindicator, 1.0);
|
||||
|
||||
gdk_event_get_state (event, &state);
|
||||
|
||||
if (!on_scrollbar &&
|
||||
(state &
|
||||
(GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) != 0)
|
||||
{
|
||||
indicator_set_over (&priv->hindicator, FALSE);
|
||||
indicator_set_over (&priv->vindicator, FALSE);
|
||||
}
|
||||
else if (input_source == GDK_SOURCE_PEN ||
|
||||
input_source == GDK_SOURCE_ERASER ||
|
||||
input_source == GDK_SOURCE_TRACKPOINT)
|
||||
{
|
||||
indicator_set_over (&priv->hindicator, TRUE);
|
||||
indicator_set_over (&priv->vindicator, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!check_update_scrollbar_proximity (sw, &priv->vindicator, event))
|
||||
check_update_scrollbar_proximity (sw, &priv->hindicator, event);
|
||||
else
|
||||
indicator_set_over (&priv->hindicator, FALSE);
|
||||
}
|
||||
}
|
||||
else if (event_type == GDK_LEAVE_NOTIFY && on_scrollbar &&
|
||||
mode == GDK_CROSSING_UNGRAB)
|
||||
{
|
||||
check_update_scrollbar_proximity (sw, &priv->vindicator, event);
|
||||
check_update_scrollbar_proximity (sw, &priv->hindicator, event);
|
||||
}
|
||||
if (gdk_event_get_event_type (event) == GDK_SCROLL)
|
||||
gtk_scrolled_window_cancel_deceleration (sw);
|
||||
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
static void
|
||||
captured_motion (GtkScrolledWindow *sw,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
GtkScrolledWindowPrivate *priv = gtk_scrolled_window_get_instance_private (sw);
|
||||
GdkDevice *source_device;
|
||||
GdkInputSource input_source;
|
||||
GdkModifierType state;
|
||||
GdkEvent *event;
|
||||
|
||||
if (!priv->use_indicators)
|
||||
return;
|
||||
|
||||
event = gtk_get_current_event ();
|
||||
source_device = gdk_event_get_source_device (event);
|
||||
input_source = gdk_device_get_source (source_device);
|
||||
|
||||
if (priv->hscrollbar_visible)
|
||||
indicator_start_fade (&priv->hindicator, 1.0);
|
||||
if (priv->vscrollbar_visible)
|
||||
indicator_start_fade (&priv->vindicator, 1.0);
|
||||
|
||||
gdk_event_get_state (event, &state);
|
||||
|
||||
if (!gtk_get_event_target_with_type (event, GTK_TYPE_SCROLLBAR) &&
|
||||
(state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) != 0)
|
||||
{
|
||||
indicator_set_over (&priv->hindicator, FALSE);
|
||||
indicator_set_over (&priv->vindicator, FALSE);
|
||||
}
|
||||
else if (input_source == GDK_SOURCE_PEN ||
|
||||
input_source == GDK_SOURCE_ERASER ||
|
||||
input_source == GDK_SOURCE_TRACKPOINT)
|
||||
{
|
||||
indicator_set_over (&priv->hindicator, TRUE);
|
||||
indicator_set_over (&priv->vindicator, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkWidget *target;
|
||||
|
||||
target = gtk_get_event_target_with_type (event, GTK_TYPE_SCROLLBAR);
|
||||
|
||||
if (!check_update_scrollbar_proximity (sw, &priv->vindicator, target, x, y))
|
||||
check_update_scrollbar_proximity (sw, &priv->hindicator, target, x, y);
|
||||
else
|
||||
indicator_set_over (&priv->hindicator, FALSE);
|
||||
}
|
||||
|
||||
g_object_unref (event);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
start_scroll_deceleration_cb (gpointer user_data)
|
||||
{
|
||||
@ -1978,6 +1951,12 @@ gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window)
|
||||
|
||||
_gtk_widget_set_captured_event_handler (widget, captured_event_cb);
|
||||
|
||||
controller = gtk_event_controller_motion_new ();
|
||||
gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_CAPTURE);
|
||||
g_signal_connect_swapped (controller, "motion",
|
||||
G_CALLBACK (captured_motion), scrolled_window);
|
||||
gtk_widget_add_controller (widget, controller);
|
||||
|
||||
widget_node = gtk_widget_get_css_node (widget);
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user