Home | History | Annotate | Download | only in src
      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 "EventNames.h"
     35 #include "KeyboardCodes.h"
     36 #include "KeyboardEvent.h"
     37 #include "MouseEvent.h"
     38 #include "PlatformKeyboardEvent.h"
     39 #include "PlatformMouseEvent.h"
     40 #include "PlatformWheelEvent.h"
     41 #include "ScrollView.h"
     42 #include "WebInputEvent.h"
     43 #include "WheelEvent.h"
     44 #include "Widget.h"
     45 
     46 using namespace WebCore;
     47 
     48 namespace WebKit {
     49 
     50 // MakePlatformMouseEvent -----------------------------------------------------
     51 
     52 PlatformMouseEventBuilder::PlatformMouseEventBuilder(Widget* widget, const WebMouseEvent& e)
     53 {
     54     // FIXME: widget is always toplevel, unless it's a popup.  We may be able
     55     // to get rid of this once we abstract popups into a WebKit API.
     56     m_position = widget->convertFromContainingWindow(IntPoint(e.x, e.y));
     57     m_globalPosition = IntPoint(e.globalX, e.globalY);
     58     m_button = static_cast<MouseButton>(e.button);
     59     m_shiftKey = (e.modifiers & WebInputEvent::ShiftKey);
     60     m_ctrlKey = (e.modifiers & WebInputEvent::ControlKey);
     61     m_altKey = (e.modifiers & WebInputEvent::AltKey);
     62     m_metaKey = (e.modifiers & WebInputEvent::MetaKey);
     63     m_modifierFlags = e.modifiers;
     64     m_timestamp = e.timeStampSeconds;
     65     m_clickCount = e.clickCount;
     66 
     67     switch (e.type) {
     68     case WebInputEvent::MouseMove:
     69     case WebInputEvent::MouseLeave:  // synthesize a move event
     70         m_eventType = MouseEventMoved;
     71         break;
     72 
     73     case WebInputEvent::MouseDown:
     74         m_eventType = MouseEventPressed;
     75         break;
     76 
     77     case WebInputEvent::MouseUp:
     78         m_eventType = MouseEventReleased;
     79         break;
     80 
     81     default:
     82         ASSERT_NOT_REACHED();
     83     }
     84 }
     85 
     86 // PlatformWheelEventBuilder --------------------------------------------------
     87 
     88 PlatformWheelEventBuilder::PlatformWheelEventBuilder(Widget* widget, const WebMouseWheelEvent& e)
     89 {
     90     m_position = widget->convertFromContainingWindow(IntPoint(e.x, e.y));
     91     m_globalPosition = IntPoint(e.globalX, e.globalY);
     92     m_deltaX = e.deltaX;
     93     m_deltaY = e.deltaY;
     94     m_wheelTicksX = e.wheelTicksX;
     95     m_wheelTicksY = e.wheelTicksY;
     96     m_isAccepted = false;
     97     m_granularity = e.scrollByPage ?
     98         ScrollByPageWheelEvent : ScrollByPixelWheelEvent;
     99     m_shiftKey = (e.modifiers & WebInputEvent::ShiftKey);
    100     m_ctrlKey = (e.modifiers & WebInputEvent::ControlKey);
    101     m_altKey = (e.modifiers & WebInputEvent::AltKey);
    102     m_metaKey = (e.modifiers & WebInputEvent::MetaKey);
    103 }
    104 
    105 // MakePlatformKeyboardEvent --------------------------------------------------
    106 
    107 static inline PlatformKeyboardEvent::Type toPlatformKeyboardEventType(WebInputEvent::Type type)
    108 {
    109     switch (type) {
    110     case WebInputEvent::KeyUp:
    111         return PlatformKeyboardEvent::KeyUp;
    112     case WebInputEvent::KeyDown:
    113         return PlatformKeyboardEvent::KeyDown;
    114     case WebInputEvent::RawKeyDown:
    115         return PlatformKeyboardEvent::RawKeyDown;
    116     case WebInputEvent::Char:
    117         return PlatformKeyboardEvent::Char;
    118     default:
    119         ASSERT_NOT_REACHED();
    120     }
    121     return PlatformKeyboardEvent::KeyDown;
    122 }
    123 
    124 PlatformKeyboardEventBuilder::PlatformKeyboardEventBuilder(const WebKeyboardEvent& e)
    125 {
    126     m_type = toPlatformKeyboardEventType(e.type);
    127     m_text = String(e.text);
    128     m_unmodifiedText = String(e.unmodifiedText);
    129     m_keyIdentifier = String(e.keyIdentifier);
    130     m_autoRepeat = (e.modifiers & WebInputEvent::IsAutoRepeat);
    131     m_windowsVirtualKeyCode = e.windowsKeyCode;
    132     m_nativeVirtualKeyCode = e.nativeKeyCode;
    133     m_isKeypad = (e.modifiers & WebInputEvent::IsKeyPad);
    134     m_shiftKey = (e.modifiers & WebInputEvent::ShiftKey);
    135     m_ctrlKey = (e.modifiers & WebInputEvent::ControlKey);
    136     m_altKey = (e.modifiers & WebInputEvent::AltKey);
    137     m_metaKey = (e.modifiers & WebInputEvent::MetaKey);
    138     m_isSystemKey = e.isSystemKey;
    139 }
    140 
    141 void PlatformKeyboardEventBuilder::setKeyType(Type type)
    142 {
    143     // According to the behavior of Webkit in Windows platform,
    144     // we need to convert KeyDown to RawKeydown and Char events
    145     // See WebKit/WebKit/Win/WebView.cpp
    146     ASSERT(m_type == KeyDown);
    147     ASSERT(type == RawKeyDown || type == Char);
    148     m_type = type;
    149 
    150     if (type == RawKeyDown) {
    151         m_text = String();
    152         m_unmodifiedText = String();
    153     } else {
    154         m_keyIdentifier = String();
    155         m_windowsVirtualKeyCode = 0;
    156     }
    157 }
    158 
    159 // Please refer to bug http://b/issue?id=961192, which talks about Webkit
    160 // keyboard event handling changes. It also mentions the list of keys
    161 // which don't have associated character events.
    162 bool PlatformKeyboardEventBuilder::isCharacterKey() const
    163 {
    164     switch (windowsVirtualKeyCode()) {
    165     case VKEY_BACK:
    166     case VKEY_ESCAPE:
    167         return false;
    168     }
    169     return true;
    170 }
    171 
    172 #if ENABLE(TOUCH_EVENTS)
    173 static inline TouchEventType toPlatformTouchEventType(const WebInputEvent::Type type)
    174 {
    175     switch (type) {
    176     case WebInputEvent::TouchStart:
    177         return TouchStart;
    178     case WebInputEvent::TouchMove:
    179         return TouchMove;
    180     case WebInputEvent::TouchEnd:
    181         return TouchEnd;
    182     case WebInputEvent::TouchCancel:
    183         return TouchCancel;
    184     default:
    185         ASSERT_NOT_REACHED();
    186     }
    187     return TouchStart;
    188 }
    189 
    190 static inline PlatformTouchPoint::State toPlatformTouchPointState(const WebTouchPoint::State state)
    191 {
    192     switch (state) {
    193     case WebTouchPoint::StateReleased:
    194         return PlatformTouchPoint::TouchReleased;
    195     case WebTouchPoint::StatePressed:
    196         return PlatformTouchPoint::TouchPressed;
    197     case WebTouchPoint::StateMoved:
    198         return PlatformTouchPoint::TouchMoved;
    199     case WebTouchPoint::StateStationary:
    200         return PlatformTouchPoint::TouchStationary;
    201     case WebTouchPoint::StateCancelled:
    202         return PlatformTouchPoint::TouchCancelled;
    203     case WebTouchPoint::StateUndefined:
    204         ASSERT_NOT_REACHED();
    205     }
    206     return PlatformTouchPoint::TouchReleased;
    207 }
    208 
    209 PlatformTouchPointBuilder::PlatformTouchPointBuilder(Widget* widget, const WebTouchPoint& point)
    210 {
    211     m_id = point.id;
    212     m_state = toPlatformTouchPointState(point.state);
    213     m_pos = widget->convertFromContainingWindow(point.position);
    214     m_screenPos = point.screenPosition;
    215 }
    216 
    217 PlatformTouchEventBuilder::PlatformTouchEventBuilder(Widget* widget, const WebTouchEvent& event)
    218 {
    219     m_type = toPlatformTouchEventType(event.type);
    220     m_ctrlKey = event.modifiers & WebInputEvent::ControlKey;
    221     m_altKey = event.modifiers & WebInputEvent::AltKey;
    222     m_shiftKey = event.modifiers & WebInputEvent::ShiftKey;
    223     m_metaKey = event.modifiers & WebInputEvent::MetaKey;
    224     m_timestamp = event.timeStampSeconds;
    225 
    226     for (int i = 0; i < event.touchPointsLength; ++i)
    227         m_touchPoints.append(PlatformTouchPointBuilder(widget, event.touchPoints[i]));
    228 }
    229 #endif
    230 
    231 static int getWebInputModifiers(const UIEventWithKeyState& event)
    232 {
    233     int modifiers = 0;
    234     if (event.ctrlKey())
    235         modifiers |= WebInputEvent::ControlKey;
    236     if (event.shiftKey())
    237         modifiers |= WebInputEvent::ShiftKey;
    238     if (event.altKey())
    239         modifiers |= WebInputEvent::AltKey;
    240     if (event.metaKey())
    241         modifiers |= WebInputEvent::MetaKey;
    242     return modifiers;
    243 }
    244 
    245 WebMouseEventBuilder::WebMouseEventBuilder(const Widget* widget, const MouseEvent& event)
    246 {
    247     if (event.type() == eventNames().mousemoveEvent)
    248         type = WebInputEvent::MouseMove;
    249     else if (event.type() == eventNames().mouseoutEvent)
    250         type = WebInputEvent::MouseLeave;
    251     else if (event.type() == eventNames().mouseoverEvent)
    252         type = WebInputEvent::MouseEnter;
    253     else if (event.type() == eventNames().mousedownEvent)
    254         type = WebInputEvent::MouseDown;
    255     else if (event.type() == eventNames().mouseupEvent)
    256         type = WebInputEvent::MouseUp;
    257     else if (event.type() == eventNames().contextmenuEvent)
    258         type = WebInputEvent::ContextMenu;
    259     else
    260         return; // Skip all other mouse events.
    261     timeStampSeconds = event.timeStamp() * 1.0e-3;
    262     switch (event.button()) {
    263     case LeftButton:
    264         button = WebMouseEvent::ButtonLeft;
    265         break;
    266     case MiddleButton:
    267         button = WebMouseEvent::ButtonMiddle;
    268         break;
    269     case RightButton:
    270         button = WebMouseEvent::ButtonRight;
    271         break;
    272     }
    273     modifiers = getWebInputModifiers(event);
    274     if (event.buttonDown()) {
    275         switch (event.button()) {
    276         case LeftButton:
    277             modifiers |= WebInputEvent::LeftButtonDown;
    278             break;
    279         case MiddleButton:
    280             modifiers |= WebInputEvent::MiddleButtonDown;
    281             break;
    282         case RightButton:
    283             modifiers |= WebInputEvent::RightButtonDown;
    284             break;
    285         }
    286     }
    287     ScrollView* view = widget->parent();
    288     IntPoint p = view->contentsToWindow(
    289         IntPoint(event.absoluteLocation().x(), event.absoluteLocation().y()));
    290     globalX = event.screenX();
    291     globalY = event.screenY();
    292     windowX = p.x();
    293     windowY = p.y();
    294     x = event.absoluteLocation().x() - widget->pos().x();
    295     y = event.absoluteLocation().y() - widget->pos().y();
    296     clickCount = event.detail();
    297 }
    298 
    299 WebMouseWheelEventBuilder::WebMouseWheelEventBuilder(const Widget* widget, const WheelEvent& event)
    300 {
    301     if (event.type() != eventNames().mousewheelEvent)
    302         return;
    303     type = WebInputEvent::MouseWheel;
    304     timeStampSeconds = event.timeStamp() * 1.0e-3;
    305     modifiers = getWebInputModifiers(event);
    306     ScrollView* view = widget->parent();
    307     IntPoint p = view->contentsToWindow(
    308         IntPoint(event.absoluteLocation().x(), event.absoluteLocation().y()));
    309     globalX = event.screenX();
    310     globalY = event.screenY();
    311     windowX = p.x();
    312     windowY = p.y();
    313     x = event.absoluteLocation().x() - widget->pos().x();
    314     y = event.absoluteLocation().y() - widget->pos().y();
    315     deltaX = static_cast<float>(event.rawDeltaX());
    316     deltaY = static_cast<float>(event.rawDeltaY());
    317     // The 120 is from WheelEvent::initWheelEvent().
    318     wheelTicksX = static_cast<float>(event.wheelDeltaX()) / 120;
    319     wheelTicksY = static_cast<float>(event.wheelDeltaY()) / 120;
    320     scrollByPage = event.granularity() == WheelEvent::Page;
    321 }
    322 
    323 WebKeyboardEventBuilder::WebKeyboardEventBuilder(const KeyboardEvent& event)
    324 {
    325     if (event.type() == eventNames().keydownEvent)
    326         type = KeyDown;
    327     else if (event.type() == eventNames().keyupEvent)
    328         type = WebInputEvent::KeyUp;
    329     else if (event.type() == eventNames().keypressEvent)
    330         type = WebInputEvent::Char;
    331     else
    332         return; // Skip all other keyboard events.
    333     modifiers = getWebInputModifiers(event);
    334     timeStampSeconds = event.timeStamp() * 1.0e-3;
    335     windowsKeyCode = event.keyCode();
    336 
    337     // The platform keyevent does not exist if the event was created using
    338     // initKeyboardEvent.
    339     if (!event.keyEvent())
    340         return;
    341     nativeKeyCode = event.keyEvent()->nativeVirtualKeyCode();
    342     unsigned int numChars = std::min(event.keyEvent()->text().length(),
    343         static_cast<unsigned int>(WebKeyboardEvent::textLengthCap));
    344     for (unsigned int i = 0; i < numChars; i++) {
    345         text[i] = event.keyEvent()->text()[i];
    346         unmodifiedText[i] = event.keyEvent()->unmodifiedText()[i];
    347     }
    348 }
    349 
    350 } // namespace WebKit
    351