<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[211220] trunk/Source/WebCore</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/211220">211220</a></dd>
<dt>Author</dt> <dd>beidson@apple.com</dd>
<dt>Date</dt> <dd>2017-01-26 11:21:39 -0800 (Thu, 26 Jan 2017)</dd>
</dl>
<h3>Log Message</h3>
<pre>Gamepad support shows wrong values for PS4 controllers (D-pad is missing).
<rdar://problem/29578619> and https://bugs.webkit.org/show_bug.cgi?id=165588
Reviewed by Alex Christensen.
No new tests (Currently unable to test HID backend directly)
DPads report their HID type as "a button", but their HID usage is "Hatswitch".
This patch adds a new element type that maps a "hatswitch" value to 4 additional buttons.
* platform/gamepad/mac/HIDGamepad.cpp:
(WebCore::HIDGamepad::initElements):
(WebCore::HIDGamepad::initElementsFromArray):
(WebCore::HIDGamepad::maybeAddButton):
(WebCore::HIDGamepad::maybeAddDPad):
(WebCore::HIDGamepad::maybeAddAxis):
(WebCore::fillInButtonValues):
(WebCore::HIDGamepad::valueChanged):
* platform/gamepad/mac/HIDGamepad.h:
(WebCore::HIDGamepadElement::isDPad):
(WebCore::HIDGamepadDPad::HIDGamepadDPad):
(WebCore::HIDGamepadDPad::normalizedValue):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformgamepadmacHIDGamepadcpp">trunk/Source/WebCore/platform/gamepad/mac/HIDGamepad.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgamepadmacHIDGamepadh">trunk/Source/WebCore/platform/gamepad/mac/HIDGamepad.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (211219 => 211220)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-01-26 18:55:34 UTC (rev 211219)
+++ trunk/Source/WebCore/ChangeLog        2017-01-26 19:21:39 UTC (rev 211220)
</span><span class="lines">@@ -1,3 +1,29 @@
</span><ins>+2017-01-26 Brady Eidson <beidson@apple.com>
+
+ Gamepad support shows wrong values for PS4 controllers (D-pad is missing).
+ <rdar://problem/29578619> and https://bugs.webkit.org/show_bug.cgi?id=165588
+
+ Reviewed by Alex Christensen.
+
+ No new tests (Currently unable to test HID backend directly)
+
+ DPads report their HID type as "a button", but their HID usage is "Hatswitch".
+ This patch adds a new element type that maps a "hatswitch" value to 4 additional buttons.
+
+ * platform/gamepad/mac/HIDGamepad.cpp:
+ (WebCore::HIDGamepad::initElements):
+ (WebCore::HIDGamepad::initElementsFromArray):
+ (WebCore::HIDGamepad::maybeAddButton):
+ (WebCore::HIDGamepad::maybeAddDPad):
+ (WebCore::HIDGamepad::maybeAddAxis):
+ (WebCore::fillInButtonValues):
+ (WebCore::HIDGamepad::valueChanged):
+
+ * platform/gamepad/mac/HIDGamepad.h:
+ (WebCore::HIDGamepadElement::isDPad):
+ (WebCore::HIDGamepadDPad::HIDGamepadDPad):
+ (WebCore::HIDGamepadDPad::normalizedValue):
+
</ins><span class="cx"> 2017-01-26 Antoine Quint <graouts@apple.com>
</span><span class="cx">
</span><span class="cx"> [Modern Media Controls] Hiding controls, changing their width and showing them again shows an incorrect layout
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgamepadmacHIDGamepadcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/gamepad/mac/HIDGamepad.cpp (211219 => 211220)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/gamepad/mac/HIDGamepad.cpp        2017-01-26 18:55:34 UTC (rev 211219)
+++ trunk/Source/WebCore/platform/gamepad/mac/HIDGamepad.cpp        2017-01-26 19:21:39 UTC (rev 211220)
</span><span class="lines">@@ -79,13 +79,16 @@
</span><span class="cx"> });
</span><span class="cx">
</span><span class="cx"> m_axisValues.resize(m_axes.size());
</span><del>- m_buttonValues.resize(m_buttons.size());
</del><ins>+ m_buttonValues.resize(m_buttons.size() + (m_dPads.size() * 4));
</ins><span class="cx">
</span><span class="cx"> for (auto& button : m_buttons)
</span><del>- getCurrentValueForElement(*button);
</del><ins>+ getCurrentValueForElement(button.get());
</ins><span class="cx">
</span><ins>+ for (auto& dPad : m_dPads)
+ getCurrentValueForElement(dPad.get());
+
</ins><span class="cx"> for (auto& axis : m_axes)
</span><del>- getCurrentValueForElement(*axis);
</del><ins>+ getCurrentValueForElement(axis.get());
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void HIDGamepad::initElementsFromArray(CFArrayRef elements)
</span><span class="lines">@@ -104,8 +107,12 @@
</span><span class="cx">
</span><span class="cx"> IOHIDElementType type = IOHIDElementGetType(element);
</span><span class="cx">
</span><del>- if ((type == kIOHIDElementTypeInput_Misc || type == kIOHIDElementTypeInput_Button) && maybeAddButton(element))
- continue;
</del><ins>+ if ((type == kIOHIDElementTypeInput_Misc || type == kIOHIDElementTypeInput_Button)) {
+ if (maybeAddButton(element))
+ continue;
+ if (maybeAddDPad(element))
+ continue;
+ }
</ins><span class="cx">
</span><span class="cx"> if ((type == kIOHIDElementTypeInput_Misc || type == kIOHIDElementTypeInput_Axis) && maybeAddAxis(element))
</span><span class="cx"> continue;
</span><span class="lines">@@ -128,14 +135,35 @@
</span><span class="cx"> CFIndex min = IOHIDElementGetLogicalMin(element);
</span><span class="cx"> CFIndex max = IOHIDElementGetLogicalMax(element);
</span><span class="cx">
</span><del>- m_buttons.append(std::make_unique<HIDGamepadButton>(usage, min, max, element));
</del><ins>+ m_buttons.append(makeUniqueRef<HIDGamepadButton>(usage, min, max, element));
</ins><span class="cx">
</span><span class="cx"> IOHIDElementCookie cookie = IOHIDElementGetCookie(element);
</span><del>- m_elementMap.set(cookie, m_buttons.last().get());
</del><ins>+ m_elementMap.set(cookie, &m_buttons.last().get());
</ins><span class="cx">
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+bool HIDGamepad::maybeAddDPad(IOHIDElementRef element)
+{
+ uint32_t usagePage = IOHIDElementGetUsagePage(element);
+ if (usagePage != kHIDPage_GenericDesktop)
+ return false;
+
+ uint32_t usage = IOHIDElementGetUsage(element);
+ if (!usage || usage != kHIDUsage_GD_Hatswitch)
+ return false;
+
+ CFIndex min = IOHIDElementGetLogicalMin(element);
+ CFIndex max = IOHIDElementGetLogicalMax(element);
+
+ m_dPads.append(makeUniqueRef<HIDGamepadDPad>(min, max, element));
+
+ IOHIDElementCookie cookie = IOHIDElementGetCookie(element);
+ m_elementMap.set(cookie, &m_dPads.last().get());
+
+ return true;
+}
+
</ins><span class="cx"> bool HIDGamepad::maybeAddAxis(IOHIDElementRef element)
</span><span class="cx"> {
</span><span class="cx"> uint32_t usagePage = IOHIDElementGetUsagePage(element);
</span><span class="lines">@@ -150,14 +178,46 @@
</span><span class="cx"> CFIndex min = IOHIDElementGetPhysicalMin(element);
</span><span class="cx"> CFIndex max = IOHIDElementGetPhysicalMax(element);
</span><span class="cx">
</span><del>- m_axes.append(std::make_unique<HIDGamepadAxis>(min, max, element));
</del><ins>+ m_axes.append(makeUniqueRef<HIDGamepadAxis>(min, max, element));
</ins><span class="cx">
</span><span class="cx"> IOHIDElementCookie cookie = IOHIDElementGetCookie(element);
</span><del>- m_elementMap.set(cookie, m_axes.last().get());
</del><ins>+ m_elementMap.set(cookie, &m_axes.last().get());
</ins><span class="cx">
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+static void fillInButtonValues(int value, double& button0, double& button1, double& button2, double& button3)
+{
+ // Standard DPads have 8 possible position values, moving around a circle:
+ // 0 - Up
+ // 1 - Up + right
+ // 2 - Right
+ // 3 - Down + right
+ // 4 - Down
+ // 5 - Down + left
+ // 6 - Left
+ // 7 - Up and Left
+ // These 8 positions are mapped on to 4 button positions:
+ // 0 - Up
+ // 1 - Down
+ // 2 - Left
+ // 3 - Right
+
+ if (value < 0 || value > 7) {
+ // Handle an invalid input value that we don't know how to interpret.
+ button0 = 0.0;
+ button1 = 0.0;
+ button2 = 0.0;
+ button3 = 0.0;
+ return;
+ }
+
+ button0 = value < 2 || value == 7 ? 1.0 : 0.0;
+ button1 = value > 2 && value < 6 ? 1.0 : 0.0;
+ button2 = value > 4 ? 1.0 : 0.0;
+ button3 = value > 0 && value < 4 ? 1.0 : 0.0;
+}
+
</ins><span class="cx"> HIDInputType HIDGamepad::valueChanged(IOHIDValueRef value)
</span><span class="cx"> {
</span><span class="cx"> IOHIDElementCookie cookie = IOHIDElementGetCookie(IOHIDValueGetElement(value));
</span><span class="lines">@@ -171,14 +231,31 @@
</span><span class="cx">
</span><span class="cx"> if (element->isButton()) {
</span><span class="cx"> for (unsigned i = 0; i < m_buttons.size(); ++i) {
</span><del>- if (m_buttons[i].get() == element)
</del><ins>+ if (&m_buttons[i].get() == element) {
</ins><span class="cx"> m_buttonValues[i] = element->normalizedValue();
</span><ins>+ break;
+ }
</ins><span class="cx"> }
</span><span class="cx"> } else if (element->isAxis()) {
</span><span class="cx"> for (unsigned i = 0; i < m_axes.size(); ++i) {
</span><del>- if (m_axes[i].get() == element)
</del><ins>+ if (&m_axes[i].get() == element) {
</ins><span class="cx"> m_axisValues[i] = element->normalizedValue();
</span><ins>+ break;
+ }
</ins><span class="cx"> }
</span><ins>+ } else if (element->isDPad()) {
+ int intValue = IOHIDValueGetIntegerValue(value) - element->min;
+ for (unsigned i = 0; i < m_dPads.size(); ++i) {
+ if (&m_dPads[i].get() != element)
+ continue;
+
+ // Each DPad represents 4 button values which are tacked on to the end of the values from non-DPad buttons.
+ unsigned firstButtonValue = m_buttons.size() + i * 4;
+
+ ASSERT(m_buttonValues.size() > firstButtonValue + 3);
+
+ fillInButtonValues(intValue, m_buttonValues[firstButtonValue], m_buttonValues[firstButtonValue + 1], m_buttonValues[firstButtonValue + 2], m_buttonValues[firstButtonValue + 3]);
+ }
</ins><span class="cx"> } else
</span><span class="cx"> ASSERT_NOT_REACHED();
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgamepadmacHIDGamepadh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/gamepad/mac/HIDGamepad.h (211219 => 211220)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/gamepad/mac/HIDGamepad.h        2017-01-26 18:55:34 UTC (rev 211219)
+++ trunk/Source/WebCore/platform/gamepad/mac/HIDGamepad.h        2017-01-26 19:21:39 UTC (rev 211220)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #include <IOKit/hid/IOHIDDevice.h>
</span><span class="cx"> #include <wtf/HashMap.h>
</span><span class="cx"> #include <wtf/RetainPtr.h>
</span><ins>+#include <wtf/UniqueRef.h>
</ins><span class="cx">
</span><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><span class="lines">@@ -54,6 +55,7 @@
</span><span class="cx">
</span><span class="cx"> virtual bool isButton() const { return false; }
</span><span class="cx"> virtual bool isAxis() const { return false; }
</span><ins>+ virtual bool isDPad() const { return false; }
</ins><span class="cx">
</span><span class="cx"> virtual double normalizedValue() = 0;
</span><span class="cx"> };
</span><span class="lines">@@ -67,7 +69,7 @@
</span><span class="cx">
</span><span class="cx"> uint32_t priority;
</span><span class="cx">
</span><del>- bool isButton() const override { return true; }
</del><ins>+ bool isButton() const final { return true; }
</ins><span class="cx">
</span><span class="cx"> // Buttons normalize to the range (0.0) - (1.0)
</span><span class="cx"> double normalizedValue() override
</span><span class="lines">@@ -82,7 +84,7 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><del>- bool isAxis() const override { return true; }
</del><ins>+ bool isAxis() const final { return true; }
</ins><span class="cx">
</span><span class="cx"> // Axes normalize to the range (-1.0) - (1.0)
</span><span class="cx"> double normalizedValue() override
</span><span class="lines">@@ -91,6 +93,17 @@
</span><span class="cx"> }
</span><span class="cx"> };
</span><span class="cx">
</span><ins>+struct HIDGamepadDPad : HIDGamepadElement {
+ HIDGamepadDPad(double min, double max, IOHIDElementRef element)
+ : HIDGamepadElement(min, max, element)
+ {
+ }
+
+ bool isDPad() const final { return true; }
+
+ virtual double normalizedValue() { RELEASE_ASSERT_NOT_REACHED(); }
+};
+
</ins><span class="cx"> enum class HIDInputType {
</span><span class="cx"> ButtonPress,
</span><span class="cx"> NotAButtonPress,
</span><span class="lines">@@ -112,6 +125,7 @@
</span><span class="cx"> void initElementsFromArray(CFArrayRef);
</span><span class="cx">
</span><span class="cx"> bool maybeAddButton(IOHIDElementRef);
</span><ins>+ bool maybeAddDPad(IOHIDElementRef);
</ins><span class="cx"> bool maybeAddAxis(IOHIDElementRef);
</span><span class="cx">
</span><span class="cx"> void getCurrentValueForElement(const HIDGamepadElement&);
</span><span class="lines">@@ -120,8 +134,9 @@
</span><span class="cx">
</span><span class="cx"> HashMap<IOHIDElementCookie, HIDGamepadElement*> m_elementMap;
</span><span class="cx">
</span><del>- Vector<std::unique_ptr<HIDGamepadButton>> m_buttons;
- Vector<std::unique_ptr<HIDGamepadAxis>> m_axes;
</del><ins>+ Vector<UniqueRef<HIDGamepadButton>> m_buttons;
+ Vector<UniqueRef<HIDGamepadAxis>> m_axes;
+ Vector<UniqueRef<HIDGamepadDPad>> m_dPads;
</ins><span class="cx"> Vector<double> m_buttonValues;
</span><span class="cx"> Vector<double> m_axisValues;
</span><span class="cx"> };
</span></span></pre>
</div>
</div>
</body>
</html>