From a62562dcf80239e785bbc86b0918fb45b8dd4d0d Mon Sep 17 00:00:00 2001 From: matheusvb3 <98937378+matheusvb3@users.noreply.github.com> Date: Fri, 21 Feb 2025 10:41:52 -0300 Subject: [PATCH] Add Ctrl+X (cut) command and numpad navigation to text composition (#23720) --- distribution/changelog.txt | 1 + src/openrct2-ui/TextComposition.cpp | 99 ++++++++++++++++++++++------- src/openrct2-ui/TextComposition.h | 3 - src/openrct2-ui/UiContext.cpp | 4 +- 4 files changed, 80 insertions(+), 27 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 570a65b337..260e9abb90 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -2,6 +2,7 @@ ------------------------------------------------------------------------ - Feature: [#22905] Add diagonal downward-inclined brakes to hybrid coaster and single rail coaster. - Improved: [#23677] Building new ride track now inherits the colour scheme from the previous piece. +- Improved: [#23720] Text fields now allow cutting to clipboard (Ctrl+X) in addition to copy and paste. - Fix: [#1972, #11679] Vehicles passing by toilets can cause them to glitch (original bug). - Fix: [#9999, #10000, #10001, #10002, #10003] Truncated scenario strings when using Catalan, Czech, Japanese, Polish or Russian. - Fix: [#14486] Guests will fall through upwards sloped paths when making their way through a park entrance or ride exit (original bug). diff --git a/src/openrct2-ui/TextComposition.cpp b/src/openrct2-ui/TextComposition.cpp index 3b59e59222..1063f69da3 100644 --- a/src/openrct2-ui/TextComposition.cpp +++ b/src/openrct2-ui/TextComposition.cpp @@ -23,9 +23,9 @@ #ifdef __MACOSX__ // macOS uses COMMAND rather than CTRL for many keyboard shortcuts - #define KEYBOARD_PRIMARY_MODIFIER KMOD_GUI + #define KB_PRIMARY_MODIFIER KMOD_GUI #else - #define KEYBOARD_PRIMARY_MODIFIER KMOD_CTRL + #define KB_PRIMARY_MODIFIER KMOD_CTRL #endif using namespace OpenRCT2; @@ -56,6 +56,56 @@ void TextComposition::Stop() _imeActive = false; } +/** + * Remaps keypad enter keypress to normal enter and the numpad keys that can be used for navigation when num lock is off. + * @return A pair with the remapped keycode and scancode. + */ +static std::pair ProcessKeyPress(SDL_Keycode key, SDL_Scancode scancode) +{ + if (key == SDLK_KP_ENTER) + { + key = SDLK_RETURN; + scancode = SDL_SCANCODE_RETURN; + } + else if (!(SDL_GetModState() & KMOD_NUM)) + { + switch (key) + { + case SDLK_KP_1: + { + key = SDLK_END; + scancode = SDL_SCANCODE_END; + break; + } + case SDLK_KP_4: + { + key = SDLK_LEFT; + scancode = SDL_SCANCODE_LEFT; + break; + } + case SDLK_KP_6: + { + key = SDLK_RIGHT; + scancode = SDL_SCANCODE_RIGHT; + break; + } + case SDLK_KP_7: + { + key = SDLK_HOME; + scancode = SDL_SCANCODE_HOME; + break; + } + case SDLK_KP_PERIOD: + { + key = SDLK_DELETE; + scancode = SDL_SCANCODE_DELETE; + break; + } + } + } + return { key, scancode }; +} + void TextComposition::HandleMessage(const SDL_Event* e) { auto& console = GetInGameConsole(); @@ -84,7 +134,7 @@ void TextComposition::HandleMessage(const SDL_Event* e) Insert(e->text.text); console.RefreshCaret(_session.SelectionStart); - OpenRCT2::Ui::Windows::WindowUpdateTextbox(); + Windows::WindowUpdateTextbox(); } break; case SDL_KEYDOWN: @@ -95,14 +145,10 @@ void TextComposition::HandleMessage(const SDL_Event* e) } uint16_t modifier = e->key.keysym.mod; - SDL_Keycode key = e->key.keysym.sym; - SDL_Scancode scancode = e->key.keysym.scancode; - if (key == SDLK_KP_ENTER) - { - // Map Keypad enter to regular enter. - key = SDLK_RETURN; - scancode = SDL_SCANCODE_RETURN; - } + SDL_Keycode rawKey = e->key.keysym.sym; + SDL_Scancode rawScancode = e->key.keysym.scancode; + + auto [key, scancode] = ProcessKeyPress(rawKey, rawScancode); GetContext()->GetUiContext()->SetKeysPressed(key, scancode); @@ -119,7 +165,7 @@ void TextComposition::HandleMessage(const SDL_Event* e) if (_session.SelectionStart > 0) { size_t endOffset = _session.SelectionStart; - if (modifier & KEYBOARD_PRIMARY_MODIFIER) + if (modifier & KB_PRIMARY_MODIFIER) CaretMoveToLeftToken(); else CaretMoveLeft(); @@ -127,7 +173,7 @@ void TextComposition::HandleMessage(const SDL_Event* e) Delete(); console.RefreshCaret(_session.SelectionStart); - OpenRCT2::Ui::Windows::WindowUpdateTextbox(); + Windows::WindowUpdateTextbox(); } break; case SDLK_HOME: @@ -141,7 +187,7 @@ void TextComposition::HandleMessage(const SDL_Event* e) case SDLK_DELETE: { size_t startOffset = _session.SelectionStart; - if (modifier & KEYBOARD_PRIMARY_MODIFIER) + if (modifier & KB_PRIMARY_MODIFIER) CaretMoveToRightToken(); else CaretMoveRight(); @@ -149,40 +195,49 @@ void TextComposition::HandleMessage(const SDL_Event* e) _session.SelectionStart = startOffset; Delete(); console.RefreshCaret(_session.SelectionStart); - OpenRCT2::Ui::Windows::WindowUpdateTextbox(); + Windows::WindowUpdateTextbox(); break; } case SDLK_RETURN: - OpenRCT2::Ui::Windows::WindowCancelTextbox(); + Windows::WindowCancelTextbox(); break; case SDLK_LEFT: - if (modifier & KEYBOARD_PRIMARY_MODIFIER) + if (modifier & KB_PRIMARY_MODIFIER) CaretMoveToLeftToken(); else CaretMoveLeft(); console.RefreshCaret(_session.SelectionStart); break; case SDLK_RIGHT: - if (modifier & KEYBOARD_PRIMARY_MODIFIER) + if (modifier & KB_PRIMARY_MODIFIER) CaretMoveToRightToken(); else CaretMoveRight(); console.RefreshCaret(_session.SelectionStart); break; case SDLK_c: - if ((modifier & KEYBOARD_PRIMARY_MODIFIER) && _session.Length) + if ((modifier & KB_PRIMARY_MODIFIER) && _session.Length) { - OpenRCT2::GetContext()->GetUiContext()->SetClipboardText(_session.Buffer->c_str()); + GetContext()->GetUiContext()->SetClipboardText(_session.Buffer->c_str()); ContextShowError(STR_COPY_INPUT_TO_CLIPBOARD, kStringIdNone, {}); } break; case SDLK_v: - if ((modifier & KEYBOARD_PRIMARY_MODIFIER) && SDL_HasClipboardText()) + if ((modifier & KB_PRIMARY_MODIFIER) && SDL_HasClipboardText()) { utf8* text = SDL_GetClipboardText(); Insert(text); SDL_free(text); - OpenRCT2::Ui::Windows::WindowUpdateTextbox(); + Windows::WindowUpdateTextbox(); + } + break; + case SDLK_x: + if ((modifier & KB_PRIMARY_MODIFIER) && _session.Length) + { + GetContext()->GetUiContext()->SetClipboardText(_session.Buffer->c_str()); + Clear(); + Windows::WindowUpdateTextbox(); + ContextShowError(STR_COPY_INPUT_TO_CLIPBOARD, kStringIdNone, {}); } break; } diff --git a/src/openrct2-ui/TextComposition.h b/src/openrct2-ui/TextComposition.h index ddad7f1deb..0d09d2be45 100644 --- a/src/openrct2-ui/TextComposition.h +++ b/src/openrct2-ui/TextComposition.h @@ -15,9 +15,6 @@ union SDL_Event; namespace OpenRCT2::Ui { - /** - * Represents a - */ class TextComposition { private: diff --git a/src/openrct2-ui/UiContext.cpp b/src/openrct2-ui/UiContext.cpp index e724c685d6..394a14e83d 100644 --- a/src/openrct2-ui/UiContext.cpp +++ b/src/openrct2-ui/UiContext.cpp @@ -61,9 +61,9 @@ using namespace OpenRCT2::Ui; #ifdef __MACOSX__ // macOS uses COMMAND rather than CTRL for many keyboard shortcuts - #define KEYBOARD_PRIMARY_MODIFIER KMOD_GUI + #define KB_PRIMARY_MODIFIER KMOD_GUI #else - #define KEYBOARD_PRIMARY_MODIFIER KMOD_CTRL + #define KB_PRIMARY_MODIFIER KMOD_CTRL #endif class UiContext final : public IUiContext