mirror of
https://github.com/torlando-tech/pyxis.git
synced 2026-08-27 21:19:56 +00:00
fix(ui): rebuild launcher focus atomically
This commit is contained in:
@@ -61,13 +61,35 @@ HomeScreen::HomeScreen() {
|
||||
}
|
||||
HomeScreen::~HomeScreen() { if (_screen) lv_obj_del(_screen); }
|
||||
void HomeScreen::show() {
|
||||
lv_obj_clear_flag(_screen, LV_OBJ_FLAG_HIDDEN); lv_obj_move_foreground(_screen);
|
||||
lv_obj_clear_flag(_screen, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_move_foreground(_screen);
|
||||
auto* group = LVGL::LVGLInit::get_default_group();
|
||||
if (group) { for (auto* button : _buttons) lv_group_add_obj(group, button); lv_group_focus_obj(_buttons[0]); }
|
||||
if (group) {
|
||||
// Rebuild the ordered launcher group without letting the first add emit
|
||||
// an automatic focus event. Messages becomes the sole final owner.
|
||||
lv_group_focus_freeze(group, true);
|
||||
for (auto* button : _buttons) lv_group_add_obj(group, button);
|
||||
lv_group_focus_freeze(group, false);
|
||||
lv_group_focus_obj(_buttons[0]);
|
||||
}
|
||||
}
|
||||
void HomeScreen::hide() {
|
||||
auto* group = LVGL::LVGLInit::get_default_group();
|
||||
if (group) for (auto* button : _buttons) lv_group_remove_obj(button);
|
||||
if (group) {
|
||||
// Removing the current owner makes LVGL synchronously focus another
|
||||
// member. Detach every other launcher tile first and the owner last so
|
||||
// no later tile becomes a transient focus owner during navigation.
|
||||
lv_obj_t* focused = lv_group_get_focused(group);
|
||||
bool focused_is_launcher = false;
|
||||
for (auto* button : _buttons) {
|
||||
if (button == focused) {
|
||||
focused_is_launcher = true;
|
||||
} else {
|
||||
lv_group_remove_obj(button);
|
||||
}
|
||||
}
|
||||
if (focused_is_launcher) lv_group_remove_obj(focused);
|
||||
}
|
||||
lv_obj_add_flag(_screen, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
void HomeScreen::clicked(lv_event_t* event) {
|
||||
|
||||
@@ -154,6 +154,37 @@ def test_directory_rebuild_has_one_final_focus_owner():
|
||||
assert rebuild.index("lv_group_focus_freeze(group,false);") < rebuild.rindex("lv_group_focus_obj")
|
||||
|
||||
|
||||
def test_launcher_transition_has_one_final_focus_owner():
|
||||
"""Leaving and restoring Home must not transiently focus later tiles."""
|
||||
home = (INCLUDE / "HomeScreen.cpp").read_text()
|
||||
show_start = home.index("void HomeScreen::show()")
|
||||
hide_start = home.index("void HomeScreen::hide()", show_start)
|
||||
show = home[show_start:hide_start]
|
||||
hide_end = home.index("void HomeScreen::clicked", hide_start)
|
||||
hide = home[hide_start:hide_end]
|
||||
|
||||
# Adding the first tile to an empty LVGL group auto-focuses it. Freeze the
|
||||
# complete ordered rebuild and make Messages the sole explicit owner.
|
||||
assert "lv_group_focus_freeze(group, true);" in show
|
||||
assert "lv_group_focus_freeze(group, false);" in show
|
||||
assert show.index("lv_group_focus_freeze(group, true);") < show.index("lv_group_add_obj")
|
||||
assert show.index("lv_group_focus_freeze(group, false);") < show.index("lv_group_focus_obj(_buttons[0])")
|
||||
|
||||
# Hide must detach every non-owner before the current owner; removing an
|
||||
# owner early makes LVGL focus each surviving launcher tile synchronously.
|
||||
assert "lv_obj_t* focused = lv_group_get_focused(group);" in hide
|
||||
non_owner_remove = re.search(
|
||||
r"if \(button == focused\)\s*\{.*?\}\s*else\s*\{\s*lv_group_remove_obj\(button\);",
|
||||
hide,
|
||||
re.S,
|
||||
)
|
||||
assert non_owner_remove
|
||||
assert "if (focused_is_launcher) lv_group_remove_obj(focused);" in hide
|
||||
assert non_owner_remove.start() < hide.index(
|
||||
"if (focused_is_launcher) lv_group_remove_obj(focused);"
|
||||
)
|
||||
|
||||
|
||||
def test_bounded_nomadnet_fonts_match_display_allowlist():
|
||||
expected = set(range(0x20, 0x7F)) | set(range(0xA0, 0x180))
|
||||
expected |= set(range(0x2190, 0x219A))
|
||||
|
||||
Reference in New Issue
Block a user