Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 26 additions & 7 deletions Source/WebCore/PlatformWPE.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,32 @@ elseif (USE_LIBDRM)
endif ()

if (ENABLE_GAMEPAD)
list(APPEND WebCore_PRIVATE_INCLUDE_DIRECTORIES
"${WEBCORE_DIR}/platform/gamepad/libwpe"
)

list(APPEND WebCore_PRIVATE_FRAMEWORK_HEADERS
platform/gamepad/libwpe/GamepadProviderLibWPE.h
)
if (USE_MANETTE_GAMEPAD_PROVIDER)
list(APPEND WebCore_PRIVATE_INCLUDE_DIRECTORIES
"${WEBCORE_DIR}/platform/gamepad/manette"
)
list(APPEND WebCore_PRIVATE_FRAMEWORK_HEADERS
platform/gamepad/manette/ManetteGamepadProvider.h
)
list(APPEND WebCore_LIBRARIES
Manette::Manette
)
list(APPEND WebCore_SOURCES
platform/gamepad/manette/ManetteGamepad.cpp
platform/gamepad/manette/ManetteGamepadProvider.cpp
)
else ()
list(APPEND WebCore_PRIVATE_INCLUDE_DIRECTORIES
"${WEBCORE_DIR}/platform/gamepad/libwpe"
)
list(APPEND WebCore_PRIVATE_FRAMEWORK_HEADERS
platform/gamepad/libwpe/GamepadProviderLibWPE.h
)
list(APPEND WebCore_SOURCES
platform/gamepad/libwpe/GamepadLibWPE.cpp
platform/gamepad/libwpe/GamepadProviderLibWPE.cpp
)
endif ()
endif ()

if (ENABLE_SPEECH_SYNTHESIS)
Expand Down
2 changes: 0 additions & 2 deletions Source/WebCore/SourcesWPE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@ loader/soup/ResourceLoaderSoup.cpp
page/linux/ResourceUsageOverlayLinux.cpp
page/linux/ResourceUsageThreadLinux.cpp

platform/gamepad/libwpe/GamepadLibWPE.cpp
platform/gamepad/libwpe/GamepadProviderLibWPE.cpp

platform/generic/ScrollbarsControllerGeneric.cpp

Expand Down
169 changes: 169 additions & 0 deletions Source/WebCore/platform/gamepad/manette/ManetteGamepad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,35 @@

#if ENABLE(GAMEPAD) && OS(LINUX)

#ifndef MANETTE_CHECK_VERSION
#define MANETTE_CHECK_VERSION(major,minor,micro) 0
#endif

#include "ManetteGamepadProvider.h"
#include <linux/input-event-codes.h>
#include <wtf/HexNumber.h>
#include <wtf/text/CString.h>

