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