Skip to content

Commit 3cc054a

Browse files
author
Robin Müller
committed
Added zoom functionality
- calculate the real vector direction in radian to determine wether to zoom or to scroll --> if the direction of the movement vectors of both fingers is almost equal the current gesture has to be SCROLL otherwise ZOOM
1 parent efe9e18 commit 3cc054a

File tree

1 file changed

+75
-28
lines changed

1 file changed

+75
-28
lines changed

src/gesture_detection.c

Lines changed: 75 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@
3838
#define SCROLL_FINGER_COUNT 2
3939
#define SCROLL_SLOW_DOWN_FACTOR -0.006
4040

41+
#define PI 3.14159265358979323846264338327
42+
#define PI_1_2 PI / 2
43+
44+
4145
typedef struct point {
4246
int x;
4347
int y;
@@ -59,7 +63,6 @@ typedef struct scroll {
5963

6064
typedef struct gesture_start {
6165
point_t point;
62-
uint32_t distance;
6366
} gesture_start_t;
6467

6568
typedef struct scroll_thread_params {
@@ -75,6 +78,7 @@ gesture_start_t gesture_start;
7578
uint8_t finger_count;
7679
volatile scroll_t scroll;
7780
gesture_t current_gesture;
81+
double last_zoom_distance;
7882

7983
static int test_grab(int fd) {
8084
int rc;
@@ -85,22 +89,22 @@ static int test_grab(int fd) {
8589
return rc;
8690
}
8791

88-
static uint8_t calculate_distance(point_t p1, point_t p2) {
92+
static double calculate_distance(point_t p1, point_t p2) {
8993
int32_t x_distance, y_distance;
9094
x_distance = p1.x - p2.x;
9195
y_distance = p1.y - p2.y;
92-
return (uint32_t) sqrt((x_distance * x_distance) + (y_distance * y_distance));
96+
return sqrt((x_distance * x_distance) + (y_distance * y_distance));
9397
}
9498

9599
static void init_gesture() {
96100
gesture_start.point = mt_slots.points[0];
101+
current_gesture = NO_GESTURE;
97102

98103
if (finger_count == SCROLL_FINGER_COUNT) {
99-
gesture_start.distance = calculate_distance(mt_slots.points[0], mt_slots.points[1]);
104+
last_zoom_distance = calculate_distance(mt_slots.points[0], mt_slots.points[1]);
100105
scroll.width = 0;
101106
scroll.x_velocity = 0;
102107
scroll.y_velocity = 0;
103-
current_gesture = NO_GESTURE;
104108
}
105109
}
106110

@@ -212,61 +216,104 @@ static input_event_array_t *do_scroll(double distance, int32_t delta, int rel_co
212216
return result;
213217
}
214218

215-
/*
216-
* @return a vector that can only have the following values for x and y: -1, 0, 1
217-
*/
218-
static point_t create_direction_vector(point_t p1, point_t p2) {
219-
point_t result;
220-
result.x = p1.x - p2.x;
221-
result.y = p1.y - p2.y;
222-
if (result.x != 0) {
223-
result.x /= fabs(result.x);
224-
}
225-
if (result.y != 0) {
226-
result.y /= fabs(result.y);
219+
static input_event_array_t *do_zoom(double distance, int32_t delta) {
220+
input_event_array_t *result = NULL;
221+
input_event_array_t *tmp = do_scroll(distance, delta, REL_WHEEL);
222+
if (tmp) {
223+
result = new_input_event_array(6);
224+
memset(&result->data[0], 0, sizeof(struct input_event));
225+
// press CTRL
226+
set_key_event(&result->data[0], KEY_LEFTCTRL, 1);
227+
set_syn_event(&result->data[1]);
228+
// copy the rel_event retrieve via do_scroll
229+
result->data[2] = tmp->data[0];
230+
set_syn_event(&result->data[3]);
231+
// release CTRL
232+
set_key_event(&result->data[4], KEY_LEFTCTRL, 0);
233+
set_syn_event(&result->data[5]);
234+
free(tmp);
227235
}
228236
return result;
229237
}
230238

231-
#define determine_gesture(scroll_enabled, v1, v2) \
239+
static point_t create_vector(point_t p1, point_t p2) {
240+
point_t result = {
241+
.x = p1.x - p2.x,
242+
.y = p1.y - p2.y
243+
};
244+
return result;
245+
}
246+
247+
#define determine_gesture(scroll_enabled, vector_direction_difference) \
232248
/* if scrolling is enable, the finger_count matches SCROLL_FINGER_COUNT and\
233249
the direction of the direction vectors for both fingers is equal the current_gesture\
234250
will be SCROLL*/\
235-
if (scroll_enabled && finger_count == SCROLL_FINGER_COUNT && v1 != 0 && v1 == v2) { \
251+
if (scroll_enabled && finger_count == SCROLL_FINGER_COUNT && vector_direction_difference < PI_1_2) { \
236252
current_gesture = SCROLL; \
237253
/* if no scrolling and zooming is enabled or the finger_count does not match\
238254
SCROLL_FINGER_COUNT the current_gesture will be SWIPE*/\
239255
} else if (!scroll_enabled || finger_count != SCROLL_FINGER_COUNT) { \
240256
current_gesture = SWIPE; \
241257
}
242258

259+
static double get_vector_direction(point_t v) {
260+
if (v.x == 0) {
261+
if (v.y >= 0) {
262+
return 0;
263+
} else {
264+
return PI;
265+
}
266+
} else if (v.y == 0) {
267+
if (v.x >= 0) {
268+
return PI / 2;
269+
} else {
270+
return 3 * PI / 2;
271+
}
272+
} else if (v.x > 0) {
273+
if (v.y > 0) {
274+
return atan(v.x / v.y);
275+
} else {
276+
return PI / 2 + atan(-v.y / v.x);
277+
}
278+
} else {
279+
if (v.y < 0) {
280+
return PI + atan(v.x / v.y);
281+
} else {
282+
return 3 * PI / 2 + atan(v.y / -v.x);
283+
}
284+
}
285+
}
286+
243287
static input_event_array_t *process_syn_event(struct input_event event,
244288
configuration_t config,
245289
point_t thresholds) {
246290
input_event_array_t *result = NULL;
247291
if (finger_count > 0 && event.code == SYN_REPORT) {
248292
direction_t direction = NONE;
249-
point_t v1;
250-
point_t v2;
293+
double vector_direction_difference;
251294
if (current_gesture == NO_GESTURE) {
252-
v1 = create_direction_vector(mt_slots.last_points[0], mt_slots.points[0]);
253-
v2 = create_direction_vector(mt_slots.last_points[1], mt_slots.points[1]);
295+
double v1_direction = get_vector_direction(create_vector(mt_slots.last_points[0], mt_slots.points[0]));
296+
double v2_direction = get_vector_direction(create_vector(mt_slots.last_points[1], mt_slots.points[1]));
297+
vector_direction_difference = fabs(v1_direction - v2_direction);
254298
// if zooming is enable, the finger_count matches SCROLL_FINGER_COUNT and the direction
255299
// vectors for both fingers are opposed to each other the current_gesture will be ZOOM
256-
if (config.zoom.enabled && finger_count == SCROLL_FINGER_COUNT && (v1.x != v2.x || v1.y != v2.y)) {
300+
if (config.zoom.enabled && finger_count == SCROLL_FINGER_COUNT && vector_direction_difference > PI_1_2) {
257301
current_gesture = ZOOM;
258302
}
259303
}
260304

261305
if (current_gesture == ZOOM) {
262-
printf("zoom\n");
306+
double finger_distance = calculate_distance(mt_slots.points[0], mt_slots.points[1]);
307+
// TODO make zoom delta configurable
308+
result = do_zoom(finger_distance - last_zoom_distance, 200);
309+
last_zoom_distance = finger_distance;
263310
} else {
264311
int32_t x_distance, y_distance;
265312
x_distance = gesture_start.point.x - mt_slots.points[0].x;
266313
y_distance = gesture_start.point.y - mt_slots.points[0].y;
267314
if (fabs(x_distance) > fabs(y_distance)) {
268315
if (current_gesture == NO_GESTURE) {
269-
determine_gesture(config.scroll.horz, v1.x, v2.x);
316+
determine_gesture(config.scroll.horz, vector_direction_difference);
270317
}
271318

272319
if (current_gesture == SWIPE) {
@@ -280,7 +327,7 @@ static input_event_array_t *process_syn_event(struct input_event event,
280327
}
281328
} else {
282329
if (current_gesture == NO_GESTURE) {
283-
determine_gesture(config.scroll.vert, v1.y, v2.y);
330+
determine_gesture(config.scroll.vert, vector_direction_difference);
284331
}
285332

286333
if (current_gesture == SWIPE) {
@@ -397,7 +444,7 @@ void process_events(int fd, configuration_t config, void (*callback)(input_event
397444
}
398445
init_gesture();
399446
syn_event_skip_counter = 0;
400-
} else if (scroll.x_velocity != 0 || scroll.y_velocity != 0) {
447+
} else if (current_gesture == SCROLL && (scroll.x_velocity != 0 || scroll.y_velocity != 0)) {
401448
scroll_thread_params_t params = {
402449
.callback = callback
403450
};

0 commit comments

Comments
 (0)