Skip to content

Commit

Permalink
Merge pull request #19505 from hrydgard/chat-input-fix
Browse files Browse the repository at this point in the history
iOS Chat input fix
  • Loading branch information
hrydgard authored Oct 2, 2024
2 parents 144f288 + cb06ac4 commit 94b76e4
Showing 8 changed files with 115 additions and 38 deletions.
2 changes: 1 addition & 1 deletion Common/UI/View.cpp
Original file line number Diff line number Diff line change
@@ -1329,7 +1329,7 @@ bool TextEdit::Key(const KeyInput &input) {

// Process chars.
if (input.flags & KEY_CHAR) {
int unichar = input.keyCode;
const int unichar = input.keyCode;
if (unichar >= 0x20 && !ctrlDown_) { // Ignore control characters.
// Insert it! (todo: do it with a string insert)
char buf[8];
1 change: 1 addition & 0 deletions GPU/Common/PresentationCommon.h
Original file line number Diff line number Diff line change
@@ -106,6 +106,7 @@ class PresentationCommon {
}
void NotifyPresent() {
// Something else did the present, skipping PresentationCommon.
// If you haven't called BindFramebufferAsRenderTarget, you must not set this.
presentedThisFrame_ = true;
}

7 changes: 7 additions & 0 deletions GPU/Common/ReplacedTexture.cpp
Original file line number Diff line number Diff line change
@@ -199,6 +199,8 @@ inline uint32_t RoundUpTo4(uint32_t value) {
}

void ReplacedTexture::Prepare(VFSBackend *vfs) {
_assert_(vfs != nullptr);

this->vfs_ = vfs;

std::unique_lock<std::mutex> lock(lock_);
@@ -295,6 +297,11 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference
data_.resize(mipLevel + 1);
}

if (!vfs_) {
ERROR_LOG(Log::G3D, "Unexpected null vfs_ pointer in LoadLevelData");
return LoadLevelResult::LOAD_ERROR;
}

ReplacedTextureLevel level;
size_t fileSize;
VFSOpenFile *openFile = vfs_->OpenFileForRead(fileRef, &fileSize);
38 changes: 37 additions & 1 deletion SDL/SDLMain.cpp
Original file line number Diff line number Diff line change
@@ -100,6 +100,10 @@ static bool g_rebootEmuThread = false;

static SDL_AudioSpec g_retFmt;

static bool g_textFocusChanged;
static bool g_textFocus;


// Window state to be transferred to the main SDL thread.
static std::mutex g_mutexWindow;
struct WindowState {
@@ -347,6 +351,23 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
#endif /* PPSSPP_PLATFORM(WINDOWS) */
return true;
}
case SystemRequestType::NOTIFY_UI_EVENT:
{
switch ((UIEventNotification)param3) {
case UIEventNotification::TEXT_GOTFOCUS:
g_textFocus = true;
g_textFocusChanged = true;
break;
case UIEventNotification::POPUP_CLOSED:
case UIEventNotification::TEXT_LOSTFOCUS:
g_textFocus = false;
g_textFocusChanged = true;
break;
default:
break;
}
return true;
}
default:
return false;
}
@@ -1087,6 +1108,18 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
}
}

void UpdateTextFocus() {
if (g_textFocusChanged) {
INFO_LOG(Log::System, "Updating text focus: %d", g_textFocus);
if (g_textFocus) {
SDL_StartTextInput();
} else {
SDL_StopTextInput();
}
g_textFocusChanged = false;
}
}

