From 979e2edc895dd6e9010d5bb8cb69ffa1f13c86fd Mon Sep 17 00:00:00 2001 From: philmoz Date: Sun, 16 Nov 2025 20:19:46 +1100 Subject: [PATCH] fix(color): memory leaks in UI code (#6794) --- .../gui/colorlcd/libui/fullscreen_dialog.cpp | 2 -- radio/src/gui/colorlcd/libui/page.cpp | 2 +- radio/src/gui/colorlcd/libui/static.cpp | 1 + radio/src/gui/colorlcd/libui/static.h | 2 +- radio/src/gui/colorlcd/libui/table.cpp | 4 +++- radio/src/gui/colorlcd/mainview/view_main.cpp | 2 +- radio/src/gui/colorlcd/model/model_mixes.cpp | 2 +- radio/src/gui/colorlcd/model/model_setup.h | 3 --- .../src/gui/colorlcd/setup_menus/pagegroup.cpp | 17 ++++++++++++++--- radio/src/gui/colorlcd/setup_menus/pagegroup.h | 2 ++ .../src/gui/colorlcd/setup_menus/quick_menu.cpp | 2 +- radio/src/gui/colorlcd/themes/theme_manager.cpp | 3 ++- radio/src/gui/colorlcd/themes/theme_manager.h | 2 +- 13 files changed, 28 insertions(+), 16 deletions(-) diff --git a/radio/src/gui/colorlcd/libui/fullscreen_dialog.cpp b/radio/src/gui/colorlcd/libui/fullscreen_dialog.cpp index 0b1554ba8..d6decbf2c 100644 --- a/radio/src/gui/colorlcd/libui/fullscreen_dialog.cpp +++ b/radio/src/gui/colorlcd/libui/fullscreen_dialog.cpp @@ -163,8 +163,6 @@ void FullScreenDialog::deleteLater(bool detach, bool trash) Layer::pop(this); Window::deleteLater(detach, trash); } - // Window* p = Layer::back(); - // if (p) p->show(); } void FullScreenDialog::setMessage(std::string text) diff --git a/radio/src/gui/colorlcd/libui/page.cpp b/radio/src/gui/colorlcd/libui/page.cpp index 85821c80a..f3fb23c6d 100644 --- a/radio/src/gui/colorlcd/libui/page.cpp +++ b/radio/src/gui/colorlcd/libui/page.cpp @@ -105,7 +105,7 @@ void Page::deleteLater(bool detach, bool trash) Layer::pop(this); Layer::back()->show(); - Window::deleteLater(detach, trash); + NavWindow::deleteLater(detach, trash); } void Page::openMenu() diff --git a/radio/src/gui/colorlcd/libui/static.cpp b/radio/src/gui/colorlcd/libui/static.cpp index a858ff24c..532e70889 100644 --- a/radio/src/gui/colorlcd/libui/static.cpp +++ b/radio/src/gui/colorlcd/libui/static.cpp @@ -186,6 +186,7 @@ void StaticIcon::deleteLater(bool detach, bool trash) if (_deleted) return; if (mask) free(mask); mask = nullptr; + Window::deleteLater(detach, trash); } void StaticIcon::setColor(LcdColorIndex color) diff --git a/radio/src/gui/colorlcd/libui/static.h b/radio/src/gui/colorlcd/libui/static.h index f81b15a2d..d0c6d26b3 100644 --- a/radio/src/gui/colorlcd/libui/static.h +++ b/radio/src/gui/colorlcd/libui/static.h @@ -201,7 +201,7 @@ class StaticLZ4Image : public Window protected: uint8_t *imgData = nullptr; - void deleteLater(bool detach, bool trash) override; + void deleteLater(bool detach = true, bool trash = true) override; }; //----------------------------------------------------------------------------- diff --git a/radio/src/gui/colorlcd/libui/table.cpp b/radio/src/gui/colorlcd/libui/table.cpp index 5878e74f5..b4f8629f2 100644 --- a/radio/src/gui/colorlcd/libui/table.cpp +++ b/radio/src/gui/colorlcd/libui/table.cpp @@ -324,7 +324,7 @@ void TableField::setAutoEdit() void TableField::deleteLater(bool detach, bool trash) { - if (!deleted()) + if (!deleted()) { if (autoedit) { lv_group_t* g = (lv_group_t*)lv_obj_get_group(lvobj); if (g) { @@ -332,4 +332,6 @@ void TableField::deleteLater(bool detach, bool trash) lv_group_set_editing(g, false); } } + Window::deleteLater(detach, trash); + } } diff --git a/radio/src/gui/colorlcd/mainview/view_main.cpp b/radio/src/gui/colorlcd/mainview/view_main.cpp index 4569a9424..0a4e6aa08 100644 --- a/radio/src/gui/colorlcd/mainview/view_main.cpp +++ b/radio/src/gui/colorlcd/mainview/view_main.cpp @@ -103,7 +103,7 @@ void ViewMain::deleteLater(bool detach, bool trash) { Layer::pop(this); QuickMenu::shutdownQuickMenu(); - Window::deleteLater(detach, trash); + NavWindow::deleteLater(detach, trash); } void ViewMain::addMainView(WidgetsContainer* view, uint32_t viewId) diff --git a/radio/src/gui/colorlcd/model/model_mixes.cpp b/radio/src/gui/colorlcd/model/model_mixes.cpp index cb8aa99e4..8e301ef59 100644 --- a/radio/src/gui/colorlcd/model/model_mixes.cpp +++ b/radio/src/gui/colorlcd/model/model_mixes.cpp @@ -84,7 +84,7 @@ class MixLineButton : public InputMixButtonBase void deleteLater(bool detach = true, bool trash = true) override { if (mplex) mplex->deleteLater(detach, trash); - ListLineButton::deleteLater(detach, trash); + InputMixButtonBase::deleteLater(detach, trash); } void delayedInit() override diff --git a/radio/src/gui/colorlcd/model/model_setup.h b/radio/src/gui/colorlcd/model/model_setup.h index 74d960670..34078da9e 100644 --- a/radio/src/gui/colorlcd/model/model_setup.h +++ b/radio/src/gui/colorlcd/model/model_setup.h @@ -35,7 +35,4 @@ class ModelSetupPage: public PageGroupItem { static LAYOUT_VAL_SCALED(BTN_H, 62) static LAYOUT_VAL_SCALED(OPTS_W, 100) static LAYOUT_SIZE_SCALED(NAM_W, 200, 140) - - private: - TextButton *labelTextButton = nullptr; }; diff --git a/radio/src/gui/colorlcd/setup_menus/pagegroup.cpp b/radio/src/gui/colorlcd/setup_menus/pagegroup.cpp index 0b64dca48..64114bce5 100644 --- a/radio/src/gui/colorlcd/setup_menus/pagegroup.cpp +++ b/radio/src/gui/colorlcd/setup_menus/pagegroup.cpp @@ -81,7 +81,7 @@ void PageGroupHeaderBase:: setTitle(const char* title) void PageGroupHeaderBase::setIcon(EdgeTxIcon newIcon) { - hdrIcon->setIcon(newIcon); + if (hdrIcon) hdrIcon->setIcon(newIcon); } void PageGroupHeaderBase::addTab(PageGroupItem* page) @@ -98,6 +98,17 @@ bool PageGroupHeaderBase::hasSubMenu(QuickMenu::SubMenu subMenu) return false; } +void PageGroupHeaderBase::deleteLater(bool detach, bool trash) +{ + if (deleted()) return; + + for (uint8_t i = 0; i < pages.size(); i += 1) + delete pages[i]; + pages.clear(); + + Window::deleteLater(detach, trash); +} + //----------------------------------------------------------------------------- class PageGroupHeader : public PageGroupHeaderBase @@ -171,7 +182,7 @@ void PageGroupBase::checkEvents() { if (deleted()) return; - Window::checkEvents(); + NavWindow::checkEvents(); if (currentTab) { currentTab->checkEvents(); } @@ -185,7 +196,7 @@ void PageGroupBase::deleteLater(bool detach, bool trash) Layer::pop(this); Layer::back()->show(); - Window::deleteLater(detach, trash); + NavWindow::deleteLater(detach, trash); } void PageGroupBase::onClicked() { Keyboard::hide(false); } diff --git a/radio/src/gui/colorlcd/setup_menus/pagegroup.h b/radio/src/gui/colorlcd/setup_menus/pagegroup.h index a627d2af7..51edeef38 100644 --- a/radio/src/gui/colorlcd/setup_menus/pagegroup.h +++ b/radio/src/gui/colorlcd/setup_menus/pagegroup.h @@ -124,6 +124,8 @@ class PageGroupHeaderBase : public Window bool isCurrent(uint8_t idx) const { return currentIndex == idx; } uint8_t tabCount() const { return pages.size(); } + void deleteLater(bool detach = true, bool trash = true) override; + protected: uint8_t currentIndex = 0; lv_obj_t* titleLabel = nullptr; diff --git a/radio/src/gui/colorlcd/setup_menus/quick_menu.cpp b/radio/src/gui/colorlcd/setup_menus/quick_menu.cpp index e4616d66b..1dd52f9f5 100644 --- a/radio/src/gui/colorlcd/setup_menus/quick_menu.cpp +++ b/radio/src/gui/colorlcd/setup_menus/quick_menu.cpp @@ -252,7 +252,7 @@ void QuickMenu::deleteLater(bool detach, bool trash) instance = nullptr; - Window::deleteLater(detach, trash); + NavWindow::deleteLater(detach, trash); } void QuickMenu::openQM(std::function cancelHandler, diff --git a/radio/src/gui/colorlcd/themes/theme_manager.cpp b/radio/src/gui/colorlcd/themes/theme_manager.cpp index 3ece035d9..c30c85b52 100644 --- a/radio/src/gui/colorlcd/themes/theme_manager.cpp +++ b/radio/src/gui/colorlcd/themes/theme_manager.cpp @@ -556,7 +556,8 @@ HeaderIcon::HeaderIcon(Window* parent, const char* iconFile, std::functioncenter(width(), height()); + this->icon = new StaticIcon(this, 0, 0, iconFile, COLOR_THEME_PRIMARY2_INDEX); + this->icon->center(width(), height()); #if defined(HARDWARE_TOUCH) if (this->action) { lv_obj_add_flag(lvobj, LV_OBJ_FLAG_CLICKABLE); diff --git a/radio/src/gui/colorlcd/themes/theme_manager.h b/radio/src/gui/colorlcd/themes/theme_manager.h index 31991dfb0..bcd25182f 100644 --- a/radio/src/gui/colorlcd/themes/theme_manager.h +++ b/radio/src/gui/colorlcd/themes/theme_manager.h @@ -183,7 +183,7 @@ class HeaderIcon : public StaticIcon HeaderIcon(Window *parent, EdgeTxIcon icon, std::function action = nullptr); HeaderIcon(Window *parent, const char* iconFile, std::function action = nullptr); - void setIcon(EdgeTxIcon newIcon) { icon->setIcon(newIcon); } + void setIcon(EdgeTxIcon newIcon) { if (icon) icon->setIcon(newIcon); } protected: std::function action;