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 <set> | |
8 | |
9 #include "base/time/time.h" | 7 #include "base/time/time.h" |
10 #include "cc/surfaces/surface_hittest.h" | 8 #include "cc/surfaces/surface_hittest.h" |
11 #include "components/mus/surfaces/surfaces_state.h" | 9 #include "components/mus/surfaces/surfaces_state.h" |
12 #include "components/mus/ws/accelerator.h" | 10 #include "components/mus/ws/accelerator.h" |
13 #include "components/mus/ws/display.h" | 11 #include "components/mus/ws/display.h" |
14 #include "components/mus/ws/event_dispatcher_delegate.h" | 12 #include "components/mus/ws/event_dispatcher_delegate.h" |
15 #include "components/mus/ws/server_window.h" | 13 #include "components/mus/ws/server_window.h" |
16 #include "components/mus/ws/server_window_delegate.h" | 14 #include "components/mus/ws/server_window_delegate.h" |
17 #include "components/mus/ws/window_coordinate_conversions.h" | 15 #include "components/mus/ws/window_coordinate_conversions.h" |
18 #include "components/mus/ws/window_finder.h" | 16 #include "components/mus/ws/window_finder.h" |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
65 | 63 |
66 } // namespace | 64 } // namespace |
67 | 65 |
68 //////////////////////////////////////////////////////////////////////////////// | 66 //////////////////////////////////////////////////////////////////////////////// |
69 | 67 |
70 EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate) | 68 EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate) |
71 : delegate_(delegate), | 69 : delegate_(delegate), |
72 root_(nullptr), | 70 root_(nullptr), |
73 capture_window_(nullptr), | 71 capture_window_(nullptr), |
74 capture_window_in_nonclient_area_(false), | 72 capture_window_in_nonclient_area_(false), |
73 system_modal_window_(nullptr), | |
75 mouse_button_down_(false), | 74 mouse_button_down_(false), |
76 mouse_cursor_source_window_(nullptr) {} | 75 mouse_cursor_source_window_(nullptr) {} |
77 | 76 |
78 EventDispatcher::~EventDispatcher() { | 77 EventDispatcher::~EventDispatcher() { |
79 std::set<ServerWindow*> pointer_targets; | |
80 if (capture_window_) { | 78 if (capture_window_) { |
81 pointer_targets.insert(capture_window_); | 79 UnobserveWindow(capture_window_); |
82 capture_window_->RemoveObserver(this); | |
83 capture_window_ = nullptr; | 80 capture_window_ = nullptr; |
84 } | 81 } |
82 if (system_modal_window_) { | |
83 UnobserveWindow(system_modal_window_); | |
84 system_modal_window_ = nullptr; | |
85 } | |
85 for (const auto& pair : pointer_targets_) { | 86 for (const auto& pair : pointer_targets_) { |
86 if (pair.second.window && | 87 if (pair.second.window) |
87 pointer_targets.insert(pair.second.window).second) { | 88 UnobserveWindow(pair.second.window); |
88 pair.second.window->RemoveObserver(this); | |
89 } | |
90 } | 89 } |
91 pointer_targets_.clear(); | 90 pointer_targets_.clear(); |
92 } | 91 } |
93 | 92 |
94 void EventDispatcher::Reset() { | 93 void EventDispatcher::Reset() { |
95 if (capture_window_) { | 94 if (capture_window_) { |
96 CancelPointerEventsToTarget(capture_window_); | 95 CancelPointerEventsToTarget(capture_window_); |
97 DCHECK(capture_window_ == nullptr); | 96 DCHECK(capture_window_ == nullptr); |
98 } | 97 } |
99 | 98 |
100 while (!pointer_targets_.empty()) | 99 while (!pointer_targets_.empty()) |
101 StopTrackingPointer(pointer_targets_.begin()->first); | 100 StopTrackingPointer(pointer_targets_.begin()->first); |
102 | 101 |
103 mouse_button_down_ = false; | 102 mouse_button_down_ = false; |
104 } | 103 } |
105 | 104 |
106 void EventDispatcher::SetMousePointerScreenLocation( | 105 void EventDispatcher::SetMousePointerScreenLocation( |
107 const gfx::Point& screen_location) { | 106 const gfx::Point& screen_location) { |
108 DCHECK(pointer_targets_.empty()); | 107 DCHECK(pointer_targets_.empty()); |
109 mouse_pointer_last_location_ = screen_location; | 108 mouse_pointer_last_location_ = screen_location; |
110 UpdateCursorProviderByLastKnownLocation(); | 109 UpdateCursorProviderByLastKnownLocation(); |
111 } | 110 } |
112 | 111 |
113 bool EventDispatcher::SetCaptureWindow(ServerWindow* window, | 112 bool EventDispatcher::SetCaptureWindow(ServerWindow* window, |
114 bool in_nonclient_area) { | 113 bool in_nonclient_area) { |
115 if (window == capture_window_) | 114 if (window == capture_window_) |
116 return true; | 115 return true; |
117 | 116 |
118 // A window that is blocked by a modal window cannot gain capture. | 117 // A window that is blocked by a modal window cannot gain capture. |
119 if (window && window->IsBlockedByModalWindow()) | 118 if (window && ((system_modal_window_ && system_modal_window_->IsDrawn()) || |
119 window->IsBlockedByModalWindow())) { | |
120 return false; | 120 return false; |
121 } | |
121 | 122 |
122 if (capture_window_) { | 123 if (capture_window_) { |
123 // Stop observing old capture window. |pointer_targets_| are cleared on | 124 // Stop observing old capture window. |pointer_targets_| are cleared on |
124 // initial setting of a capture window. | 125 // initial setting of a capture window. |
125 delegate_->OnServerWindowCaptureLost(capture_window_); | 126 delegate_->OnServerWindowCaptureLost(capture_window_); |
126 capture_window_->RemoveObserver(this); | 127 UnobserveWindow(capture_window_); |
127 } else { | 128 } else { |
128 // Cancel implicit capture to all other windows. | 129 // Cancel implicit capture to all other windows. |
129 std::set<ServerWindow*> unobserved_windows; | |
130 for (const auto& pair : pointer_targets_) { | 130 for (const auto& pair : pointer_targets_) { |
131 ServerWindow* target = pair.second.window; | 131 ServerWindow* target = pair.second.window; |
132 if (!target) | 132 if (!target) |
133 continue; | 133 continue; |
134 if (unobserved_windows.insert(target).second) | 134 UnobserveWindow(target); |
135 target->RemoveObserver(this); | |
136 if (target == window) | 135 if (target == window) |
137 continue; | 136 continue; |
138 | 137 |
139 ui::EventType event_type = pair.second.is_mouse_event | 138 ui::EventType event_type = pair.second.is_mouse_event |
140 ? ui::ET_POINTER_EXITED | 139 ? ui::ET_POINTER_EXITED |
141 : ui::ET_POINTER_CANCELLED; | 140 : ui::ET_POINTER_CANCELLED; |
142 ui::EventPointerType pointer_type = | 141 ui::EventPointerType pointer_type = |
143 pair.second.is_mouse_event ? ui::EventPointerType::POINTER_TYPE_MOUSE | 142 pair.second.is_mouse_event ? ui::EventPointerType::POINTER_TYPE_MOUSE |
144 : ui::EventPointerType::POINTER_TYPE_TOUCH; | 143 : ui::EventPointerType::POINTER_TYPE_TOUCH; |
145 // TODO(jonross): Track previous location in PointerTarget for sending | 144 // TODO(jonross): Track previous location in PointerTarget for sending |
146 // cancels. | 145 // cancels. |
147 ui::PointerEvent event(event_type, pointer_type, gfx::Point(), | 146 ui::PointerEvent event(event_type, pointer_type, gfx::Point(), |
148 gfx::Point(), ui::EF_NONE, pair.first, | 147 gfx::Point(), ui::EF_NONE, pair.first, |
149 ui::EventTimeForNow()); | 148 ui::EventTimeForNow()); |
150 DispatchToPointerTarget(pair.second, event); | 149 DispatchToPointerTarget(pair.second, event); |
151 } | 150 } |
152 pointer_targets_.clear(); | 151 pointer_targets_.clear(); |
153 } | 152 } |
154 | 153 |
155 // Begin tracking the capture window if it is not yet being observed. | 154 // Begin tracking the capture window if it is not yet being observed. |
156 if (window) { | 155 if (window) { |
157 window->AddObserver(this); | 156 ObserveWindow(window); |
158 if (!capture_window_) | 157 if (!capture_window_) |
159 delegate_->SetNativeCapture(); | 158 delegate_->SetNativeCapture(); |
160 } else { | 159 } else { |
161 delegate_->ReleaseNativeCapture(); | 160 delegate_->ReleaseNativeCapture(); |
162 if (!mouse_button_down_) | 161 if (!mouse_button_down_) |
163 UpdateCursorProviderByLastKnownLocation(); | 162 UpdateCursorProviderByLastKnownLocation(); |
164 } | 163 } |
165 | 164 |
166 capture_window_ = window; | 165 capture_window_ = window; |
167 capture_window_in_nonclient_area_ = in_nonclient_area; | 166 capture_window_in_nonclient_area_ = in_nonclient_area; |
168 return true; | 167 return true; |
169 } | 168 } |
170 | 169 |
170 bool EventDispatcher::SetSystemModalWindow(ServerWindow* window) { | |
171 DCHECK(window); | |
172 | |
173 if (window == system_modal_window_) | |
174 return true; | |
175 | |
176 if (system_modal_window_) | |
177 return false; | |
sky
2016/04/20 20:14:11
nit: spacing is off (run git cl format).
mohsen
2016/04/21 17:58:43
Done.
| |
178 | |
179 system_modal_window_ = window; | |
sky
2016/04/20 20:14:11
I think we should cancel capture here rather than
mohsen
2016/04/21 17:58:43
Done.
| |
180 system_modal_window_->SetModal(); | |
181 ObserveWindow(system_modal_window_); | |
182 return true; | |
183 } | |
184 | |
171 void EventDispatcher::UpdateCursorProviderByLastKnownLocation() { | 185 void EventDispatcher::UpdateCursorProviderByLastKnownLocation() { |
172 if (!mouse_button_down_) { | 186 if (!mouse_button_down_) { |
173 gfx::Point location = mouse_pointer_last_location_; | 187 gfx::Point location = mouse_pointer_last_location_; |
174 mouse_cursor_source_window_ = | 188 mouse_cursor_source_window_ = |
175 FindDeepestVisibleWindowForEvents(root_, surface_id_, &location); | 189 FindDeepestVisibleWindowForEvents(root_, surface_id_, &location); |
176 } | 190 } |
177 } | 191 } |
178 | 192 |
179 bool EventDispatcher::AddAccelerator(uint32_t id, | 193 bool EventDispatcher::AddAccelerator(uint32_t id, |
180 mojom::EventMatcherPtr event_matcher) { | 194 mojom::EventMatcherPtr event_matcher) { |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
302 StopTrackingPointer(pointer_id); | 316 StopTrackingPointer(pointer_id); |
303 if (!AreAnyPointersDown()) | 317 if (!AreAnyPointersDown()) |
304 delegate_->ReleaseNativeCapture(); | 318 delegate_->ReleaseNativeCapture(); |
305 } | 319 } |
306 } | 320 } |
307 | 321 |
308 void EventDispatcher::StartTrackingPointer( | 322 void EventDispatcher::StartTrackingPointer( |
309 int32_t pointer_id, | 323 int32_t pointer_id, |
310 const PointerTarget& pointer_target) { | 324 const PointerTarget& pointer_target) { |
311 DCHECK(!IsTrackingPointer(pointer_id)); | 325 DCHECK(!IsTrackingPointer(pointer_id)); |
312 if (!IsObservingWindow(pointer_target.window)) | 326 ObserveWindow(pointer_target.window); |
313 pointer_target.window->AddObserver(this); | |
314 pointer_targets_[pointer_id] = pointer_target; | 327 pointer_targets_[pointer_id] = pointer_target; |
315 } | 328 } |
316 | 329 |
317 void EventDispatcher::StopTrackingPointer(int32_t pointer_id) { | 330 void EventDispatcher::StopTrackingPointer(int32_t pointer_id) { |
318 DCHECK(IsTrackingPointer(pointer_id)); | 331 DCHECK(IsTrackingPointer(pointer_id)); |
319 ServerWindow* window = pointer_targets_[pointer_id].window; | 332 ServerWindow* window = pointer_targets_[pointer_id].window; |
320 pointer_targets_.erase(pointer_id); | 333 pointer_targets_.erase(pointer_id); |
321 if (window && !IsObservingWindow(window)) | 334 if (window) |
322 window->RemoveObserver(this); | 335 UnobserveWindow(window); |
323 } | 336 } |
324 | 337 |
325 void EventDispatcher::UpdateTargetForPointer(int32_t pointer_id, | 338 void EventDispatcher::UpdateTargetForPointer(int32_t pointer_id, |
326 const ui::LocatedEvent& event) { | 339 const ui::LocatedEvent& event) { |
327 if (!IsTrackingPointer(pointer_id)) { | 340 if (!IsTrackingPointer(pointer_id)) { |
328 StartTrackingPointer(pointer_id, PointerTargetForEvent(event)); | 341 StartTrackingPointer(pointer_id, PointerTargetForEvent(event)); |
329 return; | 342 return; |
330 } | 343 } |
331 | 344 |
332 const PointerTarget pointer_target = PointerTargetForEvent(event); | 345 const PointerTarget pointer_target = PointerTargetForEvent(event); |
(...skipping 21 matching lines...) Expand all Loading... | |
354 StopTrackingPointer(pointer_id); | 367 StopTrackingPointer(pointer_id); |
355 StartTrackingPointer(pointer_id, pointer_target); | 368 StartTrackingPointer(pointer_id, pointer_target); |
356 } | 369 } |
357 | 370 |
358 EventDispatcher::PointerTarget EventDispatcher::PointerTargetForEvent( | 371 EventDispatcher::PointerTarget EventDispatcher::PointerTargetForEvent( |
359 const ui::LocatedEvent& event) const { | 372 const ui::LocatedEvent& event) const { |
360 PointerTarget pointer_target; | 373 PointerTarget pointer_target; |
361 gfx::Point location(event.location()); | 374 gfx::Point location(event.location()); |
362 ServerWindow* target_window = | 375 ServerWindow* target_window = |
363 FindDeepestVisibleWindowForEvents(root_, surface_id_, &location); | 376 FindDeepestVisibleWindowForEvents(root_, surface_id_, &location); |
364 pointer_target.window = target_window->GetModalTarget(); | 377 pointer_target.window = |
378 system_modal_window_ && system_modal_window_->IsDrawn() | |
379 ? system_modal_window_ | |
380 : target_window->GetModalTarget(); | |
365 pointer_target.is_mouse_event = event.IsMousePointerEvent(); | 381 pointer_target.is_mouse_event = event.IsMousePointerEvent(); |
366 pointer_target.in_nonclient_area = | 382 pointer_target.in_nonclient_area = |
367 target_window != pointer_target.window || | 383 target_window != pointer_target.window || |
368 IsLocationInNonclientArea(pointer_target.window, location); | 384 IsLocationInNonclientArea(pointer_target.window, location); |
369 pointer_target.is_pointer_down = event.type() == ui::ET_POINTER_DOWN; | 385 pointer_target.is_pointer_down = event.type() == ui::ET_POINTER_DOWN; |
370 return pointer_target; | 386 return pointer_target; |
371 } | 387 } |
372 | 388 |
373 bool EventDispatcher::AreAnyPointersDown() const { | 389 bool EventDispatcher::AreAnyPointersDown() const { |
374 for (const auto& pair : pointer_targets_) { | 390 for (const auto& pair : pointer_targets_) { |
(...skipping 13 matching lines...) Expand all Loading... | |
388 transform.TransformPoint(&location); | 404 transform.TransformPoint(&location); |
389 scoped_ptr<ui::Event> clone = ui::Event::Clone(event); | 405 scoped_ptr<ui::Event> clone = ui::Event::Clone(event); |
390 clone->AsLocatedEvent()->set_location(location); | 406 clone->AsLocatedEvent()->set_location(location); |
391 // TODO(jonross): add post-target accelerator support once accelerators | 407 // TODO(jonross): add post-target accelerator support once accelerators |
392 // support pointer events. | 408 // support pointer events. |
393 delegate_->DispatchInputEventToWindow(target.window, target.in_nonclient_area, | 409 delegate_->DispatchInputEventToWindow(target.window, target.in_nonclient_area, |
394 *clone, nullptr); | 410 *clone, nullptr); |
395 } | 411 } |
396 | 412 |
397 void EventDispatcher::CancelPointerEventsToTarget(ServerWindow* window) { | 413 void EventDispatcher::CancelPointerEventsToTarget(ServerWindow* window) { |
398 window->RemoveObserver(this); | |
399 | |
400 if (capture_window_ == window) { | 414 if (capture_window_ == window) { |
415 UnobserveWindow(window); | |
401 capture_window_ = nullptr; | 416 capture_window_ = nullptr; |
402 mouse_button_down_ = false; | 417 mouse_button_down_ = false; |
403 // A window only cares to be informed that it lost capture if it explicitly | 418 // A window only cares to be informed that it lost capture if it explicitly |
404 // requested capture. A window can lose capture if another window gains | 419 // requested capture. A window can lose capture if another window gains |
405 // explicit capture. | 420 // explicit capture. |
406 delegate_->OnServerWindowCaptureLost(window); | 421 delegate_->OnServerWindowCaptureLost(window); |
407 delegate_->ReleaseNativeCapture(); | 422 delegate_->ReleaseNativeCapture(); |
408 UpdateCursorProviderByLastKnownLocation(); | 423 UpdateCursorProviderByLastKnownLocation(); |
409 return; | 424 return; |
410 } | 425 } |
411 | 426 |
412 for (auto& pair : pointer_targets_) { | 427 for (auto& pair : pointer_targets_) { |
413 if (pair.second.window == window) | 428 if (pair.second.window == window) { |
429 UnobserveWindow(window); | |
414 pair.second.window = nullptr; | 430 pair.second.window = nullptr; |
431 } | |
415 } | 432 } |
416 } | 433 } |
417 | 434 |
418 bool EventDispatcher::IsObservingWindow(ServerWindow* window) { | 435 void EventDispatcher::ObserveWindow(ServerWindow* window) { |
419 for (const auto& pair : pointer_targets_) { | 436 auto res = observed_windows_.insert(std::make_pair(window, 0u)); |
420 if (pair.second.window == window) | 437 res.first->second++; |
421 return true; | 438 if (res.second) |
439 window->AddObserver(this); | |
440 } | |
441 | |
442 void EventDispatcher::UnobserveWindow(ServerWindow* window) { | |
443 auto it = observed_windows_.find(window); | |
444 DCHECK(it != observed_windows_.end()); | |
445 DCHECK_LT(0u, it->second); | |
446 it->second--; | |
447 if (!it->second) { | |
448 window->RemoveObserver(this); | |
449 observed_windows_.erase(it); | |
422 } | 450 } |
423 return false; | |
424 } | 451 } |
425 | 452 |
426 Accelerator* EventDispatcher::FindAccelerator( | 453 Accelerator* EventDispatcher::FindAccelerator( |
427 const ui::KeyEvent& event, | 454 const ui::KeyEvent& event, |
428 const mojom::AcceleratorPhase phase) { | 455 const mojom::AcceleratorPhase phase) { |
429 for (const auto& pair : accelerators_) { | 456 for (const auto& pair : accelerators_) { |
430 if (pair.second->MatchesEvent(event, phase)) { | 457 if (pair.second->MatchesEvent(event, phase)) { |
431 return pair.second.get(); | 458 return pair.second.get(); |
432 } | 459 } |
433 } | 460 } |
434 return nullptr; | 461 return nullptr; |
435 } | 462 } |
436 | 463 |
437 void EventDispatcher::OnWillChangeWindowHierarchy(ServerWindow* window, | 464 void EventDispatcher::OnWillChangeWindowHierarchy(ServerWindow* window, |
438 ServerWindow* new_parent, | 465 ServerWindow* new_parent, |
439 ServerWindow* old_parent) { | 466 ServerWindow* old_parent) { |
440 CancelPointerEventsToTarget(window); | 467 CancelPointerEventsToTarget(window); |
441 } | 468 } |
442 | 469 |
443 void EventDispatcher::OnWindowVisibilityChanged(ServerWindow* window) { | 470 void EventDispatcher::OnWindowVisibilityChanged(ServerWindow* window) { |
444 CancelPointerEventsToTarget(window); | 471 CancelPointerEventsToTarget(window); |
445 } | 472 } |
446 | 473 |
447 void EventDispatcher::OnWindowDestroyed(ServerWindow* window) { | 474 void EventDispatcher::OnWindowDestroyed(ServerWindow* window) { |
448 CancelPointerEventsToTarget(window); | 475 CancelPointerEventsToTarget(window); |
449 | 476 |
477 if (system_modal_window_ == window) { | |
sky
2016/04/20 20:14:11
You have this in the destructor as well. Maybe Res
mohsen
2016/04/21 17:58:42
Done.
| |
478 UnobserveWindow(window); | |
479 system_modal_window_ = nullptr; | |
480 } | |
481 | |
450 if (mouse_cursor_source_window_ == window) | 482 if (mouse_cursor_source_window_ == window) |
451 mouse_cursor_source_window_ = nullptr; | 483 mouse_cursor_source_window_ = nullptr; |
452 } | 484 } |
453 | 485 |
454 } // namespace ws | 486 } // namespace ws |
455 } // namespace mus | 487 } // namespace mus |
OLD | NEW |