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