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 THIRD_PARTY_BLINK_PUBLIC_COMMON_INPUT_WEB_INPUT_EVENT_H_
32 #define THIRD_PARTY_BLINK_PUBLIC_COMMON_INPUT_WEB_INPUT_EVENT_H_
33 
34 #include <string.h>
35 
36 #include <memory>
37 
38 #include "base/time/time.h"
39 #include "third_party/blink/public/common/common_export.h"
40 #include "ui/gfx/geometry/point_f.h"
41 #include "ui/gfx/geometry/vector2d_f.h"
42 
43 namespace blink {
44 
45 // WebInputEvent --------------------------------------------------------------
46 
47 class BLINK_COMMON_EXPORT WebInputEvent {
48  public:
49   // When we use an input method (or an input method editor), we receive
50   // two events for a keypress. The former event is a keydown, which
51   // provides a keycode, and the latter is a textinput, which provides
52   // a character processed by an input method. (The mapping from a
53   // keycode to a character code is not trivial for non-English
54   // keyboards.)
55   // To support input methods, Safari sends keydown events to WebKit for
56   // filtering. WebKit sends filtered keydown events back to Safari,
57   // which sends them to input methods.
58   // Unfortunately, it is hard to apply this design to Chrome because of
59   // our multiprocess architecture. An input method is running in a
60   // browser process. On the other hand, WebKit is running in a renderer
61   // process. So, this design results in increasing IPC messages.
62   // To support input methods without increasing IPC messages, Chrome
63   // handles keyboard events in a browser process and send asynchronous
64   // input events (to be translated to DOM events) to a renderer
65   // process.
66   // This design is mostly the same as the one of Windows and Mac Carbon.
67   // So, for what it's worth, our Linux and Mac front-ends emulate our
68   // Windows front-end. To emulate our Windows front-end, we can share
69   // our back-end code among Windows, Linux, and Mac.
70   // TODO(hbono): Issue 18064: remove the KeyDown type since it isn't
71   // used in Chrome any longer.
72 
73   // A Java counterpart will be generated for this enum.
74   // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.blink_public.web
75   // GENERATED_JAVA_CLASS_NAME_OVERRIDE: WebInputEventType
76   enum Type {
77     kUndefined = -1,
78     kTypeFirst = kUndefined,
79 
80     // WebMouseEvent
81     kMouseDown,
82     kMouseTypeFirst = kMouseDown,
83     kMouseUp,
84     kMouseMove,
85     kMouseEnter,
86     kMouseLeave,
87     kContextMenu,
88     kMouseTypeLast = kContextMenu,
89 
90     // WebMouseWheelEvent
91     kMouseWheel,
92 
93     // WebKeyboardEvent
94     kRawKeyDown,
95     kKeyboardTypeFirst = kRawKeyDown,
96     // KeyDown is a single event combining RawKeyDown and Char.  If KeyDown is
97     // sent for a given keystroke, those two other events will not be sent.
98     // Platforms tend to prefer sending in one format (Android uses KeyDown,
99     // Windows uses RawKeyDown+Char, for example), but this is a weakly held
100     // property as tools like WebDriver/DevTools might still send the other
101     // format.
102     kKeyDown,
103     kKeyUp,
104     kChar,
105     kKeyboardTypeLast = kChar,
106 
107     // WebGestureEvent - input interpreted semi-semantically, most commonly from
108     // touchscreen but also used for touchpad, mousewheel, and gamepad
109     // scrolling.
110     kGestureScrollBegin,
111     kGestureTypeFirst = kGestureScrollBegin,
112     kGestureScrollEnd,
113     kGestureScrollUpdate,
114     // Fling is a high-velocity and quickly released finger movement.
115     // FlingStart is sent once and kicks off a scroll animation.
116     kGestureFlingStart,
117     kGestureFlingCancel,
118     // Pinch is two fingers moving closer or farther apart.
119     kGesturePinchBegin,
120     kGesturePinchTypeFirst = kGesturePinchBegin,
121     kGesturePinchEnd,
122     kGesturePinchUpdate,
123     kGesturePinchTypeLast = kGesturePinchUpdate,
124 
125     // The following types are variations and subevents of single-taps.
126     //
127     // Sent the moment the user's finger hits the screen.
128     kGestureTapDown,
129     // Sent a short interval later, after it seems the finger is staying in
130     // place.  It's used to activate the link highlight ("show the press").
131     kGestureShowPress,
132     // Sent on finger lift for a simple, static, quick finger tap.  This is the
133     // "main" event which maps to a synthetic mouse click event.
134     kGestureTap,
135     // Sent when a GestureTapDown didn't turn into any variation of GestureTap
136     // (likely it turned into a scroll instead).
137     kGestureTapCancel,
138     // Sent as soon as the long-press timeout fires, while the finger is still
139     // down.
140     kGestureLongPress,
141     // Sent when the finger is lifted following a GestureLongPress.
142     kGestureLongTap,
143     // Sent on finger lift when two fingers tapped at the same time without
144     // moving.
145     kGestureTwoFingerTap,
146     // A rare event sent in place of GestureTap on desktop pages viewed on an
147     // Android phone.  This tap could not yet be resolved into a GestureTap
148     // because it may still turn into a GestureDoubleTap.
149     kGestureTapUnconfirmed,
150 
151     // On Android, double-tap is two single-taps spread apart in time, like a
152     // double-click. This event is only sent on desktop pages, and is always
153     // preceded by GestureTapUnconfirmed. It's an instruction to Blink to
154     // perform a PageScaleAnimation zoom onto the double-tapped content. (It's
155     // treated differently from GestureTap with tapCount=2, which can also
156     // happen.)
157     // On desktop, this event may be used for a double-tap with two fingers on
158     // a touchpad, as the desired effect is similar to Android's double-tap.
159     kGestureDoubleTap,
160 
161     kGestureTypeLast = kGestureDoubleTap,
162 
163     // WebTouchEvent - raw touch pointers not yet classified into gestures.
164     kTouchStart,
165     kTouchTypeFirst = kTouchStart,
166     kTouchMove,
167     kTouchEnd,
168     kTouchCancel,
169     // TODO(nzolghadr): This event should be replaced with
170     // kPointerCausedUaAction
171     kTouchScrollStarted,
172     kTouchTypeLast = kTouchScrollStarted,
173 
174     // WebPointerEvent: work in progress
175     kPointerDown,
176     kPointerTypeFirst = kPointerDown,
177     kPointerUp,
178     kPointerMove,
179     kPointerRawUpdate,  // To be only used within blink.
180     kPointerCancel,
181     kPointerCausedUaAction,
182     kPointerTypeLast = kPointerCausedUaAction,
183 
184     kTypeLast = kPointerTypeLast
185   };
186 
187   // The modifier constants cannot change their values since pepper
188   // does a 1-1 mapping of its values; see
189   // content/renderer/pepper/event_conversion.cc
190   //
191   // A Java counterpart will be generated for this enum.
192   // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.blink_public.web
193   // GENERATED_JAVA_CLASS_NAME_OVERRIDE: WebInputEventModifier
194   enum Modifiers {
195     // modifiers for all events:
196     kShiftKey = 1 << 0,
197     kControlKey = 1 << 1,
198     kAltKey = 1 << 2,
199     kMetaKey = 1 << 3,
200 
201     // modifiers for keyboard events:
202     kIsKeyPad = 1 << 4,
203     kIsAutoRepeat = 1 << 5,
204 
205     // modifiers for mouse events:
206     kLeftButtonDown = 1 << 6,
207     kMiddleButtonDown = 1 << 7,
208     kRightButtonDown = 1 << 8,
209 
210     // Toggle modifers for all events.
211     kCapsLockOn = 1 << 9,
212     kNumLockOn = 1 << 10,
213 
214     kIsLeft = 1 << 11,
215     kIsRight = 1 << 12,
216 
217     // Indicates that an event was generated on the touch screen while
218     // touch accessibility is enabled, so the event should be handled
219     // by accessibility code first before normal input event processing.
220     kIsTouchAccessibility = 1 << 13,
221 
222     kIsComposing = 1 << 14,
223 
224     kAltGrKey = 1 << 15,
225     kFnKey = 1 << 16,
226     kSymbolKey = 1 << 17,
227 
228     kScrollLockOn = 1 << 18,
229 
230     // Whether this is a compatibility event generated due to a
231     // native touch event. Mouse events generated from touch
232     // events will set this.
233     kIsCompatibilityEventForTouch = 1 << 19,
234 
235     kBackButtonDown = 1 << 20,
236     kForwardButtonDown = 1 << 21,
237 
238     // Represents movement as a result of content changing under the cursor,
239     // not actual physical movement of the pointer
240     kRelativeMotionEvent = 1 << 22,
241 
242     // Indication this event was injected by the devtools.
243     // TODO(dtapuska): Remove this flag once we are able to bind callbacks
244     // in event sending.
245     kFromDebugger = 1 << 23,
246 
247     // Indicates this event is targeting an OOPIF, and the iframe or one of its
248     // ancestor frames moved within its embedding page's viewport recently.
249     kTargetFrameMovedRecently = 1 << 24,
250 
251     // When an event is forwarded to the main thread, this modifier will tell if
252     // the event was already handled by the compositor thread or not. Based on
253     // this, the decision of whether or not the main thread should handle this
254     // event for the scrollbar can then be made.
255     kScrollbarManipulationHandledOnCompositorThread = 1 << 25,
256 
257     // The set of non-stateful modifiers that specifically change the
258     // interpretation of the key being pressed. For example; IsLeft,
259     // IsRight, IsComposing don't change the meaning of the key
260     // being pressed. NumLockOn, ScrollLockOn, CapsLockOn are stateful
261     // and don't indicate explicit depressed state.
262     kKeyModifiers = kSymbolKey | kFnKey | kAltGrKey | kMetaKey | kAltKey |
263                     kControlKey | kShiftKey,
264 
265     kNoModifiers = 0,
266   };
267 
268   // Indicates whether the browser needs to block on the ACK result for
269   // this event, and if not, why (for metrics/diagnostics purposes).
270   // These values are direct mappings of the values in PlatformEvent
271   // so the values can be cast between the enumerations. static_asserts
272   // checking this are in web/WebInputEventConversion.cpp.
273   enum DispatchType {
274     // Event can be canceled.
275     kBlocking,
276     // Event can not be canceled.
277     kEventNonBlocking,
278     // All listeners are passive; not cancelable.
279     kListenersNonBlockingPassive,
280     // This value represents a state which would have normally blocking
281     // but was forced to be non-blocking during fling; not cancelable.
282     kListenersForcedNonBlockingDueToFling,
283     kLastDispatchType = kListenersForcedNonBlockingDueToFling,
284   };
285 
286   // The rail mode for a wheel event specifies the axis on which scrolling is
287   // expected to stick. If this axis is set to Free, then scrolling is not
288   // stuck to any axis.
289   enum RailsMode {
290     kRailsModeFree = 0,
291     kRailsModeHorizontal = 1,
292     kRailsModeVertical = 2,
293   };
294 
295   static const int kInputModifiers =
296       kShiftKey | kControlKey | kAltKey | kMetaKey;
297 
GetStaticTimeStampForTests()298   static constexpr base::TimeTicks GetStaticTimeStampForTests() {
299     // Note: intentionally use a relatively large delta from base::TimeTicks ==
300     // 0. Otherwise, code that tracks the time ticks of the last event that
301     // happened and computes a delta might get confused when the testing
302     // timestamp is near 0, as the computed delta may very well be under the
303     // delta threshhold.
304     //
305     // TODO(dcheng): This really shouldn't use FromInternalValue(), but
306     // constexpr support for time operations is a bit busted...
307     return base::TimeTicks::FromInternalValue(123'000'000);
308   }
309 
310   // Returns true if the WebInputEvent |type| is a mouse event.
IsMouseEventType(WebInputEvent::Type type)311   static bool IsMouseEventType(WebInputEvent::Type type) {
312     return kMouseTypeFirst <= type && type <= kMouseTypeLast;
313   }
314 
315   // Returns true if the WebInputEvent |type| is a keyboard event.
IsKeyboardEventType(WebInputEvent::Type type)316   static bool IsKeyboardEventType(WebInputEvent::Type type) {
317     return kKeyboardTypeFirst <= type && type <= kKeyboardTypeLast;
318   }
319 
320   // Returns true if the WebInputEvent |type| is a touch event.
IsTouchEventType(WebInputEvent::Type type)321   static bool IsTouchEventType(WebInputEvent::Type type) {
322     return kTouchTypeFirst <= type && type <= kTouchTypeLast;
323   }
324 
325   // Returns true if the WebInputEvent is a gesture event.
IsGestureEventType(WebInputEvent::Type type)326   static bool IsGestureEventType(WebInputEvent::Type type) {
327     return kGestureTypeFirst <= type && type <= kGestureTypeLast;
328   }
329 
330   // Returns true if the WebInputEvent |type| is a pointer event.
IsPointerEventType(WebInputEvent::Type type)331   static bool IsPointerEventType(WebInputEvent::Type type) {
332     return kPointerTypeFirst <= type && type <= kPointerTypeLast;
333   }
334 
IsSameEventClass(const WebInputEvent & other)335   bool IsSameEventClass(const WebInputEvent& other) const {
336     if (IsMouseEventType(type_))
337       return IsMouseEventType(other.type_);
338     if (IsGestureEventType(type_))
339       return IsGestureEventType(other.type_);
340     if (IsTouchEventType(type_))
341       return IsTouchEventType(other.type_);
342     if (IsKeyboardEventType(type_))
343       return IsKeyboardEventType(other.type_);
344     if (IsPointerEventType(type_))
345       return IsPointerEventType(other.type_);
346     return type_ == other.type_;
347   }
348 
IsGestureScroll()349   bool IsGestureScroll() const {
350     switch (type_) {
351       case Type::kGestureScrollBegin:
352       case Type::kGestureScrollUpdate:
353       case Type::kGestureScrollEnd:
354         return true;
355       default:
356         return false;
357     }
358   }
359 
360   // Returns true if the WebInputEvent |type| is a pinch gesture event.
IsPinchGestureEventType(WebInputEvent::Type type)361   static bool IsPinchGestureEventType(WebInputEvent::Type type) {
362     return kGesturePinchTypeFirst <= type && type <= kGesturePinchTypeLast;
363   }
364 
365   // Returns true if the WebInputEvent |type| is a fling gesture event.
IsFlingGestureEventType(WebInputEvent::Type type)366   static bool IsFlingGestureEventType(WebInputEvent::Type type) {
367     return kGestureFlingStart <= type && type <= kGestureFlingCancel;
368   }
369 
GetName(WebInputEvent::Type type)370   static const char* GetName(WebInputEvent::Type type) {
371 #define CASE_TYPE(t)        \
372   case WebInputEvent::k##t: \
373     return #t
374     switch (type) {
375       CASE_TYPE(Undefined);
376       CASE_TYPE(MouseDown);
377       CASE_TYPE(MouseUp);
378       CASE_TYPE(MouseMove);
379       CASE_TYPE(MouseEnter);
380       CASE_TYPE(MouseLeave);
381       CASE_TYPE(ContextMenu);
382       CASE_TYPE(MouseWheel);
383       CASE_TYPE(RawKeyDown);
384       CASE_TYPE(KeyDown);
385       CASE_TYPE(KeyUp);
386       CASE_TYPE(Char);
387       CASE_TYPE(GestureScrollBegin);
388       CASE_TYPE(GestureScrollEnd);
389       CASE_TYPE(GestureScrollUpdate);
390       CASE_TYPE(GestureFlingStart);
391       CASE_TYPE(GestureFlingCancel);
392       CASE_TYPE(GestureShowPress);
393       CASE_TYPE(GestureTap);
394       CASE_TYPE(GestureTapUnconfirmed);
395       CASE_TYPE(GestureTapDown);
396       CASE_TYPE(GestureTapCancel);
397       CASE_TYPE(GestureDoubleTap);
398       CASE_TYPE(GestureTwoFingerTap);
399       CASE_TYPE(GestureLongPress);
400       CASE_TYPE(GestureLongTap);
401       CASE_TYPE(GesturePinchBegin);
402       CASE_TYPE(GesturePinchEnd);
403       CASE_TYPE(GesturePinchUpdate);
404       CASE_TYPE(TouchStart);
405       CASE_TYPE(TouchMove);
406       CASE_TYPE(TouchEnd);
407       CASE_TYPE(TouchCancel);
408       CASE_TYPE(TouchScrollStarted);
409       CASE_TYPE(PointerDown);
410       CASE_TYPE(PointerUp);
411       CASE_TYPE(PointerMove);
412       CASE_TYPE(PointerRawUpdate);
413       CASE_TYPE(PointerCancel);
414       CASE_TYPE(PointerCausedUaAction);
415     }
416 #undef CASE_TYPE
417     NOTREACHED();
418     return "";
419   }
420 
FrameScale()421   float FrameScale() const { return frame_scale_; }
SetFrameScale(float scale)422   void SetFrameScale(float scale) { frame_scale_ = scale; }
423 
FrameTranslate()424   gfx::Vector2dF FrameTranslate() const { return frame_translate_; }
SetFrameTranslate(const gfx::Vector2dF & translate)425   void SetFrameTranslate(const gfx::Vector2dF& translate) {
426     frame_translate_ = translate;
427   }
428 
GetType()429   Type GetType() const { return type_; }
SetType(Type type_param)430   void SetType(Type type_param) { type_ = type_param; }
431 
GetModifiers()432   int GetModifiers() const { return modifiers_; }
SetModifiers(int modifiers_param)433   void SetModifiers(int modifiers_param) { modifiers_ = modifiers_param; }
434 
TimeStamp()435   base::TimeTicks TimeStamp() const { return time_stamp_; }
SetTimeStamp(base::TimeTicks time_stamp)436   void SetTimeStamp(base::TimeTicks time_stamp) { time_stamp_ = time_stamp; }
437 
SetTargetFrameMovedRecently()438   void SetTargetFrameMovedRecently() {
439     modifiers_ |= kTargetFrameMovedRecently;
440   }
441 
SetScrollbarManipulationHandledOnCompositorThread()442   void SetScrollbarManipulationHandledOnCompositorThread() {
443     modifiers_ |= kScrollbarManipulationHandledOnCompositorThread;
444   }
445 
446   virtual ~WebInputEvent() = default;
447 
448   virtual std::unique_ptr<WebInputEvent> Clone() const = 0;
449 
450  protected:
451   // The root frame scale.
452   float frame_scale_ = 1;
453 
454   // The root frame translation (applied post scale).
455   gfx::Vector2dF frame_translate_;
456 
WebInputEvent(Type type,int modifiers,base::TimeTicks time_stamp)457   WebInputEvent(Type type, int modifiers, base::TimeTicks time_stamp)
458       : time_stamp_(time_stamp), type_(type), modifiers_(modifiers) {}
459 
WebInputEvent()460   WebInputEvent() { time_stamp_ = base::TimeTicks(); }
461 
462   // Event time since platform start with microsecond resolution.
463   base::TimeTicks time_stamp_;
464   Type type_ = kUndefined;
465   int modifiers_ = kNoModifiers;
466 };
467 
468 }  // namespace blink
469 
470 #endif
471