From ea4c46f27c0b87658cf58f595779aa8e9bbbde0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 4 May 2026 14:29:26 +0200 Subject: [PATCH] Add ability to set keyboard focus to specific screens. Needed for searchbar on Mac. --- Common/UI/PopupScreens.cpp | 9 +++++++++ Common/UI/PopupScreens.h | 3 +-- Common/UI/Screen.cpp | 18 ++++++++++++++++-- Common/UI/Screen.h | 1 + Common/UI/UIScreen.h | 1 + UI/CwCheatScreen.h | 2 ++ UI/MainScreen.h | 1 + UI/MiscViews.cpp | 5 ++++- UI/MiscViews.h | 2 +- 9 files changed, 36 insertions(+), 6 deletions(-) diff --git a/Common/UI/PopupScreens.cpp b/Common/UI/PopupScreens.cpp index 3578a3b138..e339f45976 100644 --- a/Common/UI/PopupScreens.cpp +++ b/Common/UI/PopupScreens.cpp @@ -949,6 +949,15 @@ ViewGroup *CreateSoftKeyboard(TextEdit *edit, SoftKeyboardState *state) { return scrollView; } +TextEditPopupScreen::TextEditPopupScreen(std::string *value, std::string_view placeholder, std::string_view title, int maxLen) + : PopupScreen(title, T(I18NCat::DIALOG, "OK"), T(I18NCat::DIALOG, "Cancel")), value_(value), placeholder_(placeholder), maxLen_(maxLen) { + if (!value_) { + // Point it to our temporary. + value_ = &textEditValue_; + } +} + + void TextEditPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; UIContext &dc = *screenManager()->getUIContext(); diff --git a/Common/UI/PopupScreens.h b/Common/UI/PopupScreens.h index 0afc183505..ec86de344d 100644 --- a/Common/UI/PopupScreens.h +++ b/Common/UI/PopupScreens.h @@ -233,8 +233,7 @@ ViewGroup *CreateSoftKeyboard(TextEdit *edit, SoftKeyboardState *state); class TextEditPopupScreen : public PopupScreen { public: - TextEditPopupScreen(std::string *value, std::string_view placeholder, std::string_view title, int maxLen) - : PopupScreen(title, T(I18NCat::DIALOG, "OK"), T(I18NCat::DIALOG, "Cancel")), value_(value), placeholder_(placeholder), maxLen_(maxLen) {} + TextEditPopupScreen(std::string *value, std::string_view placeholder, std::string_view title, int maxLen); void CreatePopupContents(ViewGroup *parent) override; const char *tag() const override { return "TextEditPopup"; } diff --git a/Common/UI/Screen.cpp b/Common/UI/Screen.cpp index 4dc7e0aa90..733cdb3293 100644 --- a/Common/UI/Screen.cpp +++ b/Common/UI/Screen.cpp @@ -15,8 +15,22 @@ void Screen::focusChanged(ScreenFocusChange focusChange) { const char *eventName = ""; switch (focusChange) { - case ScreenFocusChange::FOCUS_LOST_TOP: eventName = "FOCUS_LOST_TOP"; break; - case ScreenFocusChange::FOCUS_BECAME_TOP: eventName = "FOCUS_BECAME_TOP"; break; + case ScreenFocusChange::FOCUS_LOST_TOP: + #if !defined(MOBILE_DEVICE) + if (WantsTextInput()) { + System_NotifyUIEvent(UIEventNotification::TEXT_LOSTFOCUS); + } + #endif + eventName = "FOCUS_LOST_TOP"; + break; + case ScreenFocusChange::FOCUS_BECAME_TOP: + #if !defined(MOBILE_DEVICE) + if (WantsTextInput()) { + System_NotifyUIEvent(UIEventNotification::TEXT_GOTFOCUS); + } + #endif + eventName = "FOCUS_BECAME_TOP"; + break; } DEBUG_LOG(Log::UI, "Screen %s got %s", this->tag(), eventName); } diff --git a/Common/UI/Screen.h b/Common/UI/Screen.h index 20d25ca069..8d4dd3f546 100644 --- a/Common/UI/Screen.h +++ b/Common/UI/Screen.h @@ -113,6 +113,7 @@ public: virtual bool isTopLevel() const { return false; } virtual TouchInput transformTouch(const TouchInput &touch) { return touch; } + virtual bool WantsTextInput() const { return false; } protected: int GetRequesterToken(); diff --git a/Common/UI/UIScreen.h b/Common/UI/UIScreen.h index 0db7454d9b..046c4a9f1d 100644 --- a/Common/UI/UIScreen.h +++ b/Common/UI/UIScreen.h @@ -75,6 +75,7 @@ public: virtual UI::Margins RootMargins() const { return UI::Margins(0); } virtual void focusChanged(ScreenFocusChange focusChange) override { + Screen::focusChanged(focusChange); modifiersPressed_ = Modifier::NONE; } diff --git a/UI/CwCheatScreen.h b/UI/CwCheatScreen.h index 55088bb9b0..72849b7823 100644 --- a/UI/CwCheatScreen.h +++ b/UI/CwCheatScreen.h @@ -50,6 +50,8 @@ public: const char *tag() const override { return "CwCheat"; } + bool WantsTextInput() const override { return true; } + protected: void BeforeCreateViews() override; void CreateSettingsViews(UI::ViewGroup *) override; diff --git a/UI/MainScreen.h b/UI/MainScreen.h index 4167cc2830..72c1e3d41e 100644 --- a/UI/MainScreen.h +++ b/UI/MainScreen.h @@ -52,6 +52,7 @@ public: bool key(const KeyInput &touch) override; + bool WantsTextInput() const override { return true; } protected: ViewLayoutMode LayoutMode() const override { return ViewLayoutMode::IgnoreBottomInset; } diff --git a/UI/MiscViews.cpp b/UI/MiscViews.cpp index 9a35010780..1907ed4ae2 100644 --- a/UI/MiscViews.cpp +++ b/UI/MiscViews.cpp @@ -325,6 +325,10 @@ void SearchBar::Draw(UIContext &dc) { dc.DrawText(searchFilter_, bounds_.x + leftMargin, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); } +SearchBar::SearchBar(UI::LayoutParams *params) : UI::InertView(params) { + SetVisibility(UI::Visibility::V_GONE); +} + void SearchBar::GetContentDimensions(const UIContext &dc, float &w, float &h) const { w = 0; h = 0; @@ -439,7 +443,6 @@ bool ViewSearch::Key(UI::ViewGroup *viewGroup, const KeyInput &input) { const int unichar = input.keyCode; if (unichar >= 0x20 && unichar != 127) { // 127 gets produced from Ctrl+Backspace on Windows for some reason. // TODO: Save focus state here. - // Insert it! (todo: do it with a string insert) char buf[8]; buf[u8_wc_toutf8(buf, unichar)] = '\0'; diff --git a/UI/MiscViews.h b/UI/MiscViews.h index 120bfa809a..709a7bf0da 100644 --- a/UI/MiscViews.h +++ b/UI/MiscViews.h @@ -103,7 +103,7 @@ void AddRotationPicker(ScreenManager *screenManager, UI::ViewGroup *parent, bool class SearchBar : public UI::InertView { public: - SearchBar(UI::LayoutParams *params) : UI::InertView(params) { SetVisibility(UI::Visibility::V_GONE); } + SearchBar(UI::LayoutParams *params); void Draw(UIContext &dc) override; bool Touch(const TouchInput &input) override;