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

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

Issue 1818333002: Reland: mus: Enable system modal windows (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/mus/ws/event_dispatcher.h ('k') | components/mus/ws/event_dispatcher_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/mus/ws/event_dispatcher.h" 5 #include "components/mus/ws/event_dispatcher.h"
6 6
7 #include <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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
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),
75 mouse_button_down_(false), 73 mouse_button_down_(false),
76 mouse_cursor_source_window_(nullptr) {} 74 mouse_cursor_source_window_(nullptr) {}
77 75
78 EventDispatcher::~EventDispatcher() { 76 EventDispatcher::~EventDispatcher() {
79 std::set<ServerWindow*> pointer_targets;
80 if (capture_window_) { 77 if (capture_window_) {
81 pointer_targets.insert(capture_window_); 78 UnobserveWindow(capture_window_);
82 capture_window_->RemoveObserver(this);
83 capture_window_ = nullptr; 79 capture_window_ = nullptr;
84 } 80 }
81 for (auto it = system_modal_windows_.begin();
82 it != system_modal_windows_.end();) {
83 auto remove_it = it++;
84 RemoveSystemModalWindow(remove_it);
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 &&
119 (GetActiveSystemModalWindow() || 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 void EventDispatcher::AddSystemModalWindow(ServerWindow* window) {
171 DCHECK(window);
172 DCHECK(std::find(system_modal_windows_.begin(), system_modal_windows_.end(),
173 window) == system_modal_windows_.end());
174
175 window->SetModal();
176 system_modal_windows_.push_front(window);
177 ObserveWindow(window);
sky 2016/04/25 23:36:08 It's confusing and error prone to have this class
mohsen 2016/04/26 20:24:05 I agree. Even before adding modal windows, it was
178
179 ReleaseCaptureBlockedByModalWindow(window);
180 }
181
182 void EventDispatcher::ReleaseCaptureBlockedByModalWindow(
183 const ServerWindow* modal_window) {
184 if (!capture_window_ || !modal_window->is_modal() ||
185 !modal_window->IsDrawn()) {
186 return;
187 }
188
189 if (modal_window->transient_parent() &&
190 !modal_window->transient_parent()->Contains(capture_window_)) {
191 return;
192 }
193
194 SetCaptureWindow(nullptr, false);
195 }
196
197 void EventDispatcher::ReleaseCaptureBlockedByAnyModalWindow() {
198 if (!capture_window_)
199 return;
200
201 if (!GetActiveSystemModalWindow() &&
202 !capture_window_->IsBlockedByModalWindow()) {
203 return;
204 }
205
206 SetCaptureWindow(nullptr, false);
207 }
208
171 void EventDispatcher::UpdateCursorProviderByLastKnownLocation() { 209 void EventDispatcher::UpdateCursorProviderByLastKnownLocation() {
172 if (!mouse_button_down_) { 210 if (!mouse_button_down_) {
173 gfx::Point location = mouse_pointer_last_location_; 211 gfx::Point location = mouse_pointer_last_location_;
174 mouse_cursor_source_window_ = 212 mouse_cursor_source_window_ =
175 FindDeepestVisibleWindowForEvents(root_, surface_id_, &location); 213 FindDeepestVisibleWindowForEvents(root_, surface_id_, &location);
176 } 214 }
177 } 215 }
178 216
179 bool EventDispatcher::AddAccelerator(uint32_t id, 217 bool EventDispatcher::AddAccelerator(uint32_t id,
180 mojom::EventMatcherPtr event_matcher) { 218 mojom::EventMatcherPtr event_matcher) {
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 StopTrackingPointer(pointer_id); 342 StopTrackingPointer(pointer_id);
305 if (!AreAnyPointersDown()) 343 if (!AreAnyPointersDown())
306 delegate_->ReleaseNativeCapture(); 344 delegate_->ReleaseNativeCapture();
307 } 345 }
308 } 346 }
309 347
310 void EventDispatcher::StartTrackingPointer( 348 void EventDispatcher::StartTrackingPointer(
311 int32_t pointer_id, 349 int32_t pointer_id,
312 const PointerTarget& pointer_target) { 350 const PointerTarget& pointer_target) {
313 DCHECK(!IsTrackingPointer(pointer_id)); 351 DCHECK(!IsTrackingPointer(pointer_id));
314 if (!IsObservingWindow(pointer_target.window)) 352 ObserveWindow(pointer_target.window);
315 pointer_target.window->AddObserver(this);
316 pointer_targets_[pointer_id] = pointer_target; 353 pointer_targets_[pointer_id] = pointer_target;
317 } 354 }
318 355
319 void EventDispatcher::StopTrackingPointer(int32_t pointer_id) { 356 void EventDispatcher::StopTrackingPointer(int32_t pointer_id) {
320 DCHECK(IsTrackingPointer(pointer_id)); 357 DCHECK(IsTrackingPointer(pointer_id));
321 ServerWindow* window = pointer_targets_[pointer_id].window; 358 ServerWindow* window = pointer_targets_[pointer_id].window;
322 pointer_targets_.erase(pointer_id); 359 pointer_targets_.erase(pointer_id);
323 if (window && !IsObservingWindow(window)) 360 if (window)
324 window->RemoveObserver(this); 361 UnobserveWindow(window);
325 } 362 }
326 363
327 void EventDispatcher::UpdateTargetForPointer(int32_t pointer_id, 364 void EventDispatcher::UpdateTargetForPointer(int32_t pointer_id,
328 const ui::LocatedEvent& event) { 365 const ui::LocatedEvent& event) {
329 if (!IsTrackingPointer(pointer_id)) { 366 if (!IsTrackingPointer(pointer_id)) {
330 StartTrackingPointer(pointer_id, PointerTargetForEvent(event)); 367 StartTrackingPointer(pointer_id, PointerTargetForEvent(event));
331 return; 368 return;
332 } 369 }
333 370
334 const PointerTarget pointer_target = PointerTargetForEvent(event); 371 const PointerTarget pointer_target = PointerTargetForEvent(event);
(...skipping 21 matching lines...) Expand all
356 StopTrackingPointer(pointer_id); 393 StopTrackingPointer(pointer_id);
357 StartTrackingPointer(pointer_id, pointer_target); 394 StartTrackingPointer(pointer_id, pointer_target);
358 } 395 }
359 396
360 EventDispatcher::PointerTarget EventDispatcher::PointerTargetForEvent( 397 EventDispatcher::PointerTarget EventDispatcher::PointerTargetForEvent(
361 const ui::LocatedEvent& event) const { 398 const ui::LocatedEvent& event) const {
362 PointerTarget pointer_target; 399 PointerTarget pointer_target;
363 gfx::Point location(event.location()); 400 gfx::Point location(event.location());
364 ServerWindow* target_window = 401 ServerWindow* target_window =
365 FindDeepestVisibleWindowForEvents(root_, surface_id_, &location); 402 FindDeepestVisibleWindowForEvents(root_, surface_id_, &location);
366 pointer_target.window = target_window->GetModalTarget(); 403 ServerWindow* system_modal_window = GetActiveSystemModalWindow();
404 pointer_target.window = system_modal_window ? system_modal_window
405 : target_window->GetModalTarget();
367 pointer_target.is_mouse_event = event.IsMousePointerEvent(); 406 pointer_target.is_mouse_event = event.IsMousePointerEvent();
368 pointer_target.in_nonclient_area = 407 pointer_target.in_nonclient_area =
369 target_window != pointer_target.window || 408 target_window != pointer_target.window ||
370 IsLocationInNonclientArea(pointer_target.window, location); 409 IsLocationInNonclientArea(pointer_target.window, location);
371 pointer_target.is_pointer_down = event.type() == ui::ET_POINTER_DOWN; 410 pointer_target.is_pointer_down = event.type() == ui::ET_POINTER_DOWN;
372 return pointer_target; 411 return pointer_target;
373 } 412 }
374 413
375 bool EventDispatcher::AreAnyPointersDown() const { 414 bool EventDispatcher::AreAnyPointersDown() const {
376 for (const auto& pair : pointer_targets_) { 415 for (const auto& pair : pointer_targets_) {
(...skipping 15 matching lines...) Expand all
392 transform.TransformPoint(&location); 431 transform.TransformPoint(&location);
393 std::unique_ptr<ui::Event> clone = ui::Event::Clone(event); 432 std::unique_ptr<ui::Event> clone = ui::Event::Clone(event);
394 clone->AsLocatedEvent()->set_location(location); 433 clone->AsLocatedEvent()->set_location(location);
395 // TODO(jonross): add post-target accelerator support once accelerators 434 // TODO(jonross): add post-target accelerator support once accelerators
396 // support pointer events. 435 // support pointer events.
397 delegate_->DispatchInputEventToWindow(target.window, target.in_nonclient_area, 436 delegate_->DispatchInputEventToWindow(target.window, target.in_nonclient_area,
398 *clone, nullptr); 437 *clone, nullptr);
399 } 438 }
400 439
401 void EventDispatcher::CancelPointerEventsToTarget(ServerWindow* window) { 440 void EventDispatcher::CancelPointerEventsToTarget(ServerWindow* window) {
402 window->RemoveObserver(this);
403
404 if (capture_window_ == window) { 441 if (capture_window_ == window) {
442 UnobserveWindow(window);
405 capture_window_ = nullptr; 443 capture_window_ = nullptr;
406 mouse_button_down_ = false; 444 mouse_button_down_ = false;
407 // A window only cares to be informed that it lost capture if it explicitly 445 // A window only cares to be informed that it lost capture if it explicitly
408 // requested capture. A window can lose capture if another window gains 446 // requested capture. A window can lose capture if another window gains
409 // explicit capture. 447 // explicit capture.
410 delegate_->OnServerWindowCaptureLost(window); 448 delegate_->OnServerWindowCaptureLost(window);
411 delegate_->ReleaseNativeCapture(); 449 delegate_->ReleaseNativeCapture();
412 UpdateCursorProviderByLastKnownLocation(); 450 UpdateCursorProviderByLastKnownLocation();
413 return; 451 return;
414 } 452 }
415 453
416 for (auto& pair : pointer_targets_) { 454 for (auto& pair : pointer_targets_) {
417 if (pair.second.window == window) 455 if (pair.second.window == window) {
456 UnobserveWindow(window);
418 pair.second.window = nullptr; 457 pair.second.window = nullptr;
458 }
419 } 459 }
420 } 460 }
421 461
422 bool EventDispatcher::IsObservingWindow(ServerWindow* window) { 462 void EventDispatcher::ObserveWindow(ServerWindow* window) {
423 for (const auto& pair : pointer_targets_) { 463 auto res = observed_windows_.insert(std::make_pair(window, 0u));
424 if (pair.second.window == window) 464 res.first->second++;
425 return true; 465 if (res.second)
466 window->AddObserver(this);
467 }
468
469 void EventDispatcher::UnobserveWindow(ServerWindow* window) {
470 auto it = observed_windows_.find(window);
471 DCHECK(it != observed_windows_.end());
472 DCHECK_LT(0u, it->second);
473 it->second--;
474 if (!it->second) {
475 window->RemoveObserver(this);
476 observed_windows_.erase(it);
426 } 477 }
427 return false;
428 } 478 }
429 479
430 Accelerator* EventDispatcher::FindAccelerator( 480 Accelerator* EventDispatcher::FindAccelerator(
431 const ui::KeyEvent& event, 481 const ui::KeyEvent& event,
432 const mojom::AcceleratorPhase phase) { 482 const mojom::AcceleratorPhase phase) {
433 for (const auto& pair : accelerators_) { 483 for (const auto& pair : accelerators_) {
434 if (pair.second->MatchesEvent(event, phase)) { 484 if (pair.second->MatchesEvent(event, phase)) {
435 return pair.second.get(); 485 return pair.second.get();
436 } 486 }
437 } 487 }
438 return nullptr; 488 return nullptr;
439 } 489 }
440 490
491 ServerWindow* EventDispatcher::GetActiveSystemModalWindow() const {
492 for (auto modal : system_modal_windows_) {
493 if (modal->IsDrawn())
494 return modal;
495 }
496 return nullptr;
497 }
498
499 void EventDispatcher::RemoveSystemModalWindow(ServerWindowList::iterator it) {
500 DCHECK(it != system_modal_windows_.end());
501 UnobserveWindow(*it);
502 system_modal_windows_.erase(it);
503 }
504
441 void EventDispatcher::OnWillChangeWindowHierarchy(ServerWindow* window, 505 void EventDispatcher::OnWillChangeWindowHierarchy(ServerWindow* window,
442 ServerWindow* new_parent, 506 ServerWindow* new_parent,
443 ServerWindow* old_parent) { 507 ServerWindow* old_parent) {
444 CancelPointerEventsToTarget(window); 508 CancelPointerEventsToTarget(window);
445 } 509 }
446 510
447 void EventDispatcher::OnWindowVisibilityChanged(ServerWindow* window) { 511 void EventDispatcher::OnWindowVisibilityChanged(ServerWindow* window) {
512 if (window->is_modal() && window->IsDrawn()) {
513 auto it = std::find(system_modal_windows_.begin(),
514 system_modal_windows_.end(), window);
515 DCHECK(window->transient_parent() || it != system_modal_windows_.end());
516
517 if (it != system_modal_windows_.end()) {
518 system_modal_windows_.splice(system_modal_windows_.begin(),
519 system_modal_windows_, it);
520 }
521 return;
522 }
523
448 CancelPointerEventsToTarget(window); 524 CancelPointerEventsToTarget(window);
449 } 525 }
450 526
451 void EventDispatcher::OnWindowDestroyed(ServerWindow* window) { 527 void EventDispatcher::OnWindowDestroyed(ServerWindow* window) {
452 CancelPointerEventsToTarget(window); 528 CancelPointerEventsToTarget(window);
453 529
530 auto it = std::find(system_modal_windows_.begin(),
531 system_modal_windows_.end(), window);
532 if (it != system_modal_windows_.end())
533 RemoveSystemModalWindow(it);
534
454 if (mouse_cursor_source_window_ == window) 535 if (mouse_cursor_source_window_ == window)
455 mouse_cursor_source_window_ = nullptr; 536 mouse_cursor_source_window_ = nullptr;
456 } 537 }
457 538
458 } // namespace ws 539 } // namespace ws
459 } // namespace mus 540 } // namespace mus
OLDNEW
« no previous file with comments | « components/mus/ws/event_dispatcher.h ('k') | components/mus/ws/event_dispatcher_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698