From a798963ee89164ba2758c7fdb5fabea33e22a805 Mon Sep 17 00:00:00 2001 From: Lorenzo Arena Date: Wed, 31 Jul 2024 16:46:28 +0200 Subject: [PATCH] fix(display): delete previous screen instead of current (#6494) --- src/display/lv_display.c | 6 +- tests/src/test_cases/test_screen_load.c | 113 ++++++++++++++++++++++++ 2 files changed, 115 insertions(+), 4 deletions(-) diff --git a/src/display/lv_display.c b/src/display/lv_display.c index 8ff630420..3ec8cc7d1 100644 --- a/src/display/lv_display.c +++ b/src/display/lv_display.c @@ -592,10 +592,8 @@ void lv_screen_load_anim(lv_obj_t * new_scr, lv_screen_load_anim_t anim_type, ui lv_obj_set_pos(d->scr_to_load, 0, 0); lv_obj_remove_local_style_prop(d->scr_to_load, LV_STYLE_OPA, 0); - if(d->del_prev) { - lv_obj_delete(act_scr); - } - act_scr = d->act_scr; /*Active screen changed.*/ + d->prev_scr = d->act_scr; + act_scr = d->scr_to_load; /*Active screen changed.*/ scr_load_internal(d->scr_to_load); } diff --git a/tests/src/test_cases/test_screen_load.c b/tests/src/test_cases/test_screen_load.c index 3eeff53a3..19a9f71ec 100644 --- a/tests/src/test_cases/test_screen_load.c +++ b/tests/src/test_cases/test_screen_load.c @@ -18,4 +18,117 @@ void test_screen_load_no_crash(void) lv_screen_load_anim(screen_with_anim_2, LV_SCR_LOAD_ANIM_OVER_RIGHT, 1000, 500, false); } +void test_screen_load_with_delete_no_crash(void) +{ + /*Delete active screen and load new screen should not crash*/ + lv_obj_t * screen = lv_screen_active(); + lv_obj_del(screen); + screen = lv_obj_create(NULL); + lv_scr_load(screen); + + /*Consecutively loading multiple screens (while deleting one) with transition animations should not crash*/ + lv_obj_t * screen_with_anim_1 = lv_obj_create(NULL); + lv_obj_t * screen_with_anim_2 = lv_obj_create(NULL); + lv_obj_t * screen_with_anim_3 = lv_obj_create(NULL); + + lv_scr_load_anim(screen_with_anim_1, LV_SCR_LOAD_ANIM_OVER_LEFT, 0, 0, false); + lv_scr_load_anim(screen_with_anim_2, LV_SCR_LOAD_ANIM_OVER_RIGHT, 1000, 0, true); + + /*Wait to trigger the animation start callbacks*/ + lv_test_wait(100); + + lv_scr_load_anim(screen_with_anim_3, LV_SCR_LOAD_ANIM_OVER_LEFT, 200, 0, true); + + /*The active screen should be immediately replaced*/ + TEST_ASSERT_EQUAL(lv_screen_active(), screen_with_anim_2); + + lv_test_wait(400); + + /*Check for the screens status after the transition*/ + TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_1), false); + TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_2), false); + TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_3), true); +} + +void test_screen_load_with_delete_no_crash2(void) +{ + /*Delete active screen and load new screen should not crash*/ + lv_obj_t * screen = lv_screen_active(); + lv_obj_del(screen); + screen = lv_obj_create(NULL); + lv_scr_load(screen); + + /*Consecutively loading multiple screens (while deleting one) with transition animations should not crash*/ + lv_obj_t * screen_with_anim_1 = lv_obj_create(NULL); + lv_obj_t * screen_with_anim_2 = lv_obj_create(NULL); + lv_obj_t * screen_with_anim_3 = lv_obj_create(NULL); + lv_obj_t * screen_with_anim_4 = lv_obj_create(NULL); + + lv_scr_load_anim(screen_with_anim_1, LV_SCR_LOAD_ANIM_OVER_LEFT, 0, 0, false); + lv_scr_load_anim(screen_with_anim_2, LV_SCR_LOAD_ANIM_OVER_RIGHT, 1000, 0, true); + lv_scr_load_anim(screen_with_anim_3, LV_SCR_LOAD_ANIM_OVER_LEFT, 0, 0, true); + + /*Wait to trigger the animation start callbacks*/ + lv_test_wait(100); + + lv_scr_load_anim(screen_with_anim_4, LV_SCR_LOAD_ANIM_OVER_LEFT, 200, 0, true); + + /*The active screen should be immediately replaced*/ + TEST_ASSERT_EQUAL(lv_screen_active(), screen_with_anim_3); + + lv_test_wait(400); + + /*Check for the screens status after the transition*/ + TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_1), false); + TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_2), false); + TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_3), false); + TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_4), true); +} + +static bool screen_1_unloaded_called = false; + +static void screen_with_anim_1_unloaded_cb(lv_event_t * e) +{ + LV_UNUSED(e); + screen_1_unloaded_called = true; +} + +void test_screen_load_with_delete_event(void) +{ + /*Delete active screen and load new screen should not crash*/ + lv_obj_t * screen = lv_screen_active(); + lv_obj_del(screen); + screen = lv_obj_create(NULL); + lv_scr_load(screen); + + /*Consecutively loading multiple screens (while deleting one) with transition animations should not crash*/ + lv_obj_t * screen_with_anim_1 = lv_obj_create(NULL); + lv_obj_t * screen_with_anim_2 = lv_obj_create(NULL); + lv_obj_t * screen_with_anim_3 = lv_obj_create(NULL); + lv_obj_t * screen_with_anim_4 = lv_obj_create(NULL); + + lv_scr_load_anim(screen_with_anim_1, LV_SCR_LOAD_ANIM_OVER_LEFT, 0, 0, false); + lv_obj_add_event_cb(screen_with_anim_1, screen_with_anim_1_unloaded_cb, LV_EVENT_SCREEN_UNLOADED, NULL); + lv_scr_load_anim(screen_with_anim_2, LV_SCR_LOAD_ANIM_OVER_RIGHT, 1000, 0, true); + lv_scr_load_anim(screen_with_anim_3, LV_SCR_LOAD_ANIM_OVER_LEFT, 0, 0, true); + + /*Wait to trigger the animation start callbacks*/ + lv_test_wait(100); + + TEST_ASSERT_EQUAL(screen_1_unloaded_called, true); + + lv_scr_load_anim(screen_with_anim_4, LV_SCR_LOAD_ANIM_OVER_LEFT, 200, 0, true); + + /*The active screen should be immediately replaced*/ + TEST_ASSERT_EQUAL(lv_screen_active(), screen_with_anim_3); + + lv_test_wait(400); + + /*Check for the screens status after the transition*/ + TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_1), false); + TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_2), false); + TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_3), false); + TEST_ASSERT_EQUAL(lv_obj_is_valid(screen_with_anim_4), true); +} + #endif