OSK support final update

- Renamed few functions to avoid confusion
- Now UI will report text (gotfocus, lostfocus), popup_closed to the frontend
- Both cases (DPad, Keyboard) covered
This commit is contained in:
Bashar Astifan 2023-08-24 06:33:36 +04:00
parent 3225446ff6
commit 4e2652bd4b
6 changed files with 110 additions and 64 deletions

View File

@ -391,8 +391,8 @@ void PopupScreen::TriggerFinish(DialogResult result) {
OnCompleted(result);
}
#if PPSSPP_PLATFORM(UWP)
// Inform UI to hide OSK and to disable keyboard mode
System_NotifyUIState("hide_keyboard");
// Inform UI that popup close to hide OSK (if visible)
System_NotifyUIState("popup_closed");
#endif
}

View File

@ -1086,13 +1086,10 @@ TextEdit::TextEdit(const std::string &text, const std::string &title, const std:
void TextEdit::FocusChanged(int focusFlags) {
#if PPSSPP_PLATFORM(UWP)
if (focusFlags == FF_GOTFOCUS) {
System_NotifyUIState("show_keyboard");
System_NotifyUIState("text_gotfocus");
}
else {
// OSK will be hidden by `Back` button and no reason to check focus
if (!isInputPaneVisible()) {
System_NotifyUIState("hide_keyboard");
}
System_NotifyUIState("text_lostfocus");
}
#endif
}

View File

@ -1271,7 +1271,7 @@ bool NativeKey(const KeyInput &key) {
}
#if PPSSPP_PLATFORM(UWP)
// Ignore if key sent from OnKeyDown/OnKeyUp/XInput while keyboard mode active
// Ignore if key sent from OnKeyDown/OnKeyUp/XInput while text edit active
// it's already handled by `OnCharacterReceived`
if (IgnoreInput(key.keyCode) && !(key.flags & KEY_CHAR)) {
return false;

View File

@ -192,6 +192,9 @@ void PPSSPP_UWPMain::OnDeviceRestored() {
void PPSSPP_UWPMain::OnKeyDown(int scanCode, Windows::System::VirtualKey virtualKey, int repeatCount) {
// TODO: Look like (Ctrl, Alt, Shift) don't trigger this event
bool isDPad = (int)virtualKey >= 195 && (int)virtualKey <= 218; // DPad buttons range
DPadInputState(isDPad);
auto iter = virtualKeyCodeToNKCode.find(virtualKey);
if (iter != virtualKeyCodeToNKCode.end()) {
KeyInput key{};
@ -216,7 +219,7 @@ void PPSSPP_UWPMain::OnKeyUp(int scanCode, Windows::System::VirtualKey virtualKe
void PPSSPP_UWPMain::OnCharacterReceived(int scanCode, unsigned int keyCode) {
// This event triggered only in chars case, (Arrows, Delete..etc don't call it)
// TODO: Add ` && !IsCtrlOnHold()` once it's ready and implemented
if (isKeyboardActive()) {
if (isTextEditActive()) {
KeyInput key{};
key.deviceId = DEVICE_ID_KEYBOARD;
key.keyCode = (InputKeyCode)keyCode;
@ -426,7 +429,7 @@ bool System_GetPropertyBool(SystemProperty prop) {
// Do actual check
// touch devices has input pane, we need to depend on it
// I don't know any possible way to display input dialog in non-xaml apps
return isKeybaordAvailable() || isTouchAvailable();
return isKeyboardAvailable() || isTouchAvailable();
}
default:
return false;
@ -536,26 +539,19 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
}
case SystemRequestType::NOTIFY_UI_STATE:
{
if (!param1.empty() && !strcmp(param1.c_str(), "menu")) {
CloseLaunchItem();
}
else if (!strcmp(param1.c_str(), "show_keyboard")) {
// Must be performed from UI thread
Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
CoreDispatcherPriority::Normal,
ref new Windows::UI::Core::DispatchedHandler([]()
{
ActivateKeyboardInput();
}));
}
else if (!strcmp(param1.c_str(), "hide_keyboard")) {
// Must be performed from UI thread
Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
CoreDispatcherPriority::Normal,
ref new Windows::UI::Core::DispatchedHandler([]()
{
DeactivateKeyboardInput();
}));
if (!param1.empty()) {
if (!strcmp(param1.c_str(), "menu")) {
CloseLaunchItem();
}
else if (!strcmp(param1.c_str(), "popup_closed")) {
DeactivateTextEditInput();
}
else if (!strcmp(param1.c_str(), "text_gotfocus")) {
ActivateTextEditInput(true);
}
else if (!strcmp(param1.c_str(), "text_lostfocus")) {
DeactivateTextEditInput(true);
}
}
return true;
}

View File

@ -41,9 +41,8 @@ bool findInList(std::list<T>& inputList, T& str) {
};
#pragma endregion
#pragma region Input Keyboard
bool isKeybaordAvailable() {
#pragma region Input Devices
bool isKeyboardAvailable() {
Windows::Devices::Input::KeyboardCapabilities^ keyboardCapabilities = ref new Windows::Devices::Input::KeyboardCapabilities();
bool hasKeyboard = keyboardCapabilities->KeyboardPresent != 0;
return hasKeyboard;
@ -54,8 +53,12 @@ bool isTouchAvailable() {
bool hasTouch = touchCapabilities->TouchPresent != 0;
return hasTouch;
}
#pragma endregion
bool keyboardActive = false;
#pragma region Input Keyboard
bool dPadInputActive = false;
bool textEditActive = false;
bool inputPaneVisible = false;
Platform::Agile<Windows::UI::ViewManagement::InputPane> inputPane = nullptr;
@ -72,45 +75,87 @@ void PrepareInputPane() {
inputPane->Hiding += ref new Windows::Foundation::TypedEventHandler<InputPane^, InputPaneVisibilityEventArgs^>(&OnHiding);
}
// Show input pane (OSK)
bool ShowInputPane() {
return !isInputPaneVisible() ? inputPane->TryShow() : true;
}
// Hide input pane (OSK)
bool HideInputPane() {
return isInputPaneVisible() ? inputPane->TryHide() : true;
}
// Check if input pane (OSK) visible
bool isInputPaneVisible() {
return inputPaneVisible;
}
bool isKeyboardActive() {
return keyboardActive;
// Check if text edit active (got focus)
bool isTextEditActive() {
return textEditActive;
}
void ActivateKeyboardInput() {
DEBUG_LOG(COMMON, "Activate input keyboard");
if (inputPane->TryShow()) {
DEBUG_LOG(COMMON, "Input pane: TryShow accepted");
}
else {
DEBUG_LOG(COMMON, "Input pane: (TryShow is not accepted or pane is not supported)");
}
keyboardActive = true;
// Set if the current input is DPad
void DPadInputState(bool inputState) {
dPadInputActive = inputState;
}
void DeactivateKeyboardInput() {
DEBUG_LOG(COMMON, "Deactivate input keyboard");
if (inputPane->TryHide()) {
DEBUG_LOG(COMMON, "Input pane: TryHide accepted");
}
else {
DEBUG_LOG(COMMON, "Input pane: TryHide is not accepted, or pane is not visible");
}
keyboardActive = false;
// Check if the current input is DPad
bool isDPadActive() {
return dPadInputActive;
}
void ActivateTextEditInput(bool byFocus) {
// Must be performed from UI thread
Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
CoreDispatcherPriority::Normal,
ref new Windows::UI::Core::DispatchedHandler([=]()
{
if (byFocus) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
if (!isInputPaneVisible() && (isDPadActive() || !IsXBox())) {
if (ShowInputPane()) {
DEBUG_LOG(COMMON, "Input pane: TryShow accepted");
}
else {
DEBUG_LOG(COMMON, "Input pane: (TryShow is not accepted or not supported)");
}
}
DEBUG_LOG(COMMON, "Text edit active");
textEditActive = true;
}));
}
void DeactivateTextEditInput(bool byFocus) {
// Must be performed from UI thread
Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
CoreDispatcherPriority::Normal,
ref new Windows::UI::Core::DispatchedHandler([=]()
{
if (isInputPaneVisible()) {
if (HideInputPane()) {
DEBUG_LOG(COMMON, "Input pane: TryHide accepted");
}
else {
DEBUG_LOG(COMMON, "Input pane: TryHide is not accepted, or not supported");
}
}
if (isTextEditActive()) {
DEBUG_LOG(COMMON, "Text edit inactive");
textEditActive = false;
}
}));
}
bool IgnoreInput(int keyCode) {
// When keyboard mode active and char is passed this function return 'true'
// When text edit active and char is passed this function return 'true'
// it will help to prevent KeyDown from sending the same code again
bool ignoreInput = false;
// TODO: Add ` && !IsCtrlOnHold()` once it's ready and implemented
if (isKeyboardActive()) {
if (isTextEditActive()) {
// To avoid bothering KeyDown to check this case always
// we don't get here unless keyboard mode is active
// we don't get here unless text edit is active
std::list<int> nonCharList = {
NKCODE_CTRL_LEFT,
NKCODE_CTRL_RIGHT,
@ -127,7 +172,6 @@ bool IgnoreInput(int keyCode) {
NKCODE_EXT_MOUSEBUTTON_3,
NKCODE_EXT_MOUSEBUTTON_4,
NKCODE_EXT_MOUSEBUTTON_5,
NKCODE_ESCAPE
};
if (!isInputPaneVisible()) {
// Keyboard active but no on-screen keyboard
@ -137,6 +181,7 @@ bool IgnoreInput(int keyCode) {
nonCharList.push_back(NKCODE_DPAD_LEFT);
nonCharList.push_back(NKCODE_DPAD_RIGHT);
nonCharList.push_back(NKCODE_BACK);
nonCharList.push_back(NKCODE_ESCAPE);
}
ignoreInput = !findInList(nonCharList, keyCode);

View File

@ -19,17 +19,25 @@
#include <string>
// Input Devices
bool isKeybaordAvailable();
bool isKeyboardAvailable();
bool isTouchAvailable();
// Input Keyboard/Pane
// Input Pane
void PrepareInputPane();
bool isInputPaneVisible();
bool isKeyboardActive();
void ActivateKeyboardInput();
void DeactivateKeyboardInput();
bool ShowInputPane();
bool HideInputPane();
// Text Edit
bool isTextEditActive();
void ActivateTextEditInput(bool byFocus = false);
void DeactivateTextEditInput(bool byFocus = false);
bool IgnoreInput(int keyCode);
// Input DPad
void DPadInputState(bool inputState);
bool isDPadActive();
// Keys Status
bool IsCapsLockOn();
bool IsShiftOnHold();