Title: [124904] trunk
Revision
124904
Author
[email protected]
Date
2012-08-07 12:03:58 -0700 (Tue, 07 Aug 2012)

Log Message

[Qt] Add support for the Gamepad API
https://bugs.webkit.org/show_bug.cgi?id=90637

Patch by Marcelo Lira <[email protected]> on 2012-08-07
Reviewed by Alexis Menard.

Source/WebCore:

Adds support for Gamepad API on the Qt port.

The implementation of this class relies on the Linux
kernel joystick API.

Gamepad devices are recognized through the GamepadsQt
class, which uses the udev library to watch for connection,
disconnection and other gamepad related events.

Tests for this feature already exist.

* DerivedSources.pri:
* Target.pri:
* WebCore.pri:
* platform/qt/GamepadsQt.cpp: Added.
(WebCore):
(GamepadDeviceLinuxQt):
(WebCore::GamepadDeviceLinuxQt::create):
(WebCore::GamepadDeviceLinuxQt::GamepadDeviceLinuxQt):
(WebCore::GamepadDeviceLinuxQt::~GamepadDeviceLinuxQt):
(WebCore::GamepadDeviceLinuxQt::readCallback):
(GamepadsQt):
(WebCore::GamepadsQt::GamepadsQt):
(WebCore::GamepadsQt::~GamepadsQt):
(WebCore::GamepadsQt::isGamepadDevice):
(WebCore::GamepadsQt::onGamePadChange):
(WebCore::GamepadsQt::registerDevice):
(WebCore::GamepadsQt::unregisterDevice):
(WebCore::GamepadsQt::updateGamepadList):
(WebCore::sampleGamepads):

Tools:

If the libudev library is present, the GAMEPAD flag is
turned on by default for the Qt port.

* Scripts/webkitperl/FeatureList.pm:
* qmake/mkspecs/features/features.prf:

LayoutTests:

This does not unskip the gamepad tests for the Qt port, since the flag is
optional the test would not pass without it. The user may unskip it manually.

On the other hand, the gamepad-polling-access.html test is still expected
to fail because it requires additional test infrastructure.
See https://bugs.webkit.org/show_bug.cgi?id=92873

* platform/qt/TestExpectations:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (124903 => 124904)


--- trunk/LayoutTests/ChangeLog	2012-08-07 19:01:31 UTC (rev 124903)
+++ trunk/LayoutTests/ChangeLog	2012-08-07 19:03:58 UTC (rev 124904)
@@ -1,3 +1,19 @@
+2012-08-07  Marcelo Lira  <[email protected]>
+
+        [Qt] Add support for the Gamepad API
+        https://bugs.webkit.org/show_bug.cgi?id=90637
+
+        Reviewed by Alexis Menard.
+
+        This does not unskip the gamepad tests for the Qt port, since the flag is
+        optional the test would not pass without it. The user may unskip it manually.
+
+        On the other hand, the gamepad-polling-access.html test is still expected
+        to fail because it requires additional test infrastructure.
+        See https://bugs.webkit.org/show_bug.cgi?id=92873
+
+        * platform/qt/TestExpectations:
+
 2012-08-07  Gyuyoung Kim  <[email protected]>
 
         Move test cases related to link prerender to Skipped list except for chromium port

Modified: trunk/LayoutTests/platform/qt/TestExpectations (124903 => 124904)


--- trunk/LayoutTests/platform/qt/TestExpectations	2012-08-07 19:01:31 UTC (rev 124903)
+++ trunk/LayoutTests/platform/qt/TestExpectations	2012-08-07 19:03:58 UTC (rev 124904)
@@ -117,6 +117,9 @@
 // Skip tests in fast/text/shaping
 BUGWK90951 SKIP : fast/text/shaping = PASS
 
+// Missing test infrastructure, no gamepads available.
+BUGWK92873 SKIP : gamepad/gamepad-polling-access.html = TEXT
+
 // Flaky tests
 BUGWK91376 : http/tests/security/sandboxed-iframe-modify-self.html = TEXT PASS
 BUGWK91379 : http/tests/security/contentSecurityPolicy/policy-does-not-affect-child.html = TEXT PASS

Modified: trunk/Source/WebCore/ChangeLog (124903 => 124904)


--- trunk/Source/WebCore/ChangeLog	2012-08-07 19:01:31 UTC (rev 124903)
+++ trunk/Source/WebCore/ChangeLog	2012-08-07 19:03:58 UTC (rev 124904)
@@ -1,3 +1,41 @@
+2012-08-07  Marcelo Lira  <[email protected]>
+
+        [Qt] Add support for the Gamepad API
+        https://bugs.webkit.org/show_bug.cgi?id=90637
+
+        Reviewed by Alexis Menard.
+
+        Adds support for Gamepad API on the Qt port.
+
+        The implementation of this class relies on the Linux
+        kernel joystick API.
+
+        Gamepad devices are recognized through the GamepadsQt
+        class, which uses the udev library to watch for connection,
+        disconnection and other gamepad related events.
+
+        Tests for this feature already exist.
+
+        * DerivedSources.pri:
+        * Target.pri:
+        * WebCore.pri:
+        * platform/qt/GamepadsQt.cpp: Added.
+        (WebCore):
+        (GamepadDeviceLinuxQt):
+        (WebCore::GamepadDeviceLinuxQt::create):
+        (WebCore::GamepadDeviceLinuxQt::GamepadDeviceLinuxQt):
+        (WebCore::GamepadDeviceLinuxQt::~GamepadDeviceLinuxQt):
+        (WebCore::GamepadDeviceLinuxQt::readCallback):
+        (GamepadsQt):
+        (WebCore::GamepadsQt::GamepadsQt):
+        (WebCore::GamepadsQt::~GamepadsQt):
+        (WebCore::GamepadsQt::isGamepadDevice):
+        (WebCore::GamepadsQt::onGamePadChange):
+        (WebCore::GamepadsQt::registerDevice):
+        (WebCore::GamepadsQt::unregisterDevice):
+        (WebCore::GamepadsQt::updateGamepadList):
+        (WebCore::sampleGamepads):
+
 2012-08-07  Mike Reed  <[email protected]>
 
         reimplement fastMod w/o (soon to be) private skia macros

Modified: trunk/Source/WebCore/DerivedSources.pri (124903 => 124904)


--- trunk/Source/WebCore/DerivedSources.pri	2012-08-07 19:01:31 UTC (rev 124903)
+++ trunk/Source/WebCore/DerivedSources.pri	2012-08-07 19:03:58 UTC (rev 124904)
@@ -613,6 +613,13 @@
     $$PWD/svg/SVGZoomEvent.idl
 }
 
+contains(DEFINES, ENABLE_GAMEPAD=1) {
+  IDL_BINDINGS += \
+    $$PWD/Modules/gamepad/Gamepad.idl \
+    $$PWD/Modules/gamepad/GamepadList.idl \
+    $$PWD/Modules/gamepad/NavigatorGamepad.idl
+}
+
 contains(DEFINES, ENABLE_VIDEO_TRACK=1) {
   IDL_BINDINGS += \
     $$PWD/html/track/TextTrack.idl \

Modified: trunk/Source/WebCore/Target.pri (124903 => 124904)


--- trunk/Source/WebCore/Target.pri	2012-08-07 19:01:31 UTC (rev 124903)
+++ trunk/Source/WebCore/Target.pri	2012-08-07 19:03:58 UTC (rev 124904)
@@ -3086,6 +3086,22 @@
         Modules/quota/StorageInfo.cpp
 }
 
