Skip to content

Commit

Permalink
Cursor Control: Add bit to scroll gestures
Browse files Browse the repository at this point in the history
We reinterpret scroll gestures conditionally for cursor control purpose.

This is done by add a new bit |kInternalPanXScrolls| to TouchAction,
This bit is suppressed by TouchAction::kPanX, i.e. we only set this bit
when TouchAction::kPanLeft or TouchAction::kPanRight is set. By default,
if an element has TouchAction::kPanX, it will be set. Therefore,
TouchAction::kAuto has this bit as well. When |kInternalPanXScrolls|
is set, we don't do cursor control.

When an element is flagged as editable, we remove |kInternalPanXScrolls|
bit for that element and its descendants. Therefore, if there is an
editable element, because it is not equal to TouchAction::kAuto, the
browser side will get a signal and set |has_touch_event_handler_| as
true in TouchActionFilter.

In painting stage, we also calculate horizontal scrollable information
for an element, if an element or its ancestor is horizontal scrollable,
we put |kInternalPanXScrolls| bit back to the corresponding
TouchActionRegion to disable cursor control.

When a touch start event happens, it will be dispatched to the renderer
since we know there is a touch event handler, the browser will get the
compositor touch action from the compositor hit test. The event will be
further dispatched to the renderer main thread, we do another hit test,
we also need to acquire the horizontal scrollable information for the
hit test result element, so we could decide to put
|kInternalPanXScrolls| back to the main thread touch action or not.
Main thread touch action will also be sent to the browser.

When a GestureScrollBegin generates, we use the compositor touch action
and the main thread touch action to filter it, because compositor touch
action is permissive, if we don't have |kInternalPanXScrolls| bit on
the touch action, we delay the event until we get the main thread
touch action.

If |kInternalPanXScrolls| is not set and |kPanX| is allowed and this is
a horizontal scroll, we set the GestureScrollBegin's |cursor_control|
flag to true, therefore, the whole scroll gesture sequence will be used
as cursor control.

In this way, we fulfilled multiple design goals:
1) cursor control can be disabled by not set touch-action: pan-x
2) cursor control can be disabled by register a non-passive event
handler of the touchstart event and calling event.preventDefault()
inside.
3) cursor control is disabled when the element is horizontally
scrollable.
4) cursor control is not interleaved with scroll.

Bug: 1126778
Change-Id: I7a1c58f60740ff87dbee460524de66c67878dc64
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2435324
Commit-Queue: Shimi Zhang <ctzsm@chromium.org>
Reviewed-by: David Bokan <bokan@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Bo <boliu@chromium.org>
Reviewed-by: Robert Flack <flackr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#822908}
  • Loading branch information
Shimi Zhang authored and Commit Bot committed Oct 31, 2020
1 parent 8add095 commit 9287e2c
Show file tree
Hide file tree
Showing 28 changed files with 776 additions and 140 deletions.
14 changes: 12 additions & 2 deletions cc/input/touch_action.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,15 @@ enum class TouchAction {
kPinchZoom = 0x10,
kManipulation = kPan | kPinchZoom,
kDoubleTapZoom = 0x20,
kAuto = kManipulation | kDoubleTapZoom,
kMax = (1 << 6) - 1
// Used by swipe to move cursor feature. This is only used internally
// for swipe to move cursor feature and it is not a web-visible value. When
// an element have this bit or doesn't have kPanX, we will disable swipe to
// move cursor feature for that element. When the element is contenteditable
// and it doesn't have a horizontal scrollable ancestor (including
// itself), we don't set this bit.
kInternalPanXScrolls = 0x40,
kAuto = kManipulation | kDoubleTapZoom | kInternalPanXScrolls,
kMax = (1 << 7) - 1
};

inline TouchAction operator|(TouchAction a, TouchAction b) {
Expand All @@ -58,6 +65,9 @@ inline TouchAction operator~(TouchAction touch_action) {
}

inline const char* TouchActionToString(TouchAction touch_action) {
// we skip printing internal panx scrolls since it's not a web exposed touch
// action field.
touch_action &= ~TouchAction::kInternalPanXScrolls;
switch (static_cast<int>(touch_action)) {
case 0:
return "NONE";
Expand Down
Loading

0 comments on commit 9287e2c

Please sign in to comment.