Skip to content

Commit f36bdc1

Browse files
author
Robin Müller
committed
Improved the slowdown scrolling thread
- the scrolling thread can now also handle the horizontal scrolling - added some documentation comments
1 parent 3142241 commit f36bdc1

File tree

1 file changed

+67
-35
lines changed

1 file changed

+67
-35
lines changed

src/gesture_detection.c

Lines changed: 67 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737

3838
// FIXME use 2 for SCROLL_FINGER_COUNT as soon as possible
3939
#define SCROLL_FINGER_COUNT 4
40-
#define SCROLL_SLOW_DOWN_FACTOR -0.01
40+
#define SCROLL_SLOW_DOWN_FACTOR -0.006
4141

4242
typedef struct point {
4343
int x;
@@ -63,6 +63,12 @@ typedef struct gesture_start {
6363
uint32_t distance;
6464
} gesture_start_t;
6565

66+
typedef struct scroll_thread_params {
67+
uint8_t delta;
68+
int code;
69+
void (*callback)(input_event_array_t*);
70+
} scroll_thread_params_t;
71+
6672
mt_slots_t mt_slots;
6773
gesture_start_t gesture_start;
6874
uint8_t finger_count;
@@ -136,27 +142,38 @@ static double calcualte_velocity(struct input_event event1, struct input_event e
136142

137143
static void process_abs_event(struct input_event event) {
138144
if (event.code == ABS_MT_SLOT) {
145+
// store the current mt_slot
139146
mt_slots.active = event.value;
140147
} else if (mt_slots.active < 2) {
141148
switch (event.code) {
142149
case ABS_MT_POSITION_X:
150+
// if finger count matches SCROLL_FINGER_COUNT and the ABS_MT_POSITION_X is for the first finger
151+
// the scroll data need to be updated
143152
if (mt_slots.active == 0 && finger_count == SCROLL_FINGER_COUNT) {
153+
// check wether a correct input event was set to scroll.last_x_abs_event
144154
if (scroll.last_x_abs_event.type == EV_ABS && scroll.last_x_abs_event.code == ABS_MT_POSITION_X) {
145-
scroll.x_velocity = calcualte_velocity(event, scroll.last_x_abs_event);
155+
// invert the velocity to scroll to the correct direction as a positive x direction
156+
// on the touchpad mean scroll left (negative scroll direction)
157+
scroll.x_velocity = -calcualte_velocity(scroll.last_x_abs_event, event);
146158
}
147159
scroll.last_x_abs_event = event;
148160
scroll.last_point.x = mt_slots.points[0].x;
149161
}
162+
// store the current x position for the current mt_slot
150163
mt_slots.points[mt_slots.active].x = event.value;
151164
break;
152165
case ABS_MT_POSITION_Y:
166+
// if finger count matches SCROLL_FINGER_COUNT and the ABS_MT_POSITION_Y is for the first finger
167+
// the scroll data need to be updated
153168
if (mt_slots.active == 0 && finger_count == SCROLL_FINGER_COUNT) {
169+
// check wether a correct input event was set to scroll.last_y_abs_event
154170
if (scroll.last_y_abs_event.type == EV_ABS && scroll.last_y_abs_event.code == ABS_MT_POSITION_Y) {
155171
scroll.y_velocity = calcualte_velocity(scroll.last_y_abs_event, event);
156172
}
157173
scroll.last_y_abs_event = event;
158174
scroll.last_point.y = mt_slots.points[0].y;
159175
}
176+
// store the current y position for the current mt_slot
160177
mt_slots.points[mt_slots.active].y = event.value;
161178
break;
162179
}
@@ -176,7 +193,10 @@ static void set_input_event(struct input_event *input_event, int type, int code,
176193

177194
static input_event_array_t *do_scroll(double distance, int32_t delta, int rel_code) {
178195
input_event_array_t *result = NULL;
196+
// increment the scroll width by the current moved distance
179197
scroll.width += distance;
198+
// a scroll width of delta means scroll one "scroll-unit" therefore a scroll event
199+
// can be first triggered if the absolute value of scroll.width exeeded delta
180200
if (fabs(scroll.width) > delta) {
181201
result = new_input_event_array(2);
182202
int width = (int)(scroll.width / delta);
@@ -198,6 +218,8 @@ static input_event_array_t *process_syn_event(struct input_event event,
198218
x_distance = gesture_start.point.x - mt_slots.points[0].x;
199219
y_distance = gesture_start.point.y - mt_slots.points[0].y;
200220
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
201223
if (!(config.scroll.horz && finger_count == SCROLL_FINGER_COUNT)) {
202224
if (x_distance > thresholds.x) {
203225
direction = LEFT;
@@ -208,6 +230,8 @@ static input_event_array_t *process_syn_event(struct input_event event,
208230
result = do_scroll(scroll.last_point.x - mt_slots.points[0].x, config.scroll.horz_delta, REL_HWHEEL);
209231
}
210232
} 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
211235
if (!(config.scroll.vert && finger_count == SCROLL_FINGER_COUNT)) {
212236
if (y_distance > thresholds.y) {
213237
direction = UP;
@@ -250,34 +274,35 @@ static int32_t get_axix_threshold(int fd, int axis, uint8_t percentage) {
250274
return (absinfo.maximum - absinfo.minimum) * percentage / 100;
251275
}
252276

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;
277+
#define slowdown_scroll(velocity, thread_params) \
278+
while (velocity != 0) { \
279+
struct timespec tim = { \
280+
.tv_sec = 0, \
281+
.tv_nsec = 5000000 \
282+
};\
283+
nanosleep(&tim, NULL); \
284+
input_event_array_t *events = do_scroll(velocity * 5, thread_params->delta, thread_params->code); \
285+
if (events) { \
286+
thread_params->callback(events); \
287+
} \
288+
free(events); \
289+
double new_velocity = SCROLL_SLOW_DOWN_FACTOR * 5 + fabs(velocity); \
290+
if (new_velocity < 0) { \
291+
new_velocity = 0; \
292+
} \
293+
if (velocity > 0) { \
294+
velocity = new_velocity; \
295+
} else { \
296+
velocity = -new_velocity; \
297+
} \
298+
}
258299

259300
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-
}
301+
scroll_thread_params_t *params = ((scroll_thread_params_t*)val);
302+
if (params->code == REL_WHEEL) {
303+
slowdown_scroll(scroll.y_velocity, params);
304+
} else if (params->code == REL_HWHEEL) {
305+
slowdown_scroll(scroll.x_velocity, params);
281306
}
282307
return NULL;
283308
}
@@ -290,7 +315,7 @@ void process_events(int fd, configuration_t config, void (*callback)(input_event
290315
thresholds.x = get_axix_threshold(fd, ABS_X, config.horz_threshold_percentage);
291316
thresholds.y = get_axix_threshold(fd, ABS_Y, config.vert_threshold_percentage);
292317

293-
pthread_t thread = NULL;
318+
pthread_t scroll_thread = NULL;
294319

295320
if (thresholds.x < 0 || thresholds.y < 0) {
296321
return;
@@ -313,17 +338,24 @@ void process_events(int fd, configuration_t config, void (*callback)(input_event
313338
case EV_KEY:
314339
finger_count = process_key_event(ev[i]);
315340
if (finger_count > 0) {
341+
if (scroll_thread) {
342+
pthread_cancel(scroll_thread);
343+
}
316344
init_gesture();
317345
} else if (scroll.x_velocity != 0 || scroll.y_velocity != 0) {
318-
if (thread) {
319-
pthread_cancel(thread);
320-
}
321346
scroll_thread_params_t params = {
322-
.delta = config.scroll.vert_delta,
323347
.callback = callback
324348
};
325-
pthread_create(&thread, NULL, &scroll_thread_function, (void*) &params);
326-
349+
if (fabs(scroll.x_velocity * config.scroll.horz_delta) > fabs(scroll.y_velocity * config.scroll.vert_delta)) {
350+
params.delta = config.scroll.horz_delta;
351+
params.code = REL_HWHEEL;
352+
scroll.y_velocity = 0;
353+
} else {
354+
params.delta = config.scroll.vert_delta;
355+
params.code = REL_WHEEL;
356+
scroll.x_velocity = 0;
357+
}
358+
pthread_create(&scroll_thread, NULL, &scroll_thread_function, (void*) &params);
327359
}
328360
break;
329361
case EV_ABS:

0 commit comments

Comments
 (0)