1 /**
2  * @file lv_event.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 #include "lv_obj.h"
10 #include "lv_indev.h"
11 
12 /*********************
13  *      DEFINES
14  *********************/
15 #define MY_CLASS &lv_obj_class
16 
17 /**********************
18  *      TYPEDEFS
19  **********************/
20 typedef struct _lv_event_dsc_t {
21     lv_event_cb_t cb;
22     void * user_data;
23     lv_event_code_t filter : 8;
24 } lv_event_dsc_t;
25 
26 /**********************
27  *  STATIC PROTOTYPES
28  **********************/
29 static lv_event_dsc_t * lv_obj_get_event_dsc(const lv_obj_t * obj, uint32_t id);
30 static lv_res_t event_send_core(lv_event_t * e);
31 static bool event_is_bubbled(lv_event_t * e);
32 
33 /**********************
34  *  STATIC VARIABLES
35  **********************/
36 static lv_event_t * event_head;
37 
38 /**********************
39  *      MACROS
40  **********************/
41 #if LV_LOG_TRACE_EVENT
42     #define EVENT_TRACE(...) LV_LOG_TRACE(__VA_ARGS__)
43 #else
44     #define EVENT_TRACE(...)
45 #endif
46 
47 /**********************
48  *   GLOBAL FUNCTIONS
49  **********************/
50 
lv_event_send(lv_obj_t * obj,lv_event_code_t event_code,void * param)51 lv_res_t lv_event_send(lv_obj_t * obj, lv_event_code_t event_code, void * param)
52 {
53     if(obj == NULL) return LV_RES_OK;
54 
55     LV_ASSERT_OBJ(obj, MY_CLASS);
56 
57     lv_event_t e;
58     e.target = obj;
59     e.current_target = obj;
60     e.code = event_code;
61     e.user_data = NULL;
62     e.param = param;
63     e.deleted = 0;
64     e.stop_bubbling = 0;
65     e.stop_processing = 0;
66 
67     /*Build a simple linked list from the objects used in the events
68      *It's important to know if this object was deleted by a nested event
69      *called from this `event_cb`.*/
70     e.prev = event_head;
71     event_head = &e;
72 
73     /*Send the event*/
74     lv_res_t res = event_send_core(&e);
75 
76     /*Remove this element from the list*/
77     event_head = e.prev;
78 
79     return res;
80 }
81 
lv_obj_event_base(const lv_obj_class_t * class_p,lv_event_t * e)82 lv_res_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e)
83 {
84     const lv_obj_class_t * base;
85     if(class_p == NULL) base = e->current_target->class_p;
86     else base = class_p->base_class;
87 
88     /*Find a base in which call the ancestor's event handler_cb if set*/
89     while(base && base->event_cb == NULL) base = base->base_class;
90 
91     if(base == NULL) return LV_RES_OK;
92     if(base->event_cb == NULL) return LV_RES_OK;
93 
94     /*Call the actual event callback*/
95     e->user_data = NULL;
96     base->event_cb(base, e);
97 
98     lv_res_t res = LV_RES_OK;
99     /*Stop if the object is deleted*/
100     if(e->deleted) res = LV_RES_INV;
101 
102     return res;
103 }
104 
lv_event_get_target(lv_event_t * e)105 lv_obj_t * lv_event_get_target(lv_event_t * e)
106 {
107     return e->target;
108 }
109 
lv_event_get_current_target(lv_event_t * e)110 lv_obj_t * lv_event_get_current_target(lv_event_t * e)
111 {
112     return e->current_target;
113 }
114 
lv_event_get_code(lv_event_t * e)115 lv_event_code_t lv_event_get_code(lv_event_t * e)
116 {
117     return e->code & ~LV_EVENT_PREPROCESS;
118 }
119 
lv_event_get_param(lv_event_t * e)120 void * lv_event_get_param(lv_event_t * e)
121 {
122     return e->param;
123 }
124 
lv_event_get_user_data(lv_event_t * e)125 void * lv_event_get_user_data(lv_event_t * e)
126 {
127     return e->user_data;
128 }
129 
lv_event_stop_bubbling(lv_event_t * e)130 void lv_event_stop_bubbling(lv_event_t * e)
131 {
132     e->stop_bubbling = 1;
133 }
134 
lv_event_stop_processing(lv_event_t * e)135 void lv_event_stop_processing(lv_event_t * e)
136 {
137     e->stop_processing = 1;
138 }
139 
lv_event_register_id(void)140 uint32_t lv_event_register_id(void)
141 {
142     static uint32_t last_id = _LV_EVENT_LAST;
143     last_id ++;
144     return last_id;
145 }
146 
_lv_event_mark_deleted(lv_obj_t * obj)147 void _lv_event_mark_deleted(lv_obj_t * obj)
148 {
149     lv_event_t * e = event_head;
150 
151     while(e) {
152         if(e->current_target == obj || e->target == obj) e->deleted = 1;
153         e = e->prev;
154     }
155 }
156 
lv_obj_add_event_cb(lv_obj_t * obj,lv_event_cb_t event_cb,lv_event_code_t filter,void * user_data)157 struct _lv_event_dsc_t * lv_obj_add_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter,
158                                              void * user_data)
159 {
160     LV_ASSERT_OBJ(obj, MY_CLASS);
161     lv_obj_allocate_spec_attr(obj);
162 
163     obj->spec_attr->event_dsc_cnt++;
164     obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc,
165                                                obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t));
166     LV_ASSERT_MALLOC(obj->spec_attr->event_dsc);
167 
168     obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].cb = event_cb;
169     obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].filter = filter;
170     obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].user_data = user_data;
171 
172     return &obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1];
173 }
174 
lv_obj_remove_event_cb(lv_obj_t * obj,lv_event_cb_t event_cb)175 bool lv_obj_remove_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb)
176 {
177     LV_ASSERT_OBJ(obj, MY_CLASS);
178     if(obj->spec_attr == NULL) return false;
179 
180     int32_t i = 0;
181     for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) {
182         if(event_cb == NULL || obj->spec_attr->event_dsc[i].cb == event_cb) {
183             /*Shift the remaining event handlers forward*/
184             for(; i < (obj->spec_attr->event_dsc_cnt - 1); i++) {
185                 obj->spec_attr->event_dsc[i] = obj->spec_attr->event_dsc[i + 1];
186             }
187             obj->spec_attr->event_dsc_cnt--;
188             obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc,
189                                                        obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t));
190             LV_ASSERT_MALLOC(obj->spec_attr->event_dsc);
191             return true;
192         }
193     }
194 
195     /*No event handler found*/
196     return false;
197 }
198 
lv_obj_remove_event_cb_with_user_data(lv_obj_t * obj,lv_event_cb_t event_cb,const void * user_data)199 bool lv_obj_remove_event_cb_with_user_data(lv_obj_t * obj, lv_event_cb_t event_cb, const void * user_data)
200 {
201     LV_ASSERT_OBJ(obj, MY_CLASS);
202     if(obj->spec_attr == NULL) return false;
203 
204     int32_t i = 0;
205     for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) {
206         if((event_cb == NULL || obj->spec_attr->event_dsc[i].cb == event_cb) &&
207            obj->spec_attr->event_dsc[i].user_data == user_data) {
208             /*Shift the remaining event handlers forward*/
209             for(; i < (obj->spec_attr->event_dsc_cnt - 1); i++) {
210                 obj->spec_attr->event_dsc[i] = obj->spec_attr->event_dsc[i + 1];
211             }
212             obj->spec_attr->event_dsc_cnt--;
213             obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc,
214                                                        obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t));
215             LV_ASSERT_MALLOC(obj->spec_attr->event_dsc);
216             return true;
217         }
218     }
219 
220     /*No event handler found*/
221     return false;
222 }
223 
lv_obj_remove_event_dsc(lv_obj_t * obj,struct _lv_event_dsc_t * event_dsc)224 bool lv_obj_remove_event_dsc(lv_obj_t * obj, struct _lv_event_dsc_t * event_dsc)
225 {
226     LV_ASSERT_OBJ(obj, MY_CLASS);
227     if(obj->spec_attr == NULL) return false;
228 
229     int32_t i = 0;
230     for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) {
231         if(&obj->spec_attr->event_dsc[i] == event_dsc) {
232             /*Shift the remaining event handlers forward*/
233             for(; i < (obj->spec_attr->event_dsc_cnt - 1); i++) {
234                 obj->spec_attr->event_dsc[i] = obj->spec_attr->event_dsc[i + 1];
235             }
236             obj->spec_attr->event_dsc_cnt--;
237             obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc,
238                                                        obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t));
239             LV_ASSERT_MALLOC(obj->spec_attr->event_dsc);
240             return true;
241         }
242     }
243 
244     /*No event handler found*/
245     return false;
246 }
247 
lv_obj_get_event_user_data(struct _lv_obj_t * obj,lv_event_cb_t event_cb)248 void * lv_obj_get_event_user_data(struct _lv_obj_t * obj, lv_event_cb_t event_cb)
249 {
250     LV_ASSERT_OBJ(obj, MY_CLASS);
251     if(obj->spec_attr == NULL) return NULL;
252 
253     int32_t i = 0;
254     for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) {
255         if(event_cb == obj->spec_attr->event_dsc[i].cb) return obj->spec_attr->event_dsc[i].user_data;
256     }
257     return NULL;
258 }
259 
lv_event_get_indev(lv_event_t * e)260 lv_indev_t * lv_event_get_indev(lv_event_t * e)
261 {
262 
263     if(e->code == LV_EVENT_PRESSED ||
264        e->code == LV_EVENT_PRESSING ||
265        e->code == LV_EVENT_PRESS_LOST ||
266        e->code == LV_EVENT_SHORT_CLICKED ||
267        e->code == LV_EVENT_LONG_PRESSED ||
268        e->code == LV_EVENT_LONG_PRESSED_REPEAT ||
269        e->code == LV_EVENT_CLICKED ||
270        e->code == LV_EVENT_RELEASED ||
271        e->code == LV_EVENT_SCROLL_BEGIN ||
272        e->code == LV_EVENT_SCROLL_END ||
273        e->code == LV_EVENT_SCROLL ||
274        e->code == LV_EVENT_GESTURE ||
275        e->code == LV_EVENT_KEY ||
276        e->code == LV_EVENT_FOCUSED ||
277        e->code == LV_EVENT_DEFOCUSED ||
278        e->code == LV_EVENT_LEAVE) {
279         return lv_event_get_param(e);
280     }
281     else {
282         LV_LOG_WARN("Not interpreted with this event code");
283         return NULL;
284     }
285 }
286 
lv_event_get_draw_part_dsc(lv_event_t * e)287 lv_obj_draw_part_dsc_t * lv_event_get_draw_part_dsc(lv_event_t * e)
288 {
289     if(e->code == LV_EVENT_DRAW_PART_BEGIN ||
290        e->code == LV_EVENT_DRAW_PART_END) {
291         return lv_event_get_param(e);
292     }
293     else {
294         LV_LOG_WARN("Not interpreted with this event code");
295         return NULL;
296     }
297 }
298 
lv_event_get_draw_ctx(lv_event_t * e)299 lv_draw_ctx_t * lv_event_get_draw_ctx(lv_event_t * e)
300 {
301     if(e->code == LV_EVENT_DRAW_MAIN ||
302        e->code == LV_EVENT_DRAW_MAIN_BEGIN ||
303        e->code == LV_EVENT_DRAW_MAIN_END ||
304        e->code == LV_EVENT_DRAW_POST ||
305        e->code == LV_EVENT_DRAW_POST_BEGIN ||
306        e->code == LV_EVENT_DRAW_POST_END) {
307         return lv_event_get_param(e);
308     }
309     else {
310         LV_LOG_WARN("Not interpreted with this event code");
311         return NULL;
312     }
313 }
314 
lv_event_get_old_size(lv_event_t * e)315 const lv_area_t * lv_event_get_old_size(lv_event_t * e)
316 {
317     if(e->code == LV_EVENT_SIZE_CHANGED) {
318         return lv_event_get_param(e);
319     }
320     else {
321         LV_LOG_WARN("Not interpreted with this event code");
322         return NULL;
323     }
324 }
325 
lv_event_get_key(lv_event_t * e)326 uint32_t lv_event_get_key(lv_event_t * e)
327 {
328     if(e->code == LV_EVENT_KEY) {
329         uint32_t * k = lv_event_get_param(e);
330         if(k) return *k;
331         else return 0;
332     }
333     else {
334         LV_LOG_WARN("Not interpreted with this event code");
335         return 0;
336     }
337 }
338 
lv_event_get_scroll_anim(lv_event_t * e)339 lv_anim_t * lv_event_get_scroll_anim(lv_event_t * e)
340 {
341     if(e->code == LV_EVENT_SCROLL_BEGIN) {
342         return lv_event_get_param(e);
343     }
344     else {
345         LV_LOG_WARN("Not interpreted with this event code");
346         return 0;
347     }
348 }
349 
lv_event_set_ext_draw_size(lv_event_t * e,lv_coord_t size)350 void lv_event_set_ext_draw_size(lv_event_t * e, lv_coord_t size)
351 {
352     if(e->code == LV_EVENT_REFR_EXT_DRAW_SIZE) {
353         lv_coord_t * cur_size = lv_event_get_param(e);
354         *cur_size = LV_MAX(*cur_size, size);
355     }
356     else {
357         LV_LOG_WARN("Not interpreted with this event code");
358     }
359 }
360 
lv_event_get_self_size_info(lv_event_t * e)361 lv_point_t * lv_event_get_self_size_info(lv_event_t * e)
362 {
363     if(e->code == LV_EVENT_GET_SELF_SIZE) {
364         return lv_event_get_param(e);
365     }
366     else {
367         LV_LOG_WARN("Not interpreted with this event code");
368         return 0;
369     }
370 }
371 
lv_event_get_hit_test_info(lv_event_t * e)372 lv_hit_test_info_t * lv_event_get_hit_test_info(lv_event_t * e)
373 {
374     if(e->code == LV_EVENT_HIT_TEST) {
375         return lv_event_get_param(e);
376     }
377     else {
378         LV_LOG_WARN("Not interpreted with this event code");
379         return 0;
380     }
381 }
382 
lv_event_get_cover_area(lv_event_t * e)383 const lv_area_t * lv_event_get_cover_area(lv_event_t * e)
384 {
385     if(e->code == LV_EVENT_COVER_CHECK) {
386         lv_cover_check_info_t * p = lv_event_get_param(e);
387         return p->area;
388     }
389     else {
390         LV_LOG_WARN("Not interpreted with this event code");
391         return NULL;
392     }
393 }
394 
lv_event_set_cover_res(lv_event_t * e,lv_cover_res_t res)395 void lv_event_set_cover_res(lv_event_t * e, lv_cover_res_t res)
396 {
397     if(e->code == LV_EVENT_COVER_CHECK) {
398         lv_cover_check_info_t * p = lv_event_get_param(e);
399         if(res > p->res) p->res = res;  /*Save only "stronger" results*/
400     }
401     else {
402         LV_LOG_WARN("Not interpreted with this event code");
403     }
404 }
405 
406 /**********************
407  *   STATIC FUNCTIONS
408  **********************/
409 
lv_obj_get_event_dsc(const lv_obj_t * obj,uint32_t id)410 static lv_event_dsc_t * lv_obj_get_event_dsc(const lv_obj_t * obj, uint32_t id)
411 {
412     LV_ASSERT_OBJ(obj, MY_CLASS);
413 
414     if(!obj->spec_attr) return NULL;
415     if(id >= obj->spec_attr->event_dsc_cnt) return NULL;
416 
417     return &obj->spec_attr->event_dsc[id];
418 }
419 
event_send_core(lv_event_t * e)420 static lv_res_t event_send_core(lv_event_t * e)
421 {
422     EVENT_TRACE("Sending event %d to %p with %p param", e->code, (void *)e->current_target, e->param);
423 
424     /*Call the input device's feedback callback if set*/
425     lv_indev_t * indev_act = lv_indev_get_act();
426     if(indev_act) {
427         if(indev_act->driver->feedback_cb) indev_act->driver->feedback_cb(indev_act->driver, e->code);
428         if(e->stop_processing) return LV_RES_OK;
429         if(e->deleted) return LV_RES_INV;
430     }
431 
432     lv_res_t res = LV_RES_OK;
433     lv_event_dsc_t * event_dsc = lv_obj_get_event_dsc(e->current_target, 0);
434 
435     uint32_t i = 0;
436     while(event_dsc && res == LV_RES_OK) {
437         if(event_dsc->cb  && ((event_dsc->filter & LV_EVENT_PREPROCESS) == LV_EVENT_PREPROCESS)
438            && (event_dsc->filter == (LV_EVENT_ALL | LV_EVENT_PREPROCESS) ||
439                (event_dsc->filter & ~LV_EVENT_PREPROCESS) == e->code)) {
440             e->user_data = event_dsc->user_data;
441             event_dsc->cb(e);
442 
443             if(e->stop_processing) return LV_RES_OK;
444             /*Stop if the object is deleted*/
445             if(e->deleted) return LV_RES_INV;
446         }
447 
448         i++;
449         event_dsc = lv_obj_get_event_dsc(e->current_target, i);
450     }
451 
452     res = lv_obj_event_base(NULL, e);
453 
454     event_dsc = res == LV_RES_INV ? NULL : lv_obj_get_event_dsc(e->current_target, 0);
455 
456     i = 0;
457     while(event_dsc && res == LV_RES_OK) {
458         if(event_dsc->cb && ((event_dsc->filter & LV_EVENT_PREPROCESS) == 0)
459            && (event_dsc->filter == LV_EVENT_ALL || event_dsc->filter == e->code)) {
460             e->user_data = event_dsc->user_data;
461             event_dsc->cb(e);
462 
463             if(e->stop_processing) return LV_RES_OK;
464             /*Stop if the object is deleted*/
465             if(e->deleted) return LV_RES_INV;
466         }
467 
468         i++;
469         event_dsc = lv_obj_get_event_dsc(e->current_target, i);
470     }
471 
472     if(res == LV_RES_OK && e->current_target->parent && event_is_bubbled(e)) {
473         e->current_target = e->current_target->parent;
474         res = event_send_core(e);
475         if(res != LV_RES_OK) return LV_RES_INV;
476     }
477 
478     return res;
479 }
480 
event_is_bubbled(lv_event_t * e)481 static bool event_is_bubbled(lv_event_t * e)
482 {
483     if(e->stop_bubbling) return false;
484 
485     /*Event codes that always bubble*/
486     switch(e->code) {
487         case LV_EVENT_CHILD_CREATED:
488         case LV_EVENT_CHILD_DELETED:
489             return true;
490         default:
491             break;
492     }
493 
494     /*Check other codes only if bubbling is enabled*/
495     if(lv_obj_has_flag(e->current_target, LV_OBJ_FLAG_EVENT_BUBBLE) == false) return false;
496 
497     switch(e->code) {
498         case LV_EVENT_HIT_TEST:
499         case LV_EVENT_COVER_CHECK:
500         case LV_EVENT_REFR_EXT_DRAW_SIZE:
501         case LV_EVENT_DRAW_MAIN_BEGIN:
502         case LV_EVENT_DRAW_MAIN:
503         case LV_EVENT_DRAW_MAIN_END:
504         case LV_EVENT_DRAW_POST_BEGIN:
505         case LV_EVENT_DRAW_POST:
506         case LV_EVENT_DRAW_POST_END:
507         case LV_EVENT_DRAW_PART_BEGIN:
508         case LV_EVENT_DRAW_PART_END:
509         case LV_EVENT_REFRESH:
510         case LV_EVENT_DELETE:
511         case LV_EVENT_CHILD_CREATED:
512         case LV_EVENT_CHILD_DELETED:
513         case LV_EVENT_CHILD_CHANGED:
514         case LV_EVENT_SIZE_CHANGED:
515         case LV_EVENT_STYLE_CHANGED:
516         case LV_EVENT_GET_SELF_SIZE:
517             return false;
518         default:
519             return true;
520     }
521 }
522