Unreviewed, fix the internal iOS debug build after r238380
[WebKit-https.git] / Source / WebKit / Shared / wpe / WebEventFactory.cpp
1 /*
2  * Copyright (C) 2014 Igalia S.L.
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
26 #include "config.h"
27 #include "WebEventFactory.h"
28
29 #include <WebCore/PlatformKeyboardEvent.h>
30 #include <WebCore/Scrollbar.h>
31 #include <cmath>
32 #include <wpe/wpe.h>
33
34 namespace WebKit {
35
36 static inline bool isWPEKeyCodeFromKeyPad(unsigned keyCode)
37 {
38     return keyCode >= WPE_KEY_KP_Space && keyCode <= WPE_KEY_KP_9;
39 }
40
41 static WebEvent::Modifiers modifiersForEventModifiers(unsigned eventModifiers)
42 {
43     unsigned modifiers = 0;
44
45     if (eventModifiers & wpe_input_keyboard_modifier_control)
46         modifiers |= WebEvent::ControlKey;
47     if (eventModifiers & wpe_input_keyboard_modifier_shift)
48         modifiers |= WebEvent::ShiftKey;
49     if (eventModifiers & wpe_input_keyboard_modifier_alt)
50         modifiers |= WebEvent::AltKey;
51     if (eventModifiers & wpe_input_keyboard_modifier_meta)
52         modifiers |= WebEvent::MetaKey;
53
54     return static_cast<WebEvent::Modifiers>(modifiers);
55 }
56
57 WallTime wallTimeForEventTime(uint64_t timestamp)
58 {
59     // This works if and only if the WPE backend uses CLOCK_MONOTONIC for its
60     // event timestamps, and so long as g_get_monotonic_time() continues to do
61     // so as well, and so long as WTF::MonotonicTime continues to use
62     // g_get_monotonic_time(). It also assumes the event timestamp is in
63     // milliseconds.
64     return timestamp ? MonotonicTime::fromRawSeconds(timestamp / 1000.).approximateWallTime() : WallTime::now();
65 }
66
67 WebKeyboardEvent WebEventFactory::createWebKeyboardEvent(struct wpe_input_keyboard_event* event)
68 {
69     String singleCharacterString = WebCore::PlatformKeyboardEvent::singleCharacterString(event->key_code);
70
71     return WebKeyboardEvent(event->pressed ? WebEvent::KeyDown : WebEvent::KeyUp,
72         WebCore::PlatformKeyboardEvent::singleCharacterString(event->key_code),
73         WebCore::PlatformKeyboardEvent::keyValueForWPEKeyCode(event->key_code),
74         WebCore::PlatformKeyboardEvent::keyCodeForHardwareKeyCode(event->hardware_key_code),
75         WebCore::PlatformKeyboardEvent::keyIdentifierForWPEKeyCode(event->key_code),
76         WebCore::PlatformKeyboardEvent::windowsKeyCodeForWPEKeyCode(event->key_code),
77         event->key_code,
78         isWPEKeyCodeFromKeyPad(event->key_code),
79         modifiersForEventModifiers(event->modifiers),
80         wallTimeForEventTime(event->time));
81 }
82
83 static inline short pressedMouseButtons(uint32_t modifiers)
84 {
85     // MouseEvent.buttons
86     // https://www.w3.org/TR/uievents/#ref-for-dom-mouseevent-buttons-1
87
88     // 0 MUST indicate no button is currently active.
89     short buttons = 0;
90
91     // 1 MUST indicate the primary button of the device (in general, the left button or the only button on
92     // single-button devices, used to activate a user interface control or select text).
93     if (modifiers & wpe_input_pointer_modifier_button1)
94         buttons |= 1;
95
96     // 2 MUST indicate the secondary button (in general, the right button, often used to display a context menu),
97     // if present.
98     if (modifiers & wpe_input_pointer_modifier_button2)
99         buttons |= 2;
100
101     // 4 MUST indicate the auxiliary button (in general, the middle button, often combined with a mouse wheel).
102     if (modifiers & wpe_input_pointer_modifier_button3)
103         buttons |= 4;
104
105     return buttons;
106 }
107
108 WebMouseEvent WebEventFactory::createWebMouseEvent(struct wpe_input_pointer_event* event, float deviceScaleFactor)
109 {
110     WebEvent::Type type = WebEvent::NoType;
111     switch (event->type) {
112     case wpe_input_pointer_event_type_motion:
113         type = WebEvent::MouseMove;
114         break;
115     case wpe_input_pointer_event_type_button:
116         type = event->state ? WebEvent::MouseDown : WebEvent::MouseUp;
117         break;
118     case wpe_input_pointer_event_type_null:
119         ASSERT_NOT_REACHED();
120     }
121
122     WebMouseEvent::Button button = WebMouseEvent::NoButton;
123     switch (event->type) {
124     case wpe_input_pointer_event_type_motion:
125     case wpe_input_pointer_event_type_button:
126         if (event->button == 1)
127             button = WebMouseEvent::LeftButton;
128         else if (event->button == 2)
129             button = WebMouseEvent::RightButton;
130         else if (event->button == 3)
131             button = WebMouseEvent::MiddleButton;
132         break;
133     case wpe_input_pointer_event_type_null:
134         ASSERT_NOT_REACHED();
135     }
136
137     unsigned clickCount = (type == WebEvent::MouseDown) ? 1 : 0;
138
139     // FIXME: Proper button support. deltaX/Y/Z. Click count.
140     WebCore::IntPoint position(event->x, event->y);
141     position.scale(1 / deviceScaleFactor);
142     return WebMouseEvent(type, button, pressedMouseButtons(event->modifiers), position, position,
143         0, 0, 0, clickCount, modifiersForEventModifiers(event->modifiers), wallTimeForEventTime(event->time));
144 }
145
146 WebWheelEvent WebEventFactory::createWebWheelEvent(struct wpe_input_axis_event* event, float deviceScaleFactor)
147 {
148     // FIXME: We shouldn't hard-code this.
149     enum Axis {
150         Vertical,
151         Horizontal,
152         Smooth
153     };
154
155     WebCore::FloatSize wheelTicks;
156     WebCore::FloatSize delta;
157     switch (event->axis) {
158     case Vertical:
159         wheelTicks = WebCore::FloatSize(0, std::copysign(1, event->value));
160         delta = wheelTicks;
161         delta.scale(WebCore::Scrollbar::pixelsPerLineStep());
162         break;
163     case Horizontal:
164         wheelTicks = WebCore::FloatSize(std::copysign(1, event->value), 0);
165         delta = wheelTicks;
166         delta.scale(WebCore::Scrollbar::pixelsPerLineStep());
167         break;
168     case Smooth:
169         wheelTicks = WebCore::FloatSize(0, event->value / deviceScaleFactor);
170         delta = wheelTicks;
171         break;
172     default:
173         ASSERT_NOT_REACHED();
174     };
175
176     WebCore::IntPoint position(event->x, event->y);
177     position.scale(1 / deviceScaleFactor);
178     return WebWheelEvent(WebEvent::Wheel, position, position,
179         delta, wheelTicks, WebWheelEvent::ScrollByPixelWheelEvent, static_cast<WebEvent::Modifiers>(0), wallTimeForEventTime(event->time));
180 }
181
182 static WebKit::WebPlatformTouchPoint::TouchPointState stateForTouchPoint(int mainEventId, const struct wpe_input_touch_event_raw* point)
183 {
184     if (point->id != mainEventId)
185         return WebKit::WebPlatformTouchPoint::TouchStationary;
186
187     switch (point->type) {
188     case wpe_input_touch_event_type_down:
189         return WebKit::WebPlatformTouchPoint::TouchPressed;
190     case wpe_input_touch_event_type_motion:
191         return WebKit::WebPlatformTouchPoint::TouchMoved;
192     case wpe_input_touch_event_type_up:
193         return WebKit::WebPlatformTouchPoint::TouchReleased;
194     case wpe_input_touch_event_type_null:
195         ASSERT_NOT_REACHED();
196         break;
197     };
198
199     return WebKit::WebPlatformTouchPoint::TouchStationary;
200 }
201
202 WebTouchEvent WebEventFactory::createWebTouchEvent(struct wpe_input_touch_event* event, float deviceScaleFactor)
203 {
204     WebEvent::Type type = WebEvent::NoType;
205     switch (event->type) {
206     case wpe_input_touch_event_type_down:
207         type = WebEvent::TouchStart;
208         break;
209     case wpe_input_touch_event_type_motion:
210         type = WebEvent::TouchMove;
211         break;
212     case wpe_input_touch_event_type_up:
213         type = WebEvent::TouchEnd;
214         break;
215     case wpe_input_touch_event_type_null:
216         ASSERT_NOT_REACHED();
217     }
218
219     Vector<WebKit::WebPlatformTouchPoint> touchPoints;
220     touchPoints.reserveCapacity(event->touchpoints_length);
221
222     for (unsigned i = 0; i < event->touchpoints_length; ++i) {
223         auto& point = event->touchpoints[i];
224         if (point.type == wpe_input_touch_event_type_null)
225             continue;
226
227         WebCore::IntPoint pointCoordinates(point.x, point.y);
228         pointCoordinates.scale(1 / deviceScaleFactor);
229         touchPoints.uncheckedAppend(
230             WebKit::WebPlatformTouchPoint(point.id, stateForTouchPoint(event->id, &point),
231                 pointCoordinates, pointCoordinates));
232     }
233
234     return WebTouchEvent(type, WTFMove(touchPoints), WebEvent::Modifiers(0), wallTimeForEventTime(event->time));
235 }
236
237 } // namespace WebKit