feat(event): add preprocessing and stop bubbling features for events (#3003)

This commit is contained in:
X-Ryl669
2022-01-13 17:38:51 +01:00
committed by GitHub
parent 49dc90a2b6
commit 37c038569c
2 changed files with 60 additions and 6 deletions

View File

@@ -62,6 +62,8 @@ lv_res_t lv_event_send(lv_obj_t * obj, lv_event_code_t event_code, void * param)
e.user_data = NULL;
e.param = param;
e.deleted = 0;
e.stop_bubbling = 0;
e.stop_processing = 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
@@ -115,7 +117,7 @@ lv_obj_t * lv_event_get_current_target(lv_event_t * e)
lv_event_code_t lv_event_get_code(lv_event_t * e)
{
return e->code;
return e->code & ~LV_EVENT_PREPROCESS;
}
void * lv_event_get_param(lv_event_t * e)
@@ -128,6 +130,16 @@ void * lv_event_get_user_data(lv_event_t * e)
return e->user_data;
}
void lv_event_stop_bubbling(lv_event_t * e)
{
e->stop_bubbling = 1;
}
void lv_event_stop_processing(lv_event_t * e)
{
e->stop_processing = 1;
}
uint32_t lv_event_register_id(void)
{
@@ -419,20 +431,42 @@ static lv_res_t event_send_core(lv_event_t * e)
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, e->code);
if(e->stop_processing) return LV_RES_OK;
if(e->deleted) return LV_RES_INV;
}
lv_res_t res = LV_RES_OK;
res = lv_obj_event_base(NULL, e);
lv_event_dsc_t * event_dsc = res == LV_RES_INV ? NULL : lv_obj_get_event_dsc(e->current_target, 0);
uint32_t i = 0;
while(event_dsc && res == LV_RES_OK) {
if(event_dsc->cb && (event_dsc->filter == LV_EVENT_ALL || event_dsc->filter == e->code)) {
if(event_dsc->cb && ((event_dsc->filter & LV_EVENT_PREPROCESS) == LV_EVENT_PREPROCESS)
&& (event_dsc->filter == (LV_EVENT_ALL | LV_EVENT_PREPROCESS) ||
(event_dsc->filter & ~LV_EVENT_PREPROCESS) == e->code)) {
e->user_data = event_dsc->user_data;
event_dsc->cb(e);
if(e->stop_processing) return LV_RES_OK;
/*Stop if the object is deleted*/
if(e->deleted) return LV_RES_INV;
}
i++;
event_dsc = lv_obj_get_event_dsc(e->current_target, i);
}
res = lv_obj_event_base(NULL, e);
event_dsc = res == LV_RES_INV ? NULL : lv_obj_get_event_dsc(e->current_target, 0);
i = 0;
while(event_dsc && res == LV_RES_OK) {
if(event_dsc->cb && ((event_dsc->filter & LV_EVENT_PREPROCESS) == 0)
&& (event_dsc->filter == LV_EVENT_ALL || event_dsc->filter == e->code)) {
e->user_data = event_dsc->user_data;
event_dsc->cb(e);
if(e->stop_processing) return LV_RES_OK;
/*Stop if the object is deleted*/
if(e->deleted) return LV_RES_INV;
}
@@ -445,7 +479,6 @@ static lv_res_t event_send_core(lv_event_t * e)
e->current_target = e->current_target->parent;
res = event_send_core(e);
if(res != LV_RES_OK) return LV_RES_INV;
}
return res;
@@ -453,6 +486,8 @@ static lv_res_t event_send_core(lv_event_t * e)
static bool event_is_bubbled(lv_event_t * e)
{
if(e->stop_bubbling) return false;
/*Event codes that always bubble*/
switch(e->code) {
case LV_EVENT_CHILD_CREATED:

View File

@@ -84,7 +84,11 @@ typedef enum {
LV_EVENT_LAYOUT_CHANGED, /**< The children position has changed due to a layout recalculation*/
LV_EVENT_GET_SELF_SIZE, /**< Get the internal size of a widget*/
_LV_EVENT_LAST /** Number of default events*/
_LV_EVENT_LAST, /** Number of default events*/
LV_EVENT_PREPROCESS = 0x80, /** This is a flag that can be set with a event so it's processed
before the class default event processing */
} lv_event_code_t;
typedef struct _lv_event_t {
@@ -95,6 +99,8 @@ typedef struct _lv_event_t {
void * param;
struct _lv_event_t * prev;
uint8_t deleted : 1;
uint8_t stop_processing : 1;
uint8_t stop_bubbling : 1;
} lv_event_t;
/**
@@ -183,6 +189,19 @@ void * lv_event_get_param(lv_event_t * e);
*/
void * lv_event_get_user_data(lv_event_t * e);
/**
* Stop the event from bubbling.
* This is only valid when called in the middle of a event processing chain.
* @param e pointer to the event descriptor
*/
void lv_event_stop_bubbling(lv_event_t * e);
/**
* Stop processing this event.
* This is only valid when called in the middle of a event processing chain.
* @param e pointer to the event descriptor
*/
void lv_event_stop_processing(lv_event_t * e);
/**
* Register a new, custom event ID.