Skip to content

Commit 2dca512

Browse files
committed
Gamepad.vibrationActuator: Add support for "trigger-rumble" effect type
https://bugs.webkit.org/show_bug.cgi?id=250352 rdar://104315486 Reviewed by Brent Fulgham and Geoffrey Garen. Gamepad.vibrationActuator: Add support for "trigger-rumble" effect type: - https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/GamepadHapticsActuatorTriggerRumble/explainer.md It allows vibrating the triggers (which the XBox controller supports), while the existing "dual-rumble" only makes the handles vibrate. This isn't yet part of the specification at: - https://w3c.github.io/gamepad/extensions.html#dom-gamepadhapticeffecttype However, it is supported by Blink and used by XBox cloud games. I am adding support behind an experimental feature flag, off by default. * Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml: * Source/WebCore/Modules/gamepad/GamepadEffectParameters.h: * Source/WebCore/Modules/gamepad/GamepadEffectParameters.idl: * Source/WebCore/Modules/gamepad/GamepadHapticActuator.cpp: (WebCore::GamepadHapticActuator::canPlayEffectType const): (WebCore::GamepadHapticActuator::playEffect): (WebCore::GamepadHapticActuator::stopEffects): (WebCore::GamepadHapticActuator::document const): (WebCore::GamepadHapticActuator::promiseForEffectType): * Source/WebCore/Modules/gamepad/GamepadHapticActuator.h: * Source/WebCore/Modules/gamepad/GamepadHapticEffectType.idl: * Source/WebCore/platform/gamepad/cocoa/GameControllerGamepad.mm: (WebCore::GameControllerGamepad::setupElements): * Source/WebCore/platform/gamepad/cocoa/GameControllerHapticEffect.h: * Source/WebCore/platform/gamepad/cocoa/GameControllerHapticEffect.mm: (WebCore::GameControllerHapticEffect::create): (WebCore::GameControllerHapticEffect::GameControllerHapticEffect): (WebCore::GameControllerHapticEffect::start): (WebCore::GameControllerHapticEffect::stop): (WebCore::GameControllerHapticEffect::leftEffectFinishedPlaying): (WebCore::GameControllerHapticEffect::rightEffectFinishedPlaying): (WebCore::GameControllerHapticEffect::strongEffectFinishedPlaying): Deleted. (WebCore::GameControllerHapticEffect::weakEffectFinishedPlaying): Deleted. * Source/WebCore/platform/gamepad/cocoa/GameControllerHapticEngines.h: (WebCore::GameControllerHapticEngines::leftHandleEngine): (WebCore::GameControllerHapticEngines::rightHandleEngine): (WebCore::GameControllerHapticEngines::leftTriggerEngine): (WebCore::GameControllerHapticEngines::rightTriggerEngine): (WebCore::GameControllerHapticEngines::strongEngine): Deleted. (WebCore::GameControllerHapticEngines::weakEngine): Deleted. * Source/WebCore/platform/gamepad/cocoa/GameControllerHapticEngines.mm: (WebCore::GameControllerHapticEngines::GameControllerHapticEngines): (WebCore::GameControllerHapticEngines::currentEffectForType): (WebCore::GameControllerHapticEngines::playEffect): (WebCore::GameControllerHapticEngines::stopEffects): (WebCore::GameControllerHapticEngines::ensureStarted): (WebCore::GameControllerHapticEngines::stop): * Source/WebCore/platform/gamepad/cocoa/GameControllerSoftLink.h: * Source/WebCore/platform/gamepad/cocoa/GameControllerSoftLink.mm: * Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in: Canonical link: https://commits.webkit.org/259507@main
1 parent fc0d8fb commit 2dca512

14 files changed

+252
-89
lines changed

Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2405,6 +2405,20 @@ GStreamerEnabled:
24052405
WebKit:
24062406
default: true
24072407

2408+
GamepadTriggerRumbleEnabled:
2409+
type: bool
2410+
status: testable
2411+
humanReadableName: "Gamepad trigger vibration support"
2412+
humanReadableDescription: "Support for Gamepad trigger vibration"
2413+
condition: ENABLE(GAMEPAD)
2414+
defaultValue:
2415+
WebKitLegacy:
2416+
default: false
2417+
WebKit:
2418+
default: false
2419+
WebCore:
2420+
default: false
2421+
24082422
GamepadVibrationActuatorEnabled:
24092423
type: bool
24102424
status: testable

