mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-06-20 23:44:08 +00:00
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.
This commit is contained in:
+55
-55
@@ -60,12 +60,15 @@
|
|||||||
#include <SDL_stdinc.h>
|
#include <SDL_stdinc.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <concepts>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cwchar>
|
#include <cwchar>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <js/RootingAPI.h>
|
#include <js/RootingAPI.h>
|
||||||
#include <js/TypeDecls.h>
|
#include <js/TypeDecls.h>
|
||||||
#include <js/Value.h>
|
#include <js/Value.h>
|
||||||
|
#include <numeric>
|
||||||
|
#include <string_view>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -76,11 +79,44 @@ namespace
|
|||||||
// For text being typed into the console.
|
// For text being typed into the console.
|
||||||
constexpr int CONSOLE_BUFFER_SIZE = 1024;
|
constexpr int CONSOLE_BUFFER_SIZE = 1024;
|
||||||
|
|
||||||
|
template<std::invocable<std::string> 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<const SDL_Scancode_, KeyMapping>& key)
|
||||||
|
{
|
||||||
|
if (std::get<1>(key).front().name != "console.toggle")
|
||||||
|
return acc;
|
||||||
|
|
||||||
|
return acc + (acc.empty() ? "Press " : " / ") +
|
||||||
|
FindScancodeName(static_cast<SDL_Scancode>(std::get<0>(key)));
|
||||||
|
})};
|
||||||
|
|
||||||
|
if (!str.empty())
|
||||||
|
insertMessage(str + " to quit.");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::invocable<std::string> 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
|
} // anonymous namespace
|
||||||
|
|
||||||
CConsole* g_Console = 0;
|
CConsole* g_Console = 0;
|
||||||
|
|
||||||
CConsole::CConsole()
|
CConsole::CConsole() :
|
||||||
|
m_InputHandler{g_VideoMode.m_InputManager, Input::Slot::CONSOLE, {*this}}
|
||||||
{
|
{
|
||||||
m_Toggle = false;
|
m_Toggle = false;
|
||||||
m_Visible = false;
|
m_Visible = false;
|
||||||
@@ -139,37 +175,6 @@ void CConsole::UpdateScreenSize(int w, int h)
|
|||||||
m_Height = height / g_VideoMode.GetScale();
|
m_Height = height / g_VideoMode.GetScale();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConsole::ShowQuitHotkeys()
|
|
||||||
{
|
|
||||||
if (m_QuitHotkeyWasShown)
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::string str;
|
|
||||||
for (const std::pair<const SDL_Scancode_, KeyMapping>& key : g_HotkeyMap)
|
|
||||||
if (key.second.front().name == "console.toggle")
|
|
||||||
str += (str.empty() ? "Press " : " / ") + FindScancodeName(static_cast<SDL_Scancode>(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)
|
void CConsole::SetVisible(bool visible)
|
||||||
{
|
{
|
||||||
if (visible != m_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)
|
void CConsole::SetBuffer(const wchar_t* szMessage)
|
||||||
{
|
{
|
||||||
int oldBufferPos = m_BufferPos; // remember since FlushBuffer will set it to 0
|
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<int>(ev.type) == SDL_HOTKEYPRESS)
|
if (static_cast<int>(ev.type) == SDL_HOTKEYPRESS)
|
||||||
{
|
{
|
||||||
std::string hotkey = static_cast<const char*>(ev.user.data1);
|
std::string_view hotkey{static_cast<const char*>(ev.user.data1)};
|
||||||
|
|
||||||
if (hotkey == "console.toggle")
|
if (hotkey == "console.toggle")
|
||||||
{
|
{
|
||||||
ResetActiveHotkeys();
|
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<decltype(args)>(args)...);
|
||||||
|
});
|
||||||
return Input::Reaction::HANDLED;
|
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());
|
console.m_Buffer[console.m_BufferLength] = 0;
|
||||||
SDL_SetClipboardText(text.c_str());
|
SDL_SetClipboardText(utf8_from_wstring(console.m_Buffer.get()).c_str());
|
||||||
return Input::Reaction::HANDLED;
|
return Input::Reaction::HANDLED;
|
||||||
}
|
}
|
||||||
else if (g_Console->IsActive() && hotkey == "paste")
|
if (hotkey == "paste")
|
||||||
{
|
{
|
||||||
char* utf8_text = SDL_GetClipboardText();
|
char* utf8_text = SDL_GetClipboardText();
|
||||||
if (!utf8_text)
|
if (!utf8_text)
|
||||||
return Input::Reaction::HANDLED;
|
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);
|
SDL_free(utf8_text);
|
||||||
|
|
||||||
for (wchar_t c : text)
|
|
||||||
g_Console->InsertChar(0, c);
|
|
||||||
|
|
||||||
return Input::Reaction::HANDLED;
|
return Input::Reaction::HANDLED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_Console->IsActive())
|
if (!console.IsActive())
|
||||||
return Input::Reaction::PASS;
|
return Input::Reaction::PASS;
|
||||||
|
|
||||||
// In SDL2, we no longer get Unicode wchars via SDL_Keysym
|
// 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
|
// TODO: this could be more efficient with an interface to insert UTF-8 strings directly
|
||||||
std::wstring wstr = wstring_from_utf8(ev.text.text);
|
std::wstring wstr = wstring_from_utf8(ev.text.text);
|
||||||
for (size_t i = 0; i < wstr.length(); ++i)
|
for (size_t i = 0; i < wstr.length(); ++i)
|
||||||
g_Console->InsertChar(0, wstr[i]);
|
console.InsertChar(0, wstr[i]);
|
||||||
return Input::Reaction::HANDLED;
|
return Input::Reaction::HANDLED;
|
||||||
}
|
}
|
||||||
// TODO: text editing events for IME support
|
// 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) &&
|
if (ev.type == SDL_KEYDOWN && isUnprintableChar(ev.key.keysym) &&
|
||||||
!HotkeyIsPressed("console.toggle"))
|
!HotkeyIsPressed("console.toggle"))
|
||||||
{
|
{
|
||||||
g_Console->InsertChar(sym, 0);
|
console.InsertChar(sym, 0);
|
||||||
return Input::Reaction::HANDLED;
|
return Input::Reaction::HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ public:
|
|||||||
|
|
||||||
void UpdateScreenSize(int w, int h);
|
void UpdateScreenSize(int w, int h);
|
||||||
|
|
||||||
void ToggleVisible();
|
|
||||||
void SetVisible(bool visible);
|
void SetVisible(bool visible);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,14 +63,10 @@ public:
|
|||||||
|
|
||||||
void Render(CCanvas2D& canvas);
|
void Render(CCanvas2D& canvas);
|
||||||
|
|
||||||
void InsertChar(const int szChar, const wchar_t cooked);
|
|
||||||
|
|
||||||
void InsertMessage(const std::string& message);
|
void InsertMessage(const std::string& message);
|
||||||
|
|
||||||
void SetBuffer(const wchar_t* szMessage);
|
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();
|
void FlushBuffer();
|
||||||
|
|
||||||
bool IsActive() const { return m_Visible; }
|
bool IsActive() const { return m_Visible; }
|
||||||
@@ -115,6 +110,8 @@ private:
|
|||||||
bool m_QuitHotkeyWasShown; // show console.toggle hotkey values at first time
|
bool m_QuitHotkeyWasShown; // show console.toggle hotkey values at first time
|
||||||
double m_CursorBlinkRate; // cursor blink rate in seconds, if greater than 0.0
|
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 DrawWindow(CCanvas2D& canvas);
|
||||||
void DrawHistory(CTextRenderer& textRenderer);
|
void DrawHistory(CTextRenderer& textRenderer);
|
||||||
void DrawBuffer(CTextRenderer& textRenderer);
|
void DrawBuffer(CTextRenderer& textRenderer);
|
||||||
@@ -131,11 +128,15 @@ private:
|
|||||||
|
|
||||||
void LoadHistory();
|
void LoadHistory();
|
||||||
void SaveHistory();
|
void SaveHistory();
|
||||||
void ShowQuitHotkeys();
|
|
||||||
|
struct InputHandler
|
||||||
|
{
|
||||||
|
CConsole& console;
|
||||||
|
Input::Reaction operator()(const SDL_Event& ev);
|
||||||
|
};
|
||||||
|
Input::Handler<InputHandler> m_InputHandler;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CConsole* g_Console;
|
extern CConsole* g_Console;
|
||||||
|
|
||||||
extern Input::Reaction conInputHandler(const SDL_Event& ev);
|
|
||||||
|
|
||||||
#endif // INCLUDED_CCONSOLE
|
#endif // INCLUDED_CCONSOLE
|
||||||
|
|||||||
@@ -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
|
// hotkey handler so that input boxes can be typed in without
|
||||||
// setting off hotkeys.
|
// setting off hotkeys.
|
||||||
handlers->emplace(g_VideoMode.m_InputManager, Input::Slot::GUI, gui_handler);
|
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);
|
handlers->emplace(g_VideoMode.m_InputManager, Input::Slot::TOUCH_INPUT, touch_input_handler);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user