Unreviewed, rolling out r234489.
[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/Scrollbar.h>
30 #include <cmath>
31 #include <wpe/wpe.h>
32 #include <wtf/glib/GUniquePtr.h>
33
34 namespace WebKit {
35
36 static WebEvent::Modifiers modifiersForEvent(struct wpe_input_keyboard_event* event)
37 {
38     unsigned modifiers = 0;
39     unsigned eventModifiers = event->modifiers;
40
41     if (eventModifiers & wpe_input_keyboard_modifier_control)
42         modifiers |= WebEvent::ControlKey;
43     if (eventModifiers & wpe_input_keyboard_modifier_shift)
44         modifiers |= WebEvent::ShiftKey;
45     if (eventModifiers & wpe_input_keyboard_modifier_alt)
46         modifiers |= WebEvent::AltKey;
47     if (eventModifiers & wpe_input_keyboard_modifier_meta)
48         modifiers |= WebEvent::MetaKey;
49
50     return static_cast<WebEvent::Modifiers>(modifiers);
51 }
52
53 static String singleCharacterStringForKeyEvent(struct wpe_input_keyboard_event* event)
54 {
55     const char* singleCharacter = wpe_input_single_character_for_key_event(wpe_input_key_mapper_get_singleton(), event);
56     if (singleCharacter)
57         return String(singleCharacter);
58
59     glong length;
60     GUniquePtr<gunichar2> uchar16(g_ucs4_to_utf16(&event->unicode, 1, 0, &length, nullptr));
61     if (uchar16)
62         return String(reinterpret_cast<UChar*>(uchar16.get()), length);
63     return String();
64 }
65
66 static String identifierStringForKeyEvent(struct wpe_input_keyboard_event* event)
67 {
68     const char* identifier = wpe_input_identifier_for_key_event(wpe_input_key_mapper_get_singleton(), event);
69     if (identifier)
70         return String(identifier);
71
72     return String::format("U+%04X", event->unicode);
73 }
74
75 WallTime wallTimeForEventTime(uint64_t timestamp)
76 {
77     // This works if and only if the WPE backend uses CLOCK_MONOTONIC for its
78     // event timestamps, and so long as g_get_monotonic_time() continues to do
79     // so as well, and so long as WTF::MonotonicTime continues to use
80     // g_get_monotonic_time(). It also assumes the event timestamp is in
81     // milliseconds.
82     return timestamp ? MonotonicTime::fromRawSeconds(timestamp / 1000.).approximateWallTime() : WallTime::now();
83 }
84
85 WebKeyboardEvent WebEventFactory::createWebKeyboardEvent(struct wpe_input_keyboard_event* event)
86 {
87     String singleCharacterString = singleCharacterStringForKeyEvent(event);
88     String identifierString = identifierStringForKeyEvent(event);
89
90     return WebKeyboardEvent(event->pressed ? WebEvent::KeyDown : WebEvent::KeyUp,
91         singleCharacterString, singleCharacterString, identifierString,
92         wpe_input_windows_key_code_for_key_event(wpe_input_key_mapper_get_singleton(), event),
93         event->keyCode, 0, false, false, false,
94         modifiersForEvent(event), wallTimeForEventTime(event->time));
95 }
96
97 WebMouseEvent WebEventFactory::createWebMouseEvent(struct wpe_input_pointer_event* event, float deviceScaleFactor)
98 {
99     WebEvent::Type type = WebEvent::NoType;
100     switch (event->type) {
101     case wpe_input_pointer_event_type_motion:
102         type = WebEvent::MouseMove;
103         break;
104     case wpe_input_pointer_event_type_button:
105         type = event->state ? WebEvent::MouseDown : WebEvent::MouseUp;
106         break;
107     case wpe_input_pointer_event_type_null:
108         ASSERT_NOT_REACHED();
109     }
110
111     WebMouseEvent::Button button = WebMouseEvent::NoButton;
112     switch (event->type) {
113     case wpe_input_pointer_event_type_motion:
114     case wpe_input_pointer_event_type_button:
115         if (event->button == 1)
116             button = WebMouseEvent::LeftButton;
117         else if (event->button == 2)
118             button = WebMouseEvent::RightButton;
119         else if (event->button == 3)
120             button = WebMouseEvent::MiddleButton;
121         break;
122     case wpe_input_pointer_event_type_null:
123         ASSERT_NOT_REACHED();
124     }
125
126     unsigned clickCount = (type == WebEvent::MouseDown) ? 1 : 0;
127
128     // FIXME: Proper button support. Modifiers. deltaX/Y/Z. Click count.
129     WebCore::IntPoint position(event->x, event->y);
130     position.scale(1 / deviceScaleFactor);
131     return WebMouseEvent(type, button, 0, position, position,
132         0, 0, 0, clickCount, static_cast<WebEvent::Modifiers>(0), wallTimeForEventTime(event->time));
133 }
134
135 WebWheelEvent WebEventFactory::createWebWheelEvent(struct wpe_input_axis_event* event, float deviceScaleFactor)
136 {
137     // FIXME: We shouldn't hard-code this.
138     enum Axis {
139         Vertical,
140         Horizontal,
141         Smooth
142     };
143
144     WebCore::FloatSize wheelTicks;
145     WebCore::FloatSize delta;
146     switch (event->axis) {
147     case Vertical:
148         wheelTicks = WebCore::FloatSize(0, std::copysign(1, event->value));
149         delta = wheelTicks;
150         delta.scale(WebCore::Scrollbar::pixelsPerLineStep());
151         break;
152     case Horizontal:
153         wheelTicks = WebCore::FloatSize(std::copysign(1, event->value), 0);
154         delta = wheelTicks;
155         delta.scale(WebCore::Scrollbar::pixelsPerLineStep());
156         break;
157     case Smooth:
158         wheelTicks = WebCore::FloatSize(0, event->value / deviceScaleFactor);
159         delta = wheelTicks;
160         break;
161     default:
162         ASSERT_NOT_REACHED();
163     };
164
165     WebCore::IntPoint position(event->x, event->y);
166     position.scale(1 / deviceScaleFactor);
167     return WebWheelEvent(WebEvent::Wheel, position, position,
168         delta, wheelTicks, WebWheelEvent::ScrollByPixelWheelEvent, static_cast<WebEvent::Modifiers>(0), wallTimeForEventTime(event->time));
169 }
170
171 static WebKit::WebPlatformTouchPoint::TouchPointState stateForTouchPoint(int mainEventId, const struct wpe_input_touch_event_raw* point)
172 {
173     if (point->id != mainEventId)
174         return WebKit::WebPlatformTouchPoint::TouchStationary;
175
176     switch (point->type) {
177     case wpe_input_touch_event_type_down:
178         return WebKit::WebPlatformTouchPoint::TouchPressed;
179     case wpe_input_touch_event_type_motion:
180         return WebKit::WebPlatformTouchPoint::TouchMoved;
181     case wpe_input_touch_event_type_up:
182         return WebKit::WebPlatformTouchPoint::TouchReleased;
183     case wpe_input_touch_event_type_null:
184         ASSERT_NOT_REACHED();
185         break;
186     };
187
188     return WebKit::WebPlatformTouchPoint::TouchStationary;
189 }
190
191 WebTouchEvent WebEventFactory::createWebTouchEvent(struct wpe_input_touch_event* event, float deviceScaleFactor)
192 {
193     WebEvent::Type type = WebEvent::NoType;
194     switch (event->type) {
195     case wpe_input_touch_event_type_down:
196         type = WebEvent::TouchStart;
197         break;
198     case wpe_input_touch_event_type_motion:
199         type = WebEvent::TouchMove;
200         break;
201     case wpe_input_touch_event_type_up:
202         type = WebEvent::TouchEnd;
203         break;
204     case wpe_input_touch_event_type_null:
205         ASSERT_NOT_REACHED();
206     }
207
208     Vector<WebKit::WebPlatformTouchPoint> touchPoints;
209     touchPoints.reserveCapacity(event->touchpoints_length);
210
211     for (unsigned i = 0; i < event->touchpoints_length; ++i) {
212         auto& point = event->touchpoints[i];
213         if (point.type == wpe_input_touch_event_type_null)
214             continue;
215
216         WebCore::IntPoint pointCoordinates(point.x, point.y);
217         pointCoordinates.scale(1 / deviceScaleFactor);
218         touchPoints.uncheckedAppend(
219             WebKit::WebPlatformTouchPoint(point.id, stateForTouchPoint(event->id, &point),
220                 pointCoordinates, pointCoordinates));
221     }
222
223     return WebTouchEvent(type, WTFMove(touchPoints), WebEvent::Modifiers(0), wallTimeForEventTime(event->time));
224 }
225
226 } // namespace WebKit