| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "services/ui/ws/modal_window_controller.h" |
| |
| #include "base/memory/ptr_util.h" |
| #include "base/stl_util.h" |
| #include "services/ui/ws/event_dispatcher.h" |
| #include "services/ui/ws/server_window.h" |
| #include "services/ui/ws/server_window_drawn_tracker.h" |
| |
| namespace ui { |
| namespace ws { |
| namespace { |
| |
| const ServerWindow* GetModalChildForWindowAncestor(const ServerWindow* window) { |
| for (const ServerWindow* ancestor = window; ancestor; |
| ancestor = ancestor->parent()) { |
| for (auto* transient_child : ancestor->transient_children()) { |
| if (transient_child->is_modal() && transient_child->IsDrawn()) |
| return transient_child; |
| } |
| } |
| return nullptr; |
| } |
| |
| const ServerWindow* GetWindowModalTargetForWindow(const ServerWindow* window) { |
| const ServerWindow* modal_window = GetModalChildForWindowAncestor(window); |
| if (!modal_window) |
| return window; |
| return GetWindowModalTargetForWindow(modal_window); |
| } |
| |
| } // namespace |
| |
| ModalWindowController::ModalWindowController(EventDispatcher* event_dispatcher) |
| : event_dispatcher_(event_dispatcher) {} |
| |
| ModalWindowController::~ModalWindowController() { |
| for (auto it = system_modal_windows_.begin(); |
| it != system_modal_windows_.end(); it++) { |
| (*it)->RemoveObserver(this); |
| } |
| } |
| |
| void ModalWindowController::AddSystemModalWindow(ServerWindow* window) { |
| DCHECK(window); |
| DCHECK(!base::ContainsValue(system_modal_windows_, window)); |
| |
| window->SetModal(); |
| system_modal_windows_.push_back(window); |
| window_drawn_trackers_.insert(make_pair( |
| window, base::MakeUnique<ServerWindowDrawnTracker>(window, this))); |
| window->AddObserver(this); |
| |
| event_dispatcher_->ReleaseCaptureBlockedByModalWindow(window); |
| } |
| |
| bool ModalWindowController::IsWindowBlockedBy( |
| const ServerWindow* window, |
| const ServerWindow* modal_window) const { |
| DCHECK(window); |
| DCHECK(modal_window); |
| if (!modal_window->is_modal() || !modal_window->IsDrawn()) |
| return false; |
| |
| if (modal_window->transient_parent() && |
| !modal_window->transient_parent()->Contains(window)) { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool ModalWindowController::IsWindowBlocked(const ServerWindow* window) const { |
| DCHECK(window); |
| return GetActiveSystemModalWindow() || GetModalChildForWindowAncestor(window); |
| } |
| |
| const ServerWindow* ModalWindowController::GetTargetForWindow( |
| const ServerWindow* window) const { |
| ServerWindow* system_modal_window = GetActiveSystemModalWindow(); |
| if (system_modal_window) |
| return system_modal_window; |
| return window ? GetWindowModalTargetForWindow(window) : nullptr; |
| } |
| |
| ServerWindow* ModalWindowController::GetActiveSystemModalWindow() const { |
| for (auto it = system_modal_windows_.rbegin(); |
| it != system_modal_windows_.rend(); it++) { |
| ServerWindow* modal = *it; |
| if (modal->IsDrawn()) |
| return modal; |
| } |
| return nullptr; |
| } |
| |
| void ModalWindowController::OnWindowDestroyed(ServerWindow* window) { |
| window->RemoveObserver(this); |
| auto it = std::find(system_modal_windows_.begin(), |
| system_modal_windows_.end(), window); |
| DCHECK(it != system_modal_windows_.end()); |
| system_modal_windows_.erase(it); |
| window_drawn_trackers_.erase(window); |
| } |
| |
| void ModalWindowController::OnDrawnStateChanged(ServerWindow* ancestor, |
| ServerWindow* window, |
| bool is_drawn) { |
| if (!is_drawn) |
| return; |
| |
| // Move the most recently shown window to the end of the list. |
| auto it = std::find(system_modal_windows_.begin(), |
| system_modal_windows_.end(), window); |
| DCHECK(it != system_modal_windows_.end()); |
| system_modal_windows_.splice(system_modal_windows_.end(), |
| system_modal_windows_, it); |
| } |
| |
| } // namespace ws |
| } // namespace ui |