Commit 94307a6c authored by tdresser@chromium.org's avatar tdresser@chromium.org

Target touches to the correct display.

ui::TouchEvents now know the id of their source device.

The target of a touch can't be effected by a touch on another display.

BUG=315651
TEST=GestureRecognizerTest.GestureEventTouchLockIgnoresOtherScreens

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@243974 0039d316-1c4b-4281-b951-d872f2087c98
parent c619fd58
......@@ -2169,13 +2169,13 @@ TEST_F(GestureRecognizerTest, GestureEventTouchLockSelectsCorrectWindow) {
// Touches should now be associated with the closest touch within
// ui::GestureConfiguration::max_separation_for_gesture_touches_in_pixels
target = gesture_recognizer->GetTargetForLocation(gfx::Point(11, 11));
target = gesture_recognizer->GetTargetForLocation(gfx::Point(11, 11), -1);
EXPECT_EQ("0", WindowIDAsString(target));
target = gesture_recognizer->GetTargetForLocation(gfx::Point(511, 11));
target = gesture_recognizer->GetTargetForLocation(gfx::Point(511, 11), -1);
EXPECT_EQ("1", WindowIDAsString(target));
target = gesture_recognizer->GetTargetForLocation(gfx::Point(11, 511));
target = gesture_recognizer->GetTargetForLocation(gfx::Point(11, 511), -1);
EXPECT_EQ("2", WindowIDAsString(target));
target = gesture_recognizer->GetTargetForLocation(gfx::Point(511, 511));
target = gesture_recognizer->GetTargetForLocation(gfx::Point(511, 511), -1);
EXPECT_EQ("3", WindowIDAsString(target));
// Add a touch in the middle associated with windows[2]
......@@ -2186,20 +2186,20 @@ TEST_F(GestureRecognizerTest, GestureEventTouchLockSelectsCorrectWindow) {
kNumWindows, tes.Now());
dispatcher()->AsWindowTreeHostDelegate()->OnHostTouchEvent(&move);
target = gesture_recognizer->GetTargetForLocation(gfx::Point(250, 250));
target = gesture_recognizer->GetTargetForLocation(gfx::Point(250, 250), -1);
EXPECT_EQ("2", WindowIDAsString(target));
// Make sure that ties are broken by distance to a current touch
// Closer to the point in the bottom right.
target = gesture_recognizer->GetTargetForLocation(gfx::Point(380, 380));
target = gesture_recognizer->GetTargetForLocation(gfx::Point(380, 380), -1);
EXPECT_EQ("3", WindowIDAsString(target));
// This touch is closer to the point in the middle
target = gesture_recognizer->GetTargetForLocation(gfx::Point(300, 300));
target = gesture_recognizer->GetTargetForLocation(gfx::Point(300, 300), -1);
EXPECT_EQ("2", WindowIDAsString(target));
// A touch too far from other touches won't be locked to anything
target = gesture_recognizer->GetTargetForLocation(gfx::Point(1000, 1000));
target = gesture_recognizer->GetTargetForLocation(gfx::Point(1000, 1000), -1);
EXPECT_TRUE(target == NULL);
// Move a touch associated with windows[2] to 1000, 1000
......@@ -2207,7 +2207,7 @@ TEST_F(GestureRecognizerTest, GestureEventTouchLockSelectsCorrectWindow) {
kNumWindows, tes.Now());
dispatcher()->AsWindowTreeHostDelegate()->OnHostTouchEvent(&move2);
target = gesture_recognizer->GetTargetForLocation(gfx::Point(1000, 1000));
target = gesture_recognizer->GetTargetForLocation(gfx::Point(1000, 1000), -1);
EXPECT_EQ("2", WindowIDAsString(target));
for (int i = 0; i < kNumWindows; ++i) {
......@@ -2217,6 +2217,36 @@ TEST_F(GestureRecognizerTest, GestureEventTouchLockSelectsCorrectWindow) {
}
}
// Check that a touch's target will not be effected by a touch on a different
// screen.
TEST_F(GestureRecognizerTest, GestureEventTouchLockIgnoresOtherScreens) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
gfx::Rect bounds(0, 0, 10, 10);
scoped_ptr<aura::Window> window(
CreateTestWindowWithDelegate(delegate.get(), 0, bounds, root_window()));
const int kTouchId1 = 8;
const int kTouchId2 = 2;
TimedEvents tes;
ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(5, 5),
kTouchId1, tes.Now());
press1.set_source_device_id(1);
dispatcher()->AsWindowTreeHostDelegate()->OnHostTouchEvent(&press1);
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(20, 20),
kTouchId2, tes.Now());
press2.set_source_device_id(2);
dispatcher()->AsWindowTreeHostDelegate()->OnHostTouchEvent(&press2);
// The second press should not have been locked to the same target as the
// first, as they occured on different displays.
EXPECT_NE(
ui::GestureRecognizer::Get()->GetTouchLockedTarget(press1),
ui::GestureRecognizer::Get()->GetTouchLockedTarget(press2));
}
// Check that touch events outside the root window are still handled
// by the root window's gesture sequence.
TEST_F(GestureRecognizerTest, GestureEventOutsideRootWindowTap) {
......
......@@ -105,6 +105,7 @@ void AuraTestHelper::TearDown() {
focus_client_.reset();
client::SetFocusClient(root_window(), NULL);
root_window_.reset();
ui::GestureRecognizer::Reset();
test_screen_.reset();
gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, NULL);
......
......@@ -110,7 +110,8 @@ Window* WindowTargeter::FindTargetInRootWindow(Window* root_window,
if (consumer)
return static_cast<Window*>(consumer);
consumer =
ui::GestureRecognizer::Get()->GetTargetForLocation(event.location());
ui::GestureRecognizer::Get()->GetTargetForLocation(
event.location(), touch.source_device_id());
if (consumer)
return static_cast<Window*>(consumer);
......
......@@ -5,6 +5,7 @@
#include "ui/events/event.h"
#if defined(USE_X11)
#include <X11/extensions/XInput2.h>
#include <X11/Xlib.h>
#endif
......@@ -437,7 +438,8 @@ TouchEvent::TouchEvent(const base::NativeEvent& native_event)
radius_x_(GetTouchRadiusX(native_event)),
radius_y_(GetTouchRadiusY(native_event)),
rotation_angle_(GetTouchAngle(native_event)),
force_(GetTouchForce(native_event)) {
force_(GetTouchForce(native_event)),
source_device_id_(-1) {
latency()->AddLatencyNumberWithTimestamp(
INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
0,
......@@ -445,6 +447,12 @@ TouchEvent::TouchEvent(const base::NativeEvent& native_event)
base::TimeTicks::FromInternalValue(time_stamp().ToInternalValue()),
1,
true);
#if defined(USE_X11)
XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(native_event->xcookie.data);
source_device_id_ = xiev->deviceid;
#endif
latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
}
......@@ -457,7 +465,8 @@ TouchEvent::TouchEvent(EventType type,
radius_x_(0.0f),
radius_y_(0.0f),
rotation_angle_(0.0f),
force_(0.0f) {
force_(0.0f),
source_device_id_(-1) {
latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
}
......@@ -475,7 +484,8 @@ TouchEvent::TouchEvent(EventType type,
radius_x_(radius_x),
radius_y_(radius_y),
rotation_angle_(angle),
force_(force) {
force_(force),
source_device_id_(-1) {
latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
}
......
......@@ -437,7 +437,8 @@ class EVENTS_EXPORT TouchEvent : public LocatedEvent {
radius_x_(model.radius_x_),
radius_y_(model.radius_y_),
rotation_angle_(model.rotation_angle_),
force_(model.force_) {
force_(model.force_),
source_device_id_(model.source_device_id_) {
}
TouchEvent(EventType type,
......@@ -462,6 +463,7 @@ class EVENTS_EXPORT TouchEvent : public LocatedEvent {
float radius_y() const { return radius_y_; }
float rotation_angle() const { return rotation_angle_; }
float force() const { return force_; }
int source_device_id() const { return source_device_id_; }
// Relocate the touch-point to a new |origin|.
// This is useful when touch event is in X Root Window coordinates,
......@@ -471,6 +473,9 @@ class EVENTS_EXPORT TouchEvent : public LocatedEvent {
// Used for unit tests.
void set_radius_x(const float r) { radius_x_ = r; }
void set_radius_y(const float r) { radius_y_ = r; }
void set_source_device_id(int source_device_id) {
source_device_id_ = source_device_id;
}
// Overridden from LocatedEvent.
virtual void UpdateForRootTransform(
......@@ -504,6 +509,9 @@ class EVENTS_EXPORT TouchEvent : public LocatedEvent {
// Force (pressure) of the touch. Normalized to be [0, 1]. Default to be 0.0.
float force_;
// The device id of the screen the event came from. Default to be -1.
int source_device_id_;
};
class EVENTS_EXPORT KeyEvent : public Event {
......
......@@ -24,7 +24,8 @@ GesturePoint::GesturePoint()
velocity_calculator_(
GestureConfiguration::points_buffered_for_velocity()),
point_id_(-1),
touch_id_(-1) {
touch_id_(-1),
source_device_id_(-1) {
}
GesturePoint::~GesturePoint() {}
......@@ -34,6 +35,7 @@ void GesturePoint::Reset() {
ResetVelocity();
point_id_ = -1;
clear_enclosing_rectangle();
source_device_id_ = -1;
}
void GesturePoint::ResetVelocity() {
......
......@@ -79,6 +79,11 @@ class GesturePoint {
const gfx::Rect& enclosing_rectangle() const { return enclosing_rect_; }
void set_source_device_id(int source_device_id) {
source_device_id_ = source_device_id;
}
int source_device_id() const { return source_device_id_; }
private:
// Various statistical functions to manipulate gestures.
......@@ -131,6 +136,8 @@ class GesturePoint {
// Count of the number of events with same direction.
gfx::Vector2d same_direction_count_;
int source_device_id_;
DISALLOW_COPY_AND_ASSIGN(GesturePoint);
};
......
......@@ -19,6 +19,7 @@ class EVENTS_EXPORT GestureRecognizer {
public:
static GestureRecognizer* Create();
static GestureRecognizer* Get();
static void Reset();
// List of GestureEvent*.
typedef ScopedVector<GestureEvent> Gestures;
......@@ -46,10 +47,12 @@ class EVENTS_EXPORT GestureRecognizer {
virtual GestureConsumer* GetTargetForGestureEvent(
const GestureEvent& event) = 0;
// If there is an active touch within
// GestureConfiguration::max_separation_for_gesture_touches_in_pixels,
// of |location|, returns the target of the nearest active touch.
virtual GestureConsumer* GetTargetForLocation(const gfx::Point& location) = 0;
// Returns the target of the nearest active touch with source device of
// |source_device_id|, within
// GestureConfiguration::max_separation_for_gesture_touches_in_pixels of
// |location|, or NULL if no such point exists.
virtual GestureConsumer* GetTargetForLocation(
const gfx::Point& location, int source_device_id) = 0;
// Makes |new_consumer| the target for events previously targeting
// |current_consumer|. All other targets are canceled.
......
......@@ -78,15 +78,17 @@ GestureConsumer* GestureRecognizerImpl::GetTargetForGestureEvent(
}
GestureConsumer* GestureRecognizerImpl::GetTargetForLocation(
const gfx::Point& location) {
const gfx::Point& location, int source_device_id) {
const GesturePoint* closest_point = NULL;
int64 closest_distance_squared = 0;
std::map<GestureConsumer*, GestureSequence*>::iterator i;
for (i = consumer_sequence_.begin(); i != consumer_sequence_.end(); ++i) {
const GesturePoint* points = i->second->points();
for (int j = 0; j < GestureSequence::kMaxGesturePoints; ++j) {
if (!points[j].in_use())
if (!points[j].in_use() ||
source_device_id != points[j].source_device_id()) {
continue;
}
gfx::Vector2d delta = points[j].last_touch_position() - location;
// Relative distance is all we need here, so LengthSquared() is
// appropriate, and cheaper than Length().
......@@ -271,6 +273,11 @@ GestureRecognizer* GestureRecognizer::Get() {
return g_gesture_recognizer_instance;
}
// GestureRecognizer, static
void GestureRecognizer::Reset() {
g_gesture_recognizer_instance = NULL;
}
void SetGestureRecognizerForTesting(GestureRecognizer* gesture_recognizer) {
// Transfer helpers to the new GR.
std::vector<GestureEventHelper*>& helpers =
......
......@@ -39,7 +39,7 @@ class EVENTS_EXPORT GestureRecognizerImpl : public GestureRecognizer,
virtual GestureConsumer* GetTargetForGestureEvent(
const GestureEvent& event) OVERRIDE;
virtual GestureConsumer* GetTargetForLocation(
const gfx::Point& location) OVERRIDE;
const gfx::Point& location, int source_device_id) OVERRIDE;
virtual void TransferEventsTo(GestureConsumer* current_consumer,
GestureConsumer* new_consumer) OVERRIDE;
virtual bool GetLastTouchPointForTarget(GestureConsumer* consumer,
......
......@@ -520,6 +520,7 @@ GestureSequence::Gestures* GestureSequence::ProcessTouchEventForGesture(
}
new_point->set_point_id(point_count_++);
new_point->set_touch_id(event.touch_id());
new_point->set_source_device_id(event.source_device_id());
}
GestureState last_state = state_;
......
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