Changeset 265079 in webkit


Ignore:
Timestamp:
Jul 30, 2020 12:21:44 AM (4 years ago)
Author:
beidson@apple.com
Message:

Refactor HID gamepad code to be much less fragile and much easier to hack on.
https://bugs.webkit.org/show_bug.cgi?id=214910

Reviewed by Darin Adler.

Source/WebCore:

Covered by API tests.

Currently - for HID device gamepads - we throw all buttons and axes against the wall and see what sticks.
Instead, for specific popular devices, we'd like to have device-specific mappings so the representation makes sense.

To support that work, this is a major refactoring of the HID gamepad code. It does the following:

  • Breaks out logic specific to IOHIDDeviceRef into HIDDevice
  • Breaks out logic specific to IOHIDElementRef into HIDElement
  • Moves responsibities of managing things to the right places (e.g. HIDElement manages its own current value directly)
  • Makes HIDGamepadElement derive from HIDElement directly
  • Moves device specific logic from HIDGamepad into a subclass of HID gamepad. Currently the only subclass is "generic" which encompasses HIDGamepad's old behavior
  • Changes button/value vectors from Vector<double> to Vector<SharedGamepadValue> so multiple objects can reference the value at once. e.g. HIDGamepadButton can simply update it's own SharedGamepadValue without knowing which HIDGamepad owns it or which index into the gamepad's value vector it should be mutating.

This will be critical in the "specific device mapping" work as some types of HIDElements actually drive more than one
gamepad button value.
e.g. a "direction pad axis" actually manages 2 button values, or a "hat-switch" direction pad manages 4 button values

This patch doesn't change any current behavior.

  • Modules/gamepad/Gamepad.cpp:

(WebCore::Gamepad::updateFromPlatformGamepad):

  • Sources.txt:
  • SourcesCocoa.txt:
  • WebCore.xcodeproj/project.pbxproj:
  • platform/Logging.h:
  • platform/gamepad/PlatformGamepad.h:
  • platform/gamepad/SharedGamepadValue.h: Copied from Source/WebKit/UIProcess/Gamepad/UIGamepad.h.

(WebCore::SharedGamepadValue::SharedGamepadValue):
(WebCore::SharedGamepadValue::setValue):
(WebCore::SharedGamepadValue::value const):
(WebCore::SharedGamepadValue::Data::Data):

  • platform/gamepad/cocoa/GameControllerGamepad.h:
  • platform/gamepad/cocoa/GameControllerGamepad.mm:

(WebCore::GameControllerGamepad::setupAsExtendedGamepad):
(WebCore::GameControllerGamepad::setupAsGamepad):

  • platform/gamepad/mac/GenericHIDGamepad.cpp: Added.

(WebCore::GenericHIDGamepad::GenericHIDGamepad):
(WebCore::GenericHIDGamepad::id):
(WebCore::GenericHIDGamepad::maybeAddGenericDesktopElement):
(WebCore::GenericHIDGamepad::maybeAddButtonElement):

  • platform/gamepad/mac/GenericHIDGamepad.h: Copied from Source/WebKit/WebProcess/Gamepad/WebGamepad.h.
  • platform/gamepad/mac/HIDGamepad.cpp:

(WebCore::HIDGamepad::create):
(WebCore::HIDGamepad::HIDGamepad):
(WebCore::HIDGamepad::initialize):
(WebCore::HIDGamepad::valueChanged):
(WebCore::HIDGamepad::getCurrentValueForElement): Deleted.
(WebCore::HIDGamepad::initElements): Deleted.
(WebCore::HIDGamepad::initElementsFromArray): Deleted.
(WebCore::HIDGamepad::maybeAddButton): Deleted.
(WebCore::HIDGamepad::maybeAddAxis): Deleted.

  • platform/gamepad/mac/HIDGamepad.h:

(WebCore::HIDGamepad::hidDevice const):
(WebCore::HIDGamepadElement::HIDGamepadElement): Deleted.
(WebCore::HIDGamepadElement::~HIDGamepadElement): Deleted.
(WebCore::HIDGamepadElement::isButton const): Deleted.
(WebCore::HIDGamepadElement::isAxis const): Deleted.
(WebCore::HIDGamepadButton::HIDGamepadButton): Deleted.
(WebCore::HIDGamepadAxis::HIDGamepadAxis): Deleted.

  • platform/gamepad/mac/HIDGamepadElement.cpp: Added.

(WebCore::HIDGamepadElement::HIDGamepadElement):
(WebCore::HIDGamepadElement::refreshCurrentValue):
(WebCore::HIDGamepadElement::normalizedValue):
(WebCore::HIDGamepadButton::gamepadValueChanged):
(WebCore::HIDGamepadAxis::gamepadValueChanged):
(WebCore::HIDGamepadAxis::normalizedValue):

  • platform/gamepad/mac/HIDGamepadElement.h: Copied from Source/WebCore/platform/gamepad/PlatformGamepad.h.

(WebCore::HIDGamepadElement::~HIDGamepadElement):
(WebCore::HIDGamepadElement::isButton const):
(WebCore::HIDGamepadElement::isAxis const):

  • platform/gamepad/mac/HIDGamepadProvider.mm:

(WebCore::HIDGamepadProvider::deviceAdded):

  • platform/gamepad/mac/MultiGamepadProvider.h:
  • platform/graphics/cocoa/SourceBufferParserWebM.cpp:
  • platform/mac/HIDDevice.cpp: Added.

(WebCore::HIDDevice::HIDDevice):
(WebCore::HIDDevice::uniqueInputElementsInDeviceTreeOrder const):

  • platform/mac/HIDDevice.h: Copied from Source/WebCore/platform/gamepad/PlatformGamepad.h.

(WebCore::HIDDevice::rawElement const):
(WebCore::HIDDevice::vendorID const):
(WebCore::HIDDevice::productID const):
(WebCore::HIDDevice::productName const):

  • platform/mac/HIDElement.cpp: Copied from Source/WebKit/UIProcess/Gamepad/UIGamepad.h.

(WebCore::HIDElement::HIDElement):
(WebCore::HIDElement::valueChanged):

  • platform/mac/HIDElement.h: Copied from Source/WebKit/UIProcess/Gamepad/UIGamepad.h.

(WebCore::HIDElement::rawElement const):
(WebCore::HIDElement::physicalMin const):
(WebCore::HIDElement::physicalMax const):
(WebCore::HIDElement::physicalValue const):
(WebCore::HIDElement::usage const):
(WebCore::HIDElement::usagePage const):
(WebCore::HIDElement::cookie const):

  • testing/MockGamepad.cpp:

(WebCore::MockGamepad::updateDetails):
(WebCore::MockGamepad::setAxisValue):
(WebCore::MockGamepad::setButtonValue):

  • testing/MockGamepad.h:

Source/WebKit:

  • Shared/Gamepad/GamepadData.cpp:

(WebKit::GamepadData::GamepadData):

  • Shared/Gamepad/GamepadData.h:
  • UIProcess/Gamepad/UIGamepad.h:
  • WebProcess/Gamepad/WebGamepad.cpp:

(WebKit::WebGamepad::axisValues const):
(WebKit::WebGamepad::buttonValues const):
(WebKit::WebGamepad::updateValues):

  • WebProcess/Gamepad/WebGamepad.h:

Tools:

Add a test that verifies connect, basic button/axis changes, and disconnect of a HID gamepad.

  • TestWebKitAPI/Tests/mac/HIDGamepads.mm:
