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 #ifndef WebInputEvent_h
     32 #define WebInputEvent_h
     33 
     34 #include "../platform/WebCommon.h"
     35 #include "../platform/WebGestureDevice.h"
     36 #include "../platform/WebRect.h"
     37 #include "WebTouchPoint.h"
     38 
     39 #include <string.h>
     40 
     41 namespace blink {
     42 
     43 // The classes defined in this file are intended to be used with
     44 // WebWidget's handleInputEvent method.  These event types are cross-
     45 // platform and correspond closely to WebCore's Platform*Event classes.
     46 //
     47 // WARNING! These classes must remain PODs (plain old data).  They are
     48 // intended to be "serializable" by copying their raw bytes, so they must
     49 // not contain any non-bit-copyable member variables!
     50 //
     51 // Furthermore, the class members need to be packed so they are aligned
     52 // properly and don't have paddings/gaps, otherwise memory check tools
     53 // like Valgrind will complain about uninitialized memory usage when
     54 // transferring these classes over the wire.
     55 
     56 #pragma pack(push, 4)
     57 
     58 // WebInputEvent --------------------------------------------------------------
     59 
     60 class WebInputEvent {
     61 public:
     62     // When we use an input method (or an input method editor), we receive
     63     // two events for a keypress. The former event is a keydown, which
     64     // provides a keycode, and the latter is a textinput, which provides
     65     // a character processed by an input method. (The mapping from a
     66     // keycode to a character code is not trivial for non-English
     67     // keyboards.)
     68     // To support input methods, Safari sends keydown events to WebKit for
     69     // filtering. WebKit sends filtered keydown events back to Safari,
     70     // which sends them to input methods.
     71     // Unfortunately, it is hard to apply this design to Chrome because of
     72     // our multiprocess architecture. An input method is running in a
     73     // browser process. On the other hand, WebKit is running in a renderer
     74     // process. So, this design results in increasing IPC messages.
     75     // To support input methods without increasing IPC messages, Chrome
     76     // handles keyboard events in a browser process and send asynchronous
     77     // input events (to be translated to DOM events) to a renderer
     78     // process.
     79     // This design is mostly the same as the one of Windows and Mac Carbon.
     80     // So, for what it's worth, our Linux and Mac front-ends emulate our
     81     // Windows front-end. To emulate our Windows front-end, we can share
     82     // our back-end code among Windows, Linux, and Mac.
     83     // TODO(hbono): Issue 18064: remove the KeyDown type since it isn't
     84     // used in Chrome any longer.
     85 
     86     enum Type {
     87         Undefined = -1,
     88         TypeFirst = Undefined,
     89 
     90         // WebMouseEvent
     91         MouseDown,
     92         MouseTypeFirst = MouseDown,
     93         MouseUp,
     94         MouseMove,
     95         MouseEnter,
     96         MouseLeave,
     97         ContextMenu,
     98         MouseTypeLast = ContextMenu,
     99 
    100         // WebMouseWheelEvent
    101         MouseWheel,
    102 
    103         // WebKeyboardEvent
    104         RawKeyDown,
    105         KeyboardTypeFirst = RawKeyDown,
    106         KeyDown,
    107         KeyUp,
    108         Char,
    109         KeyboardTypeLast = Char,
    110 
    111         // WebGestureEvent
    112         GestureScrollBegin,
    113         GestureTypeFirst = GestureScrollBegin,
    114         GestureScrollEnd,
    115         GestureScrollUpdate,
    116         GestureScrollUpdateWithoutPropagation,
    117         GestureFlingStart,
    118         GestureFlingCancel,
    119         GestureShowPress,
    120         GestureTap,
    121         GestureTapUnconfirmed,
    122         GestureTapDown,
    123         GestureTapCancel,
    124         GestureDoubleTap,
    125         GestureTwoFingerTap,
    126         GestureLongPress,
    127         GestureLongTap,
    128         GesturePinchBegin,
    129         GesturePinchEnd,
    130         GesturePinchUpdate,
    131         GestureTypeLast = GesturePinchUpdate,
    132 
    133         // WebTouchEvent
    134         TouchStart,
    135         TouchTypeFirst = TouchStart,
    136         TouchMove,
    137         TouchEnd,
    138         TouchCancel,
    139         TouchTypeLast = TouchCancel,
    140 
    141         TypeLast = TouchTypeLast
    142     };
    143 
    144     enum Modifiers {
    145         // modifiers for all events:
    146         ShiftKey         = 1 << 0,
    147         ControlKey       = 1 << 1,
    148         AltKey           = 1 << 2,
    149         MetaKey          = 1 << 3,
    150 
    151         // modifiers for keyboard events:
    152         IsKeyPad         = 1 << 4,
    153         IsAutoRepeat     = 1 << 5,
    154 
    155         // modifiers for mouse events:
    156         LeftButtonDown   = 1 << 6,
    157         MiddleButtonDown = 1 << 7,
    158         RightButtonDown  = 1 << 8,
    159 
    160         // Toggle modifiers for all events. Danger: these are not reflected
    161         // into WebCore, so round-tripping from WebInputEvent to a WebCore
    162         // event and back will not preserve these flags.
    163         CapsLockOn       = 1 << 9,
    164         NumLockOn        = 1 << 10,
    165 
    166         // Left/right modifiers for keyboard events.
    167         IsLeft           = 1 << 11,
    168         IsRight          = 1 << 12,
    169 
    170         // Last input event to be sent for the current vsync interval. If this
    171         // flag is set, the sender guarantees that no more input events will be
    172         // delivered until the next vsync and the receiver can schedule
    173         // rendering accordingly. If it isn't set, the receiver should not make
    174         // any assumptions about the delivery times of future input events
    175         // w.r.t. vsync.
    176         IsLastInputEventForCurrentVSync = 1 << 13,
    177     };
    178 
    179     static const int InputModifiers = ShiftKey | ControlKey | AltKey | MetaKey;
    180 
    181     double timeStampSeconds; // Seconds since epoch.
    182     unsigned size; // The size of this structure, for serialization.
    183     Type type;
    184     int modifiers;
    185 
    186     // Returns true if the WebInputEvent |type| is a mouse event.
    187     static bool isMouseEventType(int type)
    188     {
    189         return MouseTypeFirst <= type && type <= MouseTypeLast;
    190     }
    191 
    192     // Returns true if the WebInputEvent |type| is a keyboard event.
    193     static bool isKeyboardEventType(int type)
    194     {
    195         return KeyboardTypeFirst <= type && type <= KeyboardTypeLast;
    196     }
    197 
    198     // Returns true if the WebInputEvent |type| is a touch event.
    199     static bool isTouchEventType(int type)
    200     {
    201         return TouchTypeFirst <= type && type <= TouchTypeLast;
    202     }
    203 
    204     // Returns true if the WebInputEvent is a gesture event.
    205     static bool isGestureEventType(int type)
    206     {
    207         return GestureTypeFirst <= type && type <= GestureTypeLast;
    208     }
    209 
    210 protected:
    211     explicit WebInputEvent(unsigned sizeParam)
    212     {
    213         memset(this, 0, sizeParam);
    214         timeStampSeconds = 0.0;
    215         size = sizeParam;
    216         type = Undefined;
    217         modifiers = 0;
    218     }
    219 };
    220 
    221 // WebKeyboardEvent -----------------------------------------------------------
    222 
    223 class WebKeyboardEvent : public WebInputEvent {
    224 public:
    225     // Caps on string lengths so we can make them static arrays and keep
    226     // them PODs.
    227     static const size_t textLengthCap = 4;
    228 
    229     // http://www.w3.org/TR/DOM-Level-3-Events/keyset.html lists the
    230     // identifiers.  The longest is 18 characters, so we round up to the
    231     // next multiple of 4.
    232     static const size_t keyIdentifierLengthCap = 20;
    233 
    234     // |windowsKeyCode| is the Windows key code associated with this key
    235     // event.  Sometimes it's direct from the event (i.e. on Windows),
    236     // sometimes it's via a mapping function.  If you want a list, see
    237     // WebCore/platform/chromium/KeyboardCodes* . Note that this should
    238     // ALWAYS store the non-locational version of a keycode as this is
    239     // what is returned by the Windows API. For example, it should
    240     // store VK_SHIFT instead of VK_RSHIFT. The location information
    241     // should be stored in |modifiers|.
    242     int windowsKeyCode;
    243 
    244     // The actual key code genenerated by the platform.  The DOM spec runs
    245     // on Windows-equivalent codes (thus |windowsKeyCode| above) but it
    246     // doesn't hurt to have this one around.
    247     int nativeKeyCode;
    248 
    249     // This identifies whether this event was tagged by the system as being
    250     // a "system key" event (see
    251     // http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx for
    252     // details). Other platforms don't have this concept, but it's just
    253     // easier to leave it always false than ifdef.
    254     // See comment at the top of the file for why an int is used here.
    255     bool isSystemKey;
    256 
    257     // |text| is the text generated by this keystroke.  |unmodifiedText| is
    258     // |text|, but unmodified by an concurrently-held modifiers (except
    259     // shift).  This is useful for working out shortcut keys.  Linux and
    260     // Windows guarantee one character per event.  The Mac does not, but in
    261     // reality that's all it ever gives.  We're generous, and cap it a bit
    262     // longer.
    263     WebUChar text[textLengthCap];
    264     WebUChar unmodifiedText[textLengthCap];
    265 
    266     // This is a string identifying the key pressed.
    267     char keyIdentifier[keyIdentifierLengthCap];
    268 
    269     WebKeyboardEvent()
    270         : WebInputEvent(sizeof(WebKeyboardEvent))
    271         , windowsKeyCode(0)
    272         , nativeKeyCode(0)
    273         , isSystemKey(false)
    274     {
    275         memset(&text, 0, sizeof(text));
    276         memset(&unmodifiedText, 0, sizeof(unmodifiedText));
    277         memset(&keyIdentifier, 0, sizeof(keyIdentifier));
    278     }
    279 
    280     // Sets keyIdentifier based on the value of windowsKeyCode.  This is
    281     // handy for generating synthetic keyboard events.
    282     BLINK_EXPORT void setKeyIdentifierFromWindowsKeyCode();
    283 
    284     static int windowsKeyCodeWithoutLocation(int keycode);
    285     static int locationModifiersFromWindowsKeyCode(int keycode);
    286 };
    287 
    288 // WebMouseEvent --------------------------------------------------------------
    289 
    290 class WebMouseEvent : public WebInputEvent {
    291 public:
    292     enum Button {
    293         ButtonNone = -1,
    294         ButtonLeft,
    295         ButtonMiddle,
    296         ButtonRight
    297     };
    298 
    299     Button button;
    300     int x;
    301     int y;
    302     int windowX;
    303     int windowY;
    304     int globalX;
    305     int globalY;
    306     int movementX;
    307     int movementY;
    308     int clickCount;
    309 
    310     WebMouseEvent()
    311         : WebInputEvent(sizeof(WebMouseEvent))
    312         , button(ButtonNone)
    313         , x(0)
    314         , y(0)
    315         , windowX(0)
    316         , windowY(0)
    317         , globalX(0)
    318         , globalY(0)
    319         , movementX(0)
    320         , movementY(0)
    321         , clickCount(0)
    322     {
    323     }
    324 
    325 protected:
    326     explicit WebMouseEvent(unsigned sizeParam)
    327         : WebInputEvent(sizeParam)
    328         , button(ButtonNone)
    329         , x(0)
    330         , y(0)
    331         , windowX(0)
    332         , windowY(0)
    333         , globalX(0)
    334         , globalY(0)
    335         , movementX(0)
    336         , movementY(0)
    337         , clickCount(0)
    338     {
    339     }
    340 };
    341 
    342 // WebMouseWheelEvent ---------------------------------------------------------
    343 
    344 class WebMouseWheelEvent : public WebMouseEvent {
    345 public:
    346     enum Phase {
    347         PhaseNone        = 0,
    348         PhaseBegan       = 1 << 0,
    349         PhaseStationary  = 1 << 1,
    350         PhaseChanged     = 1 << 2,
    351         PhaseEnded       = 1 << 3,
    352         PhaseCancelled   = 1 << 4,
    353         PhaseMayBegin    = 1 << 5,
    354     };
    355 
    356     float deltaX;
    357     float deltaY;
    358     float wheelTicksX;
    359     float wheelTicksY;
    360 
    361     float accelerationRatioX;
    362     float accelerationRatioY;
    363 
    364     // See comment at the top of the file for why an int is used here.
    365     int scrollByPage;
    366 
    367     // See comment at the top of the file for why an int is used here.
    368     int hasPreciseScrollingDeltas;
    369     Phase phase;
    370     Phase momentumPhase;
    371 
    372     // See comment at the top of the file for why an int is used here.
    373     // Rubberbanding is an OSX visual effect. When a user scrolls the content
    374     // area with a track pad, and the content area is already at its limit in
    375     // the direction being scrolled, the entire content area is allowed to
    376     // scroll slightly off screen, revealing a grey background. When the user
    377     // lets go, the content area snaps back into place. Blink is responsible
    378     // for this rubberbanding effect, but the embedder may wish to disable
    379     // rubber banding in the left or right direction, if the scroll should have
    380     // an alternate effect. The common case is that a scroll in the left or
    381     // right directions causes a back or forwards navigation, respectively.
    382     //
    383     // These flags prevent rubber banding from starting in a given direction,
    384     // but have no effect on an ongoing rubber banding. A rubber banding that
    385     // started in the vertical direction is allowed to continue in the right
    386     // direction, even if canRubberbandRight is 0.
    387     int canRubberbandLeft;
    388     int canRubberbandRight;
    389 
    390     WebMouseWheelEvent()
    391         : WebMouseEvent(sizeof(WebMouseWheelEvent))
    392         , deltaX(0.0f)
    393         , deltaY(0.0f)
    394         , wheelTicksX(0.0f)
    395         , wheelTicksY(0.0f)
    396         , accelerationRatioX(1.0f)
    397         , accelerationRatioY(1.0f)
    398         , scrollByPage(false)
    399         , hasPreciseScrollingDeltas(false)
    400         , phase(PhaseNone)
    401         , momentumPhase(PhaseNone)
    402         , canRubberbandLeft(true)
    403         , canRubberbandRight(true)
    404     {
    405     }
    406 };
    407 
    408 // WebGestureEvent --------------------------------------------------------------
    409 
    410 class WebGestureEvent : public WebInputEvent {
    411 public:
    412     int x;
    413     int y;
    414     int globalX;
    415     int globalY;
    416     WebGestureDevice sourceDevice;
    417 
    418     union {
    419         // Tap information must be set for GestureTap, GestureTapUnconfirmed,
    420         // and GestureDoubleTap events.
    421         struct {
    422             int tapCount;
    423             float width;
    424             float height;
    425         } tap;
    426 
    427         struct {
    428             float width;
    429             float height;
    430         } tapDown;
    431 
    432         struct {
    433             float width;
    434             float height;
    435         } showPress;
    436 
    437         struct {
    438             float width;
    439             float height;
    440         } longPress;
    441 
    442         struct {
    443             float firstFingerWidth;
    444             float firstFingerHeight;
    445         } twoFingerTap;
    446 
    447         struct {
    448             // Initial motion that triggered the scroll.
    449             // May be redundant with deltaX/deltaY in the first scrollUpdate.
    450             float deltaXHint;
    451             float deltaYHint;
    452         } scrollBegin;
    453 
    454         struct {
    455             float deltaX;
    456             float deltaY;
    457             float velocityX;
    458             float velocityY;
    459         } scrollUpdate;
    460 
    461         struct {
    462             float velocityX;
    463             float velocityY;
    464         } flingStart;
    465 
    466         struct {
    467             float scale;
    468         } pinchUpdate;
    469     } data;
    470 
    471     WebGestureEvent()
    472         : WebInputEvent(sizeof(WebGestureEvent))
    473         , x(0)
    474         , y(0)
    475         , globalX(0)
    476         , globalY(0)
    477     {
    478         memset(&data, 0, sizeof(data));
    479     }
    480 };
    481 
    482 // WebTouchEvent --------------------------------------------------------------
    483 
    484 class WebTouchEvent : public WebInputEvent {
    485 public:
    486     // Maximum number of simultaneous touches supported on
    487     // Ash/Aura.
    488     enum { touchesLengthCap = 12 };
    489 
    490     unsigned touchesLength;
    491     // List of all touches, regardless of state.
    492     WebTouchPoint touches[touchesLengthCap];
    493 
    494     // Whether the event can be canceled (with preventDefault). If true then the browser
    495     // must wait for an ACK for this event. If false then no ACK IPC is expected.
    496     // See comment at the top for why an int is used here instead of a bool.
    497     int cancelable;
    498 
    499     WebTouchEvent()
    500         : WebInputEvent(sizeof(WebTouchEvent))
    501         , touchesLength(0)
    502         , cancelable(true)
    503     {
    504     }
    505 };
    506 
    507 #pragma pack(pop)
    508 
    509 } // namespace blink
    510 
    511 #endif
    512