Skip to content

Commit 17152b8

Browse files
author
Chris Martin
committed
Bug 1609068 - Part 2: Add Mac OS Xbox wireless gamepads remapping. r=baku
Original Author: Daosheng Mu Differential Revision: https://phabricator.services.mozilla.com/D84918
1 parent de0e8c0 commit 17152b8

File tree

2 files changed

+393
-1
lines changed

2 files changed

+393
-1
lines changed

dom/gamepad/GamepadRemapping.cpp

Lines changed: 367 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,364 @@ class Dualshock4Remapper final : public GamepadRemapper {
669669
unsigned long mTouchIdBase = 0;
670670
};
671671

672+
class Xbox360Remapper final : public GamepadRemapper {
673+
public:
674+
virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
675+
676+
virtual uint32_t GetButtonCount() const override {
677+
return BUTTON_INDEX_COUNT;
678+
}
679+
680+
virtual void RemapAxisMoveEvent(uint32_t aIndex, uint32_t aAxis,
681+
double aValue) const override {
682+
RefPtr<GamepadPlatformService> service =
683+
GamepadPlatformService::GetParentService();
684+
if (!service) {
685+
return;
686+
}
687+
688+
switch (aAxis) {
689+
case 0:
690+
service->NewAxisMoveEvent(aIndex, AXIS_INDEX_LEFT_STICK_X, aValue);
691+
break;
692+
case 1:
693+
service->NewAxisMoveEvent(aIndex, AXIS_INDEX_LEFT_STICK_Y, aValue);
694+
break;
695+
case 2: {
696+
const double value = AxisToButtonValue(aValue);
697+
service->NewButtonEvent(aIndex, BUTTON_INDEX_LEFT_TRIGGER,
698+
value > BUTTON_THRESHOLD_VALUE, value);
699+
break;
700+
}
701+
case 3:
702+
service->NewAxisMoveEvent(aIndex, AXIS_INDEX_RIGHT_STICK_X, aValue);
703+
break;
704+
case 4:
705+
service->NewAxisMoveEvent(aIndex, AXIS_INDEX_RIGHT_STICK_Y, aValue);
706+
break;
707+
case 5: {
708+
const double value = AxisToButtonValue(aValue);
709+
service->NewButtonEvent(aIndex, BUTTON_INDEX_RIGHT_TRIGGER,
710+
value > BUTTON_THRESHOLD_VALUE, value);
711+
break;
712+
}
713+
default:
714+
NS_WARNING(
715+
nsPrintfCString(
716+
"Axis idx '%d' doesn't support in Xbox360Remapper().", aAxis)
717+
.get());
718+
break;
719+
}
720+
}
721+
722+
virtual void RemapButtonEvent(uint32_t aIndex, uint32_t aButton,
723+
bool aPressed) const override {
724+
RefPtr<GamepadPlatformService> service =
725+
GamepadPlatformService::GetParentService();
726+
if (!service) {
727+
return;
728+
}
729+
730+
if (GetButtonCount() <= aButton) {
731+
NS_WARNING(
732+
nsPrintfCString(
733+
"Button idx '%d' doesn't support in Xbox360Remapper().", aButton)
734+
.get());
735+
return;
736+
}
737+
738+
const std::unordered_map<uint32_t, uint32_t> buttonMapping = {
739+
{6, BUTTON_INDEX_LEFT_THUMBSTICK}, {7, BUTTON_INDEX_RIGHT_THUMBSTICK},
740+
{8, BUTTON_INDEX_START}, {9, BUTTON_INDEX_BACK_SELECT},
741+
{10, BUTTON_INDEX_META}, {11, BUTTON_INDEX_DPAD_UP},
742+
{12, BUTTON_INDEX_DPAD_DOWN}, {13, BUTTON_INDEX_DPAD_LEFT},
743+
{14, BUTTON_INDEX_DPAD_RIGHT}};
744+
745+
auto find = buttonMapping.find(aButton);
746+
if (find != buttonMapping.end()) {
747+
service->NewButtonEvent(aIndex, find->second, aPressed);
748+
} else {
749+
service->NewButtonEvent(aIndex, aButton, aPressed);
750+
}
751+
}
752+
};
753+
754+
class XboxOneSRemapper final : public GamepadRemapper {
755+
public:
756+
virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
757+
758+
virtual uint32_t GetButtonCount() const override {
759+
return BUTTON_INDEX_COUNT;
760+
}
761+
762+
virtual void RemapAxisMoveEvent(uint32_t aIndex, uint32_t aAxis,
763+
double aValue) const override {
764+
RefPtr<GamepadPlatformService> service =
765+
GamepadPlatformService::GetParentService();
766+
if (!service) {
767+
return;
768+
}
769+
770+
switch (aAxis) {
771+
case 0:
772+
service->NewAxisMoveEvent(aIndex, AXIS_INDEX_LEFT_STICK_X, aValue);
773+
break;
774+
case 1:
775+
service->NewAxisMoveEvent(aIndex, AXIS_INDEX_LEFT_STICK_Y, aValue);
776+
break;
777+
case 2: {
778+
const double value = AxisToButtonValue(aValue);
779+
service->NewButtonEvent(aIndex, BUTTON_INDEX_LEFT_TRIGGER,
780+
value > BUTTON_THRESHOLD_VALUE, value);
781+
break;
782+
}
783+
case 3:
784+
service->NewAxisMoveEvent(aIndex, AXIS_INDEX_RIGHT_STICK_X, aValue);
785+
break;
786+
case 4:
787+
service->NewAxisMoveEvent(aIndex, AXIS_INDEX_RIGHT_STICK_Y, aValue);
788+
break;
789+
case 5: {
790+
const double value = AxisToButtonValue(aValue);
791+
service->NewButtonEvent(aIndex, BUTTON_INDEX_RIGHT_TRIGGER,
792+
value > BUTTON_THRESHOLD_VALUE, value);
793+
break;
794+
}
795+
case 9:
796+
FetchDpadFromAxis(aIndex, aValue);
797+
break;
798+
default:
799+
NS_WARNING(
800+
nsPrintfCString(
801+
"Axis idx '%d' doesn't support in XboxOneSRemapper().", aAxis)
802+
.get());
803+
break;
804+
}
805+
}
806+
807+
virtual void RemapButtonEvent(uint32_t aIndex, uint32_t aButton,
808+
bool aPressed) const override {
809+
RefPtr<GamepadPlatformService> service =
810+
GamepadPlatformService::GetParentService();
811+
if (!service) {
812+
return;
813+
}
814+
815+
if (GetButtonCount() <= aButton) {
816+
NS_WARNING(
817+
nsPrintfCString(
818+
"Button idx '%d' doesn't support in XboxOneSRemapper().", aButton)
819+
.get());
820+
return;
821+
}
822+
823+
const std::unordered_map<uint32_t, uint32_t> buttonMapping = {
824+
{6, BUTTON_INDEX_BACK_SELECT},
825+
{7, BUTTON_INDEX_START},
826+
{8, BUTTON_INDEX_LEFT_THUMBSTICK},
827+
{9, BUTTON_INDEX_RIGHT_THUMBSTICK},
828+
{10, BUTTON_INDEX_META}};
829+
830+
auto find = buttonMapping.find(aButton);
831+
if (find != buttonMapping.end()) {
832+
service->NewButtonEvent(aIndex, find->second, aPressed);
833+
} else {
834+
service->NewButtonEvent(aIndex, aButton, aPressed);
835+
}
836+
}
837+
};
838+
839+
class XboxOneS2016FirmwareRemapper final : public GamepadRemapper {
840+
public:
841+
virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
842+
843+
virtual uint32_t GetButtonCount() const override {
844+
return BUTTON_INDEX_COUNT;
845+
}
846+
847+
virtual void RemapAxisMoveEvent(uint32_t aIndex, uint32_t aAxis,
848+
double aValue) const override {
849+
RefPtr<GamepadPlatformService> service =
850+
GamepadPlatformService::GetParentService();
851+
if (!service) {
852+
return;
853+
}
854+
855+
switch (aAxis) {
856+
case 0:
857+
service->NewAxisMoveEvent(aIndex, AXIS_INDEX_LEFT_STICK_X, aValue);
858+
break;
859+
case 1:
860+
service->NewAxisMoveEvent(aIndex, AXIS_INDEX_LEFT_STICK_Y, aValue);
861+
break;
862+
case 2:
863+
service->NewAxisMoveEvent(aIndex, AXIS_INDEX_RIGHT_STICK_X, aValue);
864+
break;
865+
case 3: {
866+
const double value = AxisToButtonValue(aValue);
867+
service->NewButtonEvent(aIndex, BUTTON_INDEX_LEFT_TRIGGER,
868+
value > BUTTON_THRESHOLD_VALUE, value);
869+
break;
870+
}
871+
case 4: {
872+
const double value = AxisToButtonValue(aValue);
873+
service->NewButtonEvent(aIndex, BUTTON_INDEX_RIGHT_TRIGGER,
874+
value > BUTTON_THRESHOLD_VALUE, value);
875+
break;
876+
}
877+
case 5:
878+
service->NewAxisMoveEvent(aIndex, AXIS_INDEX_RIGHT_STICK_Y, aValue);
879+
break;
880+
case 9:
881+
FetchDpadFromAxis(aIndex, aValue);
882+
break;
883+
default:
884+
NS_WARNING(nsPrintfCString("Axis idx '%d' doesn't support in "
885+
"XboxOneS2016FirmwareRemapper().",
886+
aAxis)
887+
.get());
888+
break;
889+
}
890+
}
891+
892+
virtual void RemapButtonEvent(uint32_t aIndex, uint32_t aButton,
893+
bool aPressed) const override {
894+
RefPtr<GamepadPlatformService> service =
895+
GamepadPlatformService::GetParentService();
896+
if (!service) {
897+
return;
898+
}
899+
900+
if (GetButtonCount() <= aButton) {
901+
NS_WARNING(nsPrintfCString("Button idx '%d' doesn't support in "
902+
"XboxOneS2016FirmwareRemapper().",
903+
aButton)
904+
.get());
905+
return;
906+
}
907+
908+
// kMicrosoftProductXboxOneSWireless2016 controller received a firmware
909+
// update in 2019 that changed which field is populated with the meta button
910+
// state. In order to cover the old and new cases, we have to check both
911+
// fields of {12, 15} buttons.
912+
const std::unordered_map<uint32_t, uint32_t> buttonMapping = {
913+
{0, BUTTON_INDEX_PRIMARY},
914+
{1, BUTTON_INDEX_SECONDARY},
915+
{3, BUTTON_INDEX_TERTIARY},
916+
{4, BUTTON_INDEX_QUATERNARY},
917+
{6, BUTTON_INDEX_LEFT_SHOULDER},
918+
{7, BUTTON_INDEX_RIGHT_SHOULDER},
919+
{11, BUTTON_INDEX_START},
920+
{12, BUTTON_INDEX_META},
921+
{13, BUTTON_INDEX_LEFT_THUMBSTICK},
922+
{14, BUTTON_INDEX_RIGHT_THUMBSTICK},
923+
{15, BUTTON_INDEX_META},
924+
{16, BUTTON_INDEX_BACK_SELECT}};
925+
926+
auto find = buttonMapping.find(aButton);
927+
if (find != buttonMapping.end()) {
928+
service->NewButtonEvent(aIndex, find->second, aPressed);
929+
} else {
930+
service->NewButtonEvent(aIndex, aButton, aPressed);
931+
}
932+
}
933+
};
934+
935+
class XboxOneRemapper final : public GamepadRemapper {
936+
public:
937+
virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
938+
939+
virtual uint32_t GetButtonCount() const override {
940+
return BUTTON_INDEX_COUNT;
941+
}
942+
943+
virtual void RemapAxisMoveEvent(uint32_t aIndex, uint32_t aAxis,
944+
double aValue) const override {
945+
RefPtr<GamepadPlatformService> service =
946+
GamepadPlatformService::GetParentService();
947+
if (!service) {
948+
return;
949+
}
950+
951+
switch (aAxis) {
952+
case 0:
953+
service->NewAxisMoveEvent(aIndex, AXIS_INDEX_LEFT_STICK_X, aValue);
954+
break;
955+
case 1:
956+
service->NewAxisMoveEvent(aIndex, AXIS_INDEX_LEFT_STICK_Y, aValue);
957+
break;
958+
case 2:
959+
service->NewAxisMoveEvent(aIndex, AXIS_INDEX_RIGHT_STICK_X, aValue);
960+
break;
961+
case 3:
962+
service->NewAxisMoveEvent(aIndex, AXIS_INDEX_RIGHT_STICK_Y, aValue);
963+
break;
964+
case 9:
965+
FetchDpadFromAxis(aIndex, aValue);
966+
break;
967+
case 10: {
968+
const double value = AxisToButtonValue(aValue);
969+
service->NewButtonEvent(aIndex, BUTTON_INDEX_LEFT_TRIGGER,
970+
value > BUTTON_THRESHOLD_VALUE, value);
971+
break;
972+
}
973+
case 11: {
974+
const double value = AxisToButtonValue(aValue);
975+
service->NewButtonEvent(aIndex, BUTTON_INDEX_RIGHT_TRIGGER,
976+
value > BUTTON_THRESHOLD_VALUE, value);
977+
break;
978+
}
979+
default:
980+
NS_WARNING(
981+
nsPrintfCString(
982+
"Axis idx '%d' doesn't support in XboxOneRemapper().", aAxis)
983+
.get());
984+
break;
985+
}
986+
}
987+
988+
virtual void RemapButtonEvent(uint32_t aIndex, uint32_t aButton,
989+
bool aPressed) const override {
990+
RefPtr<GamepadPlatformService> service =
991+
GamepadPlatformService::GetParentService();
992+
if (!service) {
993+
return;
994+
}
995+
996+
if (GetButtonCount() <= aButton) {
997+
NS_WARNING(
998+
nsPrintfCString(
999+
"Button idx '%d' doesn't support in XboxOneRemapper().", aButton)
1000+
.get());
1001+
return;
1002+
}
1003+
1004+
// Accessing {30, 31} buttons looks strange to me
1005+
// and without an avilable device to help verify it.
1006+
// It is according to `MapperXboxOneBluetooth()` in
1007+
// https://cs.chromium.org/chromium/src/device/gamepad/gamepad_standard_mappings_mac.mm
1008+
const std::unordered_map<uint32_t, uint32_t> buttonMapping = {
1009+
{0, BUTTON_INDEX_PRIMARY},
1010+
{1, BUTTON_INDEX_SECONDARY},
1011+
{3, BUTTON_INDEX_TERTIARY},
1012+
{4, BUTTON_INDEX_QUATERNARY},
1013+
{6, BUTTON_INDEX_LEFT_SHOULDER},
1014+
{7, BUTTON_INDEX_RIGHT_SHOULDER},
1015+
{11, BUTTON_INDEX_START},
1016+
{13, BUTTON_INDEX_LEFT_THUMBSTICK},
1017+
{14, BUTTON_INDEX_RIGHT_THUMBSTICK},
1018+
{30, BUTTON_INDEX_META},
1019+
{31, BUTTON_INDEX_BACK_SELECT}};
1020+
1021+
auto find = buttonMapping.find(aButton);
1022+
if (find != buttonMapping.end()) {
1023+
service->NewButtonEvent(aIndex, find->second, aPressed);
1024+
} else {
1025+
service->NewButtonEvent(aIndex, aButton, aPressed);
1026+
}
1027+
}
1028+
};
1029+
6721030
class LogitechDInputRemapper final : public GamepadRemapper {
6731031
public:
6741032
virtual uint32_t GetAxisCount() const override { return AXIS_INDEX_COUNT; }
@@ -1717,6 +2075,14 @@ already_AddRefed<GamepadRemapper> GetGamepadRemapper(const uint16_t aVendorId,
17172075
{GamepadId::kLogitechProductc216, new LogitechDInputRemapper()},
17182076
{GamepadId::kLogitechProductc218, new LogitechDInputRemapper()},
17192077
{GamepadId::kLogitechProductc219, new LogitechDInputRemapper()},
2078+
{GamepadId::kMicrosoftProductXbox360Wireless, new Xbox360Remapper()},
2079+
{GamepadId::kMicrosoftProductXbox360Wireless2, new Xbox360Remapper()},
2080+
{GamepadId::kMicrosoftProductXboxOneElite2Wireless,
2081+
new XboxOneRemapper()},
2082+
{GamepadId::kMicrosoftProductXboxOneSWireless, new XboxOneSRemapper()},
2083+
{GamepadId::kMicrosoftProductXboxOneSWireless2016,
2084+
new XboxOneS2016FirmwareRemapper()},
2085+
{GamepadId::kMicrosoftProductXboxAdaptiveWireless, new XboxOneRemapper()},
17202086
{GamepadId::kNintendoProduct2006, new SwitchJoyConRemapper()},
17212087
{GamepadId::kNintendoProduct2007, new SwitchJoyConRemapper()},
17222088
{GamepadId::kNintendoProduct2009, new SwitchProRemapper()},
@@ -1746,7 +2112,7 @@ already_AddRefed<GamepadRemapper> GetGamepadRemapper(const uint16_t aVendorId,
17462112
}
17472113
}
17482114

1749-
static RefPtr<GamepadRemapper> defaultRemapper = new DefaultRemapper();
2115+
RefPtr<GamepadRemapper> defaultRemapper = new DefaultRemapper();
17502116
aUsingDefault = true;
17512117
return do_AddRef(defaultRemapper.get());
17522118
}

0 commit comments

Comments
 (0)