gtk,scrolledwindow: Clamp early overshooting when snapping back
Fixes the situation where overshooting in scrolled windows with a small viewport could end up overshooting right to the opposite side, and then back again indefinitely.
This commit is contained in:
@@ -286,7 +286,8 @@ static void gtk_scrolled_window_auto_hide_scrollbars_stop (GtkScrolledWindo
|
||||
static gboolean _gtk_scrolled_window_set_adjustment_value (GtkScrolledWindow *scrolled_window,
|
||||
GtkAdjustment *adjustment,
|
||||
gdouble value,
|
||||
gboolean allow_overshooting);
|
||||
gboolean allow_overshooting,
|
||||
gboolean snap_to_border);
|
||||
|
||||
static guint signals[LAST_SIGNAL] = {0};
|
||||
|
||||
@@ -2276,37 +2277,41 @@ static gboolean
|
||||
_gtk_scrolled_window_set_adjustment_value (GtkScrolledWindow *scrolled_window,
|
||||
GtkAdjustment *adjustment,
|
||||
gdouble value,
|
||||
gboolean allow_overshooting)
|
||||
gboolean allow_overshooting,
|
||||
gboolean snap_to_border)
|
||||
{
|
||||
GtkScrolledWindowPrivate *priv = scrolled_window->priv;
|
||||
gdouble lower, upper;
|
||||
gdouble lower, upper, *prev_value;
|
||||
|
||||
lower = gtk_adjustment_get_lower (adjustment);
|
||||
upper = gtk_adjustment_get_upper (adjustment) -
|
||||
gtk_adjustment_get_page_size (adjustment);
|
||||
|
||||
if (adjustment == gtk_range_get_adjustment (GTK_RANGE (priv->hscrollbar)))
|
||||
prev_value = &priv->unclamped_hadj_value;
|
||||
else if (adjustment == gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar)))
|
||||
prev_value = &priv->unclamped_vadj_value;
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
if (snap_to_border)
|
||||
{
|
||||
if (*prev_value < 0 && value > 0)
|
||||
value = 0;
|
||||
else if (*prev_value > upper && value < upper)
|
||||
value = upper;
|
||||
}
|
||||
|
||||
if (allow_overshooting)
|
||||
{
|
||||
lower -= MAX_OVERSHOOT_DISTANCE;
|
||||
upper += MAX_OVERSHOOT_DISTANCE;
|
||||
}
|
||||
|
||||
if (adjustment == gtk_range_get_adjustment (GTK_RANGE (priv->hscrollbar)))
|
||||
{
|
||||
priv->unclamped_hadj_value = CLAMP (value, lower, upper);
|
||||
gtk_adjustment_set_value (adjustment, value);
|
||||
*prev_value = CLAMP (value, lower, upper);
|
||||
gtk_adjustment_set_value (adjustment, value);
|
||||
|
||||
return (priv->unclamped_hadj_value != value);
|
||||
}
|
||||
else if (adjustment == gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar)))
|
||||
{
|
||||
priv->unclamped_vadj_value = CLAMP (value, lower, upper);
|
||||
gtk_adjustment_set_value (adjustment, value);
|
||||
|
||||
return (priv->unclamped_vadj_value != value);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return (*prev_value != value);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -2317,7 +2322,7 @@ scrolled_window_deceleration_cb (gpointer user_data)
|
||||
GtkScrolledWindowPrivate *priv = scrolled_window->priv;
|
||||
GtkAdjustment *hadjustment, *vadjustment;
|
||||
gint old_overshoot_x, old_overshoot_y, overshoot_x, overshoot_y;
|
||||
gdouble value, clamp_value;
|
||||
gdouble value;
|
||||
gint64 current_time;
|
||||
guint elapsed;
|
||||
|
||||
@@ -2337,7 +2342,7 @@ scrolled_window_deceleration_cb (gpointer user_data)
|
||||
|
||||
if (_gtk_scrolled_window_set_adjustment_value (scrolled_window,
|
||||
hadjustment,
|
||||
value, TRUE))
|
||||
value, TRUE, TRUE))
|
||||
data->x_velocity = 0;
|
||||
}
|
||||
else
|
||||
@@ -2349,7 +2354,7 @@ scrolled_window_deceleration_cb (gpointer user_data)
|
||||
|
||||
if (_gtk_scrolled_window_set_adjustment_value (scrolled_window,
|
||||
vadjustment,
|
||||
value, TRUE))
|
||||
value, TRUE, TRUE))
|
||||
data->y_velocity = 0;
|
||||
}
|
||||
else
|
||||
@@ -2362,17 +2367,7 @@ scrolled_window_deceleration_cb (gpointer user_data)
|
||||
{
|
||||
if (old_overshoot_x != 0)
|
||||
{
|
||||
/* Overshooting finished, clamp to border */
|
||||
clamp_value = (old_overshoot_x < 0) ?
|
||||
gtk_adjustment_get_lower (hadjustment) :
|
||||
gtk_adjustment_get_upper (hadjustment) -
|
||||
gtk_adjustment_get_page_size (hadjustment);
|
||||
|
||||
_gtk_scrolled_window_set_adjustment_value (scrolled_window,
|
||||
hadjustment,
|
||||
clamp_value,
|
||||
FALSE);
|
||||
|
||||
/* Overshooting finished snapping back */
|
||||
data->x_velocity = 0;
|
||||
}
|
||||
else if (data->x_velocity > 0)
|
||||
@@ -2395,16 +2390,7 @@ scrolled_window_deceleration_cb (gpointer user_data)
|
||||
{
|
||||
if (old_overshoot_y != 0)
|
||||
{
|
||||
/* Overshooting finished, clamp to border */
|
||||
clamp_value = (old_overshoot_y < 0) ?
|
||||
gtk_adjustment_get_lower (vadjustment) :
|
||||
gtk_adjustment_get_upper (vadjustment) -
|
||||
gtk_adjustment_get_page_size (vadjustment);
|
||||
|
||||
_gtk_scrolled_window_set_adjustment_value (scrolled_window,
|
||||
vadjustment,
|
||||
clamp_value,
|
||||
FALSE);
|
||||
/* Overshooting finished snapping back */
|
||||
data->y_velocity = 0;
|
||||
}
|
||||
else if (data->y_velocity > 0)
|
||||
@@ -2470,11 +2456,11 @@ gtk_scrolled_window_cancel_deceleration (GtkScrolledWindow *scrolled_window)
|
||||
_gtk_scrolled_window_set_adjustment_value (scrolled_window,
|
||||
vadjustment,
|
||||
gtk_adjustment_get_value (vadjustment),
|
||||
FALSE);
|
||||
FALSE, TRUE);
|
||||
_gtk_scrolled_window_set_adjustment_value (scrolled_window,
|
||||
hadjustment,
|
||||
gtk_adjustment_get_value (hadjustment),
|
||||
FALSE);
|
||||
FALSE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2675,14 +2661,16 @@ gtk_scrolled_window_motion_notify_event (GtkWidget *widget,
|
||||
if (hadjustment && priv->hscrollbar_visible)
|
||||
{
|
||||
dx = (priv->last_motion_event_x_root - event->x_root) + priv->unclamped_hadj_value;
|
||||
_gtk_scrolled_window_set_adjustment_value (scrolled_window, hadjustment, dx, TRUE);
|
||||
_gtk_scrolled_window_set_adjustment_value (scrolled_window, hadjustment,
|
||||
dx, TRUE, FALSE);
|
||||
}
|
||||
|
||||
vadjustment = gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar));
|
||||
if (vadjustment && priv->vscrollbar_visible)
|
||||
{
|
||||
dy = (priv->last_motion_event_y_root - event->y_root) + priv->unclamped_vadj_value;
|
||||
_gtk_scrolled_window_set_adjustment_value (scrolled_window, vadjustment, dy, TRUE);
|
||||
_gtk_scrolled_window_set_adjustment_value (scrolled_window, vadjustment,
|
||||
dy, TRUE, FALSE);
|
||||
}
|
||||
|
||||
_gtk_scrolled_window_get_overshoot (scrolled_window,
|
||||
|
||||
Reference in New Issue
Block a user