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
41namespace 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
60class WebInputEvent {
61public:
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
210protected:
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
223class WebKeyboardEvent : public WebInputEvent {
224public:
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
290class WebMouseEvent : public WebInputEvent {
291public:
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
325protected:
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
344class WebMouseWheelEvent : public WebMouseEvent {
345public:
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
410class WebGestureEvent : public WebInputEvent {
411public:
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
484class WebTouchEvent : public WebInputEvent {
485public:
486    // Maximum number of simultaneous touches supported on
487    // Ash/Aura.
488    enum { touchesLengthCap = 12 };
489
490    unsigned touchesLength;
491    // List of all touches which are currently down.
492    WebTouchPoint touches[touchesLengthCap];
493
494    unsigned changedTouchesLength;
495    // List of all touches whose state has changed since the last WebTouchEvent
496    WebTouchPoint changedTouches[touchesLengthCap];
497
498    unsigned targetTouchesLength;
499    // List of all touches which are currently down and are targeting the event recipient.
500    WebTouchPoint targetTouches[touchesLengthCap];
501
502    // Whether the event can be canceled (with preventDefault). If true then the browser
503    // must wait for an ACK for this event. If false then no ACK IPC is expected.
504    // See comment at the top for why an int is used here instead of a bool.
505    int cancelable;
506
507    WebTouchEvent()
508        : WebInputEvent(sizeof(WebTouchEvent))
509        , touchesLength(0)
510        , changedTouchesLength(0)
511        , targetTouchesLength(0)
512        , cancelable(true)
513    {
514    }
515};
516
517#pragma pack(pop)
518
519} // namespace blink
520
521#endif
522