Commit c2693b64 authored by dgozman@chromium.org's avatar dgozman@chromium.org

Touch emulator: allow multiple touch streams.

    
When both native and emulated touch streams are available,
we should block one stream while another is active.
To achieve this RenderWidgetHostImpl gives TouchEmulator a chance
to handle native touch event, so it can be effectively blocked.
    
BUG=384522

Review URL: https://codereview.chromium.org/375863005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@284475 0039d316-1c4b-4281-b951-d872f2087c98
parent 1aca1931
...@@ -47,7 +47,9 @@ TouchEmulator::TouchEmulator(TouchEmulatorClient* client) ...@@ -47,7 +47,9 @@ TouchEmulator::TouchEmulator(TouchEmulatorClient* client)
: client_(client), : client_(client),
gesture_provider_(GetGestureProviderConfig(), this), gesture_provider_(GetGestureProviderConfig(), this),
enabled_(false), enabled_(false),
allow_pinch_(false) { allow_pinch_(false),
emulated_stream_active_sequence_count_(0),
native_stream_active_sequence_count_(0) {
DCHECK(client_); DCHECK(client_);
ResetState(); ResetState();
...@@ -85,7 +87,6 @@ void TouchEmulator::ResetState() { ...@@ -85,7 +87,6 @@ void TouchEmulator::ResetState() {
last_mouse_move_timestamp_ = 0; last_mouse_move_timestamp_ = 0;
mouse_pressed_ = false; mouse_pressed_ = false;
shift_pressed_ = false; shift_pressed_ = false;
touch_active_ = false;
suppress_next_fling_cancel_ = false; suppress_next_fling_cancel_ = false;
pinch_scale_ = 1.f; pinch_scale_ = 1.f;
pinch_gesture_active_ = false; pinch_gesture_active_ = false;
...@@ -155,7 +156,7 @@ bool TouchEmulator::HandleMouseEvent(const WebMouseEvent& mouse_event) { ...@@ -155,7 +156,7 @@ bool TouchEmulator::HandleMouseEvent(const WebMouseEvent& mouse_event) {
if (FillTouchEventAndPoint(mouse_event) && if (FillTouchEventAndPoint(mouse_event) &&
gesture_provider_.OnTouchEvent(MotionEventWeb(touch_event_))) { gesture_provider_.OnTouchEvent(MotionEventWeb(touch_event_))) {
client_->ForwardTouchEvent(touch_event_); ForwardTouchEventToClient();
} }
// Do not pass mouse events to the renderer. // Do not pass mouse events to the renderer.
...@@ -167,7 +168,7 @@ bool TouchEmulator::HandleMouseWheelEvent(const WebMouseWheelEvent& event) { ...@@ -167,7 +168,7 @@ bool TouchEmulator::HandleMouseWheelEvent(const WebMouseWheelEvent& event) {
return false; return false;
// Send mouse wheel for easy scrolling when there is no active touch. // Send mouse wheel for easy scrolling when there is no active touch.
return touch_active_; return emulated_stream_active_sequence_count_ > 0;
} }
bool TouchEmulator::HandleKeyboardEvent(const WebKeyboardEvent& event) { bool TouchEmulator::HandleKeyboardEvent(const WebKeyboardEvent& event) {
...@@ -193,11 +194,59 @@ bool TouchEmulator::HandleKeyboardEvent(const WebKeyboardEvent& event) { ...@@ -193,11 +194,59 @@ bool TouchEmulator::HandleKeyboardEvent(const WebKeyboardEvent& event) {
return false; return false;
} }
bool TouchEmulator::HandleTouchEventAck(InputEventAckState ack_result) { bool TouchEmulator::HandleTouchEvent(const blink::WebTouchEvent& event) {
const bool event_consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED; // Block native event when emulated touch stream is active.
gesture_provider_.OnTouchEventAck(event_consumed); if (emulated_stream_active_sequence_count_)
// TODO(dgozman): Disable emulation when real touch events are available. return true;
return true;
bool is_sequence_start = WebTouchEventTraits::IsTouchSequenceStart(event);
// Do not allow middle-sequence event to pass through, if start was blocked.
if (!native_stream_active_sequence_count_ && !is_sequence_start)
return true;
if (is_sequence_start)
native_stream_active_sequence_count_++;
return false;
}
void TouchEmulator::ForwardTouchEventToClient() {
const bool event_consumed = true;
// Block emulated event when emulated native stream is active.
if (native_stream_active_sequence_count_) {
gesture_provider_.OnTouchEventAck(event_consumed);
return;
}
bool is_sequence_start =
WebTouchEventTraits::IsTouchSequenceStart(touch_event_);
// Do not allow middle-sequence event to pass through, if start was blocked.
if (!emulated_stream_active_sequence_count_ && !is_sequence_start) {
gesture_provider_.OnTouchEventAck(event_consumed);
return;
}
if (is_sequence_start)
emulated_stream_active_sequence_count_++;
client_->ForwardEmulatedTouchEvent(touch_event_);
}
bool TouchEmulator::HandleTouchEventAck(
const blink::WebTouchEvent& event, InputEventAckState ack_result) {
bool is_sequence_end = WebTouchEventTraits::IsTouchSequenceEnd(event);
if (emulated_stream_active_sequence_count_) {
if (is_sequence_end)
emulated_stream_active_sequence_count_--;
const bool event_consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
gesture_provider_.OnTouchEventAck(event_consumed);
return true;
}
// We may have not seen native touch sequence start (when created in the
// middle of a sequence), so don't decrement sequence count below zero.
if (is_sequence_end && native_stream_active_sequence_count_)
native_stream_active_sequence_count_--;
return false;
} }
void TouchEmulator::OnGestureEvent(const ui::GestureEventData& gesture) { void TouchEmulator::OnGestureEvent(const ui::GestureEventData& gesture) {
...@@ -267,16 +316,15 @@ void TouchEmulator::OnGestureEvent(const ui::GestureEventData& gesture) { ...@@ -267,16 +316,15 @@ void TouchEmulator::OnGestureEvent(const ui::GestureEventData& gesture) {
} }
void TouchEmulator::CancelTouch() { void TouchEmulator::CancelTouch() {
if (!touch_active_) if (!emulated_stream_active_sequence_count_)
return; return;
WebTouchEventTraits::ResetTypeAndTouchStates( WebTouchEventTraits::ResetTypeAndTouchStates(
WebInputEvent::TouchCancel, WebInputEvent::TouchCancel,
(base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(), (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(),
&touch_event_); &touch_event_);
touch_active_ = false;
if (gesture_provider_.OnTouchEvent(MotionEventWeb(touch_event_))) if (gesture_provider_.OnTouchEvent(MotionEventWeb(touch_event_)))
client_->ForwardTouchEvent(touch_event_); ForwardTouchEventToClient();
} }
void TouchEmulator::UpdateCursor() { void TouchEmulator::UpdateCursor() {
...@@ -352,14 +400,12 @@ bool TouchEmulator::FillTouchEventAndPoint(const WebMouseEvent& mouse_event) { ...@@ -352,14 +400,12 @@ bool TouchEmulator::FillTouchEventAndPoint(const WebMouseEvent& mouse_event) {
switch (mouse_event.type) { switch (mouse_event.type) {
case WebInputEvent::MouseDown: case WebInputEvent::MouseDown:
eventType = WebInputEvent::TouchStart; eventType = WebInputEvent::TouchStart;
touch_active_ = true;
break; break;
case WebInputEvent::MouseMove: case WebInputEvent::MouseMove:
eventType = WebInputEvent::TouchMove; eventType = WebInputEvent::TouchMove;
break; break;
case WebInputEvent::MouseUp: case WebInputEvent::MouseUp:
eventType = WebInputEvent::TouchEnd; eventType = WebInputEvent::TouchEnd;
touch_active_ = false;
break; break;
default: default:
eventType = WebInputEvent::Undefined; eventType = WebInputEvent::Undefined;
......
...@@ -23,15 +23,22 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient { ...@@ -23,15 +23,22 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
void Enable(bool allow_pinch); void Enable(bool allow_pinch);
void Disable(); void Disable();
// Returns |true| if the event was consumed. // Note that TouchEmulator should always listen to touch events and their acks
// (even in disabled state) to track native stream presence.
bool enabled() const { return enabled_; }
// Returns |true| if the event was consumed. Consumed event should not
// propagate any further.
// TODO(dgozman): maybe pass latency info together with events. // TODO(dgozman): maybe pass latency info together with events.
bool HandleMouseEvent(const blink::WebMouseEvent& event); bool HandleMouseEvent(const blink::WebMouseEvent& event);
bool HandleMouseWheelEvent(const blink::WebMouseWheelEvent& event); bool HandleMouseWheelEvent(const blink::WebMouseWheelEvent& event);
bool HandleKeyboardEvent(const blink::WebKeyboardEvent& event); bool HandleKeyboardEvent(const blink::WebKeyboardEvent& event);
bool HandleTouchEvent(const blink::WebTouchEvent& event);
// Returns |true| if the event ack was consumed. Consumed ack should not // Returns |true| if the event ack was consumed. Consumed ack should not
// propagate any further. // propagate any further.
bool HandleTouchEventAck(InputEventAckState ack_result); bool HandleTouchEventAck(const blink::WebTouchEvent& event,
InputEventAckState ack_result);
// Cancel any touches, for example, when focus is lost. // Cancel any touches, for example, when focus is lost.
void CancelTouch(); void CancelTouch();
...@@ -59,6 +66,8 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient { ...@@ -59,6 +66,8 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
void PinchEnd(const blink::WebGestureEvent& event); void PinchEnd(const blink::WebGestureEvent& event);
void ScrollEnd(const blink::WebGestureEvent& event); void ScrollEnd(const blink::WebGestureEvent& event);
void ForwardTouchEventToClient();
TouchEmulatorClient* const client_; TouchEmulatorClient* const client_;
ui::FilteredGestureProvider gesture_provider_; ui::FilteredGestureProvider gesture_provider_;
...@@ -83,7 +92,8 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient { ...@@ -83,7 +92,8 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
bool shift_pressed_; bool shift_pressed_;
blink::WebTouchEvent touch_event_; blink::WebTouchEvent touch_event_;
bool touch_active_; int emulated_stream_active_sequence_count_;
int native_stream_active_sequence_count_;
// Whether we should suppress next fling cancel. This may happen when we // Whether we should suppress next fling cancel. This may happen when we
// did not send fling start in pinch mode. // did not send fling start in pinch mode.
......
...@@ -17,7 +17,7 @@ class CONTENT_EXPORT TouchEmulatorClient { ...@@ -17,7 +17,7 @@ class CONTENT_EXPORT TouchEmulatorClient {
virtual ~TouchEmulatorClient() {} virtual ~TouchEmulatorClient() {}
virtual void ForwardGestureEvent(const blink::WebGestureEvent& event) = 0; virtual void ForwardGestureEvent(const blink::WebGestureEvent& event) = 0;
virtual void ForwardTouchEvent(const blink::WebTouchEvent& event) = 0; virtual void ForwardEmulatedTouchEvent(const blink::WebTouchEvent& event) = 0;
virtual void SetCursor(const WebCursor& cursor) = 0; virtual void SetCursor(const WebCursor& cursor) = 0;
}; };
......
...@@ -71,7 +71,7 @@ class TouchEmulatorTest : public testing::Test, ...@@ -71,7 +71,7 @@ class TouchEmulatorTest : public testing::Test,
forwarded_events_.push_back(event.type); forwarded_events_.push_back(event.type);
} }
virtual void ForwardTouchEvent( virtual void ForwardEmulatedTouchEvent(
const blink::WebTouchEvent& event) OVERRIDE { const blink::WebTouchEvent& event) OVERRIDE {
forwarded_events_.push_back(event.type); forwarded_events_.push_back(event.type);
EXPECT_EQ(1U, event.touchesLength); EXPECT_EQ(1U, event.touchesLength);
...@@ -79,7 +79,8 @@ class TouchEmulatorTest : public testing::Test, ...@@ -79,7 +79,8 @@ class TouchEmulatorTest : public testing::Test,
EXPECT_EQ(last_mouse_y_, event.touches[0].position.y); EXPECT_EQ(last_mouse_y_, event.touches[0].position.y);
int expectedCancelable = event.type != WebInputEvent::TouchCancel; int expectedCancelable = event.type != WebInputEvent::TouchCancel;
EXPECT_EQ(expectedCancelable, event.cancelable); EXPECT_EQ(expectedCancelable, event.cancelable);
emulator()->HandleTouchEventAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); emulator()->HandleTouchEventAck(
event, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
} }
virtual void SetCursor(const WebCursor& cursor) OVERRIDE {} virtual void SetCursor(const WebCursor& cursor) OVERRIDE {}
...@@ -181,6 +182,66 @@ class TouchEmulatorTest : public testing::Test, ...@@ -181,6 +182,66 @@ class TouchEmulatorTest : public testing::Test,
mouse_pressed_ = false; mouse_pressed_ = false;
} }
bool TouchStart(int x, int y, bool ack) {
return SendTouchEvent(
WebInputEvent::TouchStart, WebTouchPoint::StatePressed, x, y, ack);
}
bool TouchMove(int x, int y, bool ack) {
return SendTouchEvent(
WebInputEvent::TouchMove, WebTouchPoint::StateMoved, x, y, ack);
}
bool TouchEnd(int x, int y, bool ack) {
return SendTouchEvent(
WebInputEvent::TouchEnd, WebTouchPoint::StateReleased, x, y, ack);
}
WebTouchEvent MakeTouchEvent(WebInputEvent::Type type,
WebTouchPoint::State state, int x, int y) {
WebTouchEvent event;
event.type = type;
event.timeStampSeconds = GetNextEventTimeSeconds();
event.touchesLength = 1;
event.touches[0].id = 0;
event.touches[0].state = state;
event.touches[0].position.x = x;
event.touches[0].position.y = y;
event.touches[0].screenPosition.x = x;
event.touches[0].screenPosition.y = y;
return event;
}
bool SendTouchEvent(WebInputEvent::Type type, WebTouchPoint::State state,
int x, int y, bool ack) {
WebTouchEvent event = MakeTouchEvent(type, state, x, y);
if (emulator()->HandleTouchEvent(event)) {
// Touch event is not forwarded.
return false;
}
if (ack) {
// Can't send ack if there are some pending acks.
DCHECK(!touch_events_to_ack_.size());
// Touch event is forwarded, ack should not be handled by emulator.
EXPECT_FALSE(emulator()->HandleTouchEventAck(
event, INPUT_EVENT_ACK_STATE_CONSUMED));
} else {
touch_events_to_ack_.push_back(event);
}
return true;
}
void AckOldestTouchEvent() {
DCHECK(touch_events_to_ack_.size());
WebTouchEvent event = touch_events_to_ack_[0];
touch_events_to_ack_.erase(touch_events_to_ack_.begin());
// Emulator should not handle ack from native stream.
EXPECT_FALSE(emulator()->HandleTouchEventAck(
event, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS));
}
private: private:
scoped_ptr<TouchEmulator> emulator_; scoped_ptr<TouchEmulator> emulator_;
std::vector<WebInputEvent::Type> forwarded_events_; std::vector<WebInputEvent::Type> forwarded_events_;
...@@ -193,6 +254,7 @@ class TouchEmulatorTest : public testing::Test, ...@@ -193,6 +254,7 @@ class TouchEmulatorTest : public testing::Test,
bool mouse_pressed_; bool mouse_pressed_;
int last_mouse_x_; int last_mouse_x_;
int last_mouse_y_; int last_mouse_y_;
std::vector<WebTouchEvent> touch_events_to_ack_;
base::MessageLoopForUI message_loop_; base::MessageLoopForUI message_loop_;
}; };
...@@ -346,4 +408,86 @@ TEST_F(TouchEmulatorTest, MouseWheel) { ...@@ -346,4 +408,86 @@ TEST_F(TouchEmulatorTest, MouseWheel) {
EXPECT_TRUE(SendMouseWheelEvent()); EXPECT_TRUE(SendMouseWheelEvent());
} }
TEST_F(TouchEmulatorTest, MultipleTouchStreams) {
// Native stream should be blocked while emulated is active.
MouseMove(100, 200);
EXPECT_EQ("", ExpectedEvents());
MouseDown(100, 200);
EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
EXPECT_FALSE(TouchStart(10, 10, true));
EXPECT_FALSE(TouchMove(20, 20, true));
MouseUp(200, 200);
EXPECT_EQ(
"TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate"
" TouchEnd GestureScrollEnd",
ExpectedEvents());
EXPECT_FALSE(TouchEnd(20, 20, true));
// Emulated stream should be blocked while native is active.
EXPECT_TRUE(TouchStart(10, 10, true));
EXPECT_TRUE(TouchMove(20, 20, true));
MouseDown(300, 200);
EXPECT_EQ("", ExpectedEvents());
// Re-enabling in the middle of a touch sequence should not affect this.
emulator()->Disable();
emulator()->Enable(true);
MouseDrag(300, 300);
EXPECT_EQ("", ExpectedEvents());
MouseUp(300, 300);
EXPECT_EQ("", ExpectedEvents());
EXPECT_TRUE(TouchEnd(20, 20, true));
EXPECT_EQ("", ExpectedEvents());
// Late ack for TouchEnd should not mess things up.
EXPECT_TRUE(TouchStart(10, 10, false));
EXPECT_TRUE(TouchMove(20, 20, false));
emulator()->Disable();
EXPECT_TRUE(TouchEnd(20, 20, false));
EXPECT_TRUE(TouchStart(30, 30, false));
AckOldestTouchEvent(); // TouchStart.
emulator()->Enable(true);
AckOldestTouchEvent(); // TouchMove.
AckOldestTouchEvent(); // TouchEnd.
MouseDown(300, 200);
EXPECT_EQ("", ExpectedEvents());
MouseDrag(300, 300);
EXPECT_EQ("", ExpectedEvents());
MouseUp(300, 300);
EXPECT_EQ("", ExpectedEvents());
AckOldestTouchEvent(); // TouchStart.
MouseDown(300, 200);
EXPECT_EQ("", ExpectedEvents());
EXPECT_TRUE(TouchMove(30, 40, true));
EXPECT_TRUE(TouchEnd(30, 40, true));
MouseUp(300, 200);
EXPECT_EQ("", ExpectedEvents());
// Emulation should be back to normal.
MouseDown(100, 200);
EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
MouseUp(200, 200);
EXPECT_EQ(
"TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate"
" TouchEnd GestureScrollEnd",
ExpectedEvents());
}
TEST_F(TouchEmulatorTest, MultipleTouchStreamsLateEnable) {
// Enabling in the middle of native touch sequence should be handled.
// Send artificial late TouchEnd ack, like it is the first thing emulator
// does see.
WebTouchEvent event = MakeTouchEvent(
WebInputEvent::TouchEnd, WebTouchPoint::StateReleased, 10, 10);
EXPECT_FALSE(emulator()->HandleTouchEventAck(
event, INPUT_EVENT_ACK_STATE_CONSUMED));
MouseDown(100, 200);
EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
MouseUp(200, 200);
EXPECT_EQ(
"TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate"
" TouchEnd GestureScrollEnd",
ExpectedEvents());
}
} // namespace content } // namespace content
...@@ -961,9 +961,13 @@ void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo( ...@@ -961,9 +961,13 @@ void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(
input_router_->SendGestureEvent(gesture_with_latency); input_router_->SendGestureEvent(gesture_with_latency);
} }
void RenderWidgetHostImpl::ForwardTouchEvent( void RenderWidgetHostImpl::ForwardEmulatedTouchEvent(
const blink::WebTouchEvent& touch_event) { const blink::WebTouchEvent& touch_event) {
ForwardTouchEventWithLatencyInfo(touch_event, ui::LatencyInfo()); TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardEmulatedTouchEvent");
ui::LatencyInfo latency_info =
CreateRWHLatencyInfoIfNotExist(NULL, touch_event.type);
TouchEventWithLatencyInfo touch_with_latency(touch_event, latency_info);
input_router_->SendTouchEvent(touch_with_latency);
} }
void RenderWidgetHostImpl::ForwardTouchEventWithLatencyInfo( void RenderWidgetHostImpl::ForwardTouchEventWithLatencyInfo(
...@@ -977,6 +981,16 @@ void RenderWidgetHostImpl::ForwardTouchEventWithLatencyInfo( ...@@ -977,6 +981,16 @@ void RenderWidgetHostImpl::ForwardTouchEventWithLatencyInfo(
ui::LatencyInfo latency_info = ui::LatencyInfo latency_info =
CreateRWHLatencyInfoIfNotExist(&ui_latency, touch_event.type); CreateRWHLatencyInfoIfNotExist(&ui_latency, touch_event.type);
TouchEventWithLatencyInfo touch_with_latency(touch_event, latency_info); TouchEventWithLatencyInfo touch_with_latency(touch_event, latency_info);
if (touch_emulator_ &&
touch_emulator_->HandleTouchEvent(touch_with_latency.event)) {
if (view_) {
view_->ProcessAckedTouchEvent(
touch_with_latency, INPUT_EVENT_ACK_STATE_CONSUMED);
}
return;
}
input_router_->SendTouchEvent(touch_with_latency); input_router_->SendTouchEvent(touch_with_latency);
} }
...@@ -1856,8 +1870,10 @@ void RenderWidgetHostImpl::OnTouchEventAck( ...@@ -1856,8 +1870,10 @@ void RenderWidgetHostImpl::OnTouchEventAck(
} }
ComputeTouchLatency(touch_event.latency); ComputeTouchLatency(touch_event.latency);
if (touch_emulator_ && touch_emulator_->HandleTouchEventAck(ack_result)) if (touch_emulator_ &&
touch_emulator_->HandleTouchEventAck(event.event, ack_result)) {
return; return;
}
if (view_) if (view_)
view_->ProcessAckedTouchEvent(touch_event, ack_result); view_->ProcessAckedTouchEvent(touch_event, ack_result);
...@@ -1886,6 +1902,13 @@ bool RenderWidgetHostImpl::IgnoreInputEvents() const { ...@@ -1886,6 +1902,13 @@ bool RenderWidgetHostImpl::IgnoreInputEvents() const {
} }
bool RenderWidgetHostImpl::ShouldForwardTouchEvent() const { bool RenderWidgetHostImpl::ShouldForwardTouchEvent() const {
// It's important that the emulator sees a complete native touch stream,
// allowing it to perform touch filtering as appropriate.
// TODO(dgozman): Remove when touch stream forwarding issues resolved, see
// crbug.com/375940.
if (touch_emulator_ && touch_emulator_->enabled())
return true;
return input_router_->ShouldForwardTouchEvent(); return input_router_->ShouldForwardTouchEvent();
} }
......
...@@ -297,10 +297,10 @@ class CONTENT_EXPORT RenderWidgetHostImpl ...@@ -297,10 +297,10 @@ class CONTENT_EXPORT RenderWidgetHostImpl
const blink::WebMouseWheelEvent& wheel_event, const blink::WebMouseWheelEvent& wheel_event,
const ui::LatencyInfo& ui_latency); const ui::LatencyInfo& ui_latency);
// TouchEmulatorClient overrides. // TouchEmulatorClient implementation.
virtual void ForwardGestureEvent( virtual void ForwardGestureEvent(
const blink::WebGestureEvent& gesture_event) OVERRIDE; const blink::WebGestureEvent& gesture_event) OVERRIDE;
virtual void ForwardTouchEvent( virtual void ForwardEmulatedTouchEvent(
const blink::WebTouchEvent& touch_event) OVERRIDE; const blink::WebTouchEvent& touch_event) OVERRIDE;
virtual void SetCursor(const WebCursor& cursor) OVERRIDE; virtual void SetCursor(const WebCursor& cursor) OVERRIDE;
......
...@@ -31,6 +31,20 @@ bool WebTouchEventTraits::IsTouchSequenceStart(const WebTouchEvent& event) { ...@@ -31,6 +31,20 @@ bool WebTouchEventTraits::IsTouchSequenceStart(const WebTouchEvent& event) {
return AllTouchPointsHaveState(event, blink::WebTouchPoint::StatePressed); return AllTouchPointsHaveState(event, blink::WebTouchPoint::StatePressed);
} }
bool WebTouchEventTraits::IsTouchSequenceEnd(const WebTouchEvent& event) {
if (event.type != WebInputEvent::TouchEnd &&
event.type != WebInputEvent::TouchCancel)
return false;
if (!event.touchesLength)
return true;
for (size_t i = 0; i < event.touchesLength; ++i) {
if (event.touches[i].state != blink::WebTouchPoint::StateReleased &&
event.touches[i].state != blink::WebTouchPoint::StateCancelled)
return false;
}
return true;
}
void WebTouchEventTraits::ResetType(WebInputEvent::Type type, void WebTouchEventTraits::ResetType(WebInputEvent::Type type,
double timestamp_sec, double timestamp_sec,
WebTouchEvent* event) { WebTouchEvent* event) {
......
...@@ -22,6 +22,10 @@ class CONTENT_EXPORT WebTouchEventTraits { ...@@ -22,6 +22,10 @@ class CONTENT_EXPORT WebTouchEventTraits {
// touches to some active touches (the start of a new "touch sequence"). // touches to some active touches (the start of a new "touch sequence").
static bool IsTouchSequenceStart(const blink::WebTouchEvent& event); static bool IsTouchSequenceStart(const blink::WebTouchEvent& event);
// Returns whether this event represents a transition from active
// touches to no active touches (the end of a "touch sequence").
static bool IsTouchSequenceEnd(const blink::WebTouchEvent& event);
// Sets the type of |event| to |type|, resetting any other type-specific // Sets the type of |event| to |type|, resetting any other type-specific
// properties and updating the timestamp. // properties and updating the timestamp.
static void ResetType(blink::WebInputEvent::Type type, static void ResetType(blink::WebInputEvent::Type type,
......
...@@ -305,10 +305,10 @@ void SimulateTapAt(WebContents* web_contents, const gfx::Point& point) { ...@@ -305,10 +305,10 @@ void SimulateTapAt(WebContents* web_contents, const gfx::Point& point) {
touch.PressPoint(point.x(), point.y()); touch.PressPoint(point.x(), point.y());
RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl* widget_host =
RenderWidgetHostImpl::From(web_contents->GetRenderViewHost()); RenderWidgetHostImpl::From(web_contents->GetRenderViewHost());
widget_host->ForwardTouchEvent(touch); widget_host->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
touch.timeStampSeconds += kTapDurationSeconds; touch.timeStampSeconds += kTapDurationSeconds;
touch.ReleasePoint(0); touch.ReleasePoint(0);
widget_host->ForwardTouchEvent(touch); widget_host->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
} }
void SimulateKeyPress(WebContents* web_contents, void SimulateKeyPress(WebContents* web_contents,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment