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