From ed4fd5f2c6df9991dd7fd125e05bf5223b3fa14c Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 15 Aug 2026 22:32:45 +0200 Subject: [PATCH 1/4] Ensure releasind all widgets including their callbacks. --- src/backends/sdl2_iodevice.cpp | 4 ++++ src/backends/sdl2_iodevice.h | 4 ++++ src/tinyui.cpp | 1 + src/tinyui.h | 3 +++ src/widgets.cpp | 4 ++-- 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/backends/sdl2_iodevice.cpp b/src/backends/sdl2_iodevice.cpp index 8637a14..8bb41dc 100644 --- a/src/backends/sdl2_iodevice.cpp +++ b/src/backends/sdl2_iodevice.cpp @@ -30,6 +30,10 @@ bool IODevice::update(SDL_Event &event) { return SDL_PollEvent(&event); } +void IODevice::sendEvent(const SDL_Event &event) { + SDL_PushEvent(const_cast(&event)); +} + uint32_t IODevice::getTicks() { return SDL_GetTicks(); } diff --git a/src/backends/sdl2_iodevice.h b/src/backends/sdl2_iodevice.h index a2af0a8..072275a 100644 --- a/src/backends/sdl2_iodevice.h +++ b/src/backends/sdl2_iodevice.h @@ -39,6 +39,10 @@ struct IODevice { /// @return true if an event was polled, false if not. static bool update(SDL_Event &event); + /// @brief Send an event to the io-device. + /// @param event The event to send. + static void sendEvent(const SDL_Event &event); + /// @brief Get the current ticks from the io-device. /// @return The current ticks. static uint32_t getTicks(); diff --git a/src/tinyui.cpp b/src/tinyui.cpp index 6daf8b9..57bcffb 100644 --- a/src/tinyui.cpp +++ b/src/tinyui.cpp @@ -176,6 +176,7 @@ ret_code TinyUi::release() { } Renderer::releaseRenderer(ctx); Renderer::releaseScreen(ctx); + Widgets::clear(); ctx.mRoot = nullptr; ctx.mCreated = false; diff --git a/src/tinyui.h b/src/tinyui.h index 4de6108..cf6c724 100644 --- a/src/tinyui.h +++ b/src/tinyui.h @@ -30,6 +30,7 @@ SOFTWARE. #include #include #include +#include #include #include "stb_image.h" @@ -385,6 +386,7 @@ struct CallbackI { /// @brief The default class constructor. CallbackI() : mfuncCallback{ nullptr } { clear(); + incRef(); } /// @brief The class constructor @@ -414,6 +416,7 @@ struct CallbackI { /// @brief Decrement the reference count. void decRef() { + std::cout << "DecRef: " << mNumRefs << "\n"; if (mNumRefs > 0) { --mNumRefs; if (mNumRefs <= 0) { diff --git a/src/widgets.cpp b/src/widgets.cpp index aa0f95a..fd8e568 100644 --- a/src/widgets.cpp +++ b/src/widgets.cpp @@ -733,8 +733,8 @@ void recursiveClear(Widget *current) { recursiveClear(current->mChildren[i]); } - if (current->mCallback) { - delete current->mCallback; + if (current->mCallback != nullptr) { + current->mCallback->decRef(); current->mCallback = nullptr; } delete current; From 0cdc6489a424180befda7c45b56b14603002d0aa Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 15 Aug 2026 22:41:10 +0200 Subject: [PATCH 2/4] Fix review finfing --- contrib/vcpkg | 2 +- src/backends/sdl2_iodevice.cpp | 4 ++-- src/backends/sdl2_iodevice.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/contrib/vcpkg b/contrib/vcpkg index 594ad88..f1fe3ac 160000 --- a/contrib/vcpkg +++ b/contrib/vcpkg @@ -1 +1 @@ -Subproject commit 594ad8871e1e8e45f8e626c015fd611163430207 +Subproject commit f1fe3acb62b7aba476e48e3395c40d88478ac444 diff --git a/src/backends/sdl2_iodevice.cpp b/src/backends/sdl2_iodevice.cpp index 8bb41dc..20b2a03 100644 --- a/src/backends/sdl2_iodevice.cpp +++ b/src/backends/sdl2_iodevice.cpp @@ -30,8 +30,8 @@ bool IODevice::update(SDL_Event &event) { return SDL_PollEvent(&event); } -void IODevice::sendEvent(const SDL_Event &event) { - SDL_PushEvent(const_cast(&event)); +void IODevice::sendEvent( SDL_Event &event) { + SDL_PushEvent(static_cast(&event)); } uint32_t IODevice::getTicks() { diff --git a/src/backends/sdl2_iodevice.h b/src/backends/sdl2_iodevice.h index 072275a..91fc33e 100644 --- a/src/backends/sdl2_iodevice.h +++ b/src/backends/sdl2_iodevice.h @@ -41,7 +41,7 @@ struct IODevice { /// @brief Send an event to the io-device. /// @param event The event to send. - static void sendEvent(const SDL_Event &event); + static void sendEvent(SDL_Event &event); /// @brief Get the current ticks from the io-device. /// @return The current ticks. From 0e939baffb45022214e2acbedaf0755de86f369a Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 16 Aug 2026 12:59:34 +0200 Subject: [PATCH 3/4] Fix review findings. --- src/tinyui.cpp | 4 +++- src/tinyui.h | 2 -- src/widgets.cpp | 52 ++++++++++++++++++++++++++++++------------------- 3 files changed, 35 insertions(+), 23 deletions(-) diff --git a/src/tinyui.cpp b/src/tinyui.cpp index 57bcffb..d744e67 100644 --- a/src/tinyui.cpp +++ b/src/tinyui.cpp @@ -129,7 +129,8 @@ ret_code TinyUi::getSurfaceInfo(int32_t &w, int32_t &h) { } ret_code TinyUi::getSurfaceCenter(int32_t &x, int32_t &y) { - int32_t w{-1}, h{-1}; + int32_t w{ -1 }; + int32_t h{ -1 }; x = y = -1; if (getSurfaceInfo(w, h) == ErrorCode) { return ErrorCode; @@ -177,6 +178,7 @@ ret_code TinyUi::release() { Renderer::releaseRenderer(ctx); Renderer::releaseScreen(ctx); Widgets::clear(); + ctx.mFocus = nullptr; ctx.mRoot = nullptr; ctx.mCreated = false; diff --git a/src/tinyui.h b/src/tinyui.h index cf6c724..421fc80 100644 --- a/src/tinyui.h +++ b/src/tinyui.h @@ -30,7 +30,6 @@ SOFTWARE. #include #include #include -#include #include #include "stb_image.h" @@ -416,7 +415,6 @@ struct CallbackI { /// @brief Decrement the reference count. void decRef() { - std::cout << "DecRef: " << mNumRefs << "\n"; if (mNumRefs > 0) { --mNumRefs; if (mNumRefs <= 0) { diff --git a/src/widgets.cpp b/src/widgets.cpp index fd8e568..afbebf9 100644 --- a/src/widgets.cpp +++ b/src/widgets.cpp @@ -37,12 +37,13 @@ namespace tinyui { static constexpr Id RootHandle = 1; -static Id createHandle() { - static Id id{RootHandle}; +namespace { +Id createHandle() { + static Id id{ RootHandle }; return ++id; } -static Image *findImage(Context &ctx, const char *filename) { +Image *findImage(Context &ctx, const char *filename) { if (filename == nullptr) { return nullptr; } @@ -55,7 +56,7 @@ static Image *findImage(Context &ctx, const char *filename) { return it->second; } -static Image *loadIntoImageCache(Context &ctx, const char *filename) { +Image *loadIntoImageCache(Context &ctx, const char *filename) { if (filename == nullptr) { return nullptr; } @@ -89,7 +90,7 @@ static Image *loadIntoImageCache(Context &ctx, const char *filename) { return image; } -static void releaseImageCache(Context &ctx) { +void releaseImageCache(Context &ctx) { for (auto it = ctx.mImageCache.begin(); it != ctx.mImageCache.end(); ++it) { if (Image *image = it->second; image != nullptr) { Renderer::releaseSurfaceImpl(image->mSurfaceImpl); @@ -97,22 +98,22 @@ static void releaseImageCache(Context &ctx) { } } ctx.mImageCache.clear(); -} +} -static Widget *getValidRoot(Context &ctx) { +Widget *getValidRoot(Context &ctx) { if (ctx.mRoot != nullptr) { return ctx.mRoot; } - + ctx.mRoot = new Widget; ctx.mRoot->mType = WidgetType::RootContainer; ctx.mRoot->mHandle = WidgetHandle::getRootHandle(); - + return ctx.mRoot; } -static Widget *setParent(Context &ctx, Widget *child, WidgetHandle parentId) { - Widget *parent{nullptr}; +Widget *setParent(Context &ctx, Widget *child, WidgetHandle parentId) { + Widget *parent{ nullptr }; if (parentId.mId == 0) { parent = getValidRoot(ctx); } else { @@ -129,9 +130,9 @@ static Widget *setParent(Context &ctx, Widget *child, WidgetHandle parentId) { return parent; } -static Widget *createWidget(Context &ctx, WidgetHandle parentId, const Rect &rect, WidgetType type) { +Widget *createWidget(Context &ctx, WidgetHandle parentId, const Rect &rect, WidgetType type) { auto *widget = new Widget; - widget->mHandle = WidgetHandle{createHandle()}; + widget->mHandle = WidgetHandle{ createHandle() }; widget->mType = type; widget->mRect = rect; widget->mParent = setParent(ctx, widget, parentId); @@ -144,18 +145,28 @@ static Widget *createWidget(Context &ctx, WidgetHandle parentId, const Rect &rec return widget; } -static void deleteKeyFromText(Context &ctx) { +void deleteKeyFromText(Context &ctx) { ctx.mFocus->mText.erase(ctx.mFocus->mText.size() - 1); } -static void appendKeyToText(Context &ctx, char *buffer) { +void appendKeyToText(Context &ctx, char *buffer) { + if (buffer == nullptr) { + return; + } + + if (ctx.mFocus->mKeyInputType == KeyInputType::Numeric) { + if (buffer[0] < '0' || buffer[0] > '9') { + return; + } + } + ctx.mFocus->mText.append(buffer); } -static void handleInputField(Context &ctx, EventPayload *eventPayload) { - char buffer[2] = { - static_cast(eventPayload->payload[0]), - '\0' +void handleInputField(Context &ctx, EventPayload *eventPayload) { + char buffer[2] = { + static_cast(eventPayload->payload[0]), + '\0' }; if (buffer[0] == SDLK_BACKSPACE) { deleteKeyFromText(ctx); @@ -163,6 +174,7 @@ static void handleInputField(Context &ctx, EventPayload *eventPayload) { appendKeyToText(ctx, buffer); } } +} // namespace void eventDispatcher(Context &ctx, int32_t eventId, EventPayload *eventPayload) { if (ctx.mFocus == nullptr) { @@ -420,7 +432,7 @@ WidgetHandle Widgets::treeView(WidgetHandle parentId, const char *title, const R widget->mText.assign(title); } - CallbackI *callback = new CallbackI(onTreeViewItemClicked, nullptr, Events::MouseButtonDownEvent); + auto *callback = new CallbackI(onTreeViewItemClicked, nullptr, Events::MouseButtonDownEvent); widget->mCallback = callback; if (callback != nullptr) { callback->incRef(); From 055630d8981ca1c8a70f7e9e6ae6f8a4eea46a73 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 16 Aug 2026 14:18:15 +0200 Subject: [PATCH 4/4] Fix review findings --- src/backends/sdl2_renderer.cpp | 2 +- src/backends/sdl2_renderer.h | 5 +++-- src/widgets.cpp | 8 +++++--- src/widgets.h | 3 +++ 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/backends/sdl2_renderer.cpp b/src/backends/sdl2_renderer.cpp index 65a94a8..7de6f7a 100644 --- a/src/backends/sdl2_renderer.cpp +++ b/src/backends/sdl2_renderer.cpp @@ -543,7 +543,7 @@ void Renderer::releaseSurfaceImpl(SurfaceImpl *surfaceImpl) { } } -ret_code Renderer::getSurfaceInfo(Context &ctx, int32_t &w, int32_t &h) { +ret_code Renderer::getSurfaceInfo(const Context &ctx, int32_t &w, int32_t &h) { const auto *sdlCtx = (const SDLContext *) ctx.mBackendCtx->mHandle; if (sdlCtx->mSurface == nullptr) { return ErrorCode; diff --git a/src/backends/sdl2_renderer.h b/src/backends/sdl2_renderer.h index ff49cb5..29d9f34 100644 --- a/src/backends/sdl2_renderer.h +++ b/src/backends/sdl2_renderer.h @@ -36,7 +36,8 @@ struct SDL_Renderer; struct SDL_Texture; namespace tinyui { - + +/// @brief The surface implementation using the SDL2 library. struct SurfaceImpl { SDL_Surface *mSurface{nullptr}; @@ -122,7 +123,7 @@ struct Renderer { static bool update(const Context &ctx); static SurfaceImpl *createSurfaceImpl(unsigned char *data, int w, int h, int bytesPerPixel, int pitch); static void releaseSurfaceImpl(SurfaceImpl *surfaceImpl); - static ret_code getSurfaceInfo(Context &ctx, int32_t &w, int32_t &h); + static ret_code getSurfaceInfo(const Context &ctx, int32_t &w, int32_t &h); }; } // namespace tinyui diff --git a/src/widgets.cpp b/src/widgets.cpp index afbebf9..41f463a 100644 --- a/src/widgets.cpp +++ b/src/widgets.cpp @@ -460,7 +460,7 @@ WidgetHandle Widgets::treeItem(WidgetHandle parentItemId, const char *text) { const int32_t margin = ctx.mStyle.mMargin; const int32_t w = parentRect.width; const int32_t h = parentRect.height; - size_t numChildren = parentWidget->mChildren.size() + 1; + const size_t numChildren = parentWidget->mChildren.size() + 1; const Rect rect(parentRect.top.x + margin, parentRect.top.y + static_cast(numChildren) * margin + static_cast(numChildren) * h, w, h); Widget *child = createWidget(ctx, parentItemId, rect, WidgetType::Label); @@ -543,7 +543,8 @@ static void render(Context &ctx, const Widget *currentWidget) { Renderer::drawImage(ctx, r.top.x, r.top.y, r.width, r.height, currentWidget->mImage); } if (!currentWidget->mText.empty()) { - Color4 fg = ctx.mStyle.mTextColor, bg = ctx.mStyle.mBg; + const Color4 fg = ctx.mStyle.mTextColor; + const Color4 bg = ctx.mStyle.mBg; Renderer::drawText(ctx, currentWidget->mText.c_str(), ctx.mDefaultFont, currentWidget->mRect, fg, bg, currentWidget->mAlignment); } @@ -554,7 +555,8 @@ static void render(Context &ctx, const Widget *currentWidget) { { Renderer::drawRect(ctx, r.top.x, r.top.y, r.width, r.height, false, ctx.mStyle.mFg); if (!currentWidget->mText.empty()) { - Color4 fg = ctx.mStyle.mTextColor, bg = ctx.mStyle.mBg; + const Color4 fg = ctx.mStyle.mTextColor; + const Color4 bg = ctx.mStyle.mBg; Renderer::drawText(ctx, currentWidget->mText.c_str(), ctx.mDefaultFont, currentWidget->mRect, fg, bg, currentWidget->mAlignment); } diff --git a/src/widgets.h b/src/widgets.h index 3946211..0aabec6 100644 --- a/src/widgets.h +++ b/src/widgets.h @@ -116,6 +116,9 @@ struct Widget { } if (mCallback != nullptr) { + for (size_t i = 0; i < Events::NumEvents; ++i) { + mCallback->mfuncCallback[i] = nullptr; + } mCallback->decRef(); } }