- add third_party src.
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / web / 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 "WebInputEvent.h"
35 #include "core/dom/Touch.h"
36 #include "core/dom/TouchList.h"
37 #include "core/events/GestureEvent.h"
38 #include "core/events/KeyboardEvent.h"
39 #include "core/events/MouseEvent.h"
40 #include "core/events/ThreadLocalEventNames.h"
41 #include "core/events/TouchEvent.h"
42 #include "core/events/WheelEvent.h"
43 #include "core/platform/ScrollView.h"
44 #include "core/platform/chromium/KeyboardCodes.h"
45 #include "core/rendering/RenderObject.h"
46 #include "platform/PlatformKeyboardEvent.h"
47 #include "platform/PlatformMouseEvent.h"
48 #include "platform/PlatformWheelEvent.h"
49 #include "platform/Widget.h"
50
51 using namespace WebCore;
52
53 namespace WebKit {
54
55 static const double millisPerSecond = 1000.0;
56
57 static float widgetInputEventsScaleFactor(const Widget* widget)
58 {
59     if (!widget)
60         return 1;
61
62     ScrollView* rootView =  toScrollView(widget->root());
63     if (!rootView)
64         return 1;
65
66     return rootView->inputEventsScaleFactor();
67 }
68
69 static IntSize widgetInputEventsOffset(const Widget* widget)
70 {
71     if (!widget)
72         return IntSize();
73     ScrollView* rootView =  toScrollView(widget->root());
74     if (!rootView)
75         return IntSize();
76
77     return rootView->inputEventsOffsetForEmulation();
78 }
79
80 // MakePlatformMouseEvent -----------------------------------------------------
81
82 PlatformMouseEventBuilder::PlatformMouseEventBuilder(Widget* widget, const WebMouseEvent& e)
83 {
84     float scale = widgetInputEventsScaleFactor(widget);
85     IntSize offset = widgetInputEventsOffset(widget);
86
87     // FIXME: Widget is always toplevel, unless it's a popup. We may be able
88     // to get rid of this once we abstract popups into a WebKit API.
89     m_position = widget->convertFromContainingWindow(IntPoint((e.x - offset.width()) / scale, (e.y - offset.height()) / scale));
90     m_globalPosition = IntPoint(e.globalX, e.globalY);
91     m_movementDelta = IntPoint(e.movementX / scale, e.movementY / scale);
92     m_button = static_cast<MouseButton>(e.button);
93
94     m_modifiers = 0;
95     if (e.modifiers & WebInputEvent::ShiftKey)
96         m_modifiers |= PlatformEvent::ShiftKey;
97     if (e.modifiers & WebInputEvent::ControlKey)
98         m_modifiers |= PlatformEvent::CtrlKey;
99     if (e.modifiers & WebInputEvent::AltKey)
100         m_modifiers |= PlatformEvent::AltKey;
101     if (e.modifiers & WebInputEvent::MetaKey)
102         m_modifiers |= PlatformEvent::MetaKey;
103
104     m_modifierFlags = e.modifiers;
105     m_timestamp = e.timeStampSeconds;
106     m_clickCount = e.clickCount;
107
108     switch (e.type) {
109     case WebInputEvent::MouseMove:
110     case WebInputEvent::MouseLeave:  // synthesize a move event
111         m_type = PlatformEvent::MouseMoved;
112         break;
113
114     case WebInputEvent::MouseDown:
115         m_type = PlatformEvent::MousePressed;
116         break;
117
118     case WebInputEvent::MouseUp:
119         m_type = PlatformEvent::MouseReleased;
120         break;
121
122     default:
123         ASSERT_NOT_REACHED();
124     }
125 }
126
127 // PlatformWheelEventBuilder --------------------------------------------------
128
129 PlatformWheelEventBuilder::PlatformWheelEventBuilder(Widget* widget, const WebMouseWheelEvent& e)
130 {
131     float scale = widgetInputEventsScaleFactor(widget);
132     IntSize offset = widgetInputEventsOffset(widget);
133
134     m_position = widget->convertFromContainingWindow(IntPoint((e.x - offset.width()) / scale, (e.y - offset.height()) / scale));
135     m_globalPosition = IntPoint(e.globalX, e.globalY);
136     m_deltaX = e.deltaX;
137     m_deltaY = e.deltaY;
138     m_wheelTicksX = e.wheelTicksX;
139     m_wheelTicksY = e.wheelTicksY;
140     m_granularity = e.scrollByPage ?
141         ScrollByPageWheelEvent : ScrollByPixelWheelEvent;
142
143     m_type = PlatformEvent::Wheel;
144
145     m_modifiers = 0;
146     if (e.modifiers & WebInputEvent::ShiftKey)
147         m_modifiers |= PlatformEvent::ShiftKey;
148     if (e.modifiers & WebInputEvent::ControlKey)
149         m_modifiers |= PlatformEvent::CtrlKey;
150     if (e.modifiers & WebInputEvent::AltKey)
151         m_modifiers |= PlatformEvent::AltKey;
152     if (e.modifiers & WebInputEvent::MetaKey)
153         m_modifiers |= PlatformEvent::MetaKey;
154
155     m_hasPreciseScrollingDeltas = e.hasPreciseScrollingDeltas;
156 #if OS(MACOSX)
157     m_phase = static_cast<WebCore::PlatformWheelEventPhase>(e.phase);
158     m_momentumPhase = static_cast<WebCore::PlatformWheelEventPhase>(e.momentumPhase);
159     m_timestamp = e.timeStampSeconds;
160     m_scrollCount = 0;
161     m_unacceleratedScrollingDeltaX = e.deltaX;
162     m_unacceleratedScrollingDeltaY = e.deltaY;
163 #endif
164 }
165
166 // PlatformGestureEventBuilder --------------------------------------------------
167
168 PlatformGestureEventBuilder::PlatformGestureEventBuilder(Widget* widget, const WebGestureEvent& e)
169 {
170     float scale = widgetInputEventsScaleFactor(widget);
171     IntSize offset = widgetInputEventsOffset(widget);
172
173     switch (e.type) {
174     case WebInputEvent::GestureScrollBegin:
175         m_type = PlatformEvent::GestureScrollBegin;
176         break;
177     case WebInputEvent::GestureScrollEnd:
178         m_type = PlatformEvent::GestureScrollEnd;
179         break;
180     case WebInputEvent::GestureScrollUpdate:
181         m_type = PlatformEvent::GestureScrollUpdate;
182         m_data.m_scrollUpdate.m_deltaX = e.data.scrollUpdate.deltaX / scale;
183         m_data.m_scrollUpdate.m_deltaY = e.data.scrollUpdate.deltaY / scale;
184         m_data.m_scrollUpdate.m_velocityX = e.data.scrollUpdate.velocityX;
185         m_data.m_scrollUpdate.m_velocityY = e.data.scrollUpdate.velocityY;
186         break;
187     case WebInputEvent::GestureScrollUpdateWithoutPropagation:
188         m_type = PlatformEvent::GestureScrollUpdateWithoutPropagation;
189         m_data.m_scrollUpdate.m_deltaX = e.data.scrollUpdate.deltaX / scale;
190         m_data.m_scrollUpdate.m_deltaY = e.data.scrollUpdate.deltaY / scale;
191         m_data.m_scrollUpdate.m_velocityX = e.data.scrollUpdate.velocityX;
192         m_data.m_scrollUpdate.m_velocityY = e.data.scrollUpdate.velocityY;
193         break;
194     case WebInputEvent::GestureTap:
195         m_type = PlatformEvent::GestureTap;
196         m_area = expandedIntSize(FloatSize(e.data.tap.width / scale, e.data.tap.height / scale));
197         m_data.m_tap.m_tapCount = e.data.tap.tapCount;
198         break;
199     case WebInputEvent::GestureTapUnconfirmed:
200         m_type = PlatformEvent::GestureTapUnconfirmed;
201         m_area = expandedIntSize(FloatSize(e.data.tap.width / scale, e.data.tap.height / scale));
202         break;
203     case WebInputEvent::GestureTapDown:
204         m_type = PlatformEvent::GestureTapDown;
205         m_area = expandedIntSize(FloatSize(e.data.tapDown.width / scale, e.data.tapDown.height / scale));
206         break;
207     case WebInputEvent::GestureShowPress:
208         m_type = PlatformEvent::GestureShowPress;
209         m_area = expandedIntSize(FloatSize(e.data.showPress.width / scale, e.data.showPress.height / scale));
210         break;
211     case WebInputEvent::GestureTapCancel:
212         m_type = PlatformEvent::GestureTapDownCancel;
213         break;
214     case WebInputEvent::GestureDoubleTap:
215         // DoubleTap gesture is now handled as PlatformEvent::GestureTap with tap_count = 2. So no
216         // need to convert to a Platfrom DoubleTap gesture. But in WebViewImpl::handleGestureEvent
217         // all WebGestureEvent are converted to PlatformGestureEvent, for completeness and not reach
218         // the ASSERT_NOT_REACHED() at the end, convert the DoubleTap to a NoType.
219         m_type = PlatformEvent::NoType;
220         break;
221     case WebInputEvent::GestureTwoFingerTap:
222         m_type = PlatformEvent::GestureTwoFingerTap;
223         m_area = expandedIntSize(FloatSize(e.data.twoFingerTap.firstFingerWidth / scale, e.data.twoFingerTap.firstFingerHeight / scale));
224         break;
225     case WebInputEvent::GestureLongPress:
226         m_type = PlatformEvent::GestureLongPress;
227         m_area = expandedIntSize(FloatSize(e.data.longPress.width / scale, e.data.longPress.height / scale));
228         break;
229     case WebInputEvent::GestureLongTap:
230         m_type = PlatformEvent::GestureLongTap;
231         m_area = expandedIntSize(FloatSize(e.data.longPress.width / scale, e.data.longPress.height / scale));
232         break;
233     case WebInputEvent::GesturePinchBegin:
234         m_type = PlatformEvent::GesturePinchBegin;
235         break;
236     case WebInputEvent::GesturePinchEnd:
237         m_type = PlatformEvent::GesturePinchEnd;
238         break;
239     case WebInputEvent::GesturePinchUpdate:
240         m_type = PlatformEvent::GesturePinchUpdate;
241         m_data.m_pinchUpdate.m_scale = e.data.pinchUpdate.scale;
242         break;
243     default:
244         ASSERT_NOT_REACHED();
245     }
246     m_position = widget->convertFromContainingWindow(IntPoint((e.x - offset.width()) / scale, (e.y - offset.height()) / scale));
247     m_globalPosition = IntPoint(e.globalX, e.globalY);
248     m_timestamp = e.timeStampSeconds;
249
250     m_modifiers = 0;
251     if (e.modifiers & WebInputEvent::ShiftKey)
252         m_modifiers |= PlatformEvent::ShiftKey;
253     if (e.modifiers & WebInputEvent::ControlKey)
254         m_modifiers |= PlatformEvent::CtrlKey;
255     if (e.modifiers & WebInputEvent::AltKey)
256         m_modifiers |= PlatformEvent::AltKey;
257     if (e.modifiers & WebInputEvent::MetaKey)
258         m_modifiers |= PlatformEvent::MetaKey;
259 }
260
261 // MakePlatformKeyboardEvent --------------------------------------------------
262
263 inline PlatformEvent::Type toPlatformKeyboardEventType(WebInputEvent::Type type)
264 {
265     switch (type) {
266     case WebInputEvent::KeyUp:
267         return PlatformEvent::KeyUp;
268     case WebInputEvent::KeyDown:
269         return PlatformEvent::KeyDown;
270     case WebInputEvent::RawKeyDown:
271         return PlatformEvent::RawKeyDown;
272     case WebInputEvent::Char:
273         return PlatformEvent::Char;
274     default:
275         ASSERT_NOT_REACHED();
276     }
277     return PlatformEvent::KeyDown;
278 }
279
280 PlatformKeyboardEventBuilder::PlatformKeyboardEventBuilder(const WebKeyboardEvent& e)
281 {
282     m_type = toPlatformKeyboardEventType(e.type);
283     m_text = String(e.text);
284     m_unmodifiedText = String(e.unmodifiedText);
285     m_keyIdentifier = String(e.keyIdentifier);
286     m_autoRepeat = (e.modifiers & WebInputEvent::IsAutoRepeat);
287     m_nativeVirtualKeyCode = e.nativeKeyCode;
288     m_isKeypad = (e.modifiers & WebInputEvent::IsKeyPad);
289     m_isSystemKey = e.isSystemKey;
290
291     m_modifiers = 0;
292     if (e.modifiers & WebInputEvent::ShiftKey)
293         m_modifiers |= PlatformEvent::ShiftKey;
294     if (e.modifiers & WebInputEvent::ControlKey)
295         m_modifiers |= PlatformEvent::CtrlKey;
296     if (e.modifiers & WebInputEvent::AltKey)
297         m_modifiers |= PlatformEvent::AltKey;
298     if (e.modifiers & WebInputEvent::MetaKey)
299         m_modifiers |= PlatformEvent::MetaKey;
300
301     // FIXME: PlatformKeyboardEvents expect a locational version of the keycode (e.g. VK_LSHIFT
302     // instead of VK_SHIFT). This should be changed so the location/keycode are stored separately,
303     // as in other places in the code.
304     m_windowsVirtualKeyCode = e.windowsKeyCode;
305     if (e.windowsKeyCode == VK_SHIFT) {
306         if (e.modifiers & WebInputEvent::IsLeft)
307             m_windowsVirtualKeyCode = VK_LSHIFT;
308         else if (e.modifiers & WebInputEvent::IsRight)
309             m_windowsVirtualKeyCode = VK_RSHIFT;
310     } else if (e.windowsKeyCode == VK_CONTROL) {
311         if (e.modifiers & WebInputEvent::IsLeft)
312             m_windowsVirtualKeyCode = VK_LCONTROL;
313         else if (e.modifiers & WebInputEvent::IsRight)
314             m_windowsVirtualKeyCode = VK_RCONTROL;
315     } else if (e.windowsKeyCode == VK_MENU) {
316         if (e.modifiers & WebInputEvent::IsLeft)
317             m_windowsVirtualKeyCode = VK_LMENU;
318         else if (e.modifiers & WebInputEvent::IsRight)
319             m_windowsVirtualKeyCode = VK_RMENU;
320     }
321
322 }
323
324 void PlatformKeyboardEventBuilder::setKeyType(Type type)
325 {
326     // According to the behavior of Webkit in Windows platform,
327     // we need to convert KeyDown to RawKeydown and Char events
328     // See WebKit/WebKit/Win/WebView.cpp
329     ASSERT(m_type == KeyDown);
330     ASSERT(type == RawKeyDown || type == Char);
331     m_type = type;
332
333     if (type == RawKeyDown) {
334         m_text = String();
335         m_unmodifiedText = String();
336     } else {
337         m_keyIdentifier = String();
338         m_windowsVirtualKeyCode = 0;
339     }
340 }
341
342 // Please refer to bug http://b/issue?id=961192, which talks about Webkit
343 // keyboard event handling changes. It also mentions the list of keys
344 // which don't have associated character events.
345 bool PlatformKeyboardEventBuilder::isCharacterKey() const
346 {
347     switch (windowsVirtualKeyCode()) {
348     case VKEY_BACK:
349     case VKEY_ESCAPE:
350         return false;
351     }
352     return true;
353 }
354
355 inline PlatformEvent::Type toPlatformTouchEventType(const WebInputEvent::Type type)
356 {
357     switch (type) {
358     case WebInputEvent::TouchStart:
359         return PlatformEvent::TouchStart;
360     case WebInputEvent::TouchMove:
361         return PlatformEvent::TouchMove;
362     case WebInputEvent::TouchEnd:
363         return PlatformEvent::TouchEnd;
364     case WebInputEvent::TouchCancel:
365         return PlatformEvent::TouchCancel;
366     default:
367         ASSERT_NOT_REACHED();
368     }
369     return PlatformEvent::TouchStart;
370 }
371
372 inline PlatformTouchPoint::State toPlatformTouchPointState(const WebTouchPoint::State state)
373 {
374     switch (state) {
375     case WebTouchPoint::StateReleased:
376         return PlatformTouchPoint::TouchReleased;
377     case WebTouchPoint::StatePressed:
378         return PlatformTouchPoint::TouchPressed;
379     case WebTouchPoint::StateMoved:
380         return PlatformTouchPoint::TouchMoved;
381     case WebTouchPoint::StateStationary:
382         return PlatformTouchPoint::TouchStationary;
383     case WebTouchPoint::StateCancelled:
384         return PlatformTouchPoint::TouchCancelled;
385     case WebTouchPoint::StateUndefined:
386         ASSERT_NOT_REACHED();
387     }
388     return PlatformTouchPoint::TouchReleased;
389 }
390
391 inline WebTouchPoint::State toWebTouchPointState(const AtomicString& type)
392 {
393     if (type == EventTypeNames::touchend)
394         return WebTouchPoint::StateReleased;
395     if (type == EventTypeNames::touchcancel)
396         return WebTouchPoint::StateCancelled;
397     if (type == EventTypeNames::touchstart)
398         return WebTouchPoint::StatePressed;
399     if (type == EventTypeNames::touchmove)
400         return WebTouchPoint::StateMoved;
401     return WebTouchPoint::StateUndefined;
402 }
403
404 PlatformTouchPointBuilder::PlatformTouchPointBuilder(Widget* widget, const WebTouchPoint& point)
405 {
406     float scale = widgetInputEventsScaleFactor(widget);
407     IntSize offset = widgetInputEventsOffset(widget);
408     m_id = point.id;
409     m_state = toPlatformTouchPointState(point.state);
410     m_pos = widget->convertFromContainingWindow(IntPoint((point.position.x - offset.width()) / scale, (point.position.y - offset.height()) / scale));
411     m_screenPos = point.screenPosition;
412     m_radiusY = point.radiusY / scale;
413     m_radiusX = point.radiusX / scale;
414     m_rotationAngle = point.rotationAngle;
415     m_force = point.force;
416 }
417
418 PlatformTouchEventBuilder::PlatformTouchEventBuilder(Widget* widget, const WebTouchEvent& event)
419 {
420     m_type = toPlatformTouchEventType(event.type);
421
422     m_modifiers = 0;
423     if (event.modifiers & WebInputEvent::ShiftKey)
424         m_modifiers |= PlatformEvent::ShiftKey;
425     if (event.modifiers & WebInputEvent::ControlKey)
426         m_modifiers |= PlatformEvent::CtrlKey;
427     if (event.modifiers & WebInputEvent::AltKey)
428         m_modifiers |= PlatformEvent::AltKey;
429     if (event.modifiers & WebInputEvent::MetaKey)
430         m_modifiers |= PlatformEvent::MetaKey;
431
432     m_timestamp = event.timeStampSeconds;
433
434     for (unsigned i = 0; i < event.touchesLength; ++i)
435         m_touchPoints.append(PlatformTouchPointBuilder(widget, event.touches[i]));
436 }
437
438 static int getWebInputModifiers(const UIEventWithKeyState& event)
439 {
440     int modifiers = 0;
441     if (event.ctrlKey())
442         modifiers |= WebInputEvent::ControlKey;
443     if (event.shiftKey())
444         modifiers |= WebInputEvent::ShiftKey;
445     if (event.altKey())
446         modifiers |= WebInputEvent::AltKey;
447     if (event.metaKey())
448         modifiers |= WebInputEvent::MetaKey;
449     return modifiers;
450 }
451
452 static IntPoint convertAbsoluteLocationForRenderObject(const LayoutPoint& location, const WebCore::RenderObject& renderObject)
453 {
454     return roundedIntPoint(renderObject.absoluteToLocal(location, UseTransforms));
455 }
456
457 static void updateWebMouseEventFromWebCoreMouseEvent(const MouseRelatedEvent& event, const Widget& widget, const WebCore::RenderObject& renderObject, WebMouseEvent& webEvent)
458 {
459     webEvent.timeStampSeconds = event.timeStamp() / millisPerSecond;
460     webEvent.modifiers = getWebInputModifiers(event);
461
462     ScrollView* view =  toScrollView(widget.parent());
463     IntPoint windowPoint = IntPoint(event.absoluteLocation().x(), event.absoluteLocation().y());
464     if (view)
465         windowPoint = view->contentsToWindow(windowPoint);
466     webEvent.globalX = event.screenX();
467     webEvent.globalY = event.screenY();
468     webEvent.windowX = windowPoint.x();
469     webEvent.windowY = windowPoint.y();
470     IntPoint localPoint = convertAbsoluteLocationForRenderObject(event.absoluteLocation(), renderObject);
471     webEvent.x = localPoint.x();
472     webEvent.y = localPoint.y();
473 }
474
475 WebMouseEventBuilder::WebMouseEventBuilder(const Widget* widget, const WebCore::RenderObject* renderObject, const MouseEvent& event)
476 {
477     if (event.type() == EventTypeNames::mousemove)
478         type = WebInputEvent::MouseMove;
479     else if (event.type() == EventTypeNames::mouseout)
480         type = WebInputEvent::MouseLeave;
481     else if (event.type() == EventTypeNames::mouseover)
482         type = WebInputEvent::MouseEnter;
483     else if (event.type() == EventTypeNames::mousedown)
484         type = WebInputEvent::MouseDown;
485     else if (event.type() == EventTypeNames::mouseup)
486         type = WebInputEvent::MouseUp;
487     else if (event.type() == EventTypeNames::contextmenu)
488         type = WebInputEvent::ContextMenu;
489     else
490         return; // Skip all other mouse events.
491
492     updateWebMouseEventFromWebCoreMouseEvent(event, *widget, *renderObject, *this);
493
494     switch (event.button()) {
495     case LeftButton:
496         button = WebMouseEvent::ButtonLeft;
497         break;
498     case MiddleButton:
499         button = WebMouseEvent::ButtonMiddle;
500         break;
501     case RightButton:
502         button = WebMouseEvent::ButtonRight;
503         break;
504     }
505     if (event.buttonDown()) {
506         switch (event.button()) {
507         case LeftButton:
508             modifiers |= WebInputEvent::LeftButtonDown;
509             break;
510         case MiddleButton:
511             modifiers |= WebInputEvent::MiddleButtonDown;
512             break;
513         case RightButton:
514             modifiers |= WebInputEvent::RightButtonDown;
515             break;
516         }
517     } else
518         button = WebMouseEvent::ButtonNone;
519     movementX = event.webkitMovementX();
520     movementY = event.webkitMovementY();
521     clickCount = event.detail();
522 }
523
524 WebMouseEventBuilder::WebMouseEventBuilder(const Widget* widget, const WebCore::RenderObject* renderObject, const TouchEvent& event)
525 {
526     if (!event.touches())
527         return;
528     if (event.touches()->length() != 1) {
529         if (event.touches()->length() || event.type() != EventTypeNames::touchend || !event.changedTouches() || event.changedTouches()->length() != 1)
530             return;
531     }
532
533     const Touch* touch = event.touches()->length() == 1 ? event.touches()->item(0) : event.changedTouches()->item(0);
534     if (touch->identifier())
535         return;
536
537     if (event.type() == EventTypeNames::touchstart)
538         type = MouseDown;
539     else if (event.type() == EventTypeNames::touchmove)
540         type = MouseMove;
541     else if (event.type() == EventTypeNames::touchend)
542         type = MouseUp;
543     else
544         return;
545
546     updateWebMouseEventFromWebCoreMouseEvent(event, *widget, *renderObject, *this);
547
548     button = WebMouseEvent::ButtonLeft;
549     modifiers |= WebInputEvent::LeftButtonDown;
550     clickCount = (type == MouseDown || type == MouseUp);
551
552     IntPoint localPoint = convertAbsoluteLocationForRenderObject(touch->absoluteLocation(), *renderObject);
553     x = localPoint.x();
554     y = localPoint.y();
555 }
556
557 WebMouseEventBuilder::WebMouseEventBuilder(const WebCore::Widget* widget, const WebCore::PlatformMouseEvent& event)
558 {
559     switch (event.type()) {
560     case PlatformEvent::MouseMoved:
561         type = MouseMove;
562         break;
563     case PlatformEvent::MousePressed:
564         type = MouseDown;
565         break;
566     case PlatformEvent::MouseReleased:
567         type = MouseUp;
568         break;
569     default:
570         ASSERT_NOT_REACHED();
571         type = Undefined;
572         return;
573     }
574
575     modifiers = 0;
576     if (event.modifiers() & PlatformEvent::ShiftKey)
577         modifiers |= ShiftKey;
578     if (event.modifiers() & PlatformEvent::CtrlKey)
579         modifiers |= ControlKey;
580     if (event.modifiers() & PlatformEvent::AltKey)
581         modifiers |= AltKey;
582     if (event.modifiers() & PlatformEvent::MetaKey)
583         modifiers |= MetaKey;
584
585     timeStampSeconds = event.timestamp();
586
587     // FIXME: Widget is always toplevel, unless it's a popup. We may be able
588     // to get rid of this once we abstract popups into a WebKit API.
589     IntPoint position = widget->convertToContainingWindow(event.position());
590     float scale = widgetInputEventsScaleFactor(widget);
591     position.scale(scale, scale);
592     x = position.x();
593     y = position.y();
594     globalX = event.globalPosition().x();
595     globalY = event.globalPosition().y();
596     movementX = event.movementDelta().x() * scale;
597     movementY = event.movementDelta().y() * scale;
598
599     button = static_cast<Button>(event.button());
600     clickCount = event.clickCount();
601 }
602
603 WebMouseWheelEventBuilder::WebMouseWheelEventBuilder(const Widget* widget, const WebCore::RenderObject* renderObject, const WheelEvent& event)
604 {
605     if (event.type() != EventTypeNames::wheel && event.type() != EventTypeNames::mousewheel)
606         return;
607     type = WebInputEvent::MouseWheel;
608     updateWebMouseEventFromWebCoreMouseEvent(event, *widget, *renderObject, *this);
609     deltaX = -event.deltaX();
610     deltaY = -event.deltaY();
611     wheelTicksX = event.ticksX();
612     wheelTicksY = event.ticksY();
613     scrollByPage = event.deltaMode() == WheelEvent::DOM_DELTA_PAGE;
614 }
615
616 WebKeyboardEventBuilder::WebKeyboardEventBuilder(const KeyboardEvent& event)
617 {
618     if (event.type() == EventTypeNames::keydown)
619         type = KeyDown;
620     else if (event.type() == EventTypeNames::keyup)
621         type = WebInputEvent::KeyUp;
622     else if (event.type() == EventTypeNames::keypress)
623         type = WebInputEvent::Char;
624     else
625         return; // Skip all other keyboard events.
626
627     modifiers = getWebInputModifiers(event);
628     if (event.location() == KeyboardEvent::DOM_KEY_LOCATION_NUMPAD)
629         modifiers |= WebInputEvent::IsKeyPad;
630     else if (event.location() == KeyboardEvent::DOM_KEY_LOCATION_LEFT)
631         modifiers |= WebInputEvent::IsLeft;
632     else if (event.location() == KeyboardEvent::DOM_KEY_LOCATION_RIGHT)
633         modifiers |= WebInputEvent::IsRight;
634
635     timeStampSeconds = event.timeStamp() / millisPerSecond;
636     windowsKeyCode = event.keyCode();
637
638     // The platform keyevent does not exist if the event was created using
639     // initKeyboardEvent.
640     if (!event.keyEvent())
641         return;
642     nativeKeyCode = event.keyEvent()->nativeVirtualKeyCode();
643     unsigned numberOfCharacters = std::min(event.keyEvent()->text().length(), static_cast<unsigned>(textLengthCap));
644     for (unsigned i = 0; i < numberOfCharacters; ++i) {
645         text[i] = event.keyEvent()->text()[i];
646         unmodifiedText[i] = event.keyEvent()->unmodifiedText()[i];
647     }
648     memcpy(keyIdentifier, event.keyIdentifier().ascii().data(), event.keyIdentifier().length());
649 }
650
651 WebInputEvent::Type toWebKeyboardEventType(PlatformEvent::Type type)
652 {
653     switch (type) {
654     case PlatformEvent::KeyUp:
655         return WebInputEvent::KeyUp;
656     case PlatformEvent::KeyDown:
657         return WebInputEvent::KeyDown;
658     case PlatformEvent::RawKeyDown:
659         return WebInputEvent::RawKeyDown;
660     case PlatformEvent::Char:
661         return WebInputEvent::Char;
662     default:
663         return WebInputEvent::Undefined;
664     }
665 }
666
667 int toWebKeyboardEventModifiers(int modifiers)
668 {
669     int newModifiers = 0;
670     if (modifiers & PlatformEvent::ShiftKey)
671         newModifiers |= WebInputEvent::ShiftKey;
672     if (modifiers & PlatformEvent::CtrlKey)
673         newModifiers |= WebInputEvent::ControlKey;
674     if (modifiers & PlatformEvent::AltKey)
675         newModifiers |= WebInputEvent::AltKey;
676     if (modifiers & PlatformEvent::MetaKey)
677         newModifiers |= WebInputEvent::MetaKey;
678     return newModifiers;
679 }
680
681 WebKeyboardEventBuilder::WebKeyboardEventBuilder(const WebCore::PlatformKeyboardEvent& event)
682 {
683     type = toWebKeyboardEventType(event.type());
684     modifiers = toWebKeyboardEventModifiers(event.modifiers());
685     if (event.isAutoRepeat())
686         modifiers |= WebInputEvent::IsAutoRepeat;
687     if (event.isKeypad())
688         modifiers |= WebInputEvent::IsKeyPad;
689     isSystemKey = event.isSystemKey();
690     nativeKeyCode = event.nativeVirtualKeyCode();
691
692     windowsKeyCode = windowsKeyCodeWithoutLocation(event.windowsVirtualKeyCode());
693     modifiers |= locationModifiersFromWindowsKeyCode(event.windowsVirtualKeyCode());
694
695     event.text().copyTo(text, 0, textLengthCap);
696     event.unmodifiedText().copyTo(unmodifiedText, 0, textLengthCap);
697     memcpy(keyIdentifier, event.keyIdentifier().ascii().data(), std::min(static_cast<unsigned>(keyIdentifierLengthCap), event.keyIdentifier().length()));
698 }
699
700 static void addTouchPoints(const Widget* widget, const AtomicString& touchType, TouchList* touches, WebTouchPoint* touchPoints, unsigned* touchPointsLength, const WebCore::RenderObject* renderObject)
701 {
702     unsigned numberOfTouches = std::min(touches->length(), static_cast<unsigned>(WebTouchEvent::touchesLengthCap));
703     for (unsigned i = 0; i < numberOfTouches; ++i) {
704         const Touch* touch = touches->item(i);
705
706         WebTouchPoint point;
707         point.id = touch->identifier();
708         point.screenPosition = WebPoint(touch->screenX(), touch->screenY());
709         point.position = convertAbsoluteLocationForRenderObject(touch->absoluteLocation(), *renderObject);
710         point.radiusX = touch->webkitRadiusX();
711         point.radiusY = touch->webkitRadiusY();
712         point.rotationAngle = touch->webkitRotationAngle();
713         point.force = touch->webkitForce();
714         point.state = toWebTouchPointState(touchType);
715
716         touchPoints[i] = point;
717     }
718     *touchPointsLength = numberOfTouches;
719 }
720
721 WebTouchEventBuilder::WebTouchEventBuilder(const Widget* widget, const WebCore::RenderObject* renderObject, const TouchEvent& event)
722 {
723     if (event.type() == EventTypeNames::touchstart)
724         type = TouchStart;
725     else if (event.type() == EventTypeNames::touchmove)
726         type = TouchMove;
727     else if (event.type() == EventTypeNames::touchend)
728         type = TouchEnd;
729     else if (event.type() == EventTypeNames::touchcancel)
730         type = TouchCancel;
731     else {
732         ASSERT_NOT_REACHED();
733         type = Undefined;
734         return;
735     }
736
737     modifiers = getWebInputModifiers(event);
738     timeStampSeconds = event.timeStamp() / millisPerSecond;
739
740     addTouchPoints(widget, event.type(), event.touches(), touches, &touchesLength, renderObject);
741     addTouchPoints(widget, event.type(), event.changedTouches(), changedTouches, &changedTouchesLength, renderObject);
742     addTouchPoints(widget, event.type(), event.targetTouches(), targetTouches, &targetTouchesLength, renderObject);
743 }
744
745 WebGestureEventBuilder::WebGestureEventBuilder(const Widget* widget, const WebCore::RenderObject* renderObject, const GestureEvent& event)
746 {
747     if (event.type() == EventTypeNames::gesturetap)
748         type = GestureTap;
749     else if (event.type() == EventTypeNames::gestureshowpress)
750         type = GestureShowPress;
751     else if (event.type() == EventTypeNames::gesturetapdown)
752         type = GestureTapDown;
753     else if (event.type() == EventTypeNames::gesturescrollstart)
754         type = GestureScrollBegin;
755     else if (event.type() == EventTypeNames::gesturescrollend)
756         type = GestureScrollEnd;
757     else if (event.type() == EventTypeNames::gesturescrollupdate) {
758         type = GestureScrollUpdate;
759         data.scrollUpdate.deltaX = event.deltaX();
760         data.scrollUpdate.deltaY = event.deltaY();
761     }
762
763     timeStampSeconds = event.timeStamp() / millisPerSecond;
764     modifiers = getWebInputModifiers(event);
765
766     globalX = event.screenX();
767     globalY = event.screenY();
768     IntPoint localPoint = convertAbsoluteLocationForRenderObject(event.absoluteLocation(), *renderObject);
769     x = localPoint.x();
770     y = localPoint.y();
771 }
772
773 } // namespace WebKit