diff --git a/Source/WebCore/PlatformWPE.cmake b/Source/WebCore/PlatformWPE.cmake index d133eae894734..52d7a70cc30e9 100644 --- a/Source/WebCore/PlatformWPE.cmake +++ b/Source/WebCore/PlatformWPE.cmake @@ -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) diff --git a/Source/WebCore/SourcesWPE.txt b/Source/WebCore/SourcesWPE.txt index 891c8ea264628..28a5d1572b84c 100644 --- a/Source/WebCore/SourcesWPE.txt +++ b/Source/WebCore/SourcesWPE.txt @@ -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 diff --git a/Source/WebCore/platform/gamepad/manette/ManetteGamepad.cpp b/Source/WebCore/platform/gamepad/manette/ManetteGamepad.cpp index 58d707a5ef9c4..150772fb3a3e7 100644 --- a/Source/WebCore/platform/gamepad/manette/ManetteGamepad.cpp +++ b/Source/WebCore/platform/gamepad/manette/ManetteGamepad.cpp @@ -28,6 +28,10 @@ #if ENABLE(GAMEPAD) && OS(LINUX) +#ifndef MANETTE_CHECK_VERSION +#define MANETTE_CHECK_VERSION(major,minor,micro) 0 +#endif + #include "ManetteGamepadProvider.h" #include #include @@ -35,6 +39,24 @@ 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) { @@ -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; @@ -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) { @@ -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; @@ -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); @@ -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() @@ -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(button)].setValue(clampTo(value, 0.0, 1.0)); + + ManetteGamepadProvider::singleton().gamepadHadInput(*this, ManetteGamepadProvider::ShouldMakeGamepadsVisible::Yes); +} + +void ManetteGamepad::playEffect(GamepadHapticEffectType type, const GamepadEffectParameters& parameters, CompletionHandler&& 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&& 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(parameters.duration)); +#else + manette_device_rumble(m_device.get(), parameters.strongMagnitude * G_MAXUINT16, parameters.weakMagnitude * G_MAXUINT16, static_cast(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) diff --git a/Source/WebCore/platform/gamepad/manette/ManetteGamepad.h b/Source/WebCore/platform/gamepad/manette/ManetteGamepad.h index 172b05ae6e397..d917c368f868b 100644 --- a/Source/WebCore/platform/gamepad/manette/ManetteGamepad.h +++ b/Source/WebCore/platform/gamepad/manette/ManetteGamepad.h @@ -27,10 +27,11 @@ #if ENABLE(GAMEPAD) && OS(LINUX) +#include "GamepadEffectParameters.h" #include "PlatformGamepad.h" #include -#include +#include #include namespace WebCore { @@ -71,17 +72,27 @@ class ManetteGamepad final : public PlatformGamepad { ManetteGamepad(ManetteDevice*, unsigned index); virtual ~ManetteGamepad(); - const Vector& axisValues() const final { return m_axisValues; } - const Vector& 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&&) final; + void stopEffects(CompletionHandler&&) final; private: + const Vector& axisValues() const final { return m_axisValues; } + const Vector& buttonValues() const final { return m_buttonValues; } + void effectDelayTimerFired(); + void effectDurationTimerFired(); + void startRumble(const GamepadEffectParameters&); + GRefPtr m_device; Vector m_buttonValues; Vector m_axisValues; + RunLoop::Timer m_effectDelayTimer; + RunLoop::Timer m_effectDurationTimer; + CompletionHandler m_effectCompletionHandler; + GamepadEffectParameters m_pendingEffectParameters; }; } // namespace WebCore diff --git a/Source/WebCore/platform/gamepad/manette/ManetteGamepadProvider.cpp b/Source/WebCore/platform/gamepad/manette/ManetteGamepadProvider.cpp index 1782e8c2f7aa7..7ff01c3d8fa6f 100644 --- a/Source/WebCore/platform/gamepad/manette/ManetteGamepadProvider.cpp +++ b/Source/WebCore/platform/gamepad/manette/ManetteGamepadProvider.cpp @@ -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" @@ -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 iter(manette_monitor_iterate(m_monitor.get())); while (manette_monitor_iter_next(iter.get(), &device)) deviceConnected(device); +#endif }); } @@ -196,16 +210,26 @@ std::unique_ptr ManetteGamepadProvider::removeGamepadForDevice(M return result; } -void ManetteGamepadProvider::playEffect(unsigned, const String&, GamepadHapticEffectType, const GamepadEffectParameters&, CompletionHandler&& completionHandler) +void ManetteGamepadProvider::playEffect(unsigned gamepadIndex, const String& gamepadID, GamepadHapticEffectType type, const GamepadEffectParameters& parameters, CompletionHandler&& 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(gamepad.get())->playEffect(type, parameters, WTFMove(completionHandler)); } -void ManetteGamepadProvider::stopEffects(unsigned, const String&, CompletionHandler&& completionHandler) +void ManetteGamepadProvider::stopEffects(unsigned gamepadIndex, const String& gamepadID, CompletionHandler&& 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(gamepad.get())->stopEffects(WTFMove(completionHandler)); } } // namespace WebCore diff --git a/Source/WebKit/PlatformWPE.cmake b/Source/WebKit/PlatformWPE.cmake index 1c067e128f4df..b65a5407dec37 100644 --- a/Source/WebKit/PlatformWPE.cmake +++ b/Source/WebKit/PlatformWPE.cmake @@ -468,6 +468,18 @@ if (ENABLE_BUBBLEWRAP_SANDBOX) list(APPEND WebKit_LIBRARIES Libseccomp::Libseccomp) endif () +if (ENABLE_GAMEPAD) + if (USE_MANETTE_GAMEPAD_PROVIDER) + list(APPEND WebKit_SOURCES + UIProcess/Gamepad/manette/UIGamepadProviderManette.cpp + ) + else () + list(APPEND WebKit_SOURCES + UIProcess/Gamepad/libwpe/UIGamepadProviderLibWPE.cpp + ) + endif () +endif () + if (USE_GSTREAMER_FULL) list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES ${GSTREAMER_FULL_INCLUDE_DIRS} diff --git a/Source/WebKit/Shared/WebPreferencesDefaultValues.cpp b/Source/WebKit/Shared/WebPreferencesDefaultValues.cpp index 6b4d3406cc7ba..3c50779e79b5c 100644 --- a/Source/WebKit/Shared/WebPreferencesDefaultValues.cpp +++ b/Source/WebKit/Shared/WebPreferencesDefaultValues.cpp @@ -271,7 +271,7 @@ bool defaultShowModalDialogEnabled() #if ENABLE(GAMEPAD) bool defaultGamepadVibrationActuatorEnabled() { -#if HAVE(WIDE_GAMECONTROLLER_SUPPORT) +#if HAVE(WIDE_GAMECONTROLLER_SUPPORT) || USE(MANETTE) return true; #else return false; diff --git a/Source/WebKit/SourcesWPE.txt b/Source/WebKit/SourcesWPE.txt index 7f5d22aad87f1..b4298dc6b1cbf 100644 --- a/Source/WebKit/SourcesWPE.txt +++ b/Source/WebKit/SourcesWPE.txt @@ -220,7 +220,6 @@ UIProcess/Automation/libwpe/WebAutomationSessionWPE.cpp UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp -UIProcess/Gamepad/libwpe/UIGamepadProviderLibWPE.cpp UIProcess/geoclue/GeoclueGeolocationProvider.cpp diff --git a/Source/WebKit/UIProcess/API/wpe/WPEWebViewLegacy.cpp b/Source/WebKit/UIProcess/API/wpe/WPEWebViewLegacy.cpp index 51f763d4dcae1..4724617ae896b 100644 --- a/Source/WebKit/UIProcess/API/wpe/WPEWebViewLegacy.cpp +++ b/Source/WebKit/UIProcess/API/wpe/WPEWebViewLegacy.cpp @@ -38,7 +38,7 @@ #include #include -#if ENABLE(GAMEPAD) +#if ENABLE(GAMEPAD) && !USE(MANETTE_GAMEPAD_PROVIDER) #include #endif @@ -389,6 +389,12 @@ WebKit::WebPageProxy* ViewLegacy::platformWebPageProxyForGamepadInput() if (views.isEmpty()) return nullptr; +#if USE(MANETTE_GAMEPAD_PROVIDER) + auto index = views.findIf([](ViewLegacy* view) { + return view->viewState().contains(WebCore::ActivityState::IsVisible) + && view->viewState().contains(WebCore::ActivityState::IsFocused); + }); +#else struct wpe_view_backend* viewBackend = WebCore::GamepadProviderLibWPE::singleton().inputView(); size_t index = notFound; @@ -405,6 +411,7 @@ WebKit::WebPageProxy* ViewLegacy::platformWebPageProxyForGamepadInput() && view->viewState().contains(WebCore::ActivityState::IsFocused); }); } +#endif if (index != notFound) return &(views[index]->page()); diff --git a/Source/WebKit/UIProcess/Gamepad/manette/UIGamepadProviderManette.cpp b/Source/WebKit/UIProcess/Gamepad/manette/UIGamepadProviderManette.cpp index a16ea593bbf82..a74245fb1383e 100644 --- a/Source/WebKit/UIProcess/Gamepad/manette/UIGamepadProviderManette.cpp +++ b/Source/WebKit/UIProcess/Gamepad/manette/UIGamepadProviderManette.cpp @@ -32,6 +32,10 @@ #include #include +#if PLATFORM(WPE) +#include "WPEWebViewLegacy.h" +#endif + namespace WebKit { using namespace WebCore; @@ -47,7 +51,11 @@ void UIGamepadProvider::platformSetDefaultGamepadProvider() #if !PLATFORM(GTK) WebPageProxy* UIGamepadProvider::platformWebPageProxyForGamepadInput() { +#if PLATFORM(WPE) && USE(MANETTE_GAMEPAD_PROVIDER) + return WKWPE::ViewLegacy::platformWebPageProxyForGamepadInput(); +#else return nullptr; +#endif } #endif diff --git a/Source/cmake/FindManette.cmake b/Source/cmake/FindManette.cmake index 5c1551c1feb69..b2ffd16641b99 100644 --- a/Source/cmake/FindManette.cmake +++ b/Source/cmake/FindManette.cmake @@ -53,7 +53,13 @@ This will define the following variables in your project: #]=======================================================================] find_package(PkgConfig QUIET) -pkg_check_modules(PC_MANETTE QUIET manette-0.2) + +# Try manette-1 first (libmanette 1.0), fall back to manette-0.2 +pkg_check_modules(PC_MANETTE QUIET manette-1) +if (NOT PC_MANETTE_FOUND) + pkg_check_modules(PC_MANETTE QUIET manette-0.2) +endif () + set(Manette_COMPILE_OPTIONS ${PC_MANETTE_CFLAGS_OTHER}) set(Manette_VERSION ${PC_MANETTE_VERSION}) @@ -64,7 +70,7 @@ find_path(Manette_INCLUDE_DIR ) find_library(Manette_LIBRARY - NAMES ${Manette_NAMES} manette-0.2 + NAMES ${Manette_NAMES} manette-1 manette-0.2 HINTS ${PC_MANETTE_LIBDIR} ${PC_MANETTE_LIBRARY_DIRS} ) diff --git a/Source/cmake/OptionsWPE.cmake b/Source/cmake/OptionsWPE.cmake index 41fb857ec5aea..7928a5ff8b288 100644 --- a/Source/cmake/OptionsWPE.cmake +++ b/Source/cmake/OptionsWPE.cmake @@ -236,6 +236,19 @@ if (ENABLE_GAMEPAD AND (NOT (WPE_VERSION VERSION_GREATER_EQUAL 1.16.2))) message(FATAL_ERROR "libwpe>=1.16.2 is required for ENABLE_GAMEPAD") endif () +option(USE_MANETTE_GAMEPAD_PROVIDER "Use ManetteGamepadProvider (direct libmanette) instead of libwpe gamepad" OFF) + +if (ENABLE_GAMEPAD) + if (USE_MANETTE_GAMEPAD_PROVIDER) + find_package(Manette) + if (NOT Manette_FOUND) + message(FATAL_ERROR "libmanette is required for USE_MANETTE_GAMEPAD_PROVIDER") + endif () + SET_AND_EXPOSE_TO_BUILD(USE_MANETTE TRUE) + SET_AND_EXPOSE_TO_BUILD(USE_MANETTE_GAMEPAD_PROVIDER TRUE) + endif () +endif () + if (ENABLE_SPEECH_SYNTHESIS) if (USE_FLITE) if (USE_TTS_CLIENT)