3636#include "gesture_detection.h"
3737
3838// FIXME use 2 for SCROLL_FINGER_COUNT as soon as possible
39- #define SCROLL_FINGER_COUNT 4
39+ #define SCROLL_FINGER_COUNT 2
4040#define SCROLL_SLOW_DOWN_FACTOR -0.006
4141
4242typedef struct point {
@@ -47,6 +47,7 @@ typedef struct point {
4747typedef struct mt_slots {
4848 uint8_t active ;
4949 point_t points [2 ];
50+ point_t last_points [2 ];
5051} mt_slots_t ;
5152
5253typedef struct scroll {
@@ -69,10 +70,13 @@ typedef struct scroll_thread_params {
6970 void (* callback )(input_event_array_t * );
7071} scroll_thread_params_t ;
7172
73+ typedef enum gesture { NO_GESTURE , SCROLL , ZOOM , SWIPE } gesture_t ;
74+
7275mt_slots_t mt_slots ;
7376gesture_start_t gesture_start ;
7477uint8_t finger_count ;
7578volatile scroll_t scroll ;
79+ gesture_t current_gesture ;
7680
7781static int test_grab (int fd ) {
7882 int rc ;
@@ -83,19 +87,23 @@ static int test_grab(int fd) {
8387 return rc ;
8488}
8589
86- static void init_gesture ( ) {
90+ static uint8_t calculate_distance ( point_t p1 , point_t p2 ) {
8791 int32_t x_distance , y_distance ;
88- gesture_start .point .x = mt_slots .points [0 ].x ;
89- gesture_start .point .y = mt_slots .points [0 ].y ;
92+ x_distance = p1 .x - p2 .x ;
93+ y_distance = p1 .y - p2 .y ;
94+ return (uint32_t ) sqrt ((x_distance * x_distance ) + (y_distance * y_distance ));
95+ }
96+
97+ static void init_gesture () {
98+ gesture_start .point = mt_slots .points [0 ];
9099
91100 if (finger_count == SCROLL_FINGER_COUNT ) {
92- x_distance = mt_slots .points [0 ].x - mt_slots .points [1 ].x ;
93- y_distance = mt_slots .points [0 ].y - mt_slots .points [1 ].y ;
94- gesture_start .distance = (uint32_t ) sqrt ((x_distance * x_distance ) + (y_distance * y_distance ));
101+ gesture_start .distance = calculate_distance (mt_slots .points [0 ], mt_slots .points [1 ]);
95102 scroll .width = 0 ;
96103 scroll .last_point = mt_slots .points [0 ];
97104 scroll .x_velocity = 0 ;
98105 scroll .y_velocity = 0 ;
106+ current_gesture = NO_GESTURE ;
99107 }
100108}
101109
@@ -159,6 +167,7 @@ static void process_abs_event(struct input_event event) {
159167 scroll .last_x_abs_event = event ;
160168 scroll .last_point .x = mt_slots .points [0 ].x ;
161169 }
170+ mt_slots .last_points [mt_slots .active ].x = mt_slots .points [mt_slots .active ].x ;
162171 // store the current x position for the current mt_slot
163172 mt_slots .points [mt_slots .active ].x = event .value ;
164173 break ;
@@ -173,6 +182,7 @@ static void process_abs_event(struct input_event event) {
173182 scroll .last_y_abs_event = event ;
174183 scroll .last_point .y = mt_slots .points [0 ].y ;
175184 }
185+ mt_slots .last_points [mt_slots .active ].y = mt_slots .points [mt_slots .active ].y ;
176186 // store the current y position for the current mt_slot
177187 mt_slots .points [mt_slots .active ].y = event .value ;
178188 break ;
@@ -207,6 +217,22 @@ static input_event_array_t *do_scroll(double distance, int32_t delta, int rel_co
207217 return result ;
208218}
209219
220+ /*
221+ * @return a vector that can only have the following values for x and y: -1, 0, 1
222+ */
223+ static point_t create_direction_vector (point_t p1 , point_t p2 ) {
224+ point_t result ;
225+ result .x = p1 .x - p2 .x ;
226+ result .y = p1 .y - p2 .y ;
227+ if (result .x != 0 ) {
228+ result .x /= fabs (result .x );
229+ }
230+ if (result .y != 0 ) {
231+ result .y /= fabs (result .y );
232+ }
233+ return result ;
234+ }
235+
210236static input_event_array_t * process_syn_event (struct input_event event ,
211237 configuration_t config ,
212238 point_t thresholds ) {
@@ -218,28 +244,66 @@ static input_event_array_t *process_syn_event(struct input_event event,
218244 x_distance = gesture_start .point .x - mt_slots .points [0 ].x ;
219245 y_distance = gesture_start .point .y - mt_slots .points [0 ].y ;
220246 if (fabs (x_distance ) > fabs (y_distance )) {
221- // only check for the finger_count LEFT and RIGHT gestures if horizontal scrolling is
222- // disabled and the the finger_count doesn't match SCROLL_FINGER_COUNT
223- if (!(config .scroll .horz && finger_count == SCROLL_FINGER_COUNT )) {
247+ if (current_gesture == NO_GESTURE ) {
248+ point_t v1 = create_direction_vector (mt_slots .last_points [0 ], mt_slots .points [0 ]);
249+ point_t v2 = create_direction_vector (mt_slots .last_points [1 ], mt_slots .points [1 ]);
250+ // if horizontal scrolling is enable, the finger_count matches SCROLL_FINGER_COUNT and
251+ // the x direction of the direction vectors for both fingers is equal the current_gesture
252+ // will be SCROLL
253+ if (config .scroll .horz && finger_count == SCROLL_FINGER_COUNT && v1 .x != 0 && v1 .x == v2 .x ) {
254+ current_gesture = SCROLL ;
255+ // if zooming is enable, the finger_count matches SCROLL_FINGER_COUNT and the direction
256+ // vectors for both fingers are opposed to each other the current_gesture will be ZOOM
257+ } else if (config .zoom .enabled && finger_count == SCROLL_FINGER_COUNT && (v1 .x != v2 .x || v1 .y != v2 .y )) {
258+ current_gesture = ZOOM ;
259+ // if no scrolling and zooming is enabled or the finger_count does not match
260+ // SCROLL_FINGER_COUNT the current_gesture will be SWIPE
261+ } else if ((!config .scroll .horz && !config .zoom .enabled ) || finger_count != SCROLL_FINGER_COUNT ) {
262+ current_gesture = SWIPE ;
263+ }
264+ }
265+
266+ if (current_gesture == SWIPE ) {
224267 if (x_distance > thresholds .x ) {
225268 direction = LEFT ;
226269 } else if (x_distance < - thresholds .x ) {
227270 direction = RIGHT ;
228271 }
229- } else {
230- result = do_scroll (scroll .last_point .x - mt_slots .points [0 ].x , config .scroll .horz_delta , REL_HWHEEL );
272+ } else if (current_gesture == SCROLL ) {
273+ result = do_scroll (scroll .last_point .x - mt_slots .points [0 ].x , config .scroll .horz_delta , REL_HWHEEL );
274+ } else if (current_gesture == ZOOM ) {
275+ printf ("zoom\n" );
231276 }
232277 } else {
233- // only check for the finger_count UP and DOWN gestures if horizontal scrolling is
234- // disabled and the the finger_count doesn't match SCROLL_FINGER_COUNT
235- if (!(config .scroll .vert && finger_count == SCROLL_FINGER_COUNT )) {
278+ if (current_gesture == NO_GESTURE ) {
279+ point_t v1 = create_direction_vector (mt_slots .last_points [0 ], mt_slots .points [0 ]);
280+ point_t v2 = create_direction_vector (mt_slots .last_points [1 ], mt_slots .points [1 ]);
281+ // if vertical scrolling is enable, the finger_count matches SCROLL_FINGER_COUNT and
282+ // the y direction of the direction vectors for both fingers is equal the current_gesture
283+ // will be SCROLL
284+ if (config .scroll .vert && finger_count == SCROLL_FINGER_COUNT && v1 .y != 0 && v1 .y == v2 .y ) {
285+ current_gesture = SCROLL ;
286+ // if zooming is enable, the finger_count matches SCROLL_FINGER_COUNT and the direction
287+ // vectors for both fingers are opposed to each other the current_gesture will be ZOOM
288+ } else if (config .zoom .enabled && finger_count == SCROLL_FINGER_COUNT && (v1 .x != v2 .x || v1 .y != v2 .y )) {
289+ current_gesture = ZOOM ;
290+ // if no scrolling and zooming is enabled or the finger_count does not match
291+ // SCROLL_FINGER_COUNT the current_gesture will be SWIPE
292+ } else if ((!config .scroll .vert && !config .zoom .enabled ) || finger_count != SCROLL_FINGER_COUNT ) {
293+ current_gesture = SWIPE ;
294+ }
295+ }
296+
297+ if (current_gesture == SWIPE ) {
236298 if (y_distance > thresholds .y ) {
237299 direction = UP ;
238300 } else if (y_distance < - thresholds .y ) {
239301 direction = DOWN ;
240302 }
241- } else {
303+ } else if ( current_gesture == SCROLL ) {
242304 result = do_scroll (mt_slots .points [0 ].y - scroll .last_point .y , config .scroll .vert_delta , REL_WHEEL );
305+ } else if (current_gesture == ZOOM ) {
306+ printf ("zoom\n" );
243307 }
244308 }
245309 if (direction != NONE ) {
@@ -317,6 +381,8 @@ void process_events(int fd, configuration_t config, void (*callback)(input_event
317381
318382 pthread_t scroll_thread = NULL ;
319383
384+ uint8_t syn_event_skip_counter = 0 ;
385+
320386 if (thresholds .x < 0 || thresholds .y < 0 ) {
321387 return ;
322388 }
@@ -342,6 +408,7 @@ void process_events(int fd, configuration_t config, void (*callback)(input_event
342408 pthread_cancel (scroll_thread );
343409 }
344410 init_gesture ();
411+ syn_event_skip_counter = 0 ;
345412 } else if (scroll .x_velocity != 0 || scroll .y_velocity != 0 ) {
346413 scroll_thread_params_t params = {
347414 .callback = callback
@@ -361,7 +428,12 @@ void process_events(int fd, configuration_t config, void (*callback)(input_event
361428 case EV_ABS :
362429 process_abs_event (ev [i ]);
363430 break ;
364- case EV_SYN : {
431+ case EV_SYN :
432+ // skip the first 3 EV_SYN events to get enough data for mt_slots.last_points and .points
433+ // to calculate the direction vectors correctly
434+ if (syn_event_skip_counter < 3 ) {
435+ syn_event_skip_counter ++ ;
436+ } else {
365437 input_event_array_t * input_events = process_syn_event (ev [i ], config , thresholds );
366438 callback (input_events );
367439 free (input_events );
0 commit comments