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