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