| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/renderer_host/input/touch_action_filter.h" |
| #include "content/browser/renderer_host/event_with_latency_info.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h" |
| #include "third_party/blink/public/common/input/web_input_event.h" |
| #include "third_party/blink/public/mojom/input/input_event_result.mojom-shared.h" |
| #include "ui/events/blink/blink_features.h" |
| |
| using blink::SyntheticWebGestureEventBuilder; |
| using blink::WebGestureEvent; |
| using blink::WebInputEvent; |
| |
| namespace content { |
| namespace { |
| |
| const blink::WebGestureDevice kSourceDevice = |
| blink::WebGestureDevice::kTouchscreen; |
| |
| } // namespace |
| |
| class TouchActionFilterTest : public testing::Test { |
| public: |
| TouchActionFilterTest() { filter_.OnHasTouchEventHandlers(true); } |
| ~TouchActionFilterTest() override = default; |
| |
| protected: |
| base::Optional<cc::TouchAction> ActiveTouchAction() const { |
| return filter_.active_touch_action_; |
| } |
| void ResetTouchAction() { filter_.ResetTouchAction(); } |
| void ResetActiveTouchAction() { filter_.active_touch_action_.reset(); } |
| void ResetCompositorAllowedTouchAction() { |
| filter_.compositor_allowed_touch_action_ = cc::TouchAction::kAuto; |
| } |
| void SetNoDeferredEvents() { filter_.has_deferred_events_ = false; } |
| void SetGestureSequenceInProgress() { |
| filter_.gesture_sequence_in_progress_ = true; |
| } |
| void ResetGestureSequenceInProgress() { |
| filter_.gesture_sequence_in_progress_ = false; |
| } |
| void PanTest(cc::TouchAction action, |
| float scroll_x, |
| float scroll_y, |
| float dx, |
| float dy, |
| float expected_dx, |
| float expected_dy) { |
| WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapDown, kSourceDevice); |
| WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureScrollEnd, kSourceDevice); |
| |
| { |
| // Scrolls with no direction hint are permitted in the |action| direction. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(action); |
| filter_.IncreaseActiveTouches(); |
| |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin(0, 0, |
| kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| |
| WebGestureEvent scroll_update = |
| SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, dy, 0, |
| kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(expected_dx, scroll_update.data.scroll_update.delta_x); |
| EXPECT_EQ(expected_dy, scroll_update.data.scroll_update.delta_y); |
| |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.DecreaseActiveTouches(); |
| } |
| |
| { |
| // Scrolls biased towards the touch-action axis are permitted. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(action); |
| filter_.IncreaseActiveTouches(); |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin(scroll_x, scroll_y, |
| kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| |
| WebGestureEvent scroll_update = |
| SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, dy, 0, |
| kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(expected_dx, scroll_update.data.scroll_update.delta_x); |
| EXPECT_EQ(expected_dy, scroll_update.data.scroll_update.delta_y); |
| |
| // Ensure that scrolls in the opposite direction are not filtered once |
| // scrolling has started. (Once scrolling is started, the direction may |
| // be reversed by the user even if scrolls that start in the reversed |
| // direction are disallowed. |
| WebGestureEvent scroll_update2 = |
| SyntheticWebGestureEventBuilder::BuildScrollUpdate(-dx, -dy, 0, |
| kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update2), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(-expected_dx, scroll_update2.data.scroll_update.delta_x); |
| EXPECT_EQ(-expected_dy, scroll_update2.data.scroll_update.delta_y); |
| |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.DecreaseActiveTouches(); |
| } |
| |
| { |
| // Scrolls biased towards the perpendicular of the touch-action axis are |
| // suppressed entirely. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(action); |
| filter_.IncreaseActiveTouches(); |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin(scroll_y, scroll_x, |
| kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| |
| WebGestureEvent scroll_update = |
| SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, dy, 0, |
| kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(dx, scroll_update.data.scroll_update.delta_x); |
| EXPECT_EQ(dy, scroll_update.data.scroll_update.delta_y); |
| |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| filter_.DecreaseActiveTouches(); |
| } |
| } |
| |
| void PanTestForUnidirectionalTouchAction(cc::TouchAction action, |
| float scroll_x, |
| float scroll_y) { |
| WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapDown, kSourceDevice); |
| WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureScrollEnd, kSourceDevice); |
| |
| { |
| // Scrolls towards the touch-action direction are permitted. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(action); |
| filter_.IncreaseActiveTouches(); |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin(scroll_x, scroll_y, |
| kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| |
| WebGestureEvent scroll_update = |
| SyntheticWebGestureEventBuilder::BuildScrollUpdate(scroll_x, scroll_y, |
| 0, kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.DecreaseActiveTouches(); |
| } |
| |
| { |
| // Scrolls towards the exact opposite of the touch-action direction are |
| // suppressed entirely. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(action); |
| filter_.IncreaseActiveTouches(); |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin( |
| -scroll_x, -scroll_y, kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| |
| WebGestureEvent scroll_update = |
| SyntheticWebGestureEventBuilder::BuildScrollUpdate( |
| -scroll_x, -scroll_y, 0, kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| filter_.DecreaseActiveTouches(); |
| } |
| |
| { |
| // Scrolls towards the diagonal opposite of the touch-action direction are |
| // suppressed entirely. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(action); |
| filter_.IncreaseActiveTouches(); |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin( |
| -scroll_x - scroll_y, -scroll_x - scroll_y, kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| |
| WebGestureEvent scroll_update = |
| SyntheticWebGestureEventBuilder::BuildScrollUpdate( |
| -scroll_x - scroll_y, -scroll_x - scroll_y, 0, kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| filter_.DecreaseActiveTouches(); |
| } |
| } |
| TouchActionFilter filter_; |
| }; |
| |
| TEST_F(TouchActionFilterTest, SimpleFilter) { |
| WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapDown, kSourceDevice); |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin(2, 3, kSourceDevice); |
| const float kDeltaX = 5; |
| const float kDeltaY = 10; |
| WebGestureEvent scroll_update = |
| SyntheticWebGestureEventBuilder::BuildScrollUpdate(kDeltaX, kDeltaY, 0, |
| kSourceDevice); |
| WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureScrollEnd, kSourceDevice); |
| |
| // cc::TouchAction::kAuto doesn't cause any filtering. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kAuto); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(kDeltaX, scroll_update.data.scroll_update.delta_x); |
| EXPECT_EQ(kDeltaY, scroll_update.data.scroll_update.delta_y); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.DecreaseActiveTouches(); |
| |
| // cc::TouchAction::kNone filters out all scroll events, but no other events. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kNone); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(kDeltaX, scroll_update.data.scroll_update.delta_x); |
| EXPECT_EQ(kDeltaY, scroll_update.data.scroll_update.delta_y); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| filter_.DecreaseActiveTouches(); |
| |
| // When a new touch sequence begins, the state is reset. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kAuto); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.DecreaseActiveTouches(); |
| |
| // Setting touch action doesn't impact any in-progress gestures. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kAuto); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.OnSetTouchAction(cc::TouchAction::kNone); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.DecreaseActiveTouches(); |
| |
| // And the state is still cleared for the next gesture. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kAuto); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.DecreaseActiveTouches(); |
| |
| // Changing the touch action during a gesture has no effect. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kNone); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| filter_.OnSetTouchAction(cc::TouchAction::kAuto); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(kDeltaX, scroll_update.data.scroll_update.delta_x); |
| EXPECT_EQ(kDeltaY, scroll_update.data.scroll_update.delta_y); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| filter_.DecreaseActiveTouches(); |
| } |
| |
| TEST_F(TouchActionFilterTest, PanLeft) { |
| const float kDX = 5; |
| const float kDY = 10; |
| const float kScrollX = 7; |
| const float kScrollY = 6; |
| |
| PanTest(cc::TouchAction::kPanLeft, kScrollX, kScrollY, kDX, kDY, kDX, 0); |
| PanTestForUnidirectionalTouchAction(cc::TouchAction::kPanLeft, kScrollX, 0); |
| } |
| |
| TEST_F(TouchActionFilterTest, PanRight) { |
| const float kDX = 5; |
| const float kDY = 10; |
| const float kScrollX = -7; |
| const float kScrollY = 6; |
| |
| PanTest(cc::TouchAction::kPanRight, kScrollX, kScrollY, kDX, kDY, kDX, 0); |
| PanTestForUnidirectionalTouchAction(cc::TouchAction::kPanRight, kScrollX, 0); |
| } |
| |
| TEST_F(TouchActionFilterTest, PanX) { |
| const float kDX = 5; |
| const float kDY = 10; |
| const float kScrollX = 7; |
| const float kScrollY = 6; |
| |
| PanTest(cc::TouchAction::kPanX, kScrollX, kScrollY, kDX, kDY, kDX, 0); |
| } |
| |
| TEST_F(TouchActionFilterTest, PanUp) { |
| const float kDX = 5; |
| const float kDY = 10; |
| const float kScrollX = 6; |
| const float kScrollY = 7; |
| |
| PanTest(cc::TouchAction::kPanUp, kScrollX, kScrollY, kDX, kDY, 0, kDY); |
| PanTestForUnidirectionalTouchAction(cc::TouchAction::kPanUp, 0, kScrollY); |
| } |
| |
| TEST_F(TouchActionFilterTest, PanDown) { |
| const float kDX = 5; |
| const float kDY = 10; |
| const float kScrollX = 6; |
| const float kScrollY = -7; |
| |
| PanTest(cc::TouchAction::kPanDown, kScrollX, kScrollY, kDX, kDY, 0, kDY); |
| PanTestForUnidirectionalTouchAction(cc::TouchAction::kPanDown, 0, kScrollY); |
| } |
| |
| TEST_F(TouchActionFilterTest, PanY) { |
| const float kDX = 5; |
| const float kDY = 10; |
| const float kScrollX = 6; |
| const float kScrollY = 7; |
| |
| PanTest(cc::TouchAction::kPanY, kScrollX, kScrollY, kDX, kDY, 0, kDY); |
| } |
| |
| TEST_F(TouchActionFilterTest, PanXY) { |
| const float kDX = 5; |
| const float kDY = 10; |
| WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapDown, kSourceDevice); |
| WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureScrollEnd, kSourceDevice); |
| |
| { |
| // Scrolls hinted in the X axis are permitted and unmodified. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kPan); |
| filter_.IncreaseActiveTouches(); |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin(-7, 6, kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| |
| WebGestureEvent scroll_update = |
| SyntheticWebGestureEventBuilder::BuildScrollUpdate(kDX, kDY, 0, |
| kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(kDX, scroll_update.data.scroll_update.delta_x); |
| EXPECT_EQ(kDY, scroll_update.data.scroll_update.delta_y); |
| |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.DecreaseActiveTouches(); |
| } |
| |
| { |
| // Scrolls hinted in the Y axis are permitted and unmodified. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kPan); |
| filter_.IncreaseActiveTouches(); |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin(-6, 7, kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| |
| WebGestureEvent scroll_update = |
| SyntheticWebGestureEventBuilder::BuildScrollUpdate(kDX, kDY, 0, |
| kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(kDX, scroll_update.data.scroll_update.delta_x); |
| EXPECT_EQ(kDY, scroll_update.data.scroll_update.delta_y); |
| |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.DecreaseActiveTouches(); |
| } |
| |
| { |
| // A two-finger gesture is not allowed. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kPan); |
| filter_.IncreaseActiveTouches(); |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin(-6, 7, kSourceDevice, |
| 2); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| |
| WebGestureEvent scroll_update = |
| SyntheticWebGestureEventBuilder::BuildScrollUpdate(kDX, kDY, 0, |
| kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| filter_.DecreaseActiveTouches(); |
| } |
| } |
| |
| TEST_F(TouchActionFilterTest, BitMath) { |
| // Verify that the simple flag mixing properties we depend on are now |
| // trivially true. |
| EXPECT_EQ(cc::TouchAction::kNone, |
| cc::TouchAction::kNone & cc::TouchAction::kAuto); |
| EXPECT_EQ(cc::TouchAction::kNone, |
| cc::TouchAction::kPanY & cc::TouchAction::kPanX); |
| EXPECT_EQ(cc::TouchAction::kPan, |
| cc::TouchAction::kAuto & cc::TouchAction::kPan); |
| EXPECT_EQ(cc::TouchAction::kManipulation, |
| cc::TouchAction::kAuto & ~cc::TouchAction::kDoubleTapZoom); |
| EXPECT_EQ(cc::TouchAction::kPanX, |
| cc::TouchAction::kPanLeft | cc::TouchAction::kPanRight); |
| EXPECT_EQ(cc::TouchAction::kAuto, |
| cc::TouchAction::kManipulation | cc::TouchAction::kDoubleTapZoom); |
| } |
| |
| TEST_F(TouchActionFilterTest, MultiTouch) { |
| WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapDown, kSourceDevice); |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin(2, 3, kSourceDevice); |
| const float kDeltaX = 5; |
| const float kDeltaY = 10; |
| WebGestureEvent scroll_update = |
| SyntheticWebGestureEventBuilder::BuildScrollUpdate(kDeltaX, kDeltaY, 0, |
| kSourceDevice); |
| WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureScrollEnd, kSourceDevice); |
| |
| // For multiple points, the intersection is what matters. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kNone); |
| filter_.OnSetTouchAction(cc::TouchAction::kAuto); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(kDeltaX, scroll_update.data.scroll_update.delta_x); |
| EXPECT_EQ(kDeltaY, scroll_update.data.scroll_update.delta_y); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| filter_.DecreaseActiveTouches(); |
| |
| // Intersection of PAN_X and PAN_Y is NONE. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kPanX); |
| filter_.OnSetTouchAction(cc::TouchAction::kPanY); |
| filter_.OnSetTouchAction(cc::TouchAction::kPan); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| filter_.DecreaseActiveTouches(); |
| } |
| |
| class TouchActionFilterPinchTest : public testing::Test { |
| public: |
| TouchActionFilterPinchTest() = default; |
| |
| void RunTest(bool force_enable_zoom) { |
| filter_.OnHasTouchEventHandlers(true); |
| filter_.SetForceEnableZoom(force_enable_zoom); |
| |
| WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapDown, kSourceDevice); |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin(2, 3, kSourceDevice, |
| 2); |
| WebGestureEvent pinch_begin = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGesturePinchBegin, kSourceDevice); |
| WebGestureEvent pinch_update = |
| SyntheticWebGestureEventBuilder::BuildPinchUpdate(1.2f, 5, 5, 0, |
| kSourceDevice); |
| WebGestureEvent pinch_end = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGesturePinchEnd, kSourceDevice); |
| WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureScrollEnd, kSourceDevice); |
| |
| // Pinch is allowed with touch-action: auto. |
| filter_.ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kAuto); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.DecreaseActiveTouches(); |
| |
| // Pinch is not allowed with touch-action: none. |
| filter_.ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kNone); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| filter_.DecreaseActiveTouches(); |
| |
| // Pinch is not allowed with touch-action: pan-x pan-y except for force |
| // enable zoom. |
| filter_.ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kPan); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_NE(filter_.FilterGestureEvent(&scroll_begin), |
| force_enable_zoom |
| ? FilterGestureEventResult::kFilterGestureEventFiltered |
| : FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_NE(filter_.FilterGestureEvent(&pinch_begin), |
| force_enable_zoom |
| ? FilterGestureEventResult::kFilterGestureEventFiltered |
| : FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_NE(filter_.FilterGestureEvent(&pinch_update), |
| force_enable_zoom |
| ? FilterGestureEventResult::kFilterGestureEventFiltered |
| : FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_NE(filter_.FilterGestureEvent(&pinch_end), |
| force_enable_zoom |
| ? FilterGestureEventResult::kFilterGestureEventFiltered |
| : FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_NE(filter_.FilterGestureEvent(&scroll_end), |
| force_enable_zoom |
| ? FilterGestureEventResult::kFilterGestureEventFiltered |
| : FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.DecreaseActiveTouches(); |
| |
| // Pinch is allowed with touch-action: manipulation. |
| filter_.ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kManipulation); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_FALSE(filter_.drop_pinch_events_); |
| // The pinch gesture is always re-evaluated on pinch begin. |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.DecreaseActiveTouches(); |
| |
| // Pinch state is automatically reset at the end of a scroll. |
| filter_.ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kAuto); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.DecreaseActiveTouches(); |
| |
| filter_.ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kAuto); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.DecreaseActiveTouches(); |
| |
| // Scrolling is allowed when two fingers are down. |
| filter_.ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kPinchZoom); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.DecreaseActiveTouches(); |
| |
| // At double-tap-drag-zoom case, the pointer_count is 1 at GesturePinchBegin |
| // and we need to evaluate whether the gesture is allowed or not at that |
| // time. |
| scroll_begin.data.scroll_begin.pointer_count = 1; |
| filter_.ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kPinchZoom); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| filter_.DecreaseActiveTouches(); |
| } |
| |
| private: |
| TouchActionFilter filter_; |
| }; |
| |
| TEST_F(TouchActionFilterPinchTest, Pinch) { |
| RunTest(false); |
| } |
| |
| // Enables force enable zoom will override touch-action except for |
| // touch-action: none. |
| TEST_F(TouchActionFilterPinchTest, ForceEnableZoom) { |
| RunTest(true); |
| } |
| |
| TEST_F(TouchActionFilterTest, DoubleTapWithTouchActionAuto) { |
| WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapDown, kSourceDevice); |
| WebGestureEvent unconfirmed_tap = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapUnconfirmed, kSourceDevice); |
| WebGestureEvent tap_cancel = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapCancel, kSourceDevice); |
| WebGestureEvent double_tap = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureDoubleTap, kSourceDevice); |
| |
| // Double tap is allowed with touch action auto. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kAuto); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&unconfirmed_tap), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(unconfirmed_tap.GetType(), |
| WebInputEvent::Type::kGestureTapUnconfirmed); |
| // The tap cancel will come as part of the next touch sequence. |
| ResetTouchAction(); |
| // Changing the touch action for the second tap doesn't effect the behaviour |
| // of the event. |
| filter_.OnSetTouchAction(cc::TouchAction::kNone); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_cancel), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&double_tap), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| } |
| |
| TEST_F(TouchActionFilterTest, DoubleTap) { |
| WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapDown, kSourceDevice); |
| WebGestureEvent unconfirmed_tap = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapUnconfirmed, kSourceDevice); |
| WebGestureEvent tap_cancel = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapCancel, kSourceDevice); |
| WebGestureEvent double_tap = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureDoubleTap, kSourceDevice); |
| |
| // Double tap is disabled with any touch action other than auto. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kManipulation); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&unconfirmed_tap), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(WebInputEvent::Type::kGestureTap, unconfirmed_tap.GetType()); |
| // Changing the touch action for the second tap doesn't effect the behaviour |
| // of the event. The tap cancel will come as part of the next touch sequence. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kAuto); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_cancel), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&double_tap), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(WebInputEvent::Type::kGestureTap, double_tap.GetType()); |
| EXPECT_EQ(2, double_tap.data.tap.tap_count); |
| filter_.DecreaseActiveTouches(); |
| } |
| |
| TEST_F(TouchActionFilterTest, SingleTapWithTouchActionAuto) { |
| WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapDown, kSourceDevice); |
| WebGestureEvent unconfirmed_tap1 = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapUnconfirmed, kSourceDevice); |
| WebGestureEvent tap = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTap, kSourceDevice); |
| |
| // Single tap is allowed with touch action auto. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kAuto); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&unconfirmed_tap1), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(WebInputEvent::Type::kGestureTapUnconfirmed, |
| unconfirmed_tap1.GetType()); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| } |
| |
| TEST_F(TouchActionFilterTest, SingleTap) { |
| WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapDown, kSourceDevice); |
| WebGestureEvent unconfirmed_tap1 = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapUnconfirmed, kSourceDevice); |
| WebGestureEvent tap = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTap, kSourceDevice); |
| |
| // With touch action other than auto, tap unconfirmed is turned into tap. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kNone); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&unconfirmed_tap1), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(WebInputEvent::Type::kGestureTap, unconfirmed_tap1.GetType()); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| filter_.DecreaseActiveTouches(); |
| } |
| |
| TEST_F(TouchActionFilterTest, TouchActionResetsOnResetTouchAction) { |
| WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapDown, kSourceDevice); |
| WebGestureEvent tap = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTap, kSourceDevice); |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin(2, 3, kSourceDevice); |
| WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureScrollEnd, kSourceDevice); |
| |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kNone); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| filter_.DecreaseActiveTouches(); |
| |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kNone); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.DecreaseActiveTouches(); |
| |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kAuto); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.DecreaseActiveTouches(); |
| } |
| |
| TEST_F(TouchActionFilterTest, TouchActionResetMidSequence) { |
| filter_.OnHasTouchEventHandlers(true); |
| WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapDown, kSourceDevice); |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin(2, 3, kSourceDevice); |
| WebGestureEvent pinch_begin = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGesturePinchBegin, kSourceDevice); |
| WebGestureEvent pinch_update = |
| SyntheticWebGestureEventBuilder::BuildPinchUpdate(1.2f, 5, 5, 0, |
| kSourceDevice); |
| WebGestureEvent pinch_end = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGesturePinchEnd, kSourceDevice); |
| WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureScrollEnd, kSourceDevice); |
| |
| filter_.OnSetTouchAction(cc::TouchAction::kNone); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| |
| // Even though the allowed action is auto after the reset, the remaining |
| // scroll and pinch events should be suppressed. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kAuto); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| filter_.DecreaseActiveTouches(); |
| |
| // A new scroll and pinch sequence should be allowed. |
| filter_.OnSetTouchAction(cc::TouchAction::kAuto); |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| |
| // Resetting from auto to auto mid-stream should have no effect. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kAuto); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.DecreaseActiveTouches(); |
| } |
| |
| // This test makes sure that we do not reset scrolling touch action in the |
| // middle of a gesture sequence. |
| TEST_F(TouchActionFilterTest, TouchActionNotResetWithinGestureSequence) { |
| filter_.OnHasTouchEventHandlers(true); |
| EXPECT_FALSE(filter_.allowed_touch_action().has_value()); |
| filter_.OnSetTouchAction(cc::TouchAction::kPanY); |
| |
| WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapDown, kSourceDevice); |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin(1, 3, kSourceDevice); |
| WebGestureEvent scroll_update = |
| SyntheticWebGestureEventBuilder::BuildScrollUpdate(1, 5, 0, |
| kSourceDevice); |
| WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureScrollEnd, kSourceDevice); |
| |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(cc::TouchAction::kPanY, ActiveTouchAction().value()); |
| |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| // Simulate a touch sequence end by calling ReportAndResetTouchAction. |
| filter_.DecreaseActiveTouches(); |
| filter_.ReportAndResetTouchAction(); |
| EXPECT_FALSE(filter_.allowed_touch_action().has_value()); |
| EXPECT_EQ(cc::TouchAction::kPanY, ActiveTouchAction().value()); |
| // In fling or fling boosting case, we will see ScrollUpdate after the touch |
| // end. |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| // The |allowed_touch_action_| should have been reset, but not the |
| // |scrolling_touch_action_|. |
| EXPECT_FALSE(filter_.allowed_touch_action().has_value()); |
| EXPECT_EQ(cc::TouchAction::kPanY, ActiveTouchAction().value()); |
| } |
| |
| // The following 3 tests ensures that when the IPC message |
| // OnHasTouchEventHandlers is received in the middle of a gesture sequence, the |
| // touch action is not reset. |
| TEST_F(TouchActionFilterTest, OnHasTouchEventHandlersReceivedDuringTap) { |
| filter_.OnHasTouchEventHandlers(false); |
| |
| WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapDown, kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.OnHasTouchEventHandlers(true); |
| EXPECT_TRUE(ActiveTouchAction().has_value()); |
| |
| filter_.OnSetTouchAction(cc::TouchAction::kPan); |
| // Simulate a simple tap gesture. |
| WebGestureEvent tap = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTap, kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| // Gesture tap indicates that there is no scroll in progress, so this should |
| // reset the |allowed_touch_action_|. |
| ResetTouchAction(); |
| EXPECT_FALSE(filter_.allowed_touch_action().has_value()); |
| } |
| |
| TEST_F(TouchActionFilterTest, OnHasTouchEventHandlersReceivedDuringDoubleTap) { |
| filter_.OnHasTouchEventHandlers(false); |
| |
| WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapDown, kSourceDevice); |
| WebGestureEvent tap_cancel = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapCancel, kSourceDevice); |
| WebGestureEvent double_tap = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureDoubleTap, kSourceDevice); |
| |
| // Simulate a double tap gesture: GTD-->GTC-->GTD-->GTC-->GDT. |
| filter_.IncreaseActiveTouches(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(ActiveTouchAction().value(), cc::TouchAction::kAuto); |
| filter_.OnHasTouchEventHandlers(true); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_cancel), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_TRUE(ActiveTouchAction().has_value()); |
| filter_.OnSetTouchAction(cc::TouchAction::kPan); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(ActiveTouchAction().value(), cc::TouchAction::kPan); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_cancel), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&double_tap), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.DecreaseActiveTouches(); |
| } |
| |
| TEST_F(TouchActionFilterTest, OnHasTouchEventHandlersReceivedDuringScroll) { |
| filter_.OnHasTouchEventHandlers(false); |
| |
| WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapDown, kSourceDevice); |
| WebGestureEvent tap_cancel = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapCancel, kSourceDevice); |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin(5, 0, kSourceDevice); |
| WebGestureEvent scroll_update = |
| SyntheticWebGestureEventBuilder::BuildScrollUpdate(5, 0, 0, |
| kSourceDevice); |
| WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureScrollEnd, kSourceDevice); |
| |
| // Simulate a gesture scroll: GTD-->GTC-->GSB-->GSU-->GSE. |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_cancel), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| filter_.OnHasTouchEventHandlers(true); |
| filter_.OnSetTouchAction(cc::TouchAction::kPan); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(ActiveTouchAction().value(), cc::TouchAction::kPan); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| } |
| |
| // If OnHasTouchEventHandlers IPC is received after LongTap or TwoFingerTap, |
| // the touch action should be reset. |
| TEST_F(TouchActionFilterTest, |
| OnHasTouchEventHandlersReceivedAfterLongTapOrTwoFingerTap) { |
| filter_.OnHasTouchEventHandlers(false); |
| |
| WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapDown, kSourceDevice); |
| WebGestureEvent tap_cancel = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapCancel, kSourceDevice); |
| WebGestureEvent long_tap = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureLongTap, kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_cancel), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&long_tap), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(ActiveTouchAction().value(), cc::TouchAction::kAuto); |
| |
| filter_.OnHasTouchEventHandlers(true); |
| EXPECT_FALSE(ActiveTouchAction().has_value()); |
| |
| filter_.OnHasTouchEventHandlers(false); |
| WebGestureEvent two_finger_tap = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTwoFingerTap, kSourceDevice); |
| |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_cancel), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&two_finger_tap), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(ActiveTouchAction().value(), cc::TouchAction::kAuto); |
| |
| filter_.OnHasTouchEventHandlers(true); |
| EXPECT_FALSE(ActiveTouchAction().has_value()); |
| } |
| |
| TEST_F(TouchActionFilterTest, OnHasTouchEventHandlersReceivedAfterTouchStart) { |
| filter_.OnHasTouchEventHandlers(true); |
| EXPECT_FALSE(ActiveTouchAction().has_value()); |
| EXPECT_FALSE(filter_.allowed_touch_action().has_value()); |
| |
| // Receive a touch start ack, set the touch action. |
| filter_.OnSetTouchAction(cc::TouchAction::kPanY); |
| filter_.IncreaseActiveTouches(); |
| filter_.OnHasTouchEventHandlers(false); |
| EXPECT_EQ(ActiveTouchAction().value(), cc::TouchAction::kPanY); |
| EXPECT_EQ(filter_.allowed_touch_action().value(), cc::TouchAction::kPanY); |
| filter_.OnHasTouchEventHandlers(true); |
| EXPECT_EQ(ActiveTouchAction().value(), cc::TouchAction::kPanY); |
| EXPECT_EQ(filter_.allowed_touch_action().value(), cc::TouchAction::kPanY); |
| } |
| |
| TEST_F(TouchActionFilterTest, ResetTouchActionWithActiveTouch) { |
| filter_.OnHasTouchEventHandlers(true); |
| EXPECT_FALSE(ActiveTouchAction().has_value()); |
| EXPECT_FALSE(filter_.allowed_touch_action().has_value()); |
| |
| // Receive a touch start ack, set the touch action. |
| filter_.OnSetTouchAction(cc::TouchAction::kPanY); |
| filter_.IncreaseActiveTouches(); |
| |
| // Somehow we get the ACK for the second touch start before the ACK for the |
| // first touch end. |
| filter_.OnSetTouchAction(cc::TouchAction::kPan); |
| filter_.IncreaseActiveTouches(); |
| |
| // The first touch end comes, we report and reset touch action. The touch |
| // actions should still have value. |
| filter_.DecreaseActiveTouches(); |
| filter_.ReportAndResetTouchAction(); |
| EXPECT_EQ(ActiveTouchAction().value(), cc::TouchAction::kPanY); |
| EXPECT_EQ(filter_.allowed_touch_action().value(), cc::TouchAction::kPanY); |
| |
| // The ack for the second touch end comes, the touch actions will be reset. |
| filter_.DecreaseActiveTouches(); |
| filter_.ReportAndResetTouchAction(); |
| EXPECT_FALSE(filter_.allowed_touch_action().has_value()); |
| } |
| |
| // If the renderer is busy, the gesture event might have come before the |
| // OnHasTouchEventHanlders IPC is received. In this case, we should allow all |
| // the gestures. |
| TEST_F(TouchActionFilterTest, GestureArrivesBeforeHasHandlerSet) { |
| WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapDown, kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| } |
| |
| TEST_F(TouchActionFilterTest, |
| PinchGesturesAllowedByCompositorAllowedTouchAction) { |
| filter_.OnHasTouchEventHandlers(true); |
| EXPECT_FALSE(ActiveTouchAction().has_value()); |
| EXPECT_FALSE(filter_.allowed_touch_action().has_value()); |
| |
| // Compositor allowed touch action has a default value of Auto, and pinch |
| // related gestures should be allowed. |
| WebGestureEvent pinch_begin = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGesturePinchBegin, kSourceDevice); |
| WebGestureEvent pinch_update = |
| SyntheticWebGestureEventBuilder::BuildPinchUpdate(1.2f, 5, 5, 0, |
| kSourceDevice); |
| WebGestureEvent pinch_end = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGesturePinchEnd, kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| } |
| |
| // Test gesture event filtering with compositor allowed touch action. It should |
| // test all 3 kinds of results: Allowed / Dropped / Delayed. |
| TEST_F(TouchActionFilterTest, FilterWithCompositorAllowedListedTouchAction) { |
| filter_.OnHasTouchEventHandlers(true); |
| EXPECT_FALSE(ActiveTouchAction().has_value()); |
| EXPECT_FALSE(filter_.allowed_touch_action().has_value()); |
| |
| int dx = 2, dy = 5; |
| // Test gestures that are allowed. |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin(dx, dy, kSourceDevice); |
| WebGestureEvent scroll_update = |
| SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, dy, 0, |
| kSourceDevice); |
| WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureScrollEnd, kSourceDevice); |
| |
| filter_.OnSetCompositorAllowedTouchAction(cc::TouchAction::kPan); |
| EXPECT_EQ(filter_.compositor_allowed_touch_action(), cc::TouchAction::kPan); |
| SetGestureSequenceInProgress(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| |
| // Pinch related gestures are always delayed. |
| ResetTouchAction(); |
| ResetActiveTouchAction(); |
| ResetCompositorAllowedTouchAction(); |
| filter_.OnSetCompositorAllowedTouchAction(cc::TouchAction::kPan); |
| EXPECT_EQ(filter_.compositor_allowed_touch_action(), cc::TouchAction::kPan); |
| WebGestureEvent pinch_begin = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGesturePinchBegin, kSourceDevice); |
| WebGestureEvent pinch_update = |
| SyntheticWebGestureEventBuilder::BuildPinchUpdate(1.2f, 5, 5, 0, |
| kSourceDevice); |
| WebGestureEvent pinch_end = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGesturePinchEnd, kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin), |
| FilterGestureEventResult::kFilterGestureEventDelayed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update), |
| FilterGestureEventResult::kFilterGestureEventDelayed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end), |
| FilterGestureEventResult::kFilterGestureEventDelayed); |
| |
| // Scroll updates should be delayed if the compositor allowed listed touch |
| // action is PanY, because there are delta along the direction that is not |
| // allowed. |
| ResetTouchAction(); |
| ResetActiveTouchAction(); |
| ResetCompositorAllowedTouchAction(); |
| filter_.OnSetCompositorAllowedTouchAction(cc::TouchAction::kPanY); |
| SetNoDeferredEvents(); |
| EXPECT_EQ(filter_.compositor_allowed_touch_action(), cc::TouchAction::kPanY); |
| SetGestureSequenceInProgress(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventDelayed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventDelayed); |
| |
| ResetTouchAction(); |
| ResetActiveTouchAction(); |
| ResetCompositorAllowedTouchAction(); |
| filter_.OnSetCompositorAllowedTouchAction(cc::TouchAction::kPanX); |
| SetNoDeferredEvents(); |
| EXPECT_EQ(filter_.compositor_allowed_touch_action(), cc::TouchAction::kPanX); |
| |
| dy = 0; |
| scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin(dx, dy, kSourceDevice); |
| scroll_update = SyntheticWebGestureEventBuilder::BuildScrollUpdate( |
| dx, dy, 0, kSourceDevice); |
| SetGestureSequenceInProgress(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| |
| dx = 0; |
| dy = 5; |
| scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin(dx, dy, kSourceDevice); |
| scroll_update = SyntheticWebGestureEventBuilder::BuildScrollUpdate( |
| dx, dy, 0, kSourceDevice); |
| filter_.OnSetCompositorAllowedTouchAction(cc::TouchAction::kPanX); |
| EXPECT_EQ(filter_.compositor_allowed_touch_action(), cc::TouchAction::kPanX); |
| SetGestureSequenceInProgress(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventDelayed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventDelayed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventDelayed); |
| } |
| |
| TEST_F(TouchActionFilterTest, CompositorAllowedTouchActionResetToAuto) { |
| filter_.OnHasTouchEventHandlers(true); |
| |
| filter_.OnSetCompositorAllowedTouchAction(cc::TouchAction::kPan); |
| EXPECT_EQ(filter_.compositor_allowed_touch_action(), cc::TouchAction::kPan); |
| ResetTouchAction(); |
| EXPECT_EQ(filter_.compositor_allowed_touch_action(), cc::TouchAction::kAuto); |
| } |
| |
| TEST_F(TouchActionFilterTest, CompositorAllowedTouchActionAutoNoHasHandlers) { |
| filter_.OnHasTouchEventHandlers(false); |
| EXPECT_EQ(filter_.compositor_allowed_touch_action(), cc::TouchAction::kAuto); |
| |
| ResetTouchAction(); |
| EXPECT_EQ(filter_.compositor_allowed_touch_action(), cc::TouchAction::kAuto); |
| } |
| |
| TEST_F(TouchActionFilterTest, ResetBeforeHasHandlerSet) { |
| // This should not crash, and should set touch action to auto. |
| ResetTouchAction(); |
| WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapDown, kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| } |
| |
| TEST_F(TouchActionFilterTest, |
| CompositorAllowedTouchActionNotResetAtGestureScrollEnd) { |
| filter_.OnHasTouchEventHandlers(true); |
| |
| filter_.OnSetCompositorAllowedTouchAction(cc::TouchAction::kPan); |
| EXPECT_EQ(filter_.compositor_allowed_touch_action(), cc::TouchAction::kPan); |
| |
| int dx = 2, dy = 5; |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin(dx, dy, kSourceDevice); |
| WebGestureEvent scroll_update = |
| SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, dy, 0, |
| kSourceDevice); |
| WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureScrollEnd, kSourceDevice); |
| |
| SetGestureSequenceInProgress(); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| |
| EXPECT_EQ(filter_.compositor_allowed_touch_action(), cc::TouchAction::kPan); |
| } |
| |
| // Having a gesture scroll begin without tap down should set touch action to |
| // Auto. |
| TEST_F(TouchActionFilterTest, ScrollBeginWithoutTapDown) { |
| filter_.OnHasTouchEventHandlers(true); |
| EXPECT_FALSE(ActiveTouchAction().has_value()); |
| EXPECT_FALSE(filter_.allowed_touch_action().has_value()); |
| |
| filter_.OnSetCompositorAllowedTouchAction(cc::TouchAction::kPan); |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin(5, 0, kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.compositor_allowed_touch_action(), cc::TouchAction::kPan); |
| |
| ResetTouchAction(); |
| ResetActiveTouchAction(); |
| ResetGestureSequenceInProgress(); |
| EXPECT_FALSE(ActiveTouchAction().has_value()); |
| EXPECT_FALSE(filter_.allowed_touch_action().has_value()); |
| |
| // Ensure that there is no crash at GSB if both |allowed_| and |active_| |
| // touch action have no value. |
| filter_.OnSetCompositorAllowedTouchAction(cc::TouchAction::kPan); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| } |
| |
| // This tests a gesture tap down with |num_of_active_touches_| == 0 |
| TEST_F(TouchActionFilterTest, TapDownWithZeroNumOfActiveTouches) { |
| filter_.OnHasTouchEventHandlers(true); |
| EXPECT_FALSE(ActiveTouchAction().has_value()); |
| EXPECT_FALSE(filter_.allowed_touch_action().has_value()); |
| |
| WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureTapDown, kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&tap_down), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_TRUE(ActiveTouchAction().has_value()); |
| EXPECT_EQ(ActiveTouchAction().value(), cc::TouchAction::kAuto); |
| } |
| |
| // Regression test for crbug.com/771330. One can start one finger panning y, and |
| // add another finger to pinch zooming. The pinch zooming should not be allowed |
| // if the allowed touch action doesn't allow it. |
| TEST_F(TouchActionFilterTest, PinchZoomStartsWithOneFingerPanDisallowed) { |
| filter_.OnHasTouchEventHandlers(true); |
| filter_.OnSetTouchAction(cc::TouchAction::kPanY); |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin(0, 3, kSourceDevice); |
| WebGestureEvent scroll_update = |
| SyntheticWebGestureEventBuilder::BuildScrollUpdate(5, 10, 0, |
| kSourceDevice); |
| WebGestureEvent pinch_begin = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGesturePinchBegin, kSourceDevice); |
| WebGestureEvent pinch_update = |
| SyntheticWebGestureEventBuilder::BuildPinchUpdate(1.2f, 5, 5, 0, |
| kSourceDevice); |
| WebGestureEvent pinch_end = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGesturePinchEnd, kSourceDevice); |
| WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::Type::kGestureScrollEnd, kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end), |
| FilterGestureEventResult::kFilterGestureEventFiltered); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| } |
| |
| TEST_F(TouchActionFilterTest, ScrollBeginWithoutTapDownWithKnownTouchAction) { |
| filter_.OnHasTouchEventHandlers(true); |
| EXPECT_FALSE(ActiveTouchAction().has_value()); |
| EXPECT_FALSE(filter_.allowed_touch_action().has_value()); |
| |
| filter_.OnSetTouchAction(cc::TouchAction::kPan); |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin(5, 0, kSourceDevice); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| EXPECT_EQ(ActiveTouchAction().value(), cc::TouchAction::kPan); |
| EXPECT_EQ(filter_.allowed_touch_action().value(), cc::TouchAction::kPan); |
| } |
| |
| TEST_F(TouchActionFilterTest, TouchpadScroll) { |
| WebGestureEvent scroll_begin = |
| SyntheticWebGestureEventBuilder::BuildScrollBegin( |
| 2, 3, blink::WebGestureDevice::kTouchpad); |
| |
| // cc::TouchAction::kNone filters out only touchscreen scroll events. |
| ResetTouchAction(); |
| filter_.OnSetTouchAction(cc::TouchAction::kNone); |
| EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin), |
| FilterGestureEventResult::kFilterGestureEventAllowed); |
| } |
| |
| } // namespace content |