From b2a8f94a20bf5ba64c3fd2bca8f4ba2e98c1a4dc Mon Sep 17 00:00:00 2001 From: phosit Date: Thu, 17 Apr 2025 14:42:38 +0200 Subject: [PATCH] Move the console input handler to CConsole `conInputHandler` isn't global anymore. That makes the interface simpler and might make the compilation and the runtime faster. --- source/ps/CConsole.cpp | 110 +++++++++++++++--------------- source/ps/CConsole.h | 17 ++--- source/ps/GameSetup/GameSetup.cpp | 2 - 3 files changed, 64 insertions(+), 65 deletions(-) diff --git a/source/ps/CConsole.cpp b/source/ps/CConsole.cpp index e445381d9c..2e301f03b3 100644 --- a/source/ps/CConsole.cpp +++ b/source/ps/CConsole.cpp @@ -60,12 +60,15 @@ #include #include #include +#include #include #include #include #include #include #include +#include +#include #include #include #include @@ -76,11 +79,44 @@ namespace // For text being typed into the console. constexpr int CONSOLE_BUFFER_SIZE = 1024; +template Function> +void ShowQuitHotkeys(bool& quitHotkeyWasShown, Function insertMessage) +{ + if (std::exchange(quitHotkeyWasShown, true)) + return; + + const std::string str{std::accumulate(g_HotkeyMap.begin(), g_HotkeyMap.end(), std::string{}, + [](std::string acc, const std::pair& key) + { + if (std::get<1>(key).front().name != "console.toggle") + return acc; + + return acc + (acc.empty() ? "Press " : " / ") + + FindScancodeName(static_cast(std::get<0>(key))); + })}; + + if (!str.empty()) + insertMessage(str + " to quit."); +} + +template Function> +void SetVisible(const bool visible, bool& quitHotkeyWasShown, Function insertMessage) +{ + // TODO: this should be based on input focus, not visibility + if (visible) + { + ShowQuitHotkeys(quitHotkeyWasShown, std::move(insertMessage)); + SDL_StartTextInput(); + return; + } + SDL_StopTextInput(); +} } // anonymous namespace CConsole* g_Console = 0; -CConsole::CConsole() +CConsole::CConsole() : + m_InputHandler{g_VideoMode.m_InputManager, Input::Slot::CONSOLE, {*this}} { m_Toggle = false; m_Visible = false; @@ -139,37 +175,6 @@ void CConsole::UpdateScreenSize(int w, int h) m_Height = height / g_VideoMode.GetScale(); } -void CConsole::ShowQuitHotkeys() -{ - if (m_QuitHotkeyWasShown) - return; - - std::string str; - for (const std::pair& key : g_HotkeyMap) - if (key.second.front().name == "console.toggle") - str += (str.empty() ? "Press " : " / ") + FindScancodeName(static_cast(key.first)); - - if (!str.empty()) - InsertMessage(str + " to quit."); - - m_QuitHotkeyWasShown = true; -} - -void CConsole::ToggleVisible() -{ - m_Toggle = true; - m_Visible = !m_Visible; - - // TODO: this should be based on input focus, not visibility - if (m_Visible) - { - ShowQuitHotkeys(); - SDL_StartTextInput(); - return; - } - SDL_StopTextInput(); -} - void CConsole::SetVisible(bool visible) { if (visible != m_Visible) @@ -579,12 +584,6 @@ void CConsole::InsertMessage(const std::string& message) } } -const wchar_t* CConsole::GetBuffer() -{ - m_Buffer[m_BufferLength] = 0; - return m_Buffer.get(); -} - void CConsole::SetBuffer(const wchar_t* szMessage) { int oldBufferPos = m_BufferPos; // remember since FlushBuffer will set it to 0 @@ -692,44 +691,45 @@ static bool isUnprintableChar(SDL_Keysym key) } } -Input::Reaction conInputHandler(const SDL_Event& ev) +Input::Reaction CConsole::InputHandler::operator()(const SDL_Event& ev) { - if (!g_Console) - return Input::Reaction::PASS; - if (static_cast(ev.type) == SDL_HOTKEYPRESS) { - std::string hotkey = static_cast(ev.user.data1); + std::string_view hotkey{static_cast(ev.user.data1)}; if (hotkey == "console.toggle") { ResetActiveHotkeys(); - g_Console->ToggleVisible(); + console.m_Toggle = true; + console.m_Visible = !console.m_Visible; + ::SetVisible(console.m_Visible, console.m_QuitHotkeyWasShown, [&](auto&&... args){ + console.InsertMessage(std::forward(args)...); + }); return Input::Reaction::HANDLED; } - else if (g_Console->IsActive() && hotkey == "copy") + if (!console.IsActive()) + return Input::Reaction::PASS; + if (hotkey == "copy") { - std::string text = utf8_from_wstring(g_Console->GetBuffer()); - SDL_SetClipboardText(text.c_str()); + console.m_Buffer[console.m_BufferLength] = 0; + SDL_SetClipboardText(utf8_from_wstring(console.m_Buffer.get()).c_str()); return Input::Reaction::HANDLED; } - else if (g_Console->IsActive() && hotkey == "paste") + if (hotkey == "paste") { char* utf8_text = SDL_GetClipboardText(); if (!utf8_text) return Input::Reaction::HANDLED; - std::wstring text = wstring_from_utf8(utf8_text); + for (wchar_t c : wstring_from_utf8(utf8_text)) + console.InsertChar(0, c); SDL_free(utf8_text); - for (wchar_t c : text) - g_Console->InsertChar(0, c); - return Input::Reaction::HANDLED; } } - if (!g_Console->IsActive()) + if (!console.IsActive()) return Input::Reaction::PASS; // In SDL2, we no longer get Unicode wchars via SDL_Keysym @@ -739,7 +739,7 @@ Input::Reaction conInputHandler(const SDL_Event& ev) // TODO: this could be more efficient with an interface to insert UTF-8 strings directly std::wstring wstr = wstring_from_utf8(ev.text.text); for (size_t i = 0; i < wstr.length(); ++i) - g_Console->InsertChar(0, wstr[i]); + console.InsertChar(0, wstr[i]); return Input::Reaction::HANDLED; } // TODO: text editing events for IME support @@ -753,7 +753,7 @@ Input::Reaction conInputHandler(const SDL_Event& ev) if (ev.type == SDL_KEYDOWN && isUnprintableChar(ev.key.keysym) && !HotkeyIsPressed("console.toggle")) { - g_Console->InsertChar(sym, 0); + console.InsertChar(sym, 0); return Input::Reaction::HANDLED; } diff --git a/source/ps/CConsole.h b/source/ps/CConsole.h index d68a6d6615..ff5416a669 100644 --- a/source/ps/CConsole.h +++ b/source/ps/CConsole.h @@ -54,7 +54,6 @@ public: void UpdateScreenSize(int w, int h); - void ToggleVisible(); void SetVisible(bool visible); /** @@ -64,14 +63,10 @@ public: void Render(CCanvas2D& canvas); - void InsertChar(const int szChar, const wchar_t cooked); - void InsertMessage(const std::string& message); void SetBuffer(const wchar_t* szMessage); - // Only returns a pointer to the buffer; copy out of here if you want to keep it. - const wchar_t* GetBuffer(); void FlushBuffer(); bool IsActive() const { return m_Visible; } @@ -115,6 +110,8 @@ private: bool m_QuitHotkeyWasShown; // show console.toggle hotkey values at first time double m_CursorBlinkRate; // cursor blink rate in seconds, if greater than 0.0 + void InsertChar(const int szChar, const wchar_t cooked); + void DrawWindow(CCanvas2D& canvas); void DrawHistory(CTextRenderer& textRenderer); void DrawBuffer(CTextRenderer& textRenderer); @@ -131,11 +128,15 @@ private: void LoadHistory(); void SaveHistory(); - void ShowQuitHotkeys(); + + struct InputHandler + { + CConsole& console; + Input::Reaction operator()(const SDL_Event& ev); + }; + Input::Handler m_InputHandler; }; extern CConsole* g_Console; -extern Input::Reaction conInputHandler(const SDL_Event& ev); - #endif // INCLUDED_CCONSOLE diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp index 9876c004a7..a6191ad7f1 100644 --- a/source/ps/GameSetup/GameSetup.cpp +++ b/source/ps/GameSetup/GameSetup.cpp @@ -268,8 +268,6 @@ static void InitPs(bool setup_gui, const CStrW& gui_page, ScriptInterface* srcSc // hotkey handler so that input boxes can be typed in without // setting off hotkeys. handlers->emplace(g_VideoMode.m_InputManager, Input::Slot::GUI, gui_handler); - // Likewise for the console. - handlers->emplace(g_VideoMode.m_InputManager, Input::Slot::CONSOLE, conInputHandler); handlers->emplace(g_VideoMode.m_InputManager, Input::Slot::TOUCH_INPUT, touch_input_handler);