mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-04 09:40:19 +00:00
scrolledwindow: Replace kinetic scrolling with GtkKineticScrolling
Two GtkKineticScrolling helpers are used, one per axis direction. https://bugzilla.gnome.org/show_bug.cgi?id=729608
This commit is contained in:
parent
c726226825
commit
828594d5bd
@ -40,6 +40,7 @@
|
|||||||
#include "gtkviewport.h"
|
#include "gtkviewport.h"
|
||||||
#include "gtkwidgetprivate.h"
|
#include "gtkwidgetprivate.h"
|
||||||
#include "gtkwindow.h"
|
#include "gtkwindow.h"
|
||||||
|
#include "gtkkineticscrolling.h"
|
||||||
#include "a11y/gtkscrolledwindowaccessible.h"
|
#include "a11y/gtkscrolledwindowaccessible.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
@ -128,8 +129,8 @@
|
|||||||
|
|
||||||
/* Kinetic scrolling */
|
/* Kinetic scrolling */
|
||||||
#define MAX_OVERSHOOT_DISTANCE 50
|
#define MAX_OVERSHOOT_DISTANCE 50
|
||||||
#define FRICTION_DECELERATION 0.003
|
#define DECELERATION_FRICTION 4
|
||||||
#define OVERSHOOT_INVERSE_ACCELERATION 0.003
|
#define OVERSHOOT_FRICTION 20
|
||||||
|
|
||||||
struct _GtkScrolledWindowPrivate
|
struct _GtkScrolledWindowPrivate
|
||||||
{
|
{
|
||||||
@ -179,10 +180,8 @@ typedef struct
|
|||||||
GtkScrolledWindow *scrolled_window;
|
GtkScrolledWindow *scrolled_window;
|
||||||
gint64 last_deceleration_time;
|
gint64 last_deceleration_time;
|
||||||
|
|
||||||
gdouble x_velocity;
|
GtkKineticScrolling *hscrolling;
|
||||||
gdouble y_velocity;
|
GtkKineticScrolling *vscrolling;
|
||||||
gdouble vel_cosine;
|
|
||||||
gdouble vel_sine;
|
|
||||||
} KineticScrollData;
|
} KineticScrollData;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -672,8 +671,8 @@ scrolled_window_swipe_cb (GtkScrolledWindow *scrolled_window,
|
|||||||
gboolean overshoot;
|
gboolean overshoot;
|
||||||
|
|
||||||
overshoot = _gtk_scrolled_window_get_overshoot (scrolled_window, NULL, NULL);
|
overshoot = _gtk_scrolled_window_get_overshoot (scrolled_window, NULL, NULL);
|
||||||
priv->x_velocity = -x_velocity / 1000;
|
priv->x_velocity = -x_velocity;
|
||||||
priv->y_velocity = -y_velocity / 1000;
|
priv->y_velocity = -y_velocity;
|
||||||
|
|
||||||
/* Zero out vector components without a visible scrollbar */
|
/* Zero out vector components without a visible scrollbar */
|
||||||
if (!priv->hscrollbar_visible)
|
if (!priv->hscrollbar_visible)
|
||||||
@ -2460,7 +2459,7 @@ _gtk_scrolled_window_set_adjustment_value (GtkScrolledWindow *scrolled_window,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
scrolled_window_deceleration_cb (GtkWidget *widdget,
|
scrolled_window_deceleration_cb (GtkWidget *widget,
|
||||||
GdkFrameClock *frame_clock,
|
GdkFrameClock *frame_clock,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
@ -2469,9 +2468,12 @@ scrolled_window_deceleration_cb (GtkWidget *widdget,
|
|||||||
GtkScrolledWindowPrivate *priv = scrolled_window->priv;
|
GtkScrolledWindowPrivate *priv = scrolled_window->priv;
|
||||||
GtkAdjustment *hadjustment, *vadjustment;
|
GtkAdjustment *hadjustment, *vadjustment;
|
||||||
gint old_overshoot_x, old_overshoot_y, overshoot_x, overshoot_y;
|
gint old_overshoot_x, old_overshoot_y, overshoot_x, overshoot_y;
|
||||||
gdouble value;
|
|
||||||
gint64 current_time;
|
gint64 current_time;
|
||||||
guint elapsed;
|
gdouble position, elapsed;
|
||||||
|
|
||||||
|
current_time = gdk_frame_clock_get_frame_time (frame_clock);
|
||||||
|
elapsed = (current_time - data->last_deceleration_time) / 1000000.0;
|
||||||
|
data->last_deceleration_time = current_time;
|
||||||
|
|
||||||
hadjustment = gtk_range_get_adjustment (GTK_RANGE (priv->hscrollbar));
|
hadjustment = gtk_range_get_adjustment (GTK_RANGE (priv->hscrollbar));
|
||||||
vadjustment = gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar));
|
vadjustment = gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar));
|
||||||
@ -2479,83 +2481,27 @@ scrolled_window_deceleration_cb (GtkWidget *widdget,
|
|||||||
_gtk_scrolled_window_get_overshoot (scrolled_window,
|
_gtk_scrolled_window_get_overshoot (scrolled_window,
|
||||||
&old_overshoot_x, &old_overshoot_y);
|
&old_overshoot_x, &old_overshoot_y);
|
||||||
|
|
||||||
current_time = gdk_frame_clock_get_frame_time (frame_clock);
|
if (data->hscrolling &&
|
||||||
elapsed = (current_time - data->last_deceleration_time) / 1000;
|
gtk_kinetic_scrolling_tick (data->hscrolling, elapsed, &position))
|
||||||
data->last_deceleration_time = current_time;
|
|
||||||
|
|
||||||
if (hadjustment && priv->hscrollbar_visible)
|
|
||||||
{
|
{
|
||||||
value = priv->unclamped_hadj_value + (data->x_velocity * elapsed);
|
priv->unclamped_hadj_value = position;
|
||||||
|
gtk_adjustment_set_value (hadjustment, position);
|
||||||
if (_gtk_scrolled_window_set_adjustment_value (scrolled_window,
|
|
||||||
hadjustment,
|
|
||||||
value, TRUE, TRUE))
|
|
||||||
data->x_velocity = 0;
|
|
||||||
}
|
}
|
||||||
else
|
else if (data->hscrolling)
|
||||||
data->x_velocity = 0;
|
g_clear_pointer (&data->hscrolling, (GDestroyNotify) gtk_kinetic_scrolling_free);
|
||||||
|
|
||||||
if (vadjustment && priv->vscrollbar_visible)
|
if (data->vscrolling &&
|
||||||
|
gtk_kinetic_scrolling_tick (data->vscrolling, elapsed, &position))
|
||||||
{
|
{
|
||||||
value = priv->unclamped_vadj_value + (data->y_velocity * elapsed);
|
priv->unclamped_vadj_value = position;
|
||||||
|
gtk_adjustment_set_value (vadjustment, position);
|
||||||
if (_gtk_scrolled_window_set_adjustment_value (scrolled_window,
|
|
||||||
vadjustment,
|
|
||||||
value, TRUE, TRUE))
|
|
||||||
data->y_velocity = 0;
|
|
||||||
}
|
}
|
||||||
else
|
else if (data->vscrolling)
|
||||||
data->y_velocity = 0;
|
g_clear_pointer (&data->vscrolling, (GDestroyNotify) gtk_kinetic_scrolling_free);
|
||||||
|
|
||||||
_gtk_scrolled_window_get_overshoot (scrolled_window,
|
_gtk_scrolled_window_get_overshoot (scrolled_window,
|
||||||
&overshoot_x, &overshoot_y);
|
&overshoot_x, &overshoot_y);
|
||||||
|
|
||||||
if (overshoot_x == 0)
|
|
||||||
{
|
|
||||||
if (old_overshoot_x != 0)
|
|
||||||
{
|
|
||||||
/* Overshooting finished snapping back */
|
|
||||||
data->x_velocity = 0;
|
|
||||||
}
|
|
||||||
else if (data->x_velocity > 0)
|
|
||||||
{
|
|
||||||
data->x_velocity -= FRICTION_DECELERATION * elapsed * data->vel_sine;
|
|
||||||
data->x_velocity = MAX (0, data->x_velocity);
|
|
||||||
}
|
|
||||||
else if (data->x_velocity < 0)
|
|
||||||
{
|
|
||||||
data->x_velocity += FRICTION_DECELERATION * elapsed * data->vel_sine;
|
|
||||||
data->x_velocity = MIN (0, data->x_velocity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (overshoot_x < 0)
|
|
||||||
data->x_velocity += OVERSHOOT_INVERSE_ACCELERATION * elapsed;
|
|
||||||
else if (overshoot_x > 0)
|
|
||||||
data->x_velocity -= OVERSHOOT_INVERSE_ACCELERATION * elapsed;
|
|
||||||
|
|
||||||
if (overshoot_y == 0)
|
|
||||||
{
|
|
||||||
if (old_overshoot_y != 0)
|
|
||||||
{
|
|
||||||
/* Overshooting finished snapping back */
|
|
||||||
data->y_velocity = 0;
|
|
||||||
}
|
|
||||||
else if (data->y_velocity > 0)
|
|
||||||
{
|
|
||||||
data->y_velocity -= FRICTION_DECELERATION * elapsed * data->vel_cosine;
|
|
||||||
data->y_velocity = MAX (0, data->y_velocity);
|
|
||||||
}
|
|
||||||
else if (data->y_velocity < 0)
|
|
||||||
{
|
|
||||||
data->y_velocity += FRICTION_DECELERATION * elapsed * data->vel_cosine;
|
|
||||||
data->y_velocity = MIN (0, data->y_velocity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (overshoot_y < 0)
|
|
||||||
data->y_velocity += OVERSHOOT_INVERSE_ACCELERATION * elapsed;
|
|
||||||
else if (overshoot_y > 0)
|
|
||||||
data->y_velocity -= OVERSHOOT_INVERSE_ACCELERATION * elapsed;
|
|
||||||
|
|
||||||
if (old_overshoot_x != overshoot_x ||
|
if (old_overshoot_x != overshoot_x ||
|
||||||
old_overshoot_y != overshoot_y)
|
old_overshoot_y != overshoot_y)
|
||||||
{
|
{
|
||||||
@ -2568,12 +2514,16 @@ scrolled_window_deceleration_cb (GtkWidget *widdget,
|
|||||||
gtk_widget_queue_resize (GTK_WIDGET (scrolled_window));
|
gtk_widget_queue_resize (GTK_WIDGET (scrolled_window));
|
||||||
}
|
}
|
||||||
else if (overshoot_x < 0 || overshoot_y < 0)
|
else if (overshoot_x < 0 || overshoot_y < 0)
|
||||||
_gtk_scrolled_window_allocate_overshoot_window (scrolled_window);
|
{
|
||||||
|
_gtk_scrolled_window_allocate_overshoot_window (scrolled_window);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (overshoot_x == 0 && overshoot_y == 0 &&
|
if (!data->hscrolling && !data->vscrolling)
|
||||||
data->x_velocity == 0 && data->y_velocity == 0)
|
{
|
||||||
gtk_scrolled_window_cancel_deceleration (scrolled_window);
|
gtk_scrolled_window_cancel_deceleration (scrolled_window);
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
return G_SOURCE_CONTINUE;
|
return G_SOURCE_CONTINUE;
|
||||||
}
|
}
|
||||||
@ -2591,34 +2541,74 @@ gtk_scrolled_window_cancel_deceleration (GtkScrolledWindow *scrolled_window)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
kinetic_scroll_data_free (KineticScrollData *data)
|
||||||
|
{
|
||||||
|
if (data->hscrolling)
|
||||||
|
gtk_kinetic_scrolling_free (data->hscrolling);
|
||||||
|
if (data->vscrolling)
|
||||||
|
gtk_kinetic_scrolling_free (data->vscrolling);
|
||||||
|
|
||||||
|
g_free (data);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_scrolled_window_start_deceleration (GtkScrolledWindow *scrolled_window)
|
gtk_scrolled_window_start_deceleration (GtkScrolledWindow *scrolled_window)
|
||||||
{
|
{
|
||||||
GtkScrolledWindowPrivate *priv = scrolled_window->priv;
|
GtkScrolledWindowPrivate *priv = scrolled_window->priv;
|
||||||
GdkFrameClock *frame_clock;
|
GdkFrameClock *frame_clock;
|
||||||
KineticScrollData *data;
|
KineticScrollData *data;
|
||||||
gdouble angle;
|
|
||||||
|
g_return_if_fail (priv->deceleration_id == 0);
|
||||||
|
|
||||||
frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (scrolled_window));
|
frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (scrolled_window));
|
||||||
|
|
||||||
data = g_new0 (KineticScrollData, 1);
|
data = g_new0 (KineticScrollData, 1);
|
||||||
data->scrolled_window = scrolled_window;
|
data->scrolled_window = scrolled_window;
|
||||||
data->last_deceleration_time = gdk_frame_clock_get_frame_time (frame_clock);
|
data->last_deceleration_time = gdk_frame_clock_get_frame_time (frame_clock);
|
||||||
data->x_velocity = priv->x_velocity;
|
|
||||||
data->y_velocity = priv->y_velocity;
|
|
||||||
|
|
||||||
/* We use sine/cosine as a factor to deceleration x/y components
|
if (priv->hscrollbar_visible)
|
||||||
* of the vector, so we care about the sign later.
|
{
|
||||||
*/
|
gdouble lower,upper;
|
||||||
angle = atan2 (ABS (data->x_velocity), ABS (data->y_velocity));
|
GtkAdjustment *hadjustment;
|
||||||
data->vel_cosine = cos (angle);
|
|
||||||
data->vel_sine = sin (angle);
|
hadjustment = gtk_range_get_adjustment (GTK_RANGE (priv->hscrollbar));
|
||||||
|
lower = gtk_adjustment_get_lower (hadjustment);
|
||||||
|
upper = gtk_adjustment_get_upper (hadjustment);
|
||||||
|
upper -= gtk_adjustment_get_page_size (hadjustment);
|
||||||
|
data->hscrolling =
|
||||||
|
gtk_kinetic_scrolling_new (lower,
|
||||||
|
upper,
|
||||||
|
MAX_OVERSHOOT_DISTANCE,
|
||||||
|
DECELERATION_FRICTION,
|
||||||
|
OVERSHOOT_FRICTION,
|
||||||
|
priv->unclamped_hadj_value,
|
||||||
|
priv->x_velocity);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->vscrollbar_visible)
|
||||||
|
{
|
||||||
|
gdouble lower,upper;
|
||||||
|
GtkAdjustment *vadjustment;
|
||||||
|
|
||||||
|
vadjustment = gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar));
|
||||||
|
lower = gtk_adjustment_get_lower(vadjustment);
|
||||||
|
upper = gtk_adjustment_get_upper(vadjustment);
|
||||||
|
upper -= gtk_adjustment_get_page_size(vadjustment);
|
||||||
|
data->vscrolling =
|
||||||
|
gtk_kinetic_scrolling_new (lower,
|
||||||
|
upper,
|
||||||
|
MAX_OVERSHOOT_DISTANCE,
|
||||||
|
DECELERATION_FRICTION,
|
||||||
|
OVERSHOOT_FRICTION,
|
||||||
|
priv->unclamped_vadj_value,
|
||||||
|
priv->y_velocity);
|
||||||
|
}
|
||||||
|
|
||||||
scrolled_window->priv->deceleration_id =
|
scrolled_window->priv->deceleration_id =
|
||||||
gtk_widget_add_tick_callback (GTK_WIDGET (scrolled_window),
|
gtk_widget_add_tick_callback (GTK_WIDGET (scrolled_window),
|
||||||
scrolled_window_deceleration_cb,
|
scrolled_window_deceleration_cb, data,
|
||||||
data,
|
(GDestroyNotify) kinetic_scroll_data_free);
|
||||||
(GDestroyNotify) g_free);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
Loading…
Reference in New Issue
Block a user