Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(343)

Side by Side Diff: components/mus/ws/event_dispatcher_unittest.cc

Issue 1605773004: mus: Implement Window Server Capture (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/mus/ws/event_dispatcher.h" 5 #include "components/mus/ws/event_dispatcher.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <queue> 10 #include <queue>
(...skipping 17 matching lines...) Expand all
28 DispatchedEventDetails() : window(nullptr), in_nonclient_area(false) {} 28 DispatchedEventDetails() : window(nullptr), in_nonclient_area(false) {}
29 29
30 ServerWindow* window; 30 ServerWindow* window;
31 bool in_nonclient_area; 31 bool in_nonclient_area;
32 mojom::EventPtr event; 32 mojom::EventPtr event;
33 }; 33 };
34 34
35 class TestEventDispatcherDelegate : public EventDispatcherDelegate { 35 class TestEventDispatcherDelegate : public EventDispatcherDelegate {
36 public: 36 public:
37 explicit TestEventDispatcherDelegate(ServerWindow* root) 37 explicit TestEventDispatcherDelegate(ServerWindow* root)
38 : root_(root), focused_window_(nullptr), last_accelerator_(0) {} 38 : root_(root),
39 focused_window_(nullptr),
40 lost_capture_window_(nullptr),
41 last_accelerator_(0) {}
39 ~TestEventDispatcherDelegate() override {} 42 ~TestEventDispatcherDelegate() override {}
40 43
41 uint32_t GetAndClearLastAccelerator() { 44 uint32_t GetAndClearLastAccelerator() {
42 uint32_t return_value = last_accelerator_; 45 uint32_t return_value = last_accelerator_;
43 last_accelerator_ = 0; 46 last_accelerator_ = 0;
44 return return_value; 47 return return_value;
45 } 48 }
46 49
47 // Returns the last dispatched event, or null if there are no more. 50 // Returns the last dispatched event, or null if there are no more.
48 scoped_ptr<DispatchedEventDetails> GetAndAdvanceDispatchedEventDetails() { 51 scoped_ptr<DispatchedEventDetails> GetAndAdvanceDispatchedEventDetails() {
49 if (dispatched_event_queue_.empty()) 52 if (dispatched_event_queue_.empty())
50 return nullptr; 53 return nullptr;
51 54
52 scoped_ptr<DispatchedEventDetails> details = 55 scoped_ptr<DispatchedEventDetails> details =
53 std::move(dispatched_event_queue_.front()); 56 std::move(dispatched_event_queue_.front());
54 dispatched_event_queue_.pop(); 57 dispatched_event_queue_.pop();
55 return details; 58 return details;
56 } 59 }
57 60
58 ServerWindow* GetAndClearLastFocusedWindow() { 61 ServerWindow* GetAndClearLastFocusedWindow() {
59 ServerWindow* result = focused_window_; 62 ServerWindow* result = focused_window_;
60 focused_window_ = nullptr; 63 focused_window_ = nullptr;
61 return result; 64 return result;
62 } 65 }
63 66
64 bool has_queued_events() const { return !dispatched_event_queue_.empty(); } 67 bool has_queued_events() const { return !dispatched_event_queue_.empty(); }
68 ServerWindow* lost_capture_window() { return lost_capture_window_; }
65 69
66 private: 70 private:
67 // EventDispatcherDelegate: 71 // EventDispatcherDelegate:
68 void OnAccelerator(uint32_t accelerator, mojom::EventPtr event) override { 72 void OnAccelerator(uint32_t accelerator, mojom::EventPtr event) override {
69 EXPECT_EQ(0u, last_accelerator_); 73 EXPECT_EQ(0u, last_accelerator_);
70 last_accelerator_ = accelerator; 74 last_accelerator_ = accelerator;
71 } 75 }
72 void SetFocusedWindowFromEventDispatcher(ServerWindow* window) override { 76 void SetFocusedWindowFromEventDispatcher(ServerWindow* window) override {
73 focused_window_ = window; 77 focused_window_ = window;
74 } 78 }
75 ServerWindow* GetFocusedWindowForEventDispatcher() override { 79 ServerWindow* GetFocusedWindowForEventDispatcher() override {
76 return focused_window_; 80 return focused_window_;
77 } 81 }
82 void OnLostCapture(ServerWindow* window) override {
83 lost_capture_window_ = window;
84 }
78 void DispatchInputEventToWindow(ServerWindow* target, 85 void DispatchInputEventToWindow(ServerWindow* target,
79 bool in_nonclient_area, 86 bool in_nonclient_area,
80 mojom::EventPtr event) override { 87 mojom::EventPtr event) override {
81 scoped_ptr<DispatchedEventDetails> details(new DispatchedEventDetails); 88 scoped_ptr<DispatchedEventDetails> details(new DispatchedEventDetails);
82 details->window = target; 89 details->window = target;
83 details->in_nonclient_area = in_nonclient_area; 90 details->in_nonclient_area = in_nonclient_area;
84 details->event = std::move(event); 91 details->event = std::move(event);
85 dispatched_event_queue_.push(std::move(details)); 92 dispatched_event_queue_.push(std::move(details));
86 } 93 }
87 94
88 ServerWindow* root_; 95 ServerWindow* root_;
89 ServerWindow* focused_window_; 96 ServerWindow* focused_window_;
97 ServerWindow* lost_capture_window_;
90 uint32_t last_accelerator_; 98 uint32_t last_accelerator_;
91 std::queue<scoped_ptr<DispatchedEventDetails>> dispatched_event_queue_; 99 std::queue<scoped_ptr<DispatchedEventDetails>> dispatched_event_queue_;
92 100
93 DISALLOW_COPY_AND_ASSIGN(TestEventDispatcherDelegate); 101 DISALLOW_COPY_AND_ASSIGN(TestEventDispatcherDelegate);
94 }; 102 };
95 103
96 // Used by RunMouseEventTests(). Can identify up to two generated events. The 104 // Used by RunMouseEventTests(). Can identify up to two generated events. The
97 // first ServerWindow and two points identify the first event, the second 105 // first ServerWindow and two points identify the first event, the second
98 // ServerWindow and points identify the second event. If only one event is 106 // ServerWindow and points identify the second event. If only one event is
99 // generated set the second window to null. 107 // generated set the second window to null.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 details.get(), test.expected_target_window2, 159 details.get(), test.expected_target_window2,
152 test.expected_root_location2, test.expected_location2)) 160 test.expected_root_location2, test.expected_location2))
153 << " details2 don't match " << i; 161 << " details2 don't match " << i;
154 ASSERT_FALSE(dispatcher_delegate->has_queued_events()) 162 ASSERT_FALSE(dispatcher_delegate->has_queued_events())
155 << " unexpected queued events after running " << i; 163 << " unexpected queued events after running " << i;
156 } 164 }
157 } 165 }
158 166
159 } // namespace 167 } // namespace
160 168
161 TEST(EventDispatcherTest, ProcessEvent) { 169 // Test fixture for EventDispatcher with friend access to verify the internal
162 TestServerWindowDelegate window_delegate; 170 // state. Setup creates a TestServerWindowDelegate, a visible root ServerWindow,
163 ServerWindow root(&window_delegate, WindowId(1, 2)); 171 // a TestEventDispatcher and the EventDispatcher for testing.
164 window_delegate.set_root_window(&root); 172 class EventDispatcherTest : public testing::Test {
165 root.SetVisible(true); 173 public:
174 EventDispatcherTest() {}
175 ~EventDispatcherTest() override {}
166 176
167 ServerWindow child(&window_delegate, WindowId(1, 3)); 177 ServerWindow* root_window() { return root_window_.get(); }
168 root.Add(&child); 178 TestEventDispatcherDelegate* test_event_dispatcher_delegate() {
169 child.SetVisible(true); 179 return test_event_dispatcher_delegate_.get();
170 EnableHitTest(&child); 180 }
181 EventDispatcher* event_dispatcher() { return event_dispatcher_.get(); }
171 182
172 root.SetBounds(gfx::Rect(0, 0, 100, 100)); 183 bool AreAnyPointersDown() const;
173 child.SetBounds(gfx::Rect(10, 10, 20, 20)); 184 // Deletes everything created during SetUp()
185 void ClearSetup();
186 // Creates a window which is a child of |root_window_|. It is not owned by
187 // EventDispatcherTest.
188 ServerWindow* CreateChildWindow(const WindowId& id);
189 bool IsWindowPointerTarget(ServerWindow* window) const;
190 int NumberPointerTargetsForWindow(ServerWindow* window) const;
174 191
175 TestEventDispatcherDelegate event_dispatcher_delegate(&root); 192 protected:
176 EventDispatcher dispatcher(&event_dispatcher_delegate); 193 // testing::Test:
177 dispatcher.set_root(&root); 194 void SetUp() override;
195
196 private:
197 scoped_ptr<TestServerWindowDelegate> window_delegate_;
198 scoped_ptr<ServerWindow> root_window_;
199 scoped_ptr<TestEventDispatcherDelegate> test_event_dispatcher_delegate_;
200 scoped_ptr<EventDispatcher> event_dispatcher_;
201
202 DISALLOW_COPY_AND_ASSIGN(EventDispatcherTest);
203 };
204
205 bool EventDispatcherTest::AreAnyPointersDown() const {
206 return event_dispatcher_->AreAnyPointersDown();
207 }
208
209 void EventDispatcherTest::ClearSetup() {
210 window_delegate_.reset();
211 root_window_.reset();
212 test_event_dispatcher_delegate_.reset();
213 event_dispatcher_.reset();
214 }
215
216 ServerWindow* EventDispatcherTest::CreateChildWindow(const WindowId& id) {
217 ServerWindow* child = new ServerWindow(window_delegate_.get(), id);
218 root_window_->Add(child);
219 child->SetVisible(true);
220 EnableHitTest(child);
221 return child;
222 }
223
224 bool EventDispatcherTest::IsWindowPointerTarget(ServerWindow* window) const {
225 return event_dispatcher_->IsObservingWindow(window);
226 }
227
228 int EventDispatcherTest::NumberPointerTargetsForWindow(
229 ServerWindow* window) const {
230 int count = 0;
231 for (const auto& pair : event_dispatcher_->pointer_targets_)
232 if (pair.second.window == window)
233 count++;
234 return count;
235 }
236
237 void EventDispatcherTest::SetUp() {
238 testing::Test::SetUp();
239
240 window_delegate_.reset(new TestServerWindowDelegate());
241 root_window_.reset(new ServerWindow(window_delegate_.get(), WindowId(1, 2)));
242 window_delegate_->set_root_window(root_window_.get());
243 root_window_->SetVisible(true);
244
245 test_event_dispatcher_delegate_.reset(
246 new TestEventDispatcherDelegate(root_window_.get()));
247 event_dispatcher_.reset(
248 new EventDispatcher(test_event_dispatcher_delegate_.get()));
249 event_dispatcher_->set_root(root_window_.get());
250 }
251
252 TEST_F(EventDispatcherTest, ProcessEvent) {
253 scoped_ptr<ServerWindow> child(CreateChildWindow(WindowId(1, 3)));
254
255 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
256 child->SetBounds(gfx::Rect(10, 10, 20, 20));
178 257
179 // Send event that is over child. 258 // Send event that is over child.
180 const ui::MouseEvent ui_event( 259 const ui::MouseEvent ui_event(
181 ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), gfx::Point(20, 25), 260 ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), gfx::Point(20, 25),
182 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); 261 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
183 dispatcher.ProcessEvent( 262 event_dispatcher()->ProcessEvent(
184 mojom::Event::From(static_cast<const ui::Event&>(ui_event))); 263 mojom::Event::From(static_cast<const ui::Event&>(ui_event)));
185 264
186 scoped_ptr<DispatchedEventDetails> details = 265 scoped_ptr<DispatchedEventDetails> details =
187 event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 266 test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
188
189 ASSERT_TRUE(details); 267 ASSERT_TRUE(details);
190 ASSERT_EQ(&child, details->window); 268 ASSERT_EQ(child.get(), details->window);
191 269
192 scoped_ptr<ui::Event> dispatched_event( 270 scoped_ptr<ui::Event> dispatched_event(
193 details->event.To<scoped_ptr<ui::Event>>()); 271 details->event.To<scoped_ptr<ui::Event>>());
194 ASSERT_TRUE(dispatched_event); 272 ASSERT_TRUE(dispatched_event);
195 ASSERT_TRUE(dispatched_event->IsMouseEvent()); 273 ASSERT_TRUE(dispatched_event->IsMouseEvent());
274
196 ui::MouseEvent* dispatched_mouse_event = 275 ui::MouseEvent* dispatched_mouse_event =
197 static_cast<ui::MouseEvent*>(dispatched_event.get()); 276 static_cast<ui::MouseEvent*>(dispatched_event.get());
198 EXPECT_EQ(gfx::Point(20, 25), dispatched_mouse_event->root_location()); 277 EXPECT_EQ(gfx::Point(20, 25), dispatched_mouse_event->root_location());
199 EXPECT_EQ(gfx::Point(10, 15), dispatched_mouse_event->location()); 278 EXPECT_EQ(gfx::Point(10, 15), dispatched_mouse_event->location());
200 } 279 }
201 280
202 TEST(EventDispatcherTest, AcceleratorBasic) { 281 TEST_F(EventDispatcherTest, AcceleratorBasic) {
282 ClearSetup();
203 TestEventDispatcherDelegate event_dispatcher_delegate(nullptr); 283 TestEventDispatcherDelegate event_dispatcher_delegate(nullptr);
204 EventDispatcher dispatcher(&event_dispatcher_delegate); 284 EventDispatcher dispatcher(&event_dispatcher_delegate);
285
205 uint32_t accelerator_1 = 1; 286 uint32_t accelerator_1 = 1;
206 mojom::EventMatcherPtr matcher = mus::CreateKeyMatcher( 287 mojom::EventMatcherPtr matcher = mus::CreateKeyMatcher(
207 mus::mojom::KeyboardCode::W, mus::mojom::kEventFlagControlDown); 288 mus::mojom::KeyboardCode::W, mus::mojom::kEventFlagControlDown);
208 EXPECT_TRUE(dispatcher.AddAccelerator(accelerator_1, std::move(matcher))); 289 EXPECT_TRUE(dispatcher.AddAccelerator(accelerator_1, std::move(matcher)));
209 290
210 uint32_t accelerator_2 = 2; 291 uint32_t accelerator_2 = 2;
211 matcher = mus::CreateKeyMatcher(mus::mojom::KeyboardCode::N, 292 matcher = mus::CreateKeyMatcher(mus::mojom::KeyboardCode::N,
212 mus::mojom::kEventFlagNone); 293 mus::mojom::kEventFlagNone);
213 EXPECT_TRUE(dispatcher.AddAccelerator(accelerator_2, std::move(matcher))); 294 EXPECT_TRUE(dispatcher.AddAccelerator(accelerator_2, std::move(matcher)));
214 295
(...skipping 13 matching lines...) Expand all
228 uint32_t accelerator_3 = 3; 309 uint32_t accelerator_3 = 3;
229 matcher = mus::CreateKeyMatcher(mus::mojom::KeyboardCode::T, 310 matcher = mus::CreateKeyMatcher(mus::mojom::KeyboardCode::T,
230 mus::mojom::kEventFlagNone); 311 mus::mojom::kEventFlagNone);
231 EXPECT_FALSE(dispatcher.AddAccelerator(accelerator_3, std::move(matcher))); 312 EXPECT_FALSE(dispatcher.AddAccelerator(accelerator_3, std::move(matcher)));
232 313
233 matcher = mus::CreateKeyMatcher(mus::mojom::KeyboardCode::T, 314 matcher = mus::CreateKeyMatcher(mus::mojom::KeyboardCode::T,
234 mus::mojom::kEventFlagControlDown); 315 mus::mojom::kEventFlagControlDown);
235 EXPECT_TRUE(dispatcher.AddAccelerator(accelerator_3, std::move(matcher))); 316 EXPECT_TRUE(dispatcher.AddAccelerator(accelerator_3, std::move(matcher)));
236 } 317 }
237 318
238 TEST(EventDispatcherTest, EventMatching) { 319 TEST_F(EventDispatcherTest, EventMatching) {
239 TestServerWindowDelegate window_delegate; 320 TestEventDispatcherDelegate* event_dispatcher_delegate =
240 ServerWindow root(&window_delegate, WindowId(1, 2)); 321 test_event_dispatcher_delegate();
241 TestEventDispatcherDelegate event_dispatcher_delegate(&root); 322 EventDispatcher* dispatcher = event_dispatcher();
242 EventDispatcher dispatcher(&event_dispatcher_delegate);
243 dispatcher.set_root(&root);
244 323
245 mojom::EventMatcherPtr matcher = mus::CreateKeyMatcher( 324 mojom::EventMatcherPtr matcher = mus::CreateKeyMatcher(
246 mus::mojom::KeyboardCode::W, mus::mojom::kEventFlagControlDown); 325 mus::mojom::KeyboardCode::W, mus::mojom::kEventFlagControlDown);
247 uint32_t accelerator_1 = 1; 326 uint32_t accelerator_1 = 1;
248 dispatcher.AddAccelerator(accelerator_1, std::move(matcher)); 327 dispatcher->AddAccelerator(accelerator_1, std::move(matcher));
249 328
250 ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN); 329 ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN);
251 dispatcher.ProcessEvent(mojom::Event::From(key)); 330 dispatcher->ProcessEvent(mojom::Event::From(key));
252 EXPECT_EQ(accelerator_1, 331 EXPECT_EQ(accelerator_1,
253 event_dispatcher_delegate.GetAndClearLastAccelerator()); 332 event_dispatcher_delegate->GetAndClearLastAccelerator());
254 333
255 // EF_NUM_LOCK_ON should be ignored since CreateKeyMatcher defaults to 334 // EF_NUM_LOCK_ON should be ignored since CreateKeyMatcher defaults to
256 // ignoring. 335 // ignoring.
257 key = ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_W, 336 key = ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_W,
258 ui::EF_CONTROL_DOWN | ui::EF_NUM_LOCK_ON); 337 ui::EF_CONTROL_DOWN | ui::EF_NUM_LOCK_ON);
259 dispatcher.ProcessEvent(mojom::Event::From(key)); 338 dispatcher->ProcessEvent(mojom::Event::From(key));
260 EXPECT_EQ(accelerator_1, 339 EXPECT_EQ(accelerator_1,
261 event_dispatcher_delegate.GetAndClearLastAccelerator()); 340 event_dispatcher_delegate->GetAndClearLastAccelerator());
262 341
263 key = ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_NONE); 342 key = ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_NONE);
264 dispatcher.ProcessEvent(mojom::Event::From(key)); 343 dispatcher->ProcessEvent(mojom::Event::From(key));
265 EXPECT_EQ(0u, event_dispatcher_delegate.GetAndClearLastAccelerator()); 344 EXPECT_EQ(0u, event_dispatcher_delegate->GetAndClearLastAccelerator());
266 345
267 uint32_t accelerator_2 = 2; 346 uint32_t accelerator_2 = 2;
268 matcher = mus::CreateKeyMatcher(mus::mojom::KeyboardCode::W, 347 matcher = mus::CreateKeyMatcher(mus::mojom::KeyboardCode::W,
269 mus::mojom::kEventFlagNone); 348 mus::mojom::kEventFlagNone);
270 dispatcher.AddAccelerator(accelerator_2, std::move(matcher)); 349 dispatcher->AddAccelerator(accelerator_2, std::move(matcher));
271 dispatcher.ProcessEvent(mojom::Event::From(key)); 350 dispatcher->ProcessEvent(mojom::Event::From(key));
272 EXPECT_EQ(accelerator_2, 351 EXPECT_EQ(accelerator_2,
273 event_dispatcher_delegate.GetAndClearLastAccelerator()); 352 event_dispatcher_delegate->GetAndClearLastAccelerator());
274 353
275 dispatcher.RemoveAccelerator(accelerator_2); 354 dispatcher->RemoveAccelerator(accelerator_2);
276 dispatcher.ProcessEvent(mojom::Event::From(key)); 355 dispatcher->ProcessEvent(mojom::Event::From(key));
277 EXPECT_EQ(0u, event_dispatcher_delegate.GetAndClearLastAccelerator()); 356 EXPECT_EQ(0u, event_dispatcher_delegate->GetAndClearLastAccelerator());
278 } 357 }
279 358
280 TEST(EventDispatcherTest, Capture) { 359 TEST_F(EventDispatcherTest, Capture) {
281 TestServerWindowDelegate window_delegate; 360 ServerWindow* root = root_window();
282 ServerWindow root(&window_delegate, WindowId(1, 2)); 361 scoped_ptr<ServerWindow> child(CreateChildWindow(WindowId(1, 3)));
283 window_delegate.set_root_window(&root);
284 root.SetVisible(true);
285 362
286 ServerWindow child(&window_delegate, WindowId(1, 3)); 363 root->SetBounds(gfx::Rect(0, 0, 100, 100));
287 root.Add(&child); 364 child->SetBounds(gfx::Rect(10, 10, 20, 20));
288 child.SetVisible(true);
289
290 root.SetBounds(gfx::Rect(0, 0, 100, 100));
291 child.SetBounds(gfx::Rect(10, 10, 20, 20));
292 EnableHitTest(&child);
293
294 TestEventDispatcherDelegate event_dispatcher_delegate(&root);
295 EventDispatcher dispatcher(&event_dispatcher_delegate);
296 dispatcher.set_root(&root);
297 365
298 MouseEventTest tests[] = { 366 MouseEventTest tests[] = {
299 // Send a mouse down event over child. 367 // Send a mouse down event over child.
300 {ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), 368 {ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(20, 25),
301 gfx::Point(20, 25), base::TimeDelta(), 369 gfx::Point(20, 25), base::TimeDelta(),
302 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON), 370 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON),
303 &child, gfx::Point(20, 25), gfx::Point(10, 15), nullptr, gfx::Point(), 371 child.get(), gfx::Point(20, 25), gfx::Point(10, 15), nullptr,
304 gfx::Point()}, 372 gfx::Point(), gfx::Point()},
305 373
306 // Capture should be activated. Let's send a mouse move outside the bounds 374 // Capture should be activated. Let's send a mouse move outside the bounds
307 // of the child. 375 // of the child.
308 {ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(50, 50), 376 {ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(50, 50),
309 gfx::Point(50, 50), base::TimeDelta(), 377 gfx::Point(50, 50), base::TimeDelta(),
310 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON), 378 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON),
311 &child, gfx::Point(50, 50), gfx::Point(40, 40), nullptr, gfx::Point(), 379 child.get(), gfx::Point(50, 50), gfx::Point(40, 40), nullptr,
312 gfx::Point()}, 380 gfx::Point(), gfx::Point()},
313 // Release the mouse and verify that the mouse up event goes to the child. 381 // Release the mouse and verify that the mouse up event goes to the child.
314 {ui::MouseEvent(ui::ET_MOUSE_RELEASED, gfx::Point(50, 50), 382 {ui::MouseEvent(ui::ET_MOUSE_RELEASED, gfx::Point(50, 50),
315 gfx::Point(50, 50), base::TimeDelta(), 383 gfx::Point(50, 50), base::TimeDelta(),
316 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON), 384 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON),
317 &child, gfx::Point(50, 50), gfx::Point(40, 40), nullptr, gfx::Point(), 385 child.get(), gfx::Point(50, 50), gfx::Point(40, 40), nullptr,
318 gfx::Point()}, 386 gfx::Point(), gfx::Point()},
319 387
320 // A mouse move at (50, 50) should now go to the root window. As the 388 // A mouse move at (50, 50) should now go to the root window. As the
321 // move crosses between |child| and |root| |child| gets an exit, and 389 // move crosses between |child| and |root| |child| gets an exit, and
322 // |root| the move. 390 // |root| the move.
323 {ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(50, 50), 391 {ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(50, 50),
324 gfx::Point(50, 50), base::TimeDelta(), 392 gfx::Point(50, 50), base::TimeDelta(),
325 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON), 393 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON),
326 &child, gfx::Point(50, 50), gfx::Point(40, 40), &root, 394 child.get(), gfx::Point(50, 50), gfx::Point(40, 40), root,
327 gfx::Point(50, 50), gfx::Point(50, 50)}, 395 gfx::Point(50, 50), gfx::Point(50, 50)},
328 396
329 }; 397 };
330 RunMouseEventTests(&dispatcher, &event_dispatcher_delegate, tests, 398 RunMouseEventTests(event_dispatcher(), test_event_dispatcher_delegate(),
331 arraysize(tests)); 399 tests, arraysize(tests));
332 } 400 }
333 401
334 TEST(EventDispatcherTest, CaptureMultipleMouseButtons) { 402 TEST_F(EventDispatcherTest, CaptureMultipleMouseButtons) {
335 TestServerWindowDelegate window_delegate; 403 scoped_ptr<ServerWindow> child(CreateChildWindow(WindowId(1, 3)));
336 ServerWindow root(&window_delegate, WindowId(1, 2));
337 window_delegate.set_root_window(&root);
338 root.SetVisible(true);
339 404
340 ServerWindow child(&window_delegate, WindowId(1, 3)); 405 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
341 root.Add(&child); 406 child->SetBounds(gfx::Rect(10, 10, 20, 20));
342 child.SetVisible(true);
343 EnableHitTest(&child);
344
345 root.SetBounds(gfx::Rect(0, 0, 100, 100));
346 child.SetBounds(gfx::Rect(10, 10, 20, 20));
347
348 TestEventDispatcherDelegate event_dispatcher_delegate(&root);
349 EventDispatcher dispatcher(&event_dispatcher_delegate);
350 dispatcher.set_root(&root);
351 407
352 MouseEventTest tests[] = { 408 MouseEventTest tests[] = {
353 // Send a mouse down event over child with a left mouse button 409 // Send a mouse down event over child with a left mouse button
354 {ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), 410 {ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(20, 25),
355 gfx::Point(20, 25), base::TimeDelta(), 411 gfx::Point(20, 25), base::TimeDelta(),
356 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON), 412 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON),
357 &child, gfx::Point(20, 25), gfx::Point(10, 15), nullptr, gfx::Point(), 413 child.get(), gfx::Point(20, 25), gfx::Point(10, 15), nullptr,
358 gfx::Point()}, 414 gfx::Point(), gfx::Point()},
359 415
360 // Capture should be activated. Let's send a mouse move outside the bounds 416 // Capture should be activated. Let's send a mouse move outside the bounds
361 // of the child and press the right mouse button too. 417 // of the child and press the right mouse button too.
362 {ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(50, 50), 418 {ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(50, 50),
363 gfx::Point(50, 50), base::TimeDelta(), 419 gfx::Point(50, 50), base::TimeDelta(),
364 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON, 0), 420 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON, 0),
365 &child, gfx::Point(50, 50), gfx::Point(40, 40), nullptr, gfx::Point(), 421 child.get(), gfx::Point(50, 50), gfx::Point(40, 40), nullptr,
366 gfx::Point()}, 422 gfx::Point(), gfx::Point()},
367 423
368 // Release the left mouse button and verify that the mouse up event goes 424 // Release the left mouse button and verify that the mouse up event goes
369 // to the child. 425 // to the child.
370 {ui::MouseEvent(ui::ET_MOUSE_RELEASED, gfx::Point(50, 50), 426 {ui::MouseEvent(ui::ET_MOUSE_RELEASED, gfx::Point(50, 50),
371 gfx::Point(50, 50), base::TimeDelta(), 427 gfx::Point(50, 50), base::TimeDelta(),
372 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON, 428 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON,
373 ui::EF_RIGHT_MOUSE_BUTTON), 429 ui::EF_RIGHT_MOUSE_BUTTON),
374 &child, gfx::Point(50, 50), gfx::Point(40, 40), nullptr, gfx::Point(), 430 child.get(), gfx::Point(50, 50), gfx::Point(40, 40), nullptr,
375 gfx::Point()}, 431 gfx::Point(), gfx::Point()},
376 432
377 // A mouse move at (50, 50) should still go to the child. 433 // A mouse move at (50, 50) should still go to the child.
378 {ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(50, 50), 434 {ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(50, 50),
379 gfx::Point(50, 50), base::TimeDelta(), 435 gfx::Point(50, 50), base::TimeDelta(),
380 ui::EF_LEFT_MOUSE_BUTTON, 0), 436 ui::EF_LEFT_MOUSE_BUTTON, 0),
381 &child, gfx::Point(50, 50), gfx::Point(40, 40), nullptr, gfx::Point(), 437 child.get(), gfx::Point(50, 50), gfx::Point(40, 40), nullptr,
382 gfx::Point()}, 438 gfx::Point(), gfx::Point()},
383 439
384 }; 440 };
385 RunMouseEventTests(&dispatcher, &event_dispatcher_delegate, tests, 441 RunMouseEventTests(event_dispatcher(), test_event_dispatcher_delegate(),
386 arraysize(tests)); 442 tests, arraysize(tests));
387 } 443 }
388 444
389 TEST(EventDispatcherTest, ClientAreaGoesToOwner) { 445 TEST_F(EventDispatcherTest, ClientAreaGoesToOwner) {
390 TestServerWindowDelegate window_delegate; 446 scoped_ptr<ServerWindow> child(CreateChildWindow(WindowId(1, 3)));
391 ServerWindow root(&window_delegate, WindowId(1, 2));
392 window_delegate.set_root_window(&root);
393 root.SetVisible(true);
394 447
395 ServerWindow child(&window_delegate, WindowId(1, 3)); 448 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
396 root.Add(&child); 449 child->SetBounds(gfx::Rect(10, 10, 20, 20));
397 child.SetVisible(true);
398 EnableHitTest(&child);
399 450
400 root.SetBounds(gfx::Rect(0, 0, 100, 100)); 451 child->SetClientArea(gfx::Insets(5, 5, 5, 5), std::vector<gfx::Rect>());
401 child.SetBounds(gfx::Rect(10, 10, 20, 20));
402 452
403 child.SetClientArea(gfx::Insets(5, 5, 5, 5), std::vector<gfx::Rect>()); 453 TestEventDispatcherDelegate* event_dispatcher_delegate =
404 454 test_event_dispatcher_delegate();
405 TestEventDispatcherDelegate event_dispatcher_delegate(&root); 455 EventDispatcher* dispatcher = event_dispatcher();
406 EventDispatcher dispatcher(&event_dispatcher_delegate);
407 dispatcher.set_root(&root);
408 456
409 // Start move loop by sending mouse event over non-client area. 457 // Start move loop by sending mouse event over non-client area.
410 const ui::MouseEvent press_event( 458 const ui::MouseEvent press_event(
411 ui::ET_MOUSE_PRESSED, gfx::Point(12, 12), gfx::Point(12, 12), 459 ui::ET_MOUSE_PRESSED, gfx::Point(12, 12), gfx::Point(12, 12),
412 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); 460 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
413 dispatcher.ProcessEvent( 461 dispatcher->ProcessEvent(
414 mojom::Event::From(static_cast<const ui::Event&>(press_event))); 462 mojom::Event::From(static_cast<const ui::Event&>(press_event)));
415 463
416 // Events should target child and be in the non-client area. 464 // Events should target child and be in the non-client area.
417 scoped_ptr<DispatchedEventDetails> details = 465 scoped_ptr<DispatchedEventDetails> details =
418 event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 466 event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
419 EXPECT_FALSE(event_dispatcher_delegate.has_queued_events()); 467 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
420 ASSERT_TRUE(details); 468 ASSERT_TRUE(details);
421 ASSERT_EQ(&child, details->window); 469 ASSERT_EQ(child.get(), details->window);
422 EXPECT_TRUE(details->in_nonclient_area); 470 EXPECT_TRUE(details->in_nonclient_area);
423 471
424 // Move the mouse 5,6 pixels and target is the same. 472 // Move the mouse 5,6 pixels and target is the same.
425 const ui::MouseEvent move_event(ui::ET_MOUSE_MOVED, gfx::Point(17, 18), 473 const ui::MouseEvent move_event(ui::ET_MOUSE_MOVED, gfx::Point(17, 18),
426 gfx::Point(17, 18), base::TimeDelta(), 474 gfx::Point(17, 18), base::TimeDelta(),
427 ui::EF_LEFT_MOUSE_BUTTON, 0); 475 ui::EF_LEFT_MOUSE_BUTTON, 0);
428 dispatcher.ProcessEvent( 476 dispatcher->ProcessEvent(
429 mojom::Event::From(static_cast<const ui::Event&>(move_event))); 477 mojom::Event::From(static_cast<const ui::Event&>(move_event)));
430 478
431 // Still same target. 479 // Still same target.
432 details = event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 480 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
433 EXPECT_FALSE(event_dispatcher_delegate.has_queued_events()); 481 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
434 ASSERT_EQ(&child, details->window); 482 ASSERT_EQ(child.get(), details->window);
435 EXPECT_TRUE(details->in_nonclient_area); 483 EXPECT_TRUE(details->in_nonclient_area);
436 484
437 // Release the mouse. 485 // Release the mouse.
438 const ui::MouseEvent release_event( 486 const ui::MouseEvent release_event(
439 ui::ET_MOUSE_RELEASED, gfx::Point(17, 18), gfx::Point(17, 18), 487 ui::ET_MOUSE_RELEASED, gfx::Point(17, 18), gfx::Point(17, 18),
440 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); 488 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
441 dispatcher.ProcessEvent( 489 dispatcher->ProcessEvent(
442 mojom::Event::From(static_cast<const ui::Event&>(release_event))); 490 mojom::Event::From(static_cast<const ui::Event&>(release_event)));
443 491
444 // The event should not have been dispatched to the delegate. 492 // The event should not have been dispatched to the delegate.
445 details = event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 493 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
446 EXPECT_FALSE(event_dispatcher_delegate.has_queued_events()); 494 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
447 ASSERT_EQ(&child, details->window); 495 ASSERT_EQ(child.get(), details->window);
448 EXPECT_TRUE(details->in_nonclient_area); 496 EXPECT_TRUE(details->in_nonclient_area);
449 497
450 // Press in the client area and verify target/client area. The non-client area 498 // Press in the client area and verify target/client area. The non-client area
451 // should get an exit first. 499 // should get an exit first.
452 const ui::MouseEvent press_event2( 500 const ui::MouseEvent press_event2(
453 ui::ET_MOUSE_PRESSED, gfx::Point(21, 22), gfx::Point(21, 22), 501 ui::ET_MOUSE_PRESSED, gfx::Point(21, 22), gfx::Point(21, 22),
454 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); 502 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
455 dispatcher.ProcessEvent( 503 dispatcher->ProcessEvent(
456 mojom::Event::From(static_cast<const ui::Event&>(press_event2))); 504 mojom::Event::From(static_cast<const ui::Event&>(press_event2)));
457 details = event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 505 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
458 EXPECT_TRUE(event_dispatcher_delegate.has_queued_events()); 506 EXPECT_TRUE(event_dispatcher_delegate->has_queued_events());
459 ASSERT_EQ(&child, details->window); 507 ASSERT_EQ(child.get(), details->window);
460 EXPECT_TRUE(details->in_nonclient_area); 508 EXPECT_TRUE(details->in_nonclient_area);
461 EXPECT_EQ(mojom::EventType::MOUSE_EXIT, details->event->action); 509 EXPECT_EQ(mojom::EventType::MOUSE_EXIT, details->event->action);
462 510
463 details = event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 511 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
464 EXPECT_FALSE(event_dispatcher_delegate.has_queued_events()); 512 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
465 ASSERT_EQ(&child, details->window); 513 ASSERT_EQ(child.get(), details->window);
466 EXPECT_FALSE(details->in_nonclient_area); 514 EXPECT_FALSE(details->in_nonclient_area);
467 EXPECT_EQ(mojom::EventType::POINTER_DOWN, details->event->action); 515 EXPECT_EQ(mojom::EventType::POINTER_DOWN, details->event->action);
468 } 516 }
469 517
470 TEST(EventDispatcherTest, AdditionalClientArea) { 518 TEST_F(EventDispatcherTest, AdditionalClientArea) {
471 TestServerWindowDelegate window_delegate; 519 scoped_ptr<ServerWindow> child(CreateChildWindow(WindowId(1, 3)));
472 ServerWindow root(&window_delegate, WindowId(1, 2));
473 window_delegate.set_root_window(&root);
474 root.SetVisible(true);
475 520
476 ServerWindow child(&window_delegate, WindowId(1, 3)); 521 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
477 root.Add(&child); 522 child->SetBounds(gfx::Rect(10, 10, 20, 20));
478 child.SetVisible(true);
479 EnableHitTest(&child);
480
481 root.SetBounds(gfx::Rect(0, 0, 100, 100));
482 child.SetBounds(gfx::Rect(10, 10, 20, 20));
483 523
484 std::vector<gfx::Rect> additional_client_areas; 524 std::vector<gfx::Rect> additional_client_areas;
485 additional_client_areas.push_back(gfx::Rect(18, 0, 2, 2)); 525 additional_client_areas.push_back(gfx::Rect(18, 0, 2, 2));
486 child.SetClientArea(gfx::Insets(5, 5, 5, 5), additional_client_areas); 526 child->SetClientArea(gfx::Insets(5, 5, 5, 5), additional_client_areas);
487 527
488 TestEventDispatcherDelegate event_dispatcher_delegate(&root); 528 TestEventDispatcherDelegate* event_dispatcher_delegate =
489 EventDispatcher dispatcher(&event_dispatcher_delegate); 529 test_event_dispatcher_delegate();
490 dispatcher.set_root(&root);
491
492 // Press in the additional client area, it should go to the child. 530 // Press in the additional client area, it should go to the child.
493 const ui::MouseEvent press_event( 531 const ui::MouseEvent press_event(
494 ui::ET_MOUSE_PRESSED, gfx::Point(28, 11), gfx::Point(28, 11), 532 ui::ET_MOUSE_PRESSED, gfx::Point(28, 11), gfx::Point(28, 11),
495 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); 533 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
496 dispatcher.ProcessEvent( 534 event_dispatcher()->ProcessEvent(
497 mojom::Event::From(static_cast<const ui::Event&>(press_event))); 535 mojom::Event::From(static_cast<const ui::Event&>(press_event)));
498 536
499 // Events should target child and be in the client area. 537 // Events should target child and be in the client area.
500 scoped_ptr<DispatchedEventDetails> details = 538 scoped_ptr<DispatchedEventDetails> details =
501 event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 539 event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
502 EXPECT_FALSE(event_dispatcher_delegate.has_queued_events()); 540 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
503 ASSERT_EQ(&child, details->window); 541 ASSERT_EQ(child.get(), details->window);
504 EXPECT_FALSE(details->in_nonclient_area); 542 EXPECT_FALSE(details->in_nonclient_area);
505 } 543 }
506 544
507 TEST(EventDispatcherTest, DontFocusOnSecondDown) { 545 TEST_F(EventDispatcherTest, DontFocusOnSecondDown) {
508 TestServerWindowDelegate window_delegate; 546 scoped_ptr<ServerWindow> child1(CreateChildWindow(WindowId(1, 3)));
509 ServerWindow root(&window_delegate, WindowId(1, 2)); 547 scoped_ptr<ServerWindow> child2(CreateChildWindow(WindowId(1, 4)));
510 window_delegate.set_root_window(&root);
511 root.SetVisible(true);
512 548
513 ServerWindow child1(&window_delegate, WindowId(1, 3)); 549 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
514 root.Add(&child1); 550 child1->SetBounds(gfx::Rect(10, 10, 20, 20));
515 child1.SetVisible(true); 551 child2->SetBounds(gfx::Rect(50, 51, 11, 12));
516 EnableHitTest(&child1);
517 552
518 ServerWindow child2(&window_delegate, WindowId(1, 4)); 553 TestEventDispatcherDelegate* event_dispatcher_delegate =
519 root.Add(&child2); 554 test_event_dispatcher_delegate();
520 child2.SetVisible(true); 555 EventDispatcher* dispatcher = event_dispatcher();
521 EnableHitTest(&child2);
522
523 root.SetBounds(gfx::Rect(0, 0, 100, 100));
524 child1.SetBounds(gfx::Rect(10, 10, 20, 20));
525 child2.SetBounds(gfx::Rect(50, 51, 11, 12));
526
527 TestEventDispatcherDelegate event_dispatcher_delegate(&root);
528 EventDispatcher dispatcher(&event_dispatcher_delegate);
529 dispatcher.set_root(&root);
530 556
531 // Press on child1. First press event should change focus. 557 // Press on child1. First press event should change focus.
532 const ui::MouseEvent press_event( 558 const ui::MouseEvent press_event(
533 ui::ET_MOUSE_PRESSED, gfx::Point(12, 12), gfx::Point(12, 12), 559 ui::ET_MOUSE_PRESSED, gfx::Point(12, 12), gfx::Point(12, 12),
534 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); 560 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
535 dispatcher.ProcessEvent( 561 dispatcher->ProcessEvent(
536 mojom::Event::From(static_cast<const ui::Event&>(press_event))); 562 mojom::Event::From(static_cast<const ui::Event&>(press_event)));
537 scoped_ptr<DispatchedEventDetails> details = 563 scoped_ptr<DispatchedEventDetails> details =
538 event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 564 event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
539 EXPECT_FALSE(event_dispatcher_delegate.has_queued_events()); 565 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
540 EXPECT_EQ(&child1, details->window); 566 EXPECT_EQ(child1.get(), details->window);
541 EXPECT_EQ(&child1, event_dispatcher_delegate.GetAndClearLastFocusedWindow()); 567 EXPECT_EQ(child1.get(),
568 event_dispatcher_delegate->GetAndClearLastFocusedWindow());
542 569
543 // Press (with a different pointer id) on child2. Event should go to child2, 570 // Press (with a different pointer id) on child2. Event should go to child2,
544 // but focus should not change. 571 // but focus should not change.
545 const ui::TouchEvent touch_event(ui::ET_TOUCH_PRESSED, gfx::Point(53, 54), 2, 572 const ui::TouchEvent touch_event(ui::ET_TOUCH_PRESSED, gfx::Point(53, 54), 2,
546 base::TimeDelta()); 573 base::TimeDelta());
547 dispatcher.ProcessEvent( 574 dispatcher->ProcessEvent(
548 mojom::Event::From(static_cast<const ui::Event&>(touch_event))); 575 mojom::Event::From(static_cast<const ui::Event&>(touch_event)));
549 details = event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 576 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
550 EXPECT_FALSE(event_dispatcher_delegate.has_queued_events()); 577 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
551 EXPECT_EQ(&child2, details->window); 578 EXPECT_EQ(child2.get(), details->window);
552 EXPECT_EQ(nullptr, event_dispatcher_delegate.GetAndClearLastFocusedWindow()); 579 EXPECT_EQ(nullptr, event_dispatcher_delegate->GetAndClearLastFocusedWindow());
553 } 580 }
554 581
555 TEST(EventDispatcherTest, TwoPointersActive) { 582 TEST_F(EventDispatcherTest, TwoPointersActive) {
556 TestServerWindowDelegate window_delegate; 583 scoped_ptr<ServerWindow> child1(CreateChildWindow(WindowId(1, 3)));
557 ServerWindow root(&window_delegate, WindowId(1, 2)); 584 scoped_ptr<ServerWindow> child2(CreateChildWindow(WindowId(1, 4)));
558 window_delegate.set_root_window(&root);
559 root.SetVisible(true);
560 585
561 ServerWindow child1(&window_delegate, WindowId(1, 3)); 586 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
562 root.Add(&child1); 587 child1->SetBounds(gfx::Rect(10, 10, 20, 20));
563 child1.SetVisible(true); 588 child2->SetBounds(gfx::Rect(50, 51, 11, 12));
564 EnableHitTest(&child1);
565 589
566 ServerWindow child2(&window_delegate, WindowId(1, 4)); 590 TestEventDispatcherDelegate* event_dispatcher_delegate =
567 root.Add(&child2); 591 test_event_dispatcher_delegate();
568 child2.SetVisible(true); 592 EventDispatcher* dispatcher = event_dispatcher();
569 EnableHitTest(&child2);
570
571 root.SetBounds(gfx::Rect(0, 0, 100, 100));
572 child1.SetBounds(gfx::Rect(10, 10, 20, 20));
573 child2.SetBounds(gfx::Rect(50, 51, 11, 12));
574
575 TestEventDispatcherDelegate event_dispatcher_delegate(&root);
576 EventDispatcher dispatcher(&event_dispatcher_delegate);
577 dispatcher.set_root(&root);
578 593
579 // Press on child1. 594 // Press on child1.
580 const ui::TouchEvent touch_event1(ui::ET_TOUCH_PRESSED, gfx::Point(12, 13), 1, 595 const ui::TouchEvent touch_event1(ui::ET_TOUCH_PRESSED, gfx::Point(12, 13), 1,
581 base::TimeDelta()); 596 base::TimeDelta());
582 dispatcher.ProcessEvent( 597 dispatcher->ProcessEvent(
583 mojom::Event::From(static_cast<const ui::Event&>(touch_event1))); 598 mojom::Event::From(static_cast<const ui::Event&>(touch_event1)));
584 scoped_ptr<DispatchedEventDetails> details = 599 scoped_ptr<DispatchedEventDetails> details =
585 event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 600 event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
586 EXPECT_EQ(&child1, details->window); 601 EXPECT_EQ(child1.get(), details->window);
587 602
588 // Drag over child2, child1 should get the drag. 603 // Drag over child2, child1 should get the drag.
589 const ui::TouchEvent drag_event1(ui::ET_TOUCH_MOVED, gfx::Point(53, 54), 1, 604 const ui::TouchEvent drag_event1(ui::ET_TOUCH_MOVED, gfx::Point(53, 54), 1,
590 base::TimeDelta()); 605 base::TimeDelta());
591 dispatcher.ProcessEvent( 606 dispatcher->ProcessEvent(
592 mojom::Event::From(static_cast<const ui::Event&>(drag_event1))); 607 mojom::Event::From(static_cast<const ui::Event&>(drag_event1)));
593 details = event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 608 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
594 EXPECT_EQ(&child1, details->window); 609 EXPECT_EQ(child1.get(), details->window);
595 610
596 // Press on child2 with a different touch id. 611 // Press on child2 with a different touch id.
597 const ui::TouchEvent touch_event2(ui::ET_TOUCH_PRESSED, gfx::Point(54, 55), 2, 612 const ui::TouchEvent touch_event2(ui::ET_TOUCH_PRESSED, gfx::Point(54, 55), 2,
598 base::TimeDelta()); 613 base::TimeDelta());
599 dispatcher.ProcessEvent( 614 dispatcher->ProcessEvent(
600 mojom::Event::From(static_cast<const ui::Event&>(touch_event2))); 615 mojom::Event::From(static_cast<const ui::Event&>(touch_event2)));
601 details = event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 616 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
602 EXPECT_EQ(&child2, details->window); 617 EXPECT_EQ(child2.get(), details->window);
603 618
604 // Drag over child1 with id 2, child2 should continue to get the drag. 619 // Drag over child1 with id 2, child2 should continue to get the drag.
605 const ui::TouchEvent drag_event2(ui::ET_TOUCH_MOVED, gfx::Point(13, 14), 2, 620 const ui::TouchEvent drag_event2(ui::ET_TOUCH_MOVED, gfx::Point(13, 14), 2,
606 base::TimeDelta()); 621 base::TimeDelta());
607 dispatcher.ProcessEvent( 622 dispatcher->ProcessEvent(
608 mojom::Event::From(static_cast<const ui::Event&>(drag_event2))); 623 mojom::Event::From(static_cast<const ui::Event&>(drag_event2)));
609 details = event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 624 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
610 EXPECT_EQ(&child2, details->window); 625 EXPECT_EQ(child2.get(), details->window);
611 626
612 // Drag again with id 1, child1 should continue to get it. 627 // Drag again with id 1, child1 should continue to get it.
613 dispatcher.ProcessEvent( 628 dispatcher->ProcessEvent(
614 mojom::Event::From(static_cast<const ui::Event&>(drag_event1))); 629 mojom::Event::From(static_cast<const ui::Event&>(drag_event1)));
615 details = event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 630 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
616 EXPECT_EQ(&child1, details->window); 631 EXPECT_EQ(child1.get(), details->window);
617 632
618 // Release touch id 1, and click on 2. 2 should get it. 633 // Release touch id 1, and click on 2. 2 should get it.
619 const ui::TouchEvent touch_release(ui::ET_TOUCH_RELEASED, gfx::Point(54, 55), 634 const ui::TouchEvent touch_release(ui::ET_TOUCH_RELEASED, gfx::Point(54, 55),
620 1, base::TimeDelta()); 635 1, base::TimeDelta());
621 dispatcher.ProcessEvent( 636 dispatcher->ProcessEvent(
622 mojom::Event::From(static_cast<const ui::Event&>(touch_release))); 637 mojom::Event::From(static_cast<const ui::Event&>(touch_release)));
623 details = event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 638 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
624 EXPECT_EQ(&child1, details->window); 639 EXPECT_EQ(child1.get(), details->window);
625 const ui::TouchEvent touch_event3(ui::ET_TOUCH_PRESSED, gfx::Point(54, 55), 2, 640 const ui::TouchEvent touch_event3(ui::ET_TOUCH_PRESSED, gfx::Point(54, 55), 2,
626 base::TimeDelta()); 641 base::TimeDelta());
627 dispatcher.ProcessEvent( 642 dispatcher->ProcessEvent(
628 mojom::Event::From(static_cast<const ui::Event&>(touch_event3))); 643 mojom::Event::From(static_cast<const ui::Event&>(touch_event3)));
629 details = event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 644 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
630 EXPECT_EQ(&child2, details->window); 645 EXPECT_EQ(child2.get(), details->window);
631 } 646 }
632 647
633 TEST(EventDispatcherTest, DestroyWindowWhileGettingEvents) { 648 TEST_F(EventDispatcherTest, DestroyWindowWhileGettingEvents) {
634 TestServerWindowDelegate window_delegate; 649 scoped_ptr<ServerWindow> child(CreateChildWindow(WindowId(1, 3)));
635 ServerWindow root(&window_delegate, WindowId(1, 2));
636 window_delegate.set_root_window(&root);
637 root.SetVisible(true);
638 650
639 scoped_ptr<ServerWindow> child( 651 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
640 new ServerWindow(&window_delegate, WindowId(1, 3)));
641 root.Add(child.get());
642 child->SetVisible(true);
643 EnableHitTest(child.get());
644
645 root.SetBounds(gfx::Rect(0, 0, 100, 100));
646 child->SetBounds(gfx::Rect(10, 10, 20, 20)); 652 child->SetBounds(gfx::Rect(10, 10, 20, 20));
647 653
648 TestEventDispatcherDelegate event_dispatcher_delegate(&root); 654 TestEventDispatcherDelegate* event_dispatcher_delegate =
649 EventDispatcher dispatcher(&event_dispatcher_delegate); 655 test_event_dispatcher_delegate();
650 dispatcher.set_root(&root); 656 EventDispatcher* dispatcher = event_dispatcher();
651 657
652 // Press on child. 658 // Press on child.
653 const ui::TouchEvent touch_event1(ui::ET_TOUCH_PRESSED, gfx::Point(12, 13), 1, 659 const ui::TouchEvent touch_event1(ui::ET_TOUCH_PRESSED, gfx::Point(12, 13), 1,
654 base::TimeDelta()); 660 base::TimeDelta());
655 dispatcher.ProcessEvent( 661 dispatcher->ProcessEvent(
656 mojom::Event::From(static_cast<const ui::Event&>(touch_event1))); 662 mojom::Event::From(static_cast<const ui::Event&>(touch_event1)));
657 scoped_ptr<DispatchedEventDetails> details = 663 scoped_ptr<DispatchedEventDetails> details =
658 event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 664 event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
659 EXPECT_FALSE(event_dispatcher_delegate.has_queued_events()); 665 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
660 EXPECT_EQ(child.get(), details->window); 666 EXPECT_EQ(child.get(), details->window);
661 667
662 // Delete child, and continue the drag. Event should not be dispatched. 668 // Delete child, and continue the drag. Event should not be dispatched.
663 child.reset(); 669 child.reset();
664 670
665 const ui::TouchEvent drag_event1(ui::ET_TOUCH_MOVED, gfx::Point(53, 54), 1, 671 const ui::TouchEvent drag_event1(ui::ET_TOUCH_MOVED, gfx::Point(53, 54), 1,
666 base::TimeDelta()); 672 base::TimeDelta());
667 dispatcher.ProcessEvent( 673 dispatcher->ProcessEvent(
668 mojom::Event::From(static_cast<const ui::Event&>(drag_event1))); 674 mojom::Event::From(static_cast<const ui::Event&>(drag_event1)));
669 details = event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 675 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
670 EXPECT_EQ(nullptr, details.get()); 676 EXPECT_EQ(nullptr, details.get());
671 } 677 }
672 678
673 TEST(EventDispatcherTest, MouseInExtendedHitTestRegion) { 679 TEST_F(EventDispatcherTest, MouseInExtendedHitTestRegion) {
674 TestServerWindowDelegate window_delegate; 680 ServerWindow* root = root_window();
675 ServerWindow root(&window_delegate, WindowId(1, 2)); 681 scoped_ptr<ServerWindow> child(CreateChildWindow(WindowId(1, 3)));
676 window_delegate.set_root_window(&root);
677 root.SetVisible(true);
678 682
679 ServerWindow child(&window_delegate, WindowId(1, 3)); 683 root->SetBounds(gfx::Rect(0, 0, 100, 100));
680 root.Add(&child); 684 child->SetBounds(gfx::Rect(10, 10, 20, 20));
681 child.SetVisible(true);
682 EnableHitTest(&child);
683 685
684 root.SetBounds(gfx::Rect(0, 0, 100, 100)); 686 TestEventDispatcherDelegate* event_dispatcher_delegate =
685 child.SetBounds(gfx::Rect(10, 10, 20, 20)); 687 test_event_dispatcher_delegate();
686 688 EventDispatcher* dispatcher = event_dispatcher();
687 TestEventDispatcherDelegate event_dispatcher_delegate(&root);
688 EventDispatcher dispatcher(&event_dispatcher_delegate);
689 dispatcher.set_root(&root);
690 689
691 // Send event that is not over child. 690 // Send event that is not over child.
692 const ui::MouseEvent ui_event( 691 const ui::MouseEvent ui_event(
693 ui::ET_MOUSE_PRESSED, gfx::Point(8, 9), gfx::Point(8, 9), 692 ui::ET_MOUSE_PRESSED, gfx::Point(8, 9), gfx::Point(8, 9),
694 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); 693 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
695 dispatcher.ProcessEvent( 694 dispatcher->ProcessEvent(
696 mojom::Event::From(static_cast<const ui::Event&>(ui_event))); 695 mojom::Event::From(static_cast<const ui::Event&>(ui_event)));
697 scoped_ptr<DispatchedEventDetails> details = 696 scoped_ptr<DispatchedEventDetails> details =
698 event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 697 event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
699 ASSERT_EQ(&root, details->window); 698 ASSERT_EQ(root, details->window);
700 699
701 // Release the mouse. 700 // Release the mouse.
702 const ui::MouseEvent release_event( 701 const ui::MouseEvent release_event(
703 ui::ET_MOUSE_RELEASED, gfx::Point(8, 9), gfx::Point(8, 9), 702 ui::ET_MOUSE_RELEASED, gfx::Point(8, 9), gfx::Point(8, 9),
704 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); 703 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
705 dispatcher.ProcessEvent( 704 dispatcher->ProcessEvent(
706 mojom::Event::From(static_cast<const ui::Event&>(release_event))); 705 mojom::Event::From(static_cast<const ui::Event&>(release_event)));
707 details = event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 706 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
708 EXPECT_FALSE(event_dispatcher_delegate.has_queued_events()); 707 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
709 ASSERT_EQ(&root, details->window); 708 ASSERT_EQ(root, details->window);
710 EXPECT_FALSE(details->in_nonclient_area); 709 EXPECT_FALSE(details->in_nonclient_area);
711 710
712 // Change the extended hit test region and send event in extended hit test 711 // Change the extended hit test region and send event in extended hit test
713 // region. Should result in exit for root, followed by press for child. 712 // region. Should result in exit for root, followed by press for child.
714 child.set_extended_hit_test_region(gfx::Insets(5, 5, 5, 5)); 713 child->set_extended_hit_test_region(gfx::Insets(5, 5, 5, 5));
715 dispatcher.ProcessEvent( 714 dispatcher->ProcessEvent(
716 mojom::Event::From(static_cast<const ui::Event&>(ui_event))); 715 mojom::Event::From(static_cast<const ui::Event&>(ui_event)));
717 details = event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 716 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
718 EXPECT_EQ(&root, details->window); 717 EXPECT_EQ(root, details->window);
719 EXPECT_EQ(mojom::EventType::MOUSE_EXIT, details->event->action); 718 EXPECT_EQ(mojom::EventType::MOUSE_EXIT, details->event->action);
720 details = event_dispatcher_delegate.GetAndAdvanceDispatchedEventDetails(); 719 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
721 ASSERT_TRUE(details); 720 ASSERT_TRUE(details);
722 721
723 EXPECT_FALSE(event_dispatcher_delegate.has_queued_events()); 722 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
724 EXPECT_TRUE(details->in_nonclient_area); 723 EXPECT_TRUE(details->in_nonclient_area);
725 ASSERT_EQ(&child, details->window); 724 ASSERT_EQ(child.get(), details->window);
726 EXPECT_EQ(mojom::EventType::POINTER_DOWN, details->event->action); 725 EXPECT_EQ(mojom::EventType::POINTER_DOWN, details->event->action);
727 scoped_ptr<ui::Event> dispatched_event( 726 scoped_ptr<ui::Event> dispatched_event(
728 details->event.To<scoped_ptr<ui::Event>>()); 727 details->event.To<scoped_ptr<ui::Event>>());
729 ASSERT_TRUE(dispatched_event.get()); 728 ASSERT_TRUE(dispatched_event.get());
730 ASSERT_TRUE(dispatched_event->IsMouseEvent()); 729 ASSERT_TRUE(dispatched_event->IsMouseEvent());
731 ui::MouseEvent* dispatched_mouse_event = 730 ui::MouseEvent* dispatched_mouse_event =
732 static_cast<ui::MouseEvent*>(dispatched_event.get()); 731 static_cast<ui::MouseEvent*>(dispatched_event.get());
733 EXPECT_EQ(gfx::Point(-2, -1), dispatched_mouse_event->location()); 732 EXPECT_EQ(gfx::Point(-2, -1), dispatched_mouse_event->location());
734 } 733 }
735 734
736 TEST(EventDispatcherTest, WheelWhileDown) { 735 TEST_F(EventDispatcherTest, WheelWhileDown) {
737 TestServerWindowDelegate window_delegate; 736 scoped_ptr<ServerWindow> child1(CreateChildWindow(WindowId(1, 3)));
738 ServerWindow root(&window_delegate, WindowId(1, 2)); 737 scoped_ptr<ServerWindow> child2(CreateChildWindow(WindowId(1, 4)));
739 window_delegate.set_root_window(&root); 738
740 root.SetVisible(true); 739 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
741 740 child1->SetBounds(gfx::Rect(10, 10, 20, 20));
742 ServerWindow child1(&window_delegate, WindowId(1, 3)); 741 child2->SetBounds(gfx::Rect(50, 51, 11, 12));
743 root.Add(&child1);
744 child1.SetVisible(true);
745 EnableHitTest(&child1);
746
747 ServerWindow child2(&window_delegate, WindowId(1, 4));
748 root.Add(&child2);
749 child2.SetVisible(true);
750 EnableHitTest(&child2);
751
752 root.SetBounds(gfx::Rect(0, 0, 100, 100));
753 child1.SetBounds(gfx::Rect(10, 10, 20, 20));
754 child2.SetBounds(gfx::Rect(50, 51, 11, 12));
755
756 TestEventDispatcherDelegate event_dispatcher_delegate(&root);
757 EventDispatcher dispatcher(&event_dispatcher_delegate);
758 dispatcher.set_root(&root);
759 742
760 MouseEventTest tests[] = { 743 MouseEventTest tests[] = {
761 // Send a mouse down event over child1. 744 // Send a mouse down event over child1.
762 {ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(15, 15), 745 {ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(15, 15),
763 gfx::Point(15, 15), base::TimeDelta(), 746 gfx::Point(15, 15), base::TimeDelta(),
764 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON), 747 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON),
765 &child1, gfx::Point(15, 15), gfx::Point(5, 5), nullptr, gfx::Point(), 748 child1.get(), gfx::Point(15, 15), gfx::Point(5, 5), nullptr,
766 gfx::Point()}, 749 gfx::Point(), gfx::Point()},
767 // Send mouse wheel over child2, should go to child1 as it has capture. 750 // Send mouse wheel over child2, should go to child1 as it has capture.
768 {ui::MouseWheelEvent(gfx::Vector2d(1, 0), gfx::Point(53, 54), 751 {ui::MouseWheelEvent(gfx::Vector2d(1, 0), gfx::Point(53, 54),
769 gfx::Point(53, 54), base::TimeDelta(), ui::EF_NONE, 752 gfx::Point(53, 54), base::TimeDelta(), ui::EF_NONE,
770 ui::EF_NONE), 753 ui::EF_NONE),
771 &child1, gfx::Point(53, 54), gfx::Point(43, 44), nullptr, gfx::Point(), 754 child1.get(), gfx::Point(53, 54), gfx::Point(43, 44), nullptr,
772 gfx::Point()}, 755 gfx::Point(), gfx::Point()},
773 }; 756 };
774 RunMouseEventTests(&dispatcher, &event_dispatcher_delegate, tests, 757 RunMouseEventTests(event_dispatcher(), test_event_dispatcher_delegate(),
758 tests, arraysize(tests));
759 }
760
761 // Tests that when explicit capture has been set that all events go to the
762 // designated window, and that when capture is cleared, events find the
763 // appropriate target window.
764 TEST_F(EventDispatcherTest, SetExplictCapture) {
765 ServerWindow* root = root_window();
766 scoped_ptr<ServerWindow> child(CreateChildWindow(WindowId(1, 3)));
767
768 root->SetBounds(gfx::Rect(0, 0, 100, 100));
769 child->SetBounds(gfx::Rect(10, 10, 20, 20));
770
771 TestEventDispatcherDelegate* event_dispatcher_delegate =
772 test_event_dispatcher_delegate();
773 EventDispatcher* dispatcher = event_dispatcher();
774
775 {
776 // Send all pointer events to the child.
777 dispatcher->SetCaptureWindow(child.get(), false);
778
779 // The mouse press should go to the child even though its outside its
780 // bounds.
781 const ui::MouseEvent press_event(
782 ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), gfx::Point(5, 5),
783 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
784 dispatcher->ProcessEvent(
785 mojom::Event::From(static_cast<const ui::Event&>(press_event)));
786
787 // Events should target child.
788 scoped_ptr<DispatchedEventDetails> details =
789 event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
790
791 ASSERT_TRUE(details);
792 ASSERT_EQ(child.get(), details->window);
793 EXPECT_FALSE(details->in_nonclient_area);
794 }
795
796 {
797 // Releasing capture and sending the same event will go to the root.
798 dispatcher->SetCaptureWindow(nullptr, false);
799 const ui::MouseEvent press_event(
800 ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), gfx::Point(5, 5),
801 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
802 dispatcher->ProcessEvent(
803 mojom::Event::From(static_cast<const ui::Event&>(press_event)));
804
805 // Events should target the root.
806 scoped_ptr<DispatchedEventDetails> details =
807 event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
808
809 ASSERT_TRUE(details);
810 ASSERT_EQ(root, details->window);
811 }
812 }
813
814 // This test verifies that explicit capture overrides and resets implicit
815 // capture.
816 TEST_F(EventDispatcherTest, ExplicitCaptureOverridesImplicitCapture) {
817 ServerWindow* root = root_window();
818 scoped_ptr<ServerWindow> child(CreateChildWindow(WindowId(1, 3)));
819
820 root->SetBounds(gfx::Rect(0, 0, 100, 100));
821 child->SetBounds(gfx::Rect(10, 10, 20, 20));
822
823 TestEventDispatcherDelegate* event_dispatcher_delegate =
824 test_event_dispatcher_delegate();
825 EventDispatcher* dispatcher = event_dispatcher();
826
827 // Run some implicit capture tests.
828 MouseEventTest tests[] = {
829 // Send a mouse down event over child with a left mouse button
830 {ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(20, 25),
831 gfx::Point(20, 25), base::TimeDelta(),
832 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON),
833 child.get(), gfx::Point(20, 25), gfx::Point(10, 15)},
834 // Capture should be activated. Let's send a mouse move outside the bounds
835 // of the child and press the right mouse button too.
836 {ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(50, 50),
837 gfx::Point(50, 50), base::TimeDelta(),
838 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON, 0),
839 child.get(), gfx::Point(50, 50), gfx::Point(40, 40)},
840 // Release the left mouse button and verify that the mouse up event goes
841 // to the child.
842 {ui::MouseEvent(ui::ET_MOUSE_RELEASED, gfx::Point(50, 50),
843 gfx::Point(50, 50), base::TimeDelta(),
844 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON,
845 ui::EF_RIGHT_MOUSE_BUTTON),
846 child.get(), gfx::Point(50, 50), gfx::Point(40, 40)},
847 // A mouse move at (50, 50) should still go to the child.
848 {ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(50, 50),
849 gfx::Point(50, 50), base::TimeDelta(),
850 ui::EF_LEFT_MOUSE_BUTTON, 0),
851 child.get(), gfx::Point(50, 50), gfx::Point(40, 40)},
852
853 };
854 RunMouseEventTests(dispatcher, event_dispatcher_delegate, tests,
775 arraysize(tests)); 855 arraysize(tests));
856
857 // Add a second pointer target to the child.
858 {
859 const ui::TouchEvent touch_event(ui::ET_TOUCH_PRESSED, gfx::Point(12, 13),
860 1, base::TimeDelta());
861 dispatcher->ProcessEvent(
862 mojom::Event::From(static_cast<const ui::Event&>(touch_event)));
863 }
864
865 scoped_ptr<DispatchedEventDetails> details =
866 event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
867 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
868 EXPECT_EQ(child.get(), details->window);
869
870 // Verify that no window has explicit capture and hence we did indeed do
871 // implicit capture.
872 ASSERT_EQ(nullptr, dispatcher->capture_window());
873
874 // Give the root window explicit capture and verify input events over the
875 // child go to the root instead.
876 dispatcher->SetCaptureWindow(root, true);
877
878 // The implicit target should receive a cancel event for each pointer target.
879 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
880 ASSERT_TRUE(details);
881 EXPECT_TRUE(event_dispatcher_delegate->has_queued_events());
882 EXPECT_EQ(child.get(), details->window);
883 EXPECT_EQ(mojom::EventType::POINTER_CANCEL, details->event->action);
884
885 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
886 ASSERT_TRUE(details);
887 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
888 EXPECT_EQ(child.get(), details->window);
889 EXPECT_EQ(mojom::EventType::POINTER_CANCEL, details->event->action);
890
891 const ui::MouseEvent press_event(
892 ui::ET_MOUSE_PRESSED, gfx::Point(15, 15), gfx::Point(15, 15),
893 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
894 dispatcher->ProcessEvent(
895 mojom::Event::From(static_cast<const ui::Event&>(press_event)));
896
897 // Events should target the root.
898 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
899 ASSERT_TRUE(details);
900 ASSERT_EQ(root, details->window);
901 ASSERT_TRUE(details->in_nonclient_area);
902 }
903
904 // Tests that setting capture does delete active pointer targets for the capture
905 // window.
906 TEST_F(EventDispatcherTest, CaptureUpdatesActivePointerTargets) {
907 ServerWindow* root = root_window();
908 root->SetBounds(gfx::Rect(0, 0, 100, 100));
909
910 EventDispatcher* dispatcher = event_dispatcher();
911 {
912 const ui::MouseEvent press_event(
913 ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), gfx::Point(5, 5),
914 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
915 dispatcher->ProcessEvent(
916 mojom::Event::From(static_cast<const ui::Event&>(press_event)));
917
918 scoped_ptr<DispatchedEventDetails> details =
919 test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
920 ASSERT_TRUE(details);
921 ASSERT_EQ(root, details->window);
922 }
923 {
924 const ui::TouchEvent touch_event(ui::ET_TOUCH_PRESSED, gfx::Point(12, 13),
925 1, base::TimeDelta());
926 dispatcher->ProcessEvent(
927 mojom::Event::From(static_cast<const ui::Event&>(touch_event)));
928 }
929
930 ASSERT_TRUE(AreAnyPointersDown());
931 ASSERT_TRUE(IsWindowPointerTarget(root));
932 EXPECT_EQ(2, NumberPointerTargetsForWindow(root));
933
934 // Setting the capture should clear the implicit pointers for the specified
935 // window.
936 dispatcher->SetCaptureWindow(root, true);
937 EXPECT_FALSE(AreAnyPointersDown());
938 EXPECT_FALSE(IsWindowPointerTarget(root));
939 }
940
941 // Tests that when explicit capture is changed, that the previous window with
942 // capture is no longer being observed.
943 TEST_F(EventDispatcherTest, UpdatingCaptureStopsObservingPreviousCapture) {
944 scoped_ptr<ServerWindow> child1(CreateChildWindow(WindowId(1, 3)));
945 scoped_ptr<ServerWindow> child2(CreateChildWindow(WindowId(1, 4)));
946
947 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
948 child1->SetBounds(gfx::Rect(10, 10, 20, 20));
949 child2->SetBounds(gfx::Rect(50, 51, 11, 12));
950
951 EventDispatcher* dispatcher = event_dispatcher();
952 ASSERT_FALSE(AreAnyPointersDown());
953 ASSERT_FALSE(IsWindowPointerTarget(child1.get()));
954 ASSERT_FALSE(IsWindowPointerTarget(child2.get()));
955 dispatcher->SetCaptureWindow(child1.get(), false);
956 dispatcher->SetCaptureWindow(child2.get(), false);
957 EXPECT_EQ(child1.get(),
958 test_event_dispatcher_delegate()->lost_capture_window());
959
960 // If observing does not stop during the capture update this crashes.
961 child1->AddObserver(dispatcher);
962 }
963
964 // Tests that destroying a window with explicit capture clears the capture
965 // state.
966 TEST_F(EventDispatcherTest, DestroyingCaptureWindowRemovesExplicitCapture) {
967 scoped_ptr<ServerWindow> child(CreateChildWindow(WindowId(1, 3)));
968 child->SetBounds(gfx::Rect(10, 10, 20, 20));
969
970 EventDispatcher* dispatcher = event_dispatcher();
971 dispatcher->SetCaptureWindow(child.get(), false);
972 EXPECT_EQ(child.get(), dispatcher->capture_window());
973
974 ServerWindow* lost_capture_window = child.get();
975 child.reset();
976 EXPECT_EQ(nullptr, dispatcher->capture_window());
977 EXPECT_EQ(lost_capture_window,
978 test_event_dispatcher_delegate()->lost_capture_window());
979 }
980
981 // Tests that when |in_nonclient_area| is set for a window performing capture,
982 // that this preference is used regardless of whether an event targets the
983 // client region.
984 TEST_F(EventDispatcherTest, CaptureInNonClientAreaOverridesActualPoint) {
985 ServerWindow* root = root_window();
986 root->SetBounds(gfx::Rect(0, 0, 100, 100));
987
988 root->SetClientArea(gfx::Insets(5, 5, 5, 5), std::vector<gfx::Rect>());
989 EventDispatcher* dispatcher = event_dispatcher();
990 dispatcher->SetCaptureWindow(root, true);
991
992 TestEventDispatcherDelegate* event_dispatcher_delegate =
993 test_event_dispatcher_delegate();
994 // Press in the client area, it should be marked as non client.
995 const ui::MouseEvent press_event(
996 ui::ET_MOUSE_PRESSED, gfx::Point(6, 6), gfx::Point(6, 6),
997 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
998 event_dispatcher()->ProcessEvent(
999 mojom::Event::From(static_cast<const ui::Event&>(press_event)));
1000
1001 // Events should target child and be in the client area.
1002 scoped_ptr<DispatchedEventDetails> details =
1003 event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
1004 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
1005 ASSERT_EQ(root, details->window);
1006 EXPECT_TRUE(details->in_nonclient_area);
776 } 1007 }
777 1008
778 } // namespace ws 1009 } // namespace ws
779 } // namespace mus 1010 } // namespace mus
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698