From 38b4ff6b4c395cf011b4a525bece1959b42b9590 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Sat, 24 Apr 2021 17:04:12 +0200 Subject: [PATCH] refactor(event) move event related functions to a dedicated file (core/lv_event.c/h) --- src/core/lv_event.c | 341 ++++++++++++++++++++++++++++++++++++++++++++ src/core/lv_event.h | 186 ++++++++++++++++++++++++ src/core/lv_obj.c | 305 --------------------------------------- src/core/lv_obj.h | 167 +--------------------- 4 files changed, 528 insertions(+), 471 deletions(-) create mode 100644 src/core/lv_event.c create mode 100644 src/core/lv_event.h diff --git a/src/core/lv_event.c b/src/core/lv_event.c new file mode 100644 index 000000000..4a37fa66f --- /dev/null +++ b/src/core/lv_event.c @@ -0,0 +1,341 @@ +/** + * @file lv_event.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_obj.h" +#include "lv_indev.h" + +/********************* + * DEFINES + *********************/ +#define MY_CLASS &lv_obj_class + +/********************** + * TYPEDEFS + **********************/ +typedef struct _lv_event_temp_data { + lv_obj_t * obj; + bool deleted; + struct _lv_event_temp_data * prev; +} lv_event_temp_data_t; + +typedef struct _lv_event_dsc_t{ + lv_event_cb_t cb; + void * user_data; + lv_event_code_t filter :8; +}lv_event_dsc_t; + +/********************** + * STATIC PROTOTYPES + **********************/ +static lv_event_dsc_t * lv_obj_get_event_dsc(const lv_obj_t * obj, uint32_t id); +static lv_res_t event_send_core(lv_obj_t * obj, lv_event_code_t event_code, void * param); +static bool event_is_bubbled(lv_event_code_t e); + +/********************** + * STATIC VARIABLES + **********************/ +static lv_event_temp_data_t * event_temp_data_head; +static void * event_act_param; +static void * event_act_user_data_cb; +static lv_obj_t * event_original_target; + +/********************** + * MACROS + **********************/ +#if LV_LOG_TRACE_EVENT +# define EVENT_TRACE(...) LV_LOG_TRACE( __VA_ARGS__) +#else +# define EVENT_TRACE(...) +#endif + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_res_t lv_event_send(lv_obj_t * obj, lv_event_code_t event, void * param) +{ + if(obj == NULL) return LV_RES_OK; + + LV_ASSERT_OBJ(obj, MY_CLASS); + + /*Save the original target first in tmp variable because nested `lv_event_send` calls can overwrite it*/ + lv_obj_t * event_original_target_tmp = event_original_target; + event_original_target = obj; + + /*Send the event*/ + lv_res_t res = event_send_core(obj, event, param); + + /*Restore the original target*/ + event_original_target = event_original_target_tmp; + + return res; +} + + +lv_res_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e) +{ + const lv_obj_class_t * base; + if(class_p == NULL) base = e->target->class_p; + else base = class_p->base_class; + + /*Find a base in which Call the ancestor's event handler_cb is set*/ + while(base && base->event_cb == NULL) base = base->base_class; + + if(base == NULL) return LV_RES_OK; + if(base->event_cb == NULL) return LV_RES_OK; + + /* Build a simple linked list from the objects used in the events + * It's important to know if an this object was deleted by a nested event + * called from this `event_cb`. */ + lv_event_temp_data_t event_temp_data; + event_temp_data.obj = e->target; + event_temp_data.deleted = false; + event_temp_data.prev = NULL; + + if(event_temp_data_head) { + event_temp_data.prev = event_temp_data_head; + } + event_temp_data_head = &event_temp_data; + + /*Call the actual event callback*/ + e->user_data = NULL; + base->event_cb(base, e); + + lv_res_t res = LV_RES_OK; + /*Stop if the object is deleted*/ + if(event_temp_data.deleted) res = LV_RES_INV; + + /*Remove this element from the list*/ + event_temp_data_head = event_temp_data_head->prev; + + return res; +} + + +lv_obj_t * lv_event_get_target(lv_event_t * e) +{ + return e->target; +} + +lv_event_code_t lv_event_get_code(lv_event_t * e) +{ + return e->code; +} + +void * lv_event_get_param(lv_event_t * e) +{ + return e->param; +} + +void * lv_event_get_user_data(lv_event_t * e) +{ + return e->user_data; +} + +lv_obj_t * lv_event_get_original_target(void) +{ + return event_original_target; +} + +uint32_t lv_event_register_id(void) +{ + static uint32_t last_id = _LV_EVENT_LAST; + last_id ++; + return last_id; +} + +void _lv_event_mark_deleted(lv_obj_t * obj) +{ + lv_event_temp_data_t * t = event_temp_data_head; + + while(t) { + if(t->obj == obj) t->deleted = true; + t = t->prev; + } +} + + +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, void * user_data) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_obj_allocate_spec_attr(obj); + + obj->spec_attr->event_dsc_cnt++; + obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc, obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t)); + LV_ASSERT_MALLOC(obj->spec_attr->event_dsc); + + obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].cb = event_cb; + obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].filter = filter; + obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].user_data = user_data; + + return &obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1]; +} + +bool lv_obj_remove_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + if(obj->spec_attr == NULL) return false; + + int32_t i = 0; + for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) { + if(obj->spec_attr->event_dsc[i].cb == event_cb) { + /*Shift the remaining event handlers forward*/ + for(; i < (obj->spec_attr->event_dsc_cnt-1); i++) { + obj->spec_attr->event_dsc[i].cb = obj->spec_attr->event_dsc[i+1].cb; + obj->spec_attr->event_dsc[i].user_data = obj->spec_attr->event_dsc[i+1].user_data; + } + obj->spec_attr->event_dsc_cnt--; + obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc, obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t)); + LV_ASSERT_MALLOC(obj->spec_attr->event_dsc); + return true; + } + } + + /*No event handler found*/ + return false; +} + +bool lv_obj_remove_event_dsc(lv_obj_t * obj, struct _lv_event_dsc_t * event_dsc) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + if(obj->spec_attr == NULL) return false; + + int32_t i = 0; + for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) { + if(&obj->spec_attr->event_dsc[i] == event_dsc) { + /*Shift the remaining event handlers forward*/ + for(; i < (obj->spec_attr->event_dsc_cnt-1); i++) { + obj->spec_attr->event_dsc[i].cb = obj->spec_attr->event_dsc[i+1].cb; + obj->spec_attr->event_dsc[i].user_data = obj->spec_attr->event_dsc[i+1].user_data; + } + obj->spec_attr->event_dsc_cnt--; + obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc, obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t)); + LV_ASSERT_MALLOC(obj->spec_attr->event_dsc); + return true; + } + } + + /*No event handler found*/ + return false; +} + + +/********************** + * STATIC FUNCTIONS + **********************/ + +static lv_event_dsc_t * lv_obj_get_event_dsc(const lv_obj_t * obj, uint32_t id) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + if(!obj->spec_attr) return NULL; + if(id >= obj->spec_attr->event_dsc_cnt) return NULL; + + return &obj->spec_attr->event_dsc[id]; +} + +static lv_res_t event_send_core(lv_obj_t * obj, lv_event_code_t event_code, void * param) +{ + EVENT_TRACE("Sending event %d to %p with %p param", event_code, obj, param); + + /*Build a simple linked list from the objects used in the events + *It's important to know if an this object was deleted by a nested event + *called from this `event_cb`.*/ + lv_event_temp_data_t event_temp_data; + event_temp_data.obj = obj; + event_temp_data.deleted = false; + event_temp_data.prev = NULL; + + if(event_temp_data_head) { + event_temp_data.prev = event_temp_data_head; + } + event_temp_data_head = &event_temp_data; + + /*There could be nested event sending with different param. + *It needs to be saved for the current event context because `lv_event_get_data` returns a global param.*/ + void * event_act_param_save = event_act_param; + event_act_param = param; + + /*Call the input device's feedback callback if set*/ + lv_indev_t * indev_act = lv_indev_get_act(); + if(indev_act) { + if(indev_act->driver->feedback_cb) indev_act->driver->feedback_cb(indev_act->driver, event_code); + } + + lv_event_dsc_t * event_dsc = lv_obj_get_event_dsc(obj, 0); + lv_res_t res = LV_RES_OK; + lv_event_t e; + e.code = event_code; + e.target = obj; + e.original_target = obj; + e.param = param; + res = lv_obj_event_base(NULL, &e); + + uint32_t i = 0; + while(event_dsc && res == LV_RES_OK) { + if(event_dsc->cb && (event_dsc->filter == LV_EVENT_ALL || event_dsc->filter == event_code)) { + void * event_act_user_data_cb_save = event_act_user_data_cb; + event_act_user_data_cb = event_dsc->user_data; + + e.user_data = event_dsc->user_data; + event_dsc->cb(&e); + + event_act_user_data_cb = event_act_user_data_cb_save; + + /*Stop if the object is deleted*/ + if(event_temp_data.deleted) { + res = LV_RES_INV; + break; + } + } + + i++; + event_dsc = lv_obj_get_event_dsc(obj, i); + } + + /*Restore the event_code param*/ + event_act_param = event_act_param_save; + + /*Remove this element from the list*/ + event_temp_data_head = event_temp_data_head->prev; + + if(res == LV_RES_OK && event_is_bubbled(event_code)) { + if(lv_obj_has_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE) && obj->parent) { + res = event_send_core(obj->parent, event_code, param); + if(res != LV_RES_OK) return LV_RES_INV; + } + } + + return res; +} + +static bool event_is_bubbled(lv_event_code_t e) +{ + switch(e) { + case LV_EVENT_HIT_TEST: + case LV_EVENT_COVER_CHECK: + case LV_EVENT_REFR_EXT_DRAW_SIZE: + case LV_EVENT_DRAW_MAIN_BEGIN: + case LV_EVENT_DRAW_MAIN: + case LV_EVENT_DRAW_MAIN_END: + case LV_EVENT_DRAW_POST_BEGIN: + case LV_EVENT_DRAW_POST: + case LV_EVENT_DRAW_POST_END: + case LV_EVENT_DRAW_PART_BEGIN: + case LV_EVENT_DRAW_PART_END: + case LV_EVENT_REFRESH: + case LV_EVENT_DELETE: + case LV_EVENT_CHILD_CHANGED: + case LV_EVENT_SIZE_CHANGED: + case LV_EVENT_STYLE_CHANGED: + case LV_EVENT_GET_SELF_SIZE: + return false; + default: + return true; + } +} diff --git a/src/core/lv_event.h b/src/core/lv_event.h new file mode 100644 index 000000000..43e2df987 --- /dev/null +++ b/src/core/lv_event.h @@ -0,0 +1,186 @@ +/** + * @file lv_templ.h + * + */ + +#ifndef LV_EVENT_H +#define LV_EVENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_obj_t; +struct _lv_event_dsc_t; + +/** + * Type of event being sent to the object. + */ +typedef enum { + LV_EVENT_ALL = 0, + + /** Input device events*/ + LV_EVENT_PRESSED, /**< The object has been pressed*/ + LV_EVENT_PRESSING, /**< The object is being pressed (called continuously while pressing)*/ + LV_EVENT_PRESS_LOST, /**< The object is still being pressed but slid cursor/finger off of the object */ + LV_EVENT_SHORT_CLICKED, /**< The object was pressed for a short period of time, then released it. Not called if scrolled.*/ + LV_EVENT_LONG_PRESSED, /**< Object has been pressed for at least `long_press_time`. Not called if scrolled.*/ + LV_EVENT_LONG_PRESSED_REPEAT, /**< Called after `long_press_time` in every `long_press_repeat_time` ms. Not called if scrolled.*/ + LV_EVENT_CLICKED, /**< Called on release if not scrolled (regardless to long press)*/ + LV_EVENT_RELEASED, /**< Called in every cases when the object has been released*/ + LV_EVENT_SCROLL_BEGIN, /**< Scrolling begins*/ + LV_EVENT_SCROLL_END, /**< Scrolling ends*/ + LV_EVENT_SCROLL, /**< Scrolling*/ + LV_EVENT_GESTURE, /**< A gesture is detected. Get the gesture with `lv_indev_get_gesture_dir(lv_indev_get_act());` */ + LV_EVENT_KEY, /**< A key is sent to the object. Get the key with `lv_indev_get_key(lv_indev_get_act());`*/ + LV_EVENT_FOCUSED, /**< The object is focused*/ + LV_EVENT_DEFOCUSED, /**< The object is defocused*/ + LV_EVENT_LEAVE, /**< The object is defocused but still selected*/ + LV_EVENT_HIT_TEST, /**< Perform advanced hit-testing*/ + + /** Drawing events*/ + LV_EVENT_COVER_CHECK, /**< Check if the object fully covers an area. The event parameter is `lv_cover_check_info_t *`.*/ + LV_EVENT_REFR_EXT_DRAW_SIZE, /**< Get the required extra draw area around the object (e.g. for shadow). The event parameter is `lv_coord_t *` to store the size.*/ + LV_EVENT_DRAW_MAIN_BEGIN, /**< Starting the main drawing phase*/ + LV_EVENT_DRAW_MAIN, /**< Perform the main drawing*/ + LV_EVENT_DRAW_MAIN_END, /**< Finishing the main drawing phase*/ + LV_EVENT_DRAW_POST_BEGIN, /**< Starting the post draw phase (when all children are drawn)*/ + LV_EVENT_DRAW_POST, /**< Perform the post draw phase (when all children are drawn)*/ + LV_EVENT_DRAW_POST_END, /**< Finishing the post draw phase (when all children are drawn)*/ + LV_EVENT_DRAW_PART_BEGIN, /**< Starting to draw a part. The event parameter is `lv_obj_draw_dsc_t *`. */ + LV_EVENT_DRAW_PART_END, /**< Finishing to draw a part. The event parameter is `lv_obj_draw_dsc_t *`. */ + + /** Special events*/ + LV_EVENT_VALUE_CHANGED, /**< The object's value has changed (i.e. slider moved)*/ + LV_EVENT_INSERT, /**< A text is inserted to the object. The event data is `char *` being inserted.*/ + LV_EVENT_REFRESH, /**< Notify the object to refresh something on it (for the user)*/ + LV_EVENT_READY, /**< A process has finished*/ + LV_EVENT_CANCEL, /**< A process has been cancelled */ + + /** Other events*/ + LV_EVENT_DELETE, /**< Object is being deleted*/ + LV_EVENT_CHILD_CHANGED, /**< Child was removed/added*/ + LV_EVENT_SIZE_CHANGED, /**< Object coordinates/size have changed*/ + LV_EVENT_STYLE_CHANGED, /**< Object's style has changed*/ + LV_EVENT_BASE_DIR_CHANGED, /**< The base dir has changed*/ + LV_EVENT_GET_SELF_SIZE, /**< Get the internal size of a widget*/ + + _LV_EVENT_LAST /** Number of default events*/ +}lv_event_code_t; + + +typedef struct _lv_event_t { + struct _lv_obj_t * target; + struct _lv_obj_t * original_target; + lv_event_code_t code; + void * user_data; + void * param; +}lv_event_t; + +/** + * @brief Event callback. + * Events are used to notify the user of some action being taken on the object. + * For details, see ::lv_event_t. + */ +typedef void (*lv_event_cb_t)(lv_event_t * e); + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Send an event to the object + * @param obj pointer to an object + * @param event the type of the event from `lv_event_t` + * @param param arbitrary data depending on the object type and the event. (Usually `NULL`) + * @return LV_RES_OK: `obj` was not deleted in the event; LV_RES_INV: `obj` was deleted in the event + */ +lv_res_t lv_event_send(struct _lv_obj_t * obj, lv_event_code_t event, void * param); + +lv_res_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e); + +struct _lv_obj_t * lv_event_get_target(lv_event_t * e); + +lv_event_code_t lv_event_get_code(lv_event_t * e); + +void * lv_event_get_param(lv_event_t * e); + +void * lv_event_get_user_data(lv_event_t * e); + +/** + * Get the original target of the event. It's different than the "normal" target if the event is bubbled. + * @return pointer to the object the originally received the event before bubbling it to the parents + */ +struct _lv_obj_t * lv_event_get_original_target(void); + +/** + * Register a new, custom event ID. + * It can be used the same way as e.g. `LV_EVENT_CLICKED` to send custom events + * @return the new event id + * @example + * uint32_t LV_EVENT_MINE = 0; + * ... + * e = lv_event_register_id(); + * ... + * lv_event_send(obj, LV_EVENT_MINE, &some_data); + */ +uint32_t lv_event_register_id(void); + +/** + * Nested events can be called and one of them might belong to an object that is being deleted. + * Mark this object's `event_temp_data` deleted to know that it's `lv_event_send` should return `LV_RES_INV` + * @param obj pointer to an obejct to mark as deleted + */ +void _lv_event_mark_deleted(struct _lv_obj_t * obj); + + +/** + * Add an event handler function for an object. + * Used by the user to react on event which happens with the object. + * An object can have multiple event handler. They will be called in the same order as they were added. + * @param obj pointer to an object + * @param filter and event code (e.g. `LV_EVENT_CLICKED`) on which the event should be called. `LV_EVENT_ALL` can be sued the receive all the events. + * @param event_cb the new event function + * @param user_data custom data data will be available in `event_cb` + * @return a pointer the event descriptor. Can be used in ::lv_obj_remove_event_dsc + */ +struct _lv_event_dsc_t * lv_obj_add_event_cb(struct _lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data); + +/** + * Remove an event handler function for an object. + * @param obj pointer to an object + * @param event_cb the event function to remove + * @return true if any event handlers were removed + */ +bool lv_obj_remove_event_cb(struct _lv_obj_t * obj, lv_event_cb_t event_cb); + +/** + * Remove an event handler function for an object. + * @param obj pointer to an object + * @param event_dsc pointer to an event descriptor to remove (returned by ::lv_obj_add_event_cb) + * @return true if any event handlers were removed + */ +bool lv_obj_remove_event_dsc(struct _lv_obj_t * obj, struct _lv_event_dsc_t * event_dsc); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_EVENT_H*/ diff --git a/src/core/lv_obj.c b/src/core/lv_obj.c index 6b018b364..c1ed11e5b 100644 --- a/src/core/lv_obj.c +++ b/src/core/lv_obj.c @@ -42,17 +42,6 @@ /********************** * TYPEDEFS **********************/ -typedef struct _lv_event_temp_data { - lv_obj_t * obj; - bool deleted; - struct _lv_event_temp_data * prev; -} lv_event_temp_data_t; - -typedef struct _lv_event_dsc_t{ - lv_event_cb_t cb; - void * user_data; - lv_event_code_t filter :8; -}lv_event_dsc_t; /********************** * STATIC PROTOTYPES @@ -64,19 +53,13 @@ static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e); static void draw_scrollbar(lv_obj_t * obj, const lv_area_t * clip_area); static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc); static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_find); -static lv_res_t event_send_core(lv_obj_t * obj, lv_event_code_t event_code, void * param); static void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state); static void base_dir_refr_children(lv_obj_t * obj); -static bool event_is_bubbled(lv_event_code_t e); /********************** * STATIC VARIABLES **********************/ static bool lv_initialized = false; -static lv_event_temp_data_t * event_temp_data_head; -static void * event_act_param; -static void * event_act_user_data_cb; -static lv_obj_t * event_original_target; const lv_obj_class_t lv_obj_class = { .constructor_cb = lv_obj_constructor, .destructor_cb = lv_obj_destructor, @@ -92,11 +75,6 @@ const lv_obj_class_t lv_obj_class = { /********************** * MACROS **********************/ -#if LV_LOG_TRACE_EVENT -# define EVENT_TRACE(...) LV_LOG_TRACE( __VA_ARGS__) -#else -# define EVENT_TRACE(...) -#endif /********************** * GLOBAL FUNCTIONS @@ -199,112 +177,6 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent) return lv_obj_create_from_class(&lv_obj_class, parent); } -/*--------------------- - * Event/Signal sending - *---------------------*/ - -lv_res_t lv_event_send(lv_obj_t * obj, lv_event_code_t event, void * param) -{ - if(obj == NULL) return LV_RES_OK; - - LV_ASSERT_OBJ(obj, MY_CLASS); - - /*Save the original target first in tmp variable because nested `lv_event_send` calls can overwrite it*/ - lv_obj_t * event_original_target_tmp = event_original_target; - event_original_target = obj; - - /*Send the event*/ - lv_res_t res = event_send_core(obj, event, param); - - /*Restore the original target*/ - event_original_target = event_original_target_tmp; - - return res; -} - - -lv_res_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e) -{ - const lv_obj_class_t * base; - if(class_p == NULL) base = e->target->class_p; - else base = class_p->base_class; - - /*Find a base in which Call the ancestor's event handler_cb is set*/ - while(base && base->event_cb == NULL) base = base->base_class; - - if(base == NULL) return LV_RES_OK; - if(base->event_cb == NULL) return LV_RES_OK; - - /* Build a simple linked list from the objects used in the events - * It's important to know if an this object was deleted by a nested event - * called from this `event_cb`. */ - lv_event_temp_data_t event_temp_data; - event_temp_data.obj = e->target; - event_temp_data.deleted = false; - event_temp_data.prev = NULL; - - if(event_temp_data_head) { - event_temp_data.prev = event_temp_data_head; - } - event_temp_data_head = &event_temp_data; - - /*Call the actual event callback*/ - e->user_data = NULL; - base->event_cb(base, e); - - lv_res_t res = LV_RES_OK; - /*Stop if the object is deleted*/ - if(event_temp_data.deleted) res = LV_RES_INV; - - /*Remove this element from the list*/ - event_temp_data_head = event_temp_data_head->prev; - - return res; -} - - -lv_obj_t * lv_event_get_target(lv_event_t * e) -{ - return e->target; -} - -lv_event_code_t lv_event_get_code(lv_event_t * e) -{ - return e->code; -} - -void * lv_event_get_param(lv_event_t * e) -{ - return e->param; -} - -void * lv_event_get_user_data(lv_event_t * e) -{ - return e->user_data; -} - -lv_obj_t * lv_event_get_original_target(void) -{ - return event_original_target; -} - -uint32_t lv_event_register_id(void) -{ - static uint32_t last_id = _LV_EVENT_LAST; - last_id ++; - return last_id; -} - -void _lv_event_mark_deleted(lv_obj_t * obj) -{ - lv_event_temp_data_t * t = event_temp_data_head; - - while(t) { - if(t->obj == obj) t->deleted = true; - t = t->prev; - } -} - /*===================== * Setter functions *====================*/ @@ -372,70 +244,6 @@ void lv_obj_clear_state(lv_obj_t * obj, lv_state_t state) } } -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, void * user_data) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_obj_allocate_spec_attr(obj); - - obj->spec_attr->event_dsc_cnt++; - obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc, obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t)); - LV_ASSERT_MALLOC(obj->spec_attr->event_dsc); - - obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].cb = event_cb; - obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].filter = filter; - obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].user_data = user_data; - - return &obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1]; -} - -bool lv_obj_remove_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - if(obj->spec_attr == NULL) return false; - - int32_t i = 0; - for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) { - if(obj->spec_attr->event_dsc[i].cb == event_cb) { - /*Shift the remaining event handlers forward*/ - for(; i < (obj->spec_attr->event_dsc_cnt-1); i++) { - obj->spec_attr->event_dsc[i].cb = obj->spec_attr->event_dsc[i+1].cb; - obj->spec_attr->event_dsc[i].user_data = obj->spec_attr->event_dsc[i+1].user_data; - } - obj->spec_attr->event_dsc_cnt--; - obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc, obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t)); - LV_ASSERT_MALLOC(obj->spec_attr->event_dsc); - return true; - } - } - - /*No event handler found*/ - return false; -} - -bool lv_obj_remove_event_dsc(lv_obj_t * obj, struct _lv_event_dsc_t * event_dsc) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - if(obj->spec_attr == NULL) return false; - - int32_t i = 0; - for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) { - if(&obj->spec_attr->event_dsc[i] == event_dsc) { - /*Shift the remaining event handlers forward*/ - for(; i < (obj->spec_attr->event_dsc_cnt-1); i++) { - obj->spec_attr->event_dsc[i].cb = obj->spec_attr->event_dsc[i+1].cb; - obj->spec_attr->event_dsc[i].user_data = obj->spec_attr->event_dsc[i+1].user_data; - } - obj->spec_attr->event_dsc_cnt--; - obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc, obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t)); - LV_ASSERT_MALLOC(obj->spec_attr->event_dsc); - return true; - } - } - - /*No event handler found*/ - return false; -} - void lv_obj_set_base_dir(lv_obj_t * obj, lv_bidi_dir_t dir) { if(dir != LV_BIDI_DIR_LTR && dir != LV_BIDI_DIR_RTL && @@ -512,16 +320,6 @@ bool lv_obj_has_state(const lv_obj_t * obj, lv_state_t state) return obj->state & state ? true : false; } -lv_event_dsc_t * lv_obj_get_event_dsc(const lv_obj_t * obj, uint32_t id) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - if(!obj->spec_attr) return NULL; - if(id >= obj->spec_attr->event_dsc_cnt) return NULL; - - return &obj->spec_attr->event_dsc[id]; -} - void * lv_obj_get_group(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -1050,7 +848,6 @@ static void base_dir_refr_children(lv_obj_t * obj) } } - static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_find) { @@ -1072,105 +869,3 @@ static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_fin } return false; } - -static lv_res_t event_send_core(lv_obj_t * obj, lv_event_code_t event_code, void * param) -{ - EVENT_TRACE("Sending event %d to %p with %p param", event_code, obj, param); - - /*Build a simple linked list from the objects used in the events - *It's important to know if an this object was deleted by a nested event - *called from this `event_cb`.*/ - lv_event_temp_data_t event_temp_data; - event_temp_data.obj = obj; - event_temp_data.deleted = false; - event_temp_data.prev = NULL; - - if(event_temp_data_head) { - event_temp_data.prev = event_temp_data_head; - } - event_temp_data_head = &event_temp_data; - - /*There could be nested event sending with different param. - *It needs to be saved for the current event context because `lv_event_get_data` returns a global param.*/ - void * event_act_param_save = event_act_param; - event_act_param = param; - - /*Call the input device's feedback callback if set*/ - lv_indev_t * indev_act = lv_indev_get_act(); - if(indev_act) { - if(indev_act->driver->feedback_cb) indev_act->driver->feedback_cb(indev_act->driver, event_code); - } - - lv_event_dsc_t * event_dsc = lv_obj_get_event_dsc(obj, 0); - lv_res_t res = LV_RES_OK; - lv_event_t e; - e.code = event_code; - e.target = obj; - e.original_target = obj; - e.param = param; - res = lv_obj_event_base(NULL, &e); - - uint32_t i = 0; - while(event_dsc && res == LV_RES_OK) { - if(event_dsc->cb && (event_dsc->filter == LV_EVENT_ALL || event_dsc->filter == event_code)) { - void * event_act_user_data_cb_save = event_act_user_data_cb; - event_act_user_data_cb = event_dsc->user_data; - - e.user_data = event_dsc->user_data; - event_dsc->cb(&e); - - event_act_user_data_cb = event_act_user_data_cb_save; - - /*Stop if the object is deleted*/ - if(event_temp_data.deleted) { - res = LV_RES_INV; - break; - } - } - - i++; - event_dsc = lv_obj_get_event_dsc(obj, i); - } - - /*Restore the event_code param*/ - event_act_param = event_act_param_save; - - /*Remove this element from the list*/ - event_temp_data_head = event_temp_data_head->prev; - - if(res == LV_RES_OK && event_is_bubbled(event_code)) { - if(lv_obj_has_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE) && obj->parent) { - res = event_send_core(obj->parent, event_code, param); - if(res != LV_RES_OK) return LV_RES_INV; - } - } - - return res; -} - -static bool event_is_bubbled(lv_event_code_t e) -{ - switch(e) { - case LV_EVENT_HIT_TEST: - case LV_EVENT_COVER_CHECK: - case LV_EVENT_REFR_EXT_DRAW_SIZE: - case LV_EVENT_DRAW_MAIN_BEGIN: - case LV_EVENT_DRAW_MAIN: - case LV_EVENT_DRAW_MAIN_END: - case LV_EVENT_DRAW_POST_BEGIN: - case LV_EVENT_DRAW_POST: - case LV_EVENT_DRAW_POST_END: - case LV_EVENT_DRAW_PART_BEGIN: - case LV_EVENT_DRAW_PART_END: - case LV_EVENT_REFRESH: - case LV_EVENT_DELETE: - case LV_EVENT_CHILD_CHANGED: - case LV_EVENT_SIZE_CHANGED: - case LV_EVENT_STYLE_CHANGED: - case LV_EVENT_GET_SELF_SIZE: - return false; - default: - return true; - } -} - diff --git a/src/core/lv_obj.h b/src/core/lv_obj.h index 862df3b8c..59189160c 100644 --- a/src/core/lv_obj.h +++ b/src/core/lv_obj.h @@ -33,86 +33,6 @@ extern "C" { **********************/ struct _lv_obj_t; -struct _lv_event_dsc_t; - -/*--------------------- - * EVENTS - *---------------------*/ - -/** - * Type of event being sent to the object. - */ -typedef enum { - LV_EVENT_ALL = 0, - - /** Input device events*/ - LV_EVENT_PRESSED, /**< The object has been pressed*/ - LV_EVENT_PRESSING, /**< The object is being pressed (called continuously while pressing)*/ - LV_EVENT_PRESS_LOST, /**< The object is still being pressed but slid cursor/finger off of the object */ - LV_EVENT_SHORT_CLICKED, /**< The object was pressed for a short period of time, then released it. Not called if scrolled.*/ - LV_EVENT_LONG_PRESSED, /**< Object has been pressed for at least `long_press_time`. Not called if scrolled.*/ - LV_EVENT_LONG_PRESSED_REPEAT, /**< Called after `long_press_time` in every `long_press_repeat_time` ms. Not called if scrolled.*/ - LV_EVENT_CLICKED, /**< Called on release if not scrolled (regardless to long press)*/ - LV_EVENT_RELEASED, /**< Called in every cases when the object has been released*/ - LV_EVENT_SCROLL_BEGIN, /**< Scrolling begins*/ - LV_EVENT_SCROLL_END, /**< Scrolling ends*/ - LV_EVENT_SCROLL, /**< Scrolling*/ - LV_EVENT_GESTURE, /**< A gesture is detected. Get the gesture with `lv_indev_get_gesture_dir(lv_indev_get_act());` */ - LV_EVENT_KEY, /**< A key is sent to the object. Get the key with `lv_indev_get_key(lv_indev_get_act());`*/ - LV_EVENT_FOCUSED, /**< The object is focused*/ - LV_EVENT_DEFOCUSED, /**< The object is defocused*/ - LV_EVENT_LEAVE, /**< The object is defocused but still selected*/ - LV_EVENT_HIT_TEST, /**< Perform advanced hit-testing*/ - - /** Drawing events*/ - LV_EVENT_COVER_CHECK, /**< Check if the object fully covers an area. The event parameter is `lv_cover_check_info_t *`.*/ - LV_EVENT_REFR_EXT_DRAW_SIZE, /**< Get the required extra draw area around the object (e.g. for shadow). The event parameter is `lv_coord_t *` to store the size.*/ - LV_EVENT_DRAW_MAIN_BEGIN, /**< Starting the main drawing phase*/ - LV_EVENT_DRAW_MAIN, /**< Perform the main drawing*/ - LV_EVENT_DRAW_MAIN_END, /**< Finishing the main drawing phase*/ - LV_EVENT_DRAW_POST_BEGIN, /**< Starting the post draw phase (when all children are drawn)*/ - LV_EVENT_DRAW_POST, /**< Perform the post draw phase (when all children are drawn)*/ - LV_EVENT_DRAW_POST_END, /**< Finishing the post draw phase (when all children are drawn)*/ - LV_EVENT_DRAW_PART_BEGIN, /**< Starting to draw a part. The event parameter is `lv_obj_draw_dsc_t *`. */ - LV_EVENT_DRAW_PART_END, /**< Finishing to draw a part. The event parameter is `lv_obj_draw_dsc_t *`. */ - - /** Special events*/ - LV_EVENT_VALUE_CHANGED, /**< The object's value has changed (i.e. slider moved)*/ - LV_EVENT_INSERT, /**< A text is inserted to the object. The event data is `char *` being inserted.*/ - LV_EVENT_REFRESH, /**< Notify the object to refresh something on it (for the user)*/ - LV_EVENT_READY, /**< A process has finished*/ - LV_EVENT_CANCEL, /**< A process has been cancelled */ - - /** Other events*/ - LV_EVENT_DELETE, /**< Object is being deleted*/ - LV_EVENT_CHILD_CHANGED, /**< Child was removed/added*/ - LV_EVENT_SIZE_CHANGED, /**< Object coordinates/size have changed*/ - LV_EVENT_STYLE_CHANGED, /**< Object's style has changed*/ - LV_EVENT_BASE_DIR_CHANGED, /**< The base dir has changed*/ - LV_EVENT_GET_SELF_SIZE, /**< Get the internal size of a widget*/ - - _LV_EVENT_LAST /** Number of default events*/ -}lv_event_code_t; - - -typedef struct _lv_event_t { - struct _lv_obj_t * target; - struct _lv_obj_t * original_target; - lv_event_code_t code; - void * user_data; - void * param; -}lv_event_t; - -/** - * @brief Event callback. - * Events are used to notify the user of some action being taken on the object. - * For details, see ::lv_event_t. - */ -typedef void (*lv_event_cb_t)(lv_event_t * e); - -/*--------------------- - * EVENTS - *---------------------*/ /** * Possible states of a widget. @@ -205,6 +125,7 @@ typedef uint32_t lv_obj_flag_t; #include "lv_obj_style.h" #include "lv_obj_draw.h" #include "lv_obj_class.h" +#include "lv_event.h" #include "lv_group.h" /** @@ -301,55 +222,6 @@ void lv_deinit(void); lv_obj_t * lv_obj_create(lv_obj_t * parent); -/*--------------------- - * Event/Signal sending - *---------------------*/ - -/** - * Send an event to the object - * @param obj pointer to an object - * @param event the type of the event from `lv_event_t` - * @param param arbitrary data depending on the object type and the event. (Usually `NULL`) - * @return LV_RES_OK: `obj` was not deleted in the event; LV_RES_INV: `obj` was deleted in the event - */ -lv_res_t lv_event_send(lv_obj_t * obj, lv_event_code_t event, void * param); - -lv_res_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e); - -lv_obj_t * lv_event_get_target(lv_event_t * e); - -lv_event_code_t lv_event_get_code(lv_event_t * e); - -void * lv_event_get_param(lv_event_t * e); - -void * lv_event_get_user_data(lv_event_t * e); - -/** - * Get the original target of the event. It's different than the "normal" target if the event is bubbled. - * @return pointer to the object the originally received the event before bubbling it to the parents - */ -lv_obj_t * lv_event_get_original_target(void); - -/** - * Register a new, custom event ID. - * It can be used the same way as e.g. `LV_EVENT_CLICKED` to send custom events - * @return the new event id - * @example - * uint32_t LV_EVENT_MINE = 0; - * ... - * e = lv_event_register_id(); - * ... - * lv_event_send(obj, LV_EVENT_MINE, &some_data); - */ -uint32_t lv_event_register_id(void); - -/** - * Nested events can be called and one of them might belong to an object that is being deleted. - * Mark this object's `event_temp_data` deleted to know that it's `lv_event_send` should return `LV_RES_INV` - * @param obj pointer to an obejct to mark as deleted - */ -void _lv_event_mark_deleted(lv_obj_t * obj); - /*===================== * Setter functions *====================*/ @@ -385,34 +257,6 @@ void lv_obj_add_state(lv_obj_t * obj, lv_state_t state); */ void lv_obj_clear_state(lv_obj_t * obj, lv_state_t state); -/** - * Add an event handler function for an object. - * Used by the user to react on event which happens with the object. - * An object can have multiple event handler. They will be called in the same order as they were added. - * @param obj pointer to an object - * @param filter and event code (e.g. `LV_EVENT_CLICKED`) on which the event should be called. `LV_EVENT_ALL` can be sued the receive all the events. - * @param event_cb the new event function - * @param user_data custom data data will be available in `event_cb` - * @return a pointer the event descriptor. Can be used in ::lv_obj_remove_event_dsc - */ -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, void * user_data); - -/** - * Remove an event handler function for an object. - * @param obj pointer to an object - * @param event_cb the event function to remove - * @return true if any event handlers were removed - */ -bool lv_obj_remove_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb); - -/** - * Remove an event handler function for an object. - * @param obj pointer to an object - * @param event_dsc pointer to an event descriptor to remove (returned by ::lv_obj_add_event_cb) - * @return true if any event handlers were removed - */ -bool lv_obj_remove_event_dsc(lv_obj_t * obj, struct _lv_event_dsc_t * event_dsc); - /** * Set the base direction of the object * @param obj pointer to an object @@ -420,7 +264,6 @@ bool lv_obj_remove_event_dsc(lv_obj_t * obj, struct _lv_event_dsc_t * event_dsc) */ void lv_obj_set_base_dir(lv_obj_t * obj, lv_bidi_dir_t dir); - /*======================= * Getter functions *======================*/ @@ -464,14 +307,6 @@ lv_state_t lv_obj_get_state(const lv_obj_t * obj); */ bool lv_obj_has_state(const lv_obj_t * obj, lv_state_t state); -/** - * Get the event function of an object - * @param obj pointer to an object - * @param id the index of the event callback. 0: the firstly added - * @return the event descriptor - */ -struct _lv_event_dsc_t * lv_obj_get_event_dsc(const lv_obj_t * obj, uint32_t id); - /** * Get the group of the object * @param obj pointer to an object