blob: c599513dd8f85ec259e0b240ce51053b043028e5 [file] [log] [blame]
/*
* Copyright (C) 2009 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_INPUT_WEB_INPUT_EVENT_H_
#define THIRD_PARTY_BLINK_PUBLIC_COMMON_INPUT_WEB_INPUT_EVENT_H_
#include <string.h>
#include <memory>
#include "base/notreached.h"
#include "base/time/time.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/mojom/input/input_event.mojom-shared.h"
#include "ui/events/types/event_type.h"
#include "ui/events/types/scroll_input_type.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/vector2d_f.h"
namespace blink {
// WebInputEvent --------------------------------------------------------------
class BLINK_COMMON_EXPORT WebInputEvent {
public:
// When we use an input method (or an input method editor), we receive
// two events for a keypress. The former event is a keydown, which
// provides a keycode, and the latter is a textinput, which provides
// a character processed by an input method. (The mapping from a
// keycode to a character code is not trivial for non-English
// keyboards.)
// To support input methods, Safari sends keydown events to WebKit for
// filtering. WebKit sends filtered keydown events back to Safari,
// which sends them to input methods.
// Unfortunately, it is hard to apply this design to Chrome because of
// our multiprocess architecture. An input method is running in a
// browser process. On the other hand, WebKit is running in a renderer
// process. So, this design results in increasing IPC messages.
// To support input methods without increasing IPC messages, Chrome
// handles keyboard events in a browser process and send asynchronous
// input events (to be translated to DOM events) to a renderer
// process.
// This design is mostly the same as the one of Windows and Mac Carbon.
// So, for what it's worth, our Linux and Mac front-ends emulate our
// Windows front-end. To emulate our Windows front-end, we can share
// our back-end code among Windows, Linux, and Mac.
// TODO(hbono): Issue 18064: remove the KeyDown type since it isn't
// used in Chrome any longer.
using Type = blink::mojom::EventType;
// The modifier constants cannot change their values since pepper
// does a 1-1 mapping of its values; see
// content/renderer/pepper/event_conversion.cc
//
// A Java counterpart will be generated for this enum.
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.blink_public.web
// GENERATED_JAVA_CLASS_NAME_OVERRIDE: WebInputEventModifier
enum Modifiers {
// modifiers for all events:
kShiftKey = 1 << 0,
kControlKey = 1 << 1,
kAltKey = 1 << 2,
kMetaKey = 1 << 3,
// modifiers for keyboard events:
kIsKeyPad = 1 << 4,
kIsAutoRepeat = 1 << 5,
// modifiers for mouse events:
kLeftButtonDown = 1 << 6,
kMiddleButtonDown = 1 << 7,
kRightButtonDown = 1 << 8,
// Toggle modifers for all events.
kCapsLockOn = 1 << 9,
kNumLockOn = 1 << 10,
kIsLeft = 1 << 11,
kIsRight = 1 << 12,
// Indicates that an event was generated on the touch screen while
// touch accessibility is enabled, so the event should be handled
// by accessibility code first before normal input event processing.
kIsTouchAccessibility = 1 << 13,
kIsComposing = 1 << 14,
kAltGrKey = 1 << 15,
kFnKey = 1 << 16,
kSymbolKey = 1 << 17,
kScrollLockOn = 1 << 18,
// Whether this is a compatibility event generated due to a
// native touch event. Mouse events generated from touch
// events will set this.
kIsCompatibilityEventForTouch = 1 << 19,
kBackButtonDown = 1 << 20,
kForwardButtonDown = 1 << 21,
// Represents movement as a result of content changing under the cursor,
// not actual physical movement of the pointer
kRelativeMotionEvent = 1 << 22,
// Indication this event was injected by the devtools.
// TODO(dtapuska): Remove this flag once we are able to bind callbacks
// in event sending.
kFromDebugger = 1 << 23,
// Indicates this event is targeting an OOPIF, and the iframe or one of its
// ancestor frames moved within its embedding page's viewport recently.
kTargetFrameMovedRecently = 1 << 24,
// When an event is forwarded to the main thread, this modifier will tell if
// the event was already handled by the compositor thread or not. Based on
// this, the decision of whether or not the main thread should handle this
// event for the scrollbar can then be made.
kScrollbarManipulationHandledOnCompositorThread = 1 << 25,
// The set of non-stateful modifiers that specifically change the
// interpretation of the key being pressed. For example; IsLeft,
// IsRight, IsComposing don't change the meaning of the key
// being pressed. NumLockOn, ScrollLockOn, CapsLockOn are stateful
// and don't indicate explicit depressed state.
kKeyModifiers = kSymbolKey | kFnKey | kAltGrKey | kMetaKey | kAltKey |
kControlKey | kShiftKey,
kNoModifiers = 0,
};
using DispatchType = mojom::DispatchType;
// The rail mode for a wheel event specifies the axis on which scrolling is
// expected to stick. If this axis is set to Free, then scrolling is not
// stuck to any axis.
enum RailsMode {
kRailsModeFree = 0,
kRailsModeHorizontal = 1,
kRailsModeVertical = 2,
};
static const int kInputModifiers =
kShiftKey | kControlKey | kAltKey | kMetaKey;
static constexpr base::TimeTicks GetStaticTimeStampForTests() {
// Note: intentionally use a relatively large delta from base::TimeTicks ==
// 0. Otherwise, code that tracks the time ticks of the last event that
// happened and computes a delta might get confused when the testing
// timestamp is near 0, as the computed delta may very well be under the
// delta threshhold.
//
// TODO(dcheng): This really shouldn't use FromInternalValue(), but
// constexpr support for time operations is a bit busted...
return base::TimeTicks::FromInternalValue(123'000'000);
}
// Returns true if the WebInputEvent |type| is a mouse event.
static bool IsMouseEventType(WebInputEvent::Type type) {
return Type::kMouseTypeFirst <= type && type <= Type::kMouseTypeLast;
}
// Returns true if the WebInputEvent |type| is a keyboard event.
static bool IsKeyboardEventType(WebInputEvent::Type type) {
return Type::kKeyboardTypeFirst <= type && type <= Type::kKeyboardTypeLast;
}
// Returns true if the WebInputEvent |type| is a touch event.
static bool IsTouchEventType(WebInputEvent::Type type) {
return Type::kTouchTypeFirst <= type && type <= Type::kTouchTypeLast;
}
// Returns true if the WebInputEvent is a gesture event.
static bool IsGestureEventType(WebInputEvent::Type type) {
return Type::kGestureTypeFirst <= type && type <= Type::kGestureTypeLast;
}
// Returns true if the WebInputEvent |type| is a pointer event.
static bool IsPointerEventType(WebInputEvent::Type type) {
return Type::kPointerTypeFirst <= type && type <= Type::kPointerTypeLast;
}
bool IsSameEventClass(const WebInputEvent& other) const {
if (IsMouseEventType(type_))
return IsMouseEventType(other.type_);
if (IsGestureEventType(type_))
return IsGestureEventType(other.type_);
if (IsTouchEventType(type_))
return IsTouchEventType(other.type_);
if (IsKeyboardEventType(type_))
return IsKeyboardEventType(other.type_);
if (IsPointerEventType(type_))
return IsPointerEventType(other.type_);
return type_ == other.type_;
}
bool IsGestureScroll() const {
switch (type_) {
case Type::kGestureScrollBegin:
case Type::kGestureScrollUpdate:
case Type::kGestureScrollEnd:
return true;
default:
return false;
}
}
// Returns true if the WebInputEvent |type| is a pinch gesture event.
static bool IsPinchGestureEventType(WebInputEvent::Type type) {
return Type::kGesturePinchTypeFirst <= type &&
type <= Type::kGesturePinchTypeLast;
}
// Returns true if the WebInputEvent |type| is a fling gesture event.
static bool IsFlingGestureEventType(WebInputEvent::Type type) {
return Type::kGestureFlingStart <= type &&
type <= Type::kGestureFlingCancel;
}
static const char* GetName(WebInputEvent::Type type) {
#define CASE_TYPE(t) \
case WebInputEvent::Type::k##t: \
return #t
switch (type) {
CASE_TYPE(Undefined);
CASE_TYPE(MouseDown);
CASE_TYPE(MouseUp);
CASE_TYPE(MouseMove);
CASE_TYPE(MouseEnter);
CASE_TYPE(MouseLeave);
CASE_TYPE(ContextMenu);
CASE_TYPE(MouseWheel);
CASE_TYPE(RawKeyDown);
CASE_TYPE(KeyDown);
CASE_TYPE(KeyUp);
CASE_TYPE(Char);
CASE_TYPE(GestureScrollBegin);
CASE_TYPE(GestureScrollEnd);
CASE_TYPE(GestureScrollUpdate);
CASE_TYPE(GestureFlingStart);
CASE_TYPE(GestureFlingCancel);
CASE_TYPE(GestureShowPress);
CASE_TYPE(GestureTap);
CASE_TYPE(GestureTapUnconfirmed);
CASE_TYPE(GestureTapDown);
CASE_TYPE(GestureTapCancel);
CASE_TYPE(GestureDoubleTap);
CASE_TYPE(GestureTwoFingerTap);
CASE_TYPE(GestureLongPress);
CASE_TYPE(GestureLongTap);
CASE_TYPE(GesturePinchBegin);
CASE_TYPE(GesturePinchEnd);
CASE_TYPE(GesturePinchUpdate);
CASE_TYPE(TouchStart);
CASE_TYPE(TouchMove);
CASE_TYPE(TouchEnd);
CASE_TYPE(TouchCancel);
CASE_TYPE(TouchScrollStarted);
CASE_TYPE(PointerDown);
CASE_TYPE(PointerUp);
CASE_TYPE(PointerMove);
CASE_TYPE(PointerRawUpdate);
CASE_TYPE(PointerCancel);
CASE_TYPE(PointerCausedUaAction);
}
#undef CASE_TYPE
NOTREACHED();
return "";
}
float FrameScale() const { return frame_scale_; }
void SetFrameScale(float scale) { frame_scale_ = scale; }
gfx::Vector2dF FrameTranslate() const { return frame_translate_; }
void SetFrameTranslate(const gfx::Vector2dF& translate) {
frame_translate_ = translate;
}
Type GetType() const { return type_; }
void SetType(Type type_param) { type_ = type_param; }
int GetModifiers() const { return modifiers_; }
void SetModifiers(int modifiers_param) { modifiers_ = modifiers_param; }
base::TimeTicks TimeStamp() const { return time_stamp_; }
void SetTimeStamp(base::TimeTicks time_stamp) { time_stamp_ = time_stamp; }
void SetTargetFrameMovedRecently() {
modifiers_ |= kTargetFrameMovedRecently;
}
void SetScrollbarManipulationHandledOnCompositorThread() {
modifiers_ |= kScrollbarManipulationHandledOnCompositorThread;
}
virtual ~WebInputEvent() = default;
virtual std::unique_ptr<WebInputEvent> Clone() const = 0;
// Returns whether the current event can be merged with the provided
// |event|.
virtual bool CanCoalesce(const blink::WebInputEvent& event) const = 0;
// Merge the current event with attributes from |event|.
virtual void Coalesce(const WebInputEvent& event) = 0;
// Returns the scroll input type if this is a scroll event; otherwise,
// returns base::nullopt.
virtual base::Optional<ui::ScrollInputType> GetScrollInputType() const;
// Convert this WebInputEvent::Type to a ui::EventType. Note that this is
// not a 1:1 relationship. Multiple blink types convert to the same
// ui::EventType and not all types do convert.
ui::EventType GetTypeAsUiEventType() const;
protected:
// The root frame scale.
float frame_scale_ = 1;
// The root frame translation (applied post scale).
gfx::Vector2dF frame_translate_;
WebInputEvent(Type type, int modifiers, base::TimeTicks time_stamp)
: time_stamp_(time_stamp), type_(type), modifiers_(modifiers) {}
WebInputEvent() { time_stamp_ = base::TimeTicks(); }
static DispatchType MergeDispatchTypes(DispatchType type_1,
DispatchType type_2);
// Event time since platform start with microsecond resolution.
base::TimeTicks time_stamp_;
Type type_ = Type::kUndefined;
int modifiers_ = kNoModifiers;
};
} // namespace blink
#endif