mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-31 16:27:03 +08:00
feat(display): send screen load events to display (#9600)
This commit is contained in:
@@ -30,3 +30,7 @@
|
|||||||
Call returns immediately if `disp->flushing == 0`.
|
Call returns immediately if `disp->flushing == 0`.
|
||||||
- :cpp:enumerator:`LV_EVENT_FLUSH_WAIT_FINISH`: Sent when the call to `wait_for_flushing()`
|
- :cpp:enumerator:`LV_EVENT_FLUSH_WAIT_FINISH`: Sent when the call to `wait_for_flushing()`
|
||||||
is about to return, regardless whether any actual waiting occurred.
|
is about to return, regardless whether any actual waiting occurred.
|
||||||
|
- :cpp:enumerator:`LV_EVENT_SCREEN_UNLOAD_START`: Sent when a screen starts to be unloaded on this display
|
||||||
|
- :cpp:enumerator:`LV_EVENT_SCREEN_LOAD_START`: Sent when a screen starts to be loaded on this display
|
||||||
|
- :cpp:enumerator:`LV_EVENT_SCREEN_LOADED`: Sent when a screen finishes being loaded on this display
|
||||||
|
- :cpp:enumerator:`LV_EVENT_SCREEN_UNLOADED`: Sent when a screen finishes being unloaded on this display
|
||||||
|
|||||||
+103
-16
@@ -32,13 +32,25 @@
|
|||||||
/**********************
|
/**********************
|
||||||
* TYPEDEFS
|
* TYPEDEFS
|
||||||
**********************/
|
**********************/
|
||||||
|
typedef enum {
|
||||||
|
LV_LOAD_SCREEN_RESULT_OK,
|
||||||
|
LV_LOAD_SCREEN_RESULT_OLD_SCREEN_DELETED,
|
||||||
|
LV_LOAD_SCREEN_RESULT_NEW_SCREEN_DELETED,
|
||||||
|
LV_LOAD_SCREEN_RESULT_BOTH_SCREENS_DELETED,
|
||||||
|
LV_LOAD_SCREEN_RESULT_DISPLAY_DELETED,
|
||||||
|
} lv_load_screen_result_t;
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* STATIC PROTOTYPES
|
* STATIC PROTOTYPES
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
|
static bool old_screen_deleted(lv_load_screen_result_t res);
|
||||||
|
static bool new_screen_deleted(lv_load_screen_result_t res);
|
||||||
|
|
||||||
static lv_obj_tree_walk_res_t invalidate_layout_cb(lv_obj_t * obj, void * user_data);
|
static lv_obj_tree_walk_res_t invalidate_layout_cb(lv_obj_t * obj, void * user_data);
|
||||||
static void update_resolution(lv_display_t * disp);
|
static void update_resolution(lv_display_t * disp);
|
||||||
static bool load_new_screen(lv_obj_t * scr);
|
static void screen_event_delete_cb(lv_event_t * e);
|
||||||
|
static lv_load_screen_result_t load_new_screen(lv_obj_t * scr);
|
||||||
static void scr_load_anim_start(lv_anim_t * a);
|
static void scr_load_anim_start(lv_anim_t * a);
|
||||||
static void opa_scale_anim(void * obj, int32_t v);
|
static void opa_scale_anim(void * obj, int32_t v);
|
||||||
static void set_x_anim(void * obj, int32_t v);
|
static void set_x_anim(void * obj, int32_t v);
|
||||||
@@ -772,10 +784,16 @@ void lv_screen_load_anim(lv_obj_t * new_scr, lv_screen_load_anim_t anim_type, ui
|
|||||||
|
|
||||||
d->prev_scr = d->act_scr;
|
d->prev_scr = d->act_scr;
|
||||||
act_scr = d->scr_to_load; /*Active screen changed.*/
|
act_scr = d->scr_to_load; /*Active screen changed.*/
|
||||||
|
lv_load_screen_result_t res = load_new_screen(d->scr_to_load);
|
||||||
if(load_new_screen(d->scr_to_load)) {
|
if(res == LV_LOAD_SCREEN_RESULT_DISPLAY_DELETED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(old_screen_deleted(res)) {
|
||||||
d->prev_scr = NULL;
|
d->prev_scr = NULL;
|
||||||
}
|
}
|
||||||
|
if(new_screen_deleted(res)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
d->scr_to_load = new_scr;
|
d->scr_to_load = new_scr;
|
||||||
@@ -800,8 +818,14 @@ void lv_screen_load_anim(lv_obj_t * new_scr, lv_screen_load_anim_t anim_type, ui
|
|||||||
|
|
||||||
/*Shortcut for immediate load*/
|
/*Shortcut for immediate load*/
|
||||||
if(time == 0 && delay == 0) {
|
if(time == 0 && delay == 0) {
|
||||||
bool old_screen_deleted = load_new_screen(new_scr);
|
lv_load_screen_result_t res = load_new_screen(new_scr);
|
||||||
if(!old_screen_deleted && auto_del && act_scr) {
|
if(res == LV_LOAD_SCREEN_RESULT_DISPLAY_DELETED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(new_screen_deleted(res)) {
|
||||||
|
d->act_scr = NULL;
|
||||||
|
}
|
||||||
|
if(!old_screen_deleted(res) && auto_del && act_scr) {
|
||||||
lv_obj_delete(act_scr);
|
lv_obj_delete(act_scr);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -1327,6 +1351,15 @@ void lv_display_set_external_data(lv_display_t * disp, void * data, void (* free
|
|||||||
* STATIC FUNCTIONS
|
* STATIC FUNCTIONS
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
|
static bool old_screen_deleted(lv_load_screen_result_t res)
|
||||||
|
{
|
||||||
|
return res == LV_LOAD_SCREEN_RESULT_BOTH_SCREENS_DELETED || res == LV_LOAD_SCREEN_RESULT_OLD_SCREEN_DELETED;
|
||||||
|
}
|
||||||
|
static bool new_screen_deleted(lv_load_screen_result_t res)
|
||||||
|
{
|
||||||
|
return res == LV_LOAD_SCREEN_RESULT_BOTH_SCREENS_DELETED || res == LV_LOAD_SCREEN_RESULT_NEW_SCREEN_DELETED;
|
||||||
|
}
|
||||||
|
|
||||||
static void update_resolution(lv_display_t * disp)
|
static void update_resolution(lv_display_t * disp)
|
||||||
{
|
{
|
||||||
int32_t hor_res = lv_display_get_horizontal_resolution(disp);
|
int32_t hor_res = lv_display_get_horizontal_resolution(disp);
|
||||||
@@ -1370,8 +1403,29 @@ static lv_obj_tree_walk_res_t invalidate_layout_cb(lv_obj_t * obj, void * user_d
|
|||||||
return LV_OBJ_TREE_WALK_NEXT;
|
return LV_OBJ_TREE_WALK_NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns true if the old screen was deleted while loading the new screen*/
|
static void screen_event_delete_cb(lv_event_t * e)
|
||||||
static bool load_new_screen(lv_obj_t * scr)
|
{
|
||||||
|
lv_obj_t ** screen_var = lv_event_get_user_data(e);
|
||||||
|
*screen_var = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a new screen and report the result.
|
||||||
|
*
|
||||||
|
* @param scr the screen object to load; must not be NULL
|
||||||
|
* @return a value of ::lv_load_screen_result_t indicating the outcome:
|
||||||
|
* - LV_LOAD_SCREEN_RESULT_OK: the new screen was loaded successfully;
|
||||||
|
* both the old and new screens remain valid.
|
||||||
|
* - LV_LOAD_SCREEN_RESULT_OLD_SCREEN_DELETED: the old screen was
|
||||||
|
* deleted while loading the new screen, but the new screen remains valid.
|
||||||
|
* - LV_LOAD_SCREEN_RESULT_NEW_SCREEN_DELETED: the new screen was
|
||||||
|
* deleted during loading/unloading events; the old screen remains valid.
|
||||||
|
* - LV_LOAD_SCREEN_RESULT_BOTH_SCREENS_DELETED: both the old and new
|
||||||
|
* screens were deleted during the operation.
|
||||||
|
* - LV_LOAD_SCREEN_RESULT_DISPLAY_DELETED: the display was deleted
|
||||||
|
* while processing screen load/unload events.
|
||||||
|
*/
|
||||||
|
static lv_load_screen_result_t load_new_screen(lv_obj_t * scr)
|
||||||
{
|
{
|
||||||
/*scr must not be NULL, but d->act_scr might be*/
|
/*scr must not be NULL, but d->act_scr might be*/
|
||||||
LV_ASSERT_NULL(scr);
|
LV_ASSERT_NULL(scr);
|
||||||
@@ -1381,27 +1435,60 @@ static bool load_new_screen(lv_obj_t * scr)
|
|||||||
LV_ASSERT_NULL(d);
|
LV_ASSERT_NULL(d);
|
||||||
|
|
||||||
lv_obj_t * old_scr = d->act_scr;
|
lv_obj_t * old_scr = d->act_scr;
|
||||||
bool old_screen_deleted = false;
|
/* Attach an event delete cb to the screen so we know if the screen is deleted during an event*/
|
||||||
if(old_scr) {
|
if(old_scr) {
|
||||||
if(lv_obj_send_event(old_scr, LV_EVENT_SCREEN_UNLOAD_START, NULL) == LV_RESULT_INVALID) {
|
lv_obj_add_event_cb(old_scr, screen_event_delete_cb, LV_EVENT_DELETE, &old_scr);
|
||||||
old_screen_deleted = true;
|
}
|
||||||
|
lv_obj_add_event_cb(scr, screen_event_delete_cb, LV_EVENT_DELETE, &scr);
|
||||||
|
|
||||||
|
if(old_scr) {
|
||||||
|
if(lv_display_send_event(d, LV_EVENT_SCREEN_UNLOAD_START, old_scr) == LV_RESULT_INVALID) {
|
||||||
|
return LV_LOAD_SCREEN_RESULT_DISPLAY_DELETED;
|
||||||
|
}
|
||||||
|
if(old_scr && lv_obj_send_event(old_scr, LV_EVENT_SCREEN_UNLOAD_START, NULL) == LV_RESULT_INVALID) {
|
||||||
old_scr = NULL;
|
old_scr = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lv_obj_send_event(scr, LV_EVENT_SCREEN_LOAD_START, NULL);
|
|
||||||
|
if(lv_display_send_event(d, LV_EVENT_SCREEN_LOAD_START, scr) == LV_RESULT_INVALID) {
|
||||||
|
return LV_LOAD_SCREEN_RESULT_DISPLAY_DELETED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(scr && lv_obj_send_event(scr, LV_EVENT_SCREEN_LOAD_START, NULL) == LV_RESULT_INVALID) {
|
||||||
|
scr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
d->act_scr = scr;
|
d->act_scr = scr;
|
||||||
d->scr_to_load = NULL;
|
d->scr_to_load = NULL;
|
||||||
|
|
||||||
lv_obj_send_event(scr, LV_EVENT_SCREEN_LOADED, NULL);
|
if(scr && lv_display_send_event(d, LV_EVENT_SCREEN_LOADED, scr) == LV_RESULT_INVALID) {
|
||||||
|
return LV_LOAD_SCREEN_RESULT_DISPLAY_DELETED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(scr && lv_obj_send_event(scr, LV_EVENT_SCREEN_LOADED, NULL) == LV_RESULT_INVALID) {
|
||||||
|
d->act_scr = NULL;
|
||||||
|
scr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if(old_scr) {
|
if(old_scr) {
|
||||||
if(lv_obj_send_event(old_scr, LV_EVENT_SCREEN_UNLOADED, NULL) == LV_RESULT_INVALID) {
|
if(lv_display_send_event(d, LV_EVENT_SCREEN_UNLOADED, old_scr) == LV_RESULT_INVALID) {
|
||||||
old_screen_deleted = true;
|
return LV_LOAD_SCREEN_RESULT_DISPLAY_DELETED;
|
||||||
|
}
|
||||||
|
if(old_scr && lv_obj_send_event(old_scr, LV_EVENT_SCREEN_UNLOADED, NULL) == LV_RESULT_INVALID) {
|
||||||
|
old_scr = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_obj_invalidate(scr);
|
if(scr) {
|
||||||
return old_screen_deleted;
|
lv_obj_invalidate(scr);
|
||||||
|
lv_obj_remove_event_cb(scr, screen_event_delete_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!old_scr) {
|
||||||
|
return scr ? LV_LOAD_SCREEN_RESULT_OLD_SCREEN_DELETED : LV_LOAD_SCREEN_RESULT_BOTH_SCREENS_DELETED;
|
||||||
|
}
|
||||||
|
lv_obj_remove_event_cb(old_scr, screen_event_delete_cb);
|
||||||
|
return scr ? LV_LOAD_SCREEN_RESULT_OK : LV_LOAD_SCREEN_RESULT_NEW_SCREEN_DELETED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scr_load_anim_start(lv_anim_t * a)
|
static void scr_load_anim_start(lv_anim_t * a)
|
||||||
|
|||||||
@@ -132,9 +132,361 @@ void test_screen_load_with_delete_event(void)
|
|||||||
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_4), true);
|
TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_4), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t display_screen_load_start = 0;
|
||||||
|
static size_t display_screen_loaded = 0;
|
||||||
|
static size_t display_screen_unload_start = 0;
|
||||||
|
static size_t display_screen_unloaded = 0;
|
||||||
|
static void count_display_screen_load_events_cb(lv_event_t * e)
|
||||||
|
{
|
||||||
|
lv_obj_t * screen = lv_event_get_param(e);
|
||||||
|
TEST_ASSERT_NOT_NULL(screen);
|
||||||
|
|
||||||
|
lv_display_t * screen_display = lv_obj_get_display(screen);
|
||||||
|
TEST_ASSERT_NOT_NULL(screen_display);
|
||||||
|
TEST_ASSERT_EQUAL(screen_display, lv_event_get_target(e));
|
||||||
|
|
||||||
|
switch(lv_event_get_code(e)) {
|
||||||
|
case LV_EVENT_SCREEN_UNLOADED:
|
||||||
|
display_screen_unloaded++;
|
||||||
|
break;
|
||||||
|
case LV_EVENT_SCREEN_UNLOAD_START:
|
||||||
|
display_screen_unload_start++;
|
||||||
|
break;
|
||||||
|
case LV_EVENT_SCREEN_LOADED:
|
||||||
|
display_screen_loaded++;
|
||||||
|
break;
|
||||||
|
case LV_EVENT_SCREEN_LOAD_START:
|
||||||
|
display_screen_load_start++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_display_receives_screen_load_events(void)
|
||||||
|
{
|
||||||
|
display_screen_load_start = 0;
|
||||||
|
display_screen_loaded = 0;
|
||||||
|
display_screen_unload_start = 0;
|
||||||
|
display_screen_unloaded = 0;
|
||||||
|
|
||||||
|
lv_display_t * display = lv_display_create(100, 100);
|
||||||
|
lv_display_set_default(display);
|
||||||
|
|
||||||
|
lv_obj_t * screen1 = lv_obj_create(NULL);
|
||||||
|
|
||||||
|
lv_display_add_event_cb(display, count_display_screen_load_events_cb, LV_EVENT_SCREEN_UNLOAD_START, NULL);
|
||||||
|
lv_display_add_event_cb(display, count_display_screen_load_events_cb, LV_EVENT_SCREEN_UNLOADED, NULL);
|
||||||
|
lv_display_add_event_cb(display, count_display_screen_load_events_cb, LV_EVENT_SCREEN_LOAD_START, NULL);
|
||||||
|
lv_display_add_event_cb(display, count_display_screen_load_events_cb, LV_EVENT_SCREEN_LOADED, NULL);
|
||||||
|
|
||||||
|
lv_screen_load(screen1);
|
||||||
|
TEST_ASSERT_EQUAL(1, display_screen_unloaded);
|
||||||
|
TEST_ASSERT_EQUAL(1, display_screen_unload_start);
|
||||||
|
TEST_ASSERT_EQUAL(1, display_screen_loaded);
|
||||||
|
TEST_ASSERT_EQUAL(1, display_screen_load_start);
|
||||||
|
|
||||||
|
/* Loading the same screen doesn't do anything*/
|
||||||
|
lv_screen_load(screen1);
|
||||||
|
TEST_ASSERT_EQUAL(1, display_screen_unloaded);
|
||||||
|
TEST_ASSERT_EQUAL(1, display_screen_unload_start);
|
||||||
|
TEST_ASSERT_EQUAL(1, display_screen_loaded);
|
||||||
|
TEST_ASSERT_EQUAL(1, display_screen_load_start);
|
||||||
|
|
||||||
|
lv_display_delete(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t screen_event_count = 0;
|
||||||
|
static void screen_event_cb(lv_event_t * e)
|
||||||
|
{
|
||||||
|
LV_UNUSED(e);
|
||||||
|
screen_event_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t display_event_count = 0;
|
||||||
|
/* This event handler deletes the display during screen load events*/
|
||||||
|
static void display_event_delete_cb(lv_event_t * e)
|
||||||
|
{
|
||||||
|
lv_obj_t * screen = lv_event_get_param(e);
|
||||||
|
TEST_ASSERT_NOT_NULL(screen);
|
||||||
|
|
||||||
|
lv_display_t * screen_display = lv_obj_get_display(screen);
|
||||||
|
TEST_ASSERT_NOT_NULL(screen_display);
|
||||||
|
lv_display_t * event_display = lv_event_get_target(e);
|
||||||
|
TEST_ASSERT_NOT_NULL(event_display);
|
||||||
|
|
||||||
|
/* Screen display and event display should match*/
|
||||||
|
TEST_ASSERT_EQUAL(screen_display, event_display);
|
||||||
|
lv_display_delete(event_display);
|
||||||
|
display_event_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void test_display_delete_when_screen_is_loaded(void)
|
||||||
|
{
|
||||||
|
/* Check that LVGL correctly handles deleting the display during screen load events*/
|
||||||
|
{
|
||||||
|
lv_display_t * display = lv_display_create(100, 100);
|
||||||
|
lv_display_set_default(display);
|
||||||
|
lv_obj_t * screen = lv_obj_create(NULL);
|
||||||
|
lv_display_add_event_cb(display, display_event_delete_cb, LV_EVENT_SCREEN_UNLOAD_START, NULL);
|
||||||
|
|
||||||
|
lv_obj_add_event_cb(lv_screen_active(), screen_event_cb, LV_EVENT_SCREEN_UNLOAD_START, NULL);
|
||||||
|
lv_obj_add_event_cb(lv_screen_active(), screen_event_cb, LV_EVENT_SCREEN_UNLOADED, NULL);
|
||||||
|
|
||||||
|
lv_obj_add_event_cb(screen, screen_event_cb, LV_EVENT_SCREEN_LOAD_START, NULL);
|
||||||
|
lv_obj_add_event_cb(screen, screen_event_cb, LV_EVENT_SCREEN_LOADED, NULL);
|
||||||
|
lv_screen_load(screen);
|
||||||
|
|
||||||
|
/* The display screen event was called only once*/
|
||||||
|
TEST_ASSERT_EQUAL(display_event_count, 1);
|
||||||
|
/* No unload event for previous screen as the display was deleted
|
||||||
|
* No load event for new screen as the display was deleted */
|
||||||
|
TEST_ASSERT_EQUAL(screen_event_count, 0);
|
||||||
|
|
||||||
|
display_event_count = screen_event_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
lv_display_t * display = lv_display_create(100, 100);
|
||||||
|
lv_display_set_default(display);
|
||||||
|
lv_obj_t * screen = lv_obj_create(NULL);
|
||||||
|
lv_display_add_event_cb(display, display_event_delete_cb, LV_EVENT_SCREEN_LOAD_START, NULL);
|
||||||
|
lv_obj_add_event_cb(lv_screen_active(), screen_event_cb, LV_EVENT_SCREEN_UNLOAD_START, NULL);
|
||||||
|
lv_obj_add_event_cb(lv_screen_active(), screen_event_cb, LV_EVENT_SCREEN_UNLOADED, NULL);
|
||||||
|
|
||||||
|
lv_obj_add_event_cb(screen, screen_event_cb, LV_EVENT_SCREEN_LOAD_START, NULL);
|
||||||
|
lv_obj_add_event_cb(screen, screen_event_cb, LV_EVENT_SCREEN_LOADED, NULL);
|
||||||
|
lv_screen_load(screen);
|
||||||
|
|
||||||
|
/* The display screen event was called only once*/
|
||||||
|
TEST_ASSERT_EQUAL(display_event_count, 1);
|
||||||
|
/* We should've gotten an unload start event from previous screen before the display got deleted
|
||||||
|
* No load event for new screen as the display was deleted */
|
||||||
|
TEST_ASSERT_EQUAL(screen_event_count, 1);
|
||||||
|
|
||||||
|
display_event_count = screen_event_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
lv_display_t * display = lv_display_create(100, 100);
|
||||||
|
lv_display_set_default(display);
|
||||||
|
lv_obj_t * screen = lv_obj_create(NULL);
|
||||||
|
lv_display_add_event_cb(display, display_event_delete_cb, LV_EVENT_SCREEN_LOADED, NULL);
|
||||||
|
|
||||||
|
lv_obj_add_event_cb(lv_screen_active(), screen_event_cb, LV_EVENT_SCREEN_UNLOAD_START, NULL);
|
||||||
|
lv_obj_add_event_cb(lv_screen_active(), screen_event_cb, LV_EVENT_SCREEN_UNLOADED, NULL);
|
||||||
|
lv_obj_add_event_cb(screen, screen_event_cb, LV_EVENT_SCREEN_LOAD_START, NULL);
|
||||||
|
lv_obj_add_event_cb(screen, screen_event_cb, LV_EVENT_SCREEN_LOADED, NULL);
|
||||||
|
lv_screen_load(screen);
|
||||||
|
|
||||||
|
/* The display screen event was called only once*/
|
||||||
|
TEST_ASSERT_EQUAL(display_event_count, 1);
|
||||||
|
/* We should've gotten an unload start event from previous screen before the display got deleted
|
||||||
|
* We should've gotten an load_start event for new screen before the display was deleted */
|
||||||
|
TEST_ASSERT_EQUAL(screen_event_count, 2);
|
||||||
|
|
||||||
|
display_event_count = screen_event_count = 0;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
lv_display_t * display = lv_display_create(100, 100);
|
||||||
|
lv_display_set_default(display);
|
||||||
|
lv_obj_t * screen = lv_obj_create(NULL);
|
||||||
|
lv_display_add_event_cb(display, display_event_delete_cb, LV_EVENT_SCREEN_UNLOADED, NULL);
|
||||||
|
lv_obj_add_event_cb(lv_screen_active(), screen_event_cb, LV_EVENT_SCREEN_UNLOAD_START, NULL);
|
||||||
|
lv_obj_add_event_cb(lv_screen_active(), screen_event_cb, LV_EVENT_SCREEN_UNLOADED, NULL);
|
||||||
|
|
||||||
|
lv_obj_add_event_cb(screen, screen_event_cb, LV_EVENT_SCREEN_LOAD_START, NULL);
|
||||||
|
lv_obj_add_event_cb(screen, screen_event_cb, LV_EVENT_SCREEN_LOADED, NULL);
|
||||||
|
lv_screen_load(screen);
|
||||||
|
|
||||||
|
/* The display screen event was called only once*/
|
||||||
|
TEST_ASSERT_EQUAL(display_event_count, 1);
|
||||||
|
/* We should've gotten an unload start event from previous screen before the display got deleted
|
||||||
|
* We should've gotten an load_start and loaded events for new screen before the display was deleted */
|
||||||
|
TEST_ASSERT_EQUAL(screen_event_count, 3);
|
||||||
|
display_event_count = screen_event_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t screen_delete_event_count = 0;
|
||||||
|
/* This event handler deletes the target object during screen load events*/
|
||||||
|
static void screen_delete_event_cb(lv_event_t * e)
|
||||||
|
{
|
||||||
|
lv_obj_delete(lv_event_get_target_obj(e));
|
||||||
|
screen_delete_event_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_new_screen_delete_when_screen_is_loaded(void)
|
||||||
|
{
|
||||||
|
/* Check that LVGL correctly handles when the new screen is deleted during screen load events*/
|
||||||
|
{
|
||||||
|
lv_obj_t * screen = lv_obj_create(NULL);
|
||||||
|
lv_obj_add_event_cb(screen, screen_delete_event_cb, LV_EVENT_SCREEN_LOAD_START, NULL);
|
||||||
|
lv_screen_load(screen);
|
||||||
|
|
||||||
|
/* New screen deleted during screen load*/
|
||||||
|
TEST_ASSERT_EQUAL(screen_delete_event_count, 1);
|
||||||
|
TEST_ASSERT_NULL(lv_display_get_screen_active(lv_display_get_default()));
|
||||||
|
screen_delete_event_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
lv_obj_t * screen = lv_obj_create(NULL);
|
||||||
|
lv_obj_add_event_cb(screen, screen_delete_event_cb, LV_EVENT_SCREEN_LOADED, NULL);
|
||||||
|
lv_screen_load(screen);
|
||||||
|
|
||||||
|
/* New screen deleted during screen load*/
|
||||||
|
TEST_ASSERT_EQUAL(screen_delete_event_count, 1);
|
||||||
|
TEST_ASSERT_NULL(lv_display_get_screen_active(lv_display_get_default()));
|
||||||
|
screen_delete_event_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void test_old_screen_delete_when_screen_is_loaded(void)
|
||||||
|
{
|
||||||
|
/* Check that LVGL correctly handles when the old screen is deleted during screen load events*/
|
||||||
|
lv_obj_t * default_screen = lv_obj_create(NULL);
|
||||||
|
lv_screen_load(default_screen);
|
||||||
|
{
|
||||||
|
lv_obj_t * screen = lv_obj_create(NULL);
|
||||||
|
lv_obj_add_event_cb(lv_screen_active(), screen_delete_event_cb, LV_EVENT_SCREEN_UNLOAD_START, NULL);
|
||||||
|
lv_screen_load(screen);
|
||||||
|
|
||||||
|
/* Old screen deleted during screen load*/
|
||||||
|
TEST_ASSERT_EQUAL(screen_delete_event_count, 1);
|
||||||
|
TEST_ASSERT_EQUAL(screen, lv_display_get_screen_active(lv_display_get_default()));
|
||||||
|
screen_delete_event_count = 0;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
lv_obj_t * screen = lv_obj_create(NULL);
|
||||||
|
lv_obj_add_event_cb(lv_screen_active(), screen_delete_event_cb, LV_EVENT_SCREEN_UNLOADED, NULL);
|
||||||
|
lv_screen_load(screen);
|
||||||
|
|
||||||
|
/* Old screen deleted during screen load*/
|
||||||
|
TEST_ASSERT_EQUAL(screen_delete_event_count, 1);
|
||||||
|
TEST_ASSERT_EQUAL(screen, lv_display_get_screen_active(lv_display_get_default()));
|
||||||
|
screen_delete_event_count = 0;
|
||||||
|
}
|
||||||
|
lv_obj_t * active_screen = lv_screen_active();
|
||||||
|
TEST_ASSERT_NOT_NULL(active_screen);
|
||||||
|
lv_obj_delete(active_screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t display_screen_delete_screen_event_count = 0;
|
||||||
|
/* Deletes the display passed as a param on a display screen load event*/
|
||||||
|
static void display_delete_screen_event_cb(lv_event_t * e)
|
||||||
|
{
|
||||||
|
lv_obj_t * screen = lv_event_get_param(e);
|
||||||
|
TEST_ASSERT_NOT_NULL(screen);
|
||||||
|
lv_obj_delete(screen);
|
||||||
|
display_screen_delete_screen_event_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_screen_is_deleted_when_loaded_in_display_event(void)
|
||||||
|
{
|
||||||
|
/* Check that LVGL correctly handles deleting the screens during display screen load events*/
|
||||||
|
{
|
||||||
|
lv_display_t * display = lv_display_create(100, 100);
|
||||||
|
lv_display_set_default(display);
|
||||||
|
lv_obj_t * screen = lv_obj_create(NULL);
|
||||||
|
lv_display_add_event_cb(display, display_delete_screen_event_cb, LV_EVENT_SCREEN_UNLOAD_START, NULL);
|
||||||
|
|
||||||
|
lv_obj_add_event_cb(lv_screen_active(), screen_event_cb, LV_EVENT_SCREEN_UNLOAD_START, NULL);
|
||||||
|
lv_obj_add_event_cb(lv_screen_active(), screen_event_cb, LV_EVENT_SCREEN_UNLOADED, NULL);
|
||||||
|
|
||||||
|
lv_obj_add_event_cb(screen, screen_event_cb, LV_EVENT_SCREEN_LOAD_START, NULL);
|
||||||
|
lv_obj_add_event_cb(screen, screen_event_cb, LV_EVENT_SCREEN_LOADED, NULL);
|
||||||
|
lv_screen_load(screen);
|
||||||
|
|
||||||
|
/* The display screen event was called only once*/
|
||||||
|
TEST_ASSERT_EQUAL(display_screen_delete_screen_event_count, 1);
|
||||||
|
/* No unload events are sent to the previous screen as the old screen was deleted during the display event
|
||||||
|
* Both load events for new screen are sent */
|
||||||
|
TEST_ASSERT_EQUAL(screen_event_count, 2);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(screen, lv_screen_active());
|
||||||
|
|
||||||
|
display_screen_delete_screen_event_count = screen_event_count = 0;
|
||||||
|
lv_display_delete(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
lv_display_t * display = lv_display_create(100, 100);
|
||||||
|
lv_display_set_default(display);
|
||||||
|
lv_obj_t * screen = lv_obj_create(NULL);
|
||||||
|
lv_display_add_event_cb(display, display_delete_screen_event_cb, LV_EVENT_SCREEN_LOAD_START, NULL);
|
||||||
|
lv_obj_add_event_cb(lv_screen_active(), screen_event_cb, LV_EVENT_SCREEN_UNLOAD_START, NULL);
|
||||||
|
lv_obj_add_event_cb(lv_screen_active(), screen_event_cb, LV_EVENT_SCREEN_UNLOADED, NULL);
|
||||||
|
|
||||||
|
lv_obj_add_event_cb(screen, screen_event_cb, LV_EVENT_SCREEN_LOAD_START, NULL);
|
||||||
|
lv_obj_add_event_cb(screen, screen_event_cb, LV_EVENT_SCREEN_LOADED, NULL);
|
||||||
|
lv_screen_load(screen);
|
||||||
|
|
||||||
|
/* The display screen event was called only once*/
|
||||||
|
TEST_ASSERT_EQUAL(display_screen_delete_screen_event_count, 1);
|
||||||
|
/* Both unload events are sent to the previous screen
|
||||||
|
* No load event for new screen as the screen was deleted during the display event */
|
||||||
|
TEST_ASSERT_EQUAL(screen_event_count, 2);
|
||||||
|
|
||||||
|
TEST_ASSERT_NULL(lv_screen_active());
|
||||||
|
|
||||||
|
display_screen_delete_screen_event_count = screen_event_count = 0;
|
||||||
|
lv_display_delete(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
lv_display_t * display = lv_display_create(100, 100);
|
||||||
|
lv_display_set_default(display);
|
||||||
|
lv_obj_t * screen = lv_obj_create(NULL);
|
||||||
|
lv_display_add_event_cb(display, display_delete_screen_event_cb, LV_EVENT_SCREEN_LOADED, NULL);
|
||||||
|
|
||||||
|
lv_obj_add_event_cb(lv_screen_active(), screen_event_cb, LV_EVENT_SCREEN_UNLOAD_START, NULL);
|
||||||
|
lv_obj_add_event_cb(lv_screen_active(), screen_event_cb, LV_EVENT_SCREEN_UNLOADED, NULL);
|
||||||
|
lv_obj_add_event_cb(screen, screen_event_cb, LV_EVENT_SCREEN_LOAD_START, NULL);
|
||||||
|
lv_obj_add_event_cb(screen, screen_event_cb, LV_EVENT_SCREEN_LOADED, NULL);
|
||||||
|
lv_screen_load(screen);
|
||||||
|
|
||||||
|
/* The display screen event was called only once*/
|
||||||
|
TEST_ASSERT_EQUAL(display_screen_delete_screen_event_count, 1);
|
||||||
|
/* Both unload events are sent to the previous screen
|
||||||
|
* loaded event is not sent to the new screen as the screen was deleted during the display event */
|
||||||
|
TEST_ASSERT_EQUAL(screen_event_count, 3);
|
||||||
|
|
||||||
|
TEST_ASSERT_NULL(lv_screen_active());
|
||||||
|
|
||||||
|
display_screen_delete_screen_event_count = screen_event_count = 0;
|
||||||
|
lv_display_delete(display);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
lv_display_t * display = lv_display_create(100, 100);
|
||||||
|
lv_display_set_default(display);
|
||||||
|
lv_obj_t * screen = lv_obj_create(NULL);
|
||||||
|
lv_display_add_event_cb(display, display_delete_screen_event_cb, LV_EVENT_SCREEN_UNLOADED, NULL);
|
||||||
|
lv_obj_add_event_cb(lv_screen_active(), screen_event_cb, LV_EVENT_SCREEN_UNLOAD_START, NULL);
|
||||||
|
lv_obj_add_event_cb(lv_screen_active(), screen_event_cb, LV_EVENT_SCREEN_UNLOADED, NULL);
|
||||||
|
|
||||||
|
lv_obj_add_event_cb(screen, screen_event_cb, LV_EVENT_SCREEN_LOAD_START, NULL);
|
||||||
|
lv_obj_add_event_cb(screen, screen_event_cb, LV_EVENT_SCREEN_LOADED, NULL);
|
||||||
|
lv_screen_load(screen);
|
||||||
|
|
||||||
|
/* The display screen event was called only once*/
|
||||||
|
TEST_ASSERT_EQUAL(display_screen_delete_screen_event_count, 1);
|
||||||
|
/* unloaded event is not sent to the previous screen as the screen is deleted during display event
|
||||||
|
* Both load events for new screen are sent */
|
||||||
|
TEST_ASSERT_EQUAL(screen_event_count, 3);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(screen, lv_screen_active());
|
||||||
|
|
||||||
|
display_screen_delete_screen_event_count = screen_event_count = 0;
|
||||||
|
lv_display_delete(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static void unloaded_event_cb(lv_event_t * e)
|
static void unloaded_event_cb(lv_event_t * e)
|
||||||
{
|
{
|
||||||
lv_free(lv_event_get_target_obj(e));
|
lv_obj_delete(lv_event_get_target_obj(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
static lv_obj_t * screen_create(void)
|
static lv_obj_t * screen_create(void)
|
||||||
@@ -145,7 +497,6 @@ static lv_obj_t * screen_create(void)
|
|||||||
|
|
||||||
void test_screen_mix_event_and_manual_creation(void)
|
void test_screen_mix_event_and_manual_creation(void)
|
||||||
{
|
{
|
||||||
lv_obj_delete(lv_screen_active());
|
|
||||||
size_t free_mem = lv_test_get_free_mem();
|
size_t free_mem = lv_test_get_free_mem();
|
||||||
|
|
||||||
lv_obj_t * screen = lv_obj_create(NULL);
|
lv_obj_t * screen = lv_obj_create(NULL);
|
||||||
@@ -158,7 +509,6 @@ void test_screen_mix_event_and_manual_creation(void)
|
|||||||
|
|
||||||
/* Manually loading a screen with auto delete set to `true` should not lead to a double free */
|
/* Manually loading a screen with auto delete set to `true` should not lead to a double free */
|
||||||
lv_screen_load_anim(screen, LV_SCREEN_LOAD_ANIM_NONE, 0, 0, true);
|
lv_screen_load_anim(screen, LV_SCREEN_LOAD_ANIM_NONE, 0, 0, true);
|
||||||
|
|
||||||
lv_obj_delete(lv_screen_active());
|
lv_obj_delete(lv_screen_active());
|
||||||
|
|
||||||
TEST_ASSERT_MEM_LEAK_LESS_THAN(free_mem, 32);
|
TEST_ASSERT_MEM_LEAK_LESS_THAN(free_mem, 32);
|
||||||
|
|||||||
Reference in New Issue
Block a user