From c43b372aff848b927e44ffbfef5b8d433ef1e002 Mon Sep 17 00:00:00 2001 From: liu weikai Date: Mon, 28 Sep 2026 17:24:19 +0800 Subject: [PATCH] Enable touch keyboard in the geocaching editor --- .../geocaching/geocaching_page_shell.cpp | 7 +++- .../ui_shared/tests/geocaching/CMakeLists.txt | 9 +++++ .../stubs/ui/assets/fonts/font_utils.h | 3 ++ .../ui_shared/tests/geocaching/test_page.cpp | 40 ++++++++++++++++++- 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/modules/ui_shared/src/ui/screens/geocaching/geocaching_page_shell.cpp b/modules/ui_shared/src/ui/screens/geocaching/geocaching_page_shell.cpp index b1d5a0cc..c390cc43 100644 --- a/modules/ui_shared/src/ui/screens/geocaching/geocaching_page_shell.cpp +++ b/modules/ui_shared/src/ui/screens/geocaching/geocaching_page_shell.cpp @@ -4,6 +4,7 @@ #include "ui/page/page_profile.h" #include "ui/screens/gps/gps_page_runtime.h" #include "ui/widgets/top_bar.h" +#include "ui_lvgl_ux_packs/common/touch_text_editor.h" #include #include #include @@ -292,6 +293,9 @@ void refreshView() auto& p = *page; const auto old_generation = p.snapshot.generation; auto* focused = p.group ? lv_group_get_focused(p.group) : nullptr; + bool focus_survives = focused != nullptr; + for (auto* object = focused; object; object = lv_obj_get_parent(object)) + if (object == p.list) focus_survives = false; std::array focused_id{}; bool focused_row = false; for (size_t i = 0; i < p.row_count; ++i) @@ -383,7 +387,7 @@ void refreshView() if (p.row_ids[i] == focused_id) restore = p.rows[i]; lv_group_focus_obj(restore); } - else if (focused && !lv_obj_has_state(focused, LV_STATE_DISABLED)) lv_group_focus_obj(focused); + else if (focus_survives && !lv_obj_has_state(focused, LV_STATE_DISABLED)) lv_group_focus_obj(focused); else lv_group_focus_obj(p.tabs[static_cast(p.section)]); } } @@ -683,6 +687,7 @@ void openEditor(const ::ui::geocaching::Item* item) lv_obj_set_height(field, i == 3 || i == 4 ? 64 : 32); lv_textarea_set_max_length(field, limits[i]); lv_textarea_set_text(field, i == 5 || i == 6 ? "1.0" : ""); + ::ui::widgets::attach_touch_text_editor(field); lv_obj_set_style_bg_color(field, lv_color_hex(styles::kSidePanelBg), 0); lv_obj_set_style_text_color(field, lv_color_hex(styles::kTextPrimary), 0); lv_obj_set_style_border_color(field, lv_color_hex(styles::kBorder), 0); diff --git a/modules/ui_shared/tests/geocaching/CMakeLists.txt b/modules/ui_shared/tests/geocaching/CMakeLists.txt index 37255ee9..3a4c29fe 100644 --- a/modules/ui_shared/tests/geocaching/CMakeLists.txt +++ b/modules/ui_shared/tests/geocaching/CMakeLists.txt @@ -10,13 +10,22 @@ target_compile_definitions(page_test_lvgl PUBLIC LV_CONF_SKIP=1 LV_USE_STDLIB_MA LV_MEM_SIZE=1048576 LV_USE_STDLIB_STRING=1 LV_USE_STDLIB_SPRINTF=1 LV_USE_SNAPSHOT=1 LV_FONT_MONTSERRAT_12=1 LV_FONT_MONTSERRAT_16=1 LV_FONT_MONTSERRAT_20=1) add_executable(geocaching_page_test test_page.cpp + "${REPO_ROOT}/modules/ui_lvgl_ux_packs/tests/touch_editor/test_support.cpp" + "${REPO_ROOT}/modules/ui_lvgl_ux_packs/src/common/touch_text_editor.cpp" + "${REPO_ROOT}/modules/ui_lvgl_ux_packs/src/common/input_layout.cpp" + "${REPO_ROOT}/modules/ui_shared/src/ui/widgets/ime/ime_widget.cpp" + "${REPO_ROOT}/modules/ui_shared/src/ui/widgets/ime/pinyin_ime.cpp" + "${REPO_ROOT}/modules/ui_shared/src/ui/widgets/ime/ime_input_mode_descriptor.cpp" "${REPO_ROOT}/modules/ui_shared/src/ui/screens/geocaching/geocaching_page_shell.cpp" "${REPO_ROOT}/modules/ui_shared/src/ui/components/two_pane_styles.cpp" "${REPO_ROOT}/modules/ui_shared/src/ui/widgets/top_bar.cpp" "${REPO_ROOT}/modules/ui_shared/src/ui/page/page_profile.cpp") target_include_directories(geocaching_page_test PRIVATE stubs + "${REPO_ROOT}/modules/ui_lvgl_ux_packs/tests/touch_editor/stubs" + "${REPO_ROOT}/modules/ui_lvgl_ux_packs/include" "${REPO_ROOT}/modules/ui_shared/include" "${REPO_ROOT}/modules/ui_presentation/include") target_compile_features(geocaching_page_test PRIVATE cxx_std_17) +target_compile_definitions(geocaching_page_test PRIVATE UI_SHARED_TOUCH_IME_ENABLED=1) target_link_libraries(geocaching_page_test PRIVATE page_test_lvgl) if(MSVC) target_compile_options(geocaching_page_test PRIVATE /utf-8) diff --git a/modules/ui_shared/tests/geocaching/stubs/ui/assets/fonts/font_utils.h b/modules/ui_shared/tests/geocaching/stubs/ui/assets/fonts/font_utils.h index d2a24ea6..35b1c32e 100644 --- a/modules/ui_shared/tests/geocaching/stubs/ui/assets/fonts/font_utils.h +++ b/modules/ui_shared/tests/geocaching/stubs/ui/assets/fonts/font_utils.h @@ -2,6 +2,9 @@ #include "lvgl.h" namespace ui::fonts { +inline const lv_font_t* ui_chrome_font() { return &lv_font_montserrat_14; } +inline const lv_font_t* localized_font(const lv_font_t* base) { return base; } +inline const lv_font_t* content_font(const char*, const lv_font_t* base) { return base; } inline void apply_content_font(lv_obj_t* object, const char*, const lv_font_t* font) { lv_obj_set_style_text_font(object, font, 0); diff --git a/modules/ui_shared/tests/geocaching/test_page.cpp b/modules/ui_shared/tests/geocaching/test_page.cpp index 38398dde..29d33a67 100644 --- a/modules/ui_shared/tests/geocaching/test_page.cpp +++ b/modules/ui_shared/tests/geocaching/test_page.cpp @@ -205,6 +205,14 @@ bool save(const std::string& path, lv_obj_t* screen) lv_draw_buf_destroy(image); return out.good(); } +lv_obj_t* findKeyboard(lv_obj_t* root) +{ + if (lv_obj_check_type(root, &lv_buttonmatrix_class)) return root; + for (uint32_t i = 0; i < lv_obj_get_child_count(root); ++i) + if (auto* found = findKeyboard(lv_obj_get_child(root, i))) return found; + return nullptr; +} + int main(int argc, char** argv) { if (argc != 4) return 1; @@ -216,7 +224,9 @@ int main(int argc, char** argv) lv_display_set_buffers(display, pixels.data(), nullptr, pixels.size(), LV_DISPLAY_RENDER_MODE_PARTIAL); lv_display_set_flush_cb(display, [](lv_display_t* display, const lv_area_t*, uint8_t*) { lv_display_flush_ready(display); }); - const auto profile = width == 480 ? ui::page_profile::make_pager_profile() : ui::page_profile::make_tdeck_profile(); + auto profile = width == 480 ? ui::page_profile::make_pager_profile() : ui::page_profile::make_tdeck_profile(); + profile.compact_touch_keyboard = width == 320; + if (profile.compact_touch_keyboard) profile.ime_keyboard_height = 108; ui::page_profile::set_active_profile(&profile); auto* screen = lv_screen_active(); auto* old_group = lv_group_create(); @@ -329,6 +339,34 @@ int main(int argc, char** argv) lv_obj_send_event(lv_obj_get_child(footer, 0), LV_EVENT_CLICKED, nullptr); list = lv_obj_get_child(root, 3); auto* name_field = lv_obj_get_child(list, 1); + for (unsigned field = 0; field < 7; ++field) + { + auto* input = lv_obj_get_child(list, 2 * field + 1); + const auto layers = lv_obj_get_child_count(lv_layer_top()); + lv_obj_send_event(input, LV_EVENT_CLICKED, nullptr); + if (profile.compact_touch_keyboard) + { + if (lv_obj_get_child_count(lv_layer_top()) != layers + 1) return 40; + auto* modal = lv_obj_get_child(lv_layer_top(), -1); + auto* draft = lv_obj_get_child(modal, 1); + if (!lv_obj_check_type(draft, &lv_textarea_class)) return 41; + auto* keyboard = findKeyboard(modal); + if (!keyboard) return 45; + if (field == 0) + { + lv_buttonmatrix_set_selected_button(keyboard, 0); + lv_obj_send_event(keyboard, LV_EVENT_VALUE_CHANGED, nullptr); + if (std::strcmp(lv_textarea_get_text(draft), "q")) return 46; + } + lv_textarea_set_text(draft, field == 0 ? "Touch input" : "1.5"); + if (field == 0 && !save(std::string(argv[3]) + "-keyboard.ppm", modal)) return 42; + auto* actions = lv_obj_get_child(modal, 0); + lv_obj_send_event(lv_obj_get_child(actions, 1), LV_EVENT_CLICKED, nullptr); + if (std::strcmp(lv_textarea_get_text(input), field == 0 ? "Touch input" : "1.5") || + lv_obj_get_child_count(lv_layer_top()) != layers) return 43; + } + else if (lv_obj_get_child_count(lv_layer_top()) != layers) return 44; + } lv_textarea_set_text(name_field, "林间宝藏"); lv_textarea_set_text(lv_obj_get_child(list, 3), "30.5"); lv_textarea_set_text(lv_obj_get_child(list, 5), "120.5");