1 /**
2 * @file lv_obj_event.c
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9 #include "../misc/lv_event_private.h"
10 #include "lv_obj_event_private.h"
11 #include "lv_obj_class_private.h"
12 #include "lv_obj_private.h"
13 #include "../indev/lv_indev.h"
14 #include "../indev/lv_indev_private.h"
15
16 /*********************
17 * DEFINES
18 *********************/
19 #define MY_CLASS (&lv_obj_class)
20
21 /**********************
22 * TYPEDEFS
23 **********************/
24
25 /**********************
26 * STATIC PROTOTYPES
27 **********************/
28 static lv_result_t event_send_core(lv_event_t * e);
29 static bool event_is_bubbled(lv_event_t * e);
30
31 /**********************
32 * STATIC VARIABLES
33 **********************/
34
35 /**********************
36 * MACROS
37 **********************/
38 #if LV_USE_LOG && LV_LOG_TRACE_EVENT
39 #define LV_TRACE_EVENT(...) LV_LOG_TRACE(__VA_ARGS__)
40 #else
41 #define LV_TRACE_EVENT(...)
42 #endif
43
44 /**********************
45 * GLOBAL FUNCTIONS
46 **********************/
47
lv_obj_send_event(lv_obj_t * obj,lv_event_code_t event_code,void * param)48 lv_result_t lv_obj_send_event(lv_obj_t * obj, lv_event_code_t event_code, void * param)
49 {
50 if(obj == NULL) return LV_RESULT_OK;
51
52 LV_ASSERT_OBJ(obj, MY_CLASS);
53
54 lv_event_t e;
55 e.current_target = obj;
56 e.original_target = obj;
57 e.code = event_code;
58 e.user_data = NULL;
59 e.param = param;
60 e.deleted = 0;
61 e.stop_bubbling = 0;
62 e.stop_processing = 0;
63
64 lv_event_push(&e);
65
66 /*Send the event*/
67 lv_result_t res = event_send_core(&e);
68
69 /*Remove this element from the list*/
70 lv_event_pop(&e);
71
72 return res;
73 }
74
lv_obj_event_base(const lv_obj_class_t * class_p,lv_event_t * e)75 lv_result_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e)
76 {
77 const lv_obj_class_t * base;
78 if(class_p == NULL) base = ((lv_obj_t *)e->current_target)->class_p;
79 else base = class_p->base_class;
80
81 /*Find a base in which call the ancestor's event handler_cb if set*/
82 while(base && base->event_cb == NULL) base = base->base_class;
83
84 if(base == NULL) return LV_RESULT_OK;
85 if(base->event_cb == NULL) return LV_RESULT_OK;
86
87 /*Call the actual event callback*/
88 e->user_data = NULL;
89 LV_PROFILER_EVENT_BEGIN_TAG(lv_event_code_get_name(e->code));
90 base->event_cb(base, e);
91 LV_PROFILER_EVENT_END_TAG(lv_event_code_get_name(e->code));
92
93 lv_result_t res = LV_RESULT_OK;
94 /*Stop if the object is deleted*/
95 if(e->deleted) res = LV_RESULT_INVALID;
96
97 return res;
98 }
99
lv_obj_add_event_cb(lv_obj_t * obj,lv_event_cb_t event_cb,lv_event_code_t filter,void * user_data)100 lv_event_dsc_t * lv_obj_add_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data)
101 {
102 LV_ASSERT_OBJ(obj, MY_CLASS);
103 lv_obj_allocate_spec_attr(obj);
104
105 return lv_event_add(&obj->spec_attr->event_list, event_cb, filter, user_data);
106 }
107
lv_obj_get_event_count(lv_obj_t * obj)108 uint32_t lv_obj_get_event_count(lv_obj_t * obj)
109 {
110 LV_ASSERT_NULL(obj);
111 if(obj->spec_attr == NULL) return 0;
112 return lv_event_get_count(&obj->spec_attr->event_list);
113 }
114
lv_obj_get_event_dsc(lv_obj_t * obj,uint32_t index)115 lv_event_dsc_t * lv_obj_get_event_dsc(lv_obj_t * obj, uint32_t index)
116 {
117 LV_ASSERT_NULL(obj);
118 if(obj->spec_attr == NULL) return NULL;
119 return lv_event_get_dsc(&obj->spec_attr->event_list, index);
120 }
121
lv_obj_remove_event(lv_obj_t * obj,uint32_t index)122 bool lv_obj_remove_event(lv_obj_t * obj, uint32_t index)
123 {
124 LV_ASSERT_NULL(obj);
125 if(obj->spec_attr == NULL) return false;
126 return lv_event_remove(&obj->spec_attr->event_list, index);
127 }
128
lv_obj_remove_event_cb(lv_obj_t * obj,lv_event_cb_t event_cb)129 bool lv_obj_remove_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb)
130 {
131 LV_ASSERT_NULL(obj);
132
133 uint32_t event_cnt = lv_obj_get_event_count(obj);
134 uint32_t i;
135 for(i = 0; i < event_cnt; i++) {
136 lv_event_dsc_t * dsc = lv_obj_get_event_dsc(obj, i);
137 if(dsc && dsc->cb == event_cb) {
138 lv_obj_remove_event(obj, i);
139 return true;
140 }
141 }
142
143 return false;
144 }
145
lv_obj_remove_event_dsc(lv_obj_t * obj,lv_event_dsc_t * dsc)146 bool lv_obj_remove_event_dsc(lv_obj_t * obj, lv_event_dsc_t * dsc)
147 {
148 LV_ASSERT_NULL(obj);
149 LV_ASSERT_NULL(dsc);
150 if(obj->spec_attr == NULL) return false;
151 return lv_event_remove_dsc(&obj->spec_attr->event_list, dsc);
152 }
153
lv_obj_remove_event_cb_with_user_data(lv_obj_t * obj,lv_event_cb_t event_cb,void * user_data)154 uint32_t lv_obj_remove_event_cb_with_user_data(lv_obj_t * obj, lv_event_cb_t event_cb, void * user_data)
155 {
156 LV_ASSERT_NULL(obj);
157
158 uint32_t event_cnt = lv_obj_get_event_count(obj);
159 uint32_t removed_count = 0;
160 int32_t i;
161
162 for(i = event_cnt - 1; i >= 0; i--) {
163 lv_event_dsc_t * dsc = lv_obj_get_event_dsc(obj, i);
164 if(dsc && dsc->cb == event_cb && dsc->user_data == user_data) {
165 lv_obj_remove_event(obj, i);
166 removed_count ++;
167 }
168 }
169
170 return removed_count;
171 }
172
lv_event_get_current_target_obj(lv_event_t * e)173 lv_obj_t * lv_event_get_current_target_obj(lv_event_t * e)
174 {
175 return lv_event_get_current_target(e);
176 }
177
lv_event_get_target_obj(lv_event_t * e)178 lv_obj_t * lv_event_get_target_obj(lv_event_t * e)
179 {
180 return lv_event_get_target(e);
181 }
182
lv_event_get_indev(lv_event_t * e)183 lv_indev_t * lv_event_get_indev(lv_event_t * e)
184 {
185
186 if(e->code == LV_EVENT_PRESSED ||
187 e->code == LV_EVENT_PRESSING ||
188 e->code == LV_EVENT_PRESS_LOST ||
189 e->code == LV_EVENT_SHORT_CLICKED ||
190 e->code == LV_EVENT_LONG_PRESSED ||
191 e->code == LV_EVENT_LONG_PRESSED_REPEAT ||
192 e->code == LV_EVENT_CLICKED ||
193 e->code == LV_EVENT_RELEASED ||
194 e->code == LV_EVENT_SCROLL_BEGIN ||
195 e->code == LV_EVENT_SCROLL_END ||
196 e->code == LV_EVENT_SCROLL ||
197 e->code == LV_EVENT_GESTURE ||
198 e->code == LV_EVENT_KEY ||
199 e->code == LV_EVENT_FOCUSED ||
200 e->code == LV_EVENT_DEFOCUSED ||
201 e->code == LV_EVENT_LEAVE ||
202 e->code == LV_EVENT_HOVER_OVER ||
203 e->code == LV_EVENT_HOVER_LEAVE) {
204 return lv_event_get_param(e);
205 }
206 else {
207 LV_LOG_WARN("Not interpreted with this event code");
208 return NULL;
209 }
210 }
211
lv_event_get_layer(lv_event_t * e)212 lv_layer_t * lv_event_get_layer(lv_event_t * e)
213 {
214 if(e->code == LV_EVENT_DRAW_MAIN ||
215 e->code == LV_EVENT_DRAW_MAIN_BEGIN ||
216 e->code == LV_EVENT_DRAW_MAIN_END ||
217 e->code == LV_EVENT_DRAW_POST ||
218 e->code == LV_EVENT_DRAW_POST_BEGIN ||
219 e->code == LV_EVENT_DRAW_POST_END) {
220 return lv_event_get_param(e);
221 }
222 else {
223 LV_LOG_WARN("Not interpreted with this event code");
224 return NULL;
225 }
226 }
227
lv_event_get_old_size(lv_event_t * e)228 const lv_area_t * lv_event_get_old_size(lv_event_t * e)
229 {
230 if(e->code == LV_EVENT_SIZE_CHANGED) {
231 return lv_event_get_param(e);
232 }
233 else {
234 LV_LOG_WARN("Not interpreted with this event code");
235 return NULL;
236 }
237 }
238
lv_event_get_key(lv_event_t * e)239 uint32_t lv_event_get_key(lv_event_t * e)
240 {
241 if(e->code == LV_EVENT_KEY) {
242 uint32_t * k = lv_event_get_param(e);
243 if(k) return *k;
244 else return 0;
245 }
246 else {
247 LV_LOG_WARN("Not interpreted with this event code");
248 return 0;
249 }
250 }
251
lv_event_get_rotary_diff(lv_event_t * e)252 int32_t lv_event_get_rotary_diff(lv_event_t * e)
253 {
254 if(e->code == LV_EVENT_ROTARY) {
255 int32_t * r = lv_event_get_param(e);
256 if(r) return *r;
257 else return 0;
258 }
259 else {
260 LV_LOG_WARN("Not interpreted with this event code");
261 return 0;
262 }
263 }
264
lv_event_get_scroll_anim(lv_event_t * e)265 lv_anim_t * lv_event_get_scroll_anim(lv_event_t * e)
266 {
267 if(e->code == LV_EVENT_SCROLL_BEGIN) {
268 return lv_event_get_param(e);
269 }
270 else {
271 LV_LOG_WARN("Not interpreted with this event code");
272 return NULL;
273 }
274 }
275
lv_event_set_ext_draw_size(lv_event_t * e,int32_t size)276 void lv_event_set_ext_draw_size(lv_event_t * e, int32_t size)
277 {
278 if(e->code == LV_EVENT_REFR_EXT_DRAW_SIZE) {
279 int32_t * cur_size = lv_event_get_param(e);
280 *cur_size = LV_MAX(*cur_size, size);
281 }
282 else {
283 LV_LOG_WARN("Not interpreted with this event code");
284 }
285 }
286
lv_event_get_self_size_info(lv_event_t * e)287 lv_point_t * lv_event_get_self_size_info(lv_event_t * e)
288 {
289 if(e->code == LV_EVENT_GET_SELF_SIZE) {
290 return lv_event_get_param(e);
291 }
292 else {
293 LV_LOG_WARN("Not interpreted with this event code");
294 return 0;
295 }
296 }
297
lv_event_get_hit_test_info(lv_event_t * e)298 lv_hit_test_info_t * lv_event_get_hit_test_info(lv_event_t * e)
299 {
300 if(e->code == LV_EVENT_HIT_TEST) {
301 return lv_event_get_param(e);
302 }
303 else {
304 LV_LOG_WARN("Not interpreted with this event code");
305 return 0;
306 }
307 }
308
lv_event_get_cover_area(lv_event_t * e)309 const lv_area_t * lv_event_get_cover_area(lv_event_t * e)
310 {
311 if(e->code == LV_EVENT_COVER_CHECK) {
312 lv_cover_check_info_t * p = lv_event_get_param(e);
313 return p->area;
314 }
315 else {
316 LV_LOG_WARN("Not interpreted with this event code");
317 return NULL;
318 }
319 }
320
lv_event_set_cover_res(lv_event_t * e,lv_cover_res_t res)321 void lv_event_set_cover_res(lv_event_t * e, lv_cover_res_t res)
322 {
323 if(e->code == LV_EVENT_COVER_CHECK) {
324 lv_cover_check_info_t * p = lv_event_get_param(e);
325 if(res > p->res) p->res = res; /*Save only "stronger" results*/
326 }
327 else {
328 LV_LOG_WARN("Not interpreted with this event code");
329 }
330 }
331
lv_event_get_draw_task(lv_event_t * e)332 lv_draw_task_t * lv_event_get_draw_task(lv_event_t * e)
333 {
334 if(e->code == LV_EVENT_DRAW_TASK_ADDED) {
335 return lv_event_get_param(e);
336 }
337 else {
338 LV_LOG_WARN("Not interpreted with this event code");
339 return NULL;
340 }
341
342 }
343
344 /**********************
345 * STATIC FUNCTIONS
346 **********************/
347
event_send_core(lv_event_t * e)348 static lv_result_t event_send_core(lv_event_t * e)
349 {
350 LV_TRACE_EVENT("Sending event %d to %p with %p param", e->code, (void *)e->original_target, e->param);
351
352 /*Call the input device's feedback callback if set*/
353 lv_indev_t * indev_act = lv_indev_active();
354 if(indev_act) {
355 if(e->stop_processing) return LV_RESULT_OK;
356 if(e->deleted) return LV_RESULT_INVALID;
357 }
358
359 lv_obj_t * target = e->current_target;
360 lv_result_t res = LV_RESULT_OK;
361 lv_event_list_t * list = target->spec_attr ? &target->spec_attr->event_list : NULL;
362
363 res = lv_event_send(list, e, true);
364 if(res != LV_RESULT_OK || e->stop_processing) return res;
365
366 res = lv_obj_event_base(NULL, e);
367 if(res != LV_RESULT_OK || e->stop_processing) return res;
368
369 res = lv_event_send(list, e, false);
370 if(res != LV_RESULT_OK || e->stop_processing) return res;
371
372 lv_obj_t * parent = lv_obj_get_parent(e->current_target);
373 if(parent && event_is_bubbled(e)) {
374 e->current_target = parent;
375 res = event_send_core(e);
376 }
377
378 return res;
379 }
380
event_is_bubbled(lv_event_t * e)381 static bool event_is_bubbled(lv_event_t * e)
382 {
383 if(e->stop_bubbling) return false;
384
385 /*Event codes that always bubble*/
386 switch(e->code) {
387 case LV_EVENT_CHILD_CREATED:
388 case LV_EVENT_CHILD_DELETED:
389 return true;
390 default:
391 break;
392 }
393
394 /*Check other codes only if bubbling is enabled*/
395 if(lv_obj_has_flag(e->current_target, LV_OBJ_FLAG_EVENT_BUBBLE) == false) return false;
396
397 switch(e->code) {
398 case LV_EVENT_HIT_TEST:
399 case LV_EVENT_COVER_CHECK:
400 case LV_EVENT_REFR_EXT_DRAW_SIZE:
401 case LV_EVENT_DRAW_MAIN_BEGIN:
402 case LV_EVENT_DRAW_MAIN:
403 case LV_EVENT_DRAW_MAIN_END:
404 case LV_EVENT_DRAW_POST_BEGIN:
405 case LV_EVENT_DRAW_POST:
406 case LV_EVENT_DRAW_POST_END:
407 case LV_EVENT_DRAW_TASK_ADDED:
408 case LV_EVENT_REFRESH:
409 case LV_EVENT_DELETE:
410 case LV_EVENT_CHILD_CREATED:
411 case LV_EVENT_CHILD_DELETED:
412 case LV_EVENT_CHILD_CHANGED:
413 case LV_EVENT_SIZE_CHANGED:
414 case LV_EVENT_STYLE_CHANGED:
415 case LV_EVENT_GET_SELF_SIZE:
416 return false;
417 default:
418 return true;
419 }
420 }
421