1 #include "lv_indev_private.h"
2 #include "../misc/lv_event_private.h"
3 #include "../misc/lv_area_private.h"
4 #include "../misc/lv_anim_private.h"
5 #include "../core/lv_obj_draw_private.h"
6 /**
7  * @file lv_indev.c
8  *
9  */
10 
11 /*********************
12  *      INCLUDES
13  ********************/
14 #include "lv_indev_scroll.h"
15 #include "lv_indev_gesture.h"
16 #include "../display/lv_display_private.h"
17 #include "../core/lv_global.h"
18 #include "../core/lv_obj_private.h"
19 #include "../core/lv_group.h"
20 #include "../core/lv_refr.h"
21 
22 #include "../tick/lv_tick.h"
23 #include "../misc/lv_timer_private.h"
24 #include "../misc/lv_math.h"
25 #include "../misc/lv_profiler.h"
26 #include "../stdlib/lv_string.h"
27 
28 /*********************
29  *      DEFINES
30  *********************/
31 /*Drag threshold in pixels*/
32 #define LV_INDEV_DEF_SCROLL_LIMIT         10
33 
34 /*Drag throw slow-down in [%]. Greater value -> faster slow-down*/
35 #define LV_INDEV_DEF_SCROLL_THROW         10
36 
37 /*Long press time in milliseconds.
38  *Time to send `LV_EVENT_LONG_PRESSED`)*/
39 #define LV_INDEV_DEF_LONG_PRESS_TIME      400
40 
41 /*Repeated trigger period in long press [ms]
42  *Time between `LV_EVENT_LONG_PRESSED_REPEAT*/
43 #define LV_INDEV_DEF_LONG_PRESS_REP_TIME  100
44 
45 /*Gesture threshold in pixels*/
46 #define LV_INDEV_DEF_GESTURE_LIMIT        50
47 
48 /*Gesture min velocity at release before swipe (pixels)*/
49 #define LV_INDEV_DEF_GESTURE_MIN_VELOCITY 3
50 
51 /**< Rotary diff count will be multiplied by this and divided by 256 */
52 #define LV_INDEV_DEF_ROTARY_SENSITIVITY         256
53 
54 #if LV_INDEV_DEF_SCROLL_THROW <= 0
55     #warning "LV_INDEV_DEF_SCROLL_THROW must be greater than 0"
56 #endif
57 
58 #define indev_act LV_GLOBAL_DEFAULT()->indev_active
59 #define indev_obj_act LV_GLOBAL_DEFAULT()->indev_obj_active
60 #define indev_ll_head &(LV_GLOBAL_DEFAULT()->indev_ll)
61 
62 /**********************
63  *      TYPEDEFS
64  **********************/
65 
66 /**********************
67  *  STATIC PROTOTYPES
68  **********************/
69 static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data);
70 static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data);
71 static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data);
72 static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data);
73 static void indev_proc_press(lv_indev_t * indev);
74 static void indev_proc_release(lv_indev_t * indev);
75 static lv_result_t indev_proc_short_click(lv_indev_t * indev);
76 static void indev_proc_pointer_diff(lv_indev_t * indev);
77 static lv_obj_t * pointer_search_obj(lv_display_t * disp, lv_point_t * p);
78 static void indev_proc_reset_query_handler(lv_indev_t * indev);
79 static void indev_click_focus(lv_indev_t * indev);
80 static void indev_gesture(lv_indev_t * indev);
81 static bool indev_reset_check(lv_indev_t * indev);
82 static void indev_read_core(lv_indev_t * indev, lv_indev_data_t * data);
83 static void indev_reset_core(lv_indev_t * indev, lv_obj_t * obj);
84 static lv_result_t send_event(lv_event_code_t code, void * param);
85 
86 static void indev_scroll_throw_anim_start(lv_indev_t * indev);
87 static void indev_scroll_throw_anim_cb(void * var, int32_t v);
88 static void indev_scroll_throw_anim_completed_cb(lv_anim_t * anim);
indev_scroll_throw_anim_reset(lv_indev_t * indev)89 static inline void indev_scroll_throw_anim_reset(lv_indev_t * indev)
90 {
91     if(indev) {
92         indev->pointer.scroll_throw_vect.x = 0;
93         indev->pointer.scroll_throw_vect.y = 0;
94         indev->scroll_throw_anim = NULL;
95     }
96 }
97 
98 /**********************
99  *  STATIC VARIABLES
100  **********************/
101 
102 /**********************
103  *      MACROS
104  **********************/
105 #if LV_USE_LOG && LV_LOG_TRACE_INDEV
106     #define LV_TRACE_INDEV(...) LV_LOG_TRACE(__VA_ARGS__)
107 #else
108     #define LV_TRACE_INDEV(...)
109 #endif
110 
111 /**********************
112  *   GLOBAL FUNCTIONS
113  **********************/
114 
lv_indev_create(void)115 lv_indev_t * lv_indev_create(void)
116 {
117     lv_display_t * disp = lv_display_get_default();
118     if(disp == NULL) {
119         LV_LOG_WARN("no display was created so far");
120     }
121 
122     lv_indev_t * indev = lv_ll_ins_head(indev_ll_head);
123     LV_ASSERT_MALLOC(indev);
124     if(indev == NULL) {
125         return NULL;
126     }
127 
128     lv_memzero(indev, sizeof(lv_indev_t));
129     indev->reset_query  = 1;
130     indev->enabled = 1;
131 
132     indev->read_timer = lv_timer_create(lv_indev_read_timer_cb, LV_DEF_REFR_PERIOD, indev);
133 
134     indev->disp                 = lv_display_get_default();
135     indev->type                 = LV_INDEV_TYPE_NONE;
136     indev->mode                 = LV_INDEV_MODE_TIMER;
137     indev->scroll_limit         = LV_INDEV_DEF_SCROLL_LIMIT;
138     indev->scroll_throw         = LV_INDEV_DEF_SCROLL_THROW;
139     indev->long_press_time      = LV_INDEV_DEF_LONG_PRESS_TIME;
140     indev->long_press_repeat_time  = LV_INDEV_DEF_LONG_PRESS_REP_TIME;
141     indev->gesture_limit        = LV_INDEV_DEF_GESTURE_LIMIT;
142     indev->gesture_min_velocity = LV_INDEV_DEF_GESTURE_MIN_VELOCITY;
143     indev->rotary_sensitivity  = LV_INDEV_DEF_ROTARY_SENSITIVITY;
144     return indev;
145 }
146 
lv_indev_delete(lv_indev_t * indev)147 void lv_indev_delete(lv_indev_t * indev)
148 {
149     LV_ASSERT_NULL(indev);
150 
151     lv_indev_send_event(indev, LV_EVENT_DELETE, NULL);
152     lv_event_remove_all(&(indev->event_list));
153 
154     /*Clean up the read timer first*/
155     if(indev->read_timer) lv_timer_delete(indev->read_timer);
156 
157     /*Remove the input device from the list*/
158     lv_ll_remove(indev_ll_head, indev);
159     /*Free the memory of the input device*/
160     lv_free(indev);
161 }
162 
lv_indev_get_next(lv_indev_t * indev)163 lv_indev_t * lv_indev_get_next(lv_indev_t * indev)
164 {
165     if(indev == NULL)
166         return lv_ll_get_head(indev_ll_head);
167     else
168         return lv_ll_get_next(indev_ll_head, indev);
169 }
170 
indev_read_core(lv_indev_t * indev,lv_indev_data_t * data)171 void indev_read_core(lv_indev_t * indev, lv_indev_data_t * data)
172 {
173     LV_PROFILER_INDEV_BEGIN;
174     lv_memzero(data, sizeof(lv_indev_data_t));
175 
176     /* For touchpad sometimes users don't set the last pressed coordinate on release.
177      * So be sure a coordinates are initialized to the last point */
178     if(indev->type == LV_INDEV_TYPE_POINTER) {
179         data->point.x = indev->pointer.last_raw_point.x;
180         data->point.y = indev->pointer.last_raw_point.y;
181     }
182     /*Similarly set at least the last key in case of the user doesn't set it on release*/
183     else if(indev->type == LV_INDEV_TYPE_KEYPAD) {
184         data->key = indev->keypad.last_key;
185     }
186     /*For compatibility assume that used button was enter (encoder push)*/
187     else if(indev->type == LV_INDEV_TYPE_ENCODER) {
188         data->key = LV_KEY_ENTER;
189     }
190 
191     if(indev->read_cb) {
192         LV_TRACE_INDEV("calling indev_read_cb");
193         indev->read_cb(indev, data);
194     }
195     else {
196         LV_LOG_WARN("indev_read_cb is not registered");
197     }
198 
199     LV_PROFILER_INDEV_END;
200 }
201 
lv_indev_read_timer_cb(lv_timer_t * timer)202 void lv_indev_read_timer_cb(lv_timer_t * timer)
203 {
204     lv_indev_read(timer->user_data);
205 }
206 
lv_indev_read(lv_indev_t * indev)207 void lv_indev_read(lv_indev_t * indev)
208 {
209     if(indev == NULL) return;
210 
211     LV_TRACE_INDEV("begin");
212 
213     indev_act = indev;
214 
215     /*Read and process all indevs*/
216     if(indev->disp == NULL) return; /*Not assigned to any displays*/
217 
218     /*Handle reset query before processing the point*/
219     indev_proc_reset_query_handler(indev);
220 
221     if(indev->enabled == 0) return;
222     if(indev->disp->prev_scr != NULL) {
223         LV_TRACE_INDEV("input blocked while screen animation active");
224         return;
225     }
226 
227     LV_PROFILER_INDEV_BEGIN;
228 
229     bool continue_reading;
230     lv_indev_data_t data;
231 
232     do {
233         /*Read the data*/
234         indev_read_core(indev, &data);
235         continue_reading = indev->mode != LV_INDEV_MODE_EVENT && data.continue_reading;
236 
237         /*The active object might be deleted even in the read function*/
238         indev_proc_reset_query_handler(indev);
239         indev_obj_act = NULL;
240 
241         indev->state = data.state;
242 
243         /*Save the last activity time*/
244         if(indev->state == LV_INDEV_STATE_PRESSED) {
245             indev->disp->last_activity_time = lv_tick_get();
246         }
247         else if(indev->type == LV_INDEV_TYPE_ENCODER && data.enc_diff) {
248             indev->disp->last_activity_time = lv_tick_get();
249         }
250 
251         if(indev->type == LV_INDEV_TYPE_POINTER) {
252             indev_pointer_proc(indev, &data);
253         }
254         else if(indev->type == LV_INDEV_TYPE_KEYPAD) {
255             indev_keypad_proc(indev, &data);
256         }
257         else if(indev->type == LV_INDEV_TYPE_ENCODER) {
258             indev_encoder_proc(indev, &data);
259         }
260         else if(indev->type == LV_INDEV_TYPE_BUTTON) {
261             indev_button_proc(indev, &data);
262         }
263         /*Handle reset query if it happened in during processing*/
264         indev_proc_reset_query_handler(indev);
265     } while(continue_reading);
266 
267     /*End of indev processing, so no act indev*/
268     indev_act     = NULL;
269     indev_obj_act = NULL;
270 
271     LV_TRACE_INDEV("finished");
272     LV_PROFILER_INDEV_END;
273 }
274 
lv_indev_enable(lv_indev_t * indev,bool enable)275 void lv_indev_enable(lv_indev_t * indev, bool enable)
276 {
277     if(indev) {
278         indev->enabled = (uint8_t) enable;
279     }
280     else {
281         lv_indev_t * i = lv_indev_get_next(NULL);
282         while(i) {
283             i->enabled = (uint8_t) enable;
284             i = lv_indev_get_next(i);
285         }
286     }
287 }
288 
lv_indev_active(void)289 lv_indev_t * lv_indev_active(void)
290 {
291     return indev_act;
292 }
293 
lv_indev_set_type(lv_indev_t * indev,lv_indev_type_t indev_type)294 void lv_indev_set_type(lv_indev_t * indev, lv_indev_type_t indev_type)
295 {
296     if(indev == NULL) return;
297 
298     indev->type = indev_type;
299     indev->reset_query = 1;
300 }
301 
lv_indev_set_read_cb(lv_indev_t * indev,lv_indev_read_cb_t read_cb)302 void lv_indev_set_read_cb(lv_indev_t * indev, lv_indev_read_cb_t read_cb)
303 {
304     if(indev == NULL) return;
305 
306     indev->read_cb = read_cb;
307 }
308 
lv_indev_set_user_data(lv_indev_t * indev,void * user_data)309 void lv_indev_set_user_data(lv_indev_t * indev, void * user_data)
310 {
311     if(indev == NULL) return;
312     indev->user_data = user_data;
313 }
314 
lv_indev_set_driver_data(lv_indev_t * indev,void * driver_data)315 void lv_indev_set_driver_data(lv_indev_t * indev, void * driver_data)
316 {
317     if(indev == NULL) return;
318     indev->driver_data = driver_data;
319 }
320 
lv_indev_get_read_cb(lv_indev_t * indev)321 lv_indev_read_cb_t lv_indev_get_read_cb(lv_indev_t * indev)
322 {
323     if(indev == NULL) {
324         LV_LOG_WARN("lv_indev_get_read_cb: indev was NULL");
325         return NULL;
326     }
327 
328     return indev->read_cb;
329 }
330 
lv_indev_get_type(const lv_indev_t * indev)331 lv_indev_type_t lv_indev_get_type(const lv_indev_t * indev)
332 {
333     if(indev == NULL) return LV_INDEV_TYPE_NONE;
334 
335     return indev->type;
336 }
337 
lv_indev_get_state(const lv_indev_t * indev)338 lv_indev_state_t lv_indev_get_state(const lv_indev_t * indev)
339 {
340     if(indev == NULL) return LV_INDEV_STATE_RELEASED;
341 
342     return indev->state;
343 }
344 
lv_indev_get_group(const lv_indev_t * indev)345 lv_group_t * lv_indev_get_group(const lv_indev_t * indev)
346 {
347     if(indev == NULL) return NULL;
348 
349     return indev->group;
350 }
351 
lv_indev_get_display(const lv_indev_t * indev)352 lv_display_t * lv_indev_get_display(const lv_indev_t * indev)
353 {
354     if(indev == NULL) return NULL;
355 
356     return indev->disp;
357 }
358 
lv_indev_set_display(lv_indev_t * indev,lv_display_t * disp)359 void lv_indev_set_display(lv_indev_t * indev, lv_display_t * disp)
360 {
361     if(indev == NULL) return;
362 
363     indev->disp = disp;
364 }
365 
lv_indev_set_long_press_time(lv_indev_t * indev,uint16_t long_press_time)366 void lv_indev_set_long_press_time(lv_indev_t * indev, uint16_t long_press_time)
367 {
368     if(indev == NULL) return;
369 
370     indev->long_press_time = long_press_time;
371 }
372 
lv_indev_set_long_press_repeat_time(lv_indev_t * indev,uint16_t long_press_repeat_time)373 void lv_indev_set_long_press_repeat_time(lv_indev_t * indev, uint16_t long_press_repeat_time)
374 {
375     if(indev == NULL) return;
376 
377     indev->long_press_repeat_time = long_press_repeat_time;
378 }
379 
lv_indev_set_scroll_limit(lv_indev_t * indev,uint8_t scroll_limit)380 void lv_indev_set_scroll_limit(lv_indev_t * indev, uint8_t scroll_limit)
381 {
382     if(indev == NULL) return;
383 
384     indev->scroll_limit = scroll_limit;
385 }
386 
lv_indev_set_scroll_throw(lv_indev_t * indev,uint8_t scroll_throw)387 void lv_indev_set_scroll_throw(lv_indev_t * indev, uint8_t scroll_throw)
388 {
389     if(indev == NULL) return;
390 
391     indev->scroll_throw = scroll_throw;
392 }
393 
lv_indev_get_user_data(const lv_indev_t * indev)394 void * lv_indev_get_user_data(const lv_indev_t * indev)
395 {
396     if(indev == NULL) return NULL;
397     return indev->user_data;
398 }
399 
lv_indev_get_driver_data(const lv_indev_t * indev)400 void * lv_indev_get_driver_data(const lv_indev_t * indev)
401 {
402     if(indev == NULL) return NULL;
403 
404     return indev->driver_data;
405 }
406 
lv_indev_get_press_moved(const lv_indev_t * indev)407 bool lv_indev_get_press_moved(const lv_indev_t * indev)
408 {
409     if(indev == NULL) return false;
410 
411     return indev->pointer.press_moved;
412 }
413 
lv_indev_reset(lv_indev_t * indev,lv_obj_t * obj)414 void lv_indev_reset(lv_indev_t * indev, lv_obj_t * obj)
415 {
416     if(indev) {
417         indev_reset_core(indev, obj);
418     }
419     else {
420         lv_indev_t * i = lv_indev_get_next(NULL);
421         while(i) {
422             indev_reset_core(i, obj);
423             i = lv_indev_get_next(i);
424         }
425         indev_obj_act = NULL;
426     }
427 }
428 
lv_indev_stop_processing(lv_indev_t * indev)429 void lv_indev_stop_processing(lv_indev_t * indev)
430 {
431     if(indev == NULL) return;
432     indev->stop_processing_query = 1;
433 }
434 
lv_indev_reset_long_press(lv_indev_t * indev)435 void lv_indev_reset_long_press(lv_indev_t * indev)
436 {
437     indev->long_pr_sent         = 0;
438     indev->longpr_rep_timestamp = lv_tick_get();
439     indev->pr_timestamp         = lv_tick_get();
440 }
441 
lv_indev_set_cursor(lv_indev_t * indev,lv_obj_t * cur_obj)442 void lv_indev_set_cursor(lv_indev_t * indev, lv_obj_t * cur_obj)
443 {
444     if(indev->type != LV_INDEV_TYPE_POINTER) return;
445 
446     indev->cursor = cur_obj;
447     lv_obj_set_parent(indev->cursor, lv_display_get_layer_sys(indev->disp));
448     lv_obj_set_pos(indev->cursor, indev->pointer.act_point.x, indev->pointer.act_point.y);
449     lv_obj_remove_flag(indev->cursor, LV_OBJ_FLAG_CLICKABLE);
450     lv_obj_add_flag(indev->cursor, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_FLOATING);
451 }
452 
lv_indev_set_group(lv_indev_t * indev,lv_group_t * group)453 void lv_indev_set_group(lv_indev_t * indev, lv_group_t * group)
454 {
455     if(indev && (indev->type == LV_INDEV_TYPE_KEYPAD || indev->type == LV_INDEV_TYPE_ENCODER)) {
456         indev->group = group;
457     }
458 }
459 
lv_indev_set_button_points(lv_indev_t * indev,const lv_point_t points[])460 void lv_indev_set_button_points(lv_indev_t * indev, const lv_point_t points[])
461 {
462     if(indev && indev->type == LV_INDEV_TYPE_BUTTON) {
463         indev->btn_points = points;
464     }
465 }
466 
lv_indev_get_point(const lv_indev_t * indev,lv_point_t * point)467 void lv_indev_get_point(const lv_indev_t * indev, lv_point_t * point)
468 {
469     if(indev == NULL) {
470         point->x = 0;
471         point->y = 0;
472     }
473     else if(indev->type != LV_INDEV_TYPE_POINTER && indev->type != LV_INDEV_TYPE_BUTTON) {
474         point->x = -1;
475         point->y = -1;
476     }
477     else {
478         point->x = indev->pointer.act_point.x;
479         point->y = indev->pointer.act_point.y;
480     }
481 }
482 
lv_indev_get_gesture_dir(const lv_indev_t * indev)483 lv_dir_t lv_indev_get_gesture_dir(const lv_indev_t * indev)
484 {
485     return indev->pointer.gesture_dir;
486 }
487 
lv_indev_get_key(const lv_indev_t * indev)488 uint32_t lv_indev_get_key(const lv_indev_t * indev)
489 {
490     uint32_t key = 0;
491 
492     if(indev && indev->type == LV_INDEV_TYPE_KEYPAD)
493         key = indev->keypad.last_key;
494 
495     return key;
496 }
497 
lv_indev_get_short_click_streak(const lv_indev_t * indev)498 uint8_t lv_indev_get_short_click_streak(const lv_indev_t * indev)
499 {
500     return indev->pointer.short_click_streak;
501 }
502 
lv_indev_get_scroll_dir(const lv_indev_t * indev)503 lv_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev)
504 {
505     if(indev == NULL) return false;
506     if(indev->type != LV_INDEV_TYPE_POINTER && indev->type != LV_INDEV_TYPE_BUTTON) return false;
507     return indev->pointer.scroll_dir;
508 }
509 
lv_indev_get_scroll_obj(const lv_indev_t * indev)510 lv_obj_t * lv_indev_get_scroll_obj(const lv_indev_t * indev)
511 {
512     if(indev == NULL) return NULL;
513     if(indev->type != LV_INDEV_TYPE_POINTER && indev->type != LV_INDEV_TYPE_BUTTON) return NULL;
514     return indev->pointer.scroll_obj;
515 }
516 
lv_indev_get_vect(const lv_indev_t * indev,lv_point_t * point)517 void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point)
518 {
519     point->x = 0;
520     point->y = 0;
521 
522     if(indev == NULL) return;
523 
524     if(indev->type == LV_INDEV_TYPE_POINTER || indev->type == LV_INDEV_TYPE_BUTTON) {
525         point->x = indev->pointer.vect.x;
526         point->y = indev->pointer.vect.y;
527     }
528 }
529 
lv_indev_get_cursor(lv_indev_t * indev)530 lv_obj_t * lv_indev_get_cursor(lv_indev_t * indev)
531 {
532     if(indev == NULL) return NULL;
533     return indev->cursor;
534 }
535 
lv_indev_wait_release(lv_indev_t * indev)536 void lv_indev_wait_release(lv_indev_t * indev)
537 {
538     if(indev == NULL)return;
539     indev->wait_until_release = 1;
540 }
541 
lv_indev_get_active_obj(void)542 lv_obj_t * lv_indev_get_active_obj(void)
543 {
544     return indev_obj_act;
545 }
546 
lv_indev_get_read_timer(lv_indev_t * indev)547 lv_timer_t * lv_indev_get_read_timer(lv_indev_t * indev)
548 {
549     if(indev == NULL) {
550         LV_LOG_WARN("lv_indev_get_read_timer: indev was NULL");
551         return NULL;
552     }
553 
554     return indev->read_timer;
555 }
556 
lv_indev_get_mode(lv_indev_t * indev)557 lv_indev_mode_t lv_indev_get_mode(lv_indev_t * indev)
558 {
559     if(indev) return indev->mode;
560     return LV_INDEV_MODE_NONE;
561 }
562 
lv_indev_set_mode(lv_indev_t * indev,lv_indev_mode_t mode)563 void lv_indev_set_mode(lv_indev_t * indev, lv_indev_mode_t mode)
564 {
565     if(indev == NULL || indev->mode == mode)
566         return;
567 
568     indev->mode = mode;
569     if(indev->read_timer) {
570         if(mode == LV_INDEV_MODE_EVENT) {
571             lv_timer_pause(indev->read_timer);
572         }
573         else if(mode == LV_INDEV_MODE_TIMER) {
574             /* use default timer mode*/
575             lv_timer_set_cb(indev->read_timer, lv_indev_read_timer_cb);
576             lv_timer_resume(indev->read_timer);
577         }
578     }
579 }
580 
lv_indev_search_obj(lv_obj_t * obj,lv_point_t * point)581 lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point)
582 {
583     lv_obj_t * found_p = NULL;
584 
585     /*If this obj is hidden the children are hidden too so return immediately*/
586     if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return NULL;
587 
588     lv_point_t p_trans = *point;
589     lv_obj_transform_point(obj, &p_trans, LV_OBJ_POINT_TRANSFORM_FLAG_INVERSE);
590 
591     bool hit_test_ok = lv_obj_hit_test(obj, &p_trans);
592 
593     /*If the point is on this object check its children too*/
594     lv_area_t obj_coords = obj->coords;
595     if(lv_obj_has_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) {
596         int32_t ext_draw_size = lv_obj_get_ext_draw_size(obj);
597         lv_area_increase(&obj_coords, ext_draw_size, ext_draw_size);
598     }
599     if(lv_area_is_point_on(&obj_coords, &p_trans, 0)) {
600         int32_t i;
601         uint32_t child_cnt = lv_obj_get_child_count(obj);
602 
603         /*If a child matches use it*/
604         for(i = child_cnt - 1; i >= 0; i--) {
605             lv_obj_t * child = obj->spec_attr->children[i];
606             found_p = lv_indev_search_obj(child, &p_trans);
607             if(found_p) return found_p;
608         }
609     }
610 
611     /*If not return earlier for a clicked child and this obj's hittest was ok use it
612      *else return NULL*/
613     if(hit_test_ok) return obj;
614     else return NULL;
615 }
616 
lv_indev_add_event_cb(lv_indev_t * indev,lv_event_cb_t event_cb,lv_event_code_t filter,void * user_data)617 void lv_indev_add_event_cb(lv_indev_t * indev, lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data)
618 {
619     LV_ASSERT_NULL(indev);
620 
621     lv_event_add(&indev->event_list, event_cb, filter, user_data);
622 }
623 
lv_indev_get_event_count(lv_indev_t * indev)624 uint32_t lv_indev_get_event_count(lv_indev_t * indev)
625 {
626     LV_ASSERT_NULL(indev);
627     return lv_event_get_count(&indev->event_list);
628 }
629 
lv_indev_get_event_dsc(lv_indev_t * indev,uint32_t index)630 lv_event_dsc_t * lv_indev_get_event_dsc(lv_indev_t * indev, uint32_t index)
631 {
632     LV_ASSERT_NULL(indev);
633     return lv_event_get_dsc(&indev->event_list, index);
634 
635 }
636 
lv_indev_remove_event(lv_indev_t * indev,uint32_t index)637 bool lv_indev_remove_event(lv_indev_t * indev, uint32_t index)
638 {
639     LV_ASSERT_NULL(indev);
640 
641     return lv_event_remove(&indev->event_list, index);
642 }
643 
lv_indev_remove_event_cb_with_user_data(lv_indev_t * indev,lv_event_cb_t event_cb,void * user_data)644 uint32_t lv_indev_remove_event_cb_with_user_data(lv_indev_t * indev, lv_event_cb_t event_cb, void * user_data)
645 {
646     LV_ASSERT_NULL(indev);
647 
648     uint32_t event_cnt = lv_indev_get_event_count(indev);
649     uint32_t removed_count = 0;
650     int32_t i;
651 
652     for(i = event_cnt - 1; i >= 0; i--) {
653         lv_event_dsc_t * dsc = lv_indev_get_event_dsc(indev, i);
654         if(dsc && dsc->cb == event_cb && dsc->user_data == user_data) {
655             lv_indev_remove_event(indev, i);
656             removed_count ++;
657         }
658     }
659 
660     return removed_count;
661 }
662 
lv_indev_send_event(lv_indev_t * indev,lv_event_code_t code,void * param)663 lv_result_t lv_indev_send_event(lv_indev_t * indev, lv_event_code_t code, void * param)
664 {
665 
666     lv_event_t e;
667     lv_memzero(&e, sizeof(e));
668     e.code = code;
669     e.current_target = indev;
670     e.original_target = indev;
671     e.param = param;
672     lv_result_t res;
673     res = lv_event_send(&indev->event_list, &e, true);
674     if(res != LV_RESULT_OK) return res;
675 
676     res = lv_event_send(&indev->event_list, &e, false);
677     if(res != LV_RESULT_OK) return res;
678 
679     return res;
680 }
681 
682 /**********************
683  *   STATIC FUNCTIONS
684  **********************/
685 
686 /**
687  * Process a new point from LV_INDEV_TYPE_POINTER input device
688  * @param i pointer to an input device
689  * @param data pointer to the data read from the input device
690  */
indev_pointer_proc(lv_indev_t * i,lv_indev_data_t * data)691 static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data)
692 {
693     lv_display_t * disp = i->disp;
694     /*Save the raw points so they can be used again in indev_read_core*/
695     i->pointer.last_raw_point.x = data->point.x;
696     i->pointer.last_raw_point.y = data->point.y;
697 
698     if(disp->rotation == LV_DISPLAY_ROTATION_180 || disp->rotation == LV_DISPLAY_ROTATION_270) {
699         data->point.x = disp->hor_res - data->point.x - 1;
700         data->point.y = disp->ver_res - data->point.y - 1;
701     }
702     if(disp->rotation == LV_DISPLAY_ROTATION_90 || disp->rotation == LV_DISPLAY_ROTATION_270) {
703         int32_t tmp = data->point.y;
704         data->point.y = data->point.x;
705         data->point.x = disp->ver_res - tmp - 1;
706     }
707 
708     /*Simple sanity check*/
709     if(data->point.x < 0) {
710         LV_LOG_WARN("X is %d which is smaller than zero", (int)data->point.x);
711     }
712     if(data->point.x >= lv_display_get_horizontal_resolution(i->disp)) {
713         LV_LOG_WARN("X is %d which is greater than hor. res", (int)data->point.x);
714     }
715     if(data->point.y < 0) {
716         LV_LOG_WARN("Y is %d which is smaller than zero", (int)data->point.y);
717     }
718     if(data->point.y >= lv_display_get_vertical_resolution(i->disp)) {
719         LV_LOG_WARN("Y is %d which is greater than ver. res", (int)data->point.y);
720     }
721 
722     /*Move the cursor if set and moved*/
723     if(i->cursor != NULL &&
724        (i->pointer.last_point.x != data->point.x || i->pointer.last_point.y != data->point.y)) {
725         lv_obj_set_pos(i->cursor, data->point.x, data->point.y);
726     }
727 
728     i->pointer.act_point.x = data->point.x;
729     i->pointer.act_point.y = data->point.y;
730     i->pointer.diff = data->enc_diff;
731 
732     i->gesture_type = data->gesture_type;
733     i->gesture_data = data->gesture_data;
734 
735     /*Process the diff first as scrolling will be processed in indev_proc_release*/
736     indev_proc_pointer_diff(i);
737 
738     if(i->state == LV_INDEV_STATE_PRESSED) {
739         indev_proc_press(i);
740     }
741     else {
742         indev_proc_release(i);
743     }
744 
745     i->pointer.last_point.x = i->pointer.act_point.x;
746     i->pointer.last_point.y = i->pointer.act_point.y;
747 }
748 
749 /**
750  * Process a new point from LV_INDEV_TYPE_KEYPAD input device
751  * @param i pointer to an input device
752  * @param data pointer to the data read from the input device
753  */
indev_keypad_proc(lv_indev_t * i,lv_indev_data_t * data)754 static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data)
755 {
756     if(data->state == LV_INDEV_STATE_PRESSED && i->wait_until_release) return;
757 
758     if(i->wait_until_release) {
759         i->wait_until_release      = 0;
760         i->pr_timestamp            = 0;
761         i->long_pr_sent            = 0;
762         i->keypad.last_state = LV_INDEV_STATE_RELEASED; /*To skip the processing of release*/
763     }
764 
765     /*Save the last key. *It must be done here else `lv_indev_get_key` will return the last key in events*/
766     uint32_t prev_key = i->keypad.last_key;
767     i->keypad.last_key = data->key;
768 
769     lv_group_t * g = i->group;
770     if(g == NULL) return;
771 
772     indev_obj_act = lv_group_get_focused(g);
773     if(indev_obj_act == NULL) return;
774 
775     const bool is_enabled = !lv_obj_has_state(indev_obj_act, LV_STATE_DISABLED);
776 
777     /*Save the previous state so we can detect state changes below and also set the last state now
778      *so if any event handler on the way returns `LV_RESULT_INVALID` the last state is remembered
779      *for the next time*/
780     uint32_t prev_state             = i->keypad.last_state;
781     i->keypad.last_state = data->state;
782 
783     /*Key press happened*/
784     if(data->state == LV_INDEV_STATE_PRESSED && prev_state == LV_INDEV_STATE_RELEASED) {
785         LV_LOG_INFO("%" LV_PRIu32 " key is pressed", data->key);
786         i->pr_timestamp = lv_tick_get();
787 
788         /*Move the focus on NEXT*/
789         if(data->key == LV_KEY_NEXT) {
790             lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/
791             lv_group_focus_next(g);
792             if(indev_reset_check(i)) return;
793         }
794         /*Move the focus on PREV*/
795         else if(data->key == LV_KEY_PREV) {
796             lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/
797             lv_group_focus_prev(g);
798             if(indev_reset_check(i)) return;
799         }
800         else if(is_enabled) {
801             /*Simulate a press on the object if ENTER was pressed*/
802             if(data->key == LV_KEY_ENTER) {
803                 /*Send the ENTER as a normal KEY*/
804                 lv_group_send_data(g, LV_KEY_ENTER);
805                 if(indev_reset_check(i)) return;
806 
807                 if(send_event(LV_EVENT_PRESSED, indev_act) == LV_RESULT_INVALID) return;
808 
809             }
810             else if(data->key == LV_KEY_ESC) {
811                 /*Send the ESC as a normal KEY*/
812                 lv_group_send_data(g, LV_KEY_ESC);
813                 if(indev_reset_check(i)) return;
814 
815                 if(send_event(LV_EVENT_CANCEL, indev_act) == LV_RESULT_INVALID) return;
816             }
817             /*Just send other keys to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT`)*/
818             else {
819                 lv_group_send_data(g, data->key);
820                 if(indev_reset_check(i)) return;
821             }
822         }
823     }
824     /*Pressing*/
825     else if(is_enabled && data->state == LV_INDEV_STATE_PRESSED && prev_state == LV_INDEV_STATE_PRESSED) {
826 
827         if(data->key == LV_KEY_ENTER) {
828             if(send_event(LV_EVENT_PRESSING, indev_act) == LV_RESULT_INVALID) return;
829         }
830 
831         /*Long press time has elapsed?*/
832         if(i->long_pr_sent == 0 && lv_tick_elaps(i->pr_timestamp) > i->long_press_time) {
833             i->long_pr_sent = 1;
834             if(data->key == LV_KEY_ENTER) {
835                 i->longpr_rep_timestamp = lv_tick_get();
836 
837                 if(send_event(LV_EVENT_LONG_PRESSED, indev_act) == LV_RESULT_INVALID) return;
838             }
839         }
840         /*Long press repeated time has elapsed?*/
841         else if(i->long_pr_sent != 0 &&
842                 lv_tick_elaps(i->longpr_rep_timestamp) > i->long_press_repeat_time) {
843 
844             i->longpr_rep_timestamp = lv_tick_get();
845 
846             /*Send LONG_PRESS_REP on ENTER*/
847             if(data->key == LV_KEY_ENTER) {
848                 if(send_event(LV_EVENT_LONG_PRESSED_REPEAT, indev_act) == LV_RESULT_INVALID) return;
849             }
850             /*Move the focus on NEXT again*/
851             else if(data->key == LV_KEY_NEXT) {
852                 lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/
853                 lv_group_focus_next(g);
854                 if(indev_reset_check(i)) return;
855             }
856             /*Move the focus on PREV again*/
857             else if(data->key == LV_KEY_PREV) {
858                 lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/
859                 lv_group_focus_prev(g);
860                 if(indev_reset_check(i)) return;
861             }
862             /*Just send other keys again to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT)*/
863             else {
864                 lv_group_send_data(g, data->key);
865                 if(indev_reset_check(i)) return;
866             }
867         }
868     }
869     /*Release happened*/
870     else if(is_enabled && data->state == LV_INDEV_STATE_RELEASED && prev_state == LV_INDEV_STATE_PRESSED) {
871         LV_LOG_INFO("%" LV_PRIu32 " key is released", data->key);
872         /*The user might clear the key when it was released. Always release the pressed key*/
873         data->key = prev_key;
874         if(data->key == LV_KEY_ENTER) {
875 
876             if(send_event(LV_EVENT_RELEASED, indev_act) == LV_RESULT_INVALID) return;
877 
878             if(i->long_pr_sent == 0) {
879                 if(indev_proc_short_click(i) == LV_RESULT_INVALID) return;
880             }
881 
882             if(send_event(LV_EVENT_CLICKED, indev_act) == LV_RESULT_INVALID) return;
883 
884         }
885         i->pr_timestamp = 0;
886         i->long_pr_sent = 0;
887     }
888     indev_obj_act = NULL;
889 }
890 
891 
892 
893 /**
894  * Process a new point from LV_INDEV_TYPE_ENCODER input device
895  * @param i pointer to an input device
896  * @param data pointer to the data read from the input device
897  */
indev_encoder_proc(lv_indev_t * i,lv_indev_data_t * data)898 static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data)
899 {
900     if(data->state == LV_INDEV_STATE_PRESSED && i->wait_until_release) return;
901 
902     if(i->wait_until_release) {
903         i->wait_until_release      = 0;
904         i->pr_timestamp            = 0;
905         i->long_pr_sent            = 0;
906         i->keypad.last_state = LV_INDEV_STATE_RELEASED; /*To skip the processing of release*/
907     }
908 
909     /*Save the last keys before anything else.
910      *They need to be already saved if the function returns for any reason*/
911     lv_indev_state_t last_state     = i->keypad.last_state;
912     i->keypad.last_state = data->state;
913     i->keypad.last_key   = data->key;
914 
915     lv_group_t * g = i->group;
916     if(g == NULL) return;
917 
918     indev_obj_act = lv_group_get_focused(g);
919     if(indev_obj_act == NULL) return;
920 
921     /*Process the steps they are valid only with released button*/
922     if(data->state != LV_INDEV_STATE_RELEASED) {
923         data->enc_diff = 0;
924     }
925 
926     const bool is_enabled = !lv_obj_has_state(indev_obj_act, LV_STATE_DISABLED);
927 
928     /*Button press happened*/
929     if(data->state == LV_INDEV_STATE_PRESSED && last_state == LV_INDEV_STATE_RELEASED) {
930         LV_LOG_INFO("pressed");
931 
932         i->pr_timestamp = lv_tick_get();
933 
934         if(data->key == LV_KEY_ENTER) {
935             bool editable_or_scrollable = lv_obj_is_editable(indev_obj_act) ||
936                                           lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_SCROLLABLE);
937             if(lv_group_get_editing(g) == true || editable_or_scrollable == false) {
938 
939                 if(is_enabled) {
940                     if(send_event(LV_EVENT_PRESSED, indev_act) == LV_RESULT_INVALID) return;
941                 }
942             }
943         }
944         else if(data->key == LV_KEY_LEFT) {
945             /*emulate encoder left*/
946             data->enc_diff--;
947         }
948         else if(data->key == LV_KEY_RIGHT) {
949             /*emulate encoder right*/
950             data->enc_diff++;
951         }
952         else if(data->key == LV_KEY_ESC) {
953             /*Send the ESC as a normal KEY*/
954             lv_group_send_data(g, LV_KEY_ESC);
955             if(indev_reset_check(i)) return;
956 
957             if(is_enabled) {
958                 if(send_event(LV_EVENT_CANCEL, indev_act) == LV_RESULT_INVALID) return;
959             }
960         }
961         /*Just send other keys to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT`)*/
962         else {
963             lv_group_send_data(g, data->key);
964             if(indev_reset_check(i)) return;
965         }
966     }
967     /*Pressing*/
968     else if(data->state == LV_INDEV_STATE_PRESSED && last_state == LV_INDEV_STATE_PRESSED) {
969         /*Long press*/
970         if(i->long_pr_sent == 0 && lv_tick_elaps(i->pr_timestamp) > i->long_press_time) {
971 
972             i->long_pr_sent = 1;
973             i->longpr_rep_timestamp = lv_tick_get();
974 
975             if(data->key == LV_KEY_ENTER) {
976                 /* Always send event to indev callbacks*/
977                 lv_indev_send_event(indev_act, LV_EVENT_LONG_PRESSED, indev_obj_act);
978                 if(indev_reset_check(indev_act)) return;
979 
980                 bool editable_or_scrollable = lv_obj_is_editable(indev_obj_act) ||
981                                               lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_SCROLLABLE);
982 
983                 /*On enter long press toggle edit mode.*/
984                 if(editable_or_scrollable) {
985                     /*Don't leave edit mode if there is only one object (nowhere to navigate)*/
986                     if(lv_group_get_obj_count(g) > 1) {
987                         LV_LOG_INFO("toggling edit mode");
988                         lv_group_set_editing(g, lv_group_get_editing(g) ? false : true); /*Toggle edit mode on long press*/
989                         lv_obj_remove_state(indev_obj_act, LV_STATE_PRESSED);    /*Remove the pressed state manually*/
990                     }
991                 }
992                 /*If not editable then just send a long press event*/
993                 else {
994                     if(is_enabled) {
995                         lv_obj_send_event(indev_obj_act, LV_EVENT_LONG_PRESSED, indev_act);
996                         if(indev_reset_check(indev_act)) return;
997                     }
998                 }
999             }
1000 
1001             i->long_pr_sent = 1;
1002         }
1003         /*Long press repeated time has elapsed?*/
1004         else if(i->long_pr_sent != 0 && lv_tick_elaps(i->longpr_rep_timestamp) > i->long_press_repeat_time) {
1005 
1006             i->longpr_rep_timestamp = lv_tick_get();
1007 
1008             if(data->key == LV_KEY_ENTER) {
1009                 if(is_enabled) {
1010                     if(send_event(LV_EVENT_LONG_PRESSED_REPEAT, indev_act) == LV_RESULT_INVALID) return;
1011                 }
1012             }
1013             else if(data->key == LV_KEY_LEFT) {
1014                 /*emulate encoder left*/
1015                 data->enc_diff--;
1016             }
1017             else if(data->key == LV_KEY_RIGHT) {
1018                 /*emulate encoder right*/
1019                 data->enc_diff++;
1020             }
1021             else {
1022                 lv_group_send_data(g, data->key);
1023                 if(indev_reset_check(i)) return;
1024             }
1025 
1026         }
1027 
1028     }
1029     /*Release happened*/
1030     else if(data->state == LV_INDEV_STATE_RELEASED && last_state == LV_INDEV_STATE_PRESSED) {
1031         LV_LOG_INFO("released");
1032 
1033         if(data->key == LV_KEY_ENTER) {
1034             bool editable_or_scrollable = lv_obj_is_editable(indev_obj_act) ||
1035                                           lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_SCROLLABLE);
1036 
1037             /*The button was released on a non-editable object. Just send enter*/
1038             if(editable_or_scrollable == false) {
1039                 if(is_enabled) {
1040                     if(send_event(LV_EVENT_RELEASED, indev_act) == LV_RESULT_INVALID) return;
1041                 }
1042 
1043                 if(i->long_pr_sent == 0 && is_enabled) {
1044                     if(indev_proc_short_click(i) == LV_RESULT_INVALID) return;
1045                 }
1046 
1047                 if(is_enabled) {
1048                     if(send_event(LV_EVENT_CLICKED, indev_act) == LV_RESULT_INVALID) return;
1049                 }
1050 
1051             }
1052             /*An object is being edited and the button is released.*/
1053             else if(lv_group_get_editing(g)) {
1054                 /*Ignore long pressed enter release because it comes from mode switch*/
1055                 if(!i->long_pr_sent || lv_group_get_obj_count(g) <= 1) {
1056                     if(is_enabled) {
1057                         if(send_event(LV_EVENT_RELEASED, indev_act) == LV_RESULT_INVALID) return;
1058                         if(indev_proc_short_click(i) == LV_RESULT_INVALID) return;
1059                         if(send_event(LV_EVENT_CLICKED, indev_act) == LV_RESULT_INVALID) return;
1060                     }
1061 
1062                     lv_group_send_data(g, LV_KEY_ENTER);
1063                     if(indev_reset_check(i)) return;
1064                 }
1065                 else {
1066                     lv_obj_remove_state(indev_obj_act, LV_STATE_PRESSED);    /*Remove the pressed state manually*/
1067                 }
1068             }
1069             /*If the focused object is editable and now in navigate mode then on enter switch edit
1070                mode*/
1071             else if(!i->long_pr_sent) {
1072                 LV_LOG_INFO("entering edit mode");
1073                 lv_group_set_editing(g, true); /*Set edit mode*/
1074             }
1075         }
1076 
1077         i->pr_timestamp = 0;
1078         i->long_pr_sent = 0;
1079     }
1080     indev_obj_act = NULL;
1081 
1082     /*if encoder steps or simulated steps via left/right keys*/
1083     if(data->enc_diff != 0) {
1084         /*In edit mode send LEFT/RIGHT keys*/
1085         if(lv_group_get_editing(g)) {
1086             LV_LOG_INFO("rotated by %+d (edit)", data->enc_diff);
1087             int32_t s;
1088             if(data->enc_diff < 0) {
1089                 for(s = 0; s < -data->enc_diff; s++) {
1090                     lv_group_send_data(g, LV_KEY_LEFT);
1091                     if(indev_reset_check(i)) return;
1092                 }
1093             }
1094             else if(data->enc_diff > 0) {
1095                 for(s = 0; s < data->enc_diff; s++) {
1096                     lv_group_send_data(g, LV_KEY_RIGHT);
1097                     if(indev_reset_check(i)) return;
1098                 }
1099             }
1100         }
1101         /*In navigate mode focus on the next/prev objects*/
1102         else {
1103             LV_LOG_INFO("rotated by %+d (nav)", data->enc_diff);
1104             int32_t s;
1105             if(data->enc_diff < 0) {
1106                 for(s = 0; s < -data->enc_diff; s++) {
1107                     lv_group_focus_prev(g);
1108                     if(indev_reset_check(i)) return;
1109                 }
1110             }
1111             else if(data->enc_diff > 0) {
1112                 for(s = 0; s < data->enc_diff; s++) {
1113                     lv_group_focus_next(g);
1114                     if(indev_reset_check(i)) return;
1115                 }
1116             }
1117         }
1118     }
1119 }
1120 
1121 /**
1122  * Process new points from an input device. indev->state.pressed has to be set
1123  * @param indev pointer to an input device state
1124  * @param x x coordinate of the next point
1125  * @param y y coordinate of the next point
1126  */
indev_button_proc(lv_indev_t * i,lv_indev_data_t * data)1127 static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data)
1128 {
1129     /*Die gracefully if i->btn_points is NULL*/
1130     if(i->btn_points == NULL) {
1131         LV_LOG_WARN("btn_points is NULL");
1132         return;
1133     }
1134 
1135     int32_t x = i->btn_points[data->btn_id].x;
1136     int32_t y = i->btn_points[data->btn_id].y;
1137 
1138     if(LV_INDEV_STATE_RELEASED != data->state) {
1139         if(data->state == LV_INDEV_STATE_PRESSED) {
1140             LV_LOG_INFO("button %" LV_PRIu32 " is pressed (x:%d y:%d)", data->btn_id, (int)x, (int)y);
1141         }
1142         else {
1143             LV_LOG_INFO("button %" LV_PRIu32 " is released (x:%d y:%d)", data->btn_id, (int)x, (int)y);
1144         }
1145     }
1146 
1147     /*If a new point comes always make a release*/
1148     if(data->state == LV_INDEV_STATE_PRESSED) {
1149         if(i->pointer.last_point.x != x ||
1150            i->pointer.last_point.y != y) {
1151             indev_proc_release(i);
1152         }
1153     }
1154 
1155     if(indev_reset_check(i)) return;
1156 
1157     /*Save the new points*/
1158     i->pointer.act_point.x = x;
1159     i->pointer.act_point.y = y;
1160 
1161     if(data->state == LV_INDEV_STATE_PRESSED) indev_proc_press(i);
1162     else indev_proc_release(i);
1163 
1164     if(indev_reset_check(i)) return;
1165 
1166     i->pointer.last_point.x = i->pointer.act_point.x;
1167     i->pointer.last_point.y = i->pointer.act_point.y;
1168 }
1169 
1170 /**
1171  * Process the pressed state of LV_INDEV_TYPE_POINTER input devices
1172  * @param indev pointer to an input device 'proc'
1173  */
indev_proc_press(lv_indev_t * indev)1174 static void indev_proc_press(lv_indev_t * indev)
1175 {
1176     LV_LOG_INFO("pressed at x:%d y:%d", (int)indev->pointer.act_point.x,
1177                 (int)indev->pointer.act_point.y);
1178     indev_obj_act = indev->pointer.act_obj;
1179 
1180     if(indev->wait_until_release != 0) return;
1181 
1182     lv_display_t * disp = indev_act->disp;
1183     bool new_obj_searched = false;
1184 
1185     /*If there is no last object then search*/
1186     if(indev_obj_act == NULL) {
1187         indev_obj_act = pointer_search_obj(disp, &indev->pointer.act_point);
1188         new_obj_searched = true;
1189     }
1190     /*If there is an active object it's not scrolled and not press locked also search*/
1191     else if(indev->pointer.scroll_obj == NULL &&
1192             lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_PRESS_LOCK) == false) {
1193         indev_obj_act = pointer_search_obj(disp, &indev->pointer.act_point);
1194         new_obj_searched = true;
1195     }
1196 
1197     /*The scroll object might have scroll throw. Stop it manually*/
1198     if(new_obj_searched && indev->pointer.scroll_obj) {
1199         /*Attempt to stop scroll throw animation firstly*/
1200         if(indev->scroll_throw_anim) {
1201             lv_anim_delete(indev, indev_scroll_throw_anim_cb);
1202             indev->scroll_throw_anim = NULL;
1203         }
1204 
1205         lv_indev_scroll_throw_handler(indev);
1206         if(indev_reset_check(indev)) return;
1207     }
1208 
1209     /*If a new object was found reset some variables and send a pressed event handler*/
1210     if(indev_obj_act != indev->pointer.act_obj) {
1211         indev->pointer.last_point.x = indev->pointer.act_point.x;
1212         indev->pointer.last_point.y = indev->pointer.act_point.y;
1213 
1214         /*Without `LV_OBJ_FLAG_PRESS_LOCK` new widget can be found while pressing.*/
1215         if(indev->pointer.last_hovered && indev->pointer.last_hovered != indev_obj_act) {
1216             lv_obj_send_event(indev->pointer.last_hovered, LV_EVENT_HOVER_LEAVE, indev);
1217             if(indev_reset_check(indev)) return;
1218 
1219             lv_indev_send_event(indev, LV_EVENT_HOVER_LEAVE, indev->pointer.last_hovered);
1220             if(indev_reset_check(indev)) return;
1221 
1222             indev->pointer.last_hovered = indev_obj_act;
1223         }
1224 
1225         /*If a new object found the previous was lost, so send a PRESS_LOST event*/
1226         if(indev->pointer.act_obj != NULL) {
1227             /*Save the obj because in special cases `act_obj` can change in the event */
1228             lv_obj_t * last_obj = indev->pointer.act_obj;
1229 
1230             lv_obj_send_event(last_obj, LV_EVENT_PRESS_LOST, indev_act);
1231             if(indev_reset_check(indev)) return;
1232         }
1233 
1234         indev->pointer.act_obj  = indev_obj_act; /*Save the pressed object*/
1235         indev->pointer.last_obj = indev_obj_act;
1236 
1237         if(indev_obj_act != NULL) {
1238 
1239             /*Save the time when the obj pressed to count long press time.*/
1240             indev->pr_timestamp                 = lv_tick_get();
1241             indev->long_pr_sent                 = 0;
1242             indev->pointer.scroll_sum.x     = 0;
1243             indev->pointer.scroll_sum.y     = 0;
1244             indev->pointer.scroll_dir = LV_DIR_NONE;
1245             indev->pointer.scroll_obj = NULL;
1246             indev->pointer.gesture_dir = LV_DIR_NONE;
1247             indev->pointer.gesture_sent   = 0;
1248             indev->pointer.gesture_sum.x  = 0;
1249             indev->pointer.gesture_sum.y  = 0;
1250             indev->pointer.press_moved    = 0;
1251             indev->pointer.vect.x         = 0;
1252             indev->pointer.vect.y         = 0;
1253 
1254             const bool is_enabled = !lv_obj_has_state(indev_obj_act, LV_STATE_DISABLED);
1255             if(is_enabled) {
1256                 if(indev->pointer.last_hovered != indev_obj_act) {
1257                     if(send_event(LV_EVENT_HOVER_OVER, indev_act) == LV_RESULT_INVALID) return;
1258                 }
1259                 if(send_event(LV_EVENT_PRESSED, indev_act) == LV_RESULT_INVALID) return;
1260             }
1261 
1262             if(indev_act->wait_until_release) return;
1263 
1264             /*Handle focus*/
1265             indev_click_focus(indev_act);
1266             if(indev_reset_check(indev)) return;
1267 
1268         }
1269     }
1270 
1271     /*Calculate the vector and apply a low pass filter: new value = 0.5 * old_value + 0.5 * new_value*/
1272     indev->pointer.vect.x = indev->pointer.act_point.x - indev->pointer.last_point.x;
1273     indev->pointer.vect.y = indev->pointer.act_point.y - indev->pointer.last_point.y;
1274 
1275     indev->pointer.scroll_throw_vect.x = (indev->pointer.scroll_throw_vect.x + indev->pointer.vect.x) / 2;
1276     indev->pointer.scroll_throw_vect.y = (indev->pointer.scroll_throw_vect.y + indev->pointer.vect.y) / 2;
1277 
1278     indev->pointer.scroll_throw_vect_ori = indev->pointer.scroll_throw_vect;
1279 
1280     if(LV_ABS(indev->pointer.vect.x) > indev->scroll_limit || LV_ABS(indev->pointer.vect.y) > indev->scroll_limit) {
1281         indev->pointer.press_moved = 1;
1282     }
1283 
1284     /* Send a gesture event to a potential indev cb callback, even if no object was found */
1285     if(indev->gesture_type != LV_INDEV_GESTURE_NONE) {
1286         lv_indev_send_event(indev, LV_EVENT_GESTURE, indev_act);
1287     }
1288 
1289     if(indev_obj_act) {
1290         const bool is_enabled = !lv_obj_has_state(indev_obj_act, LV_STATE_DISABLED);
1291 
1292         if(indev->gesture_type != LV_INDEV_GESTURE_NONE) {
1293             /* NOTE: hardcoded to pinch for now */
1294             if(send_event(LV_EVENT_GESTURE, indev_act) == LV_RESULT_INVALID) return;
1295         }
1296 
1297         if(is_enabled) {
1298             if(send_event(LV_EVENT_PRESSING, indev_act) == LV_RESULT_INVALID) return;
1299         }
1300 
1301 
1302         if(indev_act->wait_until_release) return;
1303 
1304         if(indev->pointer.scroll_obj) {
1305             lv_obj_stop_scroll_anim(indev->pointer.scroll_obj);
1306         }
1307 
1308         lv_indev_scroll_handler(indev);
1309         if(indev_reset_check(indev)) return;
1310         indev_gesture(indev);
1311         if(indev_reset_check(indev)) return;
1312 
1313         if(indev->mode == LV_INDEV_MODE_EVENT && indev->read_timer && lv_timer_get_paused(indev->read_timer)) {
1314             lv_timer_resume(indev->read_timer);
1315         }
1316 
1317         /*If there is no scrolling then check for long press time*/
1318         if(indev->pointer.scroll_obj == NULL && indev->long_pr_sent == 0) {
1319             /*Send a long press event if enough time elapsed*/
1320             if(lv_tick_elaps(indev->pr_timestamp) > indev_act->long_press_time) {
1321                 if(is_enabled) {
1322                     if(send_event(LV_EVENT_LONG_PRESSED, indev_act) == LV_RESULT_INVALID) return;
1323                 }
1324                 /*Mark it to do not send the event again*/
1325                 indev->long_pr_sent = 1;
1326 
1327                 /*Save the long press time stamp for the long press repeat handler*/
1328                 indev->longpr_rep_timestamp = lv_tick_get();
1329             }
1330         }
1331 
1332         if(indev->pointer.scroll_obj == NULL && indev->long_pr_sent == 1) {
1333             if(lv_tick_elaps(indev->longpr_rep_timestamp) > indev_act->long_press_repeat_time) {
1334                 if(is_enabled) {
1335                     if(send_event(LV_EVENT_LONG_PRESSED_REPEAT, indev_act) == LV_RESULT_INVALID) return;
1336                 }
1337                 indev->longpr_rep_timestamp = lv_tick_get();
1338             }
1339         }
1340     }
1341 }
1342 
1343 /**
1344  * Process the released state of LV_INDEV_TYPE_POINTER input devices
1345  * @param proc pointer to an input device 'proc'
1346  */
indev_proc_release(lv_indev_t * indev)1347 static void indev_proc_release(lv_indev_t * indev)
1348 {
1349     if(indev->wait_until_release || /*Hover the new widget even if the coordinates didn't changed*/
1350        (indev->pointer.last_point.x != indev->pointer.act_point.x ||
1351         indev->pointer.last_point.y != indev->pointer.act_point.y)) {
1352         lv_obj_t ** last = &indev->pointer.last_hovered;
1353         lv_obj_t * hovered = pointer_search_obj(lv_display_get_default(), &indev->pointer.act_point);
1354         if(*last != hovered) {
1355             lv_obj_send_event(hovered, LV_EVENT_HOVER_OVER, indev);
1356             if(indev_reset_check(indev)) return;
1357             lv_indev_send_event(indev, LV_EVENT_HOVER_OVER, hovered);
1358             if(indev_reset_check(indev)) return;
1359 
1360             lv_obj_send_event(*last, LV_EVENT_HOVER_LEAVE, indev);
1361             if(indev_reset_check(indev)) return;
1362             lv_indev_send_event(indev, LV_EVENT_HOVER_LEAVE, *last);
1363             if(indev_reset_check(indev)) return;
1364             *last = hovered;
1365         }
1366     }
1367 
1368     if(indev->wait_until_release) {
1369         lv_obj_send_event(indev->pointer.act_obj, LV_EVENT_PRESS_LOST, indev_act);
1370         if(indev_reset_check(indev)) return;
1371 
1372         indev->pointer.act_obj  = NULL;
1373         indev->pointer.last_obj = NULL;
1374         indev->pr_timestamp           = 0;
1375         indev->longpr_rep_timestamp   = 0;
1376         indev->wait_until_release     = 0;
1377     }
1378     indev_obj_act = indev->pointer.act_obj;
1379     lv_obj_t * scroll_obj = indev->pointer.scroll_obj;
1380 
1381     if(indev->mode == LV_INDEV_MODE_EVENT && indev->read_timer && !lv_timer_get_paused(indev->read_timer)) {
1382         lv_timer_pause(indev->read_timer);
1383     }
1384 
1385     /* Send a gesture event to a potential indev cb callback, even if no object was found */
1386     if(indev->gesture_type != LV_INDEV_GESTURE_NONE) {
1387         lv_indev_send_event(indev, LV_EVENT_GESTURE, indev_act);
1388     }
1389 
1390     if(indev_obj_act) {
1391         LV_LOG_INFO("released");
1392 
1393         const bool is_enabled = !lv_obj_has_state(indev_obj_act, LV_STATE_DISABLED);
1394 
1395         if(is_enabled && indev->gesture_type != LV_INDEV_GESTURE_NONE) {
1396             if(send_event(LV_EVENT_GESTURE, indev_act) == LV_RESULT_INVALID) return;
1397         }
1398 
1399         if(is_enabled) {
1400             if(send_event(LV_EVENT_RELEASED, indev_act) == LV_RESULT_INVALID) return;
1401         }
1402 
1403         if(is_enabled) {
1404             if(scroll_obj == NULL) {
1405                 if(indev->long_pr_sent == 0) {
1406                     if(indev_proc_short_click(indev) == LV_RESULT_INVALID) return;
1407                 }
1408                 if(send_event(LV_EVENT_CLICKED, indev_act) == LV_RESULT_INVALID) return;
1409             }
1410             else {
1411                 lv_obj_send_event(scroll_obj, LV_EVENT_SCROLL_THROW_BEGIN, indev_act);
1412                 if(indev_reset_check(indev)) return;
1413             }
1414         }
1415         indev->pointer.act_obj = NULL;
1416         indev->pr_timestamp          = 0;
1417         indev->longpr_rep_timestamp  = 0;
1418 
1419         /*Get the transformed vector with this object*/
1420         if(scroll_obj) {
1421             int16_t angle = 0;
1422             int16_t scale_x = 256;
1423             int16_t scale_y = 256;
1424             lv_point_t pivot = { 0, 0 };
1425             lv_obj_t * parent = scroll_obj;
1426             while(parent) {
1427                 angle += lv_obj_get_style_transform_rotation(parent, 0);
1428                 int32_t zoom_act_x = lv_obj_get_style_transform_scale_x_safe(parent, 0);
1429                 int32_t zoom_act_y = lv_obj_get_style_transform_scale_y_safe(parent, 0);
1430                 scale_x = (scale_x * zoom_act_x) >> 8;
1431                 scale_y = (scale_x * zoom_act_y) >> 8;
1432                 parent = lv_obj_get_parent(parent);
1433             }
1434 
1435             if(scale_x == 0) {
1436                 scale_x = 1;
1437             }
1438 
1439             if(scale_y == 0) {
1440                 scale_y = 1;
1441             }
1442 
1443             if(angle != 0 || scale_y != LV_SCALE_NONE || scale_x != LV_SCALE_NONE) {
1444                 angle = -angle;
1445                 scale_x = (256 * 256) / scale_x;
1446                 scale_y = (256 * 256) / scale_y;
1447                 lv_point_transform(&indev->pointer.scroll_throw_vect, angle, scale_x, scale_y, &pivot, false);
1448                 lv_point_transform(&indev->pointer.scroll_throw_vect_ori, angle, scale_x, scale_y, &pivot, false);
1449             }
1450         }
1451     }
1452 
1453     if(scroll_obj) {
1454         if(!indev->scroll_throw_anim) {
1455             indev_scroll_throw_anim_start(indev);
1456         }
1457 
1458         if(indev_reset_check(indev)) return;
1459     }
1460 }
1461 
indev_proc_short_click(lv_indev_t * indev)1462 static lv_result_t indev_proc_short_click(lv_indev_t * indev)
1463 {
1464     /*Update streak for clicks within small distance and short time*/
1465     indev->pointer.short_click_streak++;
1466     if(lv_tick_elaps(indev->pointer.last_short_click_timestamp) > indev->long_press_time) {
1467         indev->pointer.short_click_streak = 1;
1468     }
1469     else if(indev->type == LV_INDEV_TYPE_POINTER || indev->type == LV_INDEV_TYPE_BUTTON) {
1470         int32_t dx = indev->pointer.last_short_click_point.x - indev->pointer.act_point.x;
1471         int32_t dy = indev->pointer.last_short_click_point.y - indev->pointer.act_point.y;
1472         if(dx * dx + dy * dy > indev->scroll_limit * indev->scroll_limit) indev->pointer.short_click_streak = 1;
1473     }
1474 
1475     indev->pointer.last_short_click_timestamp = lv_tick_get();
1476     lv_indev_get_point(indev, &indev->pointer.last_short_click_point);
1477 
1478     /*Simple short click*/
1479     lv_result_t res = send_event(LV_EVENT_SHORT_CLICKED, indev_act);
1480     if(res == LV_RESULT_INVALID) {
1481         return res;
1482     }
1483 
1484     /*Cycle through single/double/triple click*/
1485     switch((indev->pointer.short_click_streak - 1) % 3) {
1486         case 0:
1487             return send_event(LV_EVENT_SINGLE_CLICKED, indev_act);
1488         case 1:
1489             return send_event(LV_EVENT_DOUBLE_CLICKED, indev_act);
1490         case 2:
1491             return send_event(LV_EVENT_TRIPLE_CLICKED, indev_act);
1492     }
1493     return res;
1494 }
1495 
indev_proc_pointer_diff(lv_indev_t * indev)1496 static void indev_proc_pointer_diff(lv_indev_t * indev)
1497 {
1498     lv_obj_t * obj = indev->pointer.last_pressed;
1499     if(obj == NULL) return;
1500     if(indev->pointer.diff == 0) return;
1501 
1502     indev_obj_act = obj;
1503 
1504     bool editable = lv_obj_is_editable(obj);
1505 
1506     if(editable) {
1507         uint32_t indev_sensitivity = indev->rotary_sensitivity;
1508         uint32_t obj_sensitivity = lv_obj_get_style_rotary_sensitivity(indev_obj_act, 0);
1509         int32_t diff = (int32_t)((int32_t)indev->pointer.diff * indev_sensitivity * obj_sensitivity + 32768) >> 16;
1510         send_event(LV_EVENT_ROTARY, &diff);
1511     }
1512     else {
1513 
1514         int32_t vect = indev->pointer.diff > 0 ? indev->scroll_limit : -indev->scroll_limit;
1515         indev->pointer.vect.y = vect;
1516         indev->pointer.act_obj = obj;
1517         lv_obj_t * scroll_obj = lv_indev_find_scroll_obj(indev);
1518         if(scroll_obj == NULL) return;
1519         uint32_t indev_sensitivity = indev->rotary_sensitivity;
1520         uint32_t obj_sensitivity = lv_obj_get_style_rotary_sensitivity(scroll_obj, 0);
1521         int32_t diff = (int32_t)((int32_t)indev->pointer.diff * indev_sensitivity * obj_sensitivity + 32768) >> 16;
1522 
1523         indev->pointer.scroll_throw_vect.y = diff;
1524         indev->pointer.scroll_throw_vect_ori.y = diff;
1525         lv_indev_scroll_handler(indev);
1526     }
1527 
1528 }
1529 
pointer_search_obj(lv_display_t * disp,lv_point_t * p)1530 static lv_obj_t * pointer_search_obj(lv_display_t * disp, lv_point_t * p)
1531 {
1532     indev_obj_act = lv_indev_search_obj(lv_display_get_layer_sys(disp), p);
1533     if(indev_obj_act) return indev_obj_act;
1534 
1535     indev_obj_act = lv_indev_search_obj(lv_display_get_layer_top(disp), p);
1536     if(indev_obj_act) return indev_obj_act;
1537 
1538     /* Search the object in the active screen */
1539     indev_obj_act = lv_indev_search_obj(lv_display_get_screen_active(disp), p);
1540     if(indev_obj_act) return indev_obj_act;
1541 
1542     indev_obj_act = lv_indev_search_obj(lv_display_get_layer_bottom(disp), p);
1543     return indev_obj_act;
1544 }
1545 
1546 /**
1547  * Process a new point from LV_INDEV_TYPE_BUTTON input device
1548  * @param i pointer to an input device
1549  * @param data pointer to the data read from the input device
1550  * Reset input device if a reset query has been sent to it
1551  * @param indev pointer to an input device
1552  */
indev_proc_reset_query_handler(lv_indev_t * indev)1553 static void indev_proc_reset_query_handler(lv_indev_t * indev)
1554 {
1555     if(indev->reset_query) {
1556         indev->pointer.act_obj           = NULL;
1557         indev->pointer.last_obj          = NULL;
1558         indev->pointer.scroll_obj        = NULL;
1559         indev->pointer.last_hovered      = NULL;
1560         indev->long_pr_sent                    = 0;
1561         indev->pr_timestamp                    = 0;
1562         indev->longpr_rep_timestamp            = 0;
1563         indev->pointer.scroll_sum.x        = 0;
1564         indev->pointer.scroll_sum.y        = 0;
1565         indev->pointer.scroll_dir = LV_DIR_NONE;
1566         indev->pointer.scroll_obj = NULL;
1567         indev->pointer.scroll_throw_vect.x = 0;
1568         indev->pointer.scroll_throw_vect.y = 0;
1569         indev->pointer.gesture_sum.x     = 0;
1570         indev->pointer.gesture_sum.y     = 0;
1571         indev->reset_query                     = 0;
1572         indev->stop_processing_query           = 0;
1573         indev_obj_act                               = NULL;
1574     }
1575 }
1576 
1577 /**
1578  * Handle focus/defocus on click for POINTER input devices
1579  * @param proc pointer to the state of the indev
1580  */
indev_click_focus(lv_indev_t * indev)1581 static void indev_click_focus(lv_indev_t * indev)
1582 {
1583     /*Handle click focus*/
1584     if(lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_CLICK_FOCUSABLE) == false) {
1585         return;
1586     }
1587 
1588     lv_group_t * g_act = lv_obj_get_group(indev_obj_act);
1589     lv_group_t * g_prev = indev->pointer.last_pressed ? lv_obj_get_group(indev->pointer.last_pressed) : NULL;
1590 
1591     /*If both the last and act. obj. are in the same group (or have no group)*/
1592     if(g_act == g_prev) {
1593         /*The objects are in a group*/
1594         if(g_act) {
1595             lv_group_focus_obj(indev_obj_act);
1596             if(indev_reset_check(indev)) return;
1597         }
1598         /*The object are not in group*/
1599         else {
1600             if(indev->pointer.last_pressed != indev_obj_act) {
1601                 lv_obj_send_event(indev->pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act);
1602                 if(indev_reset_check(indev)) return;
1603 
1604                 lv_obj_send_event(indev_obj_act, LV_EVENT_FOCUSED, indev_act);
1605                 if(indev_reset_check(indev)) return;
1606             }
1607         }
1608     }
1609     /*The object are not in the same group (in different groups or one has no group)*/
1610     else {
1611         /*If the prev. obj. is not in a group then defocus it.*/
1612         if(g_prev == NULL && indev->pointer.last_pressed) {
1613             lv_obj_send_event(indev->pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act);
1614             if(indev_reset_check(indev)) return;
1615         }
1616         /*Focus on a non-group object*/
1617         else {
1618             if(indev->pointer.last_pressed) {
1619                 /*If the prev. object also wasn't in a group defocus it*/
1620                 if(g_prev == NULL) {
1621                     lv_obj_send_event(indev->pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act);
1622                     if(indev_reset_check(indev)) return;
1623                 }
1624                 /*If the prev. object also was in a group at least "LEAVE" it instead of defocus*/
1625                 else {
1626                     lv_obj_send_event(indev->pointer.last_pressed, LV_EVENT_LEAVE, indev_act);
1627                     if(indev_reset_check(indev)) return;
1628                 }
1629             }
1630         }
1631 
1632         /*Focus to the act. in its group*/
1633         if(g_act) {
1634             lv_group_focus_obj(indev_obj_act);
1635             if(indev_reset_check(indev)) return;
1636         }
1637         else {
1638             lv_obj_send_event(indev_obj_act, LV_EVENT_FOCUSED, indev_act);
1639             if(indev_reset_check(indev)) return;
1640         }
1641     }
1642     indev->pointer.last_pressed = indev_obj_act;
1643 }
1644 
1645 /**
1646 * Handle the gesture of indev_proc_p->pointer.act_obj
1647 * @param indev pointer to an input device state
1648 */
indev_gesture(lv_indev_t * indev)1649 void indev_gesture(lv_indev_t * indev)
1650 {
1651     if(indev->pointer.scroll_obj) return;
1652     if(indev->pointer.gesture_sent) return;
1653 
1654     lv_obj_t * gesture_obj = indev->pointer.act_obj;
1655 
1656     /*If gesture parent is active check recursively the gesture attribute*/
1657     while(gesture_obj && lv_obj_has_flag(gesture_obj, LV_OBJ_FLAG_GESTURE_BUBBLE)) {
1658         gesture_obj = lv_obj_get_parent(gesture_obj);
1659     }
1660 
1661     if(gesture_obj == NULL) return;
1662 
1663     if((LV_ABS(indev->pointer.vect.x) < indev_act->gesture_min_velocity) &&
1664        (LV_ABS(indev->pointer.vect.y) < indev_act->gesture_min_velocity)) {
1665         indev->pointer.gesture_sum.x = 0;
1666         indev->pointer.gesture_sum.y = 0;
1667     }
1668 
1669     /*Count the movement by gesture*/
1670     indev->pointer.gesture_sum.x += indev->pointer.vect.x;
1671     indev->pointer.gesture_sum.y += indev->pointer.vect.y;
1672 
1673     if((LV_ABS(indev->pointer.gesture_sum.x) > indev_act->gesture_limit) ||
1674        (LV_ABS(indev->pointer.gesture_sum.y) > indev_act->gesture_limit)) {
1675 
1676         indev->pointer.gesture_sent = 1;
1677 
1678         if(LV_ABS(indev->pointer.gesture_sum.x) > LV_ABS(indev->pointer.gesture_sum.y)) {
1679             if(indev->pointer.gesture_sum.x > 0)
1680                 indev->pointer.gesture_dir = LV_DIR_RIGHT;
1681             else
1682                 indev->pointer.gesture_dir = LV_DIR_LEFT;
1683         }
1684         else {
1685             if(indev->pointer.gesture_sum.y > 0)
1686                 indev->pointer.gesture_dir = LV_DIR_BOTTOM;
1687             else
1688                 indev->pointer.gesture_dir = LV_DIR_TOP;
1689         }
1690 
1691         lv_obj_send_event(gesture_obj, LV_EVENT_GESTURE, indev_act);
1692         if(indev_reset_check(indev)) return;
1693 
1694         lv_indev_send_event(indev_act, LV_EVENT_GESTURE, gesture_obj);
1695         if(indev_reset_check(indev_act)) return;
1696     }
1697 }
1698 
1699 /**
1700  * Checks if the reset_query flag has been set. If so, perform necessary global indev cleanup actions
1701  * @param proc pointer to an input device 'proc'
1702  * @return true if indev query should be immediately truncated.
1703  */
indev_reset_check(lv_indev_t * indev)1704 static bool indev_reset_check(lv_indev_t * indev)
1705 {
1706     if(indev->reset_query) {
1707         indev_obj_act = NULL;
1708     }
1709 
1710     return indev->reset_query;
1711 }
1712 
1713 /**
1714  * Checks if the stop_processing_query flag has been set. If so, do not send any events to the object
1715  * @param indev pointer to an input device
1716  * @return true if indev should stop processing the event.
1717  */
indev_stop_processing_check(lv_indev_t * indev)1718 static bool indev_stop_processing_check(lv_indev_t * indev)
1719 {
1720     return indev->stop_processing_query;
1721 }
1722 
1723 /**
1724  * Reset the indev and send event to active obj and scroll obj
1725  * @param indev pointer to an input device
1726  * @param obj pointer to obj
1727 */
indev_reset_core(lv_indev_t * indev,lv_obj_t * obj)1728 static void indev_reset_core(lv_indev_t * indev, lv_obj_t * obj)
1729 {
1730     lv_obj_t * act_obj = NULL;
1731     lv_obj_t * scroll_obj = NULL;
1732 
1733     indev->reset_query = 1;
1734     if(indev_act == indev) indev_obj_act = NULL;
1735     if(indev->type == LV_INDEV_TYPE_POINTER || indev->type == LV_INDEV_TYPE_KEYPAD) {
1736         if(obj == NULL || indev->pointer.last_pressed == obj) {
1737             indev->pointer.last_pressed = NULL;
1738         }
1739         if(obj == NULL || indev->pointer.act_obj == obj) {
1740             if(indev->pointer.act_obj) {
1741                 /* Avoid recursive calls */
1742                 act_obj = indev->pointer.act_obj;
1743                 indev->pointer.act_obj = NULL;
1744                 lv_obj_send_event(act_obj, LV_EVENT_INDEV_RESET, indev);
1745                 lv_indev_send_event(indev, LV_EVENT_INDEV_RESET, act_obj);
1746                 act_obj = NULL;
1747             }
1748         }
1749         if(obj == NULL || indev->pointer.last_obj == obj) {
1750             indev->pointer.last_obj = NULL;
1751         }
1752         if(obj == NULL || indev->pointer.scroll_obj == obj) {
1753             if(indev->pointer.scroll_obj) {
1754                 /* Avoid recursive calls */
1755                 scroll_obj = indev->pointer.scroll_obj;
1756                 indev->pointer.scroll_obj = NULL;
1757                 lv_obj_send_event(scroll_obj, LV_EVENT_INDEV_RESET, indev);
1758                 lv_indev_send_event(indev, LV_EVENT_INDEV_RESET, act_obj);
1759                 scroll_obj = NULL;
1760             }
1761         }
1762         if(obj == NULL || indev->pointer.last_hovered == obj) {
1763             indev->pointer.last_hovered = NULL;
1764         }
1765     }
1766 }
1767 
send_event(lv_event_code_t code,void * param)1768 static lv_result_t send_event(lv_event_code_t code, void * param)
1769 {
1770     lv_indev_t * indev = indev_act;
1771 
1772     if(code == LV_EVENT_PRESSED ||
1773        code == LV_EVENT_SHORT_CLICKED ||
1774        code == LV_EVENT_CLICKED ||
1775        code == LV_EVENT_RELEASED ||
1776        code == LV_EVENT_LONG_PRESSED ||
1777        code == LV_EVENT_LONG_PRESSED_REPEAT ||
1778        code == LV_EVENT_ROTARY) {
1779         lv_indev_send_event(indev, code, indev_obj_act);
1780         if(indev_reset_check(indev)) return LV_RESULT_INVALID;
1781 
1782         if(indev_stop_processing_check(indev)) {
1783             /* Not send event to the object if stop processing query is set */
1784             indev->stop_processing_query = 0;
1785             return LV_RESULT_OK;
1786         }
1787     }
1788 
1789     lv_obj_send_event(indev_obj_act, code, param);
1790     if(indev_reset_check(indev)) return LV_RESULT_INVALID;
1791 
1792     return LV_RESULT_OK;
1793 }
1794 
indev_scroll_throw_anim_cb(void * var,int32_t v)1795 static void indev_scroll_throw_anim_cb(void * var, int32_t v)
1796 {
1797     LV_ASSERT_NULL(var);
1798     LV_UNUSED(v);
1799     lv_indev_t * indev = (lv_indev_t *)var;
1800 
1801     lv_indev_scroll_throw_handler(indev);
1802 
1803     if(indev->pointer.scroll_dir == LV_DIR_NONE || indev->pointer.scroll_obj == NULL) {
1804         if(indev->scroll_throw_anim) {
1805             LV_LOG_INFO("stop animation");
1806             lv_anim_delete(indev, indev_scroll_throw_anim_cb);
1807         }
1808     }
1809 }
1810 
indev_scroll_throw_anim_completed_cb(lv_anim_t * anim)1811 static void indev_scroll_throw_anim_completed_cb(lv_anim_t * anim)
1812 {
1813     if(anim) {
1814         indev_scroll_throw_anim_reset((lv_indev_t *)anim->var);
1815     }
1816 }
1817 
indev_scroll_throw_anim_start(lv_indev_t * indev)1818 static void indev_scroll_throw_anim_start(lv_indev_t * indev)
1819 {
1820     LV_ASSERT_NULL(indev);
1821 
1822     lv_anim_t a;
1823     lv_anim_init(&a);
1824     lv_anim_set_var(&a, indev);
1825     lv_anim_set_duration(&a, 1024);
1826     lv_anim_set_values(&a, 0, 1024);
1827     lv_anim_set_exec_cb(&a, indev_scroll_throw_anim_cb);
1828     lv_anim_set_completed_cb(&a, indev_scroll_throw_anim_completed_cb);
1829     lv_anim_set_deleted_cb(&a, indev_scroll_throw_anim_completed_cb);
1830     lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
1831 
1832     indev->scroll_throw_anim = lv_anim_start(&a);
1833 }
1834