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