summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjdduke <jdduke@chromium.org>2014-11-18 12:44:35 -0800
committerCommit bot <commit-bot@chromium.org>2014-11-18 20:45:45 +0000
commit019a29ecaa7e23348b65e1c86807554ded255028 (patch)
treef7faa7e0d0c448d6cc9938aea0d685328445c9bc
parent5779b38e9f3fae82dbbed7219d96cdd19eef1813 (diff)
downloadchromium_src-019a29ecaa7e23348b65e1c86807554ded255028.zip
chromium_src-019a29ecaa7e23348b65e1c86807554ded255028.tar.gz
chromium_src-019a29ecaa7e23348b65e1c86807554ded255028.tar.bz2
Track whether a scroll sequence has been partially prevented
Listeners and consumers of a gesture event stream may wish to know if part of the gesture stream has been prevented, i.e., whether the page has consumed any of the underlying touchmove events. Route this bit for scroll update events from the TouchDispositionGestureFilter through to the generated WebGestureEvent types. This change depends on the Blink patch: https://codereview.chromium.org/690173002/ BUG=428429 Review URL: https://codereview.chromium.org/712133003 Cr-Commit-Position: refs/heads/master@{#304665}
-rw-r--r--content/browser/android/overscroll_controller_android.cc5
-rw-r--r--content/browser/renderer_host/input/web_input_event_util.cc102
-rw-r--r--content/browser/renderer_host/input/web_input_event_util.h18
-rw-r--r--content/browser/renderer_host/input/web_input_event_util_unittest.cc45
-rw-r--r--content/browser/renderer_host/ui_events_helper.cc126
-rw-r--r--content/browser/renderer_host/ui_events_helper.h2
-rw-r--r--content/common/input/gesture_event_stream_validator.cc6
-rw-r--r--content/common/input/web_input_event_traits.cc3
-rw-r--r--ui/events/gesture_detection/gesture_event_data.cc2
-rw-r--r--ui/events/gesture_detection/touch_disposition_gesture_filter.cc16
-rw-r--r--ui/events/gesture_detection/touch_disposition_gesture_filter.h8
-rw-r--r--ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc57
-rw-r--r--ui/events/gesture_event_details.cc51
-rw-r--r--ui/events/gesture_event_details.h51
14 files changed, 281 insertions, 211 deletions
diff --git a/content/browser/android/overscroll_controller_android.cc b/content/browser/android/overscroll_controller_android.cc
index db35ea4..5dda6d1 100644
--- a/content/browser/android/overscroll_controller_android.cc
+++ b/content/browser/android/overscroll_controller_android.cc
@@ -127,9 +127,8 @@ void OverscrollControllerAndroid::OnGestureEventAck(
if (event.type == blink::WebInputEvent::GestureScrollUpdate) {
// The effect should only be allowed if both the causal touch events go
// unconsumed and the generated scroll events go unconsumed.
- // TODO(jdduke): Prevent activation if the first touchmove was consumed,
- // i.e., the first GSU was prevented.
- bool consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
+ bool consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED ||
+ event.data.scrollUpdate.previousUpdateInSequencePrevented;
refresh_effect_.OnScrollUpdateAck(consumed);
}
}
diff --git a/content/browser/renderer_host/input/web_input_event_util.cc b/content/browser/renderer_host/input/web_input_event_util.cc
index 81fc359..000bcc7 100644
--- a/content/browser/renderer_host/input/web_input_event_util.cc
+++ b/content/browser/renderer_host/input/web_input_event_util.cc
@@ -14,6 +14,7 @@
#include "ui/events/event_constants.h"
#include "ui/events/gesture_detection/gesture_event_data.h"
#include "ui/events/gesture_detection/motion_event.h"
+#include "ui/gfx/geometry/safe_integer_conversions.h"
using blink::WebGestureEvent;
using blink::WebInputEvent;
@@ -279,71 +280,82 @@ blink::WebTouchEvent CreateWebTouchEventFromMotionEvent(
return result;
}
-WebGestureEvent CreateWebGestureEventFromGestureEventData(
- const ui::GestureEventData& data) {
+WebGestureEvent CreateWebGestureEvent(const ui::GestureEventDetails& details,
+ base::TimeDelta timestamp,
+ const gfx::PointF& location,
+ const gfx::PointF& raw_location,
+ int flags) {
WebGestureEvent gesture;
- gesture.modifiers = EventFlagsToWebEventModifiers(data.flags);
- gesture.x = data.x;
- gesture.y = data.y;
- gesture.globalX = data.raw_x;
- gesture.globalY = data.raw_y;
- gesture.timeStampSeconds = (data.time - base::TimeTicks()).InSecondsF();
+ gesture.timeStampSeconds = timestamp.InSecondsF();
+ gesture.x = gfx::ToFlooredInt(location.x());
+ gesture.y = gfx::ToFlooredInt(location.y());
+ gesture.globalX = gfx::ToFlooredInt(raw_location.x());
+ gesture.globalY = gfx::ToFlooredInt(raw_location.y());
+ gesture.modifiers = EventFlagsToWebEventModifiers(flags);
gesture.sourceDevice = blink::WebGestureDeviceTouchscreen;
- switch (data.type()) {
+ switch (details.type()) {
case ui::ET_GESTURE_SHOW_PRESS:
gesture.type = WebInputEvent::GestureShowPress;
- gesture.data.showPress.width = data.details.bounding_box_f().width();
- gesture.data.showPress.height = data.details.bounding_box_f().height();
+ gesture.data.showPress.width = details.bounding_box_f().width();
+ gesture.data.showPress.height = details.bounding_box_f().height();
break;
case ui::ET_GESTURE_DOUBLE_TAP:
gesture.type = WebInputEvent::GestureDoubleTap;
- DCHECK_EQ(1, data.details.tap_count());
- gesture.data.tap.tapCount = data.details.tap_count();
- gesture.data.tap.width = data.details.bounding_box_f().width();
- gesture.data.tap.height = data.details.bounding_box_f().height();
+ DCHECK_EQ(1, details.tap_count());
+ gesture.data.tap.tapCount = details.tap_count();
+ gesture.data.tap.width = details.bounding_box_f().width();
+ gesture.data.tap.height = details.bounding_box_f().height();
break;
case ui::ET_GESTURE_TAP:
gesture.type = WebInputEvent::GestureTap;
- DCHECK_EQ(1, data.details.tap_count());
- gesture.data.tap.tapCount = data.details.tap_count();
- gesture.data.tap.width = data.details.bounding_box_f().width();
- gesture.data.tap.height = data.details.bounding_box_f().height();
+ DCHECK_GE(details.tap_count(), 1);
+ gesture.data.tap.tapCount = details.tap_count();
+ gesture.data.tap.width = details.bounding_box_f().width();
+ gesture.data.tap.height = details.bounding_box_f().height();
break;
case ui::ET_GESTURE_TAP_UNCONFIRMED:
gesture.type = WebInputEvent::GestureTapUnconfirmed;
- DCHECK_EQ(1, data.details.tap_count());
- gesture.data.tap.tapCount = data.details.tap_count();
- gesture.data.tap.width = data.details.bounding_box_f().width();
- gesture.data.tap.height = data.details.bounding_box_f().height();
+ DCHECK_EQ(1, details.tap_count());
+ gesture.data.tap.tapCount = details.tap_count();
+ gesture.data.tap.width = details.bounding_box_f().width();
+ gesture.data.tap.height = details.bounding_box_f().height();
break;
case ui::ET_GESTURE_LONG_PRESS:
gesture.type = WebInputEvent::GestureLongPress;
- gesture.data.longPress.width = data.details.bounding_box_f().width();
- gesture.data.longPress.height = data.details.bounding_box_f().height();
+ gesture.data.longPress.width = details.bounding_box_f().width();
+ gesture.data.longPress.height = details.bounding_box_f().height();
break;
case ui::ET_GESTURE_LONG_TAP:
gesture.type = WebInputEvent::GestureLongTap;
- gesture.data.longPress.width = data.details.bounding_box_f().width();
- gesture.data.longPress.height = data.details.bounding_box_f().height();
+ gesture.data.longPress.width = details.bounding_box_f().width();
+ gesture.data.longPress.height = details.bounding_box_f().height();
+ break;
+ case ui::ET_GESTURE_TWO_FINGER_TAP:
+ gesture.type = blink::WebInputEvent::GestureTwoFingerTap;
+ gesture.data.twoFingerTap.firstFingerWidth = details.first_finger_width();
+ gesture.data.twoFingerTap.firstFingerHeight =
+ details.first_finger_height();
break;
case ui::ET_GESTURE_SCROLL_BEGIN:
gesture.type = WebInputEvent::GestureScrollBegin;
- gesture.data.scrollBegin.deltaXHint = data.details.scroll_x_hint();
- gesture.data.scrollBegin.deltaYHint = data.details.scroll_y_hint();
+ gesture.data.scrollBegin.deltaXHint = details.scroll_x_hint();
+ gesture.data.scrollBegin.deltaYHint = details.scroll_y_hint();
break;
case ui::ET_GESTURE_SCROLL_UPDATE:
gesture.type = WebInputEvent::GestureScrollUpdate;
- gesture.data.scrollUpdate.deltaX = data.details.scroll_x();
- gesture.data.scrollUpdate.deltaY = data.details.scroll_y();
+ gesture.data.scrollUpdate.deltaX = details.scroll_x();
+ gesture.data.scrollUpdate.deltaY = details.scroll_y();
+ gesture.data.scrollUpdate.previousUpdateInSequencePrevented =
+ details.previous_scroll_update_in_sequence_prevented();
break;
case ui::ET_GESTURE_SCROLL_END:
gesture.type = WebInputEvent::GestureScrollEnd;
break;
case ui::ET_SCROLL_FLING_START:
gesture.type = WebInputEvent::GestureFlingStart;
- gesture.data.flingStart.velocityX = data.details.velocity_x();
- gesture.data.flingStart.velocityY = data.details.velocity_y();
+ gesture.data.flingStart.velocityX = details.velocity_x();
+ gesture.data.flingStart.velocityY = details.velocity_y();
break;
case ui::ET_SCROLL_FLING_CANCEL:
gesture.type = WebInputEvent::GestureFlingCancel;
@@ -353,7 +365,7 @@ WebGestureEvent CreateWebGestureEventFromGestureEventData(
break;
case ui::ET_GESTURE_PINCH_UPDATE:
gesture.type = WebInputEvent::GesturePinchUpdate;
- gesture.data.pinchUpdate.scale = data.details.scale();
+ gesture.data.pinchUpdate.scale = details.scale();
break;
case ui::ET_GESTURE_PINCH_END:
gesture.type = WebInputEvent::GesturePinchEnd;
@@ -363,22 +375,32 @@ WebGestureEvent CreateWebGestureEventFromGestureEventData(
break;
case ui::ET_GESTURE_TAP_DOWN:
gesture.type = WebInputEvent::GestureTapDown;
- gesture.data.tapDown.width = data.details.bounding_box_f().width();
- gesture.data.tapDown.height = data.details.bounding_box_f().height();
+ gesture.data.tapDown.width = details.bounding_box_f().width();
+ gesture.data.tapDown.height = details.bounding_box_f().height();
break;
case ui::ET_GESTURE_BEGIN:
case ui::ET_GESTURE_END:
- NOTREACHED() << "ET_GESTURE_BEGIN and ET_GESTURE_END are only produced "
- << "in Aura, and should never end up here.";
+ case ui::ET_GESTURE_SWIPE:
+ // The caller is responsible for discarding these gestures appropriately.
+ gesture.type = WebInputEvent::Undefined;
break;
default:
- NOTREACHED() << "ui::EventType provided wasn't a valid gesture event.";
- break;
+ NOTREACHED() << "ui::EventType provided wasn't a valid gesture event: "
+ << details.type();
}
return gesture;
}
+WebGestureEvent CreateWebGestureEventFromGestureEventData(
+ const ui::GestureEventData& data) {
+ return CreateWebGestureEvent(data.details,
+ data.time - base::TimeTicks(),
+ gfx::PointF(data.x, data.y),
+ gfx::PointF(data.raw_x, data.raw_y),
+ data.flags);
+}
+
int EventFlagsToWebEventModifiers(int flags) {
int modifiers = 0;
diff --git a/content/browser/renderer_host/input/web_input_event_util.h b/content/browser/renderer_host/input/web_input_event_util.h
index 1cadd7d..fb25037 100644
--- a/content/browser/renderer_host/input/web_input_event_util.h
+++ b/content/browser/renderer_host/input/web_input_event_util.h
@@ -5,12 +5,14 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_WEB_INPUT_EVENT_UTIL_H_
#define CONTENT_BROWSER_RENDERER_HOST_INPUT_WEB_INPUT_EVENT_UTIL_H_
+#include "base/time/time.h"
#include "content/common/content_export.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/events/keycodes/keyboard_codes.h"
namespace ui {
struct GestureEventData;
+struct GestureEventDetails;
class MotionEvent;
}
@@ -22,15 +24,19 @@ CONTENT_EXPORT void UpdateWindowsKeyCodeAndKeyIdentifier(
blink::WebKeyboardEvent* event,
ui::KeyboardCode windows_key_code);
-// Creates a WebTouchEvent from |event|, scaling all size components from
-// |event| by |scale|.
CONTENT_EXPORT blink::WebTouchEvent CreateWebTouchEventFromMotionEvent(
const ui::MotionEvent& event);
-// Creates a WebGestureEvent from |event|, scaling all size components from
-// |event| by |scale|.
-CONTENT_EXPORT blink::WebGestureEvent CreateWebGestureEventFromGestureEventData(
- const ui::GestureEventData& data);
+CONTENT_EXPORT blink::WebGestureEvent CreateWebGestureEvent(
+ const ui::GestureEventDetails& details,
+ base::TimeDelta timestamp,
+ const gfx::PointF& location,
+ const gfx::PointF& raw_location,
+ int flags);
+
+// Convenience wrapper for |CreateWebGestureEvent| using the supplied |data|.
+CONTENT_EXPORT blink::WebGestureEvent
+CreateWebGestureEventFromGestureEventData(const ui::GestureEventData& data);
int EventFlagsToWebEventModifiers(int flags);
diff --git a/content/browser/renderer_host/input/web_input_event_util_unittest.cc b/content/browser/renderer_host/input/web_input_event_util_unittest.cc
index 1d29a07..6d50575 100644
--- a/content/browser/renderer_host/input/web_input_event_util_unittest.cc
+++ b/content/browser/renderer_host/input/web_input_event_util_unittest.cc
@@ -13,7 +13,10 @@
#include "content/common/input/web_input_event_traits.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/event_constants.h"
+#include "ui/events/gesture_detection/gesture_event_data.h"
#include "ui/events/gesture_detection/motion_event_generic.h"
+#include "ui/events/gesture_event_details.h"
+#include "ui/gfx/geometry/safe_integer_conversions.h"
using blink::WebInputEvent;
using blink::WebTouchEvent;
@@ -58,4 +61,46 @@ TEST(WebInputEventUtilTest, MotionEventConversion) {
WebInputEventTraits::ToString(actual_event));
}
+TEST(WebInputEventUtilTest, ScrollUpdateConversion) {
+ int motion_event_id = 0;
+ MotionEvent::ToolType tool_type = MotionEvent::TOOL_TYPE_UNKNOWN;
+ base::TimeTicks timestamp = base::TimeTicks::Now();
+ gfx::Vector2dF delta(-5.f, 10.f);
+ gfx::PointF pos(1.f, 2.f);
+ gfx::PointF raw_pos(11.f, 12.f);
+ size_t touch_points = 1;
+ gfx::RectF rect(pos, gfx::SizeF());
+ int flags = 0;
+ ui::GestureEventDetails details(ui::ET_GESTURE_SCROLL_UPDATE,
+ delta.x(),
+ delta.y());
+ details.mark_previous_scroll_update_in_sequence_prevented();
+ ui::GestureEventData event(details,
+ motion_event_id,
+ tool_type,
+ timestamp,
+ pos.x(),
+ pos.y(),
+ raw_pos.x(),
+ raw_pos.y(),
+ touch_points,
+ rect,
+ flags);
+
+ blink::WebGestureEvent web_event =
+ CreateWebGestureEventFromGestureEventData(event);
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, web_event.type);
+ EXPECT_EQ(0, web_event.modifiers);
+ EXPECT_EQ((timestamp - base::TimeTicks()).InSecondsF(),
+ web_event.timeStampSeconds);
+ EXPECT_EQ(gfx::ToFlooredInt(pos.x()), web_event.x);
+ EXPECT_EQ(gfx::ToFlooredInt(pos.y()), web_event.y);
+ EXPECT_EQ(gfx::ToFlooredInt(raw_pos.x()), web_event.globalX);
+ EXPECT_EQ(gfx::ToFlooredInt(raw_pos.y()), web_event.globalY);
+ EXPECT_EQ(blink::WebGestureDeviceTouchscreen, web_event.sourceDevice);
+ EXPECT_EQ(delta.x(), web_event.data.scrollUpdate.deltaX);
+ EXPECT_EQ(delta.y(), web_event.data.scrollUpdate.deltaY);
+ EXPECT_TRUE(web_event.data.scrollUpdate.previousUpdateInSequencePrevented);
+}
+
} // namespace content
diff --git a/content/browser/renderer_host/ui_events_helper.cc b/content/browser/renderer_host/ui_events_helper.cc
index b514425..fc6509b 100644
--- a/content/browser/renderer_host/ui_events_helper.cc
+++ b/content/browser/renderer_host/ui_events_helper.cc
@@ -12,31 +12,6 @@
namespace {
-int WebModifiersToUIFlags(int modifiers) {
- int flags = ui::EF_NONE;
-
- if (modifiers & blink::WebInputEvent::ShiftKey)
- flags |= ui::EF_SHIFT_DOWN;
- if (modifiers & blink::WebInputEvent::ControlKey)
- flags |= ui::EF_CONTROL_DOWN;
- if (modifiers & blink::WebInputEvent::AltKey)
- flags |= ui::EF_ALT_DOWN;
- if (modifiers & blink::WebInputEvent::MetaKey)
- flags |= ui::EF_COMMAND_DOWN;
-
- if (modifiers & blink::WebInputEvent::LeftButtonDown)
- flags |= ui::EF_LEFT_MOUSE_BUTTON;
- if (modifiers & blink::WebInputEvent::RightButtonDown)
- flags |= ui::EF_RIGHT_MOUSE_BUTTON;
- if (modifiers & blink::WebInputEvent::MiddleButtonDown)
- flags |= ui::EF_MIDDLE_MOUSE_BUTTON;
-
- if (modifiers & blink::WebInputEvent::CapsLockOn)
- flags |= ui::EF_CAPS_LOCK_DOWN;
-
- return flags;
-}
-
ui::EventType WebTouchPointStateToEventType(
blink::WebTouchPoint::State state) {
switch (state) {
@@ -117,7 +92,7 @@ bool MakeUITouchEventsFromWebTouchEvents(
return false;
}
- int flags = WebModifiersToUIFlags(touch.modifiers);
+ int flags = WebEventModifiersToEventFlags(touch.modifiers);
base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds(
static_cast<int64>(touch.timeStampSeconds * 1000000));
for (unsigned i = 0; i < touch.touchesLength; ++i) {
@@ -147,100 +122,11 @@ bool MakeUITouchEventsFromWebTouchEvents(
blink::WebGestureEvent MakeWebGestureEventFromUIEvent(
const ui::GestureEvent& event) {
- blink::WebGestureEvent gesture_event;
-
- switch (event.type()) {
- case ui::ET_GESTURE_TAP:
- gesture_event.type = blink::WebInputEvent::GestureTap;
- gesture_event.data.tap.tapCount = event.details().tap_count();
- gesture_event.data.tap.width = event.details().bounding_box().width();
- gesture_event.data.tap.height = event.details().bounding_box().height();
- break;
- case ui::ET_GESTURE_TAP_DOWN:
- gesture_event.type = blink::WebInputEvent::GestureTapDown;
- gesture_event.data.tapDown.width =
- event.details().bounding_box().width();
- gesture_event.data.tapDown.height =
- event.details().bounding_box().height();
- break;
- case ui::ET_GESTURE_SHOW_PRESS:
- gesture_event.type = blink::WebInputEvent::GestureShowPress;
- gesture_event.data.showPress.width =
- event.details().bounding_box().width();
- gesture_event.data.showPress.height =
- event.details().bounding_box().height();
- break;
- case ui::ET_GESTURE_TAP_CANCEL:
- gesture_event.type = blink::WebInputEvent::GestureTapCancel;
- break;
- case ui::ET_GESTURE_SCROLL_BEGIN:
- gesture_event.type = blink::WebInputEvent::GestureScrollBegin;
- gesture_event.data.scrollBegin.deltaXHint =
- event.details().scroll_x_hint();
- gesture_event.data.scrollBegin.deltaYHint =
- event.details().scroll_y_hint();
- break;
- case ui::ET_GESTURE_SCROLL_UPDATE:
- gesture_event.type = blink::WebInputEvent::GestureScrollUpdate;
- gesture_event.data.scrollUpdate.deltaX = event.details().scroll_x();
- gesture_event.data.scrollUpdate.deltaY = event.details().scroll_y();
- break;
- case ui::ET_GESTURE_SCROLL_END:
- gesture_event.type = blink::WebInputEvent::GestureScrollEnd;
- break;
- case ui::ET_GESTURE_PINCH_BEGIN:
- gesture_event.type = blink::WebInputEvent::GesturePinchBegin;
- break;
- case ui::ET_GESTURE_PINCH_UPDATE:
- gesture_event.type = blink::WebInputEvent::GesturePinchUpdate;
- gesture_event.data.pinchUpdate.scale = event.details().scale();
- break;
- case ui::ET_GESTURE_PINCH_END:
- gesture_event.type = blink::WebInputEvent::GesturePinchEnd;
- break;
- case ui::ET_SCROLL_FLING_START:
- gesture_event.type = blink::WebInputEvent::GestureFlingStart;
- gesture_event.data.flingStart.velocityX = event.details().velocity_x();
- gesture_event.data.flingStart.velocityY = event.details().velocity_y();
- break;
- case ui::ET_SCROLL_FLING_CANCEL:
- gesture_event.type = blink::WebInputEvent::GestureFlingCancel;
- break;
- case ui::ET_GESTURE_LONG_PRESS:
- gesture_event.type = blink::WebInputEvent::GestureLongPress;
- gesture_event.data.longPress.width =
- event.details().bounding_box().width();
- gesture_event.data.longPress.height =
- event.details().bounding_box().height();
- break;
- case ui::ET_GESTURE_LONG_TAP:
- gesture_event.type = blink::WebInputEvent::GestureLongTap;
- gesture_event.data.longPress.width =
- event.details().bounding_box().width();
- gesture_event.data.longPress.height =
- event.details().bounding_box().height();
- break;
- case ui::ET_GESTURE_TWO_FINGER_TAP:
- gesture_event.type = blink::WebInputEvent::GestureTwoFingerTap;
- gesture_event.data.twoFingerTap.firstFingerWidth =
- event.details().first_finger_width();
- gesture_event.data.twoFingerTap.firstFingerHeight =
- event.details().first_finger_height();
- break;
- case ui::ET_GESTURE_BEGIN:
- case ui::ET_GESTURE_END:
- case ui::ET_GESTURE_SWIPE:
- gesture_event.type = blink::WebInputEvent::Undefined;
- break;
- default:
- NOTREACHED() << "Unknown gesture type: " << event.type();
- }
-
- gesture_event.sourceDevice = blink::WebGestureDeviceTouchscreen;
- gesture_event.modifiers = EventFlagsToWebEventModifiers(event.flags());
- gesture_event.timeStampSeconds = event.time_stamp().InSecondsF();
-
- return gesture_event;
+ return CreateWebGestureEvent(event.details(),
+ event.time_stamp(),
+ event.location_f(),
+ event.root_location_f(),
+ event.flags());
}
blink::WebTouchPoint* UpdateWebTouchEventFromUIEvent(
diff --git a/content/browser/renderer_host/ui_events_helper.h b/content/browser/renderer_host/ui_events_helper.h
index 883ba48..f2dac18 100644
--- a/content/browser/renderer_host/ui_events_helper.h
+++ b/content/browser/renderer_host/ui_events_helper.h
@@ -48,8 +48,6 @@ CONTENT_EXPORT bool MakeUITouchEventsFromWebTouchEvents(
blink::WebGestureEvent MakeWebGestureEventFromUIEvent(
const ui::GestureEvent& event);
-int EventFlagsToWebEventModifiers(int flags);
-
// Updates the WebTouchEvent based on the TouchEvent. It returns the updated
// WebTouchPoint contained in the WebTouchEvent, or NULL if no point was
// updated.
diff --git a/content/common/input/gesture_event_stream_validator.cc b/content/common/input/gesture_event_stream_validator.cc
index 09b88c8..4bb7e05 100644
--- a/content/common/input/gesture_event_stream_validator.cc
+++ b/content/common/input/gesture_event_stream_validator.cc
@@ -5,6 +5,8 @@
#include "content/common/input/gesture_event_stream_validator.h"
#include "base/logging.h"
+#include "base/strings/stringprintf.h"
+#include "content/common/input/web_input_event_traits.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
using blink::WebInputEvent;
@@ -22,6 +24,10 @@ bool GestureEventStreamValidator::Validate(const blink::WebGestureEvent& event,
std::string* error_msg) {
DCHECK(error_msg);
error_msg->clear();
+ if (!WebInputEvent::isGestureEventType(event.type)) {
+ error_msg->append(base::StringPrintf(
+ "Invalid gesture type: %s", WebInputEventTraits::GetName(event.type)));
+ }
switch (event.type) {
case WebInputEvent::GestureScrollBegin:
if (scrolling_)
diff --git a/content/common/input/web_input_event_traits.cc b/content/common/input/web_input_event_traits.cc
index 4515dce..087cf61 100644
--- a/content/common/input/web_input_event_traits.cc
+++ b/content/common/input/web_input_event_traits.cc
@@ -267,6 +267,9 @@ void Coalesce(const WebGestureEvent& event_to_coalesce,
event_to_coalesce.data.scrollUpdate.deltaX;
event->data.scrollUpdate.deltaY +=
event_to_coalesce.data.scrollUpdate.deltaY;
+ DCHECK_EQ(
+ event->data.scrollUpdate.previousUpdateInSequencePrevented,
+ event_to_coalesce.data.scrollUpdate.previousUpdateInSequencePrevented);
} else if (event->type == WebInputEvent::GesturePinchUpdate) {
event->data.pinchUpdate.scale *= event_to_coalesce.data.pinchUpdate.scale;
// Ensure the scale remains bounded above 0 and below Infinity so that
diff --git a/ui/events/gesture_detection/gesture_event_data.cc b/ui/events/gesture_detection/gesture_event_data.cc
index 2102f23..b166ffa 100644
--- a/ui/events/gesture_detection/gesture_event_data.cc
+++ b/ui/events/gesture_detection/gesture_event_data.cc
@@ -36,7 +36,7 @@ GestureEventData::GestureEventData(const GestureEventDetails& details,
GestureEventData::GestureEventData(EventType type,
const GestureEventData& other)
- : details(type),
+ : details(type, other.details),
motion_event_id(other.motion_event_id),
primary_tool_type(other.primary_tool_type),
time(other.time),
diff --git a/ui/events/gesture_detection/touch_disposition_gesture_filter.cc b/ui/events/gesture_detection/touch_disposition_gesture_filter.cc
index fcb92d4..564d014 100644
--- a/ui/events/gesture_detection/touch_disposition_gesture_filter.cc
+++ b/ui/events/gesture_detection/touch_disposition_gesture_filter.cc
@@ -314,6 +314,15 @@ void TouchDispositionGestureFilter::SendGesture(
ending_event_primary_tool_type_ = event.primary_tool_type;
needs_scroll_ending_event_ = true;
break;
+ case ET_GESTURE_SCROLL_UPDATE:
+ if (state_.HasFilteredGestureType(ET_GESTURE_SCROLL_UPDATE)) {
+ GestureEventData modified_event(ET_GESTURE_SCROLL_UPDATE, event);
+ modified_event.details
+ .mark_previous_scroll_update_in_sequence_prevented();
+ client_->ForwardGestureEvent(modified_event);
+ return;
+ }
+ break;
case ET_GESTURE_SCROLL_END:
needs_scroll_ending_event_ = false;
break;
@@ -418,10 +427,17 @@ bool TouchDispositionGestureFilter::GestureHandlingState::Filter(
last_gesture_of_type_dropped_.has_bit(
GetGestureTypeIndex(antecedent_event_type)))) {
last_gesture_of_type_dropped_.mark_bit(GetGestureTypeIndex(gesture_type));
+ any_gesture_of_type_dropped_.mark_bit(GetGestureTypeIndex(gesture_type));
return true;
}
last_gesture_of_type_dropped_.clear_bit(GetGestureTypeIndex(gesture_type));
return false;
}
+bool TouchDispositionGestureFilter::GestureHandlingState::
+ HasFilteredGestureType(EventType gesture_type) const {
+ return any_gesture_of_type_dropped_.has_bit(
+ GetGestureTypeIndex(gesture_type));
+}
+
} // namespace content
diff --git a/ui/events/gesture_detection/touch_disposition_gesture_filter.h b/ui/events/gesture_detection/touch_disposition_gesture_filter.h
index 290afaa..5895a6b 100644
--- a/ui/events/gesture_detection/touch_disposition_gesture_filter.h
+++ b/ui/events/gesture_detection/touch_disposition_gesture_filter.h
@@ -66,14 +66,18 @@ class GESTURE_DETECTION_EXPORT TouchDispositionGestureFilter {
// Returns true iff the gesture should be dropped.
bool Filter(EventType type);
+ // Whether an event of |type| has been filtered from the current sequence.
+ bool HasFilteredGestureType(EventType type) const;
+
private:
// True iff the sequence has had any touch down event consumed.
bool start_touch_consumed_;
// True iff the most recently ack'ed touch event was consumed.
bool current_touch_consumed_;
- // If the previous gesture of a given type was dropped instead of being
- // dispatched, its type will occur in this set.
+ // Indicates whether the previous gesture of a given type was dropped.
BitSet32 last_gesture_of_type_dropped_;
+ // Indicates whether *any* previous gesture of a given type was dropped.
+ BitSet32 any_gesture_of_type_dropped_;
};
void FilterAndSendPacket(const GestureEventDataPacket& packet);
diff --git a/ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc b/ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc
index 5d823b7..eb77e64 100644
--- a/ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc
+++ b/ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc
@@ -179,9 +179,13 @@ class TouchDispositionGestureFilterTest
bool GesturesSent() const { return !sent_gestures_.empty(); }
- base::TimeTicks LastSentGestureTime() const {
+ const GestureEventData& last_sent_gesture() const {
CHECK(last_sent_gesture_);
- return last_sent_gesture_->time;
+ return *last_sent_gesture_;
+ }
+
+ base::TimeTicks LastSentGestureTime() const {
+ return last_sent_gesture().time;
}
base::TimeTicks CurrentTouchTime() const {
@@ -197,18 +201,15 @@ class TouchDispositionGestureFilterTest
}
gfx::PointF LastSentGestureLocation() const {
- CHECK(last_sent_gesture_);
- return gfx::PointF(last_sent_gesture_->x, last_sent_gesture_->y);
+ return gfx::PointF(last_sent_gesture().x, last_sent_gesture().y);
}
gfx::PointF LastSentGestureRawLocation() const {
- CHECK(last_sent_gesture_);
- return gfx::PointF(last_sent_gesture_->raw_x, last_sent_gesture_->raw_y);
+ return gfx::PointF(last_sent_gesture().raw_x, last_sent_gesture().raw_y);
}
int LastSentGestureFlags() const {
- CHECK(last_sent_gesture_);
- return last_sent_gesture_->flags;
+ return last_sent_gesture().flags;
}
const gfx::RectF& ShowPressBoundingBox() const {
@@ -1148,4 +1149,44 @@ TEST_F(TouchDispositionGestureFilterTest, EventFlagPropagation) {
EXPECT_EQ(0, LastSentGestureFlags());
}
+
+TEST_F(TouchDispositionGestureFilterTest, PreviousScrollPrevented) {
+ PushGesture(ET_GESTURE_BEGIN);
+ PressTouchPoint(1, 1);
+ EXPECT_FALSE(GesturesSent());
+ SendTouchNotConsumedAck();
+ EXPECT_TRUE(
+ GesturesMatch(Gestures(ET_GESTURE_BEGIN), GetAndResetSentGestures()));
+
+ // The sent scroll update should always reflect whether any preceding scroll
+ // update has been dropped.
+ PushGesture(ET_GESTURE_SCROLL_UPDATE);
+ MoveTouchPoint(0, 2, 2);
+ SendTouchNotConsumedAck();
+ ASSERT_TRUE(GesturesSent());
+ EXPECT_FALSE(last_sent_gesture()
+ .details.previous_scroll_update_in_sequence_prevented());
+ GetAndResetSentGestures();
+
+ PushGesture(ET_GESTURE_SCROLL_UPDATE);
+ MoveTouchPoint(0, -2, -2);
+ SendTouchConsumedAck();
+ EXPECT_FALSE(GesturesSent());
+
+ PushGesture(ET_GESTURE_SCROLL_UPDATE);
+ MoveTouchPoint(0, 2, 2);
+ SendTouchNotConsumedAck();
+ ASSERT_TRUE(GesturesSent());
+ EXPECT_TRUE(last_sent_gesture()
+ .details.previous_scroll_update_in_sequence_prevented());
+ GetAndResetSentGestures();
+
+ PushGesture(ET_GESTURE_SCROLL_UPDATE);
+ MoveTouchPoint(0, 2, 2);
+ SendTouchNotConsumedAck();
+ ASSERT_TRUE(GesturesSent());
+ EXPECT_TRUE(last_sent_gesture()
+ .details.previous_scroll_update_in_sequence_prevented());
+}
+
} // namespace ui
diff --git a/ui/events/gesture_event_details.cc b/ui/events/gesture_event_details.cc
index 7807131..e14fb17 100644
--- a/ui/events/gesture_event_details.cc
+++ b/ui/events/gesture_event_details.cc
@@ -24,30 +24,30 @@ GestureEventDetails::GestureEventDetails(ui::EventType type,
DCHECK_LE(type, ET_GESTURE_TYPE_END);
switch (type_) {
case ui::ET_GESTURE_SCROLL_BEGIN:
- data.scroll_begin.x_hint = delta_x;
- data.scroll_begin.y_hint = delta_y;
+ data_.scroll_begin.x_hint = delta_x;
+ data_.scroll_begin.y_hint = delta_y;
break;
case ui::ET_GESTURE_SCROLL_UPDATE:
- data.scroll_update.x = delta_x;
- data.scroll_update.y = delta_y;
+ data_.scroll_update.x = delta_x;
+ data_.scroll_update.y = delta_y;
break;
case ui::ET_SCROLL_FLING_START:
- data.fling_velocity.x = delta_x;
- data.fling_velocity.y = delta_y;
+ data_.fling_velocity.x = delta_x;
+ data_.fling_velocity.y = delta_y;
break;
case ui::ET_GESTURE_TWO_FINGER_TAP:
- data.first_finger_enclosing_rectangle.width = delta_x;
- data.first_finger_enclosing_rectangle.height = delta_y;
+ data_.first_finger_enclosing_rectangle.width = delta_x;
+ data_.first_finger_enclosing_rectangle.height = delta_y;
break;
case ui::ET_GESTURE_SWIPE:
- data.swipe.left = delta_x < 0;
- data.swipe.right = delta_x > 0;
- data.swipe.up = delta_y < 0;
- data.swipe.down = delta_y > 0;
+ data_.swipe.left = delta_x < 0;
+ data_.swipe.right = delta_x > 0;
+ data_.swipe.up = delta_y < 0;
+ data_.swipe.down = delta_y > 0;
break;
default:
@@ -55,6 +55,33 @@ GestureEventDetails::GestureEventDetails(ui::EventType type,
}
}
+GestureEventDetails::GestureEventDetails(ui::EventType type,
+ const GestureEventDetails& other)
+ : type_(type),
+ data_(other.data_),
+ touch_points_(other.touch_points_),
+ bounding_box_(other.bounding_box_),
+ oldest_touch_id_(other.oldest_touch_id_) {
+ DCHECK_GE(type, ET_GESTURE_TYPE_START);
+ DCHECK_LE(type, ET_GESTURE_TYPE_END);
+ switch (type) {
+ case ui::ET_GESTURE_SCROLL_BEGIN:
+ // Synthetic creation of SCROLL_BEGIN from PINCH_BEGIN is explicitly
+ // allowed as an exception.
+ if (other.type() == ui::ET_GESTURE_PINCH_BEGIN)
+ break;
+ case ui::ET_GESTURE_SCROLL_UPDATE:
+ case ui::ET_SCROLL_FLING_START:
+ case ui::ET_GESTURE_SWIPE:
+ case ui::ET_GESTURE_PINCH_UPDATE:
+ DCHECK_EQ(type, other.type()) << " - Invalid gesture conversion from "
+ << other.type() << " to " << type;
+ break;
+ default:
+ break;
+ }
+}
+
GestureEventDetails::Details::Details() {
memset(this, 0, sizeof(Details));
}
diff --git a/ui/events/gesture_event_details.h b/ui/events/gesture_event_details.h
index da7a60b..66b28b9 100644
--- a/ui/events/gesture_event_details.h
+++ b/ui/events/gesture_event_details.h
@@ -19,6 +19,10 @@ struct EVENTS_BASE_EXPORT GestureEventDetails {
explicit GestureEventDetails(EventType type);
GestureEventDetails(EventType type, float delta_x, float delta_y);
+ // The caller is responsible for ensuring that the gesture data from |other|
+ // is compatible and sufficient for that expected by gestures of |type|.
+ GestureEventDetails(EventType type, const GestureEventDetails& other);
+
EventType type() const { return type_; }
int touch_points() const { return touch_points_; }
@@ -46,74 +50,74 @@ struct EVENTS_BASE_EXPORT GestureEventDetails {
float scroll_x_hint() const {
DCHECK_EQ(ET_GESTURE_SCROLL_BEGIN, type_);
- return data.scroll_begin.x_hint;
+ return data_.scroll_begin.x_hint;
}
float scroll_y_hint() const {
DCHECK_EQ(ET_GESTURE_SCROLL_BEGIN, type_);
- return data.scroll_begin.y_hint;
+ return data_.scroll_begin.y_hint;
}
float scroll_x() const {
DCHECK_EQ(ET_GESTURE_SCROLL_UPDATE, type_);
- return data.scroll_update.x;
+ return data_.scroll_update.x;
}
float scroll_y() const {
DCHECK_EQ(ET_GESTURE_SCROLL_UPDATE, type_);
- return data.scroll_update.y;
+ return data_.scroll_update.y;
}
float velocity_x() const {
DCHECK_EQ(ET_SCROLL_FLING_START, type_);
- return data.fling_velocity.x;
+ return data_.fling_velocity.x;
}
float velocity_y() const {
DCHECK_EQ(ET_SCROLL_FLING_START, type_);
- return data.fling_velocity.y;
+ return data_.fling_velocity.y;
}
float first_finger_width() const {
DCHECK_EQ(ET_GESTURE_TWO_FINGER_TAP, type_);
- return data.first_finger_enclosing_rectangle.width;
+ return data_.first_finger_enclosing_rectangle.width;
}
float first_finger_height() const {
DCHECK_EQ(ET_GESTURE_TWO_FINGER_TAP, type_);
- return data.first_finger_enclosing_rectangle.height;
+ return data_.first_finger_enclosing_rectangle.height;
}
float scale() const {
DCHECK_EQ(ET_GESTURE_PINCH_UPDATE, type_);
- return data.scale;
+ return data_.scale;
}
bool swipe_left() const {
DCHECK_EQ(ET_GESTURE_SWIPE, type_);
- return data.swipe.left;
+ return data_.swipe.left;
}
bool swipe_right() const {
DCHECK_EQ(ET_GESTURE_SWIPE, type_);
- return data.swipe.right;
+ return data_.swipe.right;
}
bool swipe_up() const {
DCHECK_EQ(ET_GESTURE_SWIPE, type_);
- return data.swipe.up;
+ return data_.swipe.up;
}
bool swipe_down() const {
DCHECK_EQ(ET_GESTURE_SWIPE, type_);
- return data.swipe.down;
+ return data_.swipe.down;
}
int tap_count() const {
DCHECK(type_ == ET_GESTURE_TAP ||
type_ == ET_GESTURE_TAP_UNCONFIRMED ||
type_ == ET_GESTURE_DOUBLE_TAP);
- return data.tap_count;
+ return data_.tap_count;
}
void set_tap_count(int tap_count) {
@@ -121,13 +125,23 @@ struct EVENTS_BASE_EXPORT GestureEventDetails {
DCHECK(type_ == ET_GESTURE_TAP ||
type_ == ET_GESTURE_TAP_UNCONFIRMED ||
type_ == ET_GESTURE_DOUBLE_TAP);
- data.tap_count = tap_count;
+ data_.tap_count = tap_count;
}
void set_scale(float scale) {
DCHECK_GE(scale, 0.0f);
DCHECK_EQ(type_, ET_GESTURE_PINCH_UPDATE);
- data.scale = scale;
+ data_.scale = scale;
+ }
+
+ void mark_previous_scroll_update_in_sequence_prevented() {
+ DCHECK_EQ(ET_GESTURE_SCROLL_UPDATE, type_);
+ data_.scroll_update.previous_update_in_sequence_prevented = true;
+ }
+
+ bool previous_scroll_update_in_sequence_prevented() const {
+ DCHECK_EQ(ET_GESTURE_SCROLL_UPDATE, type_);
+ return data_.scroll_update.previous_update_in_sequence_prevented;
}
private:
@@ -144,6 +158,9 @@ struct EVENTS_BASE_EXPORT GestureEventDetails {
struct { // SCROLL delta.
float x;
float y;
+ // Whether any previous scroll update in the current scroll sequence was
+ // suppressed because the underlying touch was consumed.
+ bool previous_update_in_sequence_prevented;
} scroll_update;
float scale; // PINCH scale.
@@ -170,7 +187,7 @@ struct EVENTS_BASE_EXPORT GestureEventDetails {
// Tap information must be set for ET_GESTURE_TAP,
// ET_GESTURE_TAP_UNCONFIRMED, and ET_GESTURE_DOUBLE_TAP events.
int tap_count; // TAP repeat count.
- } data;
+ } data_;
int touch_points_; // Number of active touch points in the gesture.