void UpdateSDLCursor() {
#if !defined(MOBILE_DEVICE)
if (lastUIState != GetUIState()) {
@@ -1428,7 +1461,8 @@ int main(int argc, char *argv[]) {
#endif

// Avoid the IME popup when holding keys. This doesn't affect all versions of SDL.
// TODO: Enable it in text input fields
// Note: We re-enable it in text input fields! This is necessary otherwise we don't receive
// KEY_CHAR events.
SDL_StopTextInput();

InitSDLAudioDevice();
@@ -1465,6 +1499,7 @@ int main(int argc, char *argv[]) {
if (g_QuitRequested || g_RestartRequested)
break;

UpdateTextFocus();
UpdateSDLCursor();

inputTracker.MouseCaptureControl();
@@ -1491,6 +1526,7 @@ int main(int argc, char *argv[]) {
if (g_QuitRequested || g_RestartRequested)
break;

UpdateTextFocus();
UpdateSDLCursor();

inputTracker.MouseCaptureControl();
54 changes: 40 additions & 14 deletions UI/ChatScreen.cpp
Original file line number Diff line number Diff line change
@@ -15,21 +15,28 @@
#include "Core/System.h"
#include "Core/HLE/proAdhoc.h"
#include "UI/ChatScreen.h"
#include "UI/PopupScreens.h"

void ChatMenu::CreateContents(UI::ViewGroup *parent) {
using namespace UI;
auto n = GetI18NCategory(I18NCat::NETWORKING);
LinearLayout *outer = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT,400));
scroll_ = outer->Add(new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 1.0)));
LinearLayout *bottom = outer->Add(new LinearLayout(ORIENT_HORIZONTAL, new LayoutParams(FILL_PARENT, WRAP_CONTENT)));
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(SDL)
chatEdit_ = bottom->Add(new TextEdit("", n->T("Chat message"), n->T("Chat Here"), new LinearLayoutParams(1.0)));
chatEdit_->OnEnter.Handle(this, &ChatMenu::OnSubmit);

#elif PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(IOS)
bottom->Add(new Button(n->T("Chat Here"),new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->OnClick.Handle(this, &ChatMenu::OnSubmit);
bottom->Add(new Button(n->T("Send")))->OnClick.Handle(this, &ChatMenu::OnSubmit);
#endif
chatButton_ = nullptr;
chatEdit_ = nullptr;
chatVert_ = nullptr;

if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_DESKTOP) {
// We have direct keyboard input.
chatEdit_ = bottom->Add(new TextEdit("", n->T("Chat message"), n->T("Chat Here"), new LinearLayoutParams(1.0)));
chatEdit_->OnEnter.Handle(this, &ChatMenu::OnSubmitMessage);
} else {
// If we have a native input box, like on Android, or at least we can do a popup text input with our UI...
chatButton_ = bottom->Add(new Button(n->T("Chat message"), new LayoutParams(FILL_PARENT, WRAP_CONTENT)));
chatButton_->OnClick.Handle(this, &ChatMenu::OnAskForChatMessage);
}

if (g_Config.bEnableQuickChat) {
LinearLayout *quickChat = outer->Add(new LinearLayout(ORIENT_HORIZONTAL, new LayoutParams(FILL_PARENT, WRAP_CONTENT)));
@@ -89,18 +96,37 @@ void ChatMenu::CreateSubviews(const Bounds &screenBounds) {
UpdateChat();
}

UI::EventReturn ChatMenu::OnSubmit(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || (defined(SDL) && !PPSSPP_PLATFORM(SWITCH))
UI::EventReturn ChatMenu::OnSubmitMessage(UI::EventParams &e) {
std::string chat = chatEdit_->GetText();
chatEdit_->SetText("");
chatEdit_->SetFocus();
sendChat(chat);
#elif PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) || PPSSPP_PLATFORM(IOS)
return UI::EVENT_DONE;
}

UI::EventReturn ChatMenu::OnAskForChatMessage(UI::EventParams &e) {
auto n = GetI18NCategory(I18NCat::NETWORKING);
System_InputBoxGetString(token_, n->T("Chat"), "", false, [](const std::string &value, int) {
sendChat(value);
});
#endif

using namespace UI;

if (System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) {
System_InputBoxGetString(token_, n->T("Chat"), "", false, [](const std::string &value, int) {
sendChat(value);
});
} else {
// We need to pop up a UI inputbox.
messageTemp_.clear();
TextEditPopupScreen *popupScreen = new TextEditPopupScreen(&messageTemp_, "", n->T("Chat message"), 256);
if (System_GetPropertyBool(SYSPROP_KEYBOARD_IS_SOFT)) {
popupScreen->SetAlignTop(true);
}
popupScreen->OnChange.Add([=](UI::EventParams &e) {
sendChat(messageTemp_);
return UI::EVENT_DONE;
});
popupScreen->SetPopupOrigin(chatButton_);
screenManager_->push(popupScreen);
}
return UI::EVENT_DONE;
}

13 changes: 8 additions & 5 deletions UI/ChatScreen.h
Original file line number Diff line number Diff line change
@@ -5,8 +5,8 @@

class ChatMenu : public UI::AnchorLayout {
public:
ChatMenu(int token, const Bounds &screenBounds, UI::LayoutParams *lp = nullptr)
: UI::AnchorLayout(lp), token_(token) {
ChatMenu(int token, const Bounds &screenBounds, ScreenManager *screenManager, UI::LayoutParams *lp = nullptr)
: UI::AnchorLayout(lp), screenManager_(screenManager), token_(token) {
CreateSubviews(screenBounds);
}
void Update() override;
@@ -25,22 +25,25 @@ class ChatMenu : public UI::AnchorLayout {
void CreateContents(UI::ViewGroup *parent);
void UpdateChat();

UI::EventReturn OnSubmit(UI::EventParams &e);
UI::EventReturn OnAskForChatMessage(UI::EventParams &e);

UI::EventReturn OnSubmitMessage(UI::EventParams &e);
UI::EventReturn OnQuickChat1(UI::EventParams &e);
UI::EventReturn OnQuickChat2(UI::EventParams &e);
UI::EventReturn OnQuickChat3(UI::EventParams &e);
UI::EventReturn OnQuickChat4(UI::EventParams &e);
UI::EventReturn OnQuickChat5(UI::EventParams &e);

#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(SDL)
UI::TextEdit *chatEdit_ = nullptr;
#endif
UI::ScrollView *scroll_ = nullptr;
UI::LinearLayout *chatVert_ = nullptr;
UI::ViewGroup *box_ = nullptr;
ScreenManager *screenManager_;

int chatChangeID_ = 0;
bool toBottom_ = true;
bool promptInput_ = false;
int token_;
std::string messageTemp_;
UI::Button *chatButton_ = nullptr;
};
28 changes: 16 additions & 12 deletions UI/EmuScreen.cpp
Original file line number Diff line number Diff line change
@@ -468,6 +468,11 @@ EmuScreen::~EmuScreen() {
}

void EmuScreen::dialogFinished(const Screen *dialog, DialogResult result) {
if (std::string_view(dialog->tag()) == "TextEditPopup") {
// Chat message finished.
return;
}

// TODO: improve the way with which we got commands from PauseMenu.
// DR_CANCEL/DR_BACK means clicked on "continue", DR_OK means clicked on "back to menu",
// DR_YES means a message sent to PauseMenu by System_PostUIMessage.
@@ -584,19 +589,19 @@ void EmuScreen::sendMessage(UIMessage message, const char *value) {
if (!chatButton_)
RecreateViews();

#if defined(USING_WIN_UI)
// temporary workaround for hotkey its freeze the ui when open chat screen using hotkey and native keyboard is enable
if (g_Config.bBypassOSKWithKeyboard) {
// TODO: Make translatable.
g_OSD.Show(OSDType::MESSAGE_INFO, "Disable \"Use system native keyboard\" to use ctrl + c hotkey", 2.0f);
if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_DESKTOP) {
// temporary workaround for hotkey its freeze the ui when open chat screen using hotkey and native keyboard is enable
if (g_Config.bBypassOSKWithKeyboard) {
// TODO: Make translatable.
g_OSD.Show(OSDType::MESSAGE_INFO, "Disable \"Use system native keyboard\" to use ctrl + c hotkey", 2.0f);
} else {
UI::EventParams e{};
OnChatMenu.Trigger(e);
}
} else {
UI::EventParams e{};
OnChatMenu.Trigger(e);
}
#else
UI::EventParams e{};
OnChatMenu.Trigger(e);
#endif
}
} else if (message == UIMessage::APP_RESUMED && screenManager()->topScreen() == this) {
if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_TV) {
@@ -930,7 +935,6 @@ bool EmuScreen::UnsyncKey(const KeyInput &key) {
if (UI::IsFocusMovementEnabled()) {
return UIScreen::UnsyncKey(key);
}

return controlMapper_.Key(key, &pauseTrigger_);
}

@@ -1055,7 +1059,7 @@ void EmuScreen::CreateViews() {
root_->Add(btn)->OnClick.Handle(this, &EmuScreen::OnChat);
chatButton_ = btn;
}
chatMenu_ = root_->Add(new ChatMenu(GetRequesterToken(), screenManager()->getUIContext()->GetBounds(), new LayoutParams(FILL_PARENT, FILL_PARENT)));
chatMenu_ = root_->Add(new ChatMenu(GetRequesterToken(), screenManager()->getUIContext()->GetBounds(), screenManager(), new LayoutParams(FILL_PARENT, FILL_PARENT)));
chatMenu_->SetVisibility(UI::V_GONE);
} else {
chatButton_ = nullptr;
@@ -1464,8 +1468,8 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
if (!framebufferBound && PSP_IsInited()) {
// draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR, clearColor }, "EmuScreen_Stepping");
gpu->CopyDisplayToOutput(true);
framebufferBound = true;
}
framebufferBound = true;
}
break;
}
10 changes: 5 additions & 5 deletions UI/PauseScreen.cpp
Original file line number Diff line number Diff line change
@@ -380,9 +380,9 @@ void GamePauseScreen::CreateViews() {
leftColumnItems->Add(new NoticeView(NoticeLevel::INFO, notAvailable, ""));
}

ViewGroup *middleColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(64, FILL_PARENT, Margins(0, 10, 0, 15)));
LinearLayout *middleColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(64, FILL_PARENT, Margins(0, 10, 0, 15)));
root_->Add(middleColumn);

middleColumn->SetSpacing(0.0f);
ViewGroup *rightColumnHolder = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(vertical ? 200 : 300, FILL_PARENT, actionMenuMargins));

ViewGroup *rightColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0f));
@@ -404,7 +404,7 @@ void GamePauseScreen::CreateViews() {
root_->SetDefaultFocusView(continueChoice);
continueChoice->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);

rightColumnItems->Add(new Spacer(25.0));
rightColumnItems->Add(new Spacer(20.0));

std::string gameId = g_paramSFO.GetDiscID();
if (g_Config.hasGameConfig(gameId)) {
@@ -438,7 +438,7 @@ void GamePauseScreen::CreateViews() {
auto rp = GetI18NCategory(I18NCat::REPORTING);
rightColumnItems->Add(new Choice(rp->T("ReportButton", "Report Feedback")))->OnClick.Handle(this, &GamePauseScreen::OnReportFeedback);
}
rightColumnItems->Add(new Spacer(25.0));
rightColumnItems->Add(new Spacer(20.0));
if (g_Config.bPauseMenuExitsEmulator) {
auto mm = GetI18NCategory(I18NCat::MAINMENU);
rightColumnItems->Add(new Choice(mm->T("Exit")))->OnClick.Handle(this, &GamePauseScreen::OnExitToMenu);
@@ -453,7 +453,7 @@ void GamePauseScreen::CreateViews() {
playButton_->SetImageID(g_Config.bRunBehindPauseMenu ? ImageID("I_PAUSE") : ImageID("I_PLAY"));
return UI::EVENT_DONE;
});

middleColumn->Add(new Spacer(20.0));
Button *infoButton = middleColumn->Add(new Button("", ImageID("I_INFO"), new LinearLayoutParams(64, 64)));
infoButton->OnClick.Add([=](UI::EventParams &e) {
screenManager()->push(new GameScreen(gamePath_, true));

0 comments on commit 94b76e4

Please sign in to comment.