Commit c8bac580 authored by zandobersek@gmail.com's avatar zandobersek@gmail.com

[Gtk] Add support for the Gamepad API

https://bugs.webkit.org/show_bug.cgi?id=87503

Reviewed by Carlos Garcia Campos.

.: 

Only enable the Gamepad feature on Linux as support
for other operating systems is not present.

Check for the GIO Unix and GUdev dependencies when the
Gamepad feature is enabled.

* configure.ac:

Source/WebCore: 

Add support for the Gamepad feature on the GTK port.

The support is available only on Linux, with each gamepad device being presented
through a GamepadDeviceLinux object. The implementation of this class relies on
the Linux kernel joystick API.

Gamepad devices are recognized through the GamepadsGtk class, of which implementation
is based on GUdev. This way devices are properly registered on connection as objects of
the GamepadDeviceGtk class which inherits GamepadDeviceLinux. GamepadDeviceGtk reads the
joystick data through GIO pollable streams and updates the device state accordingly. The
GamepadsGtk object is then polled for gamepads data through the sampleGamepads method.

No new tests - tests already exist but require additional testing infrastructure.

* GNUmakefile.am:
* GNUmakefile.list.am:
* bindings/gobject/GNUmakefile.am:
* bindings/js/JSDOMBinding.h: Add the jsArray method that operates on a Vector of floats.
(WebCore):
(WebCore::jsArray):
* platform/gtk/GamepadsGtk.cpp: Added.
(WebCore):
(GamepadDeviceGtk):
(WebCore::GamepadDeviceGtk::create):
(WebCore::GamepadDeviceGtk::GamepadDeviceGtk):
(WebCore::GamepadDeviceGtk::~GamepadDeviceGtk):
(WebCore::GamepadDeviceGtk::readCallback):
(GamepadsGtk):
(WebCore::GamepadsGtk::GamepadsGtk):
(WebCore::GamepadsGtk::~GamepadsGtk):
(WebCore::GamepadsGtk::registerDevice):
(WebCore::GamepadsGtk::unregisterDevice):
(WebCore::GamepadsGtk::updateGamepadList):
(WebCore::GamepadsGtk::onUEventCallback):
(WebCore::GamepadsGtk::isGamepadDevice):
(WebCore::sampleGamepads):
* platform/linux/GamepadDeviceLinux.cpp: Added.
(WebCore):
(WebCore::GamepadDeviceLinux::GamepadDeviceLinux):
(WebCore::GamepadDeviceLinux::~GamepadDeviceLinux):
(WebCore::GamepadDeviceLinux::updateForEvent):
(WebCore::GamepadDeviceLinux::normalizeAxisValue):
(WebCore::GamepadDeviceLinux::normalizeButtonValue):
* platform/linux/GamepadDeviceLinux.h: Added.
(WebCore):
(GamepadDeviceLinux):
(WebCore::GamepadDeviceLinux::connected):
(WebCore::GamepadDeviceLinux::id):
(WebCore::GamepadDeviceLinux::timestamp):
(WebCore::GamepadDeviceLinux::axesCount):
(WebCore::GamepadDeviceLinux::axesData):
(WebCore::GamepadDeviceLinux::buttonsCount):
(WebCore::GamepadDeviceLinux::buttonsData):

Source/WebKit/gtk: 

Add the Gamepad feature dependencies libraries to the LIBADD
list for the libwebkitgtk library.

* GNUmakefile.am:

Source/WebKit2: 

Add the Gamepad feature dependencies libraries to the LIBADD
list for the libwebkitgtk2 library.

* GNUmakefile.am:

Tools: 

Enable the gamepad support for the GTK port.

* Scripts/webkitperl/FeatureList.pm:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@121332 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 84e87a7e
2012-06-27 Zan Dobersek <zandobersek@gmail.com>
[Gtk] Add support for the Gamepad API
https://bugs.webkit.org/show_bug.cgi?id=87503
Reviewed by Carlos Garcia Campos.
Only enable the Gamepad feature on Linux as support
for other operating systems is not present.
Check for the GIO Unix and GUdev dependencies when the
Gamepad feature is enabled.
* configure.ac:
2012-06-25 Simon Hausmann <simon.hausmann@nokia.com>
[Qt] Make it possible to build WebKit without QtWidgets
......
2012-06-27 Zan Dobersek <zandobersek@gmail.com>
[Gtk] Add support for the Gamepad API
https://bugs.webkit.org/show_bug.cgi?id=87503
Reviewed by Carlos Garcia Campos.
Add support for the Gamepad feature on the GTK port.
The support is available only on Linux, with each gamepad device being presented
through a GamepadDeviceLinux object. The implementation of this class relies on
the Linux kernel joystick API.
Gamepad devices are recognized through the GamepadsGtk class, of which implementation
is based on GUdev. This way devices are properly registered on connection as objects of
the GamepadDeviceGtk class which inherits GamepadDeviceLinux. GamepadDeviceGtk reads the
joystick data through GIO pollable streams and updates the device state accordingly. The
GamepadsGtk object is then polled for gamepads data through the sampleGamepads method.
No new tests - tests already exist but require additional testing infrastructure.
* GNUmakefile.am:
* GNUmakefile.list.am:
* bindings/gobject/GNUmakefile.am:
* bindings/js/JSDOMBinding.h: Add the jsArray method that operates on a Vector of floats.
(WebCore):
(WebCore::jsArray):
* platform/gtk/GamepadsGtk.cpp: Added.
(WebCore):
(GamepadDeviceGtk):
(WebCore::GamepadDeviceGtk::create):
(WebCore::GamepadDeviceGtk::GamepadDeviceGtk):
(WebCore::GamepadDeviceGtk::~GamepadDeviceGtk):
(WebCore::GamepadDeviceGtk::readCallback):
(GamepadsGtk):
(WebCore::GamepadsGtk::GamepadsGtk):
(WebCore::GamepadsGtk::~GamepadsGtk):
(WebCore::GamepadsGtk::registerDevice):
(WebCore::GamepadsGtk::unregisterDevice):
(WebCore::GamepadsGtk::updateGamepadList):
(WebCore::GamepadsGtk::onUEventCallback):
(WebCore::GamepadsGtk::isGamepadDevice):
(WebCore::sampleGamepads):
* platform/linux/GamepadDeviceLinux.cpp: Added.
(WebCore):
(WebCore::GamepadDeviceLinux::GamepadDeviceLinux):
(WebCore::GamepadDeviceLinux::~GamepadDeviceLinux):
(WebCore::GamepadDeviceLinux::updateForEvent):
(WebCore::GamepadDeviceLinux::normalizeAxisValue):
(WebCore::GamepadDeviceLinux::normalizeButtonValue):
* platform/linux/GamepadDeviceLinux.h: Added.
(WebCore):
(GamepadDeviceLinux):
(WebCore::GamepadDeviceLinux::connected):
(WebCore::GamepadDeviceLinux::id):
(WebCore::GamepadDeviceLinux::timestamp):
(WebCore::GamepadDeviceLinux::axesCount):
(WebCore::GamepadDeviceLinux::axesData):
(WebCore::GamepadDeviceLinux::buttonsCount):
(WebCore::GamepadDeviceLinux::buttonsData):
2012-06-27 Kentaro Hara <haraken@chromium.org>
Rename rareSVGData() to svgRareData()
......@@ -12,6 +12,7 @@ webcore_cppflags += \
-I$(srcdir)/Source/ThirdParty/ANGLE/include/GLSLANG \
-I$(srcdir)/Source/WebCore \
-I$(srcdir)/Source/WebCore/Modules/filesystem \
-I$(srcdir)/Source/WebCore/Modules/gamepad \
-I$(srcdir)/Source/WebCore/Modules/geolocation \
-I$(srcdir)/Source/WebCore/Modules/indexeddb \
-I$(srcdir)/Source/WebCore/Modules/mediastream \
......@@ -67,6 +68,7 @@ webcore_cppflags += \
-I$(srcdir)/Source/WebCore/platform/image-decoders/webp \
-I$(srcdir)/Source/WebCore/platform/image-decoders/png \
-I$(srcdir)/Source/WebCore/platform/leveldb \
-I$(srcdir)/Source/WebCore/platform/linux \
-I$(srcdir)/Source/WebCore/platform/mediastream \
-I$(srcdir)/Source/WebCore/platform/mediastream/gstreamer \
-I$(srcdir)/Source/WebCore/platform/mock \
......@@ -866,6 +868,7 @@ DerivedSources/ANGLE/glslang_tab.h: DerivedSources/ANGLE/glslang_tab.cpp
IDL_PATH := \
$(WebCore)/Modules/filesystem \
$(WebCore)/Modules/gamepad \
$(WebCore)/Modules/geolocation \
$(WebCore)/Modules/indexeddb \
$(WebCore)/Modules/mediastream \
......@@ -961,6 +964,7 @@ libWebCore_la_CPPFLAGS = \
$(CLUTTER_CFLAGS) \
$(COVERAGE_CFLAGS) \
$(ENCHANT_CFLAGS) \
$(GAMEPAD_CFLAGS) \
$(GEOCLUE_CFLAGS) \
$(GLIB_CFLAGS) \
$(GSTREAMER_CFLAGS) \
......@@ -1032,6 +1036,7 @@ libWebCoreGtk_la_CPPFLAGS = \
EXTRA_DIST += \
$(shell ls $(srcdir)/Source/WebCore/Modules/filesystem/*.idl) \
$(shell ls $(srcdir)/Source/WebCore/Modules/gamepad/*.idl) \
$(shell ls $(srcdir)/Source/WebCore/Modules/geolocation/*.idl) \
$(shell ls $(srcdir)/Source/WebCore/Modules/indexeddb/*.idl) \
$(shell ls $(srcdir)/Source/WebCore/Modules/mediastream/*.idl) \
......
......@@ -192,6 +192,10 @@ webcore_built_sources += \
DerivedSources/WebCore/JSFloat32Array.h \
DerivedSources/WebCore/JSFloat64Array.cpp \
DerivedSources/WebCore/JSFloat64Array.h \
DerivedSources/WebCore/JSGamepad.cpp \
DerivedSources/WebCore/JSGamepad.h \
DerivedSources/WebCore/JSGamepadList.cpp \
DerivedSources/WebCore/JSGamepadList.h \
DerivedSources/WebCore/JSGeolocation.cpp \
DerivedSources/WebCore/JSGeolocation.h \
DerivedSources/WebCore/JSGeoposition.cpp \
......@@ -677,6 +681,9 @@ webcore_built_sources += \
DerivedSources/WebCore/XPathGrammar.h
dom_binding_idls += \
$(WebCore)/Modules/gamepad/Gamepad.idl \
$(WebCore)/Modules/gamepad/GamepadList.idl \
$(WebCore)/Modules/gamepad/NavigatorGamepad.idl \
$(WebCore)/Modules/geolocation/Geolocation.idl \
$(WebCore)/Modules/geolocation/Geoposition.idl \
$(WebCore)/Modules/geolocation/NavigatorGeolocation.idl \
......@@ -1053,6 +1060,12 @@ webcore_modules_sources += \
Source/WebCore/Modules/filesystem/WebKitFlags.h \
Source/WebCore/Modules/filesystem/WorkerContextFileSystem.cpp \
Source/WebCore/Modules/filesystem/WorkerContextFileSystem.h \
Source/WebCore/Modules/gamepad/Gamepad.cpp \
Source/WebCore/Modules/gamepad/Gamepad.h \
Source/WebCore/Modules/gamepad/GamepadList.cpp \
Source/WebCore/Modules/gamepad/GamepadList.h \
Source/WebCore/Modules/gamepad/NavigatorGamepad.cpp \
Source/WebCore/Modules/gamepad/NavigatorGamepad.h \
Source/WebCore/Modules/geolocation/Geolocation.cpp \
Source/WebCore/Modules/geolocation/Geolocation.h \
Source/WebCore/Modules/geolocation/GeolocationController.cpp \
......@@ -3160,6 +3173,7 @@ webcore_sources += \
Source/WebCore/platform/FileSystem.h \
Source/WebCore/platform/FloatConversion.h \
Source/WebCore/platform/FractionalLayoutUnit.h \
Source/WebCore/platform/Gamepads.h \
Source/WebCore/platform/HashTools.h \
Source/WebCore/platform/HistogramSupport.cpp \
Source/WebCore/platform/HistogramSupport.h \
......@@ -3408,6 +3422,7 @@ webcore_sources += \
Source/WebCore/platform/graphics/WOFFFileFormat.h \
Source/WebCore/platform/gtk/ErrorsGtk.cpp \
Source/WebCore/platform/gtk/ErrorsGtk.h \
Source/WebCore/platform/gtk/GamepadsGtk.cpp \
Source/WebCore/platform/gtk/KURLGtk.cpp \
Source/WebCore/platform/gtk/LanguageGtk.cpp \
Source/WebCore/platform/gtk/LoggingGtk.cpp \
......@@ -3468,6 +3483,8 @@ webcore_sources += \
Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h \
Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp \
Source/WebCore/platform/image-decoders/png/PNGImageDecoder.h \
Source/WebCore/platform/linux/GamepadDeviceLinux.cpp \
Source/WebCore/platform/linux/GamepadDeviceLinux.h \
Source/WebCore/platform/mediastream/DeprecatedPeerConnectionHandler.h \
Source/WebCore/platform/mediastream/DeprecatedPeerConnectionHandlerClient.h \
Source/WebCore/platform/mediastream/IceCandidateDescriptor.cpp \
......
......@@ -66,6 +66,10 @@ webkitgtk_gdom_built_sources += \
DerivedSources/webkit/WebKitDOMFileList.cpp \
DerivedSources/webkit/WebKitDOMFileListPrivate.h \
DerivedSources/webkit/WebKitDOMFilePrivate.h \
DerivedSources/webkit/WebKitDOMGamepad.cpp \
DerivedSources/webkit/WebKitDOMGamepadList.cpp \
DerivedSources/webkit/WebKitDOMGamepadListPrivate.h \
DerivedSources/webkit/WebKitDOMGamepadPrivate.h \
DerivedSources/webkit/WebKitDOMGeolocation.cpp \
DerivedSources/webkit/WebKitDOMGeolocationPrivate.h \
DerivedSources/webkit/WebKitDOMHistory.cpp \
......@@ -295,6 +299,8 @@ webkitgtk_built_h_api += \
DerivedSources/webkit/WebKitDOMBlob.h \
DerivedSources/webkit/WebKitDOMFile.h \
DerivedSources/webkit/WebKitDOMFileList.h \
DerivedSources/webkit/WebKitDOMGamepad.h \
DerivedSources/webkit/WebKitDOMGamepadList.h \
DerivedSources/webkit/WebKitDOMGeolocation.h \
DerivedSources/webkit/WebKitDOMHTMLAnchorElement.h \
DerivedSources/webkit/WebKitDOMHTMLAppletElement.h \
......@@ -428,7 +434,6 @@ webkitgtk_gdom_built_sources += \
DerivedSources/webkit/WebKitDOMHTMLPropertiesCollectionPrivate.h
endif
if ENABLE_WEB_TIMING
webkitgtk_built_h_api += \
$(top_builddir)/DerivedSources/webkit/WebKitDOMPerformance.h \
......
......@@ -307,6 +307,18 @@ enum ParameterDefaultPolicy {
return JSC::constructArray(exec, globalObject, array);
}
template<>
inline JSC::JSValue jsArray(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<float>& iterator)
{
JSC::MarkedArgumentBuffer array;
Vector<float>::const_iterator end = iterator.end();
for (Vector<float>::const_iterator it = iterator.begin(); it != end; ++it)
array.append(JSC::jsNumber(*it));
return JSC::constructArray(exec, globalObject, array);
}
template <class T>
Vector<T> toNativeArray(JSC::ExecState* exec, JSC::JSValue value)
{
......
/*
* Copyright (C) 2012 Zan Dobersek <zandobersek@gmail.com>
*
* 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"
#if ENABLE(GAMEPAD)
#include "GamepadDeviceLinux.h"
#include "GamepadList.h"
#include <gio/gunixinputstream.h>
#include <gudev/gudev.h>
#include <wtf/HashMap.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/gobject/GOwnPtr.h>
#include <wtf/gobject/GRefPtr.h>
#include <wtf/text/StringHash.h>
namespace WebCore {
class GamepadDeviceGtk : public GamepadDeviceLinux {
public:
static PassOwnPtr<GamepadDeviceGtk> create(String deviceFile)
{
return adoptPtr(new GamepadDeviceGtk(deviceFile));
}
~GamepadDeviceGtk();
private:
GamepadDeviceGtk(String deviceFile);
static gboolean readCallback(GObject* pollableStream, gpointer data);
GRefPtr<GInputStream> m_inputStream;
GRefPtr<GSource> m_source;
};
GamepadDeviceGtk::GamepadDeviceGtk(String deviceFile)
: GamepadDeviceLinux(deviceFile)
{
if (m_fileDescriptor == -1)
return;
m_inputStream = adoptGRef(g_unix_input_stream_new(m_fileDescriptor, FALSE));
m_source = adoptGRef(g_pollable_input_stream_create_source(G_POLLABLE_INPUT_STREAM(m_inputStream.get()), 0));
g_source_set_callback(m_source.get(), reinterpret_cast<GSourceFunc>(readCallback), this, 0);
g_source_attach(m_source.get(), 0);
}
GamepadDeviceGtk::~GamepadDeviceGtk()
{
if (m_source)
g_source_destroy(m_source.get());
}
gboolean GamepadDeviceGtk::readCallback(GObject* pollableStream, gpointer data)
{
GamepadDeviceGtk* gamepadDevice = reinterpret_cast<GamepadDeviceGtk*>(data);
GOwnPtr<GError> error;
struct js_event event;
gssize len = g_pollable_input_stream_read_nonblocking(G_POLLABLE_INPUT_STREAM(pollableStream),
&event, sizeof(event), 0, &error.outPtr());
// FIXME: Properly log the error.
// In the case of G_IO_ERROR_WOULD_BLOCK error return TRUE to wait until
// the source becomes readable again and FALSE otherwise.
if (error)
return g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK);
ASSERT(len == sizeof(event));
gamepadDevice->updateForEvent(event);
return TRUE;
}
class GamepadsGtk {
public:
GamepadsGtk(unsigned length);
void registerDevice(String deviceFile);
void unregisterDevice(String deviceFile);
void updateGamepadList(GamepadList*);
private:
~GamepadsGtk();
static void onUEventCallback(GUdevClient*, gchar* action, GUdevDevice*, gpointer data);
static gboolean isGamepadDevice(GUdevDevice*);
Vector<OwnPtr<GamepadDeviceGtk> > m_slots;
HashMap<String, GamepadDeviceGtk*> m_deviceMap;
GRefPtr<GUdevClient> m_gudevClient;
};
GamepadsGtk::GamepadsGtk(unsigned length)
: m_slots(length)
{
static const char* subsystems[] = { "input", 0 };
m_gudevClient = adoptGRef(g_udev_client_new(subsystems));
g_signal_connect(m_gudevClient.get(), "uevent", G_CALLBACK(onUEventCallback), this);
GOwnPtr<GList> devicesList(g_udev_client_query_by_subsystem(m_gudevClient.get(), subsystems[0]));
for (GList* listItem = devicesList.get(); listItem; listItem = g_list_next(listItem)) {
GUdevDevice* device = G_UDEV_DEVICE(listItem->data);
String deviceFile = String::fromUTF8(g_udev_device_get_device_file(device));
if (isGamepadDevice(device))
registerDevice(deviceFile);
g_object_unref(device);
}
}
GamepadsGtk::~GamepadsGtk()
{
g_signal_handlers_disconnect_matched(m_gudevClient.get(), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
}
void GamepadsGtk::registerDevice(String deviceFile)
{
ASSERT(!m_deviceMap.contains(deviceFile));
for (unsigned index = 0; index < m_slots.size(); index++) {
if (!m_slots[index]) {
m_slots[index] = GamepadDeviceGtk::create(deviceFile);
m_deviceMap.add(deviceFile, m_slots[index].get());
break;
}
}
}
void GamepadsGtk::unregisterDevice(String deviceFile)
{
ASSERT(m_deviceMap.contains(deviceFile));
GamepadDeviceGtk* gamepadDevice = m_deviceMap.take(deviceFile);
unsigned index = m_slots.find(gamepadDevice);
ASSERT(index != notFound);
m_slots[index].clear();
}
void GamepadsGtk::updateGamepadList(GamepadList* into)
{
ASSERT(m_slots.size() == into->length());
for (unsigned i = 0; i < m_slots.size(); i++) {
if (m_slots[i].get() && m_slots[i]->connected()) {
GamepadDeviceGtk* 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 GamepadsGtk::onUEventCallback(GUdevClient* udevClient, gchar* action, GUdevDevice* device, gpointer data)
{
if (!isGamepadDevice(device))
return;
GamepadsGtk* gamepadsGtk = reinterpret_cast<GamepadsGtk*>(data);
String deviceFile = String::fromUTF8(g_udev_device_get_device_file(device));
if (!g_strcmp0(action, "add"))
gamepadsGtk->registerDevice(deviceFile);
else if (!g_strcmp0(action, "remove"))
gamepadsGtk->unregisterDevice(deviceFile);
}
gboolean GamepadsGtk::isGamepadDevice(GUdevDevice* device)
{
const gchar* deviceFile = g_udev_device_get_device_file(device);
const gchar* sysfsPath = g_udev_device_get_sysfs_path(device);
if (!deviceFile || !sysfsPath)
return FALSE;
if (!g_udev_device_has_property(device, "ID_INPUT") || !g_udev_device_has_property(device, "ID_INPUT_JOYSTICK"))
return FALSE;
return g_str_has_prefix(deviceFile, "/dev/input/js");
}
void sampleGamepads(GamepadList* into)
{
DEFINE_STATIC_LOCAL(GamepadsGtk, gamepadsGtk, (into->length()));
gamepadsGtk.updateGamepadList(into);
}
} // namespace WebCore
#endif // ENABLE(GAMEPAD)
/*
* Copyright (C) 2012 Zan Dobersek <zandobersek@gmail.com>
*
* 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 "GamepadDeviceLinux.h"
#if ENABLE(GAMEPAD)
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <wtf/text/CString.h>
namespace WebCore {
GamepadDeviceLinux::GamepadDeviceLinux(String deviceFile)
: m_fileDescriptor(-1)
, m_connected(false)
, m_lastTimestamp(0)
{
// FIXME: Log errors when returning early.
m_fileDescriptor = open(deviceFile.utf8().data(), O_RDONLY | O_NONBLOCK);
if (m_fileDescriptor == -1)
return;
char deviceName[1024];
if (ioctl(m_fileDescriptor, JSIOCGNAME(sizeof(deviceName)), deviceName) < 0)
return;
m_deviceName = String(deviceName).simplifyWhiteSpace();
uint8_t numberOfAxes;
uint8_t numberOfButtons;
if (ioctl(m_fileDescriptor, JSIOCGAXES, &numberOfAxes) < 0 || ioctl(m_fileDescriptor, JSIOCGBUTTONS, &numberOfButtons) < 0)
return;
m_axes.fill(0.0, numberOfAxes);
m_buttons.fill(0.0, numberOfButtons);
}
GamepadDeviceLinux::~GamepadDeviceLinux()
{
if (m_fileDescriptor != -1)
close(m_fileDescriptor);
}
void GamepadDeviceLinux::updateForEvent(struct js_event event)
{
if (!(event.type & JS_EVENT_AXIS || event.type & JS_EVENT_BUTTON))
return;
// Mark the device as connected only if it is not yet connected, the event is not an initialization
// and the value is not 0 (indicating a genuine interaction with the device).
if (!m_connected && !(event.type & JS_EVENT_INIT) && event.value)
m_connected = true;
if (event.type & JS_EVENT_AXIS)
m_axes[event.number] = normalizeAxisValue(event.value);
else if (event.type & JS_EVENT_BUTTON)
m_buttons[event.number] = normalizeButtonValue(event.value);
m_lastTimestamp = event.time;
}
float GamepadDeviceLinux::normalizeAxisValue(short value)
{
// Normalize from range [-32767, 32767] into range [-1.0, 1.0]
return value / 32767.0f;
}
float GamepadDeviceLinux::normalizeButtonValue(short value)
{
// Normalize from range [0, 1] into range [0.0, 1.0]
return value / 1.0f;
}
} // namespace WebCore
#endif // ENABLE(GAMEPAD)
/*
* Copyright (C) 2012 Zan Dobersek <zandobersek@gmail.com>
*
* 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.
*/
#ifndef GamepadDeviceLinux_h
#define GamepadDeviceLinux_h
#if ENABLE(GAMEPAD)
#include <linux/joystick.h>
#include <wtf/Vector.h>
#include <wtf/text/WTFString.h>
namespace WebCore {
class GamepadDeviceLinux {
public:
bool connected() { return m_connected; };
String id() { return m_deviceName; }
unsigned long long timestamp() { return m_lastTimestamp; }
unsigned axesCount() { return m_axes.size(); }
float* axesData() { return m_axes.data(); }
unsigned buttonsCount() { return m_buttons.size(); }
float* buttonsData() { return m_buttons.data(); }
protected:
GamepadDeviceLinux(String deviceFile);
~GamepadDeviceLinux();
void updateForEvent(struct js_event);
int m_fileDescriptor;
private:
float normalizeAxisValue(short value);
float normalizeButtonValue(short value);
bool m_connected;
String m_deviceName;
unsigned long long m_lastTimestamp;
Vector<float> m_axes;
Vector<float> m_buttons;
};
} // namespace WebCore
#endif // ENABLE(GAMEPAD)
#endif // GamepadDeviceLinux_h
2012-06-27 Zan Dobersek <zandobersek@gmail.com>
[Gtk] Add support for the Gamepad API
https://bugs.webkit.org/show_bug.cgi?id=87503
Reviewed by Carlos Garcia Campos.
Add the Gamepad feature dependencies libraries to the LIBADD
list for the libwebkitgtk library.
* GNUmakefile.am:
2012-06-25 Carlos Garcia Campos <cgarcia@igalia.com>