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

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

Issue 2119963002: Move mus to //services/ui (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 4 years, 5 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
« no previous file with comments | « components/mus/ws/event_dispatcher_delegate.h ('k') | components/mus/ws/event_matcher.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "components/mus/ws/event_dispatcher.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <queue>
11
12 #include "base/macros.h"
13 #include "base/memory/weak_ptr.h"
14 #include "components/mus/common/event_matcher_util.h"
15 #include "components/mus/ws/accelerator.h"
16 #include "components/mus/ws/event_dispatcher_delegate.h"
17 #include "components/mus/ws/server_window.h"
18 #include "components/mus/ws/server_window_surface_manager_test_api.h"
19 #include "components/mus/ws/test_server_window_delegate.h"
20 #include "components/mus/ws/test_utils.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "ui/events/event.h"
23
24 namespace mus {
25 namespace ws {
26 namespace test {
27 namespace {
28
29 // Client ids used to indicate the client area and non-client area.
30 const ClientSpecificId kClientAreaId = 11;
31 const ClientSpecificId kNonclientAreaId = 111;
32
33 // Identifies a generated event.
34 struct DispatchedEventDetails {
35 DispatchedEventDetails()
36 : window(nullptr), client_id(kInvalidClientId), accelerator(nullptr) {}
37
38 bool IsNonclientArea() const { return client_id == kNonclientAreaId; }
39 bool IsClientArea() const { return client_id == kClientAreaId; }
40
41 ServerWindow* window;
42 ClientSpecificId client_id;
43 std::unique_ptr<ui::Event> event;
44 Accelerator* accelerator;
45 };
46
47 class TestEventDispatcherDelegate : public EventDispatcherDelegate {
48 public:
49 // Delegate interface used by this class to release capture on event
50 // dispatcher.
51 class Delegate {
52 public:
53 virtual void ReleaseCapture() = 0;
54 };
55
56 explicit TestEventDispatcherDelegate(Delegate* delegate)
57 : delegate_(delegate),
58 focused_window_(nullptr),
59 lost_capture_window_(nullptr),
60 last_accelerator_(0) {}
61 ~TestEventDispatcherDelegate() override {}
62
63 ui::Event* last_event_target_not_found() {
64 return last_event_target_not_found_.get();
65 }
66
67 uint32_t GetAndClearLastAccelerator() {
68 uint32_t return_value = last_accelerator_;
69 last_accelerator_ = 0;
70 return return_value;
71 }
72
73 void set_root(ServerWindow* root) { root_ = root; }
74
75 // Returns the last dispatched event, or null if there are no more.
76 std::unique_ptr<DispatchedEventDetails>
77 GetAndAdvanceDispatchedEventDetails() {
78 if (dispatched_event_queue_.empty())
79 return nullptr;
80
81 std::unique_ptr<DispatchedEventDetails> details =
82 std::move(dispatched_event_queue_.front());
83 dispatched_event_queue_.pop();
84 return details;
85 }
86
87 ServerWindow* GetAndClearLastFocusedWindow() {
88 ServerWindow* result = focused_window_;
89 focused_window_ = nullptr;
90 return result;
91 }
92
93 bool has_queued_events() const { return !dispatched_event_queue_.empty(); }
94 ServerWindow* lost_capture_window() { return lost_capture_window_; }
95
96 // EventDispatcherDelegate:
97 void SetFocusedWindowFromEventDispatcher(ServerWindow* window) override {
98 focused_window_ = window;
99 }
100
101 private:
102 // EventDispatcherDelegate:
103 void OnAccelerator(uint32_t accelerator, const ui::Event& event) override {
104 EXPECT_EQ(0u, last_accelerator_);
105 last_accelerator_ = accelerator;
106 }
107 ServerWindow* GetFocusedWindowForEventDispatcher() override {
108 return focused_window_;
109 }
110 void SetNativeCapture(ServerWindow* window) override {}
111 void ReleaseNativeCapture() override {
112 if (delegate_)
113 delegate_->ReleaseCapture();
114 }
115 void OnServerWindowCaptureLost(ServerWindow* window) override {
116 lost_capture_window_ = window;
117 }
118 void OnMouseCursorLocationChanged(const gfx::Point& point) override {}
119 void DispatchInputEventToWindow(ServerWindow* target,
120 ClientSpecificId client_id,
121 const ui::Event& event,
122 Accelerator* accelerator) override {
123 std::unique_ptr<DispatchedEventDetails> details(new DispatchedEventDetails);
124 details->window = target;
125 details->client_id = client_id;
126 details->event = ui::Event::Clone(event);
127 details->accelerator = accelerator;
128 dispatched_event_queue_.push(std::move(details));
129 }
130 ClientSpecificId GetEventTargetClientId(const ServerWindow* window,
131 bool in_nonclient_area) override {
132 return in_nonclient_area ? kNonclientAreaId : kClientAreaId;
133 }
134 ServerWindow* GetRootWindowContaining(const gfx::Point& location) override {
135 return root_;
136 }
137 void OnEventTargetNotFound(const ui::Event& event) override {
138 last_event_target_not_found_ = ui::Event::Clone(event);
139 }
140
141 Delegate* delegate_;
142 ServerWindow* focused_window_;
143 ServerWindow* lost_capture_window_;
144 uint32_t last_accelerator_;
145 std::queue<std::unique_ptr<DispatchedEventDetails>> dispatched_event_queue_;
146 ServerWindow* root_ = nullptr;
147 std::unique_ptr<ui::Event> last_event_target_not_found_;
148
149 DISALLOW_COPY_AND_ASSIGN(TestEventDispatcherDelegate);
150 };
151
152 // Used by RunMouseEventTests(). Can identify up to two generated events. The
153 // first ServerWindow and two points identify the first event, the second
154 // ServerWindow and points identify the second event. If only one event is
155 // generated set the second window to null.
156 struct MouseEventTest {
157 ui::MouseEvent input_event;
158 ServerWindow* expected_target_window1;
159 gfx::Point expected_root_location1;
160 gfx::Point expected_location1;
161 ServerWindow* expected_target_window2;
162 gfx::Point expected_root_location2;
163 gfx::Point expected_location2;
164 };
165
166 // Verifies |details| matches the supplied ServerWindow and points.
167 void ExpectDispatchedEventDetailsMatches(const DispatchedEventDetails* details,
168 ServerWindow* target,
169 const gfx::Point& root_location,
170 const gfx::Point& location) {
171 if (!target) {
172 ASSERT_FALSE(details);
173 return;
174 }
175
176 ASSERT_EQ(target, details->window);
177 ASSERT_TRUE(details->event);
178 ASSERT_TRUE(details->event->IsLocatedEvent());
179 ASSERT_TRUE(details->IsClientArea());
180 ASSERT_EQ(root_location, details->event->AsLocatedEvent()->root_location());
181 ASSERT_EQ(location, details->event->AsLocatedEvent()->location());
182 }
183
184 void RunMouseEventTests(EventDispatcher* dispatcher,
185 TestEventDispatcherDelegate* dispatcher_delegate,
186 MouseEventTest* tests,
187 size_t test_count) {
188 for (size_t i = 0; i < test_count; ++i) {
189 const MouseEventTest& test = tests[i];
190 ASSERT_FALSE(dispatcher_delegate->has_queued_events())
191 << " unexpected queued events before running " << i;
192 if (test.input_event.IsMouseWheelEvent())
193 dispatcher->ProcessEvent(test.input_event);
194 else
195 dispatcher->ProcessEvent(ui::PointerEvent(test.input_event));
196
197 std::unique_ptr<DispatchedEventDetails> details =
198 dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
199 ASSERT_NO_FATAL_FAILURE(ExpectDispatchedEventDetailsMatches(
200 details.get(), test.expected_target_window1,
201 test.expected_root_location1, test.expected_location1))
202 << " details don't match " << i;
203 details = dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
204 ASSERT_NO_FATAL_FAILURE(ExpectDispatchedEventDetailsMatches(
205 details.get(), test.expected_target_window2,
206 test.expected_root_location2, test.expected_location2))
207 << " details2 don't match " << i;
208 ASSERT_FALSE(dispatcher_delegate->has_queued_events())
209 << " unexpected queued events after running " << i;
210 }
211 }
212
213 } // namespace
214
215 // Test fixture for EventDispatcher with friend access to verify the internal
216 // state. Setup creates a TestServerWindowDelegate, a visible root ServerWindow,
217 // a TestEventDispatcher and the EventDispatcher for testing.
218 class EventDispatcherTest : public testing::Test,
219 public TestEventDispatcherDelegate::Delegate {
220 public:
221 EventDispatcherTest() {}
222 ~EventDispatcherTest() override {}
223
224 ServerWindow* root_window() { return root_window_.get(); }
225 TestEventDispatcherDelegate* test_event_dispatcher_delegate() {
226 return test_event_dispatcher_delegate_.get();
227 }
228 EventDispatcher* event_dispatcher() { return event_dispatcher_.get(); }
229
230 bool AreAnyPointersDown() const;
231 // Deletes everything created during SetUp()
232 void ClearSetup();
233 std::unique_ptr<ServerWindow> CreateChildWindowWithParent(
234 const WindowId& id,
235 ServerWindow* parent);
236 // Creates a window which is a child of |root_window_|.
237 std::unique_ptr<ServerWindow> CreateChildWindow(const WindowId& id);
238 bool IsMouseButtonDown() const;
239 bool IsWindowPointerTarget(const ServerWindow* window) const;
240 int NumberPointerTargetsForWindow(ServerWindow* window) const;
241 ServerWindow* GetActiveSystemModalWindow() const;
242
243 protected:
244 // testing::Test:
245 void SetUp() override;
246
247 private:
248 // TestEventDispatcherDelegate::Delegate:
249 void ReleaseCapture() override {
250 event_dispatcher_->SetCaptureWindow(nullptr, kInvalidClientId);
251 }
252
253 std::unique_ptr<TestServerWindowDelegate> window_delegate_;
254 std::unique_ptr<ServerWindow> root_window_;
255 std::unique_ptr<TestEventDispatcherDelegate> test_event_dispatcher_delegate_;
256 std::unique_ptr<EventDispatcher> event_dispatcher_;
257
258 DISALLOW_COPY_AND_ASSIGN(EventDispatcherTest);
259 };
260
261 bool EventDispatcherTest::AreAnyPointersDown() const {
262 return EventDispatcherTestApi(event_dispatcher_.get()).AreAnyPointersDown();
263 }
264
265 void EventDispatcherTest::ClearSetup() {
266 window_delegate_.reset();
267 root_window_.reset();
268 test_event_dispatcher_delegate_.reset();
269 event_dispatcher_.reset();
270 }
271
272 std::unique_ptr<ServerWindow> EventDispatcherTest::CreateChildWindowWithParent(
273 const WindowId& id,
274 ServerWindow* parent) {
275 std::unique_ptr<ServerWindow> child(
276 new ServerWindow(window_delegate_.get(), id));
277 parent->Add(child.get());
278 child->SetVisible(true);
279 EnableHitTest(child.get());
280 return child;
281 }
282
283 std::unique_ptr<ServerWindow> EventDispatcherTest::CreateChildWindow(
284 const WindowId& id) {
285 return CreateChildWindowWithParent(id, root_window_.get());
286 }
287
288 bool EventDispatcherTest::IsMouseButtonDown() const {
289 return EventDispatcherTestApi(event_dispatcher_.get()).is_mouse_button_down();
290 }
291
292 bool EventDispatcherTest::IsWindowPointerTarget(
293 const ServerWindow* window) const {
294 return EventDispatcherTestApi(event_dispatcher_.get())
295 .IsWindowPointerTarget(window);
296 }
297
298 int EventDispatcherTest::NumberPointerTargetsForWindow(
299 ServerWindow* window) const {
300 return EventDispatcherTestApi(event_dispatcher_.get())
301 .NumberPointerTargetsForWindow(window);
302 }
303
304 ServerWindow* EventDispatcherTest::GetActiveSystemModalWindow() const {
305 ModalWindowController* mwc =
306 EventDispatcherTestApi(event_dispatcher_.get()).modal_window_controller();
307 return ModalWindowControllerTestApi(mwc).GetActiveSystemModalWindow();
308 }
309
310 void EventDispatcherTest::SetUp() {
311 testing::Test::SetUp();
312
313 window_delegate_.reset(new TestServerWindowDelegate());
314 root_window_.reset(new ServerWindow(window_delegate_.get(), WindowId(1, 2)));
315 window_delegate_->set_root_window(root_window_.get());
316 root_window_->SetVisible(true);
317
318 test_event_dispatcher_delegate_.reset(new TestEventDispatcherDelegate(this));
319 event_dispatcher_.reset(
320 new EventDispatcher(test_event_dispatcher_delegate_.get()));
321 test_event_dispatcher_delegate_->set_root(root_window_.get());
322 }
323
324 TEST_F(EventDispatcherTest, ProcessEvent) {
325 std::unique_ptr<ServerWindow> child = CreateChildWindow(WindowId(1, 3));
326
327 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
328 child->SetBounds(gfx::Rect(10, 10, 20, 20));
329
330 // Send event that is over child.
331 const ui::PointerEvent ui_event(ui::MouseEvent(
332 ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), gfx::Point(20, 25),
333 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
334 event_dispatcher()->ProcessEvent(ui_event);
335
336 std::unique_ptr<DispatchedEventDetails> details =
337 test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
338 ASSERT_TRUE(details);
339 ASSERT_EQ(child.get(), details->window);
340
341 ASSERT_TRUE(details->event);
342 ASSERT_TRUE(details->event->IsPointerEvent());
343
344 ui::PointerEvent* dispatched_event = details->event->AsPointerEvent();
345 EXPECT_EQ(gfx::Point(20, 25), dispatched_event->root_location());
346 EXPECT_EQ(gfx::Point(10, 15), dispatched_event->location());
347 }
348
349 TEST_F(EventDispatcherTest, ProcessEventNoTarget) {
350 // Send event without a target.
351 ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
352 event_dispatcher()->ProcessEvent(key);
353
354 // Event wasn't dispatched to a target.
355 std::unique_ptr<DispatchedEventDetails> details =
356 test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
357 EXPECT_FALSE(details);
358
359 // Delegate was informed that there wasn't a target.
360 ui::Event* event_out =
361 test_event_dispatcher_delegate()->last_event_target_not_found();
362 ASSERT_TRUE(event_out);
363 EXPECT_TRUE(event_out->IsKeyEvent());
364 EXPECT_EQ(ui::VKEY_A, event_out->AsKeyEvent()->key_code());
365 }
366
367 TEST_F(EventDispatcherTest, AcceleratorBasic) {
368 ClearSetup();
369 TestEventDispatcherDelegate event_dispatcher_delegate(nullptr);
370 EventDispatcher dispatcher(&event_dispatcher_delegate);
371
372 uint32_t accelerator_1 = 1;
373 mojom::EventMatcherPtr matcher = mus::CreateKeyMatcher(
374 ui::mojom::KeyboardCode::W, ui::mojom::kEventFlagControlDown);
375 EXPECT_TRUE(dispatcher.AddAccelerator(accelerator_1, std::move(matcher)));
376
377 uint32_t accelerator_2 = 2;
378 matcher = mus::CreateKeyMatcher(ui::mojom::KeyboardCode::N,
379 ui::mojom::kEventFlagNone);
380 EXPECT_TRUE(dispatcher.AddAccelerator(accelerator_2, std::move(matcher)));
381
382 // Attempting to add a new accelerator with the same id should fail.
383 matcher = mus::CreateKeyMatcher(ui::mojom::KeyboardCode::T,
384 ui::mojom::kEventFlagNone);
385 EXPECT_FALSE(dispatcher.AddAccelerator(accelerator_2, std::move(matcher)));
386
387 // Adding the accelerator with the same id should succeed once the existing
388 // accelerator is removed.
389 dispatcher.RemoveAccelerator(accelerator_2);
390 matcher = mus::CreateKeyMatcher(ui::mojom::KeyboardCode::T,
391 ui::mojom::kEventFlagNone);
392 EXPECT_TRUE(dispatcher.AddAccelerator(accelerator_2, std::move(matcher)));
393
394 // Attempting to add an accelerator with the same matcher should fail.
395 uint32_t accelerator_3 = 3;
396 matcher = mus::CreateKeyMatcher(ui::mojom::KeyboardCode::T,
397 ui::mojom::kEventFlagNone);
398 EXPECT_FALSE(dispatcher.AddAccelerator(accelerator_3, std::move(matcher)));
399
400 matcher = mus::CreateKeyMatcher(ui::mojom::KeyboardCode::T,
401 ui::mojom::kEventFlagControlDown);
402 EXPECT_TRUE(dispatcher.AddAccelerator(accelerator_3, std::move(matcher)));
403 }
404
405 TEST_F(EventDispatcherTest, EventMatching) {
406 TestEventDispatcherDelegate* event_dispatcher_delegate =
407 test_event_dispatcher_delegate();
408 EventDispatcher* dispatcher = event_dispatcher();
409
410 mojom::EventMatcherPtr matcher = mus::CreateKeyMatcher(
411 ui::mojom::KeyboardCode::W, ui::mojom::kEventFlagControlDown);
412 uint32_t accelerator_1 = 1;
413 dispatcher->AddAccelerator(accelerator_1, std::move(matcher));
414
415 ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN);
416 dispatcher->ProcessEvent(key);
417 EXPECT_EQ(accelerator_1,
418 event_dispatcher_delegate->GetAndClearLastAccelerator());
419
420 // EF_NUM_LOCK_ON should be ignored since CreateKeyMatcher defaults to
421 // ignoring.
422 key = ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_W,
423 ui::EF_CONTROL_DOWN | ui::EF_NUM_LOCK_ON);
424 dispatcher->ProcessEvent(key);
425 EXPECT_EQ(accelerator_1,
426 event_dispatcher_delegate->GetAndClearLastAccelerator());
427
428 key = ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_NONE);
429 dispatcher->ProcessEvent(key);
430 EXPECT_EQ(0u, event_dispatcher_delegate->GetAndClearLastAccelerator());
431
432 uint32_t accelerator_2 = 2;
433 matcher = mus::CreateKeyMatcher(ui::mojom::KeyboardCode::W,
434 ui::mojom::kEventFlagNone);
435 dispatcher->AddAccelerator(accelerator_2, std::move(matcher));
436 dispatcher->ProcessEvent(key);
437 EXPECT_EQ(accelerator_2,
438 event_dispatcher_delegate->GetAndClearLastAccelerator());
439
440 dispatcher->RemoveAccelerator(accelerator_2);
441 dispatcher->ProcessEvent(key);
442 EXPECT_EQ(0u, event_dispatcher_delegate->GetAndClearLastAccelerator());
443 }
444
445 // Tests that a post-target accelerator is not triggered by ProcessEvent.
446 TEST_F(EventDispatcherTest, PostTargetAccelerator) {
447 TestEventDispatcherDelegate* event_dispatcher_delegate =
448 test_event_dispatcher_delegate();
449 EventDispatcher* dispatcher = event_dispatcher();
450
451 mojom::EventMatcherPtr matcher = mus::CreateKeyMatcher(
452 ui::mojom::KeyboardCode::W, ui::mojom::kEventFlagControlDown);
453 matcher->accelerator_phase = ui::mojom::AcceleratorPhase::POST_TARGET;
454 uint32_t accelerator_1 = 1;
455 dispatcher->AddAccelerator(accelerator_1, std::move(matcher));
456
457 ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN);
458 // The post-target accelerator should be fired if there is no focused window.
459 dispatcher->ProcessEvent(key);
460 EXPECT_EQ(accelerator_1,
461 event_dispatcher_delegate->GetAndClearLastAccelerator());
462 std::unique_ptr<DispatchedEventDetails> details =
463 event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
464 EXPECT_FALSE(details);
465
466 // Set focused window for EventDispatcher dispatches key events.
467 std::unique_ptr<ServerWindow> child = CreateChildWindow(WindowId(1, 3));
468 event_dispatcher_delegate->SetFocusedWindowFromEventDispatcher(child.get());
469
470 // With a focused window the event should be dispatched.
471 dispatcher->ProcessEvent(key);
472 EXPECT_EQ(0u, event_dispatcher_delegate->GetAndClearLastAccelerator());
473 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
474 EXPECT_TRUE(details);
475 EXPECT_TRUE(details->accelerator);
476
477 base::WeakPtr<Accelerator> accelerator_weak_ptr =
478 details->accelerator->GetWeakPtr();
479 dispatcher->RemoveAccelerator(accelerator_1);
480 EXPECT_FALSE(accelerator_weak_ptr);
481
482 // Post deletion there should be no accelerator
483 dispatcher->ProcessEvent(key);
484 EXPECT_EQ(0u, event_dispatcher_delegate->GetAndClearLastAccelerator());
485 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
486 EXPECT_TRUE(details);
487 EXPECT_FALSE(details->accelerator);
488 }
489
490 TEST_F(EventDispatcherTest, Capture) {
491 ServerWindow* root = root_window();
492 std::unique_ptr<ServerWindow> child = CreateChildWindow(WindowId(1, 3));
493
494 root->SetBounds(gfx::Rect(0, 0, 100, 100));
495 child->SetBounds(gfx::Rect(10, 10, 20, 20));
496
497 MouseEventTest tests[] = {
498 // Send a mouse down event over child.
499 {ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(20, 25),
500 gfx::Point(20, 25), base::TimeTicks(),
501 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON),
502 child.get(), gfx::Point(20, 25), gfx::Point(10, 15), nullptr,
503 gfx::Point(), gfx::Point()},
504
505 // Capture should be activated. Let's send a mouse move outside the bounds
506 // of the child.
507 {ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(50, 50),
508 gfx::Point(50, 50), base::TimeTicks(),
509 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON),
510 child.get(), gfx::Point(50, 50), gfx::Point(40, 40), nullptr,
511 gfx::Point(), gfx::Point()},
512 // Release the mouse and verify that the mouse up event goes to the child.
513 {ui::MouseEvent(ui::ET_MOUSE_RELEASED, gfx::Point(50, 50),
514 gfx::Point(50, 50), base::TimeTicks(),
515 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON),
516 child.get(), gfx::Point(50, 50), gfx::Point(40, 40), nullptr,
517 gfx::Point(), gfx::Point()},
518
519 // A mouse move at (50, 50) should now go to the root window. As the
520 // move crosses between |child| and |root| |child| gets an exit, and
521 // |root| the move.
522 {ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(50, 50),
523 gfx::Point(50, 50), base::TimeTicks(),
524 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON),
525 child.get(), gfx::Point(50, 50), gfx::Point(40, 40), root,
526 gfx::Point(50, 50), gfx::Point(50, 50)},
527
528 };
529 RunMouseEventTests(event_dispatcher(), test_event_dispatcher_delegate(),
530 tests, arraysize(tests));
531 }
532
533 TEST_F(EventDispatcherTest, CaptureMultipleMouseButtons) {
534 std::unique_ptr<ServerWindow> child = CreateChildWindow(WindowId(1, 3));
535
536 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
537 child->SetBounds(gfx::Rect(10, 10, 20, 20));
538
539 MouseEventTest tests[] = {
540 // Send a mouse down event over child with a left mouse button
541 {ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(20, 25),
542 gfx::Point(20, 25), base::TimeTicks(),
543 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON),
544 child.get(), gfx::Point(20, 25), gfx::Point(10, 15), nullptr,
545 gfx::Point(), gfx::Point()},
546
547 // Capture should be activated. Let's send a mouse move outside the bounds
548 // of the child and press the right mouse button too.
549 {ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(50, 50),
550 gfx::Point(50, 50), base::TimeTicks(),
551 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON, 0),
552 child.get(), gfx::Point(50, 50), gfx::Point(40, 40), nullptr,
553 gfx::Point(), gfx::Point()},
554
555 // Release the left mouse button and verify that the mouse up event goes
556 // to the child.
557 {ui::MouseEvent(ui::ET_MOUSE_RELEASED, gfx::Point(50, 50),
558 gfx::Point(50, 50), base::TimeTicks(),
559 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON,
560 ui::EF_RIGHT_MOUSE_BUTTON),
561 child.get(), gfx::Point(50, 50), gfx::Point(40, 40), nullptr,
562 gfx::Point(), gfx::Point()},
563
564 // A mouse move at (50, 50) should still go to the child.
565 {ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(50, 50),
566 gfx::Point(50, 50), base::TimeTicks(),
567 ui::EF_LEFT_MOUSE_BUTTON, 0),
568 child.get(), gfx::Point(50, 50), gfx::Point(40, 40), nullptr,
569 gfx::Point(), gfx::Point()},
570
571 };
572 RunMouseEventTests(event_dispatcher(), test_event_dispatcher_delegate(),
573 tests, arraysize(tests));
574 }
575
576 TEST_F(EventDispatcherTest, ClientAreaGoesToOwner) {
577 std::unique_ptr<ServerWindow> child = CreateChildWindow(WindowId(1, 3));
578
579 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
580 child->SetBounds(gfx::Rect(10, 10, 20, 20));
581
582 child->SetClientArea(gfx::Insets(5, 5, 5, 5), std::vector<gfx::Rect>());
583
584 TestEventDispatcherDelegate* event_dispatcher_delegate =
585 test_event_dispatcher_delegate();
586 EventDispatcher* dispatcher = event_dispatcher();
587
588 // Start move loop by sending mouse event over non-client area.
589 const ui::PointerEvent press_event(ui::MouseEvent(
590 ui::ET_MOUSE_PRESSED, gfx::Point(12, 12), gfx::Point(12, 12),
591 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
592 dispatcher->ProcessEvent(press_event);
593
594 // Events should target child and be in the non-client area.
595 std::unique_ptr<DispatchedEventDetails> details =
596 event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
597 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
598 ASSERT_TRUE(details);
599 ASSERT_EQ(child.get(), details->window);
600 EXPECT_TRUE(details->IsNonclientArea());
601
602 // Move the mouse 5,6 pixels and target is the same.
603 const ui::PointerEvent move_event(
604 ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(17, 18), gfx::Point(17, 18),
605 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0));
606 dispatcher->ProcessEvent(move_event);
607
608 // Still same target.
609 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
610 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
611 ASSERT_EQ(child.get(), details->window);
612 EXPECT_TRUE(details->IsNonclientArea());
613
614 // Release the mouse.
615 const ui::PointerEvent release_event(ui::MouseEvent(
616 ui::ET_MOUSE_RELEASED, gfx::Point(17, 18), gfx::Point(17, 18),
617 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
618 dispatcher->ProcessEvent(release_event);
619
620 // The event should not have been dispatched to the delegate.
621 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
622 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
623 ASSERT_EQ(child.get(), details->window);
624 EXPECT_TRUE(details->IsNonclientArea());
625
626 // Press in the client area and verify target/client area. The non-client area
627 // should get an exit first.
628 const ui::PointerEvent press_event2(ui::MouseEvent(
629 ui::ET_MOUSE_PRESSED, gfx::Point(21, 22), gfx::Point(21, 22),
630 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
631 dispatcher->ProcessEvent(press_event2);
632 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
633 EXPECT_TRUE(event_dispatcher_delegate->has_queued_events());
634 ASSERT_EQ(child.get(), details->window);
635 EXPECT_TRUE(details->IsNonclientArea());
636 EXPECT_EQ(ui::ET_POINTER_EXITED, details->event->type());
637
638 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
639 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
640 ASSERT_EQ(child.get(), details->window);
641 EXPECT_TRUE(details->IsClientArea());
642 EXPECT_EQ(ui::ET_POINTER_DOWN, details->event->type());
643 }
644
645 TEST_F(EventDispatcherTest, AdditionalClientArea) {
646 std::unique_ptr<ServerWindow> child = CreateChildWindow(WindowId(1, 3));
647
648 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
649 child->SetBounds(gfx::Rect(10, 10, 20, 20));
650
651 std::vector<gfx::Rect> additional_client_areas;
652 additional_client_areas.push_back(gfx::Rect(18, 0, 2, 2));
653 child->SetClientArea(gfx::Insets(5, 5, 5, 5), additional_client_areas);
654
655 TestEventDispatcherDelegate* event_dispatcher_delegate =
656 test_event_dispatcher_delegate();
657 // Press in the additional client area, it should go to the child.
658 const ui::PointerEvent press_event(ui::MouseEvent(
659 ui::ET_MOUSE_PRESSED, gfx::Point(28, 11), gfx::Point(28, 11),
660 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
661 event_dispatcher()->ProcessEvent(press_event);
662
663 // Events should target child and be in the client area.
664 std::unique_ptr<DispatchedEventDetails> details =
665 event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
666 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
667 ASSERT_EQ(child.get(), details->window);
668 EXPECT_TRUE(details->IsClientArea());
669 }
670
671 TEST_F(EventDispatcherTest, HitTestMask) {
672 std::unique_ptr<ServerWindow> child = CreateChildWindow(WindowId(1, 3));
673
674 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
675 child->SetBounds(gfx::Rect(10, 10, 20, 20));
676 child->SetHitTestMask(gfx::Rect(2, 2, 16, 16));
677
678 // Move in the masked area.
679 const ui::PointerEvent move1(ui::MouseEvent(
680 ui::ET_MOUSE_MOVED, gfx::Point(11, 11), gfx::Point(11, 11),
681 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0));
682 event_dispatcher()->ProcessEvent(move1);
683
684 // Event went through the child window and hit the root.
685 std::unique_ptr<DispatchedEventDetails> details1 =
686 test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
687 EXPECT_EQ(root_window(), details1->window);
688 EXPECT_TRUE(details1->IsClientArea());
689
690 child->ClearHitTestMask();
691
692 // Move right in the same part of the window.
693 const ui::PointerEvent move2(ui::MouseEvent(
694 ui::ET_MOUSE_MOVED, gfx::Point(11, 12), gfx::Point(11, 12),
695 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0));
696 event_dispatcher()->ProcessEvent(move2);
697
698 // Mouse exits the root.
699 std::unique_ptr<DispatchedEventDetails> details2 =
700 test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
701 EXPECT_EQ(ui::ET_POINTER_EXITED, details2->event->type());
702
703 // Mouse hits the child.
704 std::unique_ptr<DispatchedEventDetails> details3 =
705 test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
706 EXPECT_EQ(child.get(), details3->window);
707 EXPECT_TRUE(details3->IsClientArea());
708 }
709
710 TEST_F(EventDispatcherTest, DontFocusOnSecondDown) {
711 std::unique_ptr<ServerWindow> child1 = CreateChildWindow(WindowId(1, 3));
712 std::unique_ptr<ServerWindow> child2 = CreateChildWindow(WindowId(1, 4));
713
714 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
715 child1->SetBounds(gfx::Rect(10, 10, 20, 20));
716 child2->SetBounds(gfx::Rect(50, 51, 11, 12));
717
718 TestEventDispatcherDelegate* event_dispatcher_delegate =
719 test_event_dispatcher_delegate();
720 EventDispatcher* dispatcher = event_dispatcher();
721
722 // Press on child1. First press event should change focus.
723 const ui::PointerEvent press_event(ui::MouseEvent(
724 ui::ET_MOUSE_PRESSED, gfx::Point(12, 12), gfx::Point(12, 12),
725 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
726 dispatcher->ProcessEvent(press_event);
727 std::unique_ptr<DispatchedEventDetails> details =
728 event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
729 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
730 EXPECT_EQ(child1.get(), details->window);
731 EXPECT_EQ(child1.get(),
732 event_dispatcher_delegate->GetAndClearLastFocusedWindow());
733
734 // Press (with a different pointer id) on child2. Event should go to child2,
735 // but focus should not change.
736 const ui::PointerEvent touch_event(ui::TouchEvent(
737 ui::ET_TOUCH_PRESSED, gfx::Point(53, 54), 2, base::TimeTicks()));
738 dispatcher->ProcessEvent(touch_event);
739 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
740 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
741 EXPECT_EQ(child2.get(), details->window);
742 EXPECT_EQ(nullptr, event_dispatcher_delegate->GetAndClearLastFocusedWindow());
743 }
744
745 TEST_F(EventDispatcherTest, TwoPointersActive) {
746 std::unique_ptr<ServerWindow> child1 = CreateChildWindow(WindowId(1, 3));
747 std::unique_ptr<ServerWindow> child2 = CreateChildWindow(WindowId(1, 4));
748
749 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
750 child1->SetBounds(gfx::Rect(10, 10, 20, 20));
751 child2->SetBounds(gfx::Rect(50, 51, 11, 12));
752
753 TestEventDispatcherDelegate* event_dispatcher_delegate =
754 test_event_dispatcher_delegate();
755 EventDispatcher* dispatcher = event_dispatcher();
756
757 // Press on child1.
758 const ui::PointerEvent touch_event1(ui::TouchEvent(
759 ui::ET_TOUCH_PRESSED, gfx::Point(12, 13), 1, base::TimeTicks()));
760 dispatcher->ProcessEvent(touch_event1);
761 std::unique_ptr<DispatchedEventDetails> details =
762 event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
763 EXPECT_EQ(child1.get(), details->window);
764
765 // Drag over child2, child1 should get the drag.
766 const ui::PointerEvent drag_event1(ui::TouchEvent(
767 ui::ET_TOUCH_MOVED, gfx::Point(53, 54), 1, base::TimeTicks()));
768 dispatcher->ProcessEvent(drag_event1);
769 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
770 EXPECT_EQ(child1.get(), details->window);
771
772 // Press on child2 with a different touch id.
773 const ui::PointerEvent touch_event2(ui::TouchEvent(
774 ui::ET_TOUCH_PRESSED, gfx::Point(54, 55), 2, base::TimeTicks()));
775 dispatcher->ProcessEvent(touch_event2);
776 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
777 EXPECT_EQ(child2.get(), details->window);
778
779 // Drag over child1 with id 2, child2 should continue to get the drag.
780 const ui::PointerEvent drag_event2(ui::TouchEvent(
781 ui::ET_TOUCH_MOVED, gfx::Point(13, 14), 2, base::TimeTicks()));
782 dispatcher->ProcessEvent(drag_event2);
783 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
784 EXPECT_EQ(child2.get(), details->window);
785
786 // Drag again with id 1, child1 should continue to get it.
787 dispatcher->ProcessEvent(drag_event1);
788 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
789 EXPECT_EQ(child1.get(), details->window);
790
791 // Release touch id 1, and click on 2. 2 should get it.
792 const ui::PointerEvent touch_release(ui::TouchEvent(
793 ui::ET_TOUCH_RELEASED, gfx::Point(54, 55), 1, base::TimeTicks()));
794 dispatcher->ProcessEvent(touch_release);
795 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
796 EXPECT_EQ(child1.get(), details->window);
797 const ui::PointerEvent touch_event3(ui::TouchEvent(
798 ui::ET_TOUCH_PRESSED, gfx::Point(54, 55), 2, base::TimeTicks()));
799 dispatcher->ProcessEvent(touch_event3);
800 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
801 EXPECT_EQ(child2.get(), details->window);
802 }
803
804 TEST_F(EventDispatcherTest, DestroyWindowWhileGettingEvents) {
805 std::unique_ptr<ServerWindow> child = CreateChildWindow(WindowId(1, 3));
806
807 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
808 child->SetBounds(gfx::Rect(10, 10, 20, 20));
809
810 TestEventDispatcherDelegate* event_dispatcher_delegate =
811 test_event_dispatcher_delegate();
812 EventDispatcher* dispatcher = event_dispatcher();
813
814 // Press on child.
815 const ui::PointerEvent touch_event1(ui::TouchEvent(
816 ui::ET_TOUCH_PRESSED, gfx::Point(12, 13), 1, base::TimeTicks()));
817 dispatcher->ProcessEvent(touch_event1);
818 std::unique_ptr<DispatchedEventDetails> details =
819 event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
820 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
821 EXPECT_EQ(child.get(), details->window);
822
823 // Delete child, and continue the drag. Event should not be dispatched.
824 child.reset();
825
826 const ui::PointerEvent drag_event1(ui::TouchEvent(
827 ui::ET_TOUCH_MOVED, gfx::Point(53, 54), 1, base::TimeTicks()));
828 dispatcher->ProcessEvent(drag_event1);
829 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
830 EXPECT_EQ(nullptr, details.get());
831 }
832
833 TEST_F(EventDispatcherTest, MouseInExtendedHitTestRegion) {
834 ServerWindow* root = root_window();
835 std::unique_ptr<ServerWindow> child = CreateChildWindow(WindowId(1, 3));
836
837 root->SetBounds(gfx::Rect(0, 0, 100, 100));
838 child->SetBounds(gfx::Rect(10, 10, 20, 20));
839
840 TestEventDispatcherDelegate* event_dispatcher_delegate =
841 test_event_dispatcher_delegate();
842 EventDispatcher* dispatcher = event_dispatcher();
843
844 // Send event that is not over child.
845 const ui::PointerEvent ui_event(ui::MouseEvent(
846 ui::ET_MOUSE_PRESSED, gfx::Point(8, 9), gfx::Point(8, 9),
847 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
848 dispatcher->ProcessEvent(ui_event);
849 std::unique_ptr<DispatchedEventDetails> details =
850 event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
851 ASSERT_EQ(root, details->window);
852
853 // Release the mouse.
854 const ui::PointerEvent release_event(ui::MouseEvent(
855 ui::ET_MOUSE_RELEASED, gfx::Point(8, 9), gfx::Point(8, 9),
856 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
857 dispatcher->ProcessEvent(release_event);
858 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
859 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
860 ASSERT_EQ(root, details->window);
861 EXPECT_TRUE(details->IsClientArea());
862
863 // Change the extended hit test region and send event in extended hit test
864 // region. Should result in exit for root, followed by press for child.
865 child->set_extended_hit_test_region(gfx::Insets(5, 5, 5, 5));
866 dispatcher->ProcessEvent(ui_event);
867 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
868 EXPECT_EQ(root, details->window);
869 EXPECT_EQ(ui::ET_POINTER_EXITED, details->event->type());
870 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
871 ASSERT_TRUE(details);
872
873 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
874 EXPECT_TRUE(details->IsNonclientArea());
875 ASSERT_EQ(child.get(), details->window);
876 EXPECT_EQ(ui::ET_POINTER_DOWN, details->event->type());
877 ASSERT_TRUE(details->event.get());
878 ASSERT_TRUE(details->event->IsPointerEvent());
879 EXPECT_EQ(gfx::Point(-2, -1), details->event->AsPointerEvent()->location());
880 }
881
882 TEST_F(EventDispatcherTest, WheelWhileDown) {
883 std::unique_ptr<ServerWindow> child1 = CreateChildWindow(WindowId(1, 3));
884 std::unique_ptr<ServerWindow> child2 = CreateChildWindow(WindowId(1, 4));
885
886 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
887 child1->SetBounds(gfx::Rect(10, 10, 20, 20));
888 child2->SetBounds(gfx::Rect(50, 51, 11, 12));
889
890 MouseEventTest tests[] = {
891 // Send a mouse down event over child1.
892 {ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(15, 15),
893 gfx::Point(15, 15), base::TimeTicks(),
894 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON),
895 child1.get(), gfx::Point(15, 15), gfx::Point(5, 5), nullptr,
896 gfx::Point(), gfx::Point()},
897 // Send mouse wheel over child2, should go to child1 as it has capture.
898 {ui::MouseWheelEvent(gfx::Vector2d(1, 0), gfx::Point(53, 54),
899 gfx::Point(53, 54), base::TimeTicks(), ui::EF_NONE,
900 ui::EF_NONE),
901 child1.get(), gfx::Point(53, 54), gfx::Point(43, 44), nullptr,
902 gfx::Point(), gfx::Point()},
903 };
904 RunMouseEventTests(event_dispatcher(), test_event_dispatcher_delegate(),
905 tests, arraysize(tests));
906 }
907
908 // Tests that when explicit capture has been set that all events go to the
909 // designated window, and that when capture is cleared, events find the
910 // appropriate target window.
911 TEST_F(EventDispatcherTest, SetExplicitCapture) {
912 ServerWindow* root = root_window();
913 std::unique_ptr<ServerWindow> child = CreateChildWindow(WindowId(1, 3));
914
915 root->SetBounds(gfx::Rect(0, 0, 100, 100));
916 child->SetBounds(gfx::Rect(10, 10, 20, 20));
917
918 TestEventDispatcherDelegate* event_dispatcher_delegate =
919 test_event_dispatcher_delegate();
920 EventDispatcher* dispatcher = event_dispatcher();
921
922 {
923 // Send all pointer events to the child.
924 dispatcher->SetCaptureWindow(child.get(), kClientAreaId);
925
926 // The mouse press should go to the child even though its outside its
927 // bounds.
928 const ui::PointerEvent left_press_event(ui::MouseEvent(
929 ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), gfx::Point(5, 5),
930 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
931 dispatcher->ProcessEvent(left_press_event);
932
933 // Events should target child.
934 std::unique_ptr<DispatchedEventDetails> details =
935 event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
936
937 ASSERT_TRUE(details);
938 ASSERT_EQ(child.get(), details->window);
939 EXPECT_TRUE(details->IsClientArea());
940 EXPECT_TRUE(IsMouseButtonDown());
941
942 // The mouse down state should update while capture is set.
943 const ui::PointerEvent right_press_event(ui::MouseEvent(
944 ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), gfx::Point(5, 5),
945 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON,
946 ui::EF_RIGHT_MOUSE_BUTTON));
947 dispatcher->ProcessEvent(right_press_event);
948 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
949 EXPECT_TRUE(IsMouseButtonDown());
950
951 // One button released should not clear mouse down
952 const ui::PointerEvent left_release_event(ui::MouseEvent(
953 ui::ET_MOUSE_RELEASED, gfx::Point(5, 5), gfx::Point(5, 5),
954 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON,
955 ui::EF_LEFT_MOUSE_BUTTON));
956 dispatcher->ProcessEvent(left_release_event);
957 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
958 EXPECT_TRUE(IsMouseButtonDown());
959
960 // Touch Event while mouse is down should not affect state.
961 const ui::PointerEvent touch_event(ui::TouchEvent(
962 ui::ET_TOUCH_PRESSED, gfx::Point(15, 15), 2, base::TimeTicks()));
963 dispatcher->ProcessEvent(touch_event);
964 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
965 EXPECT_TRUE(IsMouseButtonDown());
966
967 // Move event should not affect down
968 const ui::PointerEvent move_event(
969 ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(15, 5), gfx::Point(15, 5),
970 base::TimeTicks(), ui::EF_RIGHT_MOUSE_BUTTON,
971 ui::EF_RIGHT_MOUSE_BUTTON));
972 dispatcher->ProcessEvent(move_event);
973 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
974 EXPECT_TRUE(IsMouseButtonDown());
975
976 // All mouse buttons up should clear mouse down.
977 const ui::PointerEvent right_release_event(
978 ui::MouseEvent(ui::ET_MOUSE_RELEASED, gfx::Point(5, 5),
979 gfx::Point(5, 5), base::TimeTicks(),
980 ui::EF_RIGHT_MOUSE_BUTTON, ui::EF_RIGHT_MOUSE_BUTTON));
981 dispatcher->ProcessEvent(right_release_event);
982 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
983 EXPECT_FALSE(IsMouseButtonDown());
984 }
985
986 {
987 // Releasing capture and sending the same event will go to the root.
988 dispatcher->SetCaptureWindow(nullptr, kClientAreaId);
989 const ui::PointerEvent press_event(ui::MouseEvent(
990 ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), gfx::Point(5, 5),
991 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
992 dispatcher->ProcessEvent(press_event);
993
994 // Events should target the root.
995 std::unique_ptr<DispatchedEventDetails> details =
996 event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
997
998 ASSERT_TRUE(details);
999 ASSERT_EQ(root, details->window);
1000 }
1001 }
1002
1003 // This test verifies that explicit capture overrides and resets implicit
1004 // capture.
1005 TEST_F(EventDispatcherTest, ExplicitCaptureOverridesImplicitCapture) {
1006 ServerWindow* root = root_window();
1007 std::unique_ptr<ServerWindow> child = CreateChildWindow(WindowId(1, 3));
1008
1009 root->SetBounds(gfx::Rect(0, 0, 100, 100));
1010 child->SetBounds(gfx::Rect(10, 10, 20, 20));
1011
1012 TestEventDispatcherDelegate* event_dispatcher_delegate =
1013 test_event_dispatcher_delegate();
1014 EventDispatcher* dispatcher = event_dispatcher();
1015
1016 // Run some implicit capture tests.
1017 MouseEventTest tests[] = {
1018 // Send a mouse down event over child with a left mouse button
1019 {ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(20, 25),
1020 gfx::Point(20, 25), base::TimeTicks(),
1021 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON),
1022 child.get(), gfx::Point(20, 25), gfx::Point(10, 15)},
1023 // Capture should be activated. Let's send a mouse move outside the bounds
1024 // of the child and press the right mouse button too.
1025 {ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(50, 50),
1026 gfx::Point(50, 50), base::TimeTicks(),
1027 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON, 0),
1028 child.get(), gfx::Point(50, 50), gfx::Point(40, 40)},
1029 // Release the left mouse button and verify that the mouse up event goes
1030 // to the child.
1031 {ui::MouseEvent(ui::ET_MOUSE_RELEASED, gfx::Point(50, 50),
1032 gfx::Point(50, 50), base::TimeTicks(),
1033 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON,
1034 ui::EF_RIGHT_MOUSE_BUTTON),
1035 child.get(), gfx::Point(50, 50), gfx::Point(40, 40)},
1036 // A mouse move at (50, 50) should still go to the child.
1037 {ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(50, 50),
1038 gfx::Point(50, 50), base::TimeTicks(),
1039 ui::EF_LEFT_MOUSE_BUTTON, 0),
1040 child.get(), gfx::Point(50, 50), gfx::Point(40, 40)},
1041
1042 };
1043 RunMouseEventTests(dispatcher, event_dispatcher_delegate, tests,
1044 arraysize(tests));
1045
1046 // Add a second pointer target to the child.
1047 {
1048 const ui::PointerEvent touch_event(ui::TouchEvent(
1049 ui::ET_TOUCH_PRESSED, gfx::Point(12, 13), 1, base::TimeTicks()));
1050 dispatcher->ProcessEvent(touch_event);
1051 }
1052
1053 std::unique_ptr<DispatchedEventDetails> details =
1054 event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
1055 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
1056 EXPECT_EQ(child.get(), details->window);
1057
1058 // Verify that no window has explicit capture and hence we did indeed do
1059 // implicit capture.
1060 ASSERT_EQ(nullptr, dispatcher->capture_window());
1061
1062 // Give the root window explicit capture and verify input events over the
1063 // child go to the root instead.
1064 dispatcher->SetCaptureWindow(root, kNonclientAreaId);
1065
1066 // The implicit target should receive a cancel event for each pointer target.
1067 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
1068 ASSERT_TRUE(details);
1069 EXPECT_TRUE(event_dispatcher_delegate->has_queued_events());
1070 EXPECT_EQ(child.get(), details->window);
1071 EXPECT_EQ(ui::ET_POINTER_CANCELLED, details->event->type());
1072
1073 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
1074 ASSERT_TRUE(details);
1075 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
1076 EXPECT_EQ(child.get(), details->window);
1077 EXPECT_EQ(ui::ET_POINTER_EXITED, details->event->type());
1078
1079 const ui::PointerEvent press_event(ui::MouseEvent(
1080 ui::ET_MOUSE_PRESSED, gfx::Point(15, 15), gfx::Point(15, 15),
1081 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
1082 dispatcher->ProcessEvent(press_event);
1083
1084 // Events should target the root.
1085 details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
1086 ASSERT_TRUE(details);
1087 ASSERT_EQ(root, details->window);
1088 ASSERT_TRUE(details->IsNonclientArea());
1089 }
1090
1091 // Tests that setting capture does delete active pointer targets for the capture
1092 // window.
1093 TEST_F(EventDispatcherTest, CaptureUpdatesActivePointerTargets) {
1094 ServerWindow* root = root_window();
1095 root->SetBounds(gfx::Rect(0, 0, 100, 100));
1096
1097 EventDispatcher* dispatcher = event_dispatcher();
1098 {
1099 const ui::PointerEvent press_event(ui::MouseEvent(
1100 ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), gfx::Point(5, 5),
1101 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
1102 dispatcher->ProcessEvent(press_event);
1103
1104 std::unique_ptr<DispatchedEventDetails> details =
1105 test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
1106 ASSERT_TRUE(details);
1107 ASSERT_EQ(root, details->window);
1108 }
1109 {
1110 const ui::PointerEvent touch_event(ui::TouchEvent(
1111 ui::ET_TOUCH_PRESSED, gfx::Point(12, 13), 1, base::TimeTicks()));
1112 dispatcher->ProcessEvent(touch_event);
1113 }
1114
1115 ASSERT_TRUE(AreAnyPointersDown());
1116 ASSERT_TRUE(IsWindowPointerTarget(root));
1117 EXPECT_EQ(2, NumberPointerTargetsForWindow(root));
1118
1119 // Setting the capture should clear the implicit pointers for the specified
1120 // window.
1121 dispatcher->SetCaptureWindow(root, kNonclientAreaId);
1122 EXPECT_FALSE(AreAnyPointersDown());
1123 EXPECT_FALSE(IsWindowPointerTarget(root));
1124 }
1125
1126 // Tests that when explicit capture is changed, that the previous window with
1127 // capture is no longer being observed.
1128 TEST_F(EventDispatcherTest, UpdatingCaptureStopsObservingPreviousCapture) {
1129 std::unique_ptr<ServerWindow> child1 = CreateChildWindow(WindowId(1, 3));
1130 std::unique_ptr<ServerWindow> child2 = CreateChildWindow(WindowId(1, 4));
1131
1132 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
1133 child1->SetBounds(gfx::Rect(10, 10, 20, 20));
1134 child2->SetBounds(gfx::Rect(50, 51, 11, 12));
1135
1136 EventDispatcher* dispatcher = event_dispatcher();
1137 ASSERT_FALSE(AreAnyPointersDown());
1138 ASSERT_FALSE(IsWindowPointerTarget(child1.get()));
1139 ASSERT_FALSE(IsWindowPointerTarget(child2.get()));
1140 dispatcher->SetCaptureWindow(child1.get(), kClientAreaId);
1141 dispatcher->SetCaptureWindow(child2.get(), kClientAreaId);
1142 EXPECT_EQ(child1.get(),
1143 test_event_dispatcher_delegate()->lost_capture_window());
1144
1145 // If observing does not stop during the capture update this crashes.
1146 child1->AddObserver(dispatcher);
1147 }
1148
1149 // Tests that destroying a window with explicit capture clears the capture
1150 // state.
1151 TEST_F(EventDispatcherTest, DestroyingCaptureWindowRemovesExplicitCapture) {
1152 std::unique_ptr<ServerWindow> child = CreateChildWindow(WindowId(1, 3));
1153 child->SetBounds(gfx::Rect(10, 10, 20, 20));
1154
1155 EventDispatcher* dispatcher = event_dispatcher();
1156 dispatcher->SetCaptureWindow(child.get(), kClientAreaId);
1157 EXPECT_EQ(child.get(), dispatcher->capture_window());
1158
1159 ServerWindow* lost_capture_window = child.get();
1160 child.reset();
1161 EXPECT_EQ(nullptr, dispatcher->capture_window());
1162 EXPECT_EQ(lost_capture_window,
1163 test_event_dispatcher_delegate()->lost_capture_window());
1164 }
1165
1166 // Tests that when |client_id| is set for a window performing capture, that this
1167 // preference is used regardless of whether an event targets the client region.
1168 TEST_F(EventDispatcherTest, CaptureInNonClientAreaOverridesActualPoint) {
1169 ServerWindow* root = root_window();
1170 root->SetBounds(gfx::Rect(0, 0, 100, 100));
1171
1172 root->SetClientArea(gfx::Insets(5, 5, 5, 5), std::vector<gfx::Rect>());
1173 EventDispatcher* dispatcher = event_dispatcher();
1174 dispatcher->SetCaptureWindow(root, kNonclientAreaId);
1175
1176 TestEventDispatcherDelegate* event_dispatcher_delegate =
1177 test_event_dispatcher_delegate();
1178 // Press in the client area, it should be marked as non client.
1179 const ui::PointerEvent press_event(ui::MouseEvent(
1180 ui::ET_MOUSE_PRESSED, gfx::Point(6, 6), gfx::Point(6, 6),
1181 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
1182 event_dispatcher()->ProcessEvent(press_event);
1183
1184 // Events should target child and be in the client area.
1185 std::unique_ptr<DispatchedEventDetails> details =
1186 event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
1187 EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
1188 ASSERT_EQ(root, details->window);
1189 EXPECT_TRUE(details->IsNonclientArea());
1190 }
1191
1192 TEST_F(EventDispatcherTest, ProcessPointerEvents) {
1193 std::unique_ptr<ServerWindow> child = CreateChildWindow(WindowId(1, 3));
1194
1195 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
1196 child->SetBounds(gfx::Rect(10, 10, 20, 20));
1197
1198 {
1199 const ui::PointerEvent pointer_event(ui::MouseEvent(
1200 ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), gfx::Point(20, 25),
1201 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
1202 event_dispatcher()->ProcessEvent(pointer_event);
1203
1204 std::unique_ptr<DispatchedEventDetails> details =
1205 test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
1206 ASSERT_TRUE(details);
1207 ASSERT_EQ(child.get(), details->window);
1208
1209 ASSERT_TRUE(details->event);
1210 ASSERT_TRUE(details->event->IsPointerEvent());
1211
1212 ui::PointerEvent* dispatched_event = details->event->AsPointerEvent();
1213 EXPECT_EQ(gfx::Point(20, 25), dispatched_event->root_location());
1214 EXPECT_EQ(gfx::Point(10, 15), dispatched_event->location());
1215 }
1216
1217 {
1218 const int touch_id = 3;
1219 const ui::PointerEvent pointer_event(
1220 ui::TouchEvent(ui::ET_TOUCH_RELEASED, gfx::Point(25, 20), touch_id,
1221 base::TimeTicks()));
1222 event_dispatcher()->ProcessEvent(pointer_event);
1223
1224 std::unique_ptr<DispatchedEventDetails> details =
1225 test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
1226 ASSERT_TRUE(details);
1227 ASSERT_EQ(child.get(), details->window);
1228
1229 ASSERT_TRUE(details->event);
1230 ASSERT_TRUE(details->event->IsPointerEvent());
1231
1232 ui::PointerEvent* dispatched_event = details->event->AsPointerEvent();
1233 EXPECT_EQ(gfx::Point(25, 20), dispatched_event->root_location());
1234 EXPECT_EQ(gfx::Point(15, 10), dispatched_event->location());
1235 EXPECT_EQ(touch_id, dispatched_event->pointer_id());
1236 }
1237 }
1238
1239 TEST_F(EventDispatcherTest, ResetClearsPointerDown) {
1240 std::unique_ptr<ServerWindow> child = CreateChildWindow(WindowId(1, 3));
1241
1242 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
1243 child->SetBounds(gfx::Rect(10, 10, 20, 20));
1244
1245 // Send event that is over child.
1246 const ui::PointerEvent ui_event(ui::MouseEvent(
1247 ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), gfx::Point(20, 25),
1248 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
1249 event_dispatcher()->ProcessEvent(ui_event);
1250
1251 std::unique_ptr<DispatchedEventDetails> details =
1252 test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
1253 ASSERT_TRUE(details);
1254 ASSERT_EQ(child.get(), details->window);
1255
1256 EXPECT_TRUE(AreAnyPointersDown());
1257
1258 event_dispatcher()->Reset();
1259 EXPECT_FALSE(test_event_dispatcher_delegate()->has_queued_events());
1260 EXPECT_FALSE(AreAnyPointersDown());
1261 }
1262
1263 TEST_F(EventDispatcherTest, ResetClearsCapture) {
1264 ServerWindow* root = root_window();
1265 root->SetBounds(gfx::Rect(0, 0, 100, 100));
1266
1267 root->SetClientArea(gfx::Insets(5, 5, 5, 5), std::vector<gfx::Rect>());
1268 EventDispatcher* dispatcher = event_dispatcher();
1269 dispatcher->SetCaptureWindow(root, kNonclientAreaId);
1270
1271 event_dispatcher()->Reset();
1272 EXPECT_FALSE(test_event_dispatcher_delegate()->has_queued_events());
1273 EXPECT_EQ(nullptr, event_dispatcher()->capture_window());
1274 }
1275
1276 // Tests that events on a modal parent target the modal child.
1277 TEST_F(EventDispatcherTest, ModalWindowEventOnModalParent) {
1278 std::unique_ptr<ServerWindow> w1 = CreateChildWindow(WindowId(1, 3));
1279 std::unique_ptr<ServerWindow> w2 = CreateChildWindow(WindowId(1, 5));
1280
1281 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
1282 w1->SetBounds(gfx::Rect(10, 10, 30, 30));
1283 w2->SetBounds(gfx::Rect(50, 10, 10, 10));
1284
1285 w1->AddTransientWindow(w2.get());
1286 w2->SetModal();
1287
1288 // Send event that is over |w1|.
1289 const ui::PointerEvent mouse_pressed(ui::MouseEvent(
1290 ui::ET_MOUSE_PRESSED, gfx::Point(15, 15), gfx::Point(15, 15),
1291 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
1292 event_dispatcher()->ProcessEvent(mouse_pressed);
1293
1294 std::unique_ptr<DispatchedEventDetails> details =
1295 test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
1296 ASSERT_TRUE(details);
1297 EXPECT_EQ(w2.get(), details->window);
1298 EXPECT_TRUE(details->IsNonclientArea());
1299
1300 ASSERT_TRUE(details->event);
1301 ASSERT_TRUE(details->event->IsPointerEvent());
1302
1303 ui::PointerEvent* dispatched_event = details->event->AsPointerEvent();
1304 EXPECT_EQ(gfx::Point(15, 15), dispatched_event->root_location());
1305 EXPECT_EQ(gfx::Point(-35, 5), dispatched_event->location());
1306 }
1307
1308 // Tests that events on a modal child target the modal child itself.
1309 TEST_F(EventDispatcherTest, ModalWindowEventOnModalChild) {
1310 std::unique_ptr<ServerWindow> w1 = CreateChildWindow(WindowId(1, 3));
1311 std::unique_ptr<ServerWindow> w2 = CreateChildWindow(WindowId(1, 5));
1312
1313 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
1314 w1->SetBounds(gfx::Rect(10, 10, 30, 30));
1315 w2->SetBounds(gfx::Rect(50, 10, 10, 10));
1316
1317 w1->AddTransientWindow(w2.get());
1318 w2->SetModal();
1319
1320 // Send event that is over |w2|.
1321 const ui::PointerEvent mouse_pressed(ui::MouseEvent(
1322 ui::ET_MOUSE_PRESSED, gfx::Point(55, 15), gfx::Point(55, 15),
1323 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
1324 event_dispatcher()->ProcessEvent(mouse_pressed);
1325
1326 std::unique_ptr<DispatchedEventDetails> details =
1327 test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
1328 ASSERT_TRUE(details);
1329 EXPECT_EQ(w2.get(), details->window);
1330 EXPECT_TRUE(details->IsClientArea());
1331
1332 ASSERT_TRUE(details->event);
1333 ASSERT_TRUE(details->event->IsPointerEvent());
1334
1335 ui::PointerEvent* dispatched_event = details->event->AsPointerEvent();
1336 EXPECT_EQ(gfx::Point(55, 15), dispatched_event->root_location());
1337 EXPECT_EQ(gfx::Point(5, 5), dispatched_event->location());
1338 }
1339
1340 // Tests that events on an unrelated window are not affected by the modal
1341 // window.
1342 TEST_F(EventDispatcherTest, ModalWindowEventOnUnrelatedWindow) {
1343 std::unique_ptr<ServerWindow> w1 = CreateChildWindow(WindowId(1, 3));
1344 std::unique_ptr<ServerWindow> w2 = CreateChildWindow(WindowId(1, 5));
1345 std::unique_ptr<ServerWindow> w3 = CreateChildWindow(WindowId(1, 6));
1346
1347 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
1348 w1->SetBounds(gfx::Rect(10, 10, 30, 30));
1349 w2->SetBounds(gfx::Rect(50, 10, 10, 10));
1350 w3->SetBounds(gfx::Rect(70, 10, 10, 10));
1351
1352 w1->AddTransientWindow(w2.get());
1353 w2->SetModal();
1354
1355 // Send event that is over |w3|.
1356 const ui::PointerEvent mouse_pressed(ui::MouseEvent(
1357 ui::ET_MOUSE_PRESSED, gfx::Point(75, 15), gfx::Point(75, 15),
1358 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
1359 event_dispatcher()->ProcessEvent(mouse_pressed);
1360
1361 std::unique_ptr<DispatchedEventDetails> details =
1362 test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
1363 ASSERT_TRUE(details);
1364 EXPECT_EQ(w3.get(), details->window);
1365 EXPECT_TRUE(details->IsClientArea());
1366
1367 ASSERT_TRUE(details->event);
1368 ASSERT_TRUE(details->event->IsPointerEvent());
1369
1370 ui::PointerEvent* dispatched_event = details->event->AsPointerEvent();
1371 EXPECT_EQ(gfx::Point(75, 15), dispatched_event->root_location());
1372 EXPECT_EQ(gfx::Point(5, 5), dispatched_event->location());
1373 }
1374
1375 // Tests that events events on a descendant of a modal parent target the modal
1376 // child.
1377 TEST_F(EventDispatcherTest, ModalWindowEventOnDescendantOfModalParent) {
1378 std::unique_ptr<ServerWindow> w1 = CreateChildWindow(WindowId(1, 3));
1379 std::unique_ptr<ServerWindow> w11 =
1380 CreateChildWindowWithParent(WindowId(1, 4), w1.get());
1381 std::unique_ptr<ServerWindow> w2 = CreateChildWindow(WindowId(1, 5));
1382
1383 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
1384 w1->SetBounds(gfx::Rect(10, 10, 30, 30));
1385 w11->SetBounds(gfx::Rect(10, 10, 10, 10));
1386 w2->SetBounds(gfx::Rect(50, 10, 10, 10));
1387
1388 w1->AddTransientWindow(w2.get());
1389 w2->SetModal();
1390
1391 // Send event that is over |w11|.
1392 const ui::PointerEvent mouse_pressed(ui::MouseEvent(
1393 ui::ET_MOUSE_PRESSED, gfx::Point(25, 25), gfx::Point(25, 25),
1394 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
1395 event_dispatcher()->ProcessEvent(mouse_pressed);
1396
1397 std::unique_ptr<DispatchedEventDetails> details =
1398 test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
1399 ASSERT_TRUE(details);
1400 EXPECT_EQ(w2.get(), details->window);
1401 EXPECT_TRUE(details->IsNonclientArea());
1402
1403 ASSERT_TRUE(details->event);
1404 ASSERT_TRUE(details->event->IsPointerEvent());
1405
1406 ui::PointerEvent* dispatched_event = details->event->AsPointerEvent();
1407 EXPECT_EQ(gfx::Point(25, 25), dispatched_event->root_location());
1408 EXPECT_EQ(gfx::Point(-25, 15), dispatched_event->location());
1409 }
1410
1411 // Tests that events on a system modal window target the modal window itself.
1412 TEST_F(EventDispatcherTest, ModalWindowEventOnSystemModal) {
1413 std::unique_ptr<ServerWindow> w1 = CreateChildWindow(WindowId(1, 3));
1414
1415 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
1416 w1->SetBounds(gfx::Rect(10, 10, 30, 30));
1417 w1->SetModal();
1418
1419 // Send event that is over |w1|.
1420 const ui::PointerEvent mouse_pressed(ui::MouseEvent(
1421 ui::ET_MOUSE_PRESSED, gfx::Point(15, 15), gfx::Point(15, 15),
1422 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
1423 event_dispatcher()->ProcessEvent(mouse_pressed);
1424
1425 std::unique_ptr<DispatchedEventDetails> details =
1426 test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
1427 ASSERT_TRUE(details);
1428 EXPECT_EQ(w1.get(), details->window);
1429 EXPECT_TRUE(details->IsClientArea());
1430
1431 ASSERT_TRUE(details->event);
1432 ASSERT_TRUE(details->event->IsPointerEvent());
1433
1434 ui::PointerEvent* dispatched_event = details->event->AsPointerEvent();
1435 EXPECT_EQ(gfx::Point(15, 15), dispatched_event->root_location());
1436 EXPECT_EQ(gfx::Point(5, 5), dispatched_event->location());
1437 }
1438
1439 // Tests that events outside of system modal window target the modal window.
1440 TEST_F(EventDispatcherTest, ModalWindowEventOutsideSystemModal) {
1441 std::unique_ptr<ServerWindow> w1 = CreateChildWindow(WindowId(1, 3));
1442
1443 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
1444 w1->SetBounds(gfx::Rect(10, 10, 30, 30));
1445 w1->SetModal();
1446 event_dispatcher()->AddSystemModalWindow(w1.get());
1447
1448 // Send event that is over |w1|.
1449 const ui::PointerEvent mouse_pressed(ui::MouseEvent(
1450 ui::ET_MOUSE_PRESSED, gfx::Point(45, 15), gfx::Point(45, 15),
1451 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
1452 event_dispatcher()->ProcessEvent(mouse_pressed);
1453
1454 std::unique_ptr<DispatchedEventDetails> details =
1455 test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
1456 ASSERT_TRUE(details);
1457 EXPECT_EQ(w1.get(), details->window);
1458 EXPECT_TRUE(details->IsNonclientArea());
1459
1460 ASSERT_TRUE(details->event);
1461 ASSERT_TRUE(details->event->IsPointerEvent());
1462
1463 ui::PointerEvent* dispatched_event = details->event->AsPointerEvent();
1464 EXPECT_EQ(gfx::Point(45, 15), dispatched_event->root_location());
1465 EXPECT_EQ(gfx::Point(35, 5), dispatched_event->location());
1466 }
1467
1468 // Tests that setting capture to a descendant of a modal parent fails.
1469 TEST_F(EventDispatcherTest, ModalWindowSetCaptureDescendantOfModalParent) {
1470 std::unique_ptr<ServerWindow> w1 = CreateChildWindow(WindowId(1, 3));
1471 std::unique_ptr<ServerWindow> w11 =
1472 CreateChildWindowWithParent(WindowId(1, 4), w1.get());
1473 std::unique_ptr<ServerWindow> w2 = CreateChildWindow(WindowId(1, 5));
1474
1475 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
1476 w1->SetBounds(gfx::Rect(10, 10, 30, 30));
1477 w11->SetBounds(gfx::Rect(10, 10, 10, 10));
1478 w2->SetBounds(gfx::Rect(50, 10, 10, 10));
1479
1480 w1->AddTransientWindow(w2.get());
1481 w2->SetModal();
1482
1483 EXPECT_FALSE(event_dispatcher()->SetCaptureWindow(w11.get(), kClientAreaId));
1484 EXPECT_EQ(nullptr, event_dispatcher()->capture_window());
1485 }
1486
1487 // Tests that setting capture to a window unrelated to a modal parent works.
1488 TEST_F(EventDispatcherTest, ModalWindowSetCaptureUnrelatedWindow) {
1489 std::unique_ptr<ServerWindow> w1 = CreateChildWindow(WindowId(1, 3));
1490 std::unique_ptr<ServerWindow> w2 = CreateChildWindow(WindowId(1, 4));
1491 std::unique_ptr<ServerWindow> w3 = CreateChildWindow(WindowId(1, 5));
1492
1493 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
1494 w1->SetBounds(gfx::Rect(10, 10, 30, 30));
1495 w2->SetBounds(gfx::Rect(50, 10, 10, 10));
1496 w3->SetBounds(gfx::Rect(70, 10, 10, 10));
1497
1498 w1->AddTransientWindow(w2.get());
1499 w2->SetModal();
1500
1501 EXPECT_TRUE(event_dispatcher()->SetCaptureWindow(w3.get(), kClientAreaId));
1502 EXPECT_EQ(w3.get(), event_dispatcher()->capture_window());
1503 }
1504
1505 // Tests that setting capture fails when there is a system modal window.
1506 TEST_F(EventDispatcherTest, ModalWindowSystemSetCapture) {
1507 std::unique_ptr<ServerWindow> w1 = CreateChildWindow(WindowId(1, 3));
1508 std::unique_ptr<ServerWindow> w2 = CreateChildWindow(WindowId(1, 4));
1509
1510 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
1511 w1->SetBounds(gfx::Rect(10, 10, 30, 30));
1512 w2->SetBounds(gfx::Rect(50, 10, 10, 10));
1513
1514 event_dispatcher()->AddSystemModalWindow(w2.get());
1515
1516 EXPECT_FALSE(event_dispatcher()->SetCaptureWindow(w1.get(), kClientAreaId));
1517 EXPECT_EQ(nullptr, event_dispatcher()->capture_window());
1518 }
1519
1520 // Tests having multiple system modal windows.
1521 TEST_F(EventDispatcherTest, ModalWindowMultipleSystemModals) {
1522 std::unique_ptr<ServerWindow> w1 = CreateChildWindow(WindowId(1, 3));
1523 std::unique_ptr<ServerWindow> w2 = CreateChildWindow(WindowId(1, 4));
1524 std::unique_ptr<ServerWindow> w3 = CreateChildWindow(WindowId(1, 5));
1525
1526 w2->SetVisible(false);
1527
1528 // In the beginning, there should be no active system modal window.
1529 EXPECT_EQ(nullptr, GetActiveSystemModalWindow());
1530
1531 // Add a visible system modal window. It should become the active one.
1532 event_dispatcher()->AddSystemModalWindow(w1.get());
1533 EXPECT_EQ(w1.get(), GetActiveSystemModalWindow());
1534
1535 // Add an invisible system modal window. It should not change the active one.
1536 event_dispatcher()->AddSystemModalWindow(w2.get());
1537 EXPECT_EQ(w1.get(), GetActiveSystemModalWindow());
1538
1539 // Add another visible system modal window. It should become the active one.
1540 event_dispatcher()->AddSystemModalWindow(w3.get());
1541 EXPECT_EQ(w3.get(), GetActiveSystemModalWindow());
1542
1543 // Make an existing system modal window visible. It should become the active
1544 // one.
1545 w2->SetVisible(true);
1546 EXPECT_EQ(w2.get(), GetActiveSystemModalWindow());
1547
1548 // Remove the active system modal window. Next one should become active.
1549 w2.reset();
1550 EXPECT_EQ(w3.get(), GetActiveSystemModalWindow());
1551
1552 // Remove an inactive system modal window. It should not change the active
1553 // one.
1554 w1.reset();
1555 EXPECT_EQ(w3.get(), GetActiveSystemModalWindow());
1556
1557 // Remove the last remaining system modal window. There should be no active
1558 // one anymore.
1559 w3.reset();
1560 EXPECT_EQ(nullptr, GetActiveSystemModalWindow());
1561 }
1562
1563 TEST_F(EventDispatcherTest, CaptureNotResetOnParentChange) {
1564 std::unique_ptr<ServerWindow> w1 = CreateChildWindow(WindowId(1, 3));
1565 DisableHitTest(w1.get());
1566 std::unique_ptr<ServerWindow> w11 =
1567 CreateChildWindowWithParent(WindowId(1, 4), w1.get());
1568 std::unique_ptr<ServerWindow> w2 = CreateChildWindow(WindowId(1, 5));
1569 DisableHitTest(w2.get());
1570
1571 root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
1572 w1->SetBounds(gfx::Rect(0, 0, 100, 100));
1573 w11->SetBounds(gfx::Rect(10, 10, 10, 10));
1574 w2->SetBounds(gfx::Rect(0, 0, 100, 100));
1575
1576 // Send event that is over |w11|.
1577 const ui::PointerEvent mouse_pressed(ui::MouseEvent(
1578 ui::ET_MOUSE_PRESSED, gfx::Point(15, 15), gfx::Point(15, 15),
1579 base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
1580 event_dispatcher()->ProcessEvent(mouse_pressed);
1581 event_dispatcher()->SetCaptureWindow(w11.get(), kClientAreaId);
1582
1583 std::unique_ptr<DispatchedEventDetails> details =
1584 test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
1585 ASSERT_TRUE(details);
1586 EXPECT_EQ(w11.get(), details->window);
1587 EXPECT_TRUE(details->IsClientArea());
1588
1589 // Move |w11| to |w2| and verify the mouse is still down, and |w11| has
1590 // capture.
1591 w2->Add(w11.get());
1592 EXPECT_TRUE(IsMouseButtonDown());
1593 EXPECT_EQ(w11.get(),
1594 EventDispatcherTestApi(event_dispatcher()).capture_window());
1595 }
1596
1597 TEST_F(EventDispatcherTest, ChangeCaptureFromClientToNonclient) {
1598 std::unique_ptr<ServerWindow> child = CreateChildWindow(WindowId(1, 3));
1599 event_dispatcher()->SetCaptureWindow(child.get(), kNonclientAreaId);
1600 EXPECT_EQ(kNonclientAreaId,
1601 event_dispatcher()->capture_window_client_id());
1602 EXPECT_EQ(nullptr, test_event_dispatcher_delegate()->lost_capture_window());
1603 event_dispatcher()->SetCaptureWindow(child.get(), kClientAreaId);
1604 // Changing capture from client to non-client should notify the delegate.
1605 // The delegate can decide if it really wants to forward the event or not.
1606 EXPECT_EQ(child.get(),
1607 test_event_dispatcher_delegate()->lost_capture_window());
1608 EXPECT_EQ(child.get(), event_dispatcher()->capture_window());
1609 EXPECT_EQ(kClientAreaId, event_dispatcher()->capture_window_client_id());
1610 }
1611
1612 } // namespace test
1613 } // namespace ws
1614 } // namespace mus
OLDNEW
« no previous file with comments | « components/mus/ws/event_dispatcher_delegate.h ('k') | components/mus/ws/event_matcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698