Home | History | Annotate | Download | only in web
      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