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