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