NRWT lies about the number of tests that it's skipping when used with --repeat-each
[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 "GestureEvent.h"
36 #include "KeyboardCodes.h"
37 #include "KeyboardEvent.h"
38 #include "MouseEvent.h"
39 #include "PlatformKeyboardEvent.h"
40 #include "PlatformMouseEvent.h"
41 #include "PlatformWheelEvent.h"
42 #include "ScrollView.h"
43 #include "Touch.h"
44 #include "TouchEvent.h"
45 #include "TouchList.h"
46 #include "WebInputEvent.h"
47 #include "WheelEvent.h"
48 #include "Widget.h"
49
50 using namespace WebCore;
51
52 namespace WebKit {
53
54 static const double millisPerSecond = 1000.0;
55
56 // MakePlatformMouseEvent -----------------------------------------------------
57
58 PlatformMouseEventBuilder::PlatformMouseEventBuilder(Widget* widget, const WebMouseEvent& e)
59 {
60     // FIXME: widget is always toplevel, unless it's a popup.  We may be able
61     // to get rid of this once we abstract popups into a WebKit API.
62     m_position = widget->convertFromContainingWindow(IntPoint(e.x, e.y));
63     m_globalPosition = IntPoint(e.globalX, e.globalY);
64 #if ENABLE(POINTER_LOCK)
65     m_movementDelta = IntPoint(e.movementX, e.movementY);
66 #endif
67     m_button = static_cast<MouseButton>(e.button);
68
69     m_modifiers = 0;
70     if (e.modifiers & WebInputEvent::ShiftKey)
71         m_modifiers |= PlatformEvent::ShiftKey;
72     if (e.modifiers & WebInputEvent::ControlKey)
73         m_modifiers |= PlatformEvent::CtrlKey;
74     if (e.modifiers & WebInputEvent::AltKey)
75         m_modifiers |= PlatformEvent::AltKey;
76     if (e.modifiers & WebInputEvent::MetaKey)
77         m_modifiers |= PlatformEvent::MetaKey;
78
79     m_modifierFlags = e.modifiers;
80     m_timestamp = e.timeStampSeconds;
81     m_clickCount = e.clickCount;
82
83     switch (e.type) {
84     case WebInputEvent::MouseMove:
85     case WebInputEvent::MouseLeave:  // synthesize a move event
86         m_type = PlatformEvent::MouseMoved;
87         break;
88
89     case WebInputEvent::MouseDown:
90         m_type = PlatformEvent::MousePressed;
91         break;
92
93     case WebInputEvent::MouseUp:
94         m_type = PlatformEvent::MouseReleased;
95         break;
96
97     default:
98         ASSERT_NOT_REACHED();
99     }
100 }
101
102 // PlatformWheelEventBuilder --------------------------------------------------
103
104 PlatformWheelEventBuilder::PlatformWheelEventBuilder(Widget* widget, const WebMouseWheelEvent& e)
105 {
106     m_position = widget->convertFromContainingWindow(IntPoint(e.x, e.y));
107     m_globalPosition = IntPoint(e.globalX, e.globalY);
108     m_deltaX = e.deltaX;
109     m_deltaY = e.deltaY;
110     m_wheelTicksX = e.wheelTicksX;
111     m_wheelTicksY = e.wheelTicksY;
112     m_granularity = e.scrollByPage ?
113         ScrollByPageWheelEvent : ScrollByPixelWheelEvent;
114     
115     m_type = PlatformEvent::Wheel;
116
117     m_modifiers = 0;
118     if (e.modifiers & WebInputEvent::ShiftKey)
119         m_modifiers |= PlatformEvent::ShiftKey;
120     if (e.modifiers & WebInputEvent::ControlKey)
121         m_modifiers |= PlatformEvent::CtrlKey;
122     if (e.modifiers & WebInputEvent::AltKey)
123         m_modifiers |= PlatformEvent::AltKey;
124     if (e.modifiers & WebInputEvent::MetaKey)
125         m_modifiers |= PlatformEvent::MetaKey;
126
127     m_hasPreciseScrollingDeltas = e.hasPreciseScrollingDeltas;
128 #if OS(DARWIN)
129     m_phase = static_cast<WebCore::PlatformWheelEventPhase>(e.phase);
130     m_momentumPhase = static_cast<WebCore::PlatformWheelEventPhase>(e.momentumPhase);
131     m_timestamp = e.timeStampSeconds;
132     m_scrollCount = 0;
133     m_unacceleratedScrollingDeltaX = e.deltaX;
134     m_unacceleratedScrollingDeltaY = e.deltaY;
135 #endif
136 }
137
138 // PlatformGestureEventBuilder --------------------------------------------------
139
140 #if ENABLE(GESTURE_EVENTS)
141 PlatformGestureEventBuilder::PlatformGestureEventBuilder(Widget* widget, const WebGestureEvent& e)
142 {
143     switch (e.type) {
144     case WebInputEvent::GestureScrollBegin:
145         m_type = PlatformEvent::GestureScrollBegin;
146         break;
147     case WebInputEvent::GestureScrollEnd:
148         m_type = PlatformEvent::GestureScrollEnd;
149         break;
150     case WebInputEvent::GestureScrollUpdate:
151         m_type = PlatformEvent::GestureScrollUpdate;
152         break;
153     case WebInputEvent::GestureTap:
154         m_type = PlatformEvent::GestureTap;
155         m_area = IntSize(e.boundingBox.width, e.boundingBox.height);
156         break;
157     case WebInputEvent::GestureTapDown:
158         m_type = PlatformEvent::GestureTapDown;
159         break;
160     case WebInputEvent::GestureDoubleTap:
161         m_type = PlatformEvent::GestureDoubleTap;
162         break;
163     case WebInputEvent::GestureTwoFingerTap:
164         m_type = PlatformEvent::GestureTwoFingerTap;
165         break;
166     case WebInputEvent::GestureLongPress:
167         m_type = PlatformEvent::GestureLongPress;
168         m_area = IntSize(e.boundingBox.width, e.boundingBox.height);
169         break;
170     case WebInputEvent::GesturePinchBegin:
171         m_type = PlatformEvent::GesturePinchBegin;
172         break;
173     case WebInputEvent::GesturePinchEnd:
174         m_type = PlatformEvent::GesturePinchEnd;
175         break;
176     case WebInputEvent::GesturePinchUpdate:
177         m_type = PlatformEvent::GesturePinchUpdate;
178         break;
179     default:
180         ASSERT_NOT_REACHED();
181     }
182     m_position = widget->convertFromContainingWindow(IntPoint(e.x, e.y));
183     m_globalPosition = IntPoint(e.globalX, e.globalY);
184     m_deltaX = e.deltaX;
185     m_deltaY = e.deltaY;
186     m_timestamp = e.timeStampSeconds;
187
188     m_modifiers = 0;
189     if (e.modifiers & WebInputEvent::ShiftKey)
190         m_modifiers |= PlatformEvent::ShiftKey;
191     if (e.modifiers & WebInputEvent::ControlKey)
192         m_modifiers |= PlatformEvent::CtrlKey;
193     if (e.modifiers & WebInputEvent::AltKey)
194         m_modifiers |= PlatformEvent::AltKey;
195     if (e.modifiers & WebInputEvent::MetaKey)
196         m_modifiers |= PlatformEvent::MetaKey;
197 }
198 #endif
199
200 // MakePlatformKeyboardEvent --------------------------------------------------
201
202 static inline PlatformEvent::Type toPlatformKeyboardEventType(WebInputEvent::Type type)
203 {
204     switch (type) {
205     case WebInputEvent::KeyUp:
206         return PlatformEvent::KeyUp;
207     case WebInputEvent::KeyDown:
208         return PlatformEvent::KeyDown;
209     case WebInputEvent::RawKeyDown:
210         return PlatformEvent::RawKeyDown;
211     case WebInputEvent::Char:
212         return PlatformEvent::Char;
213     default:
214         ASSERT_NOT_REACHED();
215     }
216     return PlatformEvent::KeyDown;
217 }
218
219 PlatformKeyboardEventBuilder::PlatformKeyboardEventBuilder(const WebKeyboardEvent& e)
220 {
221     m_type = toPlatformKeyboardEventType(e.type);
222     m_text = String(e.text);
223     m_unmodifiedText = String(e.unmodifiedText);
224     m_keyIdentifier = String(e.keyIdentifier);
225     m_autoRepeat = (e.modifiers & WebInputEvent::IsAutoRepeat);
226     m_windowsVirtualKeyCode = e.windowsKeyCode;
227     m_nativeVirtualKeyCode = e.nativeKeyCode;
228     m_isKeypad = (e.modifiers & WebInputEvent::IsKeyPad);
229     m_isSystemKey = e.isSystemKey;
230
231     m_modifiers = 0;
232     if (e.modifiers & WebInputEvent::ShiftKey)
233         m_modifiers |= PlatformEvent::ShiftKey;
234     if (e.modifiers & WebInputEvent::ControlKey)
235         m_modifiers |= PlatformEvent::CtrlKey;
236     if (e.modifiers & WebInputEvent::AltKey)
237         m_modifiers |= PlatformEvent::AltKey;
238     if (e.modifiers & WebInputEvent::MetaKey)
239         m_modifiers |= PlatformEvent::MetaKey;
240 }
241
242 void PlatformKeyboardEventBuilder::setKeyType(Type type)
243 {
244     // According to the behavior of Webkit in Windows platform,
245     // we need to convert KeyDown to RawKeydown and Char events
246     // See WebKit/WebKit/Win/WebView.cpp
247     ASSERT(m_type == KeyDown);
248     ASSERT(type == RawKeyDown || type == Char);
249     m_type = type;
250
251     if (type == RawKeyDown) {
252         m_text = String();
253         m_unmodifiedText = String();
254     } else {
255         m_keyIdentifier = String();
256         m_windowsVirtualKeyCode = 0;
257     }
258 }
259
260 // Please refer to bug http://b/issue?id=961192, which talks about Webkit
261 // keyboard event handling changes. It also mentions the list of keys
262 // which don't have associated character events.
263 bool PlatformKeyboardEventBuilder::isCharacterKey() const
264 {
265     switch (windowsVirtualKeyCode()) {
266     case VKEY_BACK:
267     case VKEY_ESCAPE:
268         return false;
269     }
270     return true;
271 }
272
273 #if ENABLE(TOUCH_EVENTS)
274 static inline PlatformEvent::Type toPlatformTouchEventType(const WebInputEvent::Type type)
275 {
276     switch (type) {
277     case WebInputEvent::TouchStart:
278         return PlatformEvent::TouchStart;
279     case WebInputEvent::TouchMove:
280         return PlatformEvent::TouchMove;
281     case WebInputEvent::TouchEnd:
282         return PlatformEvent::TouchEnd;
283     case WebInputEvent::TouchCancel:
284         return PlatformEvent::TouchCancel;
285     default:
286         ASSERT_NOT_REACHED();
287     }
288     return PlatformEvent::TouchStart;
289 }
290
291 static inline PlatformTouchPoint::State toPlatformTouchPointState(const WebTouchPoint::State state)
292 {
293     switch (state) {
294     case WebTouchPoint::StateReleased:
295         return PlatformTouchPoint::TouchReleased;
296     case WebTouchPoint::StatePressed:
297         return PlatformTouchPoint::TouchPressed;
298     case WebTouchPoint::StateMoved:
299         return PlatformTouchPoint::TouchMoved;
300     case WebTouchPoint::StateStationary:
301         return PlatformTouchPoint::TouchStationary;
302     case WebTouchPoint::StateCancelled:
303         return PlatformTouchPoint::TouchCancelled;
304     case WebTouchPoint::StateUndefined:
305         ASSERT_NOT_REACHED();
306     }
307     return PlatformTouchPoint::TouchReleased;
308 }
309
310 PlatformTouchPointBuilder::PlatformTouchPointBuilder(Widget* widget, const WebTouchPoint& point)
311 {
312     m_id = point.id;
313     m_state = toPlatformTouchPointState(point.state);
314     m_pos = widget->convertFromContainingWindow(point.position);
315     m_screenPos = point.screenPosition;
316     m_radiusY = point.radiusY;
317     m_radiusX = point.radiusX;
318     m_rotationAngle = point.rotationAngle;
319     m_force = point.force;
320 }
321
322 PlatformTouchEventBuilder::PlatformTouchEventBuilder(Widget* widget, const WebTouchEvent& event)
323 {
324     m_type = toPlatformTouchEventType(event.type);
325
326     m_modifiers = 0;
327     if (event.modifiers & WebInputEvent::ShiftKey)
328         m_modifiers |= PlatformEvent::ShiftKey;
329     if (event.modifiers & WebInputEvent::ControlKey)
330         m_modifiers |= PlatformEvent::CtrlKey;
331     if (event.modifiers & WebInputEvent::AltKey)
332         m_modifiers |= PlatformEvent::AltKey;
333     if (event.modifiers & WebInputEvent::MetaKey)
334         m_modifiers |= PlatformEvent::MetaKey;
335
336     m_timestamp = event.timeStampSeconds;
337
338     for (unsigned i = 0; i < event.touchesLength; ++i)
339         m_touchPoints.append(PlatformTouchPointBuilder(widget, event.touches[i]));
340 }
341 #endif
342
343 static int getWebInputModifiers(const UIEventWithKeyState& event)
344 {
345     int modifiers = 0;
346     if (event.ctrlKey())
347         modifiers |= WebInputEvent::ControlKey;
348     if (event.shiftKey())
349         modifiers |= WebInputEvent::ShiftKey;
350     if (event.altKey())
351         modifiers |= WebInputEvent::AltKey;
352     if (event.metaKey())
353         modifiers |= WebInputEvent::MetaKey;
354     return modifiers;
355 }
356
357 WebMouseEventBuilder::WebMouseEventBuilder(const Widget* widget, const MouseEvent& event)
358 {
359     if (event.type() == eventNames().mousemoveEvent)
360         type = WebInputEvent::MouseMove;
361     else if (event.type() == eventNames().mouseoutEvent)
362         type = WebInputEvent::MouseLeave;
363     else if (event.type() == eventNames().mouseoverEvent)
364         type = WebInputEvent::MouseEnter;
365     else if (event.type() == eventNames().mousedownEvent)
366         type = WebInputEvent::MouseDown;
367     else if (event.type() == eventNames().mouseupEvent)
368         type = WebInputEvent::MouseUp;
369     else if (event.type() == eventNames().contextmenuEvent)
370         type = WebInputEvent::ContextMenu;
371     else
372         return; // Skip all other mouse events.
373     timeStampSeconds = event.timeStamp() / millisPerSecond;
374     switch (event.button()) {
375     case LeftButton:
376         button = WebMouseEvent::ButtonLeft;
377         break;
378     case MiddleButton:
379         button = WebMouseEvent::ButtonMiddle;
380         break;
381     case RightButton:
382         button = WebMouseEvent::ButtonRight;
383         break;
384     }
385     modifiers = getWebInputModifiers(event);
386     if (event.buttonDown()) {
387         switch (event.button()) {
388         case LeftButton:
389             modifiers |= WebInputEvent::LeftButtonDown;
390             break;
391         case MiddleButton:
392             modifiers |= WebInputEvent::MiddleButtonDown;
393             break;
394         case RightButton:
395             modifiers |= WebInputEvent::RightButtonDown;
396             break;
397         }
398     }
399     ScrollView* view = widget->parent();
400     IntPoint p = view->contentsToWindow(
401         IntPoint(event.absoluteLocation().x(), event.absoluteLocation().y()));
402     globalX = event.screenX();
403     globalY = event.screenY();
404     windowX = p.x();
405     windowY = p.y();
406     x = event.absoluteLocation().x() - widget->location().x();
407     y = event.absoluteLocation().y() - widget->location().y();
408 #if ENABLE(POINTER_LOCK)
409     movementX = event.webkitMovementX();
410     movementY = event.webkitMovementY();
411 #endif
412     clickCount = event.detail();
413 }
414
415 WebMouseWheelEventBuilder::WebMouseWheelEventBuilder(const Widget* widget, const WheelEvent& event)
416 {
417     if (event.type() != eventNames().mousewheelEvent)
418         return;
419     type = WebInputEvent::MouseWheel;
420     timeStampSeconds = event.timeStamp() / millisPerSecond;
421     modifiers = getWebInputModifiers(event);
422     ScrollView* view = widget->parent();
423     IntPoint p = view->contentsToWindow(
424         IntPoint(event.absoluteLocation().x(), event.absoluteLocation().y()));
425     globalX = event.screenX();
426     globalY = event.screenY();
427     windowX = p.x();
428     windowY = p.y();
429     x = event.absoluteLocation().x() - widget->location().x();
430     y = event.absoluteLocation().y() - widget->location().y();
431     deltaX = static_cast<float>(event.rawDeltaX());
432     deltaY = static_cast<float>(event.rawDeltaY());
433     // The 120 is from WheelEvent::initWheelEvent().
434     wheelTicksX = static_cast<float>(event.wheelDeltaX()) / 120;
435     wheelTicksY = static_cast<float>(event.wheelDeltaY()) / 120;
436     scrollByPage = event.granularity() == WheelEvent::Page;
437 }
438
439 WebKeyboardEventBuilder::WebKeyboardEventBuilder(const KeyboardEvent& event)
440 {
441     if (event.type() == eventNames().keydownEvent)
442         type = KeyDown;
443     else if (event.type() == eventNames().keyupEvent)
444         type = WebInputEvent::KeyUp;
445     else if (event.type() == eventNames().keypressEvent)
446         type = WebInputEvent::Char;
447     else
448         return; // Skip all other keyboard events.
449
450     modifiers = getWebInputModifiers(event);
451     if (event.keyLocation() & KeyboardEvent::DOM_KEY_LOCATION_NUMPAD)
452         modifiers |= WebInputEvent::IsKeyPad;
453
454     timeStampSeconds = event.timeStamp() / millisPerSecond;
455     windowsKeyCode = event.keyCode();
456
457     // The platform keyevent does not exist if the event was created using
458     // initKeyboardEvent.
459     if (!event.keyEvent())
460         return;
461     nativeKeyCode = event.keyEvent()->nativeVirtualKeyCode();
462     unsigned numberOfCharacters = std::min(event.keyEvent()->text().length(), static_cast<unsigned>(textLengthCap));
463     for (unsigned i = 0; i < numberOfCharacters; ++i) {
464         text[i] = event.keyEvent()->text()[i];
465         unmodifiedText[i] = event.keyEvent()->unmodifiedText()[i];
466     }
467     memcpy(keyIdentifier, event.keyIdentifier().ascii().data(), event.keyIdentifier().length());
468 }
469
470 #if ENABLE(TOUCH_EVENTS)
471
472 static void addTouchPoints(TouchList* touches, const IntPoint& offset, WebTouchPoint* touchPoints, unsigned* touchPointsLength)
473 {
474     unsigned numberOfTouches = std::min(touches->length(), static_cast<unsigned>(WebTouchEvent::touchesLengthCap));
475     for (unsigned i = 0; i < numberOfTouches; ++i) {
476         const Touch* touch = touches->item(i);
477
478         WebTouchPoint point;
479         point.id = touch->identifier();
480         point.screenPosition = WebPoint(touch->screenX(), touch->screenY());
481         point.position = WebPoint(touch->pageX() - offset.x(), touch->pageY() - offset.y());
482         point.radiusX = touch->webkitRadiusX();
483         point.radiusY = touch->webkitRadiusY();
484         point.rotationAngle = touch->webkitRotationAngle();
485         point.force = touch->webkitForce();
486
487         touchPoints[i] = point;
488     }
489     *touchPointsLength = numberOfTouches;
490 }
491
492 WebTouchEventBuilder::WebTouchEventBuilder(const Widget* widget, const TouchEvent& event)
493 {
494     if (event.type() == eventNames().touchstartEvent)
495         type = TouchStart;
496     else if (event.type() == eventNames().touchmoveEvent)
497         type = TouchMove;
498     else if (event.type() == eventNames().touchendEvent)
499         type = TouchEnd;
500     else if (event.type() == eventNames().touchcancelEvent)
501         type = TouchCancel;
502     else {
503         ASSERT_NOT_REACHED();
504         type = Undefined;
505         return;
506     }
507
508     modifiers = getWebInputModifiers(event);
509     timeStampSeconds = event.timeStamp() / millisPerSecond;
510
511     addTouchPoints(event.touches(), widget->location(), touches, &touchesLength);
512     addTouchPoints(event.changedTouches(), widget->location(), changedTouches, &changedTouchesLength);
513     addTouchPoints(event.targetTouches(), widget->location(), targetTouches, &targetTouchesLength);
514 }
515
516 #endif // ENABLE(TOUCH_EVENTS)
517
518 #if ENABLE(GESTURE_EVENTS)
519 WebGestureEventBuilder::WebGestureEventBuilder(const Widget* widget, const GestureEvent& event)
520 {
521     if (event.type() == eventNames().gesturetapEvent)
522         type = GestureTap;
523     else if (event.type() == eventNames().gesturetapdownEvent)
524         type = GestureTapDown;
525     else if (event.type() == eventNames().gesturescrollstartEvent)
526         type = GestureScrollBegin;
527     else if (event.type() == eventNames().gesturescrollendEvent)
528         type = GestureScrollEnd;
529     else if (event.type() == eventNames().gesturescrollupdateEvent)
530         type = GestureScrollUpdate;
531
532     timeStampSeconds = event.timeStamp() / millisPerSecond;
533     modifiers = getWebInputModifiers(event);
534
535     globalX = event.screenX();
536     globalY = event.screenY();
537     x = event.absoluteLocation().x() - widget->location().x();
538     y = event.absoluteLocation().y() - widget->location().y();
539
540     deltaX = event.deltaX();
541     deltaY = event.deltaY();
542 }
543 #endif // ENABLE(GESTURE_EVENTS)
544
545 } // namespace WebKit