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 );
@@ -482,16 +489,6 @@ mx_kinetic_scroll_view_dispose (GObject *object)
482489 G_OBJECT_CLASS (mx_kinetic_scroll_view_parent_class )-> dispose (object );
483490}
484491
485- static void
486- mx_kinetic_scroll_view_finalize (GObject * object )
487- {
488- MxKineticScrollViewPrivate * priv = MX_KINETIC_SCROLL_VIEW (object )-> priv ;
489-
490- g_array_free (priv -> motion_buffer , TRUE);
491-
492- G_OBJECT_CLASS (mx_kinetic_scroll_view_parent_class )-> finalize (object );
493- }
494-
495492static void
496493mx_kinetic_scroll_view_get_preferred_width (ClutterActor * actor ,
497494 gfloat for_height ,
@@ -621,7 +618,6 @@ mx_kinetic_scroll_view_class_init (MxKineticScrollViewClass *klass)
621618 object_class -> get_property = mx_kinetic_scroll_view_get_property ;
622619 object_class -> set_property = mx_kinetic_scroll_view_set_property ;
623620 object_class -> dispose = mx_kinetic_scroll_view_dispose ;
624- object_class -> finalize = mx_kinetic_scroll_view_finalize ;
625621
626622 actor_class -> get_preferred_width = mx_kinetic_scroll_view_get_preferred_width ;
627623 actor_class -> get_preferred_height = mx_kinetic_scroll_view_get_preferred_height ;
@@ -754,6 +750,61 @@ set_state (MxKineticScrollView *scroll, MxKineticScrollViewState state)
754750 LOG_DEBUG (scroll , "%s: finished setting state to %u" , G_STRFUNC , state );
755751}
756752
753+ /* Add a motion event to the rolling average of motion events. */
754+ static void
755+ add_motion_event (MxKineticScrollView * scroll ,
756+ gfloat x ,
757+ gfloat y )
758+ {
759+ MxKineticScrollViewPrivate * priv = scroll -> priv ;
760+ GTimeVal tv ;
761+
762+ LOG_DEBUG (scroll , "%s: x = %f, y = %f, n_motions = %u" ,
763+ G_STRFUNC , x , y , priv -> n_motions );
764+
765+ g_get_current_time (& tv );
766+
767+ if (priv -> n_motions == 0 )
768+ {
769+ priv -> motion_origin .x = x ;
770+ priv -> motion_origin .y = y ;
771+ priv -> motion_origin .time = tv ;
772+
773+ memcpy (& priv -> motion_last , & priv -> motion_origin ,
774+ sizeof (priv -> motion_last ));
775+ memcpy (& priv -> motion_total , & priv -> motion_origin ,
776+ sizeof (priv -> motion_total ));
777+
778+ priv -> n_motions = 1 ;
779+ }
780+ else if (priv -> n_motions < G_MAXUINT )
781+ {
782+ priv -> motion_last .x = x ;
783+ priv -> motion_last .y = y ;
784+ priv -> motion_last .time = tv ;
785+
786+ priv -> motion_total .x += x ;
787+ priv -> motion_total .y += y ;
788+ priv -> motion_total .time .tv_sec += tv .tv_sec ;
789+ priv -> motion_total .time .tv_usec += tv .tv_usec ;
790+
791+ /* Avoid overflow by only taking this branch if n_motions will not
792+ * overflow. Subsequent motions are ignored. */
793+ priv -> n_motions ++ ;
794+ }
795+ }
796+
797+ static void
798+ reset_motion_events (MxKineticScrollView * scroll )
799+ {
800+ MxKineticScrollViewPrivate * priv = scroll -> priv ;
801+
802+ memset (& priv -> motion_origin , 0 , sizeof (priv -> motion_origin ));
803+ memset (& priv -> motion_last , 0 , sizeof (priv -> motion_last ));
804+ memset (& priv -> motion_total , 0 , sizeof (priv -> motion_total ));
805+ priv -> n_motions = 0 ;
806+ }
807+
757808static gboolean
758809motion_event_cb (ClutterActor * actor ,
759810 ClutterEvent * event ,
@@ -836,9 +887,8 @@ motion_event_cb (ClutterActor *actor,
836887
837888 g_object_get (G_OBJECT (settings ),
838889 "drag-threshold" , & threshold , NULL );
839- g_assert (priv -> motion_buffer -> len > 0 );
840- motion = & g_array_index (priv -> motion_buffer ,
841- MxKineticScrollViewMotion , 0 );
890+ g_assert (priv -> n_motions > 0 );
891+ motion = & priv -> motion_origin ;
842892
843893 dx = ABS (motion -> x - x );
844894 dy = ABS (motion -> y - y );
@@ -920,10 +970,10 @@ motion_event_cb (ClutterActor *actor,
920970 return FALSE;
921971 }
922972
923- g_assert (priv -> motion_buffer -> len > 0 );
973+ g_assert (priv -> n_motions > 0 );
924974 LOG_DEBUG (scroll , "motion dx=%f dy=%f" ,
925- ABS (g_array_index ( priv -> motion_buffer , MxKineticScrollViewMotion , priv -> motion_buffer -> len - 1 ) .x - x ),
926- ABS (g_array_index ( priv -> motion_buffer , MxKineticScrollViewMotion , priv -> motion_buffer -> len - 1 ) .y - y ));
975+ ABS (priv -> motion_last .x - x ),
976+ ABS (priv -> motion_last .y - y ));
927977
928978 if (priv -> child )
929979 {
@@ -933,10 +983,7 @@ motion_event_cb (ClutterActor *actor,
933983 mx_scrollable_get_adjustments (MX_SCROLLABLE (priv -> child ),
934984 & hadjust , & vadjust );
935985
936- g_assert (priv -> last_motion < priv -> motion_buffer -> len );
937- motion = & g_array_index (priv -> motion_buffer ,
938- MxKineticScrollViewMotion ,
939- priv -> last_motion );
986+ motion = & priv -> motion_last ;
940987
941988 if (!priv -> align_tested )
942989 {
@@ -978,18 +1025,7 @@ motion_event_cb (ClutterActor *actor,
9781025 }
9791026 }
9801027
981- priv -> last_motion ++ ;
982- if (priv -> last_motion == priv -> motion_buffer -> len )
983- {
984- LOG_DEBUG (scroll , "increase buffer size to %u" , priv -> last_motion );
985- g_array_set_size (priv -> motion_buffer , priv -> last_motion + 1 );
986- }
987-
988- motion = & g_array_index (priv -> motion_buffer ,
989- MxKineticScrollViewMotion , priv -> last_motion );
990- motion -> x = x ;
991- motion -> y = y ;
992- g_get_current_time (& motion -> time );
1028+ add_motion_event (scroll , x , y );
9931029 }
9941030
9951031 return swallow ;
@@ -1305,7 +1341,8 @@ release_event (MxKineticScrollView *scroll,
13051341
13061342 priv -> device = NULL ;
13071343 priv -> sequence = NULL ;
1308- priv -> last_motion = 0 ;
1344+ reset_motion_events (scroll );
1345+
13091346 return FALSE;
13101347 }
13111348
@@ -1325,40 +1362,24 @@ release_event (MxKineticScrollView *scroll,
13251362 MxAdjustment * hadjust , * vadjust ;
13261363 glong time_diff ;
13271364 guint duration ;
1328- gint i ;
13291365
13301366 /* Get time delta */
13311367 g_get_current_time (& release_time );
13321368
13331369 /* Get average position/time of last x mouse events */
1334- priv -> last_motion ++ ;
1335- if (priv -> last_motion == priv -> motion_buffer -> len )
1336- {
1337- LOG_DEBUG (scroll , "increase buffer size to %u" ,
1338- priv -> last_motion );
1339- g_array_set_size (priv -> motion_buffer , priv -> last_motion + 1 );
1340- }
1341-
13421370 x_origin = y_origin = 0 ;
13431371 motion_time = (GTimeVal ){ 0 , 0 };
1344- for (i = 0 ; i < priv -> last_motion ; i ++ )
1345- {
1346- MxKineticScrollViewMotion * motion =
1347- & g_array_index (priv -> motion_buffer , MxKineticScrollViewMotion , i );
13481372
1349- /* FIXME: This doesn't guard against overflows - Should
1350- * either fix that, or calculate the correct maximum
1351- * value for the buffer size
1352- */
1353- x_origin += motion -> x ;
1354- y_origin += motion -> y ;
1355- motion_time .tv_sec += motion -> time .tv_sec ;
1356- motion_time .tv_usec += motion -> time .tv_usec ;
1357- }
1358- x_origin = x_origin / priv -> last_motion ;
1359- y_origin = y_origin / priv -> last_motion ;
1360- motion_time .tv_sec /= priv -> last_motion ;
1361- motion_time .tv_usec /= priv -> last_motion ;
1373+ g_assert (priv -> n_motions > 0 );
1374+
1375+ x_origin = priv -> motion_total .x / priv -> n_motions ;
1376+ y_origin = priv -> motion_total .y / priv -> n_motions ;
1377+ motion_time .tv_sec = priv -> motion_total .time .tv_sec / priv -> n_motions ;
1378+ motion_time .tv_usec = priv -> motion_total .time .tv_usec / priv -> n_motions ;
1379+
1380+ /* Normalise the GTimeVal. */
1381+ motion_time .tv_sec += motion_time .tv_usec / G_USEC_PER_SEC ;
1382+ motion_time .tv_usec %= G_USEC_PER_SEC ;
13621383
13631384 if (motion_time .tv_sec == release_time .tv_sec )
13641385 time_diff = release_time .tv_usec - motion_time .tv_usec ;
@@ -1400,13 +1421,13 @@ release_event (MxKineticScrollView *scroll,
14001421 "event_x = %f, event_y = %f, y = %f, nx = %f, ny = %f, "
14011422 "n = %f, frac = %f, x_origin = %f, y_origin = %f, "
14021423 "time_diff = %lu, duration = %u, "
1403- "priv->last_motion = %u, priv->dx = %f, "
1424+ "priv->n_motions = %u, priv->dx = %f, "
14041425 "priv->dy = %f, priv->decel_rate = %f, "
14051426 "priv->overshoot = %f, priv->accumulated_delta = %f, "
14061427 "priv->acceleration_factor = %f" ,
14071428 G_STRFUNC , x_pos , y_pos , event_x , event_y ,
14081429 y , nx , ny , n , frac , x_origin , y_origin , time_diff ,
1409- duration , priv -> last_motion , priv -> dx , priv -> dy ,
1430+ duration , priv -> n_motions , priv -> dx , priv -> dy ,
14101431 priv -> decel_rate , priv -> overshoot ,
14111432 priv -> accumulated_delta , priv -> acceleration_factor );
14121433
@@ -1517,14 +1538,14 @@ release_event (MxKineticScrollView *scroll,
15171538 "d = %f, ax = %f, ay = %f, y = %f, nx = %f, ny = %f, "
15181539 "n = %f, frac = %f, x_origin = %f, y_origin = %f, "
15191540 "time_diff = %lu, duration = %u, "
1520- "priv->last_motion = %u, priv->dx = %f, "
1541+ "priv->n_motions = %u, priv->dx = %f, "
15211542 "priv->dy = %f, priv->decel_rate = %f, "
15221543 "priv->overshoot = %f, priv->accumulated_delta = %f, "
15231544 "priv->acceleration_factor = %f" ,
15241545 G_STRFUNC , x_pos , y_pos , event_x , event_y , value ,
15251546 lower , upper , step_increment , page_size , d , ax , ay , y ,
15261547 nx , ny , n , frac , x_origin , y_origin , time_diff ,
1527- duration , priv -> last_motion , priv -> dx , priv -> dy ,
1548+ duration , priv -> n_motions , priv -> dx , priv -> dy ,
15281549 priv -> decel_rate , priv -> overshoot ,
15291550 priv -> accumulated_delta , priv -> acceleration_factor );
15301551
@@ -1564,7 +1585,7 @@ release_event (MxKineticScrollView *scroll,
15641585 priv -> device = NULL ;
15651586
15661587 /* Reset motion event buffer */
1567- priv -> last_motion = 0 ;
1588+ reset_motion_events ( scroll ) ;
15681589
15691590 if (!decelerating )
15701591 clamp_adjustments (scroll , priv -> clamp_duration , TRUE, TRUE);
@@ -1580,27 +1601,27 @@ press_event (MxKineticScrollView *scroll,
15801601 MxKineticScrollViewPrivate * priv = scroll -> priv ;
15811602 ClutterActor * actor = (ClutterActor * ) scroll ;
15821603 ClutterActor * stage = clutter_actor_get_stage (actor );
1583- MxKineticScrollViewMotion * motion ;
1604+ gfloat event_x , event_y ;
15841605
15851606 /* Reset automatic-scroll setting */
15861607 priv -> in_automatic_scroll = MX_AUTOMATIC_SCROLL_NONE ;
15871608 priv -> align_tested = 0 ;
15881609
15891610 /* Reset motion buffer */
1590- priv -> last_motion = 0 ;
1591- motion = & g_array_index ( priv -> motion_buffer , MxKineticScrollViewMotion , 0 );
1592- motion -> x = x ;
1593- motion -> y = y ;
1611+ reset_motion_events ( scroll ) ;
1612+
1613+ event_x = x ;
1614+ event_y = y ;
15941615
15951616 LOG_DEBUG (scroll , "initial point(%fx%f)" , x , y );
15961617
15971618 if (clutter_actor_transform_stage_point (actor , x , y ,
1598- & motion -> x , & motion -> y ))
1619+ & event_x , & event_y ))
15991620 {
16001621 guint threshold ;
16011622 MxSettings * settings = mx_settings_get_default ();
16021623
1603- g_get_current_time ( & motion -> time );
1624+ add_motion_event ( scroll , event_x , event_y );
16041625
16051626 if (priv -> deceleration_timeline )
16061627 {
@@ -1812,9 +1833,6 @@ mx_kinetic_scroll_view_init (MxKineticScrollView *self)
18121833 MxKineticScrollViewPrivate * priv = self -> priv =
18131834 KINETIC_SCROLL_VIEW_PRIVATE (self );
18141835
1815- priv -> motion_buffer =
1816- g_array_sized_new (FALSE, TRUE, sizeof (MxKineticScrollViewMotion ), 30 );
1817- g_array_set_size (priv -> motion_buffer , 3 );
18181836 priv -> decel_rate = 1.1f ;
18191837 priv -> button = 1 ;
18201838 priv -> scroll_policy = MX_SCROLL_POLICY_BOTH ;
@@ -1921,32 +1939,6 @@ mx_kinetic_scroll_view_get_deceleration (MxKineticScrollView *scroll)
19211939 return scroll -> priv -> decel_rate ;
19221940}
19231941
1924- /*
1925- void
1926- mx_kinetic_scroll_view_set_buffer_size (MxKineticScrollView *scroll,
1927- guint size)
1928- {
1929- MxKineticScrollViewPrivate *priv;
1930-
1931- g_return_if_fail (MX_IS_KINETIC_SCROLL_VIEW (scroll));
1932- g_return_if_fail (size > 0);
1933-
1934- priv = scroll->priv;
1935- if (priv->motion_buffer->len != size)
1936- {
1937- g_array_set_size (priv->motion_buffer, size);
1938- g_object_notify (G_OBJECT (scroll), "buffer-size");
1939- }
1940- }
1941-
1942- guint
1943- mx_kinetic_scroll_view_get_buffer_size (MxKineticScrollView *scroll)
1944- {
1945- g_return_val_if_fail (MX_IS_KINETIC_SCROLL_VIEW (scroll), 0);
1946- return scroll->priv->motion_buffer->len;
1947- }
1948- */
1949-
19501942/**
19511943 * mx_kinetic_scroll_view_set_mouse_button:
19521944 * @scroll: A #MxKineticScrollView
0 commit comments