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

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

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

Powered by Google App Engine
This is Rietveld 408576698