[GTK] Implement connected and disconnected events of GAMEPAD API with libmanette
[WebKit-https.git] / Source / WebCore / platform / gamepad / cocoa / GameControllerGamepad.mm
1 /*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 #import "config.h"
26 #import "GameControllerGamepad.h"
27
28 #if ENABLE(GAMEPAD)
29 #import "GameControllerGamepadProvider.h"
30 #import <GameController/GameController.h>
31
32 namespace WebCore {
33
34 GameControllerGamepad::GameControllerGamepad(GCController *controller, unsigned index)
35     : PlatformGamepad(index)
36     , m_gcController(controller)
37 {
38     ASSERT(index < 4);
39     controller.playerIndex = (GCControllerPlayerIndex)(GCControllerPlayerIndex1 + index);
40
41     m_extendedGamepad = controller.extendedGamepad;
42
43     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
44     if (!m_extendedGamepad)
45         m_gamepad = controller.gamepad;
46     ALLOW_DEPRECATED_DECLARATIONS_END
47
48     ASSERT(m_extendedGamepad || m_gamepad);
49
50     if (m_extendedGamepad)
51         setupAsExtendedGamepad();
52     else
53         setupAsGamepad();
54 }
55
56 void GameControllerGamepad::setupAsExtendedGamepad()
57 {
58     ASSERT(m_extendedGamepad);
59
60     m_id = makeString(String(m_gcController.get().vendorName), " Extended Gamepad"_s);
61     m_mapping = String("standard");
62
63     m_extendedGamepad.get().valueChangedHandler = ^(GCExtendedGamepad *, GCControllerElement *) {
64         m_lastUpdateTime = MonotonicTime::now();
65         GameControllerGamepadProvider::singleton().gamepadHadInput(*this, m_hadButtonPresses);
66         m_hadButtonPresses = false;
67     };
68
69     m_buttonValues.resize(16);
70
71     auto bindButton = ^(GCControllerButtonInput *button, size_t idx) {
72         m_buttonValues[idx] = button.value;
73         button.valueChangedHandler = ^(GCControllerButtonInput *, float value, BOOL pressed) {
74             m_buttonValues[idx] = value;
75             if (pressed)
76                 m_hadButtonPresses = true;
77         };
78     };
79
80     // Button Pad
81     bindButton(m_extendedGamepad.get().buttonA, 0);
82     bindButton(m_extendedGamepad.get().buttonB, 1);
83     bindButton(m_extendedGamepad.get().buttonX, 2);
84     bindButton(m_extendedGamepad.get().buttonY, 3);
85
86     // Shoulders, Triggers
87     bindButton(m_extendedGamepad.get().leftShoulder, 4);
88     bindButton(m_extendedGamepad.get().rightShoulder, 5);
89     bindButton(m_extendedGamepad.get().leftTrigger, 6);
90     bindButton(m_extendedGamepad.get().rightTrigger, 7);
91
92     // D Pad
93     bindButton(m_extendedGamepad.get().dpad.up, 12);
94     bindButton(m_extendedGamepad.get().dpad.down, 13);
95     bindButton(m_extendedGamepad.get().dpad.left, 14);
96     bindButton(m_extendedGamepad.get().dpad.right, 15);
97
98     // Select, Start
99 #if HAVE(GCEXTENDEDGAMEPAD_BUTTONS_OPTIONS_MENU)
100     bindButton(m_extendedGamepad.get().buttonOptions, 8);
101     bindButton(m_extendedGamepad.get().buttonMenu, 9);
102 #endif
103
104     // L3, R3
105 #if HAVE(GCEXTENDEDGAMEPAD_BUTTONS_THUMBSTICK)
106     // Thumbstick buttons are only in macOS 10.14.1 / iOS 12.1
107 #pragma clang diagnostic push
108 #pragma clang diagnostic ignored "-Wunguarded-availability"
109     if ([m_extendedGamepad.get() respondsToSelector:@selector(leftThumbstickButton)]) {
110         bindButton(m_extendedGamepad.get().leftThumbstickButton, 10);
111         bindButton(m_extendedGamepad.get().rightThumbstickButton, 11);
112     }
113 #pragma clang diagnostic pop
114 #endif
115
116     m_axisValues.resize(4);
117     m_axisValues[0] = m_extendedGamepad.get().leftThumbstick.xAxis.value;
118     m_axisValues[1] = -m_extendedGamepad.get().leftThumbstick.yAxis.value;
119     m_axisValues[2] = m_extendedGamepad.get().rightThumbstick.xAxis.value;
120     m_axisValues[3] = -m_extendedGamepad.get().rightThumbstick.yAxis.value;
121
122     m_extendedGamepad.get().leftThumbstick.xAxis.valueChangedHandler = ^(GCControllerAxisInput *, float value) {
123         m_axisValues[0] = value;
124     };
125     m_extendedGamepad.get().leftThumbstick.yAxis.valueChangedHandler = ^(GCControllerAxisInput *, float value) {
126         m_axisValues[1] = -value;
127     };
128     m_extendedGamepad.get().rightThumbstick.xAxis.valueChangedHandler = ^(GCControllerAxisInput *, float value) {
129         m_axisValues[2] = value;
130     };
131     m_extendedGamepad.get().rightThumbstick.yAxis.valueChangedHandler = ^(GCControllerAxisInput *, float value) {
132         m_axisValues[3] = -value;
133     };
134 }
135
136 void GameControllerGamepad::setupAsGamepad()
137 {
138     ASSERT(m_gamepad);
139
140     m_id = makeString(String(m_gcController.get().vendorName), " Gamepad"_s);
141
142     ALLOW_DEPRECATED_DECLARATIONS_BEGIN // GCGamepad
143     m_gamepad.get().valueChangedHandler = ^(GCGamepad *, GCControllerElement *) {
144         m_lastUpdateTime = MonotonicTime::now();
145         GameControllerGamepadProvider::singleton().gamepadHadInput(*this, m_hadButtonPresses);
146         m_hadButtonPresses = false;
147     };
148     ALLOW_DEPRECATED_DECLARATIONS_END
149
150     m_buttonValues.resize(6);
151     m_buttonValues[0] = m_extendedGamepad.get().buttonA.value;
152     m_buttonValues[1] = m_extendedGamepad.get().buttonB.value;
153     m_buttonValues[2] = m_extendedGamepad.get().buttonX.value;
154     m_buttonValues[3] = m_extendedGamepad.get().buttonY.value;
155     m_buttonValues[4] = m_extendedGamepad.get().leftShoulder.value;
156     m_buttonValues[5] = m_extendedGamepad.get().rightShoulder.value;
157
158     m_axisValues.resize(2);
159     m_axisValues[0] = m_extendedGamepad.get().dpad.xAxis.value;
160     m_axisValues[1] = m_extendedGamepad.get().dpad.yAxis.value;
161
162     m_extendedGamepad.get().buttonA.valueChangedHandler = ^(GCControllerButtonInput *, float value, BOOL pressed) {
163         m_buttonValues[0] = value;
164         if (pressed)
165             m_hadButtonPresses = true;
166     };
167     m_extendedGamepad.get().buttonB.valueChangedHandler = ^(GCControllerButtonInput *, float value, BOOL pressed) {
168         m_buttonValues[1] = value;
169         if (pressed)
170             m_hadButtonPresses = true;
171     };
172     m_extendedGamepad.get().buttonX.valueChangedHandler = ^(GCControllerButtonInput *, float value, BOOL pressed) {
173         m_buttonValues[2] = value;
174         if (pressed)
175             m_hadButtonPresses = true;
176     };
177     m_extendedGamepad.get().buttonY.valueChangedHandler = ^(GCControllerButtonInput *, float value, BOOL pressed) {
178         m_buttonValues[3] = value;
179         if (pressed)
180             m_hadButtonPresses = true;
181     };
182     m_extendedGamepad.get().leftShoulder.valueChangedHandler = ^(GCControllerButtonInput *, float value, BOOL pressed) {
183         m_buttonValues[4] = value;
184         if (pressed)
185             m_hadButtonPresses = true;
186     };
187     m_extendedGamepad.get().rightShoulder.valueChangedHandler = ^(GCControllerButtonInput *, float value, BOOL pressed) {
188         m_buttonValues[5] = value;
189         if (pressed)
190             m_hadButtonPresses = true;
191     };
192
193     m_extendedGamepad.get().leftThumbstick.xAxis.valueChangedHandler = ^(GCControllerAxisInput *, float value) {
194         m_axisValues[0] = value;
195     };
196     m_extendedGamepad.get().leftThumbstick.yAxis.valueChangedHandler = ^(GCControllerAxisInput *, float value) {
197         m_axisValues[1] = value;
198     };
199 }
200
201 } // namespace WebCore
202
203 #endif // ENABLE(GAMEPAD)