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