+contains(DEFINES, ENABLE_GAMEPAD=1) {
+    HEADERS += \
+        Modules/gamepad/Gamepad.h\
+        Modules/gamepad/GamepadList.h \
+        Modules/gamepad/NavigatorGamepad.h \
+        platform/linux/GamepadDeviceLinux.h \
+        platform/Gamepads.h
+
+    SOURCES += \
+        Modules/gamepad/Gamepad.cpp \
+        Modules/gamepad/GamepadList.cpp \
+        Modules/gamepad/NavigatorGamepad.cpp \
+        platform/linux/GamepadDeviceLinux.cpp \
+        platform/qt/GamepadsQt.cpp
+}
+
 contains(DEFINES, ENABLE_VIDEO=1) {
     SOURCES += \
         html/HTMLAudioElement.cpp \

Modified: trunk/Source/WebCore/WebCore.pri (124903 => 124904)


--- trunk/Source/WebCore/WebCore.pri	2012-08-07 19:01:31 UTC (rev 124903)
+++ trunk/Source/WebCore/WebCore.pri	2012-08-07 19:03:58 UTC (rev 124904)
@@ -158,6 +158,13 @@
      MOBILITY *= systeminfo
 }
 
+contains(DEFINES, ENABLE_GAMEPAD=1) {
+    INCLUDEPATH += \
+        $$SOURCE_DIR/platform/linux \
+        $$SOURCE_DIR/Modules/gamepad
+    PKGCONFIG += libudev
+}
+
 contains(DEFINES, ENABLE_VIDEO=1) {
     contains(DEFINES, WTF_USE_QTKIT=1) {
         INCLUDEPATH += $$SOURCE_DIR/platform/graphics/mac

Added: trunk/Source/WebCore/platform/qt/GamepadsQt.cpp (0 => 124904)


--- trunk/Source/WebCore/platform/qt/GamepadsQt.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/qt/GamepadsQt.cpp	2012-08-07 19:03:58 UTC (rev 124904)
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2012 INdT - Instituto Nokia de Tecnologia
+ * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Gamepads.h"
+
+#include "GamepadDeviceLinux.h"
+#include "GamepadList.h"
+
+#include <QObject>
+#include <QSocketNotifier>
+
+extern "C" {
+    #include <libudev.h>
+}
+
+#include <wtf/HashMap.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+
+class GamepadDeviceLinuxQt : public QObject, public GamepadDeviceLinux {
+    Q_OBJECT
+public:
+    static PassOwnPtr<GamepadDeviceLinuxQt> create(const String& deviceFile)
+    {
+        return adoptPtr(new GamepadDeviceLinuxQt(deviceFile));
+    }
+    ~GamepadDeviceLinuxQt();
+
+private:
+    GamepadDeviceLinuxQt(const String&);
+    QSocketNotifier* m_notifier;
+
+private slots:
+    bool readCallback();
+};
+
+GamepadDeviceLinuxQt::GamepadDeviceLinuxQt(const String& deviceFile)
+    : QObject()
+    , GamepadDeviceLinux(deviceFile)
+{
+    if (m_fileDescriptor == -1)
+        return;
+
+    m_notifier = new QSocketNotifier(m_fileDescriptor, QSocketNotifier::Read, this);
+    connect(m_notifier, SIGNAL(activated(int)), this, SLOT(readCallback()));
+}
+
+GamepadDeviceLinuxQt::~GamepadDeviceLinuxQt()
+{
+}
+
+bool GamepadDeviceLinuxQt::readCallback()
+{
+    js_event event;
+    int len = read(m_fileDescriptor, &event, sizeof(js_event));
+    if (len != sizeof(event))
+        return false;
+    updateForEvent(event);
+    return true;
+}
+
+class GamepadsQt : public QObject {
+    Q_OBJECT
+public:
+    GamepadsQt(unsigned);
+
+    void registerDevice(const String&);
+    void unregisterDevice(const String&);
+
+    void updateGamepadList(GamepadList*);
+
+private slots:
+    void onGamePadChange();
+
+private:
+    ~GamepadsQt();
+    bool isGamepadDevice(struct udev_device*);
+
+    Vector<OwnPtr<GamepadDeviceLinuxQt> > m_slots;
+    HashMap<String, GamepadDeviceLinuxQt*> m_deviceMap;
+
+    struct udev* m_udev;
+    struct udev_monitor* m_gamepadsMonitor;
+    QSocketNotifier* m_gamepadsNotifier;
+};
+
+GamepadsQt::GamepadsQt(unsigned length)
+    : QObject()
+    , m_slots(length)
+{
+    m_udev = udev_new();
+    m_gamepadsMonitor = udev_monitor_new_from_netlink(m_udev, "udev");
+    udev_monitor_enable_receiving(m_gamepadsMonitor);
+    udev_monitor_filter_add_match_subsystem_devtype(m_gamepadsMonitor, "input", 0);
+    m_gamepadsNotifier = new QSocketNotifier(udev_monitor_get_fd(m_gamepadsMonitor), QSocketNotifier::Read, this);
+    connect(m_gamepadsNotifier, SIGNAL(activated(int)), this, SLOT(onGamePadChange()));
+
+    struct udev_enumerate* enumerate = udev_enumerate_new(m_udev);
+    udev_enumerate_add_match_subsystem(enumerate, "input");
+    udev_enumerate_add_match_property(enumerate, "ID_INPUT_JOYSTICK", "1");
+    udev_enumerate_scan_devices(enumerate);
+    struct udev_list_entry* cur;
+    struct udev_list_entry* devs = udev_enumerate_get_list_entry(enumerate);
+    udev_list_entry_foreach(cur, devs)
+    {
+        const char* devname = udev_list_entry_get_name(cur);
+        struct udev_device* device = udev_device_new_from_syspath(m_udev, devname);
+        if (isGamepadDevice(device))
+            registerDevice(String::fromUTF8(udev_device_get_devnode(device)));
+        udev_device_unref(device);
+    }
+    udev_enumerate_unref(enumerate);
+}
+
+GamepadsQt::~GamepadsQt()
+{
+    udev_unref(m_udev);
+    udev_monitor_unref(m_gamepadsMonitor);
+}
+
+bool GamepadsQt::isGamepadDevice(struct udev_device* device)
+{
+    const char* deviceFile = udev_device_get_devnode(device);
+    const char* sysfsPath = udev_device_get_syspath(device);
+    if (!deviceFile || !sysfsPath)
+        return false;
+    if (!udev_device_get_property_value(device, "ID_INPUT") || !udev_device_get_property_value(device, "ID_INPUT_JOYSTICK"))
+        return false;
+    return QByteArray(deviceFile).startsWith("/dev/input/js");
+}
+
+void GamepadsQt::onGamePadChange()
+{
+    struct udev_device* device = udev_monitor_receive_device(m_gamepadsMonitor);
+    if (!isGamepadDevice(device))
+        return;
+    QByteArray action(udev_device_get_action(device));
+    if (action == "add")
+        registerDevice(udev_device_get_devnode(device));
+    else if (action == "remove")
+        unregisterDevice(udev_device_get_devnode(device));
+}
+
+void GamepadsQt::registerDevice(const String& deviceFile)
+{
+    ASSERT(!m_deviceMap.contains(deviceFile));
+
+    for (unsigned index = 0; index < m_slots.size(); index++) {
+        if (!m_slots[index]) {
+            m_slots[index] = GamepadDeviceLinuxQt::create(deviceFile);
+            m_deviceMap.add(deviceFile, m_slots[index].get());
+            break;
+        }
+    }
+}
+
+void GamepadsQt::unregisterDevice(const String& deviceFile)
+{
+    ASSERT(m_deviceMap.contains(deviceFile));
+
+    GamepadDeviceLinuxQt* gamepadDevice = m_deviceMap.take(deviceFile);
+    unsigned index = m_slots.find(gamepadDevice);
+
+    m_slots[index].clear();
+}
+
+void GamepadsQt::updateGamepadList(GamepadList* into)
+{
+    ASSERT(m_slots.size() == into->length());
+
+    for (unsigned i = 0; i < m_slots.size(); i++) {
+        if (m_slots[i] && m_slots[i]->connected()) {
+            GamepadDeviceLinuxQt* gamepadDevice = m_slots[i].get();
+            RefPtr<Gamepad> gamepad = into->item(i);
+            if (!gamepad)
+                gamepad = Gamepad::create();
+
+            gamepad->index(i);
+            gamepad->id(gamepadDevice->id());
+            gamepad->timestamp(gamepadDevice->timestamp());
+            gamepad->axes(gamepadDevice->axesCount(), gamepadDevice->axesData());
+            gamepad->buttons(gamepadDevice->buttonsCount(), gamepadDevice->buttonsData());
+
+            into->set(i, gamepad);
+        } else
+            into->set(i, 0);
+    }
+}
+
+void sampleGamepads(GamepadList* into)
+{
+    DEFINE_STATIC_LOCAL(GamepadsQt, gamepadsQt, (into->length()));
+    gamepadsQt.updateGamepadList(into);
+}
+
+#include "GamepadsQt.moc"
+
+} // namespace WebCore

Modified: trunk/Tools/ChangeLog (124903 => 124904)


--- trunk/Tools/ChangeLog	2012-08-07 19:01:31 UTC (rev 124903)
+++ trunk/Tools/ChangeLog	2012-08-07 19:03:58 UTC (rev 124904)
@@ -1,3 +1,16 @@
+2012-08-07  Marcelo Lira  <[email protected]>
+
+        [Qt] Add support for the Gamepad API
+        https://bugs.webkit.org/show_bug.cgi?id=90637
+
+        Reviewed by Alexis Menard.
+
+        If the libudev library is present, the GAMEPAD flag is
+        turned on by default for the Qt port.
+
+        * Scripts/webkitperl/FeatureList.pm:
+        * qmake/mkspecs/features/features.prf:
+
 2012-08-07  Rob Buis  <[email protected]>
 
         [BlackBerry] Turn on CSS Variables

Modified: trunk/Tools/Scripts/webkitperl/FeatureList.pm (124903 => 124904)


--- trunk/Tools/Scripts/webkitperl/FeatureList.pm	2012-08-07 19:01:31 UTC (rev 124903)
+++ trunk/Tools/Scripts/webkitperl/FeatureList.pm	2012-08-07 19:03:58 UTC (rev 124904)
@@ -226,7 +226,7 @@
       define => "ENABLE_FULLSCREEN_API", default => (isAppleMacWebKit() || isEfl() || isGtk() || isBlackBerry() || isQt()), value => \$fullscreenAPISupport },
 
     { option => "gamepad", desc => "Toggle Gamepad support",
-      define => "ENABLE_GAMEPAD", default => (isEfl() || isGtk()), value => \$gamepadSupport },
+      define => "ENABLE_GAMEPAD", default => (isEfl() || isGtk() || isQt()), value => \$gamepadSupport },
 
     { option => "geolocation", desc => "Toggle Geolocation support",
       define => "ENABLE_GEOLOCATION", default => (isAppleWebKit() || isGtk() || isBlackBerry()), value => \$geolocationSupport },

Modified: trunk/Tools/qmake/mkspecs/features/features.prf (124903 => 124904)


--- trunk/Tools/qmake/mkspecs/features/features.prf	2012-08-07 19:01:31 UTC (rev 124903)
+++ trunk/Tools/qmake/mkspecs/features/features.prf	2012-08-07 19:03:58 UTC (rev 124904)
@@ -152,6 +152,11 @@
     !no_webkit2: DEFINES += ENABLE_FULLSCREEN_API=1
 }
 
+# Gamepad API Support
+linux-*:!contains(DEFINES, ENABLE_GAMEPAD=.) {
+    packagesExist(libudev): DEFINES += ENABLE_GAMEPAD=1
+}
+
 # Xcomposite Support
 linux-*:config_libXcomposite: DEFINES += HAVE_XCOMPOSITE=1
 
@@ -215,6 +220,13 @@
     }
 }
 
+contains(DEFINES, ENABLE_GAMEPAD=1) {
+    !packagesExist(libudev) {
+        error("Gamepad API requires libudev to build. Please install libudev development files, or build WebKit without gamepad.")
+    } else:!linux-* {
+        error("Currently the Gamepad API is supported only on Linux, build WebKit without gamepad.")
+    }
+}
 
 # Slider Touch is sensible to use when compiling WebKit2
 haveQt(5):contains(DEFINES, ENABLE_TOUCH_EVENTS=1) {
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to