Skip to content

Commit 3142241

Browse files
author
Robin Müller
committed
Implemented first draft for smooth scroll slowdown
1 parent 48084fe commit 3142241

File tree

2 files changed

+60
-10
lines changed

2 files changed

+60
-10
lines changed

configure.ac

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ AC_PROG_CC
1212
# Checks for libraries.
1313
AC_CHECK_LIB([m], [sqrt], [], [AC_MSG_ERROR([libm is required])])
1414
AC_CHECK_LIB([iniparser], [iniparser_load], [], [AC_MSG_ERROR([libiniparser from http://ndevilla.free.fr/iniparser/ is required])])
15+
AC_CHECK_LIB(pthread, pthread_create, [], [AC_MSG_ERROR([pthread not found])])
1516

1617
# Checks for header files.
17-
AC_CHECK_HEADERS([fcntl.h stddef.h stdint.h stdlib.h string.h unistd.h])
18+
AC_CHECK_HEADERS([fcntl.h stddef.h stdint.h stdlib.h string.h unistd.h pthread.h])
1819
AC_CHECK_HEADERS([linux/input.h linux/uinput.h], [], [AC_MSG_ERROR([The linux header files are required])])
1920

2021
# Checks for typedefs, structures, and compiler characteristics.

src/gesture_detection.c

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,16 @@
2828
#include <math.h>
2929
#include <string.h>
3030
#include <stdlib.h>
31+
#include <time.h>
32+
#include <pthread.h>
3133

3234
#include <linux/input.h>
3335

3436
#include "gesture_detection.h"
3537

3638
// FIXME use 2 for SCROLL_FINGER_COUNT as soon as possible
3739
#define SCROLL_FINGER_COUNT 4
38-
40+
#define SCROLL_SLOW_DOWN_FACTOR -0.01
3941

4042
typedef struct point {
4143
int x;
@@ -53,7 +55,7 @@ typedef struct scroll {
5355
struct input_event last_y_abs_event;
5456
double x_velocity;
5557
double y_velocity;
56-
int32_t width;
58+
double width;
5759
} scroll_t;
5860

5961
typedef struct gesture_start {
@@ -64,7 +66,7 @@ typedef struct gesture_start {
6466
mt_slots_t mt_slots;
6567
gesture_start_t gesture_start;
6668
uint8_t finger_count;
67-
scroll_t scroll;
69+
volatile scroll_t scroll;
6870

6971
static int test_grab(int fd) {
7072
int rc;
@@ -80,12 +82,14 @@ static void init_gesture() {
8082
gesture_start.point.x = mt_slots.points[0].x;
8183
gesture_start.point.y = mt_slots.points[0].y;
8284

83-
if (finger_count == 2) {
85+
if (finger_count == SCROLL_FINGER_COUNT) {
8486
x_distance = mt_slots.points[0].x - mt_slots.points[1].x;
8587
y_distance = mt_slots.points[0].y - mt_slots.points[1].y;
8688
gesture_start.distance = (uint32_t) sqrt((x_distance * x_distance) + (y_distance * y_distance));
8789
scroll.width = 0;
8890
scroll.last_point = mt_slots.points[0];
91+
scroll.x_velocity = 0;
92+
scroll.y_velocity = 0;
8993
}
9094
}
9195

@@ -136,7 +140,7 @@ static void process_abs_event(struct input_event event) {
136140
} else if (mt_slots.active < 2) {
137141
switch (event.code) {
138142
case ABS_MT_POSITION_X:
139-
if (mt_slots.active == 0) {
143+
if (mt_slots.active == 0 && finger_count == SCROLL_FINGER_COUNT) {
140144
if (scroll.last_x_abs_event.type == EV_ABS && scroll.last_x_abs_event.code == ABS_MT_POSITION_X) {
141145
scroll.x_velocity = calcualte_velocity(event, scroll.last_x_abs_event);
142146
}
@@ -146,7 +150,7 @@ static void process_abs_event(struct input_event event) {
146150
mt_slots.points[mt_slots.active].x = event.value;
147151
break;
148152
case ABS_MT_POSITION_Y:
149-
if (mt_slots.active == 0) {
153+
if (mt_slots.active == 0 && finger_count == SCROLL_FINGER_COUNT) {
150154
if (scroll.last_y_abs_event.type == EV_ABS && scroll.last_y_abs_event.code == ABS_MT_POSITION_Y) {
151155
scroll.y_velocity = calcualte_velocity(scroll.last_y_abs_event, event);
152156
}
@@ -170,14 +174,15 @@ static void set_input_event(struct input_event *input_event, int type, int code,
170174
#define set_key_event(key_event, code, value) set_input_event(key_event, EV_KEY, code, value)
171175
#define set_rel_event(rel_event, code, value) set_input_event(rel_event, EV_REL, code, value)
172176

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) {
174178
input_event_array_t *result = NULL;
175179
scroll.width += distance;
176180
if (fabs(scroll.width) > delta) {
177181
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);
179184
set_syn_event(&result->data[1]);
180-
scroll.width %= delta;
185+
scroll.width -= width * delta;
181186
}
182187
return result;
183188
}
@@ -245,6 +250,38 @@ static int32_t get_axix_threshold(int fd, int axis, uint8_t percentage) {
245250
return (absinfo.maximum - absinfo.minimum) * percentage / 100;
246251
}
247252

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+
248285
void process_events(int fd, configuration_t config, void (*callback)(input_event_array_t*)) {
249286
struct input_event ev[64];
250287
int i, rd;
@@ -253,6 +290,8 @@ void process_events(int fd, configuration_t config, void (*callback)(input_event
253290
thresholds.x = get_axix_threshold(fd, ABS_X, config.horz_threshold_percentage);
254291
thresholds.y = get_axix_threshold(fd, ABS_Y, config.vert_threshold_percentage);
255292

293+
pthread_t thread = NULL;
294+
256295
if (thresholds.x < 0 || thresholds.y < 0) {
257296
return;
258297
}
@@ -275,6 +314,16 @@ void process_events(int fd, configuration_t config, void (*callback)(input_event
275314
finger_count = process_key_event(ev[i]);
276315
if (finger_count > 0) {
277316
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+
278327
}
279328
break;
280329
case EV_ABS:

0 commit comments

Comments
 (0)