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