diff --git a/src/audio/Audio.cpp b/src/audio/Audio.cpp index 19b494f..e530762 100644 --- a/src/audio/Audio.cpp +++ b/src/audio/Audio.cpp @@ -217,6 +217,7 @@ void Audio::startBackgroundLoading() { return; } } + loadingAbort = false; loadingComplete = false; loadedCount = 0; loadingThread = std::thread(&Audio::backgroundLoadingThread, this); @@ -235,12 +236,18 @@ void Audio::backgroundLoadingThread() { #endif while (true) { + if (loadingAbort.load()) { + break; + } std::string path; { std::lock_guard lock(pendingTracksMutex); if (pendingTracks.empty()) break; path = std::move(pendingTracks.front()); pendingTracks.erase(pendingTracks.begin()); + if (loadingAbort.load()) { + break; + } } AudioTrack t; t.path = path; @@ -255,6 +262,10 @@ void Audio::backgroundLoadingThread() { #endif // Thread-safe addition to tracks + if (loadingAbort.load()) { + break; + } + { std::lock_guard lock(tracksMutex); tracks.push_back(std::move(t)); @@ -262,8 +273,12 @@ void Audio::backgroundLoadingThread() { loadedCount++; - // Small delay to prevent overwhelming the system - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + // Small delay to prevent overwhelming the system (unless abort requested) + if (!loadingAbort.load()) { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } else { + break; + } } #ifdef _WIN32 @@ -328,9 +343,15 @@ void Audio::playGameMusic() { void Audio::shutdown(){ // Stop background loading thread first + loadingAbort = true; + { + std::lock_guard lock(pendingTracksMutex); + pendingTracks.clear(); + } if (loadingThread.joinable()) { loadingThread.join(); } + loadingComplete = true; if(audioStream){ SDL_DestroyAudioStream(audioStream); audioStream=nullptr; } tracks.clear(); diff --git a/src/audio/Audio.h b/src/audio/Audio.h index 3506d29..2d4b032 100644 --- a/src/audio/Audio.h +++ b/src/audio/Audio.h @@ -72,6 +72,7 @@ private: std::mutex tracksMutex; std::mutex pendingTracksMutex; std::atomic loadingComplete{false}; + std::atomic loadingAbort{false}; std::atomic loadedCount{0}; // SFX mixing support diff --git a/src/core/application/ApplicationManager.cpp b/src/core/application/ApplicationManager.cpp index 4d000cb..400b1fe 100644 --- a/src/core/application/ApplicationManager.cpp +++ b/src/core/application/ApplicationManager.cpp @@ -398,13 +398,14 @@ bool ApplicationManager::initializeManagers() { // Forward all window events to StateManager if (!m_stateManager) return; SDL_Event ev{}; - ev.type = SDL_EVENT_WINDOW_RESIZED; // generic mapping; handlers can inspect inner fields + ev.type = we.type; ev.window = we; m_stateManager->handleEvent(ev); }); m_inputManager->registerQuitHandler([this](){ SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "[QUIT] InputManager quit handler invoked - setting running=false"); + traceFile("ApplicationManager: quit handler -> m_running=false"); m_running = false; }); } diff --git a/src/core/input/InputManager.cpp b/src/core/input/InputManager.cpp index 2b1b6fe..9a72d4b 100644 --- a/src/core/input/InputManager.cpp +++ b/src/core/input/InputManager.cpp @@ -22,16 +22,8 @@ void InputManager::processEvents() { } switch (event.type) { case SDL_EVENT_QUIT: - m_shouldQuit = true; - for (auto& handler : m_quitHandlers) { - try { - // Trace quit event handling - FILE* f = fopen("tetris_trace.log", "a"); if (f) { fprintf(f, "InputManager: SDL_EVENT_QUIT polled\n"); fclose(f); } - handler(); - } catch (const std::exception& e) { - SDL_LogError(SDL_LOG_CATEGORY_INPUT, "Exception in quit handler: %s", e.what()); - } - } + case SDL_EVENT_WINDOW_CLOSE_REQUESTED: + handleQuitEvent(); break; case SDL_EVENT_KEY_DOWN: @@ -254,6 +246,10 @@ void InputManager::handleMouseMotionEvent(const SDL_MouseMotionEvent& event) { } void InputManager::handleWindowEvent(const SDL_WindowEvent& event) { + if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED) { + handleQuitEvent(); + } + // Notify handlers for (auto& handler : m_windowEventHandlers) { try { @@ -353,6 +349,11 @@ void InputManager::reset() { } void InputManager::handleQuitEvent() { + FILE* f = fopen("tetris_trace.log", "a"); + if (f) { + fprintf(f, "InputManager::handleQuitEvent invoked\n"); + fclose(f); + } m_shouldQuit = true; for (auto& handler : m_quitHandlers) { handler(); diff --git a/src/main.cpp b/src/main.cpp index 1c02302..7600ab5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -700,7 +700,7 @@ int main(int, char **) SDL_Event e; while (SDL_PollEvent(&e)) { - if (e.type == SDL_EVENT_QUIT) + if (e.type == SDL_EVENT_QUIT || e.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED) running = false; else { // Route event to state manager handlers for per-state logic diff --git a/src/main_dist.cpp b/src/main_dist.cpp index c109dda..9fad828 100644 --- a/src/main_dist.cpp +++ b/src/main_dist.cpp @@ -712,7 +712,7 @@ int main(int, char **) SDL_Event e; while (SDL_PollEvent(&e)) { - if (e.type == SDL_EVENT_QUIT) + if (e.type == SDL_EVENT_QUIT || e.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED) running = false; else { // Route event to state manager handlers for per-state logic