From 0a1d1821daee7053bdea273cccb0db6fd6a841e8 Mon Sep 17 00:00:00 2001 From: phosit Date: Wed, 16 Apr 2025 19:49:51 +0200 Subject: [PATCH] Split window from main event handler Two globals can be removed. --- source/main.cpp | 33 +----------------------- source/ps/Input.h | 21 ++++++++-------- source/ps/VideoMode.cpp | 56 +++++++++++++++++++++++++++-------------- source/ps/VideoMode.h | 20 ++++++++++----- 4 files changed, 63 insertions(+), 67 deletions(-) diff --git a/source/main.cpp b/source/main.cpp index 37f3450447..e044db9e36 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -168,14 +168,6 @@ enum ShutdownType static ShutdownType g_Shutdown = ShutdownType::None; static int g_ExitStatus{EXIT_SUCCESS}; -// to avoid redundant and/or recursive resizing, we save the new -// size after VIDEORESIZE messages and only update the video mode -// once per frame. -// these values are the latest resize message, and reset to 0 once we've -// updated the video mode -static int g_ResizedW; -static int g_ResizedH; - static std::chrono::high_resolution_clock::time_point lastFrameTime; bool IsQuitRequested() @@ -199,18 +191,6 @@ static Input::Reaction MainInputHandler(const SDL_Event& ev) { switch(ev.type) { - case SDL_WINDOWEVENT: - switch(ev.window.event) - { - case SDL_WINDOWEVENT_RESIZED: - g_ResizedW = ev.window.data1; - g_ResizedH = ev.window.data2; - break; - case SDL_WINDOWEVENT_MOVED: - g_VideoMode.UpdatePosition(ev.window.data1, ev.window.data2); - } - break; - case SDL_QUIT: QuitEngine(EXIT_SUCCESS); break; @@ -261,12 +241,6 @@ static Input::Reaction MainInputHandler(const SDL_Event& ev) g_Profiler2.Toggle(); return Input::Reaction::HANDLED; } - else if (hotkey == "mousegrabtoggle") - { - SDL_Window* const window{g_VideoMode.GetWindow()}; - const SDL_bool willGrabMouse{SDL_GetWindowGrab(window) ? SDL_FALSE : SDL_TRUE}; - SDL_SetWindowGrab(window, willGrabMouse); - } break; } @@ -449,12 +423,7 @@ static void Frame(RL::Interface* rlInterface, const int fixedFrameFrequency) if (g_Shutdown != ShutdownType::None) return; - // respond to pumped resize events - if (g_ResizedW || g_ResizedH) - { - g_VideoMode.ResizeWindow(g_ResizedW, g_ResizedH); - g_ResizedW = g_ResizedH = 0; - } + g_VideoMode.OnceAFrameWork(); if (g_NetClient) g_NetClient->Poll(); diff --git a/source/ps/Input.h b/source/ps/Input.h index 4400be9f64..72a4f9c43d 100644 --- a/source/ps/Input.h +++ b/source/ps/Input.h @@ -49,28 +49,29 @@ enum class Reaction namespace Slot { constexpr std::integral_constant PRIMARY; +constexpr std::integral_constant WINDOW; // These two must be called first `globalsInput` deals with some important global state, such as which // scancodes are being pressed, mouse buttons pressed, etc. while hotkeyStateChange updates the map of // active hotkeys. -constexpr std::integral_constant HOTKEY_STATE_CHANGE; -constexpr std::integral_constant GLOBAL; +constexpr std::integral_constant HOTKEY_STATE_CHANGE; +constexpr std::integral_constant GLOBAL; // Should be called after scancode map update (i.e. after the global input, but before UI). This never // blocks the event, but it does some processing necessary for hotkeys, which are triggered later down the // input chain. (by calling this before the UI, we can use `EventWouldTriggerHotkey` in the UI). -constexpr std::integral_constant HOTKEY_INPUT_PREPARATION; +constexpr std::integral_constant HOTKEY_INPUT_PREPARATION; -constexpr std::integral_constant TOUCH_INPUT; +constexpr std::integral_constant TOUCH_INPUT; // The console handler needs to be called before the hotkey handler so that text can be typed in without // setting off hotkeys. -constexpr std::integral_constant CONSOLE; +constexpr std::integral_constant CONSOLE; // Likewise for gui. -constexpr std::integral_constant GUI; -constexpr std::integral_constant HOTKEY_INPUT; -constexpr std::integral_constant PROFILE_VIEWER; -constexpr std::integral_constant GAME_VIEW; +constexpr std::integral_constant GUI; +constexpr std::integral_constant HOTKEY_INPUT; +constexpr std::integral_constant PROFILE_VIEWER; +constexpr std::integral_constant GAME_VIEW; } /** @@ -137,7 +138,7 @@ public: PollEventsResult PollEvents(); private: - std::array m_Handlers{{}}; + std::array m_Handlers{{}}; const std::unique_ptr> m_PriorityEvents; }; diff --git a/source/ps/VideoMode.cpp b/source/ps/VideoMode.cpp index d676e4adb0..018c258b24 100644 --- a/source/ps/VideoMode.cpp +++ b/source/ps/VideoMode.cpp @@ -39,6 +39,7 @@ #include "ps/Filesystem.h" #include "ps/Game.h" #include "ps/GameSetup/Config.h" +#include "ps/Hotkey.h" #include "ps/Pyrogenesis.h" #include "renderer/Renderer.h" #include "renderer/backend/IDevice.h" @@ -280,6 +281,36 @@ void CVideoMode::CCursor::ResetCursor() SetCursor(DEFAULT_CURSOR_NAME); } +Input::Reaction CVideoMode::InputHandler::operator()(const SDL_Event& ev) +{ + if (ev.type == SDL_HOTKEYPRESS) + { + if (static_cast(ev.user.data1) == "mousegrabtoggle"sv) + { + SDL_Window* const window{videoMode.GetWindow()}; + const SDL_bool willGrabMouse{SDL_GetWindowGrab(window) ? SDL_FALSE : SDL_TRUE}; + SDL_SetWindowGrab(window, willGrabMouse); + return Input::Reaction::HANDLED; + } + } + if (ev.type == SDL_WINDOWEVENT && videoMode.m_IsFullscreen) + { + switch (ev.window.event) + { + case SDL_WINDOWEVENT_RESIZED: + videoMode.m_ResizedW = ev.window.data1; + videoMode.m_ResizedH = ev.window.data2; + break; + case SDL_WINDOWEVENT_MOVED: + videoMode.m_WindowedX = ev.window.data1; + videoMode.m_WindowedY = ev.window.data2; + break; + } + } + + return Input::Reaction::PASS; +} + CVideoMode::CVideoMode() : m_WindowedW(DEFAULT_WINDOW_W), m_WindowedH(DEFAULT_WINDOW_H), m_WindowedX(0), m_WindowedY(0) { @@ -736,27 +767,23 @@ Renderer::Backend::ISwapChain* CVideoMode::GetOrCreateSwapChain() return m_SwapChain.get(); } -bool CVideoMode::ResizeWindow(int w, int h) +bool CVideoMode::OnceAFrameWork() { ENSURE(m_IsInitialised); - // Ignore if not windowed - if (m_IsFullscreen) - return true; - // Ignore if the size hasn't changed - if (w == m_WindowedW && h == m_WindowedH) + if ((m_ResizedH == 0 && m_ResizedW == 0) || (m_ResizedW == m_WindowedW && m_ResizedH == m_WindowedH)) return true; int bpp = GetBestBPP(); - if (!SetVideoMode(w, h, bpp, false)) + if (!SetVideoMode(m_ResizedW, m_ResizedH, bpp, false)) return false; - m_WindowedW = w; - m_WindowedH = h; + m_WindowedW = m_ResizedW; + m_WindowedH = m_ResizedH; - UpdateRenderer(w, h); + UpdateRenderer(m_ResizedW, m_ResizedH); return true; } @@ -844,15 +871,6 @@ bool CVideoMode::IsInFullscreen() const return m_IsFullscreen; } -void CVideoMode::UpdatePosition(int x, int y) -{ - if (!m_IsFullscreen) - { - m_WindowedX = x; - m_WindowedY = y; - } -} - void CVideoMode::UpdateRenderer(int w, int h) { if (w < 2) w = 2; // avoid GL errors caused by invalid sizes diff --git a/source/ps/VideoMode.h b/source/ps/VideoMode.h index 272c471cc3..2d54c84529 100644 --- a/source/ps/VideoMode.h +++ b/source/ps/VideoMode.h @@ -61,7 +61,7 @@ public: /** * Resize the SDL window and associated graphics stuff to the new size. */ - bool ResizeWindow(int w, int h); + bool OnceAFrameWork(); /** * Set scale and tell dependent compoenent to recompute sizes. @@ -83,11 +83,6 @@ public: */ bool ToggleFullscreen(); - /** - * Update window position, to restore later if necessary (SDL2 only). - */ - void UpdatePosition(int x, int y); - /** * Update the graphics code to start drawing to the new size. * This should be called after the GL context has been resized. @@ -193,6 +188,19 @@ private: std::unique_ptr m_BackendDevice; // SwapChain for the corresponding device. std::unique_ptr m_SwapChain; + + // To avoid redundant and/or recursive resizing, we save the new size after VIDEORESIZE messages and + // only update the video mode once per frame. + // These values are the values of the latest resize message. + int m_ResizedW{0}; + int m_ResizedH{0}; + + struct InputHandler + { + CVideoMode& videoMode; + Input::Reaction operator()(const SDL_Event& ev); + }; + Input::Handler m_InputHandler{m_InputManager, Input::Slot::WINDOW, {*this}}; }; extern CVideoMode g_VideoMode;