From ad128b2e1b6dbfb5171fac5989db651e71628426 Mon Sep 17 00:00:00 2001 From: Nathan Mills <38995150+Quipyowert2@users.noreply.github.com> Date: Sun, 23 Apr 2023 20:07:30 -0700 Subject: [PATCH] WIP: Fix crash when resizing. EventListener::paint can indirectly recurse by way of WindowProc. --- libgag/include/EventListener.h | 1 + libgag/src/EventListener.cpp | 14 +++++++++----- libgag/src/GUIBase.cpp | 5 ++++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/libgag/include/EventListener.h b/libgag/include/EventListener.h index e4aa0f49..f7909e74 100644 --- a/libgag/include/EventListener.h +++ b/libgag/include/EventListener.h @@ -52,6 +52,7 @@ class EventListener { GraphicContext* gfx; static EventListener* el; std::atomic quit, done; + std::atomic depth; }; } #endif //__EVENTLISTENER_H \ No newline at end of file diff --git a/libgag/src/EventListener.cpp b/libgag/src/EventListener.cpp index d60d04f0..505a5cdb 100644 --- a/libgag/src/EventListener.cpp +++ b/libgag/src/EventListener.cpp @@ -34,7 +34,7 @@ std::mutex EventListener::renderMutex; #endif EventListener::EventListener(GraphicContext* gfx) -: painter(nullptr) +: painter(nullptr), depth(0) { this->gfx = gfx; el = this; @@ -68,19 +68,22 @@ void EventListener::removePainter(const std::string& name) if (painters.empty()) assert("Tried to remove a painter when painters map is empty."); std::unique_lock lock(renderMutex); - for (auto it = painters.rbegin(); it != painters.rend();++it) + for (std::multimap >::reverse_iterator it = painters.rbegin(); it != painters.rend(); ++it) { if (it->first == name) { // There might be multiple Screens active, so we remove the one added last. // For example, a Screen with an OverlayScreen above it. - painters.erase(it.base()); + painters.erase(--(it.base())); break; } } } void EventListener::paint() { + depth++; + if (depth > 1) + return; if (painters.size()) { std::unique_lock lock(renderMutex); @@ -91,6 +94,7 @@ void EventListener::paint() } gfx->nextFrame(); } + depth--; } //https://stackoverflow.com/a/51597338/8890345 #ifdef WINDOWS_OR_MINGW @@ -124,8 +128,8 @@ void EventListener::run() { std::unique_lock lock(startMutex); quit = false; - startedCond.notify_one(); } + startedCond.notify_one(); #ifdef WINDOWS_OR_MINGW SDL_AddEventWatch(eventWatch, this); // register the event watch function SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); // we need the native Windows events, so we can listen to WM_ENTERSIZEMOVE and WM_TIMER @@ -165,8 +169,8 @@ void EventListener::run() { std::unique_lock lock(doneMutex); done = true; - doneCond.notify_one(); } + doneCond.notify_one(); } int EventListener::poll(SDL_Event* e) { diff --git a/libgag/src/GUIBase.cpp b/libgag/src/GUIBase.cpp index d6140b50..44057fc6 100644 --- a/libgag/src/GUIBase.cpp +++ b/libgag/src/GUIBase.cpp @@ -530,7 +530,10 @@ namespace GAGGUI dispatchEvents(&windowEvent); // draw - dispatchPaint(); + { + std::unique_lock lock(EventListener::instance()->renderMutex); + dispatchPaint(); + } // wait timer frameWaitTime=SDL_GetTicks()-frameStartTime;