From 3023f7d06b7d5a8e3b3d66946d49e4c4f6c7c6b7 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 19 May 2014 23:29:35 +0200 Subject: [PATCH] Android: Switch dpad default to use HAT X/Y +/- instead of "dpad", as documented. Add a simple "autoconfigure" facility for input devices, that lets the user choose if several are connected. Can be expanded in the future to provide custom default mapppings for various devices as long as we manage to identify them. Ideally, key mappings should be unique per device but they aren't yet. --- Common/KeyMap.cpp | 32 +++++++++++++++++++++++++++----- Common/KeyMap.h | 5 +++++ UI/ControlMappingScreen.cpp | 21 +++++++++++++++++++++ UI/ControlMappingScreen.h | 3 +++ UI/NativeApp.cpp | 7 +++++++ Windows/XinputDevice.cpp | 14 +++++++++++--- native | 2 +- 7 files changed, 75 insertions(+), 9 deletions(-) diff --git a/Common/KeyMap.cpp b/Common/KeyMap.cpp index b6b261b444..02a0314b21 100644 --- a/Common/KeyMap.cpp +++ b/Common/KeyMap.cpp @@ -18,10 +18,12 @@ #if defined(_WIN32) && !defined(_XBOX) #include #endif +#include +#include "base/logging.h" +#include "base/NativeApp.h" #include "file/ini_file.h" #include "input/input_state.h" -#include "base/NativeApp.h" #include "KeyMap.h" #include "../Core/HLE/sceUtility.h" @@ -40,6 +42,7 @@ struct DefMappingStruct { }; KeyMapping g_controllerMap; +std::set g_seenPads; static const DefMappingStruct defaultQwertyKeyboardKeyMap[] = { {CTRL_SQUARE, NKCODE_A}, @@ -202,10 +205,11 @@ static const DefMappingStruct defaultPadMap[] = { {CTRL_CIRCLE , NKCODE_BUTTON_B}, {CTRL_SQUARE , NKCODE_BUTTON_X}, {CTRL_TRIANGLE , NKCODE_BUTTON_Y}, - {CTRL_UP , NKCODE_DPAD_UP}, - {CTRL_RIGHT , NKCODE_DPAD_RIGHT}, - {CTRL_DOWN , NKCODE_DPAD_DOWN}, - {CTRL_LEFT , NKCODE_DPAD_LEFT}, + // The hat for DPAD is standard for bluetooth pads, which is the most likely pads on Android I think. + {CTRL_LEFT , JOYSTICK_AXIS_HAT_X, -1}, + {CTRL_RIGHT , JOYSTICK_AXIS_HAT_X, +1}, + {CTRL_UP , JOYSTICK_AXIS_HAT_Y, -1}, + {CTRL_DOWN , JOYSTICK_AXIS_HAT_Y, +1}, {CTRL_START , NKCODE_BUTTON_START}, {CTRL_SELECT , NKCODE_BUTTON_SELECT}, {CTRL_LTRIGGER , NKCODE_BUTTON_L1}, @@ -894,4 +898,22 @@ bool HasBuiltinController(const std::string &name) { return IsOuya(name) || IsXperiaPlay(name) || IsNvidiaShield(name) || IsBlackberryQWERTY(name); } +void NotifyPadConnected(const std::string &name) { + g_seenPads.insert(name); +} + +void AutoConfForPad(const std::string &name) { + ILOG("Autoconfiguring pad for %s", name.c_str()); + if (name == "Xbox 360 Pad") { + SetDefaultKeyMap(DEFAULT_MAPPING_X360, true); + } else { + SetDefaultKeyMap(DEFAULT_MAPPING_PAD, true); + } +} + +const std::set &GetSeenPads() { + return g_seenPads; +} + + } // KeyMap diff --git a/Common/KeyMap.h b/Common/KeyMap.h index 55166d0b5d..fc25c2026f 100644 --- a/Common/KeyMap.h +++ b/Common/KeyMap.h @@ -20,6 +20,7 @@ #include #include #include +#include #include "input/keycodes.h" // keyboard keys #include "../Core/HLE/sceCtrl.h" // psp keys @@ -156,9 +157,13 @@ namespace KeyMap { void UpdateConfirmCancelKeys(); + void NotifyPadConnected(const std::string &name); bool IsNvidiaShield(const std::string &name); bool IsBlackberryQWERTY(const std::string &name); bool IsXperiaPlay(const std::string &name); bool IsOuya(const std::string &name); bool HasBuiltinController(const std::string &name); + + const std::set &GetSeenPads(); + void AutoConfForPad(const std::string &name); } diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index 4a69225afe..b291851e46 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -199,6 +199,9 @@ void ControlMappingScreen::CreateViews() { LinearLayout *leftColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(200, FILL_PARENT)); leftColumn->Add(new Choice(k->T("Clear All")))->OnClick.Handle(this, &ControlMappingScreen::OnClearMapping); leftColumn->Add(new Choice(k->T("Default All")))->OnClick.Handle(this, &ControlMappingScreen::OnDefaultMapping); + if (KeyMap::GetSeenPads().size()) { + leftColumn->Add(new Choice(k->T("Autoconfigure")))->OnClick.Handle(this, &ControlMappingScreen::OnAutoConfigure); + } leftColumn->Add(new Spacer(new LinearLayoutParams(1.0f))); leftColumn->Add(new Choice(d->T("Back")))->OnClick.Handle(this, &UIScreen::OnBack); @@ -238,6 +241,24 @@ UI::EventReturn ControlMappingScreen::OnDefaultMapping(UI::EventParams ¶ms) return UI::EVENT_DONE; } +UI::EventReturn ControlMappingScreen::OnAutoConfigure(UI::EventParams ¶ms) { + std::vector items; + for (auto s : KeyMap::GetSeenPads()) { + items.push_back(s); + } + ListPopupScreen *autoConfList = new ListPopupScreen("Autoconfigure for device", items, -1); + screenManager()->push(autoConfList); + return UI::EVENT_DONE; +} + +void ControlMappingScreen::dialogFinished(const Screen *dialog, DialogResult result) { + if (result == DR_OK && dialog->tag() == "listpopup") { + ListPopupScreen *popup = (ListPopupScreen *)dialog; + KeyMap::AutoConfForPad(popup->GetChoiceString()); + RecreateViews(); + } +} + void KeyMappingNewKeyDialog::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; diff --git a/UI/ControlMappingScreen.h b/UI/ControlMappingScreen.h index 0a56f125ba..f9ed2e9262 100644 --- a/UI/ControlMappingScreen.h +++ b/UI/ControlMappingScreen.h @@ -33,6 +33,9 @@ protected: private: UI::EventReturn OnDefaultMapping(UI::EventParams ¶ms); UI::EventReturn OnClearMapping(UI::EventParams ¶ms); + UI::EventReturn OnAutoConfigure(UI::EventParams ¶ms); + + virtual void dialogFinished(const Screen *dialog, DialogResult result) override; }; class KeyMappingNewKeyDialog : public PopupScreen { diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 48433fc698..a57e67e6ab 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -657,10 +657,17 @@ void NativeRender() { } } +void HandleGlobalMessage(const std::string &msg, const std::string &value) { + if (msg == "inputDeviceConnected") { + KeyMap::NotifyPadConnected(value); + } +} + void NativeUpdate(InputState &input) { { lock_guard lock(pendingMutex); for (size_t i = 0; i < pendingMessages.size(); i++) { + HandleGlobalMessage(pendingMessages[i].msg, pendingMessages[i].value); screenManager->sendMessage(pendingMessages[i].msg.c_str(), pendingMessages[i].value.c_str()); } pendingMessages.clear(); diff --git a/Windows/XinputDevice.cpp b/Windows/XinputDevice.cpp index 5806dcd5aa..49e5039979 100644 --- a/Windows/XinputDevice.cpp +++ b/Windows/XinputDevice.cpp @@ -2,6 +2,7 @@ #include "base/NativeApp.h" #include "Core/Config.h" +#include "Common/KeyMap.h" #include "input/input_state.h" #include "input/keycodes.h" #include "XinputDevice.h" @@ -116,14 +117,16 @@ int XinputDevice::UpdateState(InputState &input_state) { if (!s_pXInputDLL) return 0; - if (this->check_delay-- > 0) return -1; + if (this->check_delay-- > 0) + return -1; + XINPUT_STATE state; ZeroMemory( &state, sizeof(XINPUT_STATE) ); DWORD dwResult; - if (this->gamepad_idx >= 0) + if (this->gamepad_idx >= 0) { dwResult = PPSSPP_XInputGetState( this->gamepad_idx, &state ); - else { + } else { // use the first gamepad that responds for (int i = 0; i < XUSER_MAX_COUNT; i++) { dwResult = PPSSPP_XInputGetState( i, &state ); @@ -135,6 +138,11 @@ int XinputDevice::UpdateState(InputState &input_state) { } if ( dwResult == ERROR_SUCCESS ) { + static bool notified = false; + if (!notified) { + notified = true; + KeyMap::NotifyPadConnected("Xbox 360 Pad"); + } ApplyButtons(state, input_state); if (prevState.Gamepad.sThumbLX != state.Gamepad.sThumbLX || prevState.Gamepad.sThumbLY != state.Gamepad.sThumbLY) { diff --git a/native b/native index edaea34df1..e7001eb701 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit edaea34df1b1b7b37eac23abf39a27e3f4b3b78e +Subproject commit e7001eb701a953c9508f5a85d40147e5f0a88f3a