Source/WebKit/chromium: Wire gesture tap events, add support for gesture events in...
[WebKit-https.git] / Source / WebKit / chromium / src / WebInputEventConversion.cpp
1 /*
2  * Copyright (C) 2009 Google 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 are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "WebInputEventConversion.h"
33
34 #include "EventNames.h"
35 #include "KeyboardCodes.h"
36 #include "KeyboardEvent.h"
37 #include "MouseEvent.h"
38 #include "PlatformKeyboardEvent.h"
39 #include "PlatformMouseEvent.h"
40 #include "PlatformWheelEvent.h"
41 #include "ScrollView.h"
42 #include "WebInputEvent.h"
43 #include "WheelEvent.h"
44 #include "Widget.h"
45
46 using namespace WebCore;
47
48 namespace WebKit {
49
50 // MakePlatformMouseEvent -----------------------------------------------------
51
52 PlatformMouseEventBuilder::PlatformMouseEventBuilder(Widget* widget, const WebMouseEvent& e)
53 {
54     // FIXME: widget is always toplevel, unless it's a popup.  We may be able
55     // to get rid of this once we abstract popups into a WebKit API.
56     m_position = widget->convertFromContainingWindow(IntPoint(e.x, e.y));
57     m_globalPosition = IntPoint(e.globalX, e.globalY);
58     m_button = static_cast<MouseButton>(e.button);
59     m_shiftKey = (e.modifiers & WebInputEvent::ShiftKey);
60     m_ctrlKey = (e.modifiers & WebInputEvent::ControlKey);
61     m_altKey = (e.modifiers & WebInputEvent::AltKey);
62     m_metaKey = (e.modifiers & WebInputEvent::MetaKey);
63     m_modifierFlags = e.modifiers;
64     m_timestamp = e.timeStampSeconds;
65     m_clickCount = e.clickCount;
66
67     switch (e.type) {
68     case WebInputEvent::MouseMove:
69     case WebInputEvent::MouseLeave:  // synthesize a move event
70         m_eventType = MouseEventMoved;
71         break;
72
73     case WebInputEvent::MouseDown:
74         m_eventType = MouseEventPressed;
75         break;
76
77     case WebInputEvent::MouseUp:
78         m_eventType = MouseEventReleased;
79         break;
80
81     default:
82         ASSERT_NOT_REACHED();
83     }
84 }
85
86 // PlatformWheelEventBuilder --------------------------------------------------
87
88 PlatformWheelEventBuilder::PlatformWheelEventBuilder(Widget* widget, const WebMouseWheelEvent& e)
89 {
90     m_position = widget->convertFromContainingWindow(IntPoint(e.x, e.y));
91     m_globalPosition = IntPoint(e.globalX, e.globalY);
92     m_deltaX = e.deltaX;
93     m_deltaY = e.deltaY;
94     m_wheelTicksX = e.wheelTicksX;
95     m_wheelTicksY = e.wheelTicksY;
96     m_isAccepted = false;
97     m_granularity = e.scrollByPage ?
98         ScrollByPageWheelEvent : ScrollByPixelWheelEvent;
99     m_shiftKey = (e.modifiers & WebInputEvent::ShiftKey);
100     m_ctrlKey = (e.modifiers & WebInputEvent::ControlKey);
101     m_altKey = (e.modifiers & WebInputEvent::AltKey);
102     m_metaKey = (e.modifiers & WebInputEvent::MetaKey);
103 #if OS(DARWIN)
104     m_hasPreciseScrollingDeltas = e.hasPreciseScrollingDeltas;
105     m_phase = static_cast<WebCore::PlatformWheelEventPhase>(e.phase);
106     m_momentumPhase = static_cast<WebCore::PlatformWheelEventPhase>(e.momentumPhase);
107     m_timestamp = e.timeStampSeconds;
108 #endif
109 }
110
111 // PlatformGestureEventBuilder --------------------------------------------------
112
113 #if ENABLE(GESTURE_EVENTS)
114 PlatformGestureEventBuilder::PlatformGestureEventBuilder(Widget* widget, const WebGestureEvent& e)
115 {
116     switch (e.type) {
117     case WebInputEvent::GestureScrollBegin:
118         m_type = PlatformGestureEvent::ScrollBeginType;
119         break;
120     case WebInputEvent::GestureScrollEnd:
121         m_type = PlatformGestureEvent::ScrollEndType;
122         break;
123     case WebInputEvent::GestureTap:
124         m_type = PlatformGestureEvent::TapType;
125         break;
126     default:
127         ASSERT_NOT_REACHED();
128     }
129     m_position = widget->convertFromContainingWindow(IntPoint(e.x, e.y));
130     m_globalPosition = IntPoint(e.globalX, e.globalY);
131     m_timestamp = e.timeStampSeconds;
132     m_shiftKey = (e.modifiers & WebInputEvent::ShiftKey);
133     m_ctrlKey = (e.modifiers & WebInputEvent::ControlKey);
134     m_altKey = (e.modifiers & WebInputEvent::AltKey);
135     m_metaKey = (e.modifiers & WebInputEvent::MetaKey);
136 }
137 #endif
138
139 // MakePlatformKeyboardEvent --------------------------------------------------
140
141 static inline PlatformKeyboardEvent::Type toPlatformKeyboardEventType(WebInputEvent::Type type)
142 {
143     switch (type) {
144     case WebInputEvent::KeyUp:
145         return PlatformKeyboardEvent::KeyUp;
146     case WebInputEvent::KeyDown:
147         return PlatformKeyboardEvent::KeyDown;
148     case WebInputEvent::RawKeyDown:
149         return PlatformKeyboardEvent::RawKeyDown;
150     case WebInputEvent::Char:
151         return PlatformKeyboardEvent::Char;
152     default:
153         ASSERT_NOT_REACHED();
154     }
155     return PlatformKeyboardEvent::KeyDown;
156 }
157
158 PlatformKeyboardEventBuilder::PlatformKeyboardEventBuilder(const WebKeyboardEvent& e)
159 {
160     m_type = toPlatformKeyboardEventType(e.type);
161     m_text = String(e.text);
162     m_unmodifiedText = String(e.unmodifiedText);
163     m_keyIdentifier = String(e.keyIdentifier);
164     m_autoRepeat = (e.modifiers & WebInputEvent::IsAutoRepeat);
165     m_windowsVirtualKeyCode = e.windowsKeyCode;
166     m_nativeVirtualKeyCode = e.nativeKeyCode;
167     m_isKeypad = (e.modifiers & WebInputEvent::IsKeyPad);
168     m_shiftKey = (e.modifiers & WebInputEvent::ShiftKey);
169     m_ctrlKey = (e.modifiers & WebInputEvent::ControlKey);
170     m_altKey = (e.modifiers & WebInputEvent::AltKey);
171     m_metaKey = (e.modifiers & WebInputEvent::MetaKey);
172     m_isSystemKey = e.isSystemKey;
173 }
174
175 void PlatformKeyboardEventBuilder::setKeyType(Type type)
176 {
177     // According to the behavior of Webkit in Windows platform,
178     // we need to convert KeyDown to RawKeydown and Char events
179     // See WebKit/WebKit/Win/WebView.cpp
180     ASSERT(m_type == KeyDown);
181     ASSERT(type == RawKeyDown || type == Char);
182     m_type = type;
183
184     if (type == RawKeyDown) {
185         m_text = String();
186         m_unmodifiedText = String();
187     } else {
188         m_keyIdentifier = String();
189         m_windowsVirtualKeyCode = 0;
190     }
191 }
192
193 // Please refer to bug http://b/issue?id=961192, which talks about Webkit
194 // keyboard event handling changes. It also mentions the list of keys
195 // which don't have associated character events.
196 bool PlatformKeyboardEventBuilder::isCharacterKey() const
197 {
198     switch (windowsVirtualKeyCode()) {
199     case VKEY_BACK:
200     case VKEY_ESCAPE:
201         return false;
202     }
203     return true;
204 }
205
206 #if ENABLE(TOUCH_EVENTS)
207 static inline TouchEventType toPlatformTouchEventType(const WebInputEvent::Type type)
208 {
209     switch (type) {
210     case WebInputEvent::TouchStart:
211         return TouchStart;
212     case WebInputEvent::TouchMove:
213         return TouchMove;
214     case WebInputEvent::TouchEnd:
215         return TouchEnd;
216     case WebInputEvent::TouchCancel:
217         return TouchCancel;
218     default:
219         ASSERT_NOT_REACHED();
220     }
221     return TouchStart;
222 }
223
224 static inline PlatformTouchPoint::State toPlatformTouchPointState(const WebTouchPoint::State state)
225 {
226     switch (state) {
227     case WebTouchPoint::StateReleased:
228         return PlatformTouchPoint::TouchReleased;
229     case WebTouchPoint::StatePressed:
230         return PlatformTouchPoint::TouchPressed;
231     case WebTouchPoint::StateMoved:
232         return PlatformTouchPoint::TouchMoved;
233     case WebTouchPoint::StateStationary:
234         return PlatformTouchPoint::TouchStationary;
235     case WebTouchPoint::StateCancelled:
236         return PlatformTouchPoint::TouchCancelled;
237     case WebTouchPoint::StateUndefined:
238         ASSERT_NOT_REACHED();
239     }
240     return PlatformTouchPoint::TouchReleased;
241 }
242
243 PlatformTouchPointBuilder::PlatformTouchPointBuilder(Widget* widget, const WebTouchPoint& point)
244 {
245     m_id = point.id;
246     m_state = toPlatformTouchPointState(point.state);
247     m_pos = widget->convertFromContainingWindow(point.position);
248     m_screenPos = point.screenPosition;
249     m_radiusY = point.radiusY;
250     m_radiusX = point.radiusX;
251     m_rotationAngle = point.rotationAngle;
252     m_force = point.force;
253 }
254
255 PlatformTouchEventBuilder::PlatformTouchEventBuilder(Widget* widget, const WebTouchEvent& event)
256 {
257     m_type = toPlatformTouchEventType(event.type);
258     m_ctrlKey = event.modifiers & WebInputEvent::ControlKey;
259     m_altKey = event.modifiers & WebInputEvent::AltKey;
260     m_shiftKey = event.modifiers & WebInputEvent::ShiftKey;
261     m_metaKey = event.modifiers & WebInputEvent::MetaKey;
262     m_timestamp = event.timeStampSeconds;
263
264     for (int i = 0; i < event.touchPointsLength; ++i)
265         m_touchPoints.append(PlatformTouchPointBuilder(widget, event.touchPoints[i]));
266 }
267 #endif
268
269 static int getWebInputModifiers(const UIEventWithKeyState& event)
270 {
271     int modifiers = 0;
272     if (event.ctrlKey())
273         modifiers |= WebInputEvent::ControlKey;
274     if (event.shiftKey())
275         modifiers |= WebInputEvent::ShiftKey;
276     if (event.altKey())
277         modifiers |= WebInputEvent::AltKey;
278     if (event.metaKey())
279         modifiers |= WebInputEvent::MetaKey;
280     return modifiers;
281 }
282
283 WebMouseEventBuilder::WebMouseEventBuilder(const Widget* widget, const MouseEvent& event)
284 {
285     if (event.type() == eventNames().mousemoveEvent)
286         type = WebInputEvent::MouseMove;
287     else if (event.type() == eventNames().mouseoutEvent)
288         type = WebInputEvent::MouseLeave;
289     else if (event.type() == eventNames().mouseoverEvent)
290         type = WebInputEvent::MouseEnter;
291     else if (event.type() == eventNames().mousedownEvent)
292         type = WebInputEvent::MouseDown;
293     else if (event.type() == eventNames().mouseupEvent)
294         type = WebInputEvent::MouseUp;
295     else if (event.type() == eventNames().contextmenuEvent)
296         type = WebInputEvent::ContextMenu;
297     else
298         return; // Skip all other mouse events.
299     timeStampSeconds = event.timeStamp() * 1.0e-3;
300     switch (event.button()) {
301     case LeftButton:
302         button = WebMouseEvent::ButtonLeft;
303         break;
304     case MiddleButton:
305         button = WebMouseEvent::ButtonMiddle;
306         break;
307     case RightButton:
308         button = WebMouseEvent::ButtonRight;
309         break;
310     }
311     modifiers = getWebInputModifiers(event);
312     if (event.buttonDown()) {
313         switch (event.button()) {
314         case LeftButton:
315             modifiers |= WebInputEvent::LeftButtonDown;
316             break;
317         case MiddleButton:
318             modifiers |= WebInputEvent::MiddleButtonDown;
319             break;
320         case RightButton:
321             modifiers |= WebInputEvent::RightButtonDown;
322             break;
323         }
324     }
325     ScrollView* view = widget->parent();
326     IntPoint p = view->contentsToWindow(
327         IntPoint(event.absoluteLocation().x(), event.absoluteLocation().y()));
328     globalX = event.screenX();
329     globalY = event.screenY();
330     windowX = p.x();
331     windowY = p.y();
332     x = event.absoluteLocation().x() - widget->location().x();
333     y = event.absoluteLocation().y() - widget->location().y();
334     clickCount = event.detail();
335 }
336
337 WebMouseWheelEventBuilder::WebMouseWheelEventBuilder(const Widget* widget, const WheelEvent& event)
338 {
339     if (event.type() != eventNames().mousewheelEvent)
340         return;
341     type = WebInputEvent::MouseWheel;
342     timeStampSeconds = event.timeStamp() * 1.0e-3;
343     modifiers = getWebInputModifiers(event);
344     ScrollView* view = widget->parent();
345     IntPoint p = view->contentsToWindow(
346         IntPoint(event.absoluteLocation().x(), event.absoluteLocation().y()));
347     globalX = event.screenX();
348     globalY = event.screenY();
349     windowX = p.x();
350     windowY = p.y();
351     x = event.absoluteLocation().x() - widget->location().x();
352     y = event.absoluteLocation().y() - widget->location().y();
353     deltaX = static_cast<float>(event.rawDeltaX());
354     deltaY = static_cast<float>(event.rawDeltaY());
355     // The 120 is from WheelEvent::initWheelEvent().
356     wheelTicksX = static_cast<float>(event.wheelDeltaX()) / 120;
357     wheelTicksY = static_cast<float>(event.wheelDeltaY()) / 120;
358     scrollByPage = event.granularity() == WheelEvent::Page;
359 }
360
361 WebKeyboardEventBuilder::WebKeyboardEventBuilder(const KeyboardEvent& event)
362 {
363     if (event.type() == eventNames().keydownEvent)
364         type = KeyDown;
365     else if (event.type() == eventNames().keyupEvent)
366         type = WebInputEvent::KeyUp;
367     else if (event.type() == eventNames().keypressEvent)
368         type = WebInputEvent::Char;
369     else
370         return; // Skip all other keyboard events.
371     modifiers = getWebInputModifiers(event);
372     timeStampSeconds = event.timeStamp() * 1.0e-3;
373     windowsKeyCode = event.keyCode();
374
375     // The platform keyevent does not exist if the event was created using
376     // initKeyboardEvent.
377     if (!event.keyEvent())
378         return;
379     nativeKeyCode = event.keyEvent()->nativeVirtualKeyCode();
380     unsigned int numChars = std::min(event.keyEvent()->text().length(),
381         static_cast<unsigned int>(WebKeyboardEvent::textLengthCap));
382     for (unsigned int i = 0; i < numChars; i++) {
383         text[i] = event.keyEvent()->text()[i];
384         unmodifiedText[i] = event.keyEvent()->unmodifiedText()[i];
385     }
386 }
387
388 } // namespace WebKit