Bug 1539178 - Add a threshold on gamepad axes to avoid gamepads be unintentionally activated. r=cmartin,baku

Differential Revision: https://phabricator.services.mozilla.com/D86287
This commit is contained in:
Daosheng Mu 2020-08-10 18:14:39 +00:00
parent 17473c0717
commit db07868613
2 changed files with 27 additions and 1 deletions

View file

@ -45,6 +45,9 @@ bool sShutdown = false;
StaticRefPtr<GamepadManager> gGamepadManagerSingleton;
const uint32_t VR_GAMEPAD_IDX_OFFSET = 0x01 << 16;
// A threshold value of axis move to determine the first
// intent.
const float AXIS_FIRST_INTENT_THRESHOLD_VALUE = 0.1f;
} // namespace
@ -416,6 +419,22 @@ already_AddRefed<GamepadManager> GamepadManager::GetService() {
return service.forget();
}
bool GamepadManager::AxisMoveIsFirstIntent(nsGlobalWindowInner* aWindow,
uint32_t aIndex,
const GamepadChangeEvent& aEvent) {
const GamepadChangeEventBody& body = aEvent.body();
if (!WindowHasSeenGamepad(aWindow, aIndex) &&
body.type() == GamepadChangeEventBody::TGamepadAxisInformation) {
// Some controllers would send small axis values even they are just idle.
// To avoid controllers be activated without its first intent.
const GamepadAxisInformation& a = body.get_GamepadAxisInformation();
if (abs(a.value()) < AXIS_FIRST_INTENT_THRESHOLD_VALUE) {
return false;
}
}
return true;
}
bool GamepadManager::MaybeWindowHasSeenGamepad(nsGlobalWindowInner* aWindow,
uint32_t aIndex) {
if (!WindowHasSeenGamepad(aWindow, aIndex)) {
@ -537,6 +556,9 @@ bool GamepadManager::SetGamepadByEvent(const GamepadChangeEvent& aEvent,
const uint32_t index =
GetGamepadIndexWithServiceType(aEvent.index(), aEvent.service_type());
if (aWindow) {
if (!AxisMoveIsFirstIntent(aWindow, index, aEvent)) {
return false;
}
firstTime = !MaybeWindowHasSeenGamepad(aWindow, index);
}

View file

@ -133,7 +133,11 @@ class GamepadManager final : public nsIObserver {
bool SetGamepadByEvent(const GamepadChangeEvent& aEvent,
nsGlobalWindowInner* aWindow = nullptr);
// To avoid unintentionally causing the gamepad be activated.
// Returns false if this gamepad hasn't been seen by this window
// and the axis move data is less than AXIS_FIRST_INTENT_THRESHOLD_VALUE.
bool AxisMoveIsFirstIntent(nsGlobalWindowInner* aWindow, uint32_t aIndex,
const GamepadChangeEvent& aEvent);
bool MaybeWindowHasSeenGamepad(nsGlobalWindowInner* aWindow, uint32_t aIndex);
// Returns true if we have already sent data from this gamepad
// to this window. This should only return true if the user