1 /**
2 * @file lv_indev.c
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 ********************/
9 #include "lv_indev.h"
10 #include "lv_disp.h"
11 #include "lv_obj.h"
12 #include "lv_indev_scroll.h"
13 #include "lv_group.h"
14 #include "lv_refr.h"
15
16 #include "../hal/lv_hal_tick.h"
17 #include "../misc/lv_timer.h"
18 #include "../misc/lv_math.h"
19
20 /*********************
21 * DEFINES
22 *********************/
23 #if LV_INDEV_DEF_SCROLL_THROW <= 0
24 #warning "LV_INDEV_DRAG_THROW must be greater than 0"
25 #endif
26
27 /**********************
28 * TYPEDEFS
29 **********************/
30
31 /**********************
32 * STATIC PROTOTYPES
33 **********************/
34 static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data);
35 static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data);
36 static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data);
37 static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data);
38 static void indev_proc_press(_lv_indev_proc_t * proc);
39 static void indev_proc_release(_lv_indev_proc_t * proc);
40 static void indev_proc_reset_query_handler(lv_indev_t * indev);
41 static void indev_click_focus(_lv_indev_proc_t * proc);
42 static void indev_gesture(_lv_indev_proc_t * proc);
43 static bool indev_reset_check(_lv_indev_proc_t * proc);
44
45 /**********************
46 * STATIC VARIABLES
47 **********************/
48 static lv_indev_t * indev_act;
49 static lv_obj_t * indev_obj_act = NULL;
50
51 /**********************
52 * MACROS
53 **********************/
54 #if LV_LOG_TRACE_INDEV
55 #define INDEV_TRACE(...) LV_LOG_TRACE(__VA_ARGS__)
56 #else
57 #define INDEV_TRACE(...)
58 #endif
59
60 /**********************
61 * GLOBAL FUNCTIONS
62 **********************/
63
lv_indev_read_timer_cb(lv_timer_t * timer)64 void lv_indev_read_timer_cb(lv_timer_t * timer)
65 {
66 INDEV_TRACE("begin");
67
68 lv_indev_data_t data;
69
70 indev_act = timer->user_data;
71
72 /*Read and process all indevs*/
73 if(indev_act->driver->disp == NULL) return; /*Not assigned to any displays*/
74
75 /*Handle reset query before processing the point*/
76 indev_proc_reset_query_handler(indev_act);
77
78 if(indev_act->proc.disabled) return;
79 bool continue_reading;
80 do {
81 /*Read the data*/
82 _lv_indev_read(indev_act, &data);
83 continue_reading = data.continue_reading;
84
85 /*The active object might deleted even in the read function*/
86 indev_proc_reset_query_handler(indev_act);
87 indev_obj_act = NULL;
88
89 indev_act->proc.state = data.state;
90
91 /*Save the last activity time*/
92 if(indev_act->proc.state == LV_INDEV_STATE_PRESSED) {
93 indev_act->driver->disp->last_activity_time = lv_tick_get();
94 }
95 else if(indev_act->driver->type == LV_INDEV_TYPE_ENCODER && data.enc_diff) {
96 indev_act->driver->disp->last_activity_time = lv_tick_get();
97 }
98
99 if(indev_act->driver->type == LV_INDEV_TYPE_POINTER) {
100 indev_pointer_proc(indev_act, &data);
101 }
102 else if(indev_act->driver->type == LV_INDEV_TYPE_KEYPAD) {
103 indev_keypad_proc(indev_act, &data);
104 }
105 else if(indev_act->driver->type == LV_INDEV_TYPE_ENCODER) {
106 indev_encoder_proc(indev_act, &data);
107 }
108 else if(indev_act->driver->type == LV_INDEV_TYPE_BUTTON) {
109 indev_button_proc(indev_act, &data);
110 }
111 /*Handle reset query if it happened in during processing*/
112 indev_proc_reset_query_handler(indev_act);
113 } while(continue_reading);
114
115 /*End of indev processing, so no act indev*/
116 indev_act = NULL;
117 indev_obj_act = NULL;
118
119 INDEV_TRACE("finished");
120 }
121
lv_indev_enable(lv_indev_t * indev,bool en)122 void lv_indev_enable(lv_indev_t * indev, bool en)
123 {
124 if(!indev) return;
125
126 indev->proc.disabled = en ? 0 : 1;
127 }
128
lv_indev_get_act(void)129 lv_indev_t * lv_indev_get_act(void)
130 {
131 return indev_act;
132 }
133
lv_indev_get_type(const lv_indev_t * indev)134 lv_indev_type_t lv_indev_get_type(const lv_indev_t * indev)
135 {
136 if(indev == NULL) return LV_INDEV_TYPE_NONE;
137
138 return indev->driver->type;
139 }
140
lv_indev_reset(lv_indev_t * indev,lv_obj_t * obj)141 void lv_indev_reset(lv_indev_t * indev, lv_obj_t * obj)
142 {
143 if(indev) {
144 indev->proc.reset_query = 1;
145 if(indev_act == indev) indev_obj_act = NULL;
146 if(indev->driver->type == LV_INDEV_TYPE_POINTER || indev->driver->type == LV_INDEV_TYPE_KEYPAD) {
147 if(obj == NULL || indev->proc.types.pointer.last_pressed == obj) {
148 indev->proc.types.pointer.last_pressed = NULL;
149 }
150 if(obj == NULL || indev->proc.types.pointer.act_obj == obj) {
151 indev->proc.types.pointer.act_obj = NULL;
152 }
153 if(obj == NULL || indev->proc.types.pointer.last_obj == obj) {
154 indev->proc.types.pointer.last_obj = NULL;
155 }
156 }
157 }
158 else {
159 lv_indev_t * i = lv_indev_get_next(NULL);
160 while(i) {
161 i->proc.reset_query = 1;
162 if(i->driver->type == LV_INDEV_TYPE_POINTER || i->driver->type == LV_INDEV_TYPE_KEYPAD) {
163 if(obj == NULL || i->proc.types.pointer.last_pressed == obj) {
164 i->proc.types.pointer.last_pressed = NULL;
165 }
166 if(obj == NULL || i->proc.types.pointer.act_obj == obj) {
167 i->proc.types.pointer.act_obj = NULL;
168 }
169 if(obj == NULL || i->proc.types.pointer.last_obj == obj) {
170 i->proc.types.pointer.last_obj = NULL;
171 }
172 }
173 i = lv_indev_get_next(i);
174 }
175 indev_obj_act = NULL;
176 }
177 }
178
lv_indev_reset_long_press(lv_indev_t * indev)179 void lv_indev_reset_long_press(lv_indev_t * indev)
180 {
181 indev->proc.long_pr_sent = 0;
182 indev->proc.longpr_rep_timestamp = lv_tick_get();
183 indev->proc.pr_timestamp = lv_tick_get();
184 }
185
lv_indev_set_cursor(lv_indev_t * indev,lv_obj_t * cur_obj)186 void lv_indev_set_cursor(lv_indev_t * indev, lv_obj_t * cur_obj)
187 {
188 if(indev->driver->type != LV_INDEV_TYPE_POINTER) return;
189
190 indev->cursor = cur_obj;
191 lv_obj_set_parent(indev->cursor, lv_disp_get_layer_sys(indev->driver->disp));
192 lv_obj_set_pos(indev->cursor, indev->proc.types.pointer.act_point.x, indev->proc.types.pointer.act_point.y);
193 lv_obj_clear_flag(indev->cursor, LV_OBJ_FLAG_CLICKABLE);
194 lv_obj_add_flag(indev->cursor, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_FLOATING);
195 }
196
lv_indev_set_group(lv_indev_t * indev,lv_group_t * group)197 void lv_indev_set_group(lv_indev_t * indev, lv_group_t * group)
198 {
199 if(indev->driver->type == LV_INDEV_TYPE_KEYPAD || indev->driver->type == LV_INDEV_TYPE_ENCODER) {
200 indev->group = group;
201 }
202 }
203
lv_indev_set_button_points(lv_indev_t * indev,const lv_point_t points[])204 void lv_indev_set_button_points(lv_indev_t * indev, const lv_point_t points[])
205 {
206 if(indev->driver->type == LV_INDEV_TYPE_BUTTON) {
207 indev->btn_points = points;
208 }
209 }
210
lv_indev_get_point(const lv_indev_t * indev,lv_point_t * point)211 void lv_indev_get_point(const lv_indev_t * indev, lv_point_t * point)
212 {
213 if(indev == NULL) {
214 point->x = 0;
215 point->y = 0;
216 return;
217 }
218 if(indev->driver->type != LV_INDEV_TYPE_POINTER && indev->driver->type != LV_INDEV_TYPE_BUTTON) {
219 point->x = -1;
220 point->y = -1;
221 }
222 else {
223 point->x = indev->proc.types.pointer.act_point.x;
224 point->y = indev->proc.types.pointer.act_point.y;
225 }
226 }
227
lv_indev_get_gesture_dir(const lv_indev_t * indev)228 lv_dir_t lv_indev_get_gesture_dir(const lv_indev_t * indev)
229 {
230 return indev->proc.types.pointer.gesture_dir;
231 }
232
lv_indev_get_key(const lv_indev_t * indev)233 uint32_t lv_indev_get_key(const lv_indev_t * indev)
234 {
235 if(indev->driver->type != LV_INDEV_TYPE_KEYPAD)
236 return 0;
237 else
238 return indev->proc.types.keypad.last_key;
239 }
240
lv_indev_get_scroll_dir(const lv_indev_t * indev)241 lv_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev)
242 {
243 if(indev == NULL) return false;
244 if(indev->driver->type != LV_INDEV_TYPE_POINTER && indev->driver->type != LV_INDEV_TYPE_BUTTON) return false;
245 return indev->proc.types.pointer.scroll_dir;
246 }
247
lv_indev_get_scroll_obj(const lv_indev_t * indev)248 lv_obj_t * lv_indev_get_scroll_obj(const lv_indev_t * indev)
249 {
250 if(indev == NULL) return NULL;
251 if(indev->driver->type != LV_INDEV_TYPE_POINTER && indev->driver->type != LV_INDEV_TYPE_BUTTON) return NULL;
252 return indev->proc.types.pointer.scroll_obj;
253 }
254
lv_indev_get_vect(const lv_indev_t * indev,lv_point_t * point)255 void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point)
256 {
257 point->x = 0;
258 point->y = 0;
259
260 if(indev == NULL) return;
261
262 if(indev->driver->type == LV_INDEV_TYPE_POINTER || indev->driver->type == LV_INDEV_TYPE_BUTTON) {
263 point->x = indev->proc.types.pointer.vect.x;
264 point->y = indev->proc.types.pointer.vect.y;
265 }
266 }
267
lv_indev_wait_release(lv_indev_t * indev)268 void lv_indev_wait_release(lv_indev_t * indev)
269 {
270 if(indev == NULL)return;
271 indev->proc.wait_until_release = 1;
272 }
273
lv_indev_get_obj_act(void)274 lv_obj_t * lv_indev_get_obj_act(void)
275 {
276 return indev_obj_act;
277 }
278
lv_indev_get_read_timer(lv_disp_t * indev)279 lv_timer_t * lv_indev_get_read_timer(lv_disp_t * indev)
280 {
281 if(!indev) {
282 LV_LOG_WARN("lv_indev_get_read_timer: indev was NULL");
283 return NULL;
284 }
285
286 return indev->refr_timer;
287 }
288
lv_indev_search_obj(lv_obj_t * obj,lv_point_t * point)289 lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point)
290 {
291 lv_obj_t * found_p = NULL;
292
293 /*If this obj is hidden the children are hidden too so return immediately*/
294 if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return NULL;
295
296 bool hit_test_ok = lv_obj_hit_test(obj, point);
297
298 /*If the point is on this object or has overflow visible check its children too*/
299 if(_lv_area_is_point_on(&obj->coords, point, 0) || lv_obj_has_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) {
300 int32_t i;
301 uint32_t child_cnt = lv_obj_get_child_cnt(obj);
302 /*If a child matches use it*/
303 for(i = child_cnt - 1; i >= 0; i--) {
304 lv_obj_t * child = obj->spec_attr->children[i];
305 found_p = lv_indev_search_obj(child, point);
306 if(found_p) return found_p;
307 }
308 }
309
310 /*If not return earlier for a clicked child and this obj's hittest was ok use it
311 *else return NULL*/
312 if(hit_test_ok) return obj;
313 else return NULL;
314 }
315
316 /**********************
317 * STATIC FUNCTIONS
318 **********************/
319
320 /**
321 * Process a new point from LV_INDEV_TYPE_POINTER input device
322 * @param i pointer to an input device
323 * @param data pointer to the data read from the input device
324 */
indev_pointer_proc(lv_indev_t * i,lv_indev_data_t * data)325 static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data)
326 {
327 lv_disp_t * disp = i->driver->disp;
328 /*Save the raw points so they can be used again in _lv_indev_read*/
329 i->proc.types.pointer.last_raw_point.x = data->point.x;
330 i->proc.types.pointer.last_raw_point.y = data->point.y;
331
332 if(disp->driver->rotated == LV_DISP_ROT_180 || disp->driver->rotated == LV_DISP_ROT_270) {
333 data->point.x = disp->driver->hor_res - data->point.x - 1;
334 data->point.y = disp->driver->ver_res - data->point.y - 1;
335 }
336 if(disp->driver->rotated == LV_DISP_ROT_90 || disp->driver->rotated == LV_DISP_ROT_270) {
337 lv_coord_t tmp = data->point.y;
338 data->point.y = data->point.x;
339 data->point.x = disp->driver->ver_res - tmp - 1;
340 }
341
342 /*Simple sanity check*/
343 if(data->point.x < 0) {
344 LV_LOG_WARN("X is %d which is smaller than zero", data->point.x);
345 }
346 if(data->point.x >= lv_disp_get_hor_res(i->driver->disp)) {
347 LV_LOG_WARN("X is %d which is greater than hor. res", data->point.x);
348 }
349 if(data->point.y < 0) {
350 LV_LOG_WARN("Y is %d which is smaller than zero", data->point.y);
351 }
352 if(data->point.y >= lv_disp_get_ver_res(i->driver->disp)) {
353 LV_LOG_WARN("Y is %d which is greater than ver. res", data->point.y);
354 }
355
356 /*Move the cursor if set and moved*/
357 if(i->cursor != NULL &&
358 (i->proc.types.pointer.last_point.x != data->point.x || i->proc.types.pointer.last_point.y != data->point.y)) {
359 lv_obj_set_pos(i->cursor, data->point.x, data->point.y);
360 }
361
362 i->proc.types.pointer.act_point.x = data->point.x;
363 i->proc.types.pointer.act_point.y = data->point.y;
364
365 if(i->proc.state == LV_INDEV_STATE_PRESSED) {
366 indev_proc_press(&i->proc);
367 }
368 else {
369 indev_proc_release(&i->proc);
370 }
371
372 i->proc.types.pointer.last_point.x = i->proc.types.pointer.act_point.x;
373 i->proc.types.pointer.last_point.y = i->proc.types.pointer.act_point.y;
374 }
375
376 /**
377 * Process a new point from LV_INDEV_TYPE_KEYPAD input device
378 * @param i pointer to an input device
379 * @param data pointer to the data read from the input device
380 */
indev_keypad_proc(lv_indev_t * i,lv_indev_data_t * data)381 static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data)
382 {
383 if(data->state == LV_INDEV_STATE_PRESSED && i->proc.wait_until_release) return;
384
385 if(i->proc.wait_until_release) {
386 i->proc.wait_until_release = 0;
387 i->proc.pr_timestamp = 0;
388 i->proc.long_pr_sent = 0;
389 i->proc.types.keypad.last_state = LV_INDEV_STATE_RELEASED; /*To skip the processing of release*/
390 }
391
392 lv_group_t * g = i->group;
393 if(g == NULL) return;
394
395 indev_obj_act = lv_group_get_focused(g);
396 if(indev_obj_act == NULL) return;
397
398 /*Save the last key to compare it with the current latter on RELEASE*/
399 uint32_t prev_key = i->proc.types.keypad.last_key;
400
401 /*Save the last key.
402 *It must be done here else `lv_indev_get_key` will return the last key in events*/
403 i->proc.types.keypad.last_key = data->key;
404
405 /*Save the previous state so we can detect state changes below and also set the last state now
406 *so if any event handler on the way returns `LV_RES_INV` the last state is remembered
407 *for the next time*/
408 uint32_t prev_state = i->proc.types.keypad.last_state;
409 i->proc.types.keypad.last_state = data->state;
410
411 /*Key press happened*/
412 if(data->state == LV_INDEV_STATE_PRESSED && prev_state == LV_INDEV_STATE_RELEASED) {
413 LV_LOG_INFO("%d key is pressed", data->key);
414 i->proc.pr_timestamp = lv_tick_get();
415
416 /*Simulate a press on the object if ENTER was pressed*/
417 if(data->key == LV_KEY_ENTER) {
418 /*Send the ENTER as a normal KEY*/
419 lv_group_send_data(g, LV_KEY_ENTER);
420
421 lv_event_send(indev_obj_act, LV_EVENT_PRESSED, indev_act);
422 if(indev_reset_check(&i->proc)) return;
423 }
424 else if(data->key == LV_KEY_ESC) {
425 /*Send the ESC as a normal KEY*/
426 lv_group_send_data(g, LV_KEY_ESC);
427
428 lv_event_send(indev_obj_act, LV_EVENT_CANCEL, indev_act);
429 if(indev_reset_check(&i->proc)) return;
430 }
431 /*Move the focus on NEXT*/
432 else if(data->key == LV_KEY_NEXT) {
433 lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/
434 lv_group_focus_next(g);
435 if(indev_reset_check(&i->proc)) return;
436 }
437 /*Move the focus on PREV*/
438 else if(data->key == LV_KEY_PREV) {
439 lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/
440 lv_group_focus_prev(g);
441 if(indev_reset_check(&i->proc)) return;
442 }
443 /*Just send other keys to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT`)*/
444 else {
445 lv_group_send_data(g, data->key);
446 }
447 }
448 /*Pressing*/
449 else if(data->state == LV_INDEV_STATE_PRESSED && prev_state == LV_INDEV_STATE_PRESSED) {
450
451 if(data->key == LV_KEY_ENTER) {
452 lv_event_send(indev_obj_act, LV_EVENT_PRESSING, indev_act);
453 if(indev_reset_check(&i->proc)) return;
454 }
455
456 /*Long press time has elapsed?*/
457 if(i->proc.long_pr_sent == 0 && lv_tick_elaps(i->proc.pr_timestamp) > i->driver->long_press_time) {
458 i->proc.long_pr_sent = 1;
459 if(data->key == LV_KEY_ENTER) {
460 i->proc.longpr_rep_timestamp = lv_tick_get();
461 lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED, indev_act);
462 if(indev_reset_check(&i->proc)) return;
463 }
464 }
465 /*Long press repeated time has elapsed?*/
466 else if(i->proc.long_pr_sent != 0 &&
467 lv_tick_elaps(i->proc.longpr_rep_timestamp) > i->driver->long_press_repeat_time) {
468
469 i->proc.longpr_rep_timestamp = lv_tick_get();
470
471 /*Send LONG_PRESS_REP on ENTER*/
472 if(data->key == LV_KEY_ENTER) {
473 lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED_REPEAT, indev_act);
474 if(indev_reset_check(&i->proc)) return;
475 }
476 /*Move the focus on NEXT again*/
477 else if(data->key == LV_KEY_NEXT) {
478 lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/
479 lv_group_focus_next(g);
480 if(indev_reset_check(&i->proc)) return;
481 }
482 /*Move the focus on PREV again*/
483 else if(data->key == LV_KEY_PREV) {
484 lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/
485 lv_group_focus_prev(g);
486 if(indev_reset_check(&i->proc)) return;
487 }
488 /*Just send other keys again to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT)*/
489 else {
490 lv_group_send_data(g, data->key);
491 if(indev_reset_check(&i->proc)) return;
492 }
493 }
494 }
495 /*Release happened*/
496 else if(data->state == LV_INDEV_STATE_RELEASED && prev_state == LV_INDEV_STATE_PRESSED) {
497 LV_LOG_INFO("%d key is released", data->key);
498 /*The user might clear the key when it was released. Always release the pressed key*/
499 data->key = prev_key;
500 if(data->key == LV_KEY_ENTER) {
501
502 lv_event_send(indev_obj_act, LV_EVENT_RELEASED, indev_act);
503 if(indev_reset_check(&i->proc)) return;
504
505 if(i->proc.long_pr_sent == 0) {
506 lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, indev_act);
507 if(indev_reset_check(&i->proc)) return;
508 }
509
510 lv_event_send(indev_obj_act, LV_EVENT_CLICKED, indev_act);
511 if(indev_reset_check(&i->proc)) return;
512
513 }
514 i->proc.pr_timestamp = 0;
515 i->proc.long_pr_sent = 0;
516 }
517 indev_obj_act = NULL;
518 }
519
520 /**
521 * Process a new point from LV_INDEV_TYPE_ENCODER input device
522 * @param i pointer to an input device
523 * @param data pointer to the data read from the input device
524 */
indev_encoder_proc(lv_indev_t * i,lv_indev_data_t * data)525 static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data)
526 {
527 if(data->state == LV_INDEV_STATE_PRESSED && i->proc.wait_until_release) return;
528
529 if(i->proc.wait_until_release) {
530 i->proc.wait_until_release = 0;
531 i->proc.pr_timestamp = 0;
532 i->proc.long_pr_sent = 0;
533 i->proc.types.keypad.last_state = LV_INDEV_STATE_RELEASED; /*To skip the processing of release*/
534 }
535
536 /*Save the last keys before anything else.
537 *They need to be already saved if the function returns for any reason*/
538 lv_indev_state_t last_state = i->proc.types.keypad.last_state;
539 i->proc.types.keypad.last_state = data->state;
540 i->proc.types.keypad.last_key = data->key;
541
542 lv_group_t * g = i->group;
543 if(g == NULL) return;
544
545 indev_obj_act = lv_group_get_focused(g);
546 if(indev_obj_act == NULL) return;
547
548 /*Process the steps they are valid only with released button*/
549 if(data->state != LV_INDEV_STATE_RELEASED) {
550 data->enc_diff = 0;
551 }
552
553 /*Refresh the focused object. It might change due to lv_group_focus_prev/next*/
554 indev_obj_act = lv_group_get_focused(g);
555 if(indev_obj_act == NULL) return;
556
557 /*Button press happened*/
558 if(data->state == LV_INDEV_STATE_PRESSED && last_state == LV_INDEV_STATE_RELEASED) {
559 LV_LOG_INFO("pressed");
560
561 i->proc.pr_timestamp = lv_tick_get();
562
563 if(data->key == LV_KEY_ENTER) {
564 bool editable_or_scrollable = lv_obj_is_editable(indev_obj_act) ||
565 lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_SCROLLABLE);
566 if(lv_group_get_editing(g) == true || editable_or_scrollable == false) {
567 lv_event_send(indev_obj_act, LV_EVENT_PRESSED, indev_act);
568 if(indev_reset_check(&i->proc)) return;
569 }
570 }
571 else if(data->key == LV_KEY_LEFT) {
572 /*emulate encoder left*/
573 data->enc_diff--;
574 }
575 else if(data->key == LV_KEY_RIGHT) {
576 /*emulate encoder right*/
577 data->enc_diff++;
578 }
579 else if(data->key == LV_KEY_ESC) {
580 /*Send the ESC as a normal KEY*/
581 lv_group_send_data(g, LV_KEY_ESC);
582
583 lv_event_send(indev_obj_act, LV_EVENT_CANCEL, indev_act);
584 if(indev_reset_check(&i->proc)) return;
585 }
586 /*Just send other keys to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT`)*/
587 else {
588 lv_group_send_data(g, data->key);
589 }
590 }
591 /*Pressing*/
592 else if(data->state == LV_INDEV_STATE_PRESSED && last_state == LV_INDEV_STATE_PRESSED) {
593 /*Long press*/
594 if(i->proc.long_pr_sent == 0 && lv_tick_elaps(i->proc.pr_timestamp) > i->driver->long_press_time) {
595
596 i->proc.long_pr_sent = 1;
597 i->proc.longpr_rep_timestamp = lv_tick_get();
598
599 if(data->key == LV_KEY_ENTER) {
600 bool editable_or_scrollable = lv_obj_is_editable(indev_obj_act) ||
601 lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_SCROLLABLE);
602
603 /*On enter long press toggle edit mode.*/
604 if(editable_or_scrollable) {
605 /*Don't leave edit mode if there is only one object (nowhere to navigate)*/
606 if(lv_group_get_obj_count(g) > 1) {
607 LV_LOG_INFO("toggling edit mode");
608 lv_group_set_editing(g, lv_group_get_editing(g) ? false : true); /*Toggle edit mode on long press*/
609 lv_obj_clear_state(indev_obj_act, LV_STATE_PRESSED); /*Remove the pressed state manually*/
610 }
611 }
612 /*If not editable then just send a long press Call the ancestor's event handler*/
613 else {
614 lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED, indev_act);
615 if(indev_reset_check(&i->proc)) return;
616 }
617 }
618
619 i->proc.long_pr_sent = 1;
620 }
621 /*Long press repeated time has elapsed?*/
622 else if(i->proc.long_pr_sent != 0 && lv_tick_elaps(i->proc.longpr_rep_timestamp) > i->driver->long_press_repeat_time) {
623
624 i->proc.longpr_rep_timestamp = lv_tick_get();
625
626 if(data->key == LV_KEY_ENTER) {
627 lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED_REPEAT, indev_act);
628 if(indev_reset_check(&i->proc)) return;
629 }
630 else if(data->key == LV_KEY_LEFT) {
631 /*emulate encoder left*/
632 data->enc_diff--;
633 }
634 else if(data->key == LV_KEY_RIGHT) {
635 /*emulate encoder right*/
636 data->enc_diff++;
637 }
638 else {
639 lv_group_send_data(g, data->key);
640 if(indev_reset_check(&i->proc)) return;
641 }
642
643 }
644
645 }
646 /*Release happened*/
647 else if(data->state == LV_INDEV_STATE_RELEASED && last_state == LV_INDEV_STATE_PRESSED) {
648 LV_LOG_INFO("released");
649
650 if(data->key == LV_KEY_ENTER) {
651 bool editable_or_scrollable = lv_obj_is_editable(indev_obj_act) ||
652 lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_SCROLLABLE);
653
654 /*The button was released on a non-editable object. Just send enter*/
655 if(editable_or_scrollable == false) {
656 lv_event_send(indev_obj_act, LV_EVENT_RELEASED, indev_act);
657 if(indev_reset_check(&i->proc)) return;
658
659 if(i->proc.long_pr_sent == 0) lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, indev_act);
660 if(indev_reset_check(&i->proc)) return;
661
662 lv_event_send(indev_obj_act, LV_EVENT_CLICKED, indev_act);
663 if(indev_reset_check(&i->proc)) return;
664
665 }
666 /*An object is being edited and the button is released.*/
667 else if(lv_group_get_editing(g)) {
668 /*Ignore long pressed enter release because it comes from mode switch*/
669 if(!i->proc.long_pr_sent || lv_group_get_obj_count(g) <= 1) {
670 lv_event_send(indev_obj_act, LV_EVENT_RELEASED, indev_act);
671 if(indev_reset_check(&i->proc)) return;
672
673 lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, indev_act);
674 if(indev_reset_check(&i->proc)) return;
675
676 lv_event_send(indev_obj_act, LV_EVENT_CLICKED, indev_act);
677 if(indev_reset_check(&i->proc)) return;
678
679
680 lv_group_send_data(g, LV_KEY_ENTER);
681 }
682 else {
683 lv_obj_clear_state(indev_obj_act, LV_STATE_PRESSED); /*Remove the pressed state manually*/
684 }
685 }
686 /*If the focused object is editable and now in navigate mode then on enter switch edit
687 mode*/
688 else if(!i->proc.long_pr_sent) {
689 LV_LOG_INFO("entering edit mode");
690 lv_group_set_editing(g, true); /*Set edit mode*/
691 }
692 }
693
694 i->proc.pr_timestamp = 0;
695 i->proc.long_pr_sent = 0;
696 }
697 indev_obj_act = NULL;
698
699 /*if encoder steps or simulated steps via left/right keys*/
700 if(data->enc_diff != 0) {
701 /*In edit mode send LEFT/RIGHT keys*/
702 if(lv_group_get_editing(g)) {
703 LV_LOG_INFO("rotated by %+d (edit)", data->enc_diff);
704 int32_t s;
705 if(data->enc_diff < 0) {
706 for(s = 0; s < -data->enc_diff; s++) lv_group_send_data(g, LV_KEY_LEFT);
707 }
708 else if(data->enc_diff > 0) {
709 for(s = 0; s < data->enc_diff; s++) lv_group_send_data(g, LV_KEY_RIGHT);
710 }
711 }
712 /*In navigate mode focus on the next/prev objects*/
713 else {
714 LV_LOG_INFO("rotated by %+d (nav)", data->enc_diff);
715 int32_t s;
716 if(data->enc_diff < 0) {
717 for(s = 0; s < -data->enc_diff; s++) lv_group_focus_prev(g);
718 }
719 else if(data->enc_diff > 0) {
720 for(s = 0; s < data->enc_diff; s++) lv_group_focus_next(g);
721 }
722 }
723 }
724 }
725
726 /**
727 * Process new points from an input device. indev->state.pressed has to be set
728 * @param indev pointer to an input device state
729 * @param x x coordinate of the next point
730 * @param y y coordinate of the next point
731 */
indev_button_proc(lv_indev_t * i,lv_indev_data_t * data)732 static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data)
733 {
734 /*Die gracefully if i->btn_points is NULL*/
735 if(i->btn_points == NULL) {
736 LV_LOG_WARN("btn_points is NULL");
737 return;
738 }
739
740 lv_coord_t x = i->btn_points[data->btn_id].x;
741 lv_coord_t y = i->btn_points[data->btn_id].y;
742
743 static lv_indev_state_t prev_state = LV_INDEV_STATE_RELEASED;
744 if(prev_state != data->state) {
745 if(data->state == LV_INDEV_STATE_PRESSED) {
746 LV_LOG_INFO("button %d is pressed (x:%d y:%d)", data->btn_id, x, y);
747 }
748 else {
749 LV_LOG_INFO("button %d is released (x:%d y:%d)", data->btn_id, x, y);
750 }
751 }
752
753 /*If a new point comes always make a release*/
754 if(data->state == LV_INDEV_STATE_PRESSED) {
755 if(i->proc.types.pointer.last_point.x != x ||
756 i->proc.types.pointer.last_point.y != y) {
757 indev_proc_release(&i->proc);
758 }
759 }
760
761 if(indev_reset_check(&i->proc)) return;
762
763 /*Save the new points*/
764 i->proc.types.pointer.act_point.x = x;
765 i->proc.types.pointer.act_point.y = y;
766
767 if(data->state == LV_INDEV_STATE_PRESSED) indev_proc_press(&i->proc);
768 else indev_proc_release(&i->proc);
769
770 if(indev_reset_check(&i->proc)) return;
771
772 i->proc.types.pointer.last_point.x = i->proc.types.pointer.act_point.x;
773 i->proc.types.pointer.last_point.y = i->proc.types.pointer.act_point.y;
774 }
775
776 /**
777 * Process the pressed state of LV_INDEV_TYPE_POINTER input devices
778 * @param indev pointer to an input device 'proc'
779 * @return LV_RES_OK: no indev reset required; LV_RES_INV: indev reset is required
780 */
indev_proc_press(_lv_indev_proc_t * proc)781 static void indev_proc_press(_lv_indev_proc_t * proc)
782 {
783 LV_LOG_INFO("pressed at x:%d y:%d", proc->types.pointer.act_point.x, proc->types.pointer.act_point.y);
784 indev_obj_act = proc->types.pointer.act_obj;
785
786 if(proc->wait_until_release != 0) return;
787
788 lv_disp_t * disp = indev_act->driver->disp;
789 bool new_obj_searched = false;
790
791 /*If there is no last object then search*/
792 if(indev_obj_act == NULL) {
793 indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_sys(disp), &proc->types.pointer.act_point);
794 if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_top(disp),
795 &proc->types.pointer.act_point);
796 if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_scr_act(disp),
797 &proc->types.pointer.act_point);
798 new_obj_searched = true;
799 }
800 /*If there is last object but it is not scrolled and not protected also search*/
801 else if(proc->types.pointer.scroll_obj == NULL &&
802 lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_PRESS_LOCK) == false) {
803 indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_sys(disp), &proc->types.pointer.act_point);
804 if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_top(disp),
805 &proc->types.pointer.act_point);
806 if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_scr_act(disp),
807 &proc->types.pointer.act_point);
808 new_obj_searched = true;
809 }
810
811 /*The last object might have scroll throw. Stop it manually*/
812 if(new_obj_searched && proc->types.pointer.last_obj) {
813 proc->types.pointer.scroll_throw_vect.x = 0;
814 proc->types.pointer.scroll_throw_vect.y = 0;
815 _lv_indev_scroll_throw_handler(proc);
816 if(indev_reset_check(proc)) return;
817 }
818
819 /*If a new object was found reset some variables and send a pressed Call the ancestor's event handler*/
820 if(indev_obj_act != proc->types.pointer.act_obj) {
821 proc->types.pointer.last_point.x = proc->types.pointer.act_point.x;
822 proc->types.pointer.last_point.y = proc->types.pointer.act_point.y;
823
824 /*If a new object found the previous was lost, so send a Call the ancestor's event handler*/
825 if(proc->types.pointer.act_obj != NULL) {
826 /*Save the obj because in special cases `act_obj` can change in the Call the ancestor's event handler function*/
827 lv_obj_t * last_obj = proc->types.pointer.act_obj;
828
829 lv_event_send(last_obj, LV_EVENT_PRESS_LOST, indev_act);
830 if(indev_reset_check(proc)) return;
831 }
832
833 proc->types.pointer.act_obj = indev_obj_act; /*Save the pressed object*/
834 proc->types.pointer.last_obj = indev_obj_act;
835
836 if(indev_obj_act != NULL) {
837 /*Save the time when the obj pressed to count long press time.*/
838 proc->pr_timestamp = lv_tick_get();
839 proc->long_pr_sent = 0;
840 proc->types.pointer.scroll_sum.x = 0;
841 proc->types.pointer.scroll_sum.y = 0;
842 proc->types.pointer.scroll_dir = LV_DIR_NONE;
843 proc->types.pointer.gesture_dir = LV_DIR_NONE;
844 proc->types.pointer.gesture_sent = 0;
845 proc->types.pointer.gesture_sum.x = 0;
846 proc->types.pointer.gesture_sum.y = 0;
847 proc->types.pointer.vect.x = 0;
848 proc->types.pointer.vect.y = 0;
849
850 /*Call the ancestor's event handler about the press*/
851 lv_event_send(indev_obj_act, LV_EVENT_PRESSED, indev_act);
852 if(indev_reset_check(proc)) return;
853
854 if(indev_act->proc.wait_until_release) return;
855
856 /*Handle focus*/
857 indev_click_focus(&indev_act->proc);
858 if(indev_reset_check(proc)) return;
859
860 }
861 }
862
863 /*Calculate the vector and apply a low pass filter: new value = 0.5 * old_value + 0.5 * new_value*/
864 proc->types.pointer.vect.x = proc->types.pointer.act_point.x - proc->types.pointer.last_point.x;
865 proc->types.pointer.vect.y = proc->types.pointer.act_point.y - proc->types.pointer.last_point.y;
866
867 proc->types.pointer.scroll_throw_vect.x = (proc->types.pointer.scroll_throw_vect.x * 4) >> 3;
868 proc->types.pointer.scroll_throw_vect.y = (proc->types.pointer.scroll_throw_vect.y * 4) >> 3;
869
870 proc->types.pointer.scroll_throw_vect.x += (proc->types.pointer.vect.x * 4) >> 3;
871 proc->types.pointer.scroll_throw_vect.y += (proc->types.pointer.vect.y * 4) >> 3;
872
873 proc->types.pointer.scroll_throw_vect_ori = proc->types.pointer.scroll_throw_vect;
874
875 if(indev_obj_act) {
876 lv_event_send(indev_obj_act, LV_EVENT_PRESSING, indev_act);
877 if(indev_reset_check(proc)) return;
878
879 if(indev_act->proc.wait_until_release) return;
880
881 _lv_indev_scroll_handler(proc);
882 if(indev_reset_check(proc)) return;
883 indev_gesture(proc);
884 if(indev_reset_check(proc)) return;
885
886 /*If there is no scrolling then check for long press time*/
887 if(proc->types.pointer.scroll_obj == NULL && proc->long_pr_sent == 0) {
888 /*Call the ancestor's event handler about the long press if enough time elapsed*/
889 if(lv_tick_elaps(proc->pr_timestamp) > indev_act->driver->long_press_time) {
890 lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED, indev_act);
891 if(indev_reset_check(proc)) return;
892
893 /*Mark the Call the ancestor's event handler sending to do not send it again*/
894 proc->long_pr_sent = 1;
895
896 /*Save the long press time stamp for the long press repeat handler*/
897 proc->longpr_rep_timestamp = lv_tick_get();
898 }
899 }
900
901 /*Send long press repeated Call the ancestor's event handler*/
902 if(proc->types.pointer.scroll_obj == NULL && proc->long_pr_sent == 1) {
903 /*Call the ancestor's event handler about the long press repeat if enough time elapsed*/
904 if(lv_tick_elaps(proc->longpr_rep_timestamp) > indev_act->driver->long_press_repeat_time) {
905 lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED_REPEAT, indev_act);
906 if(indev_reset_check(proc)) return;
907 proc->longpr_rep_timestamp = lv_tick_get();
908 }
909 }
910 }
911 }
912
913 /**
914 * Process the released state of LV_INDEV_TYPE_POINTER input devices
915 * @param proc pointer to an input device 'proc'
916 */
indev_proc_release(_lv_indev_proc_t * proc)917 static void indev_proc_release(_lv_indev_proc_t * proc)
918 {
919 if(proc->wait_until_release != 0) {
920 proc->types.pointer.act_obj = NULL;
921 proc->types.pointer.last_obj = NULL;
922 proc->pr_timestamp = 0;
923 proc->longpr_rep_timestamp = 0;
924 proc->wait_until_release = 0;
925 }
926 indev_obj_act = proc->types.pointer.act_obj;
927 lv_obj_t * scroll_obj = proc->types.pointer.scroll_obj;
928
929 /*Forget the act obj and send a released Call the ancestor's event handler*/
930 if(indev_obj_act) {
931 LV_LOG_INFO("released");
932
933 /*Send RELEASE Call the ancestor's event handler and event*/
934 lv_event_send(indev_obj_act, LV_EVENT_RELEASED, indev_act);
935 if(indev_reset_check(proc)) return;
936
937 /*Send CLICK if no scrolling*/
938 if(scroll_obj == NULL) {
939 if(proc->long_pr_sent == 0) {
940 lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, indev_act);
941 if(indev_reset_check(proc)) return;
942 }
943
944 lv_event_send(indev_obj_act, LV_EVENT_CLICKED, indev_act);
945 if(indev_reset_check(proc)) return;
946 }
947
948 proc->types.pointer.act_obj = NULL;
949 proc->pr_timestamp = 0;
950 proc->longpr_rep_timestamp = 0;
951
952 }
953
954 /*The reset can be set in the Call the ancestor's event handler function.
955 * In case of reset query ignore the remaining parts.*/
956 if(scroll_obj) {
957 _lv_indev_scroll_throw_handler(proc);
958 if(indev_reset_check(proc)) return;
959 }
960 }
961
962 /**
963 * Process a new point from LV_INDEV_TYPE_BUTTON input device
964 * @param i pointer to an input device
965 * @param data pointer to the data read from the input device
966 * Reset input device if a reset query has been sent to it
967 * @param indev pointer to an input device
968 */
indev_proc_reset_query_handler(lv_indev_t * indev)969 static void indev_proc_reset_query_handler(lv_indev_t * indev)
970 {
971 if(indev->proc.reset_query) {
972 indev->proc.types.pointer.act_obj = NULL;
973 indev->proc.types.pointer.last_obj = NULL;
974 indev->proc.types.pointer.scroll_obj = NULL;
975 indev->proc.long_pr_sent = 0;
976 indev->proc.pr_timestamp = 0;
977 indev->proc.longpr_rep_timestamp = 0;
978 indev->proc.types.pointer.scroll_sum.x = 0;
979 indev->proc.types.pointer.scroll_sum.y = 0;
980 indev->proc.types.pointer.scroll_dir = LV_DIR_NONE;
981 indev->proc.types.pointer.scroll_throw_vect.x = 0;
982 indev->proc.types.pointer.scroll_throw_vect.y = 0;
983 indev->proc.types.pointer.gesture_sum.x = 0;
984 indev->proc.types.pointer.gesture_sum.y = 0;
985 indev->proc.reset_query = 0;
986 indev_obj_act = NULL;
987 }
988 }
989
990 /**
991 * Handle focus/defocus on click for POINTER input devices
992 * @param proc pointer to the state of the indev
993 */
indev_click_focus(_lv_indev_proc_t * proc)994 static void indev_click_focus(_lv_indev_proc_t * proc)
995 {
996 /*Handle click focus*/
997 if(lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_CLICK_FOCUSABLE) == false ||
998 proc->types.pointer.last_pressed == indev_obj_act) {
999 return;
1000 }
1001
1002 lv_group_t * g_act = lv_obj_get_group(indev_obj_act);
1003 lv_group_t * g_prev = proc->types.pointer.last_pressed ? lv_obj_get_group(proc->types.pointer.last_pressed) : NULL;
1004
1005 /*If both the last and act. obj. are in the same group (or have no group)*/
1006 if(g_act == g_prev) {
1007 /*The objects are in a group*/
1008 if(g_act) {
1009 lv_group_focus_obj(indev_obj_act);
1010 if(indev_reset_check(proc)) return;
1011 }
1012 /*The object are not in group*/
1013 else {
1014 if(proc->types.pointer.last_pressed) {
1015 lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act);
1016 if(indev_reset_check(proc)) return;
1017 }
1018
1019 lv_event_send(indev_obj_act, LV_EVENT_FOCUSED, indev_act);
1020 if(indev_reset_check(proc)) return;
1021 }
1022 }
1023 /*The object are not in the same group (in different groups or one has no group)*/
1024 else {
1025 /*If the prev. obj. is not in a group then defocus it.*/
1026 if(g_prev == NULL && proc->types.pointer.last_pressed) {
1027 lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act);
1028 if(indev_reset_check(proc)) return;
1029 }
1030 /*Focus on a non-group object*/
1031 else {
1032 if(proc->types.pointer.last_pressed) {
1033 /*If the prev. object also wasn't in a group defocus it*/
1034 if(g_prev == NULL) {
1035 lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act);
1036 if(indev_reset_check(proc)) return;
1037 }
1038 /*If the prev. object also was in a group at least "LEAVE" it instead of defocus*/
1039 else {
1040 lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_LEAVE, indev_act);
1041 if(indev_reset_check(proc)) return;
1042 }
1043 }
1044 }
1045
1046 /*Focus to the act. in its group*/
1047 if(g_act) {
1048 lv_group_focus_obj(indev_obj_act);
1049 if(indev_reset_check(proc)) return;
1050 }
1051 else {
1052 lv_event_send(indev_obj_act, LV_EVENT_FOCUSED, indev_act);
1053 if(indev_reset_check(proc)) return;
1054 }
1055 }
1056 proc->types.pointer.last_pressed = indev_obj_act;
1057 }
1058
1059 /**
1060 * Handle the gesture of indev_proc_p->types.pointer.act_obj
1061 * @param indev pointer to an input device state
1062 */
indev_gesture(_lv_indev_proc_t * proc)1063 void indev_gesture(_lv_indev_proc_t * proc)
1064 {
1065
1066 if(proc->types.pointer.scroll_obj) return;
1067 if(proc->types.pointer.gesture_sent) return;
1068
1069 lv_obj_t * gesture_obj = proc->types.pointer.act_obj;
1070
1071 /*If gesture parent is active check recursively the gesture attribute*/
1072 while(gesture_obj && lv_obj_has_flag(gesture_obj, LV_OBJ_FLAG_GESTURE_BUBBLE)) {
1073 gesture_obj = lv_obj_get_parent(gesture_obj);
1074 }
1075
1076 if(gesture_obj == NULL) return;
1077
1078 if((LV_ABS(proc->types.pointer.vect.x) < indev_act->driver->gesture_min_velocity) &&
1079 (LV_ABS(proc->types.pointer.vect.y) < indev_act->driver->gesture_min_velocity)) {
1080 proc->types.pointer.gesture_sum.x = 0;
1081 proc->types.pointer.gesture_sum.y = 0;
1082 }
1083
1084 /*Count the movement by gesture*/
1085 proc->types.pointer.gesture_sum.x += proc->types.pointer.vect.x;
1086 proc->types.pointer.gesture_sum.y += proc->types.pointer.vect.y;
1087
1088 if((LV_ABS(proc->types.pointer.gesture_sum.x) > indev_act->driver->gesture_limit) ||
1089 (LV_ABS(proc->types.pointer.gesture_sum.y) > indev_act->driver->gesture_limit)) {
1090
1091 proc->types.pointer.gesture_sent = 1;
1092
1093 if(LV_ABS(proc->types.pointer.gesture_sum.x) > LV_ABS(proc->types.pointer.gesture_sum.y)) {
1094 if(proc->types.pointer.gesture_sum.x > 0)
1095 proc->types.pointer.gesture_dir = LV_DIR_RIGHT;
1096 else
1097 proc->types.pointer.gesture_dir = LV_DIR_LEFT;
1098 }
1099 else {
1100 if(proc->types.pointer.gesture_sum.y > 0)
1101 proc->types.pointer.gesture_dir = LV_DIR_BOTTOM;
1102 else
1103 proc->types.pointer.gesture_dir = LV_DIR_TOP;
1104 }
1105
1106 lv_event_send(gesture_obj, LV_EVENT_GESTURE, indev_act);
1107 if(indev_reset_check(proc)) return;
1108 }
1109 }
1110
1111 /**
1112 * Checks if the reset_query flag has been set. If so, perform necessary global indev cleanup actions
1113 * @param proc pointer to an input device 'proc'
1114 * @return true if indev query should be immediately truncated.
1115 */
indev_reset_check(_lv_indev_proc_t * proc)1116 static bool indev_reset_check(_lv_indev_proc_t * proc)
1117 {
1118 if(proc->reset_query) {
1119 indev_obj_act = NULL;
1120 }
1121
1122 return proc->reset_query ? true : false;
1123 }
1124