Source/WebCore/Modules/gamepad/GamepadEffectParameters.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ struct GamepadEffectParameters {
3737
double strongMagnitude = 0.0;
3838
double weakMagnitude = 0.0;
3939

40+
double leftTrigger = 0.0;
41+
double rightTrigger = 0.0;
42+
4043
// A maximum duration of 5 seconds is recommended by the specification:
4144
// - https://w3c.github.io/gamepad/extensions.html#gamepadeffectparameters-dictionary
4245
static constexpr Seconds maximumDuration = 5_s;

Source/WebCore/Modules/gamepad/GamepadEffectParameters.idl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,9 @@
3131
double startDelay = 0.0;
3232
double strongMagnitude = 0.0;
3333
double weakMagnitude = 0.0;
34+
35+
// Not in the specification but supported by Blink:
36+
// https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/GamepadHapticsActuatorTriggerRumble/explainer.md
37+
double leftTrigger = 0.0;
38+
double rightTrigger = 0.0;
3439
};

Source/WebCore/Modules/gamepad/GamepadHapticActuator.cpp

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ static bool areEffectParametersValid(GamepadHapticEffectType effectType, const G
4747
if (parameters.weakMagnitude < 0 || parameters.strongMagnitude < 0 || parameters.weakMagnitude > 1 || parameters.strongMagnitude > 1)
4848
return false;
4949
}
50+
if (effectType == GamepadHapticEffectType::TriggerRumble) {
51+
if (parameters.leftTrigger < 0 || parameters.rightTrigger < 0 || parameters.leftTrigger > 1 || parameters.rightTrigger > 1)
52+
return false;
53+
}
5054
return true;
5155
}
5256

@@ -70,6 +74,9 @@ GamepadHapticActuator::~GamepadHapticActuator() = default;
7074

7175
bool GamepadHapticActuator::canPlayEffectType(EffectType effectType) const
7276
{
77+
if (effectType == EffectType::TriggerRumble && (!document() || !document()->settings().gamepadTriggerRumbleEnabled()))
78+
return false;
79+
7380
return m_gamepad && m_gamepad->supportedEffectTypes().contains(effectType);
7481
}
7582

@@ -85,7 +92,8 @@ void GamepadHapticActuator::playEffect(EffectType effectType, GamepadEffectParam
8592
promise->resolve<IDLEnumeration<Result>>(Result::Preempted);
8693
return;
8794
}
88-
if (auto playingEffectPromise = std::exchange(m_playingEffectPromise, nullptr)) {
95+
auto& currentEffectPromise = promiseForEffectType(effectType);
96+
if (auto playingEffectPromise = std::exchange(currentEffectPromise, nullptr)) {
8997
queueTaskKeepingObjectAlive(*this, TaskSource::Gamepad, [playingEffectPromise = WTFMove(playingEffectPromise)] {
9098
playingEffectPromise->resolve<IDLEnumeration<Result>>(Result::Preempted);
9199
});
@@ -97,11 +105,12 @@ void GamepadHapticActuator::playEffect(EffectType effectType, GamepadEffectParam
97105

98106
effectParameters.duration = std::min(effectParameters.duration, GamepadEffectParameters::maximumDuration.milliseconds());
99107

100-
m_playingEffectPromise = WTFMove(promise);
101-
GamepadProvider::singleton().playEffect(m_gamepad->index(), m_gamepad->id(), effectType, effectParameters, [this, protectedThis = makePendingActivity(*this), playingEffectPromise = m_playingEffectPromise](bool success) mutable {
102-
if (m_playingEffectPromise != playingEffectPromise)
108+
currentEffectPromise = WTFMove(promise);
109+
GamepadProvider::singleton().playEffect(m_gamepad->index(), m_gamepad->id(), effectType, effectParameters, [this, protectedThis = makePendingActivity(*this), playingEffectPromise = currentEffectPromise, effectType](bool success) mutable {
110+
auto& currentEffectPromise = promiseForEffectType(effectType);
111+
if (playingEffectPromise != currentEffectPromise)
103112
return; // Was already pre-empted.
104-
queueTaskKeepingObjectAlive(*this, TaskSource::Gamepad, [playingEffectPromise = std::exchange(m_playingEffectPromise, nullptr), success] {
113+
queueTaskKeepingObjectAlive(*this, TaskSource::Gamepad, [playingEffectPromise = std::exchange(currentEffectPromise, nullptr), success] {
105114
playingEffectPromise->resolve<IDLEnumeration<Result>>(success ? Result::Complete : Result::Preempted);
106115
});
107116
});
@@ -123,11 +132,16 @@ void GamepadHapticActuator::reset(Ref<DeferredPromise>&& promise)
123132

124133
void GamepadHapticActuator::stopEffects(CompletionHandler<void()>&& completionHandler)
125134
{
126-
if (!m_playingEffectPromise)
135+
if (!m_triggerRumbleEffectPromise && !m_dualRumbleEffectPromise)
127136
return completionHandler();
128137

129-
queueTaskKeepingObjectAlive(*this, TaskSource::Gamepad, [playingEffectPromise = std::exchange(m_playingEffectPromise, nullptr)] {
130-
playingEffectPromise->resolve<IDLEnumeration<Result>>(Result::Preempted);
138+
auto dualRumbleEffectPromise = std::exchange(m_dualRumbleEffectPromise, nullptr);
139+
auto triggerRumbleEffectPromise = std::exchange(m_triggerRumbleEffectPromise, nullptr);
140+
queueTaskKeepingObjectAlive(*this, TaskSource::Gamepad, [dualRumbleEffectPromise = WTFMove(dualRumbleEffectPromise), triggerRumbleEffectPromise = WTFMove(triggerRumbleEffectPromise)] {
141+
if (dualRumbleEffectPromise)
142+
dualRumbleEffectPromise->resolve<IDLEnumeration<Result>>(Result::Preempted);
143+
if (triggerRumbleEffectPromise)
144+
triggerRumbleEffectPromise->resolve<IDLEnumeration<Result>>(Result::Preempted);
131145
});
132146
GamepadProvider::singleton().stopEffects(m_gamepad->index(), m_gamepad->id(), WTFMove(completionHandler));
133147
}
@@ -137,6 +151,11 @@ Document* GamepadHapticActuator::document()
137151
return downcast<Document>(scriptExecutionContext());
138152
}
139153

154+
const Document* GamepadHapticActuator::document() const
155+
{
156+
return downcast<Document>(scriptExecutionContext());
157+
}
158+
140159
const char* GamepadHapticActuator::activeDOMObjectName() const
141160
{
142161
return "GamepadHapticActuator";
@@ -160,6 +179,17 @@ void GamepadHapticActuator::visibilityStateChanged()
160179
stopEffects([] { });
161180
}
162181

182+
RefPtr<DeferredPromise>& GamepadHapticActuator::promiseForEffectType(EffectType effectType)
183+
{
184+
switch (effectType) {
185+
case EffectType::TriggerRumble:
186+
return m_triggerRumbleEffectPromise;
187+
case EffectType::DualRumble:
188+
break;
189+
}
190+
return m_dualRumbleEffectPromise;
191+
}
192+
163193
} // namespace WebCore
164194

165195
#endif // ENABLE(GAMEPAD)

Source/WebCore/Modules/gamepad/GamepadHapticActuator.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@ class GamepadHapticActuator : public RefCounted<GamepadHapticActuator>, public A
5959
GamepadHapticActuator(Document*, Type, Gamepad&);
6060

6161
Document* document();
62+
const Document* document() const;
63+
6264
void stopEffects(CompletionHandler<void()>&&);
65+
RefPtr<DeferredPromise>& promiseForEffectType(EffectType);
6366

6467
// ActiveDOMObject.
6568
const char* activeDOMObjectName() const final;
@@ -71,7 +74,8 @@ class GamepadHapticActuator : public RefCounted<GamepadHapticActuator>, public A
7174

7275
Type m_type;
7376
WeakPtr<Gamepad> m_gamepad;
74-
RefPtr<DeferredPromise> m_playingEffectPromise;
77+
RefPtr<DeferredPromise> m_dualRumbleEffectPromise;
78+
RefPtr<DeferredPromise> m_triggerRumbleEffectPromise;
7579
};
7680

7781
} // namespace WebCore

Source/WebCore/Modules/gamepad/GamepadHapticEffectType.idl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,7 @@
2727
Conditional=GAMEPAD
2828
] enum GamepadHapticEffectType {
2929
"dual-rumble",
30-
"trigger-rumble", // Not in the specification but supported by Blink.
30+
// Not in the specification but supported by Blink:
31+
// https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/GamepadHapticsActuatorTriggerRumble/explainer.md
32+
"trigger-rumble",
3133
};

Source/WebCore/platform/gamepad/cocoa/GameControllerGamepad.mm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ static void disableDefaultSystemAction(GCControllerButtonInput *button)
7676
if ([haptics.supportedLocalities containsObject:get_GameController_GCHapticsLocalityLeftHandle()] && [haptics.supportedLocalities containsObject:get_GameController_GCHapticsLocalityRightHandle()])
7777
m_supportedEffectTypes.add(GamepadHapticEffectType::DualRumble);
7878
}
79+
if (canLoad_GameController_GCHapticsLocalityLeftTrigger() && canLoad_GameController_GCHapticsLocalityRightTrigger()) {
80+
if ([haptics.supportedLocalities containsObject:get_GameController_GCHapticsLocalityLeftTrigger()] && [haptics.supportedLocalities containsObject:get_GameController_GCHapticsLocalityRightTrigger()])
81+
m_supportedEffectTypes.add(GamepadHapticEffectType::TriggerRumble);
82+
}
7983
}
8084
#endif
8185

Source/WebCore/platform/gamepad/cocoa/GameControllerHapticEffect.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,29 +29,31 @@
2929

3030
#import <wtf/CompletionHandler.h>
3131
#import <wtf/RetainPtr.h>
32+
#import <wtf/WeakPtr.h>
3233

3334
namespace WebCore {
3435

3536
class GameControllerHapticEngines;
3637
struct GamepadEffectParameters;
38+
enum class GamepadHapticEffectType : uint8_t;
3739

38-
class GameControllerHapticEffect {
40+
class GameControllerHapticEffect : public CanMakeWeakPtr<GameControllerHapticEffect> {
3941
WTF_MAKE_FAST_ALLOCATED;
4042
public:
41-
static std::unique_ptr<GameControllerHapticEffect> create(GameControllerHapticEngines&, const GamepadEffectParameters&, CompletionHandler<void(bool)>&&);
43+
static std::unique_ptr<GameControllerHapticEffect> create(GameControllerHapticEngines&, GamepadHapticEffectType, const GamepadEffectParameters&);
4244
~GameControllerHapticEffect();
4345

44-
bool start();
46+
void start(CompletionHandler<void(bool)>&&);
4547
void stop();
4648

47-
void strongEffectFinishedPlaying();
48-
void weakEffectFinishedPlaying();
49+
void leftEffectFinishedPlaying();
50+
void rightEffectFinishedPlaying();
4951

5052
private:
51-
GameControllerHapticEffect(RetainPtr<id>&& strongPlayer, RetainPtr<id>&& weakPlayer, CompletionHandler<void(bool)>&&);
53+
GameControllerHapticEffect(RetainPtr<id>&& leftPlayer, RetainPtr<id>&& rightPlayer);
5254

53-
RetainPtr<id> m_strongPlayer;
54-
RetainPtr<id> m_weakPlayer;
55+
RetainPtr<id> m_leftPlayer;
56+
RetainPtr<id> m_rightPlayer;
5557
CompletionHandler<void(bool)> m_completionHandler;
5658
};
5759

Source/WebCore/platform/gamepad/cocoa/GameControllerHapticEffect.mm

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
#import "GameControllerHapticEngines.h"
3232
#import "GamepadEffectParameters.h"
33+
#import "GamepadHapticEffectType.h"
3334
#import "Logging.h"
3435
#import <cmath>
3536

@@ -45,7 +46,7 @@ static double magnitudeToIntensity(double magnitude)
4546
return std::sqrt(std::clamp<double>(magnitude, 0, 1));
4647
}
4748

48-
std::unique_ptr<GameControllerHapticEffect> GameControllerHapticEffect::create(GameControllerHapticEngines& engines, const GamepadEffectParameters& parameters, CompletionHandler<void(bool)>&& completionHandler)
49+
std::unique_ptr<GameControllerHapticEffect> GameControllerHapticEffect::create(GameControllerHapticEngines& engines, GamepadHapticEffectType type, const GamepadEffectParameters& parameters)
4950
{
5051
auto createPlayer = [&](CHHapticEngine *engine, double magnitude) -> RetainPtr<id> {
5152
NSDictionary* hapticDict = @{
@@ -71,20 +72,32 @@ static double magnitudeToIntensity(double magnitude)
7172

7273
return retainPtr([engine createPlayerWithPattern:pattern.get() error:&error]);
7374
};
74-
auto strongPlayer = createPlayer(engines.strongEngine(), parameters.strongMagnitude);
75-
auto weakPlayer = createPlayer(engines.weakEngine(), parameters.weakMagnitude);
76-
if (!strongPlayer || !weakPlayer) {
75+
76+
RetainPtr<id> leftPlayer;
77+
RetainPtr<id> rightPlayer;
78+
switch (type) {
79+
case GamepadHapticEffectType::DualRumble: {
80+
leftPlayer = createPlayer(engines.leftHandleEngine(), parameters.strongMagnitude);
81+
rightPlayer = createPlayer(engines.rightHandleEngine(), parameters.weakMagnitude);
82+
break;
83+
}
84+
case GamepadHapticEffectType::TriggerRumble: {
85+
leftPlayer = createPlayer(engines.leftTriggerEngine(), parameters.leftTrigger);
86+
rightPlayer = createPlayer(engines.rightTriggerEngine(), parameters.rightTrigger);
87+
break;
88+
}
89+
}
90+
91+
if (!leftPlayer || !rightPlayer) {
7792
RELEASE_LOG_ERROR(Gamepad, "GameControllerHapticEffect: Failed to create the haptic effect players");
78-
completionHandler(false);
7993
return nullptr;
8094
}
81-
return std::unique_ptr<GameControllerHapticEffect>(new GameControllerHapticEffect(WTFMove(strongPlayer), WTFMove(weakPlayer), WTFMove(completionHandler)));
95+
return std::unique_ptr<GameControllerHapticEffect>(new GameControllerHapticEffect(WTFMove(leftPlayer), WTFMove(rightPlayer)));
8296
}
8397

84-
GameControllerHapticEffect::GameControllerHapticEffect(RetainPtr<id>&& strongPlayer, RetainPtr<id>&& weakPlayer, CompletionHandler<void(bool)>&& completionHandler)
85-
: m_strongPlayer(WTFMove(strongPlayer))
86-
, m_weakPlayer(WTFMove(weakPlayer))
87-
, m_completionHandler(WTFMove(completionHandler))
98+
GameControllerHapticEffect::GameControllerHapticEffect(RetainPtr<id>&& leftPlayer, RetainPtr<id>&& rightPlayer)
99+
: m_leftPlayer(WTFMove(leftPlayer))
100+
, m_rightPlayer(WTFMove(rightPlayer))
88101
{
89102
}
90103

@@ -94,40 +107,44 @@ static double magnitudeToIntensity(double magnitude)
94107
m_completionHandler(false);
95108
}
96109

97-
bool GameControllerHapticEffect::start()
110+
void GameControllerHapticEffect::start(CompletionHandler<void(bool)>&& completionHandler)
98111
{
112+
ASSERT(!m_completionHandler);
113+
m_completionHandler = WTFMove(completionHandler);
114+
99115
NSError *error;
100-
if (m_strongPlayer && ![m_strongPlayer startAtTime:0 error:&error]) {
116+
if (m_leftPlayer && ![m_leftPlayer startAtTime:0 error:&error]) {
101117
RELEASE_LOG_ERROR(Gamepad, "GameControllerHapticEffect::start: Failed to start the strong player");
102-
m_strongPlayer = nullptr;
118+
m_leftPlayer = nullptr;
103119
}
104-
if (m_weakPlayer && ![m_weakPlayer startAtTime:0 error:&error]) {
120+
if (m_rightPlayer && ![m_rightPlayer startAtTime:0 error:&error]) {
105121
RELEASE_LOG_ERROR(Gamepad, "GameControllerHapticEffect::start: Failed to start the weak player");
106-
m_weakPlayer = nullptr;
122+
m_rightPlayer = nullptr;
107123
}
108-
return m_strongPlayer || m_weakPlayer;
124+
if (!m_leftPlayer && !m_rightPlayer)
125+
m_completionHandler(false);
109126
}
110127

111128
void GameControllerHapticEffect::stop()
112129
{
113130
NSError *error;
114-
if (auto player = std::exchange(m_strongPlayer, nullptr))
131+
if (auto player = std::exchange(m_leftPlayer, nullptr))
115132
[player stopAtTime:0.0 error:&error];
116-
if (auto player = std::exchange(m_weakPlayer, nullptr))
133+
if (auto player = std::exchange(m_rightPlayer, nullptr))
117134
[player stopAtTime:0.0 error:&error];
118135
}
119136

120-
void GameControllerHapticEffect::strongEffectFinishedPlaying()
137+
void GameControllerHapticEffect::leftEffectFinishedPlaying()
121138
{
122-
m_strongPlayer = nullptr;
123-
if (!m_weakPlayer && m_completionHandler)
139+
m_leftPlayer = nullptr;
140+
if (!m_rightPlayer && m_completionHandler)
124141
m_completionHandler(true);
125142
}
126143

127-
void GameControllerHapticEffect::weakEffectFinishedPlaying()
144+
void GameControllerHapticEffect::rightEffectFinishedPlaying()
128145
{
129-
m_weakPlayer = nullptr;
130-
if (!m_strongPlayer && m_completionHandler)
146+
m_rightPlayer = nullptr;
147+
if (!m_leftPlayer && m_completionHandler)
131148
m_completionHandler(true);
132149
}
133150

Source/WebCore/platform/gamepad/cocoa/GameControllerHapticEngines.h

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,27 @@ class GameControllerHapticEngines : public CanMakeWeakPtr<GameControllerHapticEn
5151

5252
void stop(CompletionHandler<void()>&&);
5353

54-
CHHapticEngine *strongEngine() { return m_strongEngine.get(); }
55-
CHHapticEngine *weakEngine() { return m_weakEngine.get(); }
54+
CHHapticEngine *leftHandleEngine() { return m_leftHandleEngine.get(); }
55+
CHHapticEngine *rightHandleEngine() { return m_rightHandleEngine.get(); }
56+
CHHapticEngine *leftTriggerEngine() { return m_leftTriggerEngine.get(); }
57+
CHHapticEngine *rightTriggerEngine() { return m_rightTriggerEngine.get(); }
5658

5759
private:
5860
explicit GameControllerHapticEngines(GCController *);
5961

60-
void ensureStarted(CompletionHandler<void(bool)>&&);
62+
void ensureStarted(GamepadHapticEffectType, CompletionHandler<void(bool)>&&);
63+
std::unique_ptr<GameControllerHapticEffect>& currentEffectForType(GamepadHapticEffectType);
6164

62-
RetainPtr<CHHapticEngine> m_strongEngine;
63-
RetainPtr<CHHapticEngine> m_weakEngine;
64-
bool m_failedToStartStrongEngine { false };
65-
bool m_failedToStartWeakEngine { false };
66-
std::unique_ptr<GameControllerHapticEffect> m_currentEffect;
65+
RetainPtr<CHHapticEngine> m_leftHandleEngine;
66+
RetainPtr<CHHapticEngine> m_rightHandleEngine;
67+
RetainPtr<CHHapticEngine> m_leftTriggerEngine;
68+
RetainPtr<CHHapticEngine> m_rightTriggerEngine;
69+
bool m_failedToStartLeftHandleEngine { false };
70+
bool m_failedToStartRightHandleEngine { false };
71+
bool m_failedToStartLeftTriggerEngine { false };
72+
bool m_failedToStartRightTriggerEngine { false };
73+
std::unique_ptr<GameControllerHapticEffect> m_currentDualRumbleEffect;
74+
std::unique_ptr<GameControllerHapticEffect> m_currentTriggerRumbleEffect;
6775
};
6876

6977
} // namespace WebCore

0 commit comments

Comments
 (0)