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