namespace WebCore {

#if MANETTE_CHECK_VERSION(1, 0, 0)
static ManetteGamepad::StandardGamepadAxis toStandardGamepadAxis(ManetteAxis axis)
{
switch (axis) {
case MANETTE_AXIS_LEFT_X:
return ManetteGamepad::StandardGamepadAxis::LeftStickX;
case MANETTE_AXIS_LEFT_Y:
return ManetteGamepad::StandardGamepadAxis::LeftStickY;
case MANETTE_AXIS_RIGHT_X:
return ManetteGamepad::StandardGamepadAxis::RightStickX;
case MANETTE_AXIS_RIGHT_Y:
return ManetteGamepad::StandardGamepadAxis::RightStickY;
default:
break;
}
return ManetteGamepad::StandardGamepadAxis::Unknown;
}
#else
static ManetteGamepad::StandardGamepadAxis toStandardGamepadAxis(uint16_t axis)
{
switch (axis) {
Expand All @@ -51,7 +73,23 @@ static ManetteGamepad::StandardGamepadAxis toStandardGamepadAxis(uint16_t axis)
}
return ManetteGamepad::StandardGamepadAxis::Unknown;
}
#endif

#if MANETTE_CHECK_VERSION(1, 0, 0)
static void onAbsoluteAxisChanged(ManetteDevice* device, ManetteAxis axis, double value, ManetteGamepad* gamepad)
{
if (axis == MANETTE_AXIS_LEFT_TRIGGER) {
gamepad->analogButtonChanged(device, ManetteGamepad::StandardGamepadButton::LeftTrigger, value);
return;
}
if (axis == MANETTE_AXIS_RIGHT_TRIGGER) {
gamepad->analogButtonChanged(device, ManetteGamepad::StandardGamepadButton::RightTrigger, value);
return;
}

gamepad->absoluteAxisChanged(device, toStandardGamepadAxis(axis), value);
}
#else
static void onAbsoluteAxisEvent(ManetteDevice* device, ManetteEvent* event, ManetteGamepad* gamepad)
{
uint16_t axis;
Expand All @@ -61,7 +99,48 @@ static void onAbsoluteAxisEvent(ManetteDevice* device, ManetteEvent* event, Mane

gamepad->absoluteAxisChanged(device, toStandardGamepadAxis(axis), value);
}
#endif

#if MANETTE_CHECK_VERSION(1, 0, 0)
static ManetteGamepad::StandardGamepadButton toStandardGamepadButton(ManetteButton button)
{
switch (button) {
case MANETTE_BUTTON_SOUTH:
return ManetteGamepad::StandardGamepadButton::A;
case MANETTE_BUTTON_EAST:
return ManetteGamepad::StandardGamepadButton::B;
case MANETTE_BUTTON_WEST:
return ManetteGamepad::StandardGamepadButton::X;
case MANETTE_BUTTON_NORTH:
return ManetteGamepad::StandardGamepadButton::Y;
case MANETTE_BUTTON_LEFT_SHOULDER:
return ManetteGamepad::StandardGamepadButton::LeftShoulder;
case MANETTE_BUTTON_RIGHT_SHOULDER:
return ManetteGamepad::StandardGamepadButton::RightShoulder;
case MANETTE_BUTTON_SELECT:
return ManetteGamepad::StandardGamepadButton::Select;
case MANETTE_BUTTON_START:
return ManetteGamepad::StandardGamepadButton::Start;
case MANETTE_BUTTON_LEFT_STICK:
return ManetteGamepad::StandardGamepadButton::LeftStick;
case MANETTE_BUTTON_RIGHT_STICK:
return ManetteGamepad::StandardGamepadButton::RightStick;
case MANETTE_BUTTON_DPAD_UP:
return ManetteGamepad::StandardGamepadButton::DPadUp;
case MANETTE_BUTTON_DPAD_DOWN:
return ManetteGamepad::StandardGamepadButton::DPadDown;
case MANETTE_BUTTON_DPAD_LEFT:
return ManetteGamepad::StandardGamepadButton::DPadLeft;
case MANETTE_BUTTON_DPAD_RIGHT:
return ManetteGamepad::StandardGamepadButton::DPadRight;
case MANETTE_BUTTON_MODE:
return ManetteGamepad::StandardGamepadButton::Mode;
default:
break;
}
return ManetteGamepad::StandardGamepadButton::Unknown;
}
#else
static ManetteGamepad::StandardGamepadButton toStandardGamepadButton(uint16_t manetteButton)
{
switch (manetteButton) {
Expand Down Expand Up @@ -104,7 +183,19 @@ static ManetteGamepad::StandardGamepadButton toStandardGamepadButton(uint16_t ma
}
return ManetteGamepad::StandardGamepadButton::Unknown;
}
#endif

#if MANETTE_CHECK_VERSION(1, 0, 0)
static void onButtonPressed(ManetteDevice* device, ManetteButton button, ManetteGamepad* gamepad)
{
gamepad->buttonPressedOrReleased(device, toStandardGamepadButton(button), true);
}

static void onButtonReleased(ManetteDevice* device, ManetteButton button, ManetteGamepad* gamepad)
{
gamepad->buttonPressedOrReleased(device, toStandardGamepadButton(button), false);
}
#else
static void onButtonPressEvent(ManetteDevice* device, ManetteEvent* event, ManetteGamepad* gamepad)
{
uint16_t button;
Expand All @@ -122,10 +213,13 @@ static void onButtonReleaseEvent(ManetteDevice* device, ManetteEvent* event, Man

gamepad->buttonPressedOrReleased(device, toStandardGamepadButton(button), false);
}
#endif

ManetteGamepad::ManetteGamepad(ManetteDevice* device, unsigned index)
: PlatformGamepad(index)
, m_device(device)
, m_effectDelayTimer(RunLoop::current(), this, &ManetteGamepad::effectDelayTimerFired)
, m_effectDurationTimer(RunLoop::current(), this, &ManetteGamepad::effectDurationTimerFired)
{
ASSERT(index < 4);

Expand All @@ -142,9 +236,18 @@ ManetteGamepad::ManetteGamepad(ManetteDevice* device, unsigned index)
for (auto& value : m_buttonValues)
value.setValue(0.0);

if (manette_device_has_rumble(m_device.get()))
m_supportedEffectTypes.add(GamepadHapticEffectType::DualRumble);

#if MANETTE_CHECK_VERSION(1, 0, 0)
g_signal_connect(device, "button-pressed", G_CALLBACK(onButtonPressed), this);
g_signal_connect(device, "button-released", G_CALLBACK(onButtonReleased), this);
g_signal_connect(device, "absolute-axis-changed", G_CALLBACK(onAbsoluteAxisChanged), this);
#else
g_signal_connect(device, "button-press-event", G_CALLBACK(onButtonPressEvent), this);
g_signal_connect(device, "button-release-event", G_CALLBACK(onButtonReleaseEvent), this);
g_signal_connect(device, "absolute-axis-event", G_CALLBACK(onAbsoluteAxisEvent), this);
#endif
}

ManetteGamepad::~ManetteGamepad()
Expand Down Expand Up @@ -174,6 +277,72 @@ void ManetteGamepad::absoluteAxisChanged(ManetteDevice*, StandardGamepadAxis axi
ManetteGamepadProvider::singleton().gamepadHadInput(*this, ManetteGamepadProvider::ShouldMakeGamepadsVisible::Yes);
}

void ManetteGamepad::analogButtonChanged(ManetteDevice*, StandardGamepadButton button, double value)
{
if (button == StandardGamepadButton::Unknown)
return;

m_lastUpdateTime = MonotonicTime::now();
m_buttonValues[static_cast<int>(button)].setValue(clampTo(value, 0.0, 1.0));

ManetteGamepadProvider::singleton().gamepadHadInput(*this, ManetteGamepadProvider::ShouldMakeGamepadsVisible::Yes);
}

void ManetteGamepad::playEffect(GamepadHapticEffectType type, const GamepadEffectParameters& parameters, CompletionHandler<void(bool)>&& completionHandler)
{
if (!m_supportedEffectTypes.contains(type))
return completionHandler(false);

if (m_effectCompletionHandler)
stopEffects({ });

m_effectCompletionHandler = WTFMove(completionHandler);
if (parameters.startDelay) {
m_pendingEffectParameters = parameters;
m_effectDelayTimer.startOneShot(Seconds::fromMilliseconds(parameters.startDelay));
return;
}

startRumble(parameters);
}

void ManetteGamepad::stopEffects(CompletionHandler<void()>&& completionHandler)
{
m_effectDelayTimer.stop();
m_effectDurationTimer.stop();
if (m_effectCompletionHandler)
m_effectCompletionHandler(false);

manette_device_rumble(m_device.get(), 0, 0, 0);

if (completionHandler)
completionHandler();
}

void ManetteGamepad::effectDelayTimerFired()
{
startRumble(std::exchange(m_pendingEffectParameters, { }));
}

void ManetteGamepad::startRumble(const GamepadEffectParameters& parameters)
{
#if MANETTE_CHECK_VERSION(0, 2, 13)
manette_device_rumble(m_device.get(), parameters.strongMagnitude, parameters.weakMagnitude, static_cast<guint>(parameters.duration));
#else
manette_device_rumble(m_device.get(), parameters.strongMagnitude * G_MAXUINT16, parameters.weakMagnitude * G_MAXUINT16, static_cast<guint>(parameters.duration));
#endif

if (parameters.duration)
m_effectDurationTimer.startOneShot(Seconds::fromMilliseconds(parameters.duration));
else
m_effectCompletionHandler(true);
}

void ManetteGamepad::effectDurationTimerFired()
{
m_effectCompletionHandler(true);
}

} // namespace WebCore

#endif // ENABLE(GAMEPAD) && OS(LINUX)
19 changes: 15 additions & 4 deletions Source/WebCore/platform/gamepad/manette/ManetteGamepad.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@

#if ENABLE(GAMEPAD) && OS(LINUX)

#include "GamepadEffectParameters.h"
#include "PlatformGamepad.h"

#include <libmanette.h>
#include <wtf/HashMap.h>
#include <wtf/RunLoop.h>
#include <wtf/glib/GRefPtr.h>

namespace WebCore {
Expand Down Expand Up @@ -71,17 +72,27 @@ class ManetteGamepad final : public PlatformGamepad {
ManetteGamepad(ManetteDevice*, unsigned index);
virtual ~ManetteGamepad();

const Vector<SharedGamepadValue>& axisValues() const final { return m_axisValues; }
const Vector<SharedGamepadValue>& buttonValues() const final { return m_buttonValues; }

void absoluteAxisChanged(ManetteDevice*, StandardGamepadAxis, double value);
void buttonPressedOrReleased(ManetteDevice*, StandardGamepadButton, bool pressed);
void analogButtonChanged(ManetteDevice*, StandardGamepadButton, double value);
void playEffect(GamepadHapticEffectType, const GamepadEffectParameters&, CompletionHandler<void(bool)>&&) final;
void stopEffects(CompletionHandler<void()>&&) final;

private:
const Vector<SharedGamepadValue>& axisValues() const final { return m_axisValues; }
const Vector<SharedGamepadValue>& buttonValues() const final { return m_buttonValues; }
void effectDelayTimerFired();
void effectDurationTimerFired();
void startRumble(const GamepadEffectParameters&);

GRefPtr<ManetteDevice> m_device;

Vector<SharedGamepadValue> m_buttonValues;
Vector<SharedGamepadValue> m_axisValues;
RunLoop::Timer m_effectDelayTimer;
RunLoop::Timer m_effectDurationTimer;
CompletionHandler<void(bool)> m_effectCompletionHandler;
GamepadEffectParameters m_pendingEffectParameters;
};

} // namespace WebCore
Expand Down
36 changes: 30 additions & 6 deletions Source/WebCore/platform/gamepad/manette/ManetteGamepadProvider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@

#if ENABLE(GAMEPAD) && OS(LINUX)

#ifndef MANETTE_CHECK_VERSION
#define MANETTE_CHECK_VERSION(major,minor,micro) 0
#endif

#if !MANETTE_CHECK_VERSION(1, 0, 0)
#include "GUniquePtrManette.h"
#endif
#include "GamepadProviderClient.h"
#include "Logging.h"
#include "ManetteGamepad.h"
Expand Down Expand Up @@ -90,10 +96,18 @@ void ManetteGamepadProvider::startMonitoringGamepads(GamepadProviderClient& clie
m_initialGamepadsConnectedTimer.startOneShot(connectionDelayInterval);

RunLoop::current().dispatch([this] {
#if MANETTE_CHECK_VERSION(1, 0, 0)
gsize numDevices = 0;
ManetteDevice** devices = manette_monitor_list_devices(m_monitor.get(), &numDevices);
for (gsize i = 0; i < numDevices; i++)
deviceConnected(devices[i]);
g_free(devices);
#else
ManetteDevice* device;
GUniquePtr<ManetteMonitorIter> iter(manette_monitor_iterate(m_monitor.get()));
while (manette_monitor_iter_next(iter.get(), &device))
deviceConnected(device);
#endif
});
}

Expand Down Expand Up @@ -196,16 +210,26 @@ std::unique_ptr<ManetteGamepad> ManetteGamepadProvider::removeGamepadForDevice(M
return result;
}

void ManetteGamepadProvider::playEffect(unsigned, const String&, GamepadHapticEffectType, const GamepadEffectParameters&, CompletionHandler<void(bool)>&& completionHandler)
void ManetteGamepadProvider::playEffect(unsigned gamepadIndex, const String& gamepadID, GamepadHapticEffectType type, const GamepadEffectParameters& parameters, CompletionHandler<void(bool)>&& completionHandler)
{
// Not supported by this provider.
completionHandler(false);
if (gamepadIndex >= m_gamepadVector.size())
return completionHandler(false);
auto gamepad = m_gamepadVector[gamepadIndex];
if (!gamepad || gamepad->id() != gamepadID)
return completionHandler(false);

static_cast<ManetteGamepad*>(gamepad.get())->playEffect(type, parameters, WTFMove(completionHandler));
}

void ManetteGamepadProvider::stopEffects(unsigned, const String&, CompletionHandler<void()>&& completionHandler)
void ManetteGamepadProvider::stopEffects(unsigned gamepadIndex, const String& gamepadID, CompletionHandler<void()>&& completionHandler)
{
// Not supported by this provider.
completionHandler();
if (gamepadIndex >= m_gamepadVector.size())
return completionHandler();
auto gamepad = m_gamepadVector[gamepadIndex];
if (!gamepad || gamepad->id() != gamepadID)
return completionHandler();

static_cast<ManetteGamepad*>(gamepad.get())->stopEffects(WTFMove(completionHandler));
}

} // namespace WebCore
Expand Down
Loading