From 7f4d3fd0b663fecfbdcdffa8d95650bdce9beaee Mon Sep 17 00:00:00 2001 From: "Michael A. Cojocari" Date: Wed, 7 Oct 2026 16:21:57 -0400 Subject: [PATCH] M9: action menus focus first row (X last); lift message-menu X clear of buttons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ⋯ / thread action list creates its close X after the rows on the M9, so keypad focus opens on the first action and reaches the X last. The message action menu's X moves up into the card padding so the first button row no longer clips its focus cursor. Other boards unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 8fdb23ce5f5dbf58514304ab3be7a5dd04c4cdd8) --- src/ui-touch/UITask.cpp | 47 ++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/src/ui-touch/UITask.cpp b/src/ui-touch/UITask.cpp index 3bae362..49e7f7a 100644 --- a/src/ui-touch/UITask.cpp +++ b/src/ui-touch/UITask.cpp @@ -8557,6 +8557,20 @@ static void actListCloseCb(lv_event_t* e) { actListClose(); } +static lv_obj_t* actListMakeClose(lv_obj_t* parent) { + lv_obj_t* x = lv_btn_create(parent); + lv_obj_remove_style_all(x); + lv_obj_set_size(x, SC(32), SC(32)); + lv_obj_set_ext_click_area(x, 6); + lv_obj_add_event_cb(x, actListCloseCb, LV_EVENT_CLICKED, nullptr); + lv_obj_t* xl = lv_label_create(x); + lv_label_set_text(xl, LV_SYMBOL_CLOSE); + lv_obj_set_style_text_font(xl, &g_font_16, LV_PART_MAIN); + lv_obj_set_style_text_color(xl, lv_color_hex(COLOR_SUB), LV_PART_MAIN); + lv_obj_center(xl); + return x; +} + static void openActionList(const char* title, const ActItem* items, int n) { actListClose(); if (n > (int)(sizeof s_actlist_items / sizeof s_actlist_items[0])) n = (int)(sizeof s_actlist_items / sizeof s_actlist_items[0]); @@ -8606,17 +8620,9 @@ static void openActionList(const char* title, const ActItem* items, int n) { lv_obj_set_style_text_font(t, &g_font_semi_16, LV_PART_MAIN); lv_obj_set_style_text_color(t, lv_color_hex(COLOR_TEXT), LV_PART_MAIN); lv_obj_align(t, LV_ALIGN_LEFT_MID, 16, 0); - lv_obj_t* x = lv_btn_create(hd); - lv_obj_remove_style_all(x); - lv_obj_set_size(x, SC(32), SC(32)); - lv_obj_align(x, LV_ALIGN_RIGHT_MID, -6, 0); - lv_obj_set_ext_click_area(x, 6); - lv_obj_add_event_cb(x, actListCloseCb, LV_EVENT_CLICKED, nullptr); - lv_obj_t* xl = lv_label_create(x); - lv_label_set_text(xl, LV_SYMBOL_CLOSE); - lv_obj_set_style_text_font(xl, &g_font_16, LV_PART_MAIN); - lv_obj_set_style_text_color(xl, lv_color_hex(COLOR_SUB), LV_PART_MAIN); - lv_obj_center(xl); +#if !defined(HAS_THINKNODE_M9) + lv_obj_align(actListMakeClose(hd), LV_ALIGN_RIGHT_MID, -6, 0); +#endif } for (int i = 0; i < n; ++i) { const ActItem& it = s_actlist_items[i]; @@ -8660,6 +8666,15 @@ static void openActionList(const char* title, const ActItem* items, int n) { lv_obj_set_style_text_color(lb, lv_color_hex(col), LV_PART_MAIN); lv_obj_align(lb, LV_ALIGN_LEFT_MID, tx, 0); } +#if defined(HAS_THINKNODE_M9) + if (head_h) { + // M9: the header's X is created after the rows. Keypad focus follows the tree, so the + // menu opens on its first action and reaches the X last. + lv_obj_t* x = actListMakeClose(card); + lv_obj_add_flag(x, LV_OBJ_FLAG_IGNORE_LAYOUT); + lv_obj_align(x, LV_ALIGN_TOP_RIGHT, -6, (head_h - SC(32)) / 2); + } +#endif lv_obj_move_foreground(s_actlist_root); } @@ -40048,7 +40063,15 @@ static void openMessageActionMenu(int msg_idx) { } else { lv_obj_clear_flag(card, LV_OBJ_FLAG_SCROLLABLE); } - addCloseXBadge(card, msgMenuBackdropCb); + { + lv_obj_t* x = addCloseXBadge(card, msgMenuBackdropCb); +#if defined(HAS_THINKNODE_M9) + // Lift the X into the card padding so the buttons below don't clip its focus cursor. + lv_obj_align(x, LV_ALIGN_TOP_RIGHT, -2, -6); +#else + (void)x; +#endif + } // Two buttons per row, filled in reading order; an odd last button gets its // own row (left cell). bi advances per button; the grid math places it.