mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Complete OSK function support
This commit is contained in:
parent
04d72ebe54
commit
c6e7760283
10 changed files with 216 additions and 34 deletions
|
@ -475,6 +475,10 @@ void SliderPopupScreen::OnCompleted(DialogResult result) {
|
|||
e.a = *value_;
|
||||
OnChange.Trigger(e);
|
||||
}
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
// Inform UI to hide OSK and to disable keyboard mode
|
||||
System_NotifyUIState("hide_keyboard");
|
||||
#endif
|
||||
}
|
||||
|
||||
void SliderFloatPopupScreen::OnCompleted(DialogResult result) {
|
||||
|
@ -488,6 +492,10 @@ void SliderFloatPopupScreen::OnCompleted(DialogResult result) {
|
|||
} else {
|
||||
*value_ = originalValue_;
|
||||
}
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
// Inform UI to hide OSK and to disable keyboard mode
|
||||
System_NotifyUIState("hide_keyboard");
|
||||
#endif
|
||||
}
|
||||
|
||||
PopupTextInputChoice::PopupTextInputChoice(std::string *value, const std::string &title, const std::string &placeholder, int maxLen, ScreenManager *screenManager, LayoutParams *layoutParams)
|
||||
|
@ -551,6 +559,10 @@ void TextEditPopupScreen::OnCompleted(DialogResult result) {
|
|||
e.v = edit_;
|
||||
OnChange.Trigger(e);
|
||||
}
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
// Inform UI to hide OSK and to disable keyboard mode
|
||||
System_NotifyUIState("hide_keyboard");
|
||||
#endif
|
||||
}
|
||||
|
||||
void AbstractChoiceWithValueDisplay::GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert, float &w, float &h) const {
|
||||
|
|
|
@ -272,6 +272,13 @@ static bool MatchesKeyDef(const std::vector<InputMapping> &defs, const KeyInput
|
|||
// TODO: O/X confirm preference for xperia play?
|
||||
|
||||
bool IsDPadKey(const KeyInput &key) {
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
if (key.flags & KEY_CHAR) {
|
||||
// Better not to check if flags has `KEY_CHAR`
|
||||
// many of Windows chars has similar codes to `NKCODE` actions buttons
|
||||
return false;
|
||||
}
|
||||
#endif#
|
||||
if (dpadKeys.empty()) {
|
||||
return key.keyCode >= NKCODE_DPAD_UP && key.keyCode <= NKCODE_DPAD_RIGHT;
|
||||
} else {
|
||||
|
@ -280,6 +287,13 @@ bool IsDPadKey(const KeyInput &key) {
|
|||
}
|
||||
|
||||
bool IsAcceptKey(const KeyInput &key) {
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
if (key.flags & KEY_CHAR) {
|
||||
// Better not to check if flags has `KEY_CHAR`
|
||||
// many of Windows chars has similar codes to `NKCODE` actions buttons
|
||||
return false;
|
||||
}
|
||||
#endif#
|
||||
if (confirmKeys.empty()) {
|
||||
// This path is pretty much not used, confirmKeys should be set.
|
||||
// TODO: Get rid of this stuff?
|
||||
|
@ -294,6 +308,12 @@ bool IsAcceptKey(const KeyInput &key) {
|
|||
}
|
||||
|
||||
bool IsEscapeKey(const KeyInput &key) {
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
if (key.flags & KEY_CHAR) {
|
||||
// `a` char has equal value to `NKCODE_BUTTON_CIRCLE_PS3` = 97
|
||||
return false;
|
||||
}
|
||||
#endif#
|
||||
if (cancelKeys.empty()) {
|
||||
// This path is pretty much not used, cancelKeys should be set.
|
||||
// TODO: Get rid of this stuff?
|
||||
|
@ -308,6 +328,12 @@ bool IsEscapeKey(const KeyInput &key) {
|
|||
}
|
||||
|
||||
bool IsTabLeftKey(const KeyInput &key) {
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
if (key.flags & KEY_CHAR) {
|
||||
// `f` char has equal value to `NKCODE_BUTTON_L1` = 102
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if (tabLeftKeys.empty()) {
|
||||
// This path is pretty much not used, tabLeftKeys should be set.
|
||||
// TODO: Get rid of this stuff?
|
||||
|
@ -318,6 +344,13 @@ bool IsTabLeftKey(const KeyInput &key) {
|
|||
}
|
||||
|
||||
bool IsTabRightKey(const KeyInput &key) {
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
if (key.flags & KEY_CHAR) {
|
||||
// Better not to check if flags has `KEY_CHAR`
|
||||
// many of Windows chars has similar codes to `NKCODE` actions buttons
|
||||
return false;
|
||||
}
|
||||
#endif#
|
||||
if (tabRightKeys.empty()) {
|
||||
// This path is pretty much not used, tabRightKeys should be set.
|
||||
// TODO: Get rid of this stuff?
|
||||
|
@ -1079,6 +1112,17 @@ TextEdit::TextEdit(const std::string &text, const std::string &title, const std:
|
|||
caret_ = (int)text_.size();
|
||||
}
|
||||
|
||||
void TextEdit::FocusChanged(int focusFlags) {
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
if (focusFlags == FF_GOTFOCUS) {
|
||||
System_NotifyUIState("show_keyboard");
|
||||
}
|
||||
else {
|
||||
System_NotifyUIState("hide_keyboard");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void TextEdit::Draw(UIContext &dc) {
|
||||
dc.PushScissor(bounds_);
|
||||
dc.SetFontStyle(dc.theme->uiFont);
|
||||
|
@ -1155,7 +1199,14 @@ bool TextEdit::Key(const KeyInput &input) {
|
|||
return false;
|
||||
bool textChanged = false;
|
||||
// Process hardcoded navigation keys. These aren't chars.
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
// In Windows (UWP) [chars event], some chars like `z` has equal value to `NKCODE_MOVE_HOME` = 122
|
||||
// we already excluded non-char keys from being sent as `KEY_CHAR` (in keyboard/OSK mode)
|
||||
// so if flags has `KEY_CHAR` then it's char 100%
|
||||
if (input.flags & KEY_DOWN && !(input.flags & KEY_CHAR)) {
|
||||
#else
|
||||
if (input.flags & KEY_DOWN) {
|
||||
#endif
|
||||
switch (input.keyCode) {
|
||||
case NKCODE_CTRL_LEFT:
|
||||
case NKCODE_CTRL_RIGHT:
|
||||
|
|
|
@ -971,6 +971,7 @@ public:
|
|||
void SetMaxLen(size_t maxLen) { maxLen_ = maxLen; }
|
||||
void SetTextAlign(int align) { align_ = align; } // Only really useful for setting FLAG_DYNAMIC_ASCII
|
||||
|
||||
void FocusChanged(int focusFlags) override;
|
||||
void GetContentDimensions(const UIContext &dc, float &w, float &h) const override;
|
||||
void Draw(UIContext &dc) override;
|
||||
std::string DescribeText() const override;
|
||||
|
|
|
@ -2113,6 +2113,11 @@ bool HostnameSelectScreen::CanComplete(DialogResult result) {
|
|||
void HostnameSelectScreen::OnCompleted(DialogResult result) {
|
||||
if (result == DR_OK)
|
||||
*value_ = StripSpaces(addrView_->GetText());
|
||||
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
// Inform UI to hide OSK and to disable keyboard mode
|
||||
System_NotifyUIState("hide_keyboard");
|
||||
#endif
|
||||
}
|
||||
|
||||
void GestureMappingScreen::CreateViews() {
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
#endif
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
#include <dwrite_3.h>
|
||||
#include "UWP/UWPHelpers/InputHelpers.h"
|
||||
#endif
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
#include "android/jni/app-android.h"
|
||||
|
@ -1269,6 +1270,14 @@ bool NativeKey(const KeyInput &key) {
|
|||
return false;
|
||||
}
|
||||
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
// Ignore if key sent from OnKeyDown/OnKeyUp/XInput while keyboard mode active
|
||||
// it's already handled by `OnCharacterReceived`
|
||||
if (IgnoreInput(key.keyCode) && !(key.flags & KEY_CHAR)) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// INFO_LOG(SYSTEM, "Key code: %i flags: %i", key.keyCode, key.flags);
|
||||
#if !defined(MOBILE_DEVICE)
|
||||
if (g_Config.bPauseExitsEmulator) {
|
||||
|
|
|
@ -53,7 +53,7 @@ void App::InitialPPSSPP() {
|
|||
// Initial net
|
||||
net::Init();
|
||||
|
||||
//Prepare for initialization
|
||||
// Prepare for initialization
|
||||
std::wstring internalDataFolderW = ApplicationData::Current->LocalFolder->Path->Data();
|
||||
g_Config.internalDataDirectory = Path(internalDataFolderW);
|
||||
g_Config.memStickDirectory = g_Config.internalDataDirectory;
|
||||
|
@ -78,7 +78,7 @@ void App::InitialPPSSPP() {
|
|||
// it's better to call it here
|
||||
const char* argv[2] = { "fake", nullptr };
|
||||
std::string cacheFolder = ConvertWStringToUTF8(ApplicationData::Current->TemporaryFolder->Path->Data());
|
||||
// Ee will not be able to use `argv`
|
||||
// We will not be able to use `argv`
|
||||
// since launch parameters usually handled by `OnActivated`
|
||||
// and `OnActivated` will be invoked later, even after `PPSSPP_UWPMain(..)`
|
||||
// so we are handling launch cases using `LaunchItem`
|
||||
|
|
|
@ -256,22 +256,41 @@ bool DX::DeviceResources::CreateAdaptersList(ComPtr<ID3D11Device> device) {
|
|||
Microsoft::WRL::ComPtr<IDXGIFactory4> deviceFactory;
|
||||
deviceAdapter->GetParent(IID_PPV_ARGS(&deviceFactory));
|
||||
|
||||
// Current adapter (Get current adapter name)
|
||||
DXGI_ADAPTER_DESC currentDefaultAdapterDesc;
|
||||
deviceAdapter->GetDesc(¤tDefaultAdapterDesc);
|
||||
std::string currentDefaultAdapterName = ConvertWStringToUTF8(currentDefaultAdapterDesc.Description);
|
||||
|
||||
UINT i = 0;
|
||||
IDXGIAdapter* pAdapter;
|
||||
IDXGIAdapter* customAdapter = nullptr;
|
||||
auto deviceInfo = Windows::System::Profile::AnalyticsInfo::VersionInfo;
|
||||
bool isXbox = deviceInfo->DeviceFamily == "Windows.Xbox";
|
||||
while (deviceFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND)
|
||||
{
|
||||
++i;
|
||||
DXGI_ADAPTER_DESC vAdapterDesc;
|
||||
pAdapter->GetDesc(&vAdapterDesc);
|
||||
auto adapterDescription = ConvertWStringToUTF8(vAdapterDesc.Description);
|
||||
m_vAdapters.push_back(adapterDescription);
|
||||
if (g_Config.sD3D11Device == adapterDescription) {
|
||||
customAdapter = pAdapter;
|
||||
if (isXbox && adapterDescription == "Microsoft Basic Render Driver") {
|
||||
// Skip, very slow and not usefull for Xbox
|
||||
continue;
|
||||
}
|
||||
m_vAdapters.push_back(adapterDescription);
|
||||
if (!g_Config.sD3D11Device.empty() && g_Config.sD3D11Device == adapterDescription) {
|
||||
// Double check if it's the same default adapter
|
||||
if (adapterDescription != currentDefaultAdapterName) {
|
||||
customAdapter = pAdapter;
|
||||
}
|
||||
}
|
||||
++i;
|
||||
}
|
||||
deviceFactory->Release();
|
||||
|
||||
if (m_vAdapters.size() == 1) {
|
||||
// Only one (default) adapter, clear the list to hide device option from settings
|
||||
m_vAdapters.clear();
|
||||
}
|
||||
|
||||
bool reCreateDevice = false;
|
||||
if (customAdapter) {
|
||||
reCreateDevice = true;
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#include "UWPHelpers/StorageManager.h"
|
||||
#include "UWPHelpers/StorageAsync.h"
|
||||
#include "UWPHelpers/LaunchItem.h"
|
||||
#include <UWPHelpers/InputHelpers.h>
|
||||
#include "UWPHelpers/InputHelpers.h"
|
||||
|
||||
using namespace UWP;
|
||||
using namespace Windows::Foundation;
|
||||
|
@ -198,6 +198,7 @@ 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
|
||||
auto iter = virtualKeyCodeToNKCode.find(virtualKey);
|
||||
if (iter != virtualKeyCodeToNKCode.end()) {
|
||||
KeyInput key{};
|
||||
|
@ -220,12 +221,12 @@ void PPSSPP_UWPMain::OnKeyUp(int scanCode, Windows::System::VirtualKey virtualKe
|
|||
}
|
||||
|
||||
void PPSSPP_UWPMain::OnCharacterReceived(int scanCode, unsigned int keyCode) {
|
||||
// TODO: Once on-screen keyboard show/hide solved, add `InputPaneVisible()` as extra condition
|
||||
if (!PSP_IsInited() && !IsCtrlOnHold()) {
|
||||
// This event triggered only in chars case, (Arrows, Delete..etc don't call it)
|
||||
if (isKeyboardActive() && !IsCtrlOnHold()) {
|
||||
KeyInput key{};
|
||||
key.deviceId = DEVICE_ID_KEYBOARD;
|
||||
key.keyCode = (InputKeyCode)keyCode;
|
||||
key.flags = KEY_DOWN | KEY_CHAR;
|
||||
key.flags = KEY_DOWN | KEY_UP | KEY_CHAR;
|
||||
NativeKey(key);
|
||||
}
|
||||
}
|
||||
|
@ -359,10 +360,9 @@ int System_GetPropertyInt(SystemProperty prop) {
|
|||
|
||||
case SYSPROP_DEVICE_TYPE:
|
||||
{
|
||||
auto ver = Windows::System::Profile::AnalyticsInfo::VersionInfo;
|
||||
if (ver->DeviceFamily == "Windows.Mobile") {
|
||||
if (IsMobile()) {
|
||||
return DEVICE_TYPE_MOBILE;
|
||||
} else if (ver->DeviceFamily == "Windows.Xbox") {
|
||||
} else if (IsXBox()) {
|
||||
return DEVICE_TYPE_TV;
|
||||
} else {
|
||||
return DEVICE_TYPE_DESKTOP;
|
||||
|
@ -407,8 +407,7 @@ bool System_GetPropertyBool(SystemProperty prop) {
|
|||
switch (prop) {
|
||||
case SYSPROP_HAS_OPEN_DIRECTORY:
|
||||
{
|
||||
auto ver = Windows::System::Profile::AnalyticsInfo::VersionInfo;
|
||||
return ver->DeviceFamily != "Windows.Xbox";
|
||||
return !IsXBox();
|
||||
}
|
||||
case SYSPROP_HAS_FILE_BROWSER:
|
||||
return true;
|
||||
|
@ -550,7 +549,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
|
|||
CoreDispatcherPriority::Normal,
|
||||
ref new Windows::UI::Core::DispatchedHandler([]()
|
||||
{
|
||||
ShowInputPane();
|
||||
ActivateKeyboardInput();
|
||||
}));
|
||||
}
|
||||
else if (!strcmp(param1.c_str(), "hide_keyboard")) {
|
||||
|
@ -559,7 +558,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
|
|||
CoreDispatcherPriority::Normal,
|
||||
ref new Windows::UI::Core::DispatchedHandler([]()
|
||||
{
|
||||
HideInputPane();
|
||||
DeactivateKeyboardInput();
|
||||
}));
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "InputHelpers.h"
|
||||
#include "UWPUtil.h"
|
||||
|
@ -29,6 +30,13 @@ using namespace Windows::ApplicationModel::Core;
|
|||
using namespace Windows::Data::Xml::Dom;
|
||||
using namespace Windows::UI::Notifications;
|
||||
|
||||
#pragma region Extenstions
|
||||
template<typename T>
|
||||
bool findInList(std::list<T>& inputList, T& str) {
|
||||
return (std::find(inputList.begin(), inputList.end(), str) != inputList.end());
|
||||
};
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Input Keyboard
|
||||
|
||||
bool isKeybaordAvailable() {
|
||||
|
@ -43,24 +51,89 @@ bool isTouchAvailable() {
|
|||
return hasTouch;
|
||||
}
|
||||
|
||||
bool keyboardVisible = false;
|
||||
bool InputPaneVisible() {
|
||||
return keyboardVisible;
|
||||
bool keyboardActive = false;
|
||||
bool inputPaneVisible = false;
|
||||
bool isInputPaneVisible() {
|
||||
// On Xbox we can check this using input pan
|
||||
if (IsXBox()) {
|
||||
return InputPane::GetForCurrentView()->Visible;
|
||||
}
|
||||
else {
|
||||
return inputPaneVisible;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ShowInputPane() {
|
||||
VERBOSE_LOG(COMMON, "ShowInputKeyboard");
|
||||
InputPane::GetForCurrentView()->TryShow();
|
||||
keyboardVisible = true;
|
||||
bool isKeyboardActive() {
|
||||
return keyboardActive;
|
||||
}
|
||||
|
||||
void HideInputPane() {
|
||||
VERBOSE_LOG(COMMON, "HideInputKeyboard");
|
||||
InputPane::GetForCurrentView()->TryHide();
|
||||
keyboardVisible = false;
|
||||
void ActivateKeyboardInput() {
|
||||
DEBUG_LOG(COMMON, "Activate input keyboard");
|
||||
// When no
|
||||
inputPaneVisible = InputPane::GetForCurrentView()->TryShow();
|
||||
keyboardActive = true;
|
||||
|
||||
if (inputPaneVisible) {
|
||||
DEBUG_LOG(COMMON, "Input pane: TryShow accepted");
|
||||
}
|
||||
else {
|
||||
DEBUG_LOG(COMMON, "Input pane: (TryShow is not accepted or pane is not supported)");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void DeactivateKeyboardInput() {
|
||||
DEBUG_LOG(COMMON, "Deactivate input keyboard");
|
||||
if (InputPane::GetForCurrentView()->TryHide()) {
|
||||
inputPaneVisible = false;
|
||||
DEBUG_LOG(COMMON, "Input pane: TryHide accepted");
|
||||
}
|
||||
else {
|
||||
DEBUG_LOG(COMMON, "Input pane: TryHide is not accepted, or pane is not visible");
|
||||
}
|
||||
keyboardActive = false;
|
||||
}
|
||||
|
||||
bool IgnoreInput(int keyCode) {
|
||||
// When keyboard mode active and char is passed this function return 'true'
|
||||
// it will help to prevent KeyDown from sending the same code again
|
||||
bool ignoreInput = false;
|
||||
if (isKeyboardActive() && !IsCtrlOnHold()) {
|
||||
// To avoid bothering KeyDown to check this case always
|
||||
// we don't get here unless keyboard mode is active
|
||||
std::list<int> nonCharList = {
|
||||
NKCODE_CTRL_LEFT,
|
||||
NKCODE_CTRL_RIGHT,
|
||||
NKCODE_MOVE_HOME,
|
||||
NKCODE_PAGE_UP,
|
||||
NKCODE_MOVE_END,
|
||||
NKCODE_PAGE_DOWN,
|
||||
NKCODE_FORWARD_DEL,
|
||||
NKCODE_DEL,
|
||||
NKCODE_ENTER,
|
||||
NKCODE_NUMPAD_ENTER,
|
||||
NKCODE_EXT_MOUSEBUTTON_1,
|
||||
NKCODE_EXT_MOUSEBUTTON_2,
|
||||
NKCODE_EXT_MOUSEBUTTON_3,
|
||||
NKCODE_EXT_MOUSEBUTTON_4,
|
||||
NKCODE_EXT_MOUSEBUTTON_5,
|
||||
NKCODE_ESCAPE
|
||||
};
|
||||
if (!isInputPaneVisible()) {
|
||||
// Keyboard active but no on-screen keyboard
|
||||
// allow arrow keys for navigation
|
||||
nonCharList.push_back(NKCODE_DPAD_UP);
|
||||
nonCharList.push_back(NKCODE_DPAD_DOWN);
|
||||
nonCharList.push_back(NKCODE_DPAD_LEFT);
|
||||
nonCharList.push_back(NKCODE_DPAD_RIGHT);
|
||||
nonCharList.push_back(NKCODE_BACK);
|
||||
}
|
||||
|
||||
ignoreInput = !findInList(nonCharList, keyCode);
|
||||
}
|
||||
|
||||
return ignoreInput;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Keys Status
|
||||
|
@ -92,4 +165,14 @@ std::string GetLangRegion() {
|
|||
}
|
||||
return langRegion;
|
||||
}
|
||||
|
||||
bool IsXBox() {
|
||||
auto deviceInfo = Windows::System::Profile::AnalyticsInfo::VersionInfo;
|
||||
return deviceInfo->DeviceFamily == "Windows.Xbox";
|
||||
}
|
||||
|
||||
bool IsMobile() {
|
||||
auto deviceInfo = Windows::System::Profile::AnalyticsInfo::VersionInfo;
|
||||
return deviceInfo->DeviceFamily == "Windows.Mobile";
|
||||
}
|
||||
#pragma endregion
|
||||
|
|
|
@ -22,11 +22,12 @@
|
|||
bool isKeybaordAvailable();
|
||||
bool isTouchAvailable();
|
||||
|
||||
// Input Pane
|
||||
bool InputPaneVisible();
|
||||
void ShowInputPane();
|
||||
void HideInputPane();
|
||||
|
||||
// Input Keyboard/Pane
|
||||
bool isInputPaneVisible();
|
||||
bool isKeyboardActive();
|
||||
void ActivateKeyboardInput();
|
||||
void DeactivateKeyboardInput();
|
||||
bool IgnoreInput(int keyCode);
|
||||
|
||||
// Keys Status
|
||||
bool IsCapsLockOn();
|
||||
|
@ -35,3 +36,5 @@ bool IsCtrlOnHold();
|
|||
|
||||
// Misc
|
||||
std::string GetLangRegion();
|
||||
bool IsXBox();
|
||||
bool IsMobile();
|
||||
|
|
Loading…
Add table
Reference in a new issue