Location:
trunk
Files:
3 added
24 edited
6 copied

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r265075 r265079  
     12020-07-30  Brady Eidson  <beidson@apple.com>
     2
     3        Refactor HID gamepad code to be much less fragile and much easier to hack on.
     4        https://bugs.webkit.org/show_bug.cgi?id=214910
     5
     6        Reviewed by Darin Adler.
     7
     8        Covered by API tests.
     9               
     10        Currently - for HID device gamepads - we throw all buttons and axes against the wall and see what sticks.
     11        Instead, for specific popular devices, we'd like to have device-specific mappings so the representation makes sense.
     12       
     13        To support that work, this is a major refactoring of the HID gamepad code. It does the following:
     14
     15        - Breaks out logic specific to IOHIDDeviceRef into HIDDevice
     16       
     17        - Breaks out logic specific to IOHIDElementRef into HIDElement
     18       
     19        - Moves responsibities of managing things to the right places (e.g. HIDElement manages its own current value directly)
     20       
     21        - Makes HIDGamepadElement derive from HIDElement directly
     22         
     23        - Moves device specific logic from HIDGamepad into a subclass of HID gamepad. Currently the only subclass is "generic"
     24          which encompasses HIDGamepad's old behavior
     25
     26        - Changes button/value vectors from Vector<double> to Vector<SharedGamepadValue> so multiple objects can reference
     27          the value at once.
     28          e.g. HIDGamepadButton can simply update it's own SharedGamepadValue without knowing which HIDGamepad owns it or which index
     29          into the gamepad's value vector it should be mutating.
     30
     31          This will be critical in the "specific device mapping" work as some types of HIDElements actually drive more than one
     32          gamepad button value.
     33          e.g. a "direction pad axis" actually manages 2 button values, or a "hat-switch" direction pad manages 4 button values
     34         
     35        This patch doesn't change any current behavior.
     36
     37        * Modules/gamepad/Gamepad.cpp:
     38        (WebCore::Gamepad::updateFromPlatformGamepad):
     39
     40        * Sources.txt:
     41        * SourcesCocoa.txt:
     42        * WebCore.xcodeproj/project.pbxproj:
     43
     44        * platform/Logging.h:
     45
     46        * platform/gamepad/PlatformGamepad.h:
     47
     48        * platform/gamepad/SharedGamepadValue.h: Copied from Source/WebKit/UIProcess/Gamepad/UIGamepad.h.
     49        (WebCore::SharedGamepadValue::SharedGamepadValue):
     50        (WebCore::SharedGamepadValue::setValue):
     51        (WebCore::SharedGamepadValue::value const):
     52        (WebCore::SharedGamepadValue::Data::Data):
     53
     54        * platform/gamepad/cocoa/GameControllerGamepad.h:
     55        * platform/gamepad/cocoa/GameControllerGamepad.mm:
     56        (WebCore::GameControllerGamepad::setupAsExtendedGamepad):
     57        (WebCore::GameControllerGamepad::setupAsGamepad):
     58
     59        * platform/gamepad/mac/GenericHIDGamepad.cpp: Added.
     60        (WebCore::GenericHIDGamepad::GenericHIDGamepad):
     61        (WebCore::GenericHIDGamepad::id):
     62        (WebCore::GenericHIDGamepad::maybeAddGenericDesktopElement):
     63        (WebCore::GenericHIDGamepad::maybeAddButtonElement):
     64        * platform/gamepad/mac/GenericHIDGamepad.h: Copied from Source/WebKit/WebProcess/Gamepad/WebGamepad.h.
     65
     66        * platform/gamepad/mac/HIDGamepad.cpp:
     67        (WebCore::HIDGamepad::create):
     68        (WebCore::HIDGamepad::HIDGamepad):
     69        (WebCore::HIDGamepad::initialize):
     70        (WebCore::HIDGamepad::valueChanged):
     71        (WebCore::HIDGamepad::getCurrentValueForElement): Deleted.
     72        (WebCore::HIDGamepad::initElements): Deleted.
     73        (WebCore::HIDGamepad::initElementsFromArray): Deleted.
     74        (WebCore::HIDGamepad::maybeAddButton): Deleted.
     75        (WebCore::HIDGamepad::maybeAddAxis): Deleted.
     76        * platform/gamepad/mac/HIDGamepad.h:
     77        (WebCore::HIDGamepad::hidDevice const):
     78        (WebCore::HIDGamepadElement::HIDGamepadElement): Deleted.
     79        (WebCore::HIDGamepadElement::~HIDGamepadElement): Deleted.
     80        (WebCore::HIDGamepadElement::isButton const): Deleted.
     81        (WebCore::HIDGamepadElement::isAxis const): Deleted.
     82        (WebCore::HIDGamepadButton::HIDGamepadButton): Deleted.
     83        (WebCore::HIDGamepadAxis::HIDGamepadAxis): Deleted.
     84
     85        * platform/gamepad/mac/HIDGamepadElement.cpp: Added.
     86        (WebCore::HIDGamepadElement::HIDGamepadElement):
     87        (WebCore::HIDGamepadElement::refreshCurrentValue):
     88        (WebCore::HIDGamepadElement::normalizedValue):
     89        (WebCore::HIDGamepadButton::gamepadValueChanged):
     90        (WebCore::HIDGamepadAxis::gamepadValueChanged):
     91        (WebCore::HIDGamepadAxis::normalizedValue):
     92        * platform/gamepad/mac/HIDGamepadElement.h: Copied from Source/WebCore/platform/gamepad/PlatformGamepad.h.
     93        (WebCore::HIDGamepadElement::~HIDGamepadElement):
     94        (WebCore::HIDGamepadElement::isButton const):
     95        (WebCore::HIDGamepadElement::isAxis const):
     96
     97        * platform/gamepad/mac/HIDGamepadProvider.mm:
     98        (WebCore::HIDGamepadProvider::deviceAdded):
     99        * platform/gamepad/mac/MultiGamepadProvider.h:
     100
     101        * platform/graphics/cocoa/SourceBufferParserWebM.cpp:
     102
     103        * platform/mac/HIDDevice.cpp: Added.
     104        (WebCore::HIDDevice::HIDDevice):
     105        (WebCore::HIDDevice::uniqueInputElementsInDeviceTreeOrder const):
     106        * platform/mac/HIDDevice.h: Copied from Source/WebCore/platform/gamepad/PlatformGamepad.h.
     107        (WebCore::HIDDevice::rawElement const):
     108        (WebCore::HIDDevice::vendorID const):
     109        (WebCore::HIDDevice::productID const):
     110        (WebCore::HIDDevice::productName const):
     111
     112        * platform/mac/HIDElement.cpp: Copied from Source/WebKit/UIProcess/Gamepad/UIGamepad.h.
     113        (WebCore::HIDElement::HIDElement):
     114        (WebCore::HIDElement::valueChanged):
     115        * platform/mac/HIDElement.h: Copied from Source/WebKit/UIProcess/Gamepad/UIGamepad.h.
     116        (WebCore::HIDElement::rawElement const):
     117        (WebCore::HIDElement::physicalMin const):
     118        (WebCore::HIDElement::physicalMax const):
     119        (WebCore::HIDElement::physicalValue const):
     120        (WebCore::HIDElement::usage const):
     121        (WebCore::HIDElement::usagePage const):
     122        (WebCore::HIDElement::cookie const):
     123
     124        * testing/MockGamepad.cpp:
     125        (WebCore::MockGamepad::updateDetails):
     126        (WebCore::MockGamepad::setAxisValue):
     127        (WebCore::MockGamepad::setButtonValue):
     128        * testing/MockGamepad.h:
     129
    11302020-07-29  Joonghun Park  <jh718.park@samsung.com>
    2131
  • trunk/Source/WebCore/Modules/gamepad/Gamepad.cpp

    r256215 r265079  
    6363{
    6464    for (unsigned i = 0; i < m_axes.size(); ++i)
    65         m_axes[i] = platformGamepad.axisValues()[i];
     65        m_axes[i] = platformGamepad.axisValues()[i].value();
    6666    for (unsigned i = 0; i < m_buttons.size(); ++i)
    67         m_buttons[i]->setValue(platformGamepad.buttonValues()[i]);
     67        m_buttons[i]->setValue(platformGamepad.buttonValues()[i].value());
    6868
    6969    m_timestamp = platformGamepad.lastUpdateTime();
  • trunk/Source/WebCore/Sources.txt

    r265066 r265079  
    18161816platform/encryptedmedia/CDMPrivate.cpp
    18171817platform/encryptedmedia/CDMProxy.cpp
     1818platform/gamepad/EmptyGamepadProvider.cpp
     1819platform/gamepad/GamepadProvider.cpp
    18181820platform/graphics/ANGLEWebKitBridge.cpp
    18191821platform/graphics/BitmapImage.cpp
  • trunk/Source/WebCore/SourcesCocoa.txt

    r264805 r265079  
    258258platform/gamepad/cocoa/GameControllerGamepad.mm
    259259platform/gamepad/cocoa/GameControllerGamepadProvider.mm
     260platform/gamepad/mac/GenericHIDGamepad.cpp
    260261platform/gamepad/mac/HIDGamepad.cpp
     262platform/gamepad/mac/HIDGamepadElement.cpp
    261263platform/gamepad/mac/HIDGamepadProvider.mm
    262264platform/gamepad/mac/MultiGamepadProvider.mm
     
    469471platform/mac/BlocklistUpdater.mm
    470472platform/mac/CursorMac.mm @no-unify
     473platform/mac/HIDDevice.cpp
     474platform/mac/HIDElement.cpp
    471475platform/mac/KeyEventMac.mm @no-unify
    472476platform/mac/LocalCurrentGraphicsContextMac.mm
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r265066 r265079  
    13991399                5106D7BE18BDB76F000AB166 /* ContextMenuContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 5106D7BC18BDB76F000AB166 /* ContextMenuContext.h */; settings = {ATTRIBUTES = (Private, ); }; };
    14001400                510A58FA1BACC7F200C19282 /* IDBRequestData.h in Headers */ = {isa = PBXBuildFile; fileRef = 510A58F61BACC4A500C19282 /* IDBRequestData.h */; settings = {ATTRIBUTES = (Private, ); }; };
     1401                510A91DA24CF3D8C00BFD89C /* HIDGamepadElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 510A91D624CE8EDE00BFD89C /* HIDGamepadElement.h */; settings = {ATTRIBUTES = (Private, ); }; };
     1402                510A91DC24CF46FE00BFD89C /* SharedGamepadValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 510A91DB24CF441800BFD89C /* SharedGamepadValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
     1403                510A91EA24D004C300BFD89C /* HIDElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 510A91E324CFCC1800BFD89C /* HIDElement.h */; settings = {ATTRIBUTES = (Private, ); }; };
     1404                510A91EB24D004C800BFD89C /* HIDDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 510A91E224CFCC1800BFD89C /* HIDDevice.h */; settings = {ATTRIBUTES = (Private, ); }; };
    14011405                510D4A34103165EE0049EA54 /* SocketStreamError.h in Headers */ = {isa = PBXBuildFile; fileRef = 510D4A2E103165EE0049EA54 /* SocketStreamError.h */; settings = {ATTRIBUTES = (Private, ); }; };
    14021406                510D4A37103165EE0049EA54 /* SocketStreamHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = 510D4A31103165EE0049EA54 /* SocketStreamHandle.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    14331437                514C767D0CE923A1007EF3CD /* ResourceRequestBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 514C76680CE923A1007EF3CD /* ResourceRequestBase.h */; settings = {ATTRIBUTES = (Private, ); }; };
    14341438                514C767F0CE923A1007EF3CD /* ResourceResponseBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 514C766A0CE923A1007EF3CD /* ResourceResponseBase.h */; settings = {ATTRIBUTES = (Private, ); }; };
    1435                 515BE18F1D54F5FB00DD7C68 /* EmptyGamepadProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 515BE1881D54F5F600DD7C68 /* EmptyGamepadProvider.cpp */; };
    14361439                515BE1901D54F5FB00DD7C68 /* EmptyGamepadProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 515BE1891D54F5F600DD7C68 /* EmptyGamepadProvider.h */; };
    1437                 515BE1911D54F5FB00DD7C68 /* GamepadProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 515BE18A1D54F5F600DD7C68 /* GamepadProvider.cpp */; };
    14381440                515BE1921D54F5FB00DD7C68 /* GamepadProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 515BE18B1D54F5F600DD7C68 /* GamepadProvider.h */; settings = {ATTRIBUTES = (Private, ); }; };
    14391441                515BE1931D54F5FB00DD7C68 /* GamepadProviderClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 515BE18C1D54F5F600DD7C68 /* GamepadProviderClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    82158217                510A58FD1BB07A9600C19282 /* IDBConnectionToServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBConnectionToServer.h; sourceTree = "<group>"; };
    82168218                510A58FE1BB07AA500C19282 /* IDBConnectionToClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBConnectionToClient.h; sourceTree = "<group>"; };
     8219                510A91D524CE8EDE00BFD89C /* HIDGamepadElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HIDGamepadElement.cpp; sourceTree = "<group>"; };
     8220                510A91D624CE8EDE00BFD89C /* HIDGamepadElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HIDGamepadElement.h; sourceTree = "<group>"; };
     8221                510A91DB24CF441800BFD89C /* SharedGamepadValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SharedGamepadValue.h; sourceTree = "<group>"; };
     8222                510A91E224CFCC1800BFD89C /* HIDDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HIDDevice.h; sourceTree = "<group>"; };
     8223                510A91E324CFCC1800BFD89C /* HIDElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HIDElement.h; sourceTree = "<group>"; };
     8224                510A91E424CFCC1800BFD89C /* HIDElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HIDElement.cpp; sourceTree = "<group>"; };
     8225                510A91E524CFCC1800BFD89C /* HIDDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HIDDevice.cpp; sourceTree = "<group>"; };
     8226                510A91E724CFEA1700BFD89C /* GenericHIDGamepad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GenericHIDGamepad.cpp; sourceTree = "<group>"; };
     8227                510A91E924CFEA3200BFD89C /* GenericHIDGamepad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenericHIDGamepad.h; sourceTree = "<group>"; };
    82178228                510D4A2E103165EE0049EA54 /* SocketStreamError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SocketStreamError.h; sourceTree = "<group>"; };
    82188229                510D4A30103165EE0049EA54 /* SocketStreamHandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SocketStreamHandle.cpp; sourceTree = "<group>"; };
     
    83708381                51714EAE1CF6654A004723C4 /* JSGCObservation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSGCObservation.cpp; sourceTree = "<group>"; };
    83718382                51714EAF1CF6654A004723C4 /* JSGCObservation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGCObservation.h; sourceTree = "<group>"; };
     8383                51715FE824CD05DD002C97E6 /* GamepadConstants.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GamepadConstants.cpp; sourceTree = "<group>"; };
     8384                51715FE924CD05DD002C97E6 /* GamepadConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GamepadConstants.h; sourceTree = "<group>"; };
    83728385                51741D0B0B07259A00ED442C /* BackForwardClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BackForwardClient.h; sourceTree = "<group>"; };
    83738386                51741D0D0B07259A00ED442C /* HistoryItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HistoryItem.h; sourceTree = "<group>"; };
     
    1964419657                                515BE1881D54F5F600DD7C68 /* EmptyGamepadProvider.cpp */,
    1964519658                                515BE1891D54F5F600DD7C68 /* EmptyGamepadProvider.h */,
     19659                                51715FE824CD05DD002C97E6 /* GamepadConstants.cpp */,
     19660                                51715FE924CD05DD002C97E6 /* GamepadConstants.h */,
    1964619661                                515BE18A1D54F5F600DD7C68 /* GamepadProvider.cpp */,
    1964719662                                515BE18B1D54F5F600DD7C68 /* GamepadProvider.h */,
    1964819663                                515BE18C1D54F5F600DD7C68 /* GamepadProviderClient.h */,
    1964919664                                515BE18E1D54F5F600DD7C68 /* PlatformGamepad.h */,
     19665                                510A91DB24CF441800BFD89C /* SharedGamepadValue.h */,
    1965019666                        );
    1965119667                        path = gamepad;
     
    1965519671                        isa = PBXGroup;
    1965619672                        children = (
     19673                                510A91E724CFEA1700BFD89C /* GenericHIDGamepad.cpp */,
     19674                                510A91E924CFEA3200BFD89C /* GenericHIDGamepad.h */,
    1965719675                                515BE1971D54F6BD00DD7C68 /* HIDGamepad.cpp */,
    1965819676                                515BE1981D54F6BD00DD7C68 /* HIDGamepad.h */,
     19677                                510A91D524CE8EDE00BFD89C /* HIDGamepadElement.cpp */,
     19678                                510A91D624CE8EDE00BFD89C /* HIDGamepadElement.h */,
    1965919679                                515BE19A1D54F6BD00DD7C68 /* HIDGamepadProvider.h */,
    1966019680                                515BE1991D54F6BD00DD7C68 /* HIDGamepadProvider.mm */,
     
    2105221072                                F58784F002DE375901EA4122 /* CursorMac.mm */,
    2105321073                                E1BA66F01742BD8600C20251 /* DynamicLinkerInterposing.h */,
     21074                                510A91E524CFCC1800BFD89C /* HIDDevice.cpp */,
     21075                                510A91E224CFCC1800BFD89C /* HIDDevice.h */,
     21076                                510A91E424CFCC1800BFD89C /* HIDElement.cpp */,
     21077                                510A91E324CFCC1800BFD89C /* HIDElement.h */,
    2105421078                                935C476E09AC4D7300A6AAB4 /* KeyEventMac.mm */,
    2105521079                                F44A5F571FED3830007F5944 /* LegacyNSPasteboardTypes.h */,
     
    3103131055                                CDA595982146DF7800A84185 /* HEVCUtilitiesCocoa.h in Headers */,
    3103231056                                F55B3DC01251F12D003EF269 /* HiddenInputType.h in Headers */,
     31057                                510A91EB24D004C800BFD89C /* HIDDevice.h in Headers */,
     31058                                510A91EA24D004C300BFD89C /* HIDElement.h in Headers */,
    3103331059                                515BE19C1D54F6C100DD7C68 /* HIDGamepad.h in Headers */,
     31060                                510A91DA24CF3D8C00BFD89C /* HIDGamepadElement.h in Headers */,
    3103431061                                515BE19E1D54F6C100DD7C68 /* HIDGamepadProvider.h in Headers */,
    3103531062                                CDCFABBD18C0AF78006F8450 /* HighlightData.h in Headers */,
     
    3330933336                                1D9F0FC12122029B005D8FD4 /* ShareData.h in Headers */,
    3331033337                                1A4A954E0B4EDCCB002D8C3C /* SharedBuffer.h in Headers */,
     33338                                510A91DC24CF46FE00BFD89C /* SharedGamepadValue.h in Headers */,
    3331133339                                834DFAD01F7DAE5D00C2725B /* SharedStringHash.h in Headers */,
    3331233340                                93309EA3099EB78C0056E581 /* SharedTimer.h in Headers */,
     
    3461934647                                5CBD59592280E926002B22AA /* CustomHeaderFields.cpp in Sources */,
    3462034648                                4463CF682212FA68001A8577 /* DataDetectorsCoreSoftLink.mm in Sources */,
    34621                                 515BE18F1D54F5FB00DD7C68 /* EmptyGamepadProvider.cpp in Sources */,
    3462234649                                6E72F54C229DCD0C00B3E151 /* ExtensionsGLANGLE.cpp in Sources */,
    3462334650                                7CE6CBFD187F394900D46BF5 /* FormatConverter.cpp in Sources */,
     
    3462734654                                516C62201950D48700337E75 /* GamepadEvent.cpp in Sources */,
    3462834655                                51A9D9E9195B931F001B2B5C /* GamepadManager.cpp in Sources */,
    34629                                 515BE1911D54F5FB00DD7C68 /* GamepadProvider.cpp in Sources */,
    3463034656                                837964CF1F8DB69D00218EA0 /* GeolocationPositionDataIOS.mm in Sources */,
    3463134657                                6E72F54E229DCD1000B3E151 /* GraphicsContextGLANGLE.cpp in Sources */,
  • trunk/Source/WebCore/platform/Logging.h

    r264134 r265079  
    11/*
    2  * Copyright (C) 2003-2017 Apple Inc.  All rights reserved.
     2 * Copyright (C) 2003-2020 Apple Inc.  All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    6464    M(Fullscreen) \
    6565    M(Gamepad) \
     66    M(HID) \
    6667    M(History) \
    6768    M(IOSurface) \
  • trunk/Source/WebCore/platform/gamepad/PlatformGamepad.h

    r264207 r265079  
    2828#if ENABLE(GAMEPAD)
    2929
     30#include "SharedGamepadValue.h"
    3031#include <wtf/Forward.h>
    3132#include <wtf/MonotonicTime.h>
     
    4445    virtual MonotonicTime lastUpdateTime() const { return m_lastUpdateTime; }
    4546    MonotonicTime connectTime() const { return m_connectTime; }
    46     virtual const Vector<double>& axisValues() const = 0;
    47     virtual const Vector<double>& buttonValues() const = 0;
     47   
     48    virtual const Vector<SharedGamepadValue>& axisValues() const = 0;
     49    virtual const Vector<SharedGamepadValue>& buttonValues() const = 0;
    4850
    4951    virtual const char* source() const { return "Unknown"_s; }
  • trunk/Source/WebCore/platform/gamepad/SharedGamepadValue.h

    r265078 r265079  
    11/*
    2  * Copyright (C) 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2020 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2828#if ENABLE(GAMEPAD)
    2929
    30 #include <wtf/MonotonicTime.h>
    31 #include <wtf/Vector.h>
    32 #include <wtf/text/WTFString.h>
     30#include <wtf/FastMalloc.h>
     31#include <wtf/Nonmovable.h>
     32#include <wtf/Ref.h>
     33#include <wtf/RefCounted.h>
    3334
    3435namespace WebCore {
    35 class PlatformGamepad;
    36 }
    3736
    38 namespace WebKit {
     37class SharedGamepadValue {
     38public:
     39    SharedGamepadValue()
     40        : m_data(adoptRef(*new Data(0.0)))
     41    {
     42    }
    3943
    40 class GamepadData;
     44    explicit SharedGamepadValue(double value)
     45        : m_data(adoptRef(*new Data(value)))
     46    {
     47    }
    4148
    42 class UIGamepad {
    43     WTF_MAKE_FAST_ALLOCATED;
    44 public:
    45     UIGamepad(WebCore::PlatformGamepad&);
    46 
    47     unsigned index() const { return m_index; }
    48 
    49     GamepadData condensedGamepadData() const;
    50     GamepadData fullGamepadData() const;
    51 
    52     void updateFromPlatformGamepad(WebCore::PlatformGamepad&);
     49    void setValue(double value) { m_data->value = value; }
     50    double value() const { return m_data->value; }
    5351
    5452private:
    55     unsigned m_index;
    56     String m_id;
    57     String m_mapping;
    58     Vector<double> m_axisValues;
    59     Vector<double> m_buttonValues;
    60     MonotonicTime m_lastUpdateTime;
     53    struct Data : RefCounted<Data> {
     54        WTF_MAKE_STRUCT_FAST_ALLOCATED;
     55
     56        Data(double theValue)
     57            : value(theValue)
     58        {
     59        }
     60
     61        double value;
     62    };
     63
     64    Ref<Data> m_data;
    6165};
    6266
    63 }
     67} // namespace WebCore
    6468
    6569#endif // ENABLE(GAMEPAD)
  • trunk/Source/WebCore/platform/gamepad/cocoa/GameControllerGamepad.h

    r264207 r265079  
    4545    GameControllerGamepad(GCController *, unsigned index);
    4646
    47     const Vector<double>& axisValues() const final { return m_axisValues; }
    48     const Vector<double>& buttonValues() const final { return m_buttonValues; }
     47    const Vector<SharedGamepadValue>& axisValues() const final { return m_axisValues; }
     48    const Vector<SharedGamepadValue>& buttonValues() const final { return m_buttonValues; }
    4949
    5050    const char* source() const final { return "GameController"_s; }
     
    5656    RetainPtr<GCController> m_gcController;
    5757
    58     Vector<double> m_axisValues;
    59     Vector<double> m_buttonValues;
     58    Vector<SharedGamepadValue> m_axisValues;
     59    Vector<SharedGamepadValue> m_buttonValues;
    6060
    6161    RetainPtr<GCGamepad> m_gamepad;
  • trunk/Source/WebCore/platform/gamepad/cocoa/GameControllerGamepad.mm

    r264258 r265079  
    111111
    112112    auto bindButton = ^(GCControllerButtonInput *button, GamepadButtons index) {
    113         m_buttonValues[(size_t)index] = button.value;
     113        m_buttonValues[(size_t)index].setValue(button.value);
    114114        button.valueChangedHandler = ^(GCControllerButtonInput *, float value, BOOL pressed) {
    115             m_buttonValues[(size_t)index] = value;
     115            m_buttonValues[(size_t)index].setValue(value);
    116116            if (pressed)
    117117                m_hadButtonPresses = true;
     
    159159
    160160    m_axisValues.resize(4);
    161     m_axisValues[0] = m_extendedGamepad.get().leftThumbstick.xAxis.value;
    162     m_axisValues[1] = -m_extendedGamepad.get().leftThumbstick.yAxis.value;
    163     m_axisValues[2] = m_extendedGamepad.get().rightThumbstick.xAxis.value;
    164     m_axisValues[3] = -m_extendedGamepad.get().rightThumbstick.yAxis.value;
     161    m_axisValues[0].setValue(m_extendedGamepad.get().leftThumbstick.xAxis.value);
     162    m_axisValues[1].setValue(-m_extendedGamepad.get().leftThumbstick.yAxis.value);
     163    m_axisValues[2].setValue(m_extendedGamepad.get().rightThumbstick.xAxis.value);
     164    m_axisValues[3].setValue(-m_extendedGamepad.get().rightThumbstick.yAxis.value);
    165165
    166166    m_extendedGamepad.get().leftThumbstick.xAxis.valueChangedHandler = ^(GCControllerAxisInput *, float value) {
    167         m_axisValues[0] = value;
     167        m_axisValues[0].setValue(value);
    168168    };
    169169    m_extendedGamepad.get().leftThumbstick.yAxis.valueChangedHandler = ^(GCControllerAxisInput *, float value) {
    170         m_axisValues[1] = -value;
     170        m_axisValues[1].setValue(-value);
    171171    };
    172172    m_extendedGamepad.get().rightThumbstick.xAxis.valueChangedHandler = ^(GCControllerAxisInput *, float value) {
    173         m_axisValues[2] = value;
     173        m_axisValues[2].setValue(value);
    174174    };
    175175    m_extendedGamepad.get().rightThumbstick.yAxis.valueChangedHandler = ^(GCControllerAxisInput *, float value) {
    176         m_axisValues[3] = -value;
     176        m_axisValues[3].setValue(-value);
    177177    };
    178178}
     
    193193
    194194    m_buttonValues.resize(6);
    195     m_buttonValues[0] = m_extendedGamepad.get().buttonA.value;
    196     m_buttonValues[1] = m_extendedGamepad.get().buttonB.value;
    197     m_buttonValues[2] = m_extendedGamepad.get().buttonX.value;
    198     m_buttonValues[3] = m_extendedGamepad.get().buttonY.value;
    199     m_buttonValues[4] = m_extendedGamepad.get().leftShoulder.value;
    200     m_buttonValues[5] = m_extendedGamepad.get().rightShoulder.value;
     195    m_buttonValues[0].setValue(m_extendedGamepad.get().buttonA.value);
     196    m_buttonValues[1].setValue(m_extendedGamepad.get().buttonB.value);
     197    m_buttonValues[2].setValue(m_extendedGamepad.get().buttonX.value);
     198    m_buttonValues[3].setValue(m_extendedGamepad.get().buttonY.value);
     199    m_buttonValues[4].setValue(m_extendedGamepad.get().leftShoulder.value);
     200    m_buttonValues[5].setValue(m_extendedGamepad.get().rightShoulder.value);
    201201
    202202    m_axisValues.resize(2);
    203     m_axisValues[0] = m_extendedGamepad.get().dpad.xAxis.value;
    204     m_axisValues[1] = m_extendedGamepad.get().dpad.yAxis.value;
     203    m_axisValues[0].setValue(m_extendedGamepad.get().dpad.xAxis.value);
     204    m_axisValues[1].setValue(m_extendedGamepad.get().dpad.yAxis.value);
    205205
    206206    m_extendedGamepad.get().buttonA.valueChangedHandler = ^(GCControllerButtonInput *, float value, BOOL pressed) {
    207         m_buttonValues[0] = value;
     207        m_buttonValues[0].setValue(value);
    208208        if (pressed)
    209209            m_hadButtonPresses = true;
    210210    };
    211211    m_extendedGamepad.get().buttonB.valueChangedHandler = ^(GCControllerButtonInput *, float value, BOOL pressed) {
    212         m_buttonValues[1] = value;
     212        m_buttonValues[1].setValue(value);
    213213        if (pressed)
    214214            m_hadButtonPresses = true;
    215215    };
    216216    m_extendedGamepad.get().buttonX.valueChangedHandler = ^(GCControllerButtonInput *, float value, BOOL pressed) {
    217         m_buttonValues[2] = value;
     217        m_buttonValues[2].setValue(value);
    218218        if (pressed)
    219219            m_hadButtonPresses = true;
    220220    };
    221221    m_extendedGamepad.get().buttonY.valueChangedHandler = ^(GCControllerButtonInput *, float value, BOOL pressed) {
    222         m_buttonValues[3] = value;
     222        m_buttonValues[3].setValue(value);
    223223        if (pressed)
    224224            m_hadButtonPresses = true;
    225225    };
    226226    m_extendedGamepad.get().leftShoulder.valueChangedHandler = ^(GCControllerButtonInput *, float value, BOOL pressed) {
    227         m_buttonValues[4] = value;
     227        m_buttonValues[4].setValue(value);
    228228        if (pressed)
    229229            m_hadButtonPresses = true;
    230230    };
    231231    m_extendedGamepad.get().rightShoulder.valueChangedHandler = ^(GCControllerButtonInput *, float value, BOOL pressed) {
    232         m_buttonValues[5] = value;
     232        m_buttonValues[5].setValue(value);
    233233        if (pressed)
    234234            m_hadButtonPresses = true;
     
    236236
    237237    m_extendedGamepad.get().leftThumbstick.xAxis.valueChangedHandler = ^(GCControllerAxisInput *, float value) {
    238         m_axisValues[0] = value;
     238        m_axisValues[0].setValue(value);
    239239    };
    240240    m_extendedGamepad.get().leftThumbstick.yAxis.valueChangedHandler = ^(GCControllerAxisInput *, float value) {
    241         m_axisValues[1] = value;
     241        m_axisValues[1].setValue(value);
    242242    };
    243243}
  • trunk/Source/WebCore/platform/gamepad/mac/GenericHIDGamepad.h

    r265078 r265079  
    11/*
    2  * Copyright (C) 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2020 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2626#pragma once
    2727
    28 #if ENABLE(GAMEPAD)
     28#if ENABLE(GAMEPAD) && PLATFORM(MAC)
    2929
    30 #include <WebCore/PlatformGamepad.h>
     30#include "HIDGamepad.h"
    3131
    32 namespace WebKit {
     32namespace WebCore {
    3333
    34 class SharedMemory;
    35 
    36 class GamepadData;
    37 
    38 class WebGamepad : public WebCore::PlatformGamepad {
     34class GenericHIDGamepad final : public HIDGamepad {
    3935public:
    40     WebGamepad(const GamepadData&);
    41 
    42     const Vector<double>& axisValues() const override;
    43     const Vector<double>& buttonValues() const override;
    44 
    45     void updateValues(const GamepadData&);
     36    GenericHIDGamepad(HIDDevice&&, unsigned index);
    4637
    4738private:
    48     Vector<double> m_axisValues;
    49     Vector<double> m_buttonValues;
     39    String id() final;
     40
     41    void maybeAddGenericDesktopElement(HIDElement&);
     42    void maybeAddButtonElement(HIDElement&);
    5043};
    5144
    52 }
     45} // namespace WebCore
    5346
    54 #endif // ENABLE(GAMEPAD)
     47#endif // ENABLE(GAMEPAD) && PLATFORM(MAC)
  • trunk/Source/WebCore/platform/gamepad/mac/HIDGamepad.cpp

    r264475 r265079  
    2929#if ENABLE(GAMEPAD) && PLATFORM(MAC)
    3030
     31#include "GenericHIDGamepad.h"
     32#include "Logging.h"
    3133#include <IOKit/hid/IOHIDElement.h>
    3234#include <IOKit/hid/IOHIDUsageTables.h>
    3335#include <IOKit/hid/IOHIDValue.h>
    34 #include <wtf/HexNumber.h>
    3536#include <wtf/cf/TypeCastsCF.h>
    3637#include <wtf/text/CString.h>
    3738
    38 WTF_DECLARE_CF_TYPE_TRAIT(IOHIDElement);
    39 
    4039namespace WebCore {
    4140
    42 HIDGamepad::HIDGamepad(IOHIDDeviceRef hidDevice, unsigned index)
     41std::unique_ptr<HIDGamepad> HIDGamepad::create(IOHIDDeviceRef rawDevice, unsigned index)
     42{
     43    auto device = HIDDevice { rawDevice };
     44
     45    // When we support specific mapping for a particular device, here is where we'll decide what kind of HIDGamepad to make.
     46    // For now, it's only the GenericHIDGamepad
     47    auto newGamepad = makeUnique<GenericHIDGamepad>(WTFMove(device), index);
     48
     49    newGamepad->initialize();
     50    return WTFMove(newGamepad);
     51}
     52
     53HIDGamepad::HIDGamepad(HIDDevice&& device, unsigned index)
    4354    : PlatformGamepad(index)
    44     , m_hidDevice(hidDevice)
     55    , m_device(WTFMove(device))
    4556{
    4657    m_connectTime = m_lastUpdateTime = MonotonicTime::now();
    47 
    48     CFNumberRef cfVendorID = (CFNumberRef)IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDVendorIDKey));
    49     CFNumberRef cfProductID = (CFNumberRef)IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDProductIDKey));
    50 
    51     int vendorID, productID;
    52     CFNumberGetValue(cfVendorID, kCFNumberIntType, &vendorID);
    53     CFNumberGetValue(cfProductID, kCFNumberIntType, &productID);
    54 
    55     CFStringRef cfProductName = (CFStringRef)IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDProductKey));
    56     String productName(cfProductName);
    57 
    58     // Currently the spec has no formatting for the id string.
    59     // This string formatting matches Firefox.
    60     m_id = makeString(hex(vendorID, Lowercase), '-', hex(productID, Lowercase), '-', productName);
    61 
    62     initElements();
    6358}
    6459
    65 void HIDGamepad::getCurrentValueForElement(const HIDGamepadElement& gamepadElement)
     60void HIDGamepad::initialize()
    6661{
    67     IOHIDElementRef element = gamepadElement.iohidElement.get();
    68     IOHIDValueRef value;
    69     if (IOHIDDeviceGetValue(IOHIDElementGetDevice(element), element, &value) == kIOReturnSuccess)
    70         valueChanged(value);
    71 }
     62    m_id = id();
    7263
    73 void HIDGamepad::initElements()
    74 {
    75     RetainPtr<CFArrayRef> elements = adoptCF(IOHIDDeviceCopyMatchingElements(m_hidDevice.get(), NULL, kIOHIDOptionsTypeNone));
    76     initElementsFromArray(elements.get());
    77 
    78     // Buttons are specified to appear highest priority first in the array.
    79     std::sort(m_buttons.begin(), m_buttons.end(), [](auto& a, auto& b) {
    80         return a->priority < b->priority;
    81     });
    82 
    83     LOG(Gamepad, "HIDGamepad initialized with %zu buttons and %zu axes", m_buttons.size(), m_axes.size());
    84 
    85     m_axisValues.resize(m_axes.size());
    86     m_buttonValues.resize(m_buttons.size());
    87 
    88     for (auto& button : m_buttons)
    89         getCurrentValueForElement(button.get());
    90 
    91     for (auto& axis : m_axes)
    92         getCurrentValueForElement(axis.get());
    93 }
    94 
    95 void HIDGamepad::initElementsFromArray(CFArrayRef elements)
    96 {
    97     for (CFIndex i = 0, count = CFArrayGetCount(elements); i < count; ++i) {
    98         IOHIDElementRef element = checked_cf_cast<IOHIDElementRef>(CFArrayGetValueAtIndex(elements, i));
    99         if (CFGetTypeID(element) != IOHIDElementGetTypeID())
    100             continue;
    101 
    102         // As a physical element can appear in the device twice (in different collections) and can be
    103         // represented by different IOHIDElementRef objects, we look at the IOHIDElementCookie which
    104         // is meant to be unique for each physical element.
    105         IOHIDElementCookie cookie = IOHIDElementGetCookie(element);
    106         if (m_elementMap.contains(cookie))
    107             continue;
    108 
    109         IOHIDElementType type = IOHIDElementGetType(element);
    110 
    111         if ((type == kIOHIDElementTypeInput_Misc || type == kIOHIDElementTypeInput_Button)) {
    112             if (maybeAddButton(element))
    113                 continue;
    114         }
    115 
    116         if ((type == kIOHIDElementTypeInput_Misc || type == kIOHIDElementTypeInput_Axis) && maybeAddAxis(element))
    117             continue;
    118 
    119         if (type == kIOHIDElementTypeCollection)
    120             initElementsFromArray(IOHIDElementGetChildren(element));
    121     }
    122 }
    123 
    124 bool HIDGamepad::maybeAddButton(IOHIDElementRef element)
    125 {
    126     uint32_t usagePage = IOHIDElementGetUsagePage(element);
    127     if (usagePage != kHIDPage_Button && usagePage != kHIDPage_GenericDesktop)
    128         return false;
    129 
    130     uint32_t usage = IOHIDElementGetUsage(element);
    131 
    132     if (usagePage == kHIDPage_GenericDesktop) {
    133         if (usage < kHIDUsage_GD_DPadUp || usage > kHIDUsage_GD_DPadLeft)
    134             return false;
    135         usage = std::numeric_limits<uint32_t>::max();
    136     } else if (!usage)
    137         return false;
    138 
    139     CFIndex min = IOHIDElementGetLogicalMin(element);
    140     CFIndex max = IOHIDElementGetLogicalMax(element);
    141 
    142     m_buttons.append(makeUniqueRef<HIDGamepadButton>(usage, min, max, element));
    143 
    144     IOHIDElementCookie cookie = IOHIDElementGetCookie(element);
    145     m_elementMap.set(cookie, &m_buttons.last().get());
    146 
    147     return true;
    148 }
    149 
    150 bool HIDGamepad::maybeAddAxis(IOHIDElementRef element)
    151 {
    152     uint32_t usagePage = IOHIDElementGetUsagePage(element);
    153     if (usagePage != kHIDPage_GenericDesktop)
    154         return false;
    155 
    156     uint32_t usage = IOHIDElementGetUsage(element);
    157     // This range covers the standard axis usages.
    158     if (usage < kHIDUsage_GD_X || usage > kHIDUsage_GD_Rz)
    159         return false;
    160 
    161     CFIndex min = IOHIDElementGetPhysicalMin(element);
    162     CFIndex max = IOHIDElementGetPhysicalMax(element);
    163 
    164     m_axes.append(makeUniqueRef<HIDGamepadAxis>(min, max, element));
    165 
    166     IOHIDElementCookie cookie = IOHIDElementGetCookie(element);
    167     m_elementMap.set(cookie, &m_axes.last().get());
    168 
    169     return true;
     64    for (auto& element : m_elementMap.values())
     65        element->refreshCurrentValue();
    17066}
    17167
     
    17975        return HIDInputType::NotAButtonPress;
    18076
    181     element->rawValue = IOHIDValueGetScaledValue(value, kIOHIDValueScaleTypePhysical);
    182 
    183     if (element->isButton()) {
    184         for (unsigned i = 0; i < m_buttons.size(); ++i) {
    185             if (&m_buttons[i].get() == element) {
    186                 m_buttonValues[i] = element->normalizedValue();
    187                 break;
    188             }
    189         }
    190     } else if (element->isAxis()) {
    191         for (unsigned i = 0; i < m_axes.size(); ++i) {
    192             if (&m_axes[i].get() == element) {
    193                 m_axisValues[i] = element->normalizedValue();
    194                 break;
    195             }
    196         }
    197     } else
    198         ASSERT_NOT_REACHED();
    199 
    20077    m_lastUpdateTime = MonotonicTime::now();
    20178
    202     return element->isButton() ? HIDInputType::ButtonPress : HIDInputType::NotAButtonPress;
     79    return element->gamepadValueChanged(value);
    20380}
    20481
  • trunk/Source/WebCore/platform/gamepad/mac/HIDGamepad.h

    r264475 r265079  
    2828#if ENABLE(GAMEPAD) && PLATFORM(MAC)
    2929
     30#include "HIDDevice.h"
     31#include "HIDGamepadElement.h"
    3032#include "PlatformGamepad.h"
    3133#include <IOKit/hid/IOHIDDevice.h>
    3234#include <wtf/HashMap.h>
    33 #include <wtf/RetainPtr.h>
    34 #include <wtf/UniqueRef.h>
    3535
    3636namespace WebCore {
    3737
    38 struct HIDGamepadElement {
    39     WTF_MAKE_STRUCT_FAST_ALLOCATED;
    40     HIDGamepadElement(double theMin, double theMax, IOHIDElementRef element)
    41         : min(theMin)
    42         , max(theMax)
    43         , rawValue(theMin)
    44         , iohidElement(element)
    45     {
    46     }
    47    
    48     virtual ~HIDGamepadElement()
    49     {
    50     }
    51 
    52     double min;
    53     double max;
    54     double rawValue;
    55     RetainPtr<IOHIDElementRef> iohidElement;
    56 
    57     virtual bool isButton() const { return false; }
    58     virtual bool isAxis() const { return false; }
    59 
    60     virtual double normalizedValue() = 0;
    61 };
    62 
    63 struct HIDGamepadButton : HIDGamepadElement {
    64     HIDGamepadButton(uint32_t thePriority, double min, double max, IOHIDElementRef element)
    65         : HIDGamepadElement(min, max, element)
    66         , priority(thePriority)
    67     {
    68     }
    69 
    70     uint32_t priority;
    71 
    72     bool isButton() const final { return true; }
    73 
    74     // Buttons normalize to the range (0.0) - (1.0)
    75     double normalizedValue() override
    76     {
    77         return (rawValue - min) / (max - min);
    78     }
    79 };
    80 
    81 struct HIDGamepadAxis : HIDGamepadElement {
    82     HIDGamepadAxis(double min, double max, IOHIDElementRef element)
    83         : HIDGamepadElement(min, max, element)
    84     {
    85     }
    86 
    87     bool isAxis() const final { return true; }
    88 
    89     // Axes normalize to the range (-1.0) - (1.0)
    90     double normalizedValue() override
    91     {
    92         return (((rawValue - min) / (max - min)) * 2) - 1;
    93     }
    94 };
    95 
    96 enum class HIDInputType {
    97     ButtonPress,
    98     NotAButtonPress,
    99 };
    100 
    10138class HIDGamepad : public PlatformGamepad {
    10239public:
    103     HIDGamepad(IOHIDDeviceRef, unsigned index);
     40    static std::unique_ptr<HIDGamepad> create(IOHIDDeviceRef, unsigned index);
    10441
    105     IOHIDDeviceRef hidDevice() const { return m_hidDevice.get(); }
     42    const HIDDevice& hidDevice() const { return m_device; }
    10643
     44    void initialize();
    10745    HIDInputType valueChanged(IOHIDValueRef);
    10846
    109     const Vector<double>& axisValues() const final { return m_axisValues; }
    110     const Vector<double>& buttonValues() const final { return m_buttonValues; }
     47    const Vector<SharedGamepadValue>& axisValues() const final { return m_axisValues; }
     48    const Vector<SharedGamepadValue>& buttonValues() const final { return m_buttonValues; }
    11149
    11250    const char* source() const final { return "HID"_s; }
    11351
     52protected:
     53    HIDGamepad(HIDDevice&&, unsigned index);
     54
     55    virtual String id() = 0;
     56
     57    HashMap<IOHIDElementCookie, std::unique_ptr<HIDGamepadElement>> m_elementMap;
     58    Vector<SharedGamepadValue> m_buttonValues;
     59    Vector<SharedGamepadValue> m_axisValues;
     60
    11461private:
    115     void initElements();
    116     void initElementsFromArray(CFArrayRef);
    117 
    118     bool maybeAddButton(IOHIDElementRef);
    119     bool maybeAddAxis(IOHIDElementRef);
    120 
    121     void getCurrentValueForElement(const HIDGamepadElement&);
    122 
    123     RetainPtr<IOHIDDeviceRef> m_hidDevice;
    124 
    125     HashMap<IOHIDElementCookie, HIDGamepadElement*> m_elementMap;
    126 
    127     Vector<UniqueRef<HIDGamepadButton>> m_buttons;
    128     Vector<UniqueRef<HIDGamepadAxis>> m_axes;
    129     Vector<double> m_buttonValues;
    130     Vector<double> m_axisValues;
     62    HIDDevice m_device;
    13163};
    13264
  • trunk/Source/WebCore/platform/gamepad/mac/HIDGamepadElement.h

    r265078 r265079  
    11/*
    2  * Copyright (C) 2014 Apple Inc. All rights reserved.
     2 * Copyright (C) 2020 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2626#pragma once
    2727
    28 #if ENABLE(GAMEPAD)
     28#if ENABLE(GAMEPAD) && PLATFORM(MAC)
    2929
    30 #include <wtf/Forward.h>
    31 #include <wtf/MonotonicTime.h>
    32 #include <wtf/text/WTFString.h>
     30#include "HIDElement.h"
     31#include "SharedGamepadValue.h"
     32#include <wtf/HashMap.h>
     33#include <wtf/RetainPtr.h>
     34#include <wtf/UniqueRef.h>
    3335
    3436namespace WebCore {
    3537
    36 class PlatformGamepad {
     38enum class HIDInputType {
     39    ButtonPress,
     40    NotAButtonPress,
     41};
     42
     43class HIDGamepadElement : public HIDElement {
    3744    WTF_MAKE_FAST_ALLOCATED;
    3845public:
    39     virtual ~PlatformGamepad() = default;
     46    virtual ~HIDGamepadElement() { }
    4047
    41     const String& id() const { return m_id; }
    42     const String& mapping() const { return m_mapping; }
    43     unsigned index() const { return m_index; }
    44     virtual MonotonicTime lastUpdateTime() const { return m_lastUpdateTime; }
    45     MonotonicTime connectTime() const { return m_connectTime; }
    46     virtual const Vector<double>& axisValues() const = 0;
    47     virtual const Vector<double>& buttonValues() const = 0;
     48    virtual double normalizedValue();
     49    virtual HIDInputType gamepadValueChanged(IOHIDValueRef) = 0;
    4850
    49     virtual const char* source() const { return "Unknown"_s; }
     51    void refreshCurrentValue();
    5052
    5153protected:
    52     explicit PlatformGamepad(unsigned index)
    53         : m_index(index)
     54    HIDGamepadElement(const HIDElement&, SharedGamepadValue&);
     55
     56    virtual bool isButton() const { return false; }
     57    virtual bool isAxis() const { return false; }
     58
     59    SharedGamepadValue m_value;
     60};
     61
     62class HIDGamepadButton final : public HIDGamepadElement {
     63public:
     64    HIDGamepadButton(const HIDElement& element, SharedGamepadValue& value)
     65        : HIDGamepadElement(element, value)
    5466    {
    5567    }
    5668
    57     String m_id;
    58     String m_mapping;
    59     unsigned m_index;
    60     MonotonicTime m_lastUpdateTime;
    61     MonotonicTime m_connectTime;
     69    bool isButton() const final { return true; }
     70
     71private:
     72    HIDInputType gamepadValueChanged(IOHIDValueRef) override;
     73};
     74
     75class HIDGamepadAxis final : public HIDGamepadElement {
     76public:
     77    HIDGamepadAxis(const HIDElement& element, SharedGamepadValue& value)
     78        : HIDGamepadElement(element, value)
     79    {
     80    }
     81
     82    bool isAxis() const final { return true; }
     83    double normalizedValue() final;
     84
     85private:
     86    HIDInputType gamepadValueChanged(IOHIDValueRef) override;
    6287};
    6388
    6489} // namespace WebCore
    6590
    66 #endif // ENABLE(GAMEPAD)
     91#endif // ENABLE(GAMEPAD) && PLATFORM(MAC)
  • trunk/Source/WebCore/platform/gamepad/mac/HIDGamepadProvider.mm

    r264874 r265079  
    236236
    237237    unsigned index = indexForNewlyConnectedDevice();
    238     std::unique_ptr<HIDGamepad> gamepad = makeUnique<HIDGamepad>(device, index);
     238    auto gamepad = HIDGamepad::create(device, index);
    239239
    240240    if (m_gamepadVector.size() <= index)
  • trunk/Source/WebCore/platform/gamepad/mac/MultiGamepadProvider.h

    r264769 r265079  
    6464    Vector<PlatformGamepad*> m_gamepadVector;
    6565
    66     // We create our own Gamepad type - to wrap both HID and GameControler gamepads -
     66    // We create our own Gamepad type - to wrap both HID and GameController gamepads -
    6767    // because MultiGamepadProvider needs to manage the indexes of its own gamepads
    6868    // no matter what the HID or GameController index is.
     
    7979
    8080        MonotonicTime lastUpdateTime() const final { return m_platformGamepad->lastUpdateTime(); }
    81         const Vector<double>& axisValues() const final { return m_platformGamepad->axisValues(); }
    82         const Vector<double>& buttonValues() const final { return m_platformGamepad->buttonValues(); }
     81        const Vector<SharedGamepadValue>& axisValues() const final { return m_platformGamepad->axisValues(); }
     82        const Vector<SharedGamepadValue>& buttonValues() const final { return m_platformGamepad->buttonValues(); }
    8383
    8484        const char* source() const final { return m_platformGamepad->source(); }
  • trunk/Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.cpp

    r265073 r265079  
    3939#include "VP9UtilitiesCocoa.h"
    4040#include "VideoTrackPrivateWebM.h"
     41#include "VideoToolboxSoftLink.h"
    4142#include <JavaScriptCore/DataView.h>
    4243#include <pal/cf/CoreMediaSoftLink.h>
  • trunk/Source/WebCore/platform/mac/HIDDevice.h

    r265078 r265079  
    11/*
    2  * Copyright (C) 2014 Apple Inc. All rights reserved.
     2 * Copyright (C) 2020 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2626#pragma once
    2727
    28 #if ENABLE(GAMEPAD)
     28#if PLATFORM(MAC)
    2929
    3030#include <wtf/Forward.h>
    31 #include <wtf/MonotonicTime.h>
    32 #include <wtf/text/WTFString.h>
     31#include <wtf/RetainPtr.h>
     32
     33typedef struct CF_BRIDGED_TYPE(id) __IOHIDDevice * IOHIDDeviceRef;
    3334
    3435namespace WebCore {
    3536
    36 class PlatformGamepad {
     37class HIDElement;
     38
     39class HIDDevice {
    3740    WTF_MAKE_FAST_ALLOCATED;
    3841public:
    39     virtual ~PlatformGamepad() = default;
     42    explicit HIDDevice(IOHIDDeviceRef);
    4043
    41     const String& id() const { return m_id; }
    42     const String& mapping() const { return m_mapping; }
    43     unsigned index() const { return m_index; }
    44     virtual MonotonicTime lastUpdateTime() const { return m_lastUpdateTime; }
    45     MonotonicTime connectTime() const { return m_connectTime; }
    46     virtual const Vector<double>& axisValues() const = 0;
    47     virtual const Vector<double>& buttonValues() const = 0;
     44    IOHIDDeviceRef rawElement() const { return m_rawDevice.get(); }
    4845
    49     virtual const char* source() const { return "Unknown"_s; }
     46    // Walks the collection tree of all elements in the device as presented by IOKit.
     47    // Adds each unique input element to the vector in the tree traversal order it was encountered.
     48    // "Unique" is defined as "having a different IOHIDElementCookie from any previously added element"
     49    Vector<HIDElement> uniqueInputElementsInDeviceTreeOrder() const;
    5050
    51 protected:
    52     explicit PlatformGamepad(unsigned index)
    53         : m_index(index)
    54     {
    55     }
     51    uint16_t vendorID() const { return m_vendorID; }
     52    uint16_t productID() const { return m_productID; }
     53    const String& productName() const { return m_productName; }
    5654
    57     String m_id;
    58     String m_mapping;
    59     unsigned m_index;
    60     MonotonicTime m_lastUpdateTime;
    61     MonotonicTime m_connectTime;
     55private:
     56    RetainPtr<IOHIDDeviceRef> m_rawDevice;
     57
     58    uint16_t m_vendorID;
     59    uint16_t m_productID;
     60    String m_productName;
    6261};
    6362
    6463} // namespace WebCore
    6564
    66 #endif // ENABLE(GAMEPAD)
     65#endif // PLATFORM(MAC)
  • trunk/Source/WebCore/platform/mac/HIDElement.cpp

    r265078 r265079  
    11/*
    2  * Copyright (C) 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2020 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 #pragma once
     26#include "config.h"
     27#include "HIDElement.h"
    2728
    28 #if ENABLE(GAMEPAD)
     29#if PLATFORM(MAC)
    2930
    30 #include <wtf/MonotonicTime.h>
    31 #include <wtf/Vector.h>
    32 #include <wtf/text/WTFString.h>
     31#include <IOKit/hid/IOHIDValue.h>
    3332
    3433namespace WebCore {
    35 class PlatformGamepad;
     34
     35HIDElement::HIDElement(IOHIDElementRef element)
     36    : m_physicalMin(IOHIDElementGetPhysicalMin(element))
     37    , m_physicalMax(IOHIDElementGetPhysicalMax(element))
     38    , m_physicalValue(m_physicalMin)
     39    , m_usage(IOHIDElementGetUsage(element))
     40    , m_usagePage(IOHIDElementGetUsagePage(element))
     41    , m_cookie(IOHIDElementGetCookie(element))
     42    , m_rawElement(element)
     43{
    3644}
    3745
    38 namespace WebKit {
     46void HIDElement::valueChanged(IOHIDValueRef value)
     47{
     48    if (IOHIDValueGetElement(value) != m_rawElement.get()) {
     49        LOG(HID, "HIDElement: Changed value whose IOHIDElement %p doesn't match %p", IOHIDValueGetElement(value), m_rawElement.get());
     50        return;
     51    }
    3952
    40 class GamepadData;
    41 
    42 class UIGamepad {
    43     WTF_MAKE_FAST_ALLOCATED;
    44 public:
    45     UIGamepad(WebCore::PlatformGamepad&);
    46 
    47     unsigned index() const { return m_index; }
    48 
    49     GamepadData condensedGamepadData() const;
    50     GamepadData fullGamepadData() const;
    51 
    52     void updateFromPlatformGamepad(WebCore::PlatformGamepad&);
    53 
    54 private:
    55     unsigned m_index;
    56     String m_id;
    57     String m_mapping;
    58     Vector<double> m_axisValues;
    59     Vector<double> m_buttonValues;
    60     MonotonicTime m_lastUpdateTime;
    61 };
    62 
     53    m_physicalValue = IOHIDValueGetScaledValue(value, kIOHIDValueScaleTypePhysical);
    6354}
    6455
    65 #endif // ENABLE(GAMEPAD)
     56} // namespace WebCore
     57
     58#endif // PLATFORM(MAC)
  • trunk/Source/WebCore/platform/mac/HIDElement.h

    r265078 r265079  
    11/*
    2  * Copyright (C) 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2020 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2626#pragma once
    2727
    28 #if ENABLE(GAMEPAD)
     28#if PLATFORM(MAC)
    2929
    30 #include <wtf/MonotonicTime.h>
    31 #include <wtf/Vector.h>
    32 #include <wtf/text/WTFString.h>
     30#include <IOKit/hid/IOHIDDevice.h>
     31#include <wtf/RetainPtr.h>
    3332
    3433namespace WebCore {
    35 class PlatformGamepad;
    36 }
    3734
    38 namespace WebKit {
    39 
    40 class GamepadData;
    41 
    42 class UIGamepad {
     35class HIDElement {
    4336    WTF_MAKE_FAST_ALLOCATED;
    4437public:
    45     UIGamepad(WebCore::PlatformGamepad&);
     38    explicit HIDElement(IOHIDElementRef);
    4639
    47     unsigned index() const { return m_index; }
     40    IOHIDElementRef rawElement() const { return m_rawElement.get(); }
    4841
    49     GamepadData condensedGamepadData() const;
    50     GamepadData fullGamepadData() const;
     42    CFIndex physicalMin() const { return m_physicalMin; }
     43    CFIndex physicalMax() const { return m_physicalMax; }
     44    CFIndex physicalValue() const { return m_physicalValue; }
     45    uint32_t usage() const { return m_usage; }
     46    uint32_t usagePage() const { return m_usagePage; }
     47    IOHIDElementCookie cookie() const { return m_cookie; }
    5148
    52     void updateFromPlatformGamepad(WebCore::PlatformGamepad&);
     49    void valueChanged(IOHIDValueRef);
    5350
    5451private:
    55     unsigned m_index;
    56     String m_id;
    57     String m_mapping;
    58     Vector<double> m_axisValues;
    59     Vector<double> m_buttonValues;
    60     MonotonicTime m_lastUpdateTime;
     52    CFIndex m_physicalMin;
     53    CFIndex m_physicalMax;
     54    CFIndex m_physicalValue;
     55    uint32_t m_usage;
     56    uint32_t m_usagePage;
     57    IOHIDElementCookie m_cookie;
     58    RetainPtr<IOHIDElementRef> m_rawElement;
    6159};
    6260
    63 }
    6461
    65 #endif // ENABLE(GAMEPAD)
     62} // namespace WebCore
     63
     64#endif // PLATFORM(MAC)
  • trunk/Source/WebCore/testing/MockGamepad.cpp

    r256215 r265079  
    4242    m_id = gamepadID;
    4343    m_mapping = mapping;
    44     m_axisValues = Vector<double>(axisCount, 0.0);
    45     m_buttonValues = Vector<double>(buttonCount, 0.0);
     44    m_axisValues.clear();
     45    for (size_t i = 0; i < axisCount; ++i)
     46        m_axisValues.append({ });
     47    m_buttonValues.clear();
     48    for (size_t i = 0; i < buttonCount; ++i)
     49        m_buttonValues.append({ });
    4650    m_lastUpdateTime = MonotonicTime::now();
    4751}
     
    5458    }
    5559
    56     m_axisValues[index] = value;
     60    m_axisValues[index].setValue(value);
    5761    m_lastUpdateTime = MonotonicTime::now();
    5862    return true;
     
    6670    }
    6771
    68     m_buttonValues[index] = value;
     72    m_buttonValues[index].setValue(value);
    6973    m_lastUpdateTime = MonotonicTime::now();
    7074    return true;
  • trunk/Source/WebCore/testing/MockGamepad.h

    r256215 r265079  
    3636    MockGamepad(unsigned index, const String& gamepadID, const String& mapping, unsigned axisCount, unsigned buttonCount);
    3737
    38     const Vector<double>& axisValues() const final { return m_axisValues; }
    39     const Vector<double>& buttonValues() const final { return m_buttonValues; }
     38    const Vector<SharedGamepadValue>& axisValues() const final { return m_axisValues; }
     39    const Vector<SharedGamepadValue>& buttonValues() const final { return m_buttonValues; }
    4040
    4141    void updateDetails(const String& gamepadID, const String& mapping, unsigned axisCount, unsigned buttonCount);
     
    4444
    4545private:
    46     Vector<double> m_axisValues;
    47     Vector<double> m_buttonValues;
     46    Vector<SharedGamepadValue> m_axisValues;
     47    Vector<SharedGamepadValue> m_buttonValues;
    4848};
    4949
  • trunk/Source/WebKit/ChangeLog

    r265078 r265079  
     12020-07-30  Brady Eidson  <beidson@apple.com>
     2
     3        Refactor HID gamepad code to be much less fragile and much easier to hack on.
     4        https://bugs.webkit.org/show_bug.cgi?id=214910
     5
     6        Reviewed by Darin Adler.
     7
     8        * Shared/Gamepad/GamepadData.cpp:
     9        (WebKit::GamepadData::GamepadData):
     10        * Shared/Gamepad/GamepadData.h:
     11
     12        * UIProcess/Gamepad/UIGamepad.h:
     13
     14        * WebProcess/Gamepad/WebGamepad.cpp:
     15        (WebKit::WebGamepad::axisValues const):
     16        (WebKit::WebGamepad::buttonValues const):
     17        (WebKit::WebGamepad::updateValues):
     18        * WebProcess/Gamepad/WebGamepad.h:
     19
    1202020-07-30  Commit Queue  <commit-queue@webkit.org>
    221
  • trunk/Source/WebKit/Shared/Gamepad/GamepadData.cpp

    r256215 r265079  
    3232#include <wtf/text/StringBuilder.h>
    3333
     34using WebCore::SharedGamepadValue;
     35
    3436namespace WebKit {
    3537
    36 GamepadData::GamepadData(unsigned index, const Vector<double>& axisValues, const Vector<double>& buttonValues, MonotonicTime lastUpdateTime)
     38GamepadData::GamepadData(unsigned index, const Vector<SharedGamepadValue>& axisValues, const Vector<SharedGamepadValue>& buttonValues, MonotonicTime lastUpdateTime)
    3739    : m_index(index)
    38     , m_axisValues(axisValues)
    39     , m_buttonValues(buttonValues)
     40    , m_axisValues(WTF::map(axisValues, [](const auto& value) { return value.value(); }))
     41    , m_buttonValues(WTF::map(buttonValues, [](const auto& value) { return value.value(); }))
    4042    , m_lastUpdateTime(lastUpdateTime)
    4143{
    4244}
    4345
    44 GamepadData::GamepadData(unsigned index, const String& id, const String& mapping, const Vector<double>& axisValues, const Vector<double>& buttonValues, MonotonicTime lastUpdateTime)
     46GamepadData::GamepadData(unsigned index, const String& id, const String& mapping, const Vector<SharedGamepadValue>& axisValues, const Vector<SharedGamepadValue>& buttonValues, MonotonicTime lastUpdateTime)
    4547    : m_index(index)
    4648    , m_id(id)
    4749    , m_mapping(mapping)
    48     , m_axisValues(axisValues)
    49     , m_buttonValues(buttonValues)
     50    , m_axisValues(WTF::map(axisValues, [](const auto& value) { return value.value(); }))
     51    , m_buttonValues(WTF::map(buttonValues, [](const auto& value) { return value.value(); }))
    5052    , m_lastUpdateTime(lastUpdateTime)
    5153{
  • trunk/Source/WebKit/Shared/Gamepad/GamepadData.h

    r256215 r265079  
    2828#if ENABLE(GAMEPAD)
    2929
     30#include <WebCore/SharedGamepadValue.h>
    3031#include <wtf/MonotonicTime.h>
    3132#include <wtf/Vector.h>
     
    4647    }
    4748
    48     GamepadData(unsigned index, const Vector<double>& axisValues, const Vector<double>& buttonValues, MonotonicTime lastUpdateTime);
    49     GamepadData(unsigned index, const String& id, const String& mapping, const Vector<double>& axisValues, const Vector<double>& buttonValues, MonotonicTime lastUpdateTime);
     49    GamepadData(unsigned index, const Vector<WebCore::SharedGamepadValue>& axisValues, const Vector<WebCore::SharedGamepadValue>& buttonValues, MonotonicTime lastUpdateTime);
     50    GamepadData(unsigned index, const String& id, const String& mapping, const Vector<WebCore::SharedGamepadValue>& axisValues, const Vector<WebCore::SharedGamepadValue>& buttonValues, MonotonicTime lastUpdateTime);
    5051
    5152    void encode(IPC::Encoder&) const;
  • trunk/Source/WebKit/UIProcess/Gamepad/UIGamepad.h

    r256215 r265079  
    2828#if ENABLE(GAMEPAD)
    2929
     30#include <WebCore/SharedGamepadValue.h>
    3031#include <wtf/MonotonicTime.h>
    3132#include <wtf/Vector.h>
     
    5657    String m_id;
    5758    String m_mapping;
    58     Vector<double> m_axisValues;
    59     Vector<double> m_buttonValues;
     59    Vector<WebCore::SharedGamepadValue> m_axisValues;
     60    Vector<WebCore::SharedGamepadValue> m_buttonValues;
    6061    MonotonicTime m_lastUpdateTime;
    6162};
  • trunk/Source/WebKit/WebProcess/Gamepad/WebGamepad.cpp

    r256215 r265079  
    3232#include "Logging.h"
    3333
     34using WebCore::SharedGamepadValue;
    3435
    3536namespace WebKit {
     
    4849}
    4950
    50 const Vector<double>& WebGamepad::axisValues() const
     51const Vector<SharedGamepadValue>& WebGamepad::axisValues() const
    5152{
    5253    return m_axisValues;
    5354}
    5455
    55 const Vector<double>& WebGamepad::buttonValues() const
     56const Vector<SharedGamepadValue>& WebGamepad::buttonValues() const
    5657{
    5758    return m_buttonValues;
     
    6566    ASSERT(m_buttonValues.size() == gamepadData.buttonValues().size());
    6667
    67     m_axisValues = gamepadData.axisValues();
    68     m_buttonValues = gamepadData.buttonValues();
    6968
     69    m_axisValues = WTF::map(gamepadData.axisValues(), [](auto value) { return SharedGamepadValue(value); });
     70    m_buttonValues = WTF::map(gamepadData.buttonValues(), [](auto value) { return SharedGamepadValue(value); });
    7071    m_lastUpdateTime = gamepadData.lastUpdateTime();
    7172}
  • trunk/Source/WebKit/WebProcess/Gamepad/WebGamepad.h

    r204853 r265079  
    4040    WebGamepad(const GamepadData&);
    4141
    42     const Vector<double>& axisValues() const override;
    43     const Vector<double>& buttonValues() const override;
     42    const Vector<WebCore::SharedGamepadValue>& axisValues() const override;
     43    const Vector<WebCore::SharedGamepadValue>& buttonValues() const override;
    4444
    4545    void updateValues(const GamepadData&);
    4646
    4747private:
    48     Vector<double> m_axisValues;
    49     Vector<double> m_buttonValues;
     48    Vector<WebCore::SharedGamepadValue> m_axisValues;
     49    Vector<WebCore::SharedGamepadValue> m_buttonValues;
    5050};
    5151
  • trunk/Tools/ChangeLog

    r265077 r265079  
     12020-07-30  Brady Eidson  <beidson@apple.com>
     2
     3        Refactor HID gamepad code to be much less fragile and much easier to hack on.
     4        https://bugs.webkit.org/show_bug.cgi?id=214910
     5
     6        Reviewed by Darin Adler.
     7
     8        Add a test that verifies connect, basic button/axis changes, and disconnect of a HID gamepad.
     9       
     10        * TestWebKitAPI/Tests/mac/HIDGamepads.mm:
     11
    1122020-07-29  Fujii Hironori  <Hironori.Fujii@sony.com>
    213
  • trunk/Tools/TestWebKitAPI/Tests/mac/HIDGamepads.mm

    r264874 r265079  
    3030#import "InstanceMethodSwizzler.h"
    3131#import "PlatformUtilities.h"
     32#import "Test.h"
    3233#import "TestURLSchemeHandler.h"
    3334#import "TestWKWebView.h"
     
    6061}
    6162
     63function handleGamepadDisconnect(evt)
     64{
     65    window.webkit.messageHandlers.gamepad.postMessage("Disconnect: " + JSON.stringify(evt.gamepad.id));
     66}
     67
    6268addEventListener("gamepadconnected", handleGamepadConnect);
     69addEventListener("gamepaddisconnected", handleGamepadDisconnect);
    6370
    6471</script>
     
    197204}
    198205
     206static const char* pollGamepadStateFunction = R"GAMEPADRESOURCE(
     207var result = new Object();
     208var gamepads = navigator.getGamepads();
     209result.gamepadCount = gamepads.length;
     210result.gamepadButtons = new Array;
     211result.gamepadAxes = new Array;
     212
     213for (var i = 0; i < gamepads.length; ++i) {
     214    result.gamepadButtons[i] = new Array;
     215    for (var j = 0; j < gamepads[i].buttons.length; ++j)
     216        result.gamepadButtons[i][j] = gamepads[i].buttons[j].value;
     217
     218    result.gamepadAxes[i] = new Array;
     219    for (var j = 0; j < gamepads[i].axes.length; ++j)
     220        result.gamepadAxes[i][j] = gamepads[i].axes[j];
     221}
     222
     223return result;
     224
     225)GAMEPADRESOURCE";
     226
     227TEST(Gamepad, GamepadState)
     228{
     229    auto keyWindowSwizzler = makeUnique<InstanceMethodSwizzler>([NSApplication class], @selector(keyWindow), reinterpret_cast<IMP>(getKeyWindowForTesting));
     230
     231    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     232    auto messageHandler = adoptNS([[GamepadMessageHandler alloc] init]);
     233    [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"gamepad"];
     234
     235    auto schemeHandler = adoptNS([[TestURLSchemeHandler alloc] init]);
     236    [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"gamepad"];
     237
     238    [schemeHandler setStartURLSchemeTaskHandler:^(WKWebView *, id<WKURLSchemeTask> task) {
     239        auto response = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil]);
     240        [task didReceiveResponse:response.get()];
     241        [task didReceiveData:[NSData dataWithBytes:mainBytes length:strlen(mainBytes)]];
     242        [task didFinish];
     243    }];
     244
     245    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
     246    keyWindowForTesting = [webView window];
     247    [webView synchronouslyLoadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"gamepad://host/main.html"]]];
     248
     249    [[webView window] makeFirstResponder:webView.get()];
     250
     251    // Resigning/reinstating the key window state triggers the "key window did change" notification that WKWebView currently
     252    // needs to convince it to monitor gamepad devices
     253    [[webView window] resignKeyWindow];
     254    [[webView window] makeKeyWindow];
     255
     256    // Connect a gamepad and make it visible to the page
     257    auto gamepad = makeUnique<VirtualGamepad>(VirtualGamepad::shenzhenLongshengweiTechnologyGamepadMapping());
     258    while (![webView.get().configuration.processPool _numberOfConnectedGamepadsForTesting])
     259        Util::sleep(0.01);
     260
     261    Vector<double> expectedButtons = { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
     262    Vector<double> expectedAxes = { -0.9921568627450981, -0.003921568627450966, -0.003921568627450966, -0.003921568627450966, -0.003921568627450966 };
     263
     264    auto updateStateAndPublish = [&] {
     265        for (size_t i = 0; i < expectedButtons.size(); ++i)
     266            gamepad->setButtonValue(i, expectedButtons[i]);
     267        for (size_t i = 0; i < 5; ++i)
     268            gamepad->setAxisValue(i, expectedAxes[i]);
     269        gamepad->publishReport();
     270    };
     271
     272    updateStateAndPublish();
     273
     274    // Wait for the page to tell us a gamepad connected
     275    Util::run(&didReceiveMessage);
     276    didReceiveMessage = false;
     277
     278    EXPECT_EQ(messageHandler.get().messages.size(), 1u);
     279    EXPECT_TRUE([messageHandler.get().messages[0] isEqualToString:@"\"79-11-Virtual Shenzhen Longshengwei Technology Gamepad\""]);
     280
     281    bool done = false;
     282    bool gotNewValues = false;
     283    auto resultBlock = [&] (id result, NSError *error) {
     284        EXPECT_NULL(error);
     285        EXPECT_TRUE([result[@"gamepadCount"] isEqualToNumber:@(1)]);
     286
     287        bool areEqual = true;
     288
     289        for (size_t i = 0; i < 10; ++i) {
     290            if (!WTF::areEssentiallyEqual([(NSNumber *)result[@"gamepadButtons"][0][i] doubleValue], expectedButtons[i]))
     291                areEqual = false;
     292        }
     293
     294        for (size_t i = 0; i < 5; ++i) {
     295            if (!WTF::areEssentiallyEqual([(NSNumber *)result[@"gamepadAxes"][0][i] doubleValue], expectedAxes[i]))
     296                areEqual = false;
     297        }
     298
     299        if (areEqual)
     300            gotNewValues = true;
     301
     302        done = true;
     303    };
     304
     305    // Change some buttons, polling state to confirm
     306    NSDate *start = [NSDate date];
     307    while (!gotNewValues) {
     308        [webView callAsyncJavaScript:@(pollGamepadStateFunction) arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:resultBlock];
     309        Util::run(&done);
     310        done = false;
     311
     312        if ([[NSDate date] timeIntervalSinceDate:start] > 1.0)
     313            break;
     314    }
     315    EXPECT_TRUE(gotNewValues);
     316    gotNewValues = false;
     317
     318    expectedButtons = { 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0 };
     319    updateStateAndPublish();
     320
     321    start = [NSDate date];
     322    while (!gotNewValues) {
     323        [webView callAsyncJavaScript:@(pollGamepadStateFunction) arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:resultBlock];
     324        Util::run(&done);
     325        done = false;
     326
     327        if ([[NSDate date] timeIntervalSinceDate:start] > 1.0)
     328            break;
     329    }
     330    EXPECT_TRUE(gotNewValues);
     331    gotNewValues = false;
     332
     333    expectedAxes = { -1.0, -1.0, -1.0, -1.0, 1.0 };
     334    updateStateAndPublish();
     335
     336    // Even though we set -1.0 for each "X" axis, the first 3 axes on this controller are always constant
     337    expectedAxes = { -0.9921568627450981, -0.003921568627450966, -0.003921568627450966, -1.0, 1.0 };
     338
     339    start = [NSDate date];
     340    while (!gotNewValues) {
     341        [webView callAsyncJavaScript:@(pollGamepadStateFunction) arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:resultBlock];
     342        Util::run(&done);
     343        done = false;
     344
     345        if ([[NSDate date] timeIntervalSinceDate:start] > 1.0)
     346            break;
     347    }
     348    EXPECT_TRUE(gotNewValues);
     349    gotNewValues = false;
     350
     351    // Disconnect the gamepad
     352    gamepad = nullptr;
     353
     354    Util::run(&didReceiveMessage);
     355    didReceiveMessage = false;
     356
     357    EXPECT_EQ(messageHandler.get().messages.size(), 2u);
     358    EXPECT_TRUE([messageHandler.get().messages[1] isEqualToString:@"Disconnect: \"79-11-Virtual Shenzhen Longshengwei Technology Gamepad\""]);
     359}
     360
    199361} // namespace TestWebKitAPI
    200362
Note: See TracChangeset for help on using the changeset viewer.