28
28
#include <math.h>
29
29
#include <string.h>
30
30
#include <stdlib.h>
31
+ #include <time.h>
32
+ #include <pthread.h>
31
33
32
34
#include <linux/input.h>
33
35
34
36
#include "gesture_detection.h"
35
37
36
38
// FIXME use 2 for SCROLL_FINGER_COUNT as soon as possible
37
39
#define SCROLL_FINGER_COUNT 4
38
-
40
+ #define SCROLL_SLOW_DOWN_FACTOR -0.01
39
41
40
42
typedef struct point {
41
43
int x ;
@@ -53,7 +55,7 @@ typedef struct scroll {
53
55
struct input_event last_y_abs_event ;
54
56
double x_velocity ;
55
57
double y_velocity ;
56
- int32_t width ;
58
+ double width ;
57
59
} scroll_t ;
58
60
59
61
typedef struct gesture_start {
@@ -64,7 +66,7 @@ typedef struct gesture_start {
64
66
mt_slots_t mt_slots ;
65
67
gesture_start_t gesture_start ;
66
68
uint8_t finger_count ;
67
- scroll_t scroll ;
69
+ volatile scroll_t scroll ;
68
70
69
71
static int test_grab (int fd ) {
70
72
int rc ;
@@ -80,12 +82,14 @@ static void init_gesture() {
80
82
gesture_start .point .x = mt_slots .points [0 ].x ;
81
83
gesture_start .point .y = mt_slots .points [0 ].y ;
82
84
83
- if (finger_count == 2 ) {
85
+ if (finger_count == SCROLL_FINGER_COUNT ) {
84
86
x_distance = mt_slots .points [0 ].x - mt_slots .points [1 ].x ;
85
87
y_distance = mt_slots .points [0 ].y - mt_slots .points [1 ].y ;
86
88
gesture_start .distance = (uint32_t ) sqrt ((x_distance * x_distance ) + (y_distance * y_distance ));
87
89
scroll .width = 0 ;
88
90
scroll .last_point = mt_slots .points [0 ];
91
+ scroll .x_velocity = 0 ;
92
+ scroll .y_velocity = 0 ;
89
93
}
90
94
}
91
95
@@ -136,7 +140,7 @@ static void process_abs_event(struct input_event event) {
136
140
} else if (mt_slots .active < 2 ) {
137
141
switch (event .code ) {
138
142
case ABS_MT_POSITION_X :
139
- if (mt_slots .active == 0 ) {
143
+ if (mt_slots .active == 0 && finger_count == SCROLL_FINGER_COUNT ) {
140
144
if (scroll .last_x_abs_event .type == EV_ABS && scroll .last_x_abs_event .code == ABS_MT_POSITION_X ) {
141
145
scroll .x_velocity = calcualte_velocity (event , scroll .last_x_abs_event );
142
146
}
@@ -146,7 +150,7 @@ static void process_abs_event(struct input_event event) {
146
150
mt_slots .points [mt_slots .active ].x = event .value ;
147
151
break ;
148
152
case ABS_MT_POSITION_Y :
149
- if (mt_slots .active == 0 ) {
153
+ if (mt_slots .active == 0 && finger_count == SCROLL_FINGER_COUNT ) {
150
154
if (scroll .last_y_abs_event .type == EV_ABS && scroll .last_y_abs_event .code == ABS_MT_POSITION_Y ) {
151
155
scroll .y_velocity = calcualte_velocity (scroll .last_y_abs_event , event );
152
156
}
@@ -170,14 +174,15 @@ static void set_input_event(struct input_event *input_event, int type, int code,
170
174
#define set_key_event (key_event , code , value ) set_input_event(key_event, EV_KEY, code, value)
171
175
#define set_rel_event (rel_event , code , value ) set_input_event(rel_event, EV_REL, code, value)
172
176
173
- static input_event_array_t * do_scroll (int32_t distance , int32_t delta , int rel_code ) {
177
+ static input_event_array_t * do_scroll (double distance , int32_t delta , int rel_code ) {
174
178
input_event_array_t * result = NULL ;
175
179
scroll .width += distance ;
176
180
if (fabs (scroll .width ) > delta ) {
177
181
result = new_input_event_array (2 );
178
- set_rel_event (& result -> data [0 ], rel_code , scroll .width / delta );
182
+ int width = (int )(scroll .width / delta );
183
+ set_rel_event (& result -> data [0 ], rel_code , width );
179
184
set_syn_event (& result -> data [1 ]);
180
- scroll .width %= delta ;
185
+ scroll .width -= width * delta ;
181
186
}
182
187
return result ;
183
188
}
@@ -245,6 +250,38 @@ static int32_t get_axix_threshold(int fd, int axis, uint8_t percentage) {
245
250
return (absinfo .maximum - absinfo .minimum ) * percentage / 100 ;
246
251
}
247
252
253
+ typedef struct scroll_thread_params {
254
+ uint8_t delta ;
255
+ int code ;
256
+ void (* callback )(input_event_array_t * );
257
+ } scroll_thread_params_t ;
258
+
259
+ static void * scroll_thread_function (void * val ) {
260
+ while (scroll .y_velocity != 0 ) {
261
+ struct timespec tim = {
262
+ .tv_sec = 0 ,
263
+ .tv_nsec = 5000000
264
+ };
265
+ nanosleep (& tim , NULL );
266
+ scroll_thread_params_t * params = ((scroll_thread_params_t * )val );
267
+ input_event_array_t * events = do_scroll (scroll .y_velocity * 5 , params -> delta , REL_WHEEL );
268
+ if (events ) {
269
+ params -> callback (events );
270
+ }
271
+ free (events );
272
+ double new_velocity = SCROLL_SLOW_DOWN_FACTOR * 5 + fabs (scroll .y_velocity );
273
+ if (new_velocity < 0 ) {
274
+ new_velocity = 0 ;
275
+ }
276
+ if (scroll .y_velocity > 0 ) {
277
+ scroll .y_velocity = new_velocity ;
278
+ } else {
279
+ scroll .y_velocity = - new_velocity ;
280
+ }
281
+ }
282
+ return NULL ;
283
+ }
284
+
248
285
void process_events (int fd , configuration_t config , void (* callback )(input_event_array_t * )) {
249
286
struct input_event ev [64 ];
250
287
int i , rd ;
@@ -253,6 +290,8 @@ void process_events(int fd, configuration_t config, void (*callback)(input_event
253
290
thresholds .x = get_axix_threshold (fd , ABS_X , config .horz_threshold_percentage );
254
291
thresholds .y = get_axix_threshold (fd , ABS_Y , config .vert_threshold_percentage );
255
292
293
+ pthread_t thread = NULL ;
294
+
256
295
if (thresholds .x < 0 || thresholds .y < 0 ) {
257
296
return ;
258
297
}
@@ -275,6 +314,16 @@ void process_events(int fd, configuration_t config, void (*callback)(input_event
275
314
finger_count = process_key_event (ev [i ]);
276
315
if (finger_count > 0 ) {
277
316
init_gesture ();
317
+ } else if (scroll .x_velocity != 0 || scroll .y_velocity != 0 ) {
318
+ if (thread ) {
319
+ pthread_cancel (thread );
320
+ }
321
+ scroll_thread_params_t params = {
322
+ .delta = config .scroll .vert_delta ,
323
+ .callback = callback
324
+ };
325
+ pthread_create (& thread , NULL , & scroll_thread_function , (void * ) & params );
326
+
278
327
}
279
328
break ;
280
329
case EV_ABS :
0 commit comments