1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-28 07:03:00 +08:00

refactor(event) simplify the internals of event sending

This commit is contained in:
Gabor Kiss-Vamosi 2021-04-25 13:45:29 +02:00
parent 2d00a3fc17
commit 26ed7aa852
2 changed files with 94 additions and 111 deletions

View File

@ -17,11 +17,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;
@ -33,16 +28,13 @@ typedef struct _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 lv_res_t event_send_core(lv_event_t * e);
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;
static lv_event_t * event_head;
/**********************
* MACROS
@ -57,21 +49,32 @@ static lv_obj_t * event_original_target;
* GLOBAL FUNCTIONS
**********************/
lv_res_t lv_event_send(lv_obj_t * obj, lv_event_code_t event, void * param)
lv_res_t lv_event_send(lv_obj_t * obj, lv_event_code_t event_code, 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;
lv_event_t e;
e.target = obj;
e.current_target = obj;
e.code = event_code;
e.user_data = NULL;
e.param = param;
e.deleted = 0;
/*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`.*/
e.prev = event_head;
event_head = &e;
/*Send the event*/
lv_res_t res = event_send_core(obj, event, param);
lv_res_t res = event_send_core(&e);
/*Restore the original target*/
event_original_target = event_original_target_tmp;
/*Remove this element from the list*/
event_head = e.prev;
return res;
}
@ -89,29 +92,13 @@ lv_res_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e)
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;
if(e->deleted) res = LV_RES_INV;
return res;
}
@ -122,6 +109,11 @@ lv_obj_t * lv_event_get_target(lv_event_t * e)
return e->target;
}
lv_obj_t * lv_event_get_current_target(lv_event_t * e)
{
return e->current_target;
}
lv_event_code_t lv_event_get_code(lv_event_t * e)
{
return e->code;
@ -137,10 +129,6 @@ 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)
{
@ -151,11 +139,11 @@ uint32_t lv_event_register_id(void)
void _lv_event_mark_deleted(lv_obj_t * obj)
{
lv_event_temp_data_t * t = event_temp_data_head;
lv_event_t * e = event_head;
while(t) {
if(t->obj == obj) t->deleted = true;
t = t->prev;
while(e) {
if(e->current_target == obj || e->target == obj) e->deleted = 1;
e = e->prev;
}
}
@ -239,74 +227,38 @@ static lv_event_dsc_t * lv_obj_get_event_dsc(const lv_obj_t * obj, uint32_t id)
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)
static lv_res_t event_send_core(lv_event_t * e)
{
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;
EVENT_TRACE("Sending event %d to %p with %p param", e->code, e->current_target, e->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);
if(indev_act->driver->feedback_cb) indev_act->driver->feedback_cb(indev_act->driver, e->code);
}
lv_event_dsc_t * event_dsc = lv_obj_get_event_dsc(obj, 0);
lv_event_dsc_t * event_dsc = lv_obj_get_event_dsc(e->current_target, 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);
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;
if(event_dsc->cb && (event_dsc->filter == LV_EVENT_ALL || event_dsc->filter == e->code)) {
e->user_data = event_dsc->user_data;
event_dsc->cb(e);
/*Stop if the object is deleted*/
if(event_temp_data.deleted) {
res = LV_RES_INV;
break;
}
if(e->deleted) return LV_RES_INV;
}
i++;
event_dsc = lv_obj_get_event_dsc(obj, i);
event_dsc = lv_obj_get_event_dsc(e->current_target, 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 && event_is_bubbled(e->code)) {
if(lv_obj_has_flag(e->current_target, LV_OBJ_FLAG_EVENT_BUBBLE) && e->current_target->parent) {
e->current_target = e->current_target->parent;
res = event_send_core(e);
if(res != LV_RES_OK) return LV_RES_INV;
}
}

View File

@ -84,10 +84,12 @@ typedef enum {
typedef struct _lv_event_t {
struct _lv_obj_t * target;
struct _lv_obj_t * original_target;
struct _lv_obj_t * current_target;
lv_event_code_t code;
void * user_data;
void * param;
struct _lv_event_t * prev;
uint8_t deleted :1;
}lv_event_t;
/**
@ -103,28 +105,57 @@ typedef void (*lv_event_cb_t)(lv_event_t * e);
/**
* 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
* @param obj pointer to an object
* @param event_code the type of the event from `lv_event_t`
* @param param arbitrary data depending on the widget 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_code
*/
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);
lv_res_t lv_event_send(struct _lv_obj_t * obj, lv_event_code_t event_code, void * param);
/**
* 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
* Used by the widgets internally to call the ancestor widget types's event handler
* @param class_p pointer to the class of the widget (NOT the ancestor class)
* @param e pointer to the event descriptor
* @return LV_RES_OK: the taget object was not deleted in the event; LV_RES_INV: it was deleted in the event_code
*/
struct _lv_obj_t * lv_event_get_original_target(void);
lv_res_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e);
/**
* Get the object originally targeted by the event. It's the same even if the event is bubbled.
* @param e pointer to the event descriptor
* @return the target of the event_code
*/
struct _lv_obj_t * lv_event_get_target(lv_event_t * e);
/**
* Get the current target of the event. It's the object which event handler being called.
* If the event is not bubbled it's the same as "normal" target.
* @param e pointer to the event descriptor
* @return pointer to the current target of the event_code
*/
struct _lv_obj_t * lv_event_get_current_target(lv_event_t * e);
/**
* Get the event code of an event
* @param e pointer to the event descriptor
* @return the event code. (E.g. `LV_EVENT_CLICKED`, `LV_EVENT_FOCUSED`, etc)
*/
lv_event_code_t lv_event_get_code(lv_event_t * e);
/**
* Get the parameter passed when the event was sent
* @param e pointer to the event descriptor
* @return pointer to the parameter
*/
void * lv_event_get_param(lv_event_t * e);
/**
* Get the user_data passed when the event was registered on the object
* @param e pointer to the event descriptor
* @return pointer to the user_data
*/
void * lv_event_get_user_data(lv_event_t * e);
/**
* Register a new, custom event ID.