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