OLD | NEW |
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 "components/mus/public/cpp/event_matcher.h" | 7 #include "components/mus/public/cpp/event_matcher.h" |
8 #include "components/mus/ws/event_dispatcher_delegate.h" | 8 #include "components/mus/ws/event_dispatcher_delegate.h" |
9 #include "components/mus/ws/server_window.h" | 9 #include "components/mus/ws/server_window.h" |
10 #include "components/mus/ws/test_server_window_delegate.h" | 10 #include "components/mus/ws/test_server_window_delegate.h" |
11 #include "mojo/converters/input_events/input_events_type_converters.h" | 11 #include "mojo/converters/input_events/input_events_type_converters.h" |
12 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
13 #include "ui/events/event.h" | 13 #include "ui/events/event.h" |
14 | 14 |
15 namespace mus { | 15 namespace mus { |
16 namespace ws { | 16 namespace ws { |
17 namespace { | 17 namespace { |
18 | 18 |
19 class TestEventDispatcherDelegate : public EventDispatcherDelegate { | 19 class TestEventDispatcherDelegate : public EventDispatcherDelegate { |
20 public: | 20 public: |
21 explicit TestEventDispatcherDelegate(ServerWindow* root) | 21 explicit TestEventDispatcherDelegate(ServerWindow* root) |
22 : root_(root), | 22 : root_(root), |
23 focused_window_(nullptr), | 23 focused_window_(nullptr), |
24 last_target_(nullptr), | 24 last_target_(nullptr), |
25 last_accelerator_(0) {} | 25 last_accelerator_(0), |
| 26 last_in_nonclient_area_(false) {} |
26 ~TestEventDispatcherDelegate() override {} | 27 ~TestEventDispatcherDelegate() override {} |
27 | 28 |
28 mojo::EventPtr GetAndClearLastDispatchedEvent() { | 29 mojo::EventPtr GetAndClearLastDispatchedEvent() { |
29 return last_dispatched_event_.Pass(); | 30 return last_dispatched_event_.Pass(); |
30 } | 31 } |
31 | 32 |
32 uint32_t GetAndClearLastAccelerator() { | 33 uint32_t GetAndClearLastAccelerator() { |
33 uint32_t return_value = last_accelerator_; | 34 uint32_t return_value = last_accelerator_; |
34 last_accelerator_ = 0; | 35 last_accelerator_ = 0; |
35 return return_value; | 36 return return_value; |
36 } | 37 } |
37 | 38 |
38 ServerWindow* last_target() { return last_target_; } | 39 ServerWindow* last_target() { return last_target_; } |
39 | 40 |
| 41 bool GetAndClearLastInNonclientArea() { |
| 42 const bool result = last_in_nonclient_area_; |
| 43 last_in_nonclient_area_ = false; |
| 44 return result; |
| 45 } |
| 46 |
40 private: | 47 private: |
41 // EventDispatcherDelegate: | 48 // EventDispatcherDelegate: |
42 void OnAccelerator(uint32_t accelerator, mojo::EventPtr event) override { | 49 void OnAccelerator(uint32_t accelerator, mojo::EventPtr event) override { |
43 EXPECT_EQ(0u, last_accelerator_); | 50 EXPECT_EQ(0u, last_accelerator_); |
44 last_accelerator_ = accelerator; | 51 last_accelerator_ = accelerator; |
45 } | 52 } |
46 void SetFocusedWindowFromEventDispatcher(ServerWindow* window) override { | 53 void SetFocusedWindowFromEventDispatcher(ServerWindow* window) override { |
47 focused_window_ = window; | 54 focused_window_ = window; |
48 } | 55 } |
49 ServerWindow* GetFocusedWindowForEventDispatcher() override { | 56 ServerWindow* GetFocusedWindowForEventDispatcher() override { |
50 return focused_window_; | 57 return focused_window_; |
51 } | 58 } |
52 void DispatchInputEventToWindow(ServerWindow* target, | 59 void DispatchInputEventToWindow(ServerWindow* target, |
| 60 bool in_nonclient_area, |
53 mojo::EventPtr event) override { | 61 mojo::EventPtr event) override { |
54 last_target_ = target; | 62 last_target_ = target; |
55 last_dispatched_event_ = event.Pass(); | 63 last_dispatched_event_ = event.Pass(); |
| 64 last_in_nonclient_area_ = in_nonclient_area; |
56 } | 65 } |
57 | 66 |
58 ServerWindow* root_; | 67 ServerWindow* root_; |
59 ServerWindow* focused_window_; | 68 ServerWindow* focused_window_; |
60 ServerWindow* last_target_; | 69 ServerWindow* last_target_; |
61 mojo::EventPtr last_dispatched_event_; | 70 mojo::EventPtr last_dispatched_event_; |
62 uint32_t last_accelerator_; | 71 uint32_t last_accelerator_; |
| 72 bool last_in_nonclient_area_; |
63 | 73 |
64 DISALLOW_COPY_AND_ASSIGN(TestEventDispatcherDelegate); | 74 DISALLOW_COPY_AND_ASSIGN(TestEventDispatcherDelegate); |
65 }; | 75 }; |
66 | 76 |
67 struct MouseEventTest { | 77 struct MouseEventTest { |
68 ui::MouseEvent input_event; | 78 ui::MouseEvent input_event; |
69 ServerWindow* expected_target_window; | 79 ServerWindow* expected_target_window; |
70 gfx::Point expected_root_location; | 80 gfx::Point expected_root_location; |
71 gfx::Point expected_location; | 81 gfx::Point expected_location; |
72 }; | 82 }; |
(...skipping 10 matching lines...) Expand all Loading... |
83 ASSERT_EQ(test.expected_target_window, dispatcher_delegate->last_target()) | 93 ASSERT_EQ(test.expected_target_window, dispatcher_delegate->last_target()) |
84 << "Test " << i << " failed."; | 94 << "Test " << i << " failed."; |
85 | 95 |
86 mojo::EventPtr dispatched_event_mojo = | 96 mojo::EventPtr dispatched_event_mojo = |
87 dispatcher_delegate->GetAndClearLastDispatchedEvent(); | 97 dispatcher_delegate->GetAndClearLastDispatchedEvent(); |
88 ASSERT_TRUE(dispatched_event_mojo.get()) << "Test " << i << " failed."; | 98 ASSERT_TRUE(dispatched_event_mojo.get()) << "Test " << i << " failed."; |
89 scoped_ptr<ui::Event> dispatched_event( | 99 scoped_ptr<ui::Event> dispatched_event( |
90 dispatched_event_mojo.To<scoped_ptr<ui::Event>>()); | 100 dispatched_event_mojo.To<scoped_ptr<ui::Event>>()); |
91 ASSERT_TRUE(dispatched_event.get()) << "Test " << i << " failed."; | 101 ASSERT_TRUE(dispatched_event.get()) << "Test " << i << " failed."; |
92 ASSERT_TRUE(dispatched_event->IsMouseEvent()) << "Test " << i << " failed."; | 102 ASSERT_TRUE(dispatched_event->IsMouseEvent()) << "Test " << i << " failed."; |
| 103 EXPECT_FALSE(dispatcher_delegate->GetAndClearLastInNonclientArea()) |
| 104 << "Test " << i << " failed."; |
93 ui::MouseEvent* dispatched_mouse_event = | 105 ui::MouseEvent* dispatched_mouse_event = |
94 static_cast<ui::MouseEvent*>(dispatched_event.get()); | 106 static_cast<ui::MouseEvent*>(dispatched_event.get()); |
95 EXPECT_EQ(test.expected_root_location, | 107 EXPECT_EQ(test.expected_root_location, |
96 dispatched_mouse_event->root_location()) | 108 dispatched_mouse_event->root_location()) |
97 << "Test " << i << " failed."; | 109 << "Test " << i << " failed."; |
98 EXPECT_EQ(test.expected_location, dispatched_mouse_event->location()) | 110 EXPECT_EQ(test.expected_location, dispatched_mouse_event->location()) |
99 << "Test " << i << " failed."; | 111 << "Test " << i << " failed."; |
100 } | 112 } |
101 } | 113 } |
102 | 114 |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
261 {ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::PointF(50.f, 50.f), | 273 {ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::PointF(50.f, 50.f), |
262 gfx::PointF(50.f, 50.f), base::TimeDelta(), | 274 gfx::PointF(50.f, 50.f), base::TimeDelta(), |
263 ui::EF_LEFT_MOUSE_BUTTON, 0), | 275 ui::EF_LEFT_MOUSE_BUTTON, 0), |
264 &child, gfx::Point(50, 50), gfx::Point(40, 40)}, | 276 &child, gfx::Point(50, 50), gfx::Point(40, 40)}, |
265 | 277 |
266 }; | 278 }; |
267 RunMouseEventTests(&dispatcher, &event_dispatcher_delegate, tests, | 279 RunMouseEventTests(&dispatcher, &event_dispatcher_delegate, tests, |
268 arraysize(tests)); | 280 arraysize(tests)); |
269 } | 281 } |
270 | 282 |
271 TEST(EventDispatcherTest, MoveWindow) { | 283 TEST(EventDispatcherTest, ClientAreaGoesToOwner) { |
272 TestServerWindowDelegate window_delegate; | 284 TestServerWindowDelegate window_delegate; |
273 ServerWindow root(&window_delegate, WindowId(1, 2)); | 285 ServerWindow root(&window_delegate, WindowId(1, 2)); |
274 window_delegate.set_root_window(&root); | 286 window_delegate.set_root_window(&root); |
275 root.SetVisible(true); | 287 root.SetVisible(true); |
276 | 288 |
277 ServerWindow child(&window_delegate, WindowId(1, 3)); | 289 ServerWindow child(&window_delegate, WindowId(1, 3)); |
278 root.Add(&child); | 290 root.Add(&child); |
279 child.SetVisible(true); | 291 child.SetVisible(true); |
280 | 292 |
281 root.SetBounds(gfx::Rect(0, 0, 100, 100)); | 293 root.SetBounds(gfx::Rect(0, 0, 100, 100)); |
282 child.SetBounds(gfx::Rect(10, 10, 20, 20)); | 294 child.SetBounds(gfx::Rect(10, 10, 20, 20)); |
283 | 295 |
284 root.set_is_draggable_window_container(true); | |
285 child.SetClientArea(gfx::Rect(5, 5, 10, 10)); | 296 child.SetClientArea(gfx::Rect(5, 5, 10, 10)); |
286 | 297 |
287 TestEventDispatcherDelegate event_dispatcher_delegate(&root); | 298 TestEventDispatcherDelegate event_dispatcher_delegate(&root); |
288 EventDispatcher dispatcher(&event_dispatcher_delegate); | 299 EventDispatcher dispatcher(&event_dispatcher_delegate); |
289 dispatcher.set_root(&root); | 300 dispatcher.set_root(&root); |
290 | 301 |
291 // Start move loop by sending mouse event over non-client area. | 302 // Start move loop by sending mouse event over non-client area. |
292 const ui::MouseEvent press_event( | 303 const ui::MouseEvent press_event( |
293 ui::ET_MOUSE_PRESSED, gfx::PointF(12.f, 12.f), gfx::PointF(12.f, 12.f), | 304 ui::ET_MOUSE_PRESSED, gfx::PointF(12.f, 12.f), gfx::PointF(12.f, 12.f), |
294 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); | 305 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); |
295 dispatcher.OnEvent( | 306 dispatcher.OnEvent( |
296 mojo::Event::From(static_cast<const ui::Event&>(press_event))); | 307 mojo::Event::From(static_cast<const ui::Event&>(press_event))); |
297 | 308 |
298 // The event should not have been dispatched to the delegate. | 309 // Events should target child and be in the non-client area. |
299 ASSERT_EQ(nullptr, event_dispatcher_delegate.last_target()); | 310 ASSERT_EQ(&child, event_dispatcher_delegate.last_target()); |
| 311 EXPECT_TRUE(event_dispatcher_delegate.GetAndClearLastInNonclientArea()); |
300 | 312 |
301 // Move the mouse 5,6 pixels and verify window moved. | 313 // Move the mouse 5,6 pixels and target is the same. |
302 const ui::MouseEvent move_event(ui::ET_MOUSE_MOVED, gfx::PointF(17.f, 18.f), | 314 const ui::MouseEvent move_event(ui::ET_MOUSE_MOVED, gfx::PointF(17.f, 18.f), |
303 gfx::PointF(17.f, 18.f), base::TimeDelta(), | 315 gfx::PointF(17.f, 18.f), base::TimeDelta(), |
304 ui::EF_LEFT_MOUSE_BUTTON, 0); | 316 ui::EF_LEFT_MOUSE_BUTTON, 0); |
305 dispatcher.OnEvent( | 317 dispatcher.OnEvent( |
306 mojo::Event::From(static_cast<const ui::Event&>(move_event))); | 318 mojo::Event::From(static_cast<const ui::Event&>(move_event))); |
307 | 319 |
308 // The event should not have been dispatched to the delegate. | 320 // Still same target. |
309 ASSERT_EQ(nullptr, event_dispatcher_delegate.last_target()); | 321 ASSERT_EQ(&child, event_dispatcher_delegate.last_target()); |
310 | 322 EXPECT_TRUE(event_dispatcher_delegate.GetAndClearLastInNonclientArea()); |
311 EXPECT_EQ(gfx::Rect(15, 16, 20, 20), child.bounds()); | |
312 | 323 |
313 // Release the mouse. | 324 // Release the mouse. |
314 const ui::MouseEvent release_event( | 325 const ui::MouseEvent release_event( |
315 ui::ET_MOUSE_RELEASED, gfx::PointF(17.f, 18.f), gfx::PointF(17.f, 18.f), | 326 ui::ET_MOUSE_RELEASED, gfx::PointF(17.f, 18.f), gfx::PointF(17.f, 18.f), |
316 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); | 327 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); |
317 dispatcher.OnEvent( | 328 dispatcher.OnEvent( |
318 mojo::Event::From(static_cast<const ui::Event&>(release_event))); | 329 mojo::Event::From(static_cast<const ui::Event&>(release_event))); |
319 | 330 |
320 // The event should not have been dispatched to the delegate. | 331 // The event should not have been dispatched to the delegate. |
321 ASSERT_EQ(nullptr, event_dispatcher_delegate.last_target()); | 332 ASSERT_EQ(&child, event_dispatcher_delegate.last_target()); |
| 333 EXPECT_TRUE(event_dispatcher_delegate.GetAndClearLastInNonclientArea()); |
322 | 334 |
323 // Press in the client area and verify the window gets it. | 335 // Press in the client area and verify target/client area. |
324 const ui::MouseEvent press_event2( | 336 const ui::MouseEvent press_event2( |
325 ui::ET_MOUSE_PRESSED, gfx::PointF(21.f, 22.f), gfx::PointF(21.f, 22.f), | 337 ui::ET_MOUSE_PRESSED, gfx::PointF(21.f, 22.f), gfx::PointF(21.f, 22.f), |
326 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); | 338 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); |
327 dispatcher.OnEvent( | 339 dispatcher.OnEvent( |
328 mojo::Event::From(static_cast<const ui::Event&>(press_event2))); | 340 mojo::Event::From(static_cast<const ui::Event&>(press_event2))); |
329 ASSERT_EQ(&child, event_dispatcher_delegate.last_target()); | 341 ASSERT_EQ(&child, event_dispatcher_delegate.last_target()); |
330 } | 342 EXPECT_FALSE(event_dispatcher_delegate.GetAndClearLastInNonclientArea()); |
331 | |
332 TEST(EventDispatcherTest, DestroyWindowWhileMoving) { | |
333 TestServerWindowDelegate window_delegate; | |
334 ServerWindow root(&window_delegate, WindowId(1, 2)); | |
335 window_delegate.set_root_window(&root); | |
336 root.SetVisible(true); | |
337 | |
338 scoped_ptr<ServerWindow> child( | |
339 new ServerWindow(&window_delegate, WindowId(1, 3))); | |
340 root.Add(child.get()); | |
341 child->SetVisible(true); | |
342 | |
343 root.SetBounds(gfx::Rect(0, 0, 100, 100)); | |
344 child->SetBounds(gfx::Rect(10, 10, 20, 20)); | |
345 | |
346 root.set_is_draggable_window_container(true); | |
347 child->SetClientArea(gfx::Rect(5, 5, 10, 10)); | |
348 | |
349 TestEventDispatcherDelegate event_dispatcher_delegate(&root); | |
350 EventDispatcher dispatcher(&event_dispatcher_delegate); | |
351 dispatcher.set_root(&root); | |
352 | |
353 // Start move loop by sending mouse event over non-client area. | |
354 const ui::MouseEvent press_event( | |
355 ui::ET_MOUSE_PRESSED, gfx::PointF(12.f, 12.f), gfx::PointF(12.f, 12.f), | |
356 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); | |
357 dispatcher.OnEvent( | |
358 mojo::Event::From(static_cast<const ui::Event&>(press_event))); | |
359 | |
360 // The event should not have been dispatched to the delegate. | |
361 ASSERT_EQ(nullptr, event_dispatcher_delegate.last_target()); | |
362 | |
363 // Destroy the child, no events should be propagated until after the release. | |
364 child.reset(); | |
365 | |
366 const ui::MouseEvent move_event(ui::ET_MOUSE_MOVED, gfx::PointF(17.f, 18.f), | |
367 gfx::PointF(17.f, 18.f), base::TimeDelta(), | |
368 ui::EF_LEFT_MOUSE_BUTTON, 0); | |
369 dispatcher.OnEvent( | |
370 mojo::Event::From(static_cast<const ui::Event&>(move_event))); | |
371 ASSERT_EQ(nullptr, event_dispatcher_delegate.last_target()); | |
372 | |
373 const ui::MouseEvent release_event( | |
374 ui::ET_MOUSE_RELEASED, gfx::PointF(17.f, 18.f), gfx::PointF(17.f, 18.f), | |
375 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); | |
376 dispatcher.OnEvent( | |
377 mojo::Event::From(static_cast<const ui::Event&>(release_event))); | |
378 ASSERT_EQ(nullptr, event_dispatcher_delegate.last_target()); | |
379 | |
380 const ui::MouseEvent press_event2( | |
381 ui::ET_MOUSE_PRESSED, gfx::PointF(21.f, 22.f), gfx::PointF(21.f, 22.f), | |
382 base::TimeDelta(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); | |
383 dispatcher.OnEvent( | |
384 mojo::Event::From(static_cast<const ui::Event&>(press_event2))); | |
385 ASSERT_EQ(&root, event_dispatcher_delegate.last_target()); | |
386 } | 343 } |
387 | 344 |
388 } // namespace ws | 345 } // namespace ws |
389 } // namespace mus | 346 } // namespace mus |
OLD | NEW |