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/notreached.h"
39 #include "base/time/time.h"
40 #include "third_party/blink/public/common/common_export.h"
41 #include "third_party/blink/public/mojom/input/input_event.mojom-shared.h"
42 #include "ui/events/types/event_type.h"
43 #include "ui/events/types/scroll_input_type.h"
44 #include "ui/gfx/geometry/point_f.h"
45 #include "ui/gfx/geometry/vector2d_f.h"
46 
47 namespace blink {
48 
49 // WebInputEvent --------------------------------------------------------------
50 
51 class BLINK_COMMON_EXPORT WebInputEvent {
52  public:
53   // When we use an input method (or an input method editor), we receive
54   // two events for a keypress. The former event is a keydown, which
55   // provides a keycode, and the latter is a textinput, which provides
56   // a character processed by an input method. (The mapping from a
57   // keycode to a character code is not trivial for non-English
58   // keyboards.)
59   // To support input methods, Safari sends keydown events to WebKit for
60   // filtering. WebKit sends filtered keydown events back to Safari,
61   // which sends them to input methods.
62   // Unfortunately, it is hard to apply this design to Chrome because of
63   // our multiprocess architecture. An input method is running in a
64   // browser process. On the other hand, WebKit is running in a renderer
65   // process. So, this design results in increasing IPC messages.
66   // To support input methods without increasing IPC messages, Chrome
67   // handles keyboard events in a browser process and send asynchronous
68   // input events (to be translated to DOM events) to a renderer
69   // process.
70   // This design is mostly the same as the one of Windows and Mac Carbon.
71   // So, for what it's worth, our Linux and Mac front-ends emulate our
72   // Windows front-end. To emulate our Windows front-end, we can share
73   // our back-end code among Windows, Linux, and Mac.
74   // TODO(hbono): Issue 18064: remove the KeyDown type since it isn't
75   // used in Chrome any longer.
76 
77   using Type = blink::mojom::EventType;
78 
79   // The modifier constants cannot change their values since pepper
80   // does a 1-1 mapping of its values; see
81   // content/renderer/pepper/event_conversion.cc
82   //
83   // A Java counterpart will be generated for this enum.
84   // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.blink_public.web
85   // GENERATED_JAVA_CLASS_NAME_OVERRIDE: WebInputEventModifier
86   enum Modifiers {
87     // modifiers for all events:
88     kShiftKey = 1 << 0,
89     kControlKey = 1 << 1,
90     kAltKey = 1 << 2,
91     kMetaKey = 1 << 3,
92 
93     // modifiers for keyboard events:
94     kIsKeyPad = 1 << 4,
95     kIsAutoRepeat = 1 << 5,
96 
97     // modifiers for mouse events:
98     kLeftButtonDown = 1 << 6,
99     kMiddleButtonDown = 1 << 7,
100     kRightButtonDown = 1 << 8,
101 
102     // Toggle modifers for all events.
103     kCapsLockOn = 1 << 9,
104     kNumLockOn = 1 << 10,
105 
106     kIsLeft = 1 << 11,
107     kIsRight = 1 << 12,
108 
109     // Indicates that an event was generated on the touch screen while
110     // touch accessibility is enabled, so the event should be handled
111     // by accessibility code first before normal input event processing.
112     kIsTouchAccessibility = 1 << 13,
113 
114     kIsComposing = 1 << 14,
115 
116     kAltGrKey = 1 << 15,
117     kFnKey = 1 << 16,
118     kSymbolKey = 1 << 17,
119 
120     kScrollLockOn = 1 << 18,
121 
122     // Whether this is a compatibility event generated due to a
123     // native touch event. Mouse events generated from touch
124     // events will set this.
125     kIsCompatibilityEventForTouch = 1 << 19,
126 
127     kBackButtonDown = 1 << 20,
128     kForwardButtonDown = 1 << 21,
129 
130     // Represents movement as a result of content changing under the cursor,
131     // not actual physical movement of the pointer
132     kRelativeMotionEvent = 1 << 22,
133 
134     // Indication this event was injected by the devtools.
135     // TODO(dtapuska): Remove this flag once we are able to bind callbacks
136     // in event sending.
137     kFromDebugger = 1 << 23,
138 
139     // Indicates this event is targeting an OOPIF, and the iframe or one of its
140     // ancestor frames moved within its embedding page's viewport recently.
141     kTargetFrameMovedRecently = 1 << 24,
142 
143     // When an event is forwarded to the main thread, this modifier will tell if
144     // the event was already handled by the compositor thread or not. Based on
145     // this, the decision of whether or not the main thread should handle this
146     // event for the scrollbar can then be made.
147     kScrollbarManipulationHandledOnCompositorThread = 1 << 25,
148 
149     // The set of non-stateful modifiers that specifically change the
150     // interpretation of the key being pressed. For example; IsLeft,
151     // IsRight, IsComposing don't change the meaning of the key
152     // being pressed. NumLockOn, ScrollLockOn, CapsLockOn are stateful
153     // and don't indicate explicit depressed state.
154     kKeyModifiers = kSymbolKey | kFnKey | kAltGrKey | kMetaKey | kAltKey |
155                     kControlKey | kShiftKey,
156 
157     kNoModifiers = 0,
158   };
159 
160   using DispatchType = mojom::DispatchType;
161 
162   // The rail mode for a wheel event specifies the axis on which scrolling is
163   // expected to stick. If this axis is set to Free, then scrolling is not
164   // stuck to any axis.
165   enum RailsMode {
166     kRailsModeFree = 0,
167     kRailsModeHorizontal = 1,
168     kRailsModeVertical = 2,
169   };
170 
171   static const int kInputModifiers =
172       kShiftKey | kControlKey | kAltKey | kMetaKey;
173 
GetStaticTimeStampForTests()174   static constexpr base::TimeTicks GetStaticTimeStampForTests() {
175     // Note: intentionally use a relatively large delta from base::TimeTicks ==
176     // 0. Otherwise, code that tracks the time ticks of the last event that
177     // happened and computes a delta might get confused when the testing
178     // timestamp is near 0, as the computed delta may very well be under the
179     // delta threshhold.
180     //
181     // TODO(dcheng): This really shouldn't use FromInternalValue(), but
182     // constexpr support for time operations is a bit busted...
183     return base::TimeTicks::FromInternalValue(123'000'000);
184   }
185 
186   // Returns true if the WebInputEvent |type| is a mouse event.
IsMouseEventType(WebInputEvent::Type type)187   static bool IsMouseEventType(WebInputEvent::Type type) {
188     return Type::kMouseTypeFirst <= type && type <= Type::kMouseTypeLast;
189   }
190 
191   // Returns true if the WebInputEvent |type| is a keyboard event.
IsKeyboardEventType(WebInputEvent::Type type)192   static bool IsKeyboardEventType(WebInputEvent::Type type) {
193     return Type::kKeyboardTypeFirst <= type && type <= Type::kKeyboardTypeLast;
194   }
195 
196   // Returns true if the WebInputEvent |type| is a touch event.
IsTouchEventType(WebInputEvent::Type type)197   static bool IsTouchEventType(WebInputEvent::Type type) {
198     return Type::kTouchTypeFirst <= type && type <= Type::kTouchTypeLast;
199   }
200 
201   // Returns true if the WebInputEvent is a gesture event.
IsGestureEventType(WebInputEvent::Type type)202   static bool IsGestureEventType(WebInputEvent::Type type) {
203     return Type::kGestureTypeFirst <= type && type <= Type::kGestureTypeLast;
204   }
205 
206   // Returns true if the WebInputEvent |type| is a pointer event.
IsPointerEventType(WebInputEvent::Type type)207   static bool IsPointerEventType(WebInputEvent::Type type) {
208     return Type::kPointerTypeFirst <= type && type <= Type::kPointerTypeLast;
209   }
210 
IsSameEventClass(const WebInputEvent & other)211   bool IsSameEventClass(const WebInputEvent& other) const {
212     if (IsMouseEventType(type_))
213       return IsMouseEventType(other.type_);
214     if (IsGestureEventType(type_))
215       return IsGestureEventType(other.type_);
216     if (IsTouchEventType(type_))
217       return IsTouchEventType(other.type_);
218     if (IsKeyboardEventType(type_))
219       return IsKeyboardEventType(other.type_);
220     if (IsPointerEventType(type_))
221       return IsPointerEventType(other.type_);
222     return type_ == other.type_;
223   }
224 
IsGestureScroll()225   bool IsGestureScroll() const {
226     switch (type_) {
227       case Type::kGestureScrollBegin:
228       case Type::kGestureScrollUpdate:
229       case Type::kGestureScrollEnd:
230         return true;
231       default:
232         return false;
233     }
234   }
235 
236   // Returns true if the WebInputEvent |type| is a pinch gesture event.
IsPinchGestureEventType(WebInputEvent::Type type)237   static bool IsPinchGestureEventType(WebInputEvent::Type type) {
238     return Type::kGesturePinchTypeFirst <= type &&
239            type <= Type::kGesturePinchTypeLast;
240   }
241 
242   // Returns true if the WebInputEvent |type| is a fling gesture event.
IsFlingGestureEventType(WebInputEvent::Type type)243   static bool IsFlingGestureEventType(WebInputEvent::Type type) {
244     return Type::kGestureFlingStart <= type &&
245            type <= Type::kGestureFlingCancel;
246   }
247 
GetName(WebInputEvent::Type type)248   static const char* GetName(WebInputEvent::Type type) {
249 #define CASE_TYPE(t)              \
250   case WebInputEvent::Type::k##t: \
251     return #t
252     switch (type) {
253       CASE_TYPE(Undefined);
254       CASE_TYPE(MouseDown);
255       CASE_TYPE(MouseUp);
256       CASE_TYPE(MouseMove);
257       CASE_TYPE(MouseEnter);
258       CASE_TYPE(MouseLeave);
259       CASE_TYPE(ContextMenu);
260       CASE_TYPE(MouseWheel);
261       CASE_TYPE(RawKeyDown);
262       CASE_TYPE(KeyDown);
263       CASE_TYPE(KeyUp);
264       CASE_TYPE(Char);
265       CASE_TYPE(GestureScrollBegin);
266       CASE_TYPE(GestureScrollEnd);
267       CASE_TYPE(GestureScrollUpdate);
268       CASE_TYPE(GestureFlingStart);
269       CASE_TYPE(GestureFlingCancel);
270       CASE_TYPE(GestureShowPress);
271       CASE_TYPE(GestureTap);
272       CASE_TYPE(GestureTapUnconfirmed);
273       CASE_TYPE(GestureTapDown);
274       CASE_TYPE(GestureTapCancel);
275       CASE_TYPE(GestureDoubleTap);
276       CASE_TYPE(GestureTwoFingerTap);
277       CASE_TYPE(GestureLongPress);
278       CASE_TYPE(GestureLongTap);
279       CASE_TYPE(GesturePinchBegin);
280       CASE_TYPE(GesturePinchEnd);
281       CASE_TYPE(GesturePinchUpdate);
282       CASE_TYPE(TouchStart);
283       CASE_TYPE(TouchMove);
284       CASE_TYPE(TouchEnd);
285       CASE_TYPE(TouchCancel);
286       CASE_TYPE(TouchScrollStarted);
287       CASE_TYPE(PointerDown);
288       CASE_TYPE(PointerUp);
289       CASE_TYPE(PointerMove);
290       CASE_TYPE(PointerRawUpdate);
291       CASE_TYPE(PointerCancel);
292       CASE_TYPE(PointerCausedUaAction);
293     }
294 #undef CASE_TYPE
295     NOTREACHED();
296     return "";
297   }
298 
FrameScale()299   float FrameScale() const { return frame_scale_; }
SetFrameScale(float scale)300   void SetFrameScale(float scale) { frame_scale_ = scale; }
301 
FrameTranslate()302   gfx::Vector2dF FrameTranslate() const { return frame_translate_; }
SetFrameTranslate(const gfx::Vector2dF & translate)303   void SetFrameTranslate(const gfx::Vector2dF& translate) {
304     frame_translate_ = translate;
305   }
306 
GetType()307   Type GetType() const { return type_; }
SetType(Type type_param)308   void SetType(Type type_param) { type_ = type_param; }
309 
GetModifiers()310   int GetModifiers() const { return modifiers_; }
SetModifiers(int modifiers_param)311   void SetModifiers(int modifiers_param) { modifiers_ = modifiers_param; }
312 
TimeStamp()313   base::TimeTicks TimeStamp() const { return time_stamp_; }
SetTimeStamp(base::TimeTicks time_stamp)314   void SetTimeStamp(base::TimeTicks time_stamp) { time_stamp_ = time_stamp; }
315 
SetTargetFrameMovedRecently()316   void SetTargetFrameMovedRecently() {
317     modifiers_ |= kTargetFrameMovedRecently;
318   }
319 
SetScrollbarManipulationHandledOnCompositorThread()320   void SetScrollbarManipulationHandledOnCompositorThread() {
321     modifiers_ |= kScrollbarManipulationHandledOnCompositorThread;
322   }
323 
324   virtual ~WebInputEvent() = default;
325 
326   virtual std::unique_ptr<WebInputEvent> Clone() const = 0;
327 
328   // Returns whether the current event can be merged with the provided
329   // |event|.
330   virtual bool CanCoalesce(const blink::WebInputEvent& event) const = 0;
331 
332   // Merge the current event with attributes from |event|.
333   virtual void Coalesce(const WebInputEvent& event) = 0;
334 
335   // Returns the scroll input type if this is a scroll event; otherwise,
336   // returns base::nullopt.
337   virtual base::Optional<ui::ScrollInputType> GetScrollInputType() const;
338 
339   // Convert this WebInputEvent::Type to a ui::EventType. Note that this is
340   // not a 1:1 relationship. Multiple blink types convert to the same
341   // ui::EventType and not all types do convert.
342   ui::EventType GetTypeAsUiEventType() const;
343 
344  protected:
345   // The root frame scale.
346   float frame_scale_ = 1;
347 
348   // The root frame translation (applied post scale).
349   gfx::Vector2dF frame_translate_;
350 
WebInputEvent(Type type,int modifiers,base::TimeTicks time_stamp)351   WebInputEvent(Type type, int modifiers, base::TimeTicks time_stamp)
352       : time_stamp_(time_stamp), type_(type), modifiers_(modifiers) {}
353 
WebInputEvent()354   WebInputEvent() { time_stamp_ = base::TimeTicks(); }
355 
356   static DispatchType MergeDispatchTypes(DispatchType type_1,
357                                          DispatchType type_2);
358 
359   // Event time since platform start with microsecond resolution.
360   base::TimeTicks time_stamp_;
361   Type type_ = Type::kUndefined;
362   int modifiers_ = kNoModifiers;
363 };
364 
365 }  // namespace blink
366 
367 #endif
368