blob: aac1fb664a0a40c072405346bf2811e9989f33e0 [file] [log] [blame]
// 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/event_with_latency_info.h"
#include "content/browser/renderer_host/input/touch_action_filter.h"
#include "content/common/input/input_event_ack_state.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
using blink::WebGestureEvent;
using blink::WebInputEvent;
namespace content {
TEST(TouchActionFilterTest, SimpleFilter) {
TouchActionFilter filter;
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(2, 3);
const float kDeltaX = 5;
const float kDeltaY = 10;
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(kDeltaX, kDeltaY, 0);
WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureScrollEnd, blink::WebGestureDeviceTouchscreen);
WebGestureEvent tap = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureTap, blink::WebGestureDeviceTouchscreen);
// No events filtered by default.
filter.ResetTouchAction();
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update));
EXPECT_EQ(kDeltaX, scroll_update.data.scrollUpdate.deltaX);
EXPECT_EQ(kDeltaY, scroll_update.data.scrollUpdate.deltaY);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
filter.ResetTouchAction();
EXPECT_FALSE(filter.FilterGestureEvent(&tap));
// TOUCH_ACTION_AUTO doesn't cause any filtering.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_AUTO);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update));
EXPECT_EQ(kDeltaX, scroll_update.data.scrollUpdate.deltaX);
EXPECT_EQ(kDeltaY, scroll_update.data.scrollUpdate.deltaY);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
// TOUCH_ACTION_NONE filters out all scroll events, but no other events.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_NONE);
EXPECT_FALSE(filter.FilterGestureEvent(&tap));
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
EXPECT_EQ(kDeltaX, scroll_update.data.scrollUpdate.deltaX);
EXPECT_EQ(kDeltaY, scroll_update.data.scrollUpdate.deltaY);
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
// When a new touch sequence begins, the state is reset.
filter.ResetTouchAction();
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update));
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
// Setting touch action doesn't impact any in-progress gestures.
filter.ResetTouchAction();
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
filter.OnSetTouchAction(TOUCH_ACTION_NONE);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update));
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
// And the state is still cleared for the next gesture.
filter.ResetTouchAction();
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
// Changing the touch action during a gesture has no effect.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_NONE);
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
filter.OnSetTouchAction(TOUCH_ACTION_AUTO);
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
EXPECT_EQ(kDeltaX, scroll_update.data.scrollUpdate.deltaX);
EXPECT_EQ(kDeltaY, scroll_update.data.scrollUpdate.deltaY);
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
filter.ResetTouchAction();
}
TEST(TouchActionFilterTest, Fling) {
TouchActionFilter filter;
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(2, 3);
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(5, 10, 0);
const float kFlingX = 7;
const float kFlingY = -4;
WebGestureEvent fling_start = SyntheticWebGestureEventBuilder::BuildFling(
kFlingX, kFlingY, blink::WebGestureDeviceTouchscreen);
WebGestureEvent pad_fling = SyntheticWebGestureEventBuilder::BuildFling(
kFlingX, kFlingY, blink::WebGestureDeviceTouchpad);
// TOUCH_ACTION_NONE filters out fling events.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_NONE);
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
EXPECT_TRUE(filter.FilterGestureEvent(&fling_start));
EXPECT_EQ(kFlingX, fling_start.data.flingStart.velocityX);
EXPECT_EQ(kFlingY, fling_start.data.flingStart.velocityY);
// touchpad flings aren't filtered.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_NONE);
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
EXPECT_FALSE(filter.FilterGestureEvent(&pad_fling));
EXPECT_TRUE(filter.FilterGestureEvent(&fling_start));
filter.ResetTouchAction();
}
TEST(TouchActionFilterTest, PanX) {
TouchActionFilter filter;
const float kDX = 5;
const float kDY = 10;
const float kFlingX = 7;
const float kFlingY = -4;
WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureScrollEnd, blink::WebGestureDeviceTouchscreen);
{
// Scrolls with no direction hint are permitted in the X axis.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_PAN_X);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(0, 0);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(kDX, kDY, 0);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update));
EXPECT_EQ(kDX, scroll_update.data.scrollUpdate.deltaX);
EXPECT_EQ(0, scroll_update.data.scrollUpdate.deltaY);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
}
{
// Scrolls hinted mostly in the X axis are permitted in that axis.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_PAN_X);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(-7, 6);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(kDX, kDY, 0);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update));
EXPECT_EQ(kDX, scroll_update.data.scrollUpdate.deltaX);
EXPECT_EQ(0, scroll_update.data.scrollUpdate.deltaY);
WebGestureEvent scroll_update2 =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(-4, -2, 0);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update2));
EXPECT_EQ(-4, scroll_update2.data.scrollUpdate.deltaX);
EXPECT_EQ(0, scroll_update2.data.scrollUpdate.deltaY);
WebGestureEvent fling_start = SyntheticWebGestureEventBuilder::BuildFling(
kFlingX, kFlingY, blink::WebGestureDeviceTouchscreen);
EXPECT_FALSE(filter.FilterGestureEvent(&fling_start));
EXPECT_EQ(kFlingX, fling_start.data.flingStart.velocityX);
EXPECT_EQ(0, fling_start.data.flingStart.velocityY);
}
{
// Scrolls hinted mostly in the Y direction are suppressed entirely.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_PAN_X);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(-7, 8);
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(kDX, kDY, 0);
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
EXPECT_EQ(kDX, scroll_update.data.scrollUpdate.deltaX);
EXPECT_EQ(kDY, scroll_update.data.scrollUpdate.deltaY);
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
}
filter.ResetTouchAction();
}
TEST(TouchActionFilterTest, PanY) {
TouchActionFilter filter;
const float kDX = 5;
const float kDY = 10;
const float kFlingX = 7;
const float kFlingY = -4;
WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureScrollEnd, blink::WebGestureDeviceTouchscreen);
{
// Scrolls with no direction hint are permitted in the Y axis.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_PAN_Y);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(0, 0);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(kDX, kDY, 0);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update));
EXPECT_EQ(0, scroll_update.data.scrollUpdate.deltaX);
EXPECT_EQ(kDY, scroll_update.data.scrollUpdate.deltaY);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
}
{
// Scrolls hinted mostly in the Y axis are permitted in that axis.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_PAN_Y);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(-6, 7);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(kDX, kDY, 0);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update));
EXPECT_EQ(0, scroll_update.data.scrollUpdate.deltaX);
EXPECT_EQ(kDY, scroll_update.data.scrollUpdate.deltaY);
WebGestureEvent scroll_update2 =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(-4, -2, 0);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update2));
EXPECT_EQ(0, scroll_update2.data.scrollUpdate.deltaX);
EXPECT_EQ(-2, scroll_update2.data.scrollUpdate.deltaY);
WebGestureEvent fling_start = SyntheticWebGestureEventBuilder::BuildFling(
kFlingX, kFlingY, blink::WebGestureDeviceTouchscreen);
EXPECT_FALSE(filter.FilterGestureEvent(&fling_start));
EXPECT_EQ(0, fling_start.data.flingStart.velocityX);
EXPECT_EQ(kFlingY, fling_start.data.flingStart.velocityY);
}
{
// Scrolls hinted mostly in the X direction are suppressed entirely.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_PAN_Y);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(-8, 7);
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(kDX, kDY, 0);
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
EXPECT_EQ(kDX, scroll_update.data.scrollUpdate.deltaX);
EXPECT_EQ(kDY, scroll_update.data.scrollUpdate.deltaY);
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
}
filter.ResetTouchAction();
}
TEST(TouchActionFilterTest, PanXY) {
TouchActionFilter filter;
const float kDX = 5;
const float kDY = 10;
const float kFlingX = 7;
const float kFlingY = -4;
{
// Scrolls hinted in the X axis are permitted and unmodified.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_PAN_X_Y);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(-7, 6);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(kDX, kDY, 0);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update));
EXPECT_EQ(kDX, scroll_update.data.scrollUpdate.deltaX);
EXPECT_EQ(kDY, scroll_update.data.scrollUpdate.deltaY);
WebGestureEvent fling_start = SyntheticWebGestureEventBuilder::BuildFling(
kFlingX, kFlingY, blink::WebGestureDeviceTouchscreen);
EXPECT_FALSE(filter.FilterGestureEvent(&fling_start));
EXPECT_EQ(kFlingX, fling_start.data.flingStart.velocityX);
EXPECT_EQ(kFlingY, fling_start.data.flingStart.velocityY);
}
{
// Scrolls hinted in the Y axis are permitted and unmodified.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_PAN_X_Y);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(-6, 7);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(kDX, kDY, 0);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update));
EXPECT_EQ(kDX, scroll_update.data.scrollUpdate.deltaX);
EXPECT_EQ(kDY, scroll_update.data.scrollUpdate.deltaY);
WebGestureEvent fling_start = SyntheticWebGestureEventBuilder::BuildFling(
kFlingX, kFlingY, blink::WebGestureDeviceTouchscreen);
EXPECT_FALSE(filter.FilterGestureEvent(&fling_start));
EXPECT_EQ(kFlingX, fling_start.data.flingStart.velocityX);
EXPECT_EQ(kFlingY, fling_start.data.flingStart.velocityY);
}
filter.ResetTouchAction();
}
TEST(TouchActionFilterTest, Intersect) {
EXPECT_EQ(TOUCH_ACTION_NONE,
TouchActionFilter::Intersect(TOUCH_ACTION_NONE, TOUCH_ACTION_AUTO));
EXPECT_EQ(TOUCH_ACTION_NONE,
TouchActionFilter::Intersect(TOUCH_ACTION_AUTO, TOUCH_ACTION_NONE));
EXPECT_EQ(TOUCH_ACTION_PAN_X,
TouchActionFilter::Intersect(TOUCH_ACTION_AUTO, TOUCH_ACTION_PAN_X));
EXPECT_EQ(TOUCH_ACTION_PAN_Y,
TouchActionFilter::Intersect(TOUCH_ACTION_PAN_Y, TOUCH_ACTION_AUTO));
EXPECT_EQ(TOUCH_ACTION_AUTO,
TouchActionFilter::Intersect(TOUCH_ACTION_AUTO, TOUCH_ACTION_AUTO));
EXPECT_EQ(TOUCH_ACTION_PAN_X,
TouchActionFilter::Intersect(TOUCH_ACTION_PAN_X_Y, TOUCH_ACTION_PAN_X));
EXPECT_EQ(TOUCH_ACTION_PAN_Y,
TouchActionFilter::Intersect(TOUCH_ACTION_PAN_Y, TOUCH_ACTION_PAN_X_Y));
EXPECT_EQ(TOUCH_ACTION_PAN_X_Y,
TouchActionFilter::Intersect(TOUCH_ACTION_PAN_X_Y, TOUCH_ACTION_AUTO));
EXPECT_EQ(TOUCH_ACTION_NONE,
TouchActionFilter::Intersect(TOUCH_ACTION_PAN_X, TOUCH_ACTION_PAN_Y));
}
TEST(TouchActionFilterTest, MultiTouch) {
TouchActionFilter filter;
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(2, 3);
const float kDeltaX = 5;
const float kDeltaY = 10;
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(kDeltaX, kDeltaY, 0);
WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureScrollEnd, blink::WebGestureDeviceTouchscreen);
// For multiple points, the intersection is what matters.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_NONE);
filter.OnSetTouchAction(TOUCH_ACTION_AUTO);
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
EXPECT_EQ(kDeltaX, scroll_update.data.scrollUpdate.deltaX);
EXPECT_EQ(kDeltaY, scroll_update.data.scrollUpdate.deltaY);
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
// Intersection of PAN_X and PAN_Y is NONE.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_PAN_X);
filter.OnSetTouchAction(TOUCH_ACTION_PAN_Y);
filter.OnSetTouchAction(TOUCH_ACTION_PAN_X_Y);
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
filter.ResetTouchAction();
}
TEST(TouchActionFilterTest, Pinch) {
TouchActionFilter filter;
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(2, 3);
WebGestureEvent pinch_begin = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GesturePinchBegin, blink::WebGestureDeviceTouchscreen);
WebGestureEvent pinch_update =
SyntheticWebGestureEventBuilder::BuildPinchUpdate(
1.2f, 5, 5, 0, blink::WebGestureDeviceTouchscreen);
WebGestureEvent pinch_end = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GesturePinchEnd, blink::WebGestureDeviceTouchscreen);
WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureScrollEnd, blink::WebGestureDeviceTouchscreen);
// Pinch is allowed with touch-action: auto.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_AUTO);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
// Pinch is not allowed with touch-action: none.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_NONE);
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
EXPECT_TRUE(filter.FilterGestureEvent(&pinch_begin));
EXPECT_TRUE(filter.FilterGestureEvent(&pinch_update));
EXPECT_TRUE(filter.FilterGestureEvent(&pinch_end));
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
// Pinch is not allowed with touch-action: pan-x pan-y.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_PAN_X_Y);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
EXPECT_TRUE(filter.FilterGestureEvent(&pinch_begin));
EXPECT_TRUE(filter.FilterGestureEvent(&pinch_update));
EXPECT_TRUE(filter.FilterGestureEvent(&pinch_end));
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
// Pinch is allowed with touch-action: manipulation.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_MANIPULATION);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
// Pinch state is automatically reset at the end of a scroll.
filter.ResetTouchAction();
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
// Pinching can become disallowed during a single scroll gesture, but
// can't become allowed again until the scroll terminates.
// Note that the current TouchEventQueue design makes this scenario
// impossible in practice (no touch events are sent to the renderer
// while scrolling) and so no SetTouchAction can occur. But this
// could change in the future, so it's still worth verifying in this
// unit test.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_AUTO);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
filter.OnSetTouchAction(TOUCH_ACTION_NONE);
EXPECT_TRUE(filter.FilterGestureEvent(&pinch_begin));
EXPECT_TRUE(filter.FilterGestureEvent(&pinch_update));
EXPECT_TRUE(filter.FilterGestureEvent(&pinch_end));
filter.OnSetTouchAction(TOUCH_ACTION_AUTO);
EXPECT_TRUE(filter.FilterGestureEvent(&pinch_begin));
EXPECT_TRUE(filter.FilterGestureEvent(&pinch_update));
EXPECT_TRUE(filter.FilterGestureEvent(&pinch_end));
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
// Once a pinch has started, any change in state won't affect the current
// pinch gesture, but can affect a future one within the same scroll.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_AUTO);
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
filter.OnSetTouchAction(TOUCH_ACTION_NONE);
EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
EXPECT_TRUE(filter.FilterGestureEvent(&pinch_begin));
EXPECT_TRUE(filter.FilterGestureEvent(&pinch_update));
EXPECT_TRUE(filter.FilterGestureEvent(&pinch_end));
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
filter.ResetTouchAction();
}
TEST(TouchActionFilterTest, DoubleTapWithTouchActionAuto) {
TouchActionFilter filter;
WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureTapDown, blink::WebGestureDeviceTouchscreen);
WebGestureEvent unconfirmed_tap = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureTapUnconfirmed, blink::WebGestureDeviceTouchscreen);
WebGestureEvent tap_cancel = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureTapCancel, blink::WebGestureDeviceTouchscreen);
WebGestureEvent double_tap = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureDoubleTap, blink::WebGestureDeviceTouchscreen);
// Double tap is allowed with touch action auto.
filter.ResetTouchAction();
EXPECT_FALSE(filter.FilterGestureEvent(&tap_down));
EXPECT_FALSE(filter.FilterGestureEvent(&unconfirmed_tap));
EXPECT_EQ(unconfirmed_tap.type, WebInputEvent::GestureTapUnconfirmed);
// The tap cancel will come as part of the next touch sequence.
filter.ResetTouchAction();
// Changing the touch action for the second tap doesn't effect the behaviour
// of the event.
filter.OnSetTouchAction(TOUCH_ACTION_NONE);
EXPECT_FALSE(filter.FilterGestureEvent(&tap_cancel));
EXPECT_FALSE(filter.FilterGestureEvent(&tap_down));
EXPECT_FALSE(filter.FilterGestureEvent(&double_tap));
filter.ResetTouchAction();
}
TEST(TouchActionFilterTest, DoubleTap) {
TouchActionFilter filter;
WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureTapDown, blink::WebGestureDeviceTouchscreen);
WebGestureEvent unconfirmed_tap = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureTapUnconfirmed, blink::WebGestureDeviceTouchscreen);
WebGestureEvent tap_cancel = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureTapCancel, blink::WebGestureDeviceTouchscreen);
WebGestureEvent double_tap = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureDoubleTap, blink::WebGestureDeviceTouchscreen);
// Double tap is disabled with any touch action other than auto.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_MANIPULATION);
EXPECT_FALSE(filter.FilterGestureEvent(&tap_down));
EXPECT_FALSE(filter.FilterGestureEvent(&unconfirmed_tap));
EXPECT_EQ(WebInputEvent::GestureTap, unconfirmed_tap.type);
// 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.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_AUTO);
EXPECT_TRUE(filter.FilterGestureEvent(&tap_cancel));
EXPECT_FALSE(filter.FilterGestureEvent(&tap_down));
EXPECT_FALSE(filter.FilterGestureEvent(&double_tap));
EXPECT_EQ(WebInputEvent::GestureTap, double_tap.type);
filter.ResetTouchAction();
}
TEST(TouchActionFilterTest, SingleTapWithTouchActionAuto) {
TouchActionFilter filter;
WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureTapDown, blink::WebGestureDeviceTouchscreen);
WebGestureEvent unconfirmed_tap1 = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureTapUnconfirmed, blink::WebGestureDeviceTouchscreen);
WebGestureEvent tap = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureTap, blink::WebGestureDeviceTouchscreen);
// Single tap is allowed with touch action auto.
filter.ResetTouchAction();
EXPECT_FALSE(filter.FilterGestureEvent(&tap_down));
EXPECT_FALSE(filter.FilterGestureEvent(&unconfirmed_tap1));
EXPECT_EQ(WebInputEvent::GestureTapUnconfirmed, unconfirmed_tap1.type);
EXPECT_FALSE(filter.FilterGestureEvent(&tap));
filter.ResetTouchAction();
}
TEST(TouchActionFilterTest, SingleTap) {
TouchActionFilter filter;
WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureTapDown, blink::WebGestureDeviceTouchscreen);
WebGestureEvent unconfirmed_tap1 = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureTapUnconfirmed, blink::WebGestureDeviceTouchscreen);
WebGestureEvent tap = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureTap, blink::WebGestureDeviceTouchscreen);
// With touch action other than auto, tap unconfirmed is turned into tap.
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_NONE);
EXPECT_FALSE(filter.FilterGestureEvent(&tap_down));
EXPECT_FALSE(filter.FilterGestureEvent(&unconfirmed_tap1));
EXPECT_EQ(WebInputEvent::GestureTap, unconfirmed_tap1.type);
EXPECT_TRUE(filter.FilterGestureEvent(&tap));
filter.ResetTouchAction();
}
TEST(TouchActionFilterTest, TouchActionResetsOnResetTouchAction) {
TouchActionFilter filter;
WebGestureEvent tap = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureTap, blink::WebGestureDeviceTouchscreen);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(2, 3);
WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureScrollEnd, blink::WebGestureDeviceTouchscreen);
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_NONE);
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
filter.ResetTouchAction();
filter.OnSetTouchAction(TOUCH_ACTION_NONE);
EXPECT_FALSE(filter.FilterGestureEvent(&tap));
filter.ResetTouchAction();
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
}
TEST(TouchActionFilterTest, TouchActionResetMidSequence) {
TouchActionFilter filter;
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(2, 3);
WebGestureEvent pinch_begin = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GesturePinchBegin, blink::WebGestureDeviceTouchscreen);
WebGestureEvent pinch_update =
SyntheticWebGestureEventBuilder::BuildPinchUpdate(
1.2f, 5, 5, 0, blink::WebGestureDeviceTouchscreen);
WebGestureEvent pinch_end = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GesturePinchEnd, blink::WebGestureDeviceTouchscreen);
WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::GestureScrollEnd, blink::WebGestureDeviceTouchscreen);
filter.OnSetTouchAction(TOUCH_ACTION_NONE);
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
EXPECT_TRUE(filter.FilterGestureEvent(&pinch_begin));
EXPECT_TRUE(filter.FilterGestureEvent(&pinch_update));
// Even though the allowed action is auto after the reset, the remaining
// scroll and pinch events should be suppressed.
filter.ResetTouchAction();
EXPECT_TRUE(filter.FilterGestureEvent(&pinch_update));
EXPECT_TRUE(filter.FilterGestureEvent(&pinch_end));
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
// A new scroll and pinch sequence should be allowed.
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
// Resetting from auto to auto mid-stream should have no effect.
filter.ResetTouchAction();
EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
}
} // namespace content