Skip to content

Commit

Permalink
kinetic-scroll-view: Grow the motion buffer over time
Browse files Browse the repository at this point in the history
The motion buffer contains a history of motion events for the current
scrolling action, starting from the initial touch event. This is used at
the release of the scroll to work out an average origin coordinate,
which is then used in the calculation of whether to use kinetic
scrolling.

Previously, the oldest entry in the motion buffer was removed if the
buffer filled up, then the buffer was expanded in size. This meant that
for scrolling actions with many motion events, the average taken over
the events would quickly creep towards the location of the most recent
motion event. This meant that, often, the threshold for starting a
kinetic scroll was not reached, and hence kinetic scrolling would not
happen.

Stop removing the oldest entry from the buffer, and instead grow it
indefinitely. This does make the widget prone to consuming all the
system’s memory if the user scrolls around for a _very_ long time. This
may be better fixed by calculating a moving average instead, and
eliminating the motion buffer.

clutter-project#98
  • Loading branch information
Philip Withnall committed Sep 21, 2015
1 parent 07d5575 commit ad0f931
Showing 1 changed file with 13 additions and 5 deletions.
18 changes: 13 additions & 5 deletions mx/mx-kinetic-scroll-view.c
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,7 @@ motion_event_cb (ClutterActor *actor,

g_object_get (G_OBJECT (settings),
"drag-threshold", &threshold, NULL);
g_assert (priv->motion_buffer->len > 0);
motion = &g_array_index (priv->motion_buffer,
MxKineticScrollViewMotion, 0);

Expand Down Expand Up @@ -915,6 +916,7 @@ motion_event_cb (ClutterActor *actor,
return FALSE;
}

g_assert (priv->motion_buffer->len > 0);
LOG_DEBUG (scroll, "motion dx=%f dy=%f",
ABS (g_array_index (priv->motion_buffer, MxKineticScrollViewMotion, priv->motion_buffer->len - 1).x - x),
ABS (g_array_index (priv->motion_buffer, MxKineticScrollViewMotion, priv->motion_buffer->len - 1).y - y));
Expand All @@ -927,6 +929,7 @@ motion_event_cb (ClutterActor *actor,
mx_scrollable_get_adjustments (MX_SCROLLABLE (priv->child),
&hadjust, &vadjust);

g_assert (priv->last_motion < priv->motion_buffer->len);
motion = &g_array_index (priv->motion_buffer,
MxKineticScrollViewMotion,
priv->last_motion);
Expand Down Expand Up @@ -974,10 +977,8 @@ motion_event_cb (ClutterActor *actor,
priv->last_motion ++;
if (priv->last_motion == priv->motion_buffer->len)
{
LOG_DEBUG (scroll, "reset");
priv->motion_buffer = g_array_remove_index (priv->motion_buffer, 0);
g_array_set_size (priv->motion_buffer, priv->last_motion);
priv->last_motion --;
LOG_DEBUG (scroll, "increase buffer size to %u", priv->last_motion);
g_array_set_size (priv->motion_buffer, priv->last_motion + 1);
}

motion = &g_array_index (priv->motion_buffer,
Expand Down Expand Up @@ -1301,6 +1302,13 @@ release_event (MxKineticScrollView *scroll,

/* Get average position/time of last x mouse events */
priv->last_motion ++;
if (priv->last_motion == priv->motion_buffer->len)
{
LOG_DEBUG (scroll, "increase buffer size to %u",
priv->last_motion);
g_array_set_size (priv->motion_buffer, priv->last_motion + 1);
}

x_origin = y_origin = 0;
motion_time = (GTimeVal){ 0, 0 };
for (i = 0; i < priv->last_motion; i++)
Expand Down Expand Up @@ -1736,7 +1744,7 @@ mx_kinetic_scroll_view_init (MxKineticScrollView *self)
KINETIC_SCROLL_VIEW_PRIVATE (self);

priv->motion_buffer =
g_array_sized_new (FALSE, TRUE, sizeof (MxKineticScrollViewMotion), 3);
g_array_sized_new (FALSE, TRUE, sizeof (MxKineticScrollViewMotion), 30);
g_array_set_size (priv->motion_buffer, 3);
priv->decel_rate = 1.1f;
priv->button = 1;
Expand Down

0 comments on commit ad0f931

Please sign in to comment.