4444#include "mx-scrollable.h"
4545#include "mx-focusable.h"
4646#include <math.h>
47+ #include <string.h>
4748
4849#define _KINETIC_DEBUG 0
4950
@@ -98,9 +99,21 @@ struct _MxKineticScrollViewPrivate
9899
99100 MxAutomaticScroll in_automatic_scroll ;
100101
101- /* Mouse motion event information */
102- GArray * motion_buffer ;
103- guint last_motion ;
102+ /* Mouse motion event information.
103+ * @motion_origin is the details of the first motion event in a sequence.
104+ * @motion_last is the most recent motion event in a sequence.
105+ * @motion_total is the total value of all the motion events in a sequence.
106+ * FIXME: The code does not currently handle overflow here.
107+ * @n_motions is the number of events used in the calculation of
108+ * @motion_total.
109+ *
110+ * @motion_origin, @motion_last and @motion_total are valid iff
111+ * @n_motions > 0.
112+ */
113+ MxKineticScrollViewMotion motion_origin ;
114+ MxKineticScrollViewMotion motion_last ;
115+ MxKineticScrollViewMotion motion_total ;
116+ guint n_motions ;
104117
105118 /* Variables for storing acceleration information */
106119 ClutterTimeline * deceleration_timeline ;
@@ -310,12 +323,6 @@ mx_kinetic_scroll_view_get_property (GObject *object,
310323 g_value_set_double (value , priv -> decel_rate );
311324 break ;
312325
313- /*
314- case PROP_BUFFER_SIZE :
315- g_value_set_uint (value, priv->motion_buffer->len);
316- break;
317- */
318-
319326 case PROP_HADJUST :
320327 mx_kinetic_scroll_view_get_adjustments (MX_SCROLLABLE (object ),
321328 & adjustment , NULL );
@@ -483,16 +490,6 @@ mx_kinetic_scroll_view_dispose (GObject *object)
483490 G_OBJECT_CLASS (mx_kinetic_scroll_view_parent_class )-> dispose (object );
484491}
485492
486- static void
487- mx_kinetic_scroll_view_finalize (GObject * object )
488- {
489- MxKineticScrollViewPrivate * priv = MX_KINETIC_SCROLL_VIEW (object )-> priv ;
490-
491- g_array_free (priv -> motion_buffer , TRUE);
492-
493- G_OBJECT_CLASS (mx_kinetic_scroll_view_parent_class )-> finalize (object );
494- }
495-
496493static void
497494mx_kinetic_scroll_view_get_preferred_width (ClutterActor * actor ,
498495 gfloat for_height ,
@@ -622,7 +619,6 @@ mx_kinetic_scroll_view_class_init (MxKineticScrollViewClass *klass)
622619 object_class -> get_property = mx_kinetic_scroll_view_get_property ;
623620 object_class -> set_property = mx_kinetic_scroll_view_set_property ;
624621 object_class -> dispose = mx_kinetic_scroll_view_dispose ;
625- object_class -> finalize = mx_kinetic_scroll_view_finalize ;
626622
627623 actor_class -> get_preferred_width = mx_kinetic_scroll_view_get_preferred_width ;
628624 actor_class -> get_preferred_height = mx_kinetic_scroll_view_get_preferred_height ;
@@ -755,6 +751,61 @@ set_state (MxKineticScrollView *scroll, MxKineticScrollViewState state)
755751 LOG_DEBUG (scroll , "%s: finished setting state to %u" , G_STRFUNC , state );
756752}
757753
754+ /* Add a motion event to the rolling average of motion events. */
755+ static void
756+ add_motion_event (MxKineticScrollView * scroll ,
757+ gfloat x ,
758+ gfloat y )
759+ {
760+ MxKineticScrollViewPrivate * priv = scroll -> priv ;
761+ GTimeVal tv ;
762+
763+ LOG_DEBUG (scroll , "%s: x = %f, y = %f, n_motions = %u" ,
764+ G_STRFUNC , x , y , priv -> n_motions );
765+
766+ g_get_current_time (& tv );
767+
768+ if (priv -> n_motions == 0 )
769+ {
770+ priv -> motion_origin .x = x ;
771+ priv -> motion_origin .y = y ;
772+ priv -> motion_origin .time = tv ;
773+
774+ memcpy (& priv -> motion_last , & priv -> motion_origin ,
775+ sizeof (priv -> motion_last ));
776+ memcpy (& priv -> motion_total , & priv -> motion_origin ,
777+ sizeof (priv -> motion_total ));
778+
779+ priv -> n_motions = 1 ;
780+ }
781+ else if (priv -> n_motions < G_MAXUINT )
782+ {
783+ priv -> motion_last .x = x ;
784+ priv -> motion_last .y = y ;
785+ priv -> motion_last .time = tv ;
786+
787+ priv -> motion_total .x += x ;
788+ priv -> motion_total .y += y ;
789+ priv -> motion_total .time .tv_sec += tv .tv_sec ;
790+ priv -> motion_total .time .tv_usec += tv .tv_usec ;
791+
792+ /* Avoid overflow by only taking this branch if n_motions will not
793+ * overflow. Subsequent motions are ignored. */
794+ priv -> n_motions ++ ;
795+ }
796+ }
797+
798+ static void
799+ reset_motion_events (MxKineticScrollView * scroll )
800+ {
801+ MxKineticScrollViewPrivate * priv = scroll -> priv ;
802+
803+ memset (& priv -> motion_origin , 0 , sizeof (priv -> motion_origin ));
804+ memset (& priv -> motion_last , 0 , sizeof (priv -> motion_last ));
805+ memset (& priv -> motion_total , 0 , sizeof (priv -> motion_total ));
806+ priv -> n_motions = 0 ;
807+ }
808+
758809static gboolean
759810motion_event_cb (ClutterActor * actor ,
760811 ClutterEvent * event ,
@@ -837,9 +888,8 @@ motion_event_cb (ClutterActor *actor,
837888
838889 g_object_get (G_OBJECT (settings ),
839890 "drag-threshold" , & threshold , NULL );
840- g_assert (priv -> motion_buffer -> len > 0 );
841- motion = & g_array_index (priv -> motion_buffer ,
842- MxKineticScrollViewMotion , 0 );
891+ g_assert (priv -> n_motions > 0 );
892+ motion = & priv -> motion_origin ;
843893
844894 dx = ABS (motion -> x - x );
845895 dy = ABS (motion -> y - y );
@@ -921,10 +971,10 @@ motion_event_cb (ClutterActor *actor,
921971 return FALSE;
922972 }
923973
924- g_assert (priv -> motion_buffer -> len > 0 );
974+ g_assert (priv -> n_motions > 0 );
925975 LOG_DEBUG (scroll , "motion dx=%f dy=%f" ,
926- ABS (g_array_index ( priv -> motion_buffer , MxKineticScrollViewMotion , priv -> motion_buffer -> len - 1 ) .x - x ),
927- ABS (g_array_index ( priv -> motion_buffer , MxKineticScrollViewMotion , priv -> motion_buffer -> len - 1 ) .y - y ));
976+ ABS (priv -> motion_last .x - x ),
977+ ABS (priv -> motion_last .y - y ));
928978
929979 if (priv -> child )
930980 {
@@ -934,10 +984,7 @@ motion_event_cb (ClutterActor *actor,
934984 mx_scrollable_get_adjustments (MX_SCROLLABLE (priv -> child ),
935985 & hadjust , & vadjust );
936986
937- g_assert (priv -> last_motion < priv -> motion_buffer -> len );
938- motion = & g_array_index (priv -> motion_buffer ,
939- MxKineticScrollViewMotion ,
940- priv -> last_motion );
987+ motion = & priv -> motion_last ;
941988
942989 if (!priv -> align_tested )
943990 {
@@ -979,18 +1026,7 @@ motion_event_cb (ClutterActor *actor,
9791026 }
9801027 }
9811028
982- priv -> last_motion ++ ;
983- if (priv -> last_motion == priv -> motion_buffer -> len )
984- {
985- LOG_DEBUG (scroll , "increase buffer size to %u" , priv -> last_motion );
986- g_array_set_size (priv -> motion_buffer , priv -> last_motion + 1 );
987- }
988-
989- motion = & g_array_index (priv -> motion_buffer ,
990- MxKineticScrollViewMotion , priv -> last_motion );
991- motion -> x = x ;
992- motion -> y = y ;
993- g_get_current_time (& motion -> time );
1029+ add_motion_event (scroll , x , y );
9941030 }
9951031
9961032 return swallow ;
@@ -1306,7 +1342,8 @@ release_event (MxKineticScrollView *scroll,
13061342
13071343 priv -> device = NULL ;
13081344 priv -> sequence = NULL ;
1309- priv -> last_motion = 0 ;
1345+ reset_motion_events (scroll );
1346+
13101347 return FALSE;
13111348 }
13121349
@@ -1326,40 +1363,24 @@ release_event (MxKineticScrollView *scroll,
13261363 MxAdjustment * hadjust , * vadjust ;
13271364 glong time_diff ;
13281365 guint duration ;
1329- gint i ;
13301366
13311367 /* Get time delta */
13321368 g_get_current_time (& release_time );
13331369
13341370 /* Get average position/time of last x mouse events */
1335- priv -> last_motion ++ ;
1336- if (priv -> last_motion == priv -> motion_buffer -> len )
1337- {
1338- LOG_DEBUG (scroll , "increase buffer size to %u" ,
1339- priv -> last_motion );
1340- g_array_set_size (priv -> motion_buffer , priv -> last_motion + 1 );
1341- }
1342-
13431371 x_origin = y_origin = 0 ;
13441372 motion_time = (GTimeVal ){ 0 , 0 };
1345- for (i = 0 ; i < priv -> last_motion ; i ++ )
1346- {
1347- MxKineticScrollViewMotion * motion =
1348- & g_array_index (priv -> motion_buffer , MxKineticScrollViewMotion , i );
13491373
1350- /* FIXME: This doesn't guard against overflows - Should
1351- * either fix that, or calculate the correct maximum
1352- * value for the buffer size
1353- */
1354- x_origin += motion -> x ;
1355- y_origin += motion -> y ;
1356- motion_time .tv_sec += motion -> time .tv_sec ;
1357- motion_time .tv_usec += motion -> time .tv_usec ;
1358- }
1359- x_origin = x_origin / priv -> last_motion ;
1360- y_origin = y_origin / priv -> last_motion ;
1361- motion_time .tv_sec /= priv -> last_motion ;
1362- motion_time .tv_usec /= priv -> last_motion ;
1374+ g_assert (priv -> n_motions > 0 );
1375+
1376+ x_origin = priv -> motion_total .x / priv -> n_motions ;
1377+ y_origin = priv -> motion_total .y / priv -> n_motions ;
1378+ motion_time .tv_sec = priv -> motion_total .time .tv_sec / priv -> n_motions ;
1379+ motion_time .tv_usec = priv -> motion_total .time .tv_usec / priv -> n_motions ;
1380+
1381+ /* Normalise the GTimeVal. */
1382+ motion_time .tv_sec += motion_time .tv_usec / G_USEC_PER_SEC ;
1383+ motion_time .tv_usec %= G_USEC_PER_SEC ;
13631384
13641385 if (motion_time .tv_sec == release_time .tv_sec )
13651386 time_diff = release_time .tv_usec - motion_time .tv_usec ;
@@ -1401,13 +1422,13 @@ release_event (MxKineticScrollView *scroll,
14011422 "event_x = %f, event_y = %f, y = %f, nx = %f, ny = %f, "
14021423 "n = %f, frac = %f, x_origin = %f, y_origin = %f, "
14031424 "time_diff = %lu, duration = %u, "
1404- "priv->last_motion = %u, priv->dx = %f, "
1425+ "priv->n_motions = %u, priv->dx = %f, "
14051426 "priv->dy = %f, priv->decel_rate = %f, "
14061427 "priv->overshoot = %f, priv->accumulated_delta = %f, "
14071428 "priv->acceleration_factor = %f" ,
14081429 G_STRFUNC , x_pos , y_pos , event_x , event_y ,
14091430 y , nx , ny , n , frac , x_origin , y_origin , time_diff ,
1410- duration , priv -> last_motion , priv -> dx , priv -> dy ,
1431+ duration , priv -> n_motions , priv -> dx , priv -> dy ,
14111432 priv -> decel_rate , priv -> overshoot ,
14121433 priv -> accumulated_delta , priv -> acceleration_factor );
14131434
@@ -1518,14 +1539,14 @@ release_event (MxKineticScrollView *scroll,
15181539 "d = %f, ax = %f, ay = %f, y = %f, nx = %f, ny = %f, "
15191540 "n = %f, frac = %f, x_origin = %f, y_origin = %f, "
15201541 "time_diff = %lu, duration = %u, "
1521- "priv->last_motion = %u, priv->dx = %f, "
1542+ "priv->n_motions = %u, priv->dx = %f, "
15221543 "priv->dy = %f, priv->decel_rate = %f, "
15231544 "priv->overshoot = %f, priv->accumulated_delta = %f, "
15241545 "priv->acceleration_factor = %f" ,
15251546 G_STRFUNC , x_pos , y_pos , event_x , event_y , value ,
15261547 lower , upper , step_increment , page_size , d , ax , ay , y ,
15271548 nx , ny , n , frac , x_origin , y_origin , time_diff ,
1528- duration , priv -> last_motion , priv -> dx , priv -> dy ,
1549+ duration , priv -> n_motions , priv -> dx , priv -> dy ,
15291550 priv -> decel_rate , priv -> overshoot ,
15301551 priv -> accumulated_delta , priv -> acceleration_factor );
15311552
@@ -1566,7 +1587,7 @@ release_event (MxKineticScrollView *scroll,
15661587 priv -> device = NULL ;
15671588
15681589 /* Reset motion event buffer */
1569- priv -> last_motion = 0 ;
1590+ reset_motion_events ( scroll ) ;
15701591
15711592 if (!decelerating )
15721593 clamp_adjustments (scroll , priv -> clamp_duration , TRUE, TRUE);
@@ -1582,27 +1603,27 @@ press_event (MxKineticScrollView *scroll,
15821603 MxKineticScrollViewPrivate * priv = scroll -> priv ;
15831604 ClutterActor * actor = (ClutterActor * ) scroll ;
15841605 ClutterActor * stage = clutter_actor_get_stage (actor );
1585- MxKineticScrollViewMotion * motion ;
1606+ gfloat event_x , event_y ;
15861607
15871608 /* Reset automatic-scroll setting */
15881609 priv -> in_automatic_scroll = MX_AUTOMATIC_SCROLL_NONE ;
15891610 priv -> align_tested = 0 ;
15901611
15911612 /* Reset motion buffer */
1592- priv -> last_motion = 0 ;
1593- motion = & g_array_index ( priv -> motion_buffer , MxKineticScrollViewMotion , 0 );
1594- motion -> x = x ;
1595- motion -> y = y ;
1613+ reset_motion_events ( scroll ) ;
1614+
1615+ event_x = x ;
1616+ event_y = y ;
15961617
15971618 LOG_DEBUG (scroll , "initial point(%fx%f)" , x , y );
15981619
15991620 if (clutter_actor_transform_stage_point (actor , x , y ,
1600- & motion -> x , & motion -> y ))
1621+ & event_x , & event_y ))
16011622 {
16021623 guint threshold ;
16031624 MxSettings * settings = mx_settings_get_default ();
16041625
1605- g_get_current_time ( & motion -> time );
1626+ add_motion_event ( scroll , event_x , event_y );
16061627
16071628 if (priv -> deceleration_timeline )
16081629 {
@@ -1815,9 +1836,6 @@ mx_kinetic_scroll_view_init (MxKineticScrollView *self)
18151836 MxKineticScrollViewPrivate * priv = self -> priv =
18161837 KINETIC_SCROLL_VIEW_PRIVATE (self );
18171838
1818- priv -> motion_buffer =
1819- g_array_sized_new (FALSE, TRUE, sizeof (MxKineticScrollViewMotion ), 30 );
1820- g_array_set_size (priv -> motion_buffer , 3 );
18211839 priv -> decel_rate = 1.1f ;
18221840 priv -> button = 1 ;
18231841 priv -> scroll_policy = MX_SCROLL_POLICY_BOTH ;
@@ -1925,32 +1943,6 @@ mx_kinetic_scroll_view_get_deceleration (MxKineticScrollView *scroll)
19251943 return scroll -> priv -> decel_rate ;
19261944}
19271945
1928- /*
1929- void
1930- mx_kinetic_scroll_view_set_buffer_size (MxKineticScrollView *scroll,
1931- guint size)
1932- {
1933- MxKineticScrollViewPrivate *priv;
1934-
1935- g_return_if_fail (MX_IS_KINETIC_SCROLL_VIEW (scroll));
1936- g_return_if_fail (size > 0);
1937-
1938- priv = scroll->priv;
1939- if (priv->motion_buffer->len != size)
1940- {
1941- g_array_set_size (priv->motion_buffer, size);
1942- g_object_notify (G_OBJECT (scroll), "buffer-size");
1943- }
1944- }
1945-
1946- guint
1947- mx_kinetic_scroll_view_get_buffer_size (MxKineticScrollView *scroll)
1948- {
1949- g_return_val_if_fail (MX_IS_KINETIC_SCROLL_VIEW (scroll), 0);
1950- return scroll->priv->motion_buffer->len;
1951- }
1952- */
1953-
19541946/**
19551947 * mx_kinetic_scroll_view_set_mouse_button:
19561948 * @scroll: A #MxKineticScrollView
0 commit comments