| Index: components/mus/ws/focus_controller.cc
|
| diff --git a/components/mus/ws/focus_controller.cc b/components/mus/ws/focus_controller.cc
|
| deleted file mode 100644
|
| index 5728acbe15455987b36c1dd15142cfae222c9ae4..0000000000000000000000000000000000000000
|
| --- a/components/mus/ws/focus_controller.cc
|
| +++ /dev/null
|
| @@ -1,311 +0,0 @@
|
| -// Copyright 2015 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 "components/mus/ws/focus_controller.h"
|
| -
|
| -#include "base/macros.h"
|
| -#include "components/mus/public/interfaces/window_manager.mojom.h"
|
| -#include "components/mus/ws/focus_controller_delegate.h"
|
| -#include "components/mus/ws/focus_controller_observer.h"
|
| -#include "components/mus/ws/server_window.h"
|
| -#include "components/mus/ws/server_window_drawn_tracker.h"
|
| -
|
| -namespace mus {
|
| -namespace ws {
|
| -
|
| -namespace {
|
| -
|
| -ServerWindow* GetDeepestLastDescendant(ServerWindow* window) {
|
| - while (!window->children().empty())
|
| - window = window->children().back();
|
| - return window;
|
| -}
|
| -
|
| -// This can be used to iterate over each node in a rooted tree for the purpose
|
| -// of shifting focus/activation.
|
| -class WindowTreeIterator {
|
| - public:
|
| - explicit WindowTreeIterator(ServerWindow* root) : root_(root) {}
|
| - ~WindowTreeIterator() {}
|
| -
|
| - ServerWindow* GetNext(ServerWindow* window) const {
|
| - if (window == root_ || window == nullptr)
|
| - return GetDeepestLastDescendant(root_);
|
| -
|
| - // Return the next sibling.
|
| - ServerWindow* parent = window->parent();
|
| - if (parent) {
|
| - const ServerWindow::Windows& siblings = parent->children();
|
| - ServerWindow::Windows::const_reverse_iterator iter =
|
| - std::find(siblings.rbegin(), siblings.rend(), window);
|
| - DCHECK(iter != siblings.rend());
|
| - ++iter;
|
| - if (iter != siblings.rend())
|
| - return GetDeepestLastDescendant(*iter);
|
| - }
|
| -
|
| - // All children and siblings have been explored. Next is the parent.
|
| - return parent;
|
| - }
|
| -
|
| - private:
|
| - ServerWindow* root_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(WindowTreeIterator);
|
| -};
|
| -
|
| -} // namespace
|
| -
|
| -FocusController::FocusController(FocusControllerDelegate* delegate,
|
| - ServerWindow* root)
|
| - : delegate_(delegate),
|
| - root_(root),
|
| - focused_window_(nullptr),
|
| - active_window_(nullptr),
|
| - activation_reason_(ActivationChangeReason::UNKNONW) {
|
| - DCHECK(delegate_);
|
| - DCHECK(root_);
|
| -}
|
| -
|
| -FocusController::~FocusController() {
|
| -}
|
| -
|
| -bool FocusController::SetFocusedWindow(ServerWindow* window) {
|
| - if (GetFocusedWindow() == window)
|
| - return true;
|
| -
|
| - return SetFocusedWindowImpl(FocusControllerChangeSource::EXPLICIT, window);
|
| -}
|
| -
|
| -ServerWindow* FocusController::GetFocusedWindow() {
|
| - return focused_window_;
|
| -}
|
| -
|
| -void FocusController::ActivateNextWindow() {
|
| - WindowTreeIterator iter(root_);
|
| - ServerWindow* activate = active_window_;
|
| - while (true) {
|
| - activate = iter.GetNext(activate);
|
| - if (activation_reason_ == ActivationChangeReason::CYCLE) {
|
| - if (activate == active_window_) {
|
| - // We have cycled over all the activatable windows. Remove the oldest
|
| - // window that was cycled.
|
| - if (!cycle_windows_->windows().empty()) {
|
| - cycle_windows_->Remove(cycle_windows_->windows().front());
|
| - continue;
|
| - }
|
| - } else if (cycle_windows_->Contains(activate)) {
|
| - // We are cycling between activated windows, and this window has already
|
| - // been through the cycle. So skip over it.
|
| - continue;
|
| - }
|
| - }
|
| - if (activate == active_window_ || CanBeActivated(activate))
|
| - break;
|
| - }
|
| - SetActiveWindow(activate, ActivationChangeReason::CYCLE);
|
| -
|
| - if (active_window_) {
|
| - // Do not shift focus if the focused window already lives in the active
|
| - // window.
|
| - if (focused_window_ && active_window_->Contains(focused_window_))
|
| - return;
|
| - // Focus the first focusable window in the tree.
|
| - WindowTreeIterator iter(active_window_);
|
| - ServerWindow* focus = nullptr;
|
| - do {
|
| - focus = iter.GetNext(focus);
|
| - } while (focus != active_window_ && !CanBeFocused(focus));
|
| - SetFocusedWindow(focus);
|
| - } else {
|
| - SetFocusedWindow(nullptr);
|
| - }
|
| -}
|
| -
|
| -void FocusController::AddObserver(FocusControllerObserver* observer) {
|
| - observers_.AddObserver(observer);
|
| -}
|
| -
|
| -void FocusController::RemoveObserver(FocusControllerObserver* observer) {
|
| - observers_.RemoveObserver(observer);
|
| -}
|
| -
|
| -void FocusController::SetActiveWindow(ServerWindow* window,
|
| - ActivationChangeReason reason) {
|
| - DCHECK(!window || CanBeActivated(window));
|
| - if (active_window_ == window)
|
| - return;
|
| - if (reason != ActivationChangeReason::CYCLE) {
|
| - cycle_windows_.reset();
|
| - } else if (activation_reason_ != ActivationChangeReason::CYCLE) {
|
| - DCHECK(!cycle_windows_);
|
| - cycle_windows_.reset(new ServerWindowTracker());
|
| - if (active_window_)
|
| - cycle_windows_->Add(active_window_);
|
| - }
|
| -
|
| - ServerWindow* old_active = active_window_;
|
| - active_window_ = window;
|
| - activation_reason_ = reason;
|
| - FOR_EACH_OBSERVER(FocusControllerObserver, observers_,
|
| - OnActivationChanged(old_active, active_window_));
|
| - if (active_window_ && activation_reason_ == ActivationChangeReason::CYCLE)
|
| - cycle_windows_->Add(active_window_);
|
| -}
|
| -
|
| -bool FocusController::CanBeFocused(ServerWindow* window) const {
|
| - // All ancestors of |window| must be drawn, and be focusable.
|
| - for (ServerWindow* w = window; w; w = w->parent()) {
|
| - if (!w->IsDrawn())
|
| - return false;
|
| - if (!w->can_focus())
|
| - return false;
|
| - }
|
| -
|
| - // |window| must be a descendent of an activatable window.
|
| - return GetActivatableAncestorOf(window) != nullptr;
|
| -}
|
| -
|
| -bool FocusController::CanBeActivated(ServerWindow* window) const {
|
| - DCHECK(window);
|
| - // A detached window cannot be activated.
|
| - if (!root_->Contains(window))
|
| - return false;
|
| -
|
| - // The parent window must be allowed to have active children.
|
| - if (!delegate_->CanHaveActiveChildren(window->parent()))
|
| - return false;
|
| -
|
| - if (!window->can_focus())
|
| - return false;
|
| -
|
| - // The window must be drawn, or if it's not drawn, it must be minimized.
|
| - if (!window->IsDrawn()) {
|
| - bool is_minimized = false;
|
| - const ServerWindow::Properties& props = window->properties();
|
| - if (props.count(mojom::WindowManager::kShowState_Property)) {
|
| - is_minimized =
|
| - props.find(mojom::WindowManager::kShowState_Property)->second[0] ==
|
| - static_cast<int>(mus::mojom::ShowState::MINIMIZED);
|
| - }
|
| - if (!is_minimized)
|
| - return false;
|
| - }
|
| -
|
| - // TODO(sad): If there's a transient modal window, then this cannot be
|
| - // activated.
|
| - return true;
|
| -}
|
| -
|
| -ServerWindow* FocusController::GetActivatableAncestorOf(
|
| - ServerWindow* window) const {
|
| - for (ServerWindow* w = window; w; w = w->parent()) {
|
| - if (CanBeActivated(w))
|
| - return w;
|
| - }
|
| - return nullptr;
|
| -}
|
| -
|
| -bool FocusController::SetFocusedWindowImpl(
|
| - FocusControllerChangeSource change_source,
|
| - ServerWindow* window) {
|
| - if (window && !CanBeFocused(window))
|
| - return false;
|
| -
|
| - ServerWindow* old_focused = GetFocusedWindow();
|
| -
|
| - DCHECK(!window || window->IsDrawn());
|
| -
|
| - // Activate the closest activatable ancestor window.
|
| - // TODO(sad): The window to activate doesn't necessarily have to be a direct
|
| - // ancestor (e.g. could be a transient parent).
|
| - SetActiveWindow(GetActivatableAncestorOf(window),
|
| - ActivationChangeReason::FOCUS);
|
| -
|
| - FOR_EACH_OBSERVER(FocusControllerObserver, observers_,
|
| - OnFocusChanged(change_source, old_focused, window));
|
| -
|
| - focused_window_ = window;
|
| - // We can currently use only a single ServerWindowDrawnTracker since focused
|
| - // window is expected to be a direct descendant of the active window.
|
| - if (focused_window_ && active_window_) {
|
| - DCHECK(active_window_->Contains(focused_window_));
|
| - }
|
| - ServerWindow* track_window = focused_window_;
|
| - if (!track_window)
|
| - track_window = active_window_;
|
| - if (track_window)
|
| - drawn_tracker_.reset(new ServerWindowDrawnTracker(track_window, this));
|
| - else
|
| - drawn_tracker_.reset();
|
| - return true;
|
| -}
|
| -
|
| -void FocusController::OnDrawnStateWillChange(ServerWindow* ancestor,
|
| - ServerWindow* window,
|
| - bool is_drawn) {
|
| - DCHECK(!is_drawn);
|
| - DCHECK_NE(ancestor, window);
|
| - DCHECK(root_->Contains(window));
|
| - drawn_tracker_.reset();
|
| -
|
| - // Find the window that triggered this state-change notification.
|
| - ServerWindow* trigger = window;
|
| - while (trigger->parent() != ancestor)
|
| - trigger = trigger->parent();
|
| - DCHECK(trigger);
|
| - auto will_be_hidden = [trigger](ServerWindow* w) {
|
| - return trigger->Contains(w);
|
| - };
|
| -
|
| - // If |window| is |active_window_|, then activate the next activatable window
|
| - // that does not belong to the subtree which is getting hidden.
|
| - if (window == active_window_) {
|
| - WindowTreeIterator iter(root_);
|
| - ServerWindow* activate = active_window_;
|
| - do {
|
| - activate = iter.GetNext(activate);
|
| - } while (activate != active_window_ &&
|
| - (will_be_hidden(activate) || !CanBeActivated(activate)));
|
| - if (activate == window)
|
| - activate = nullptr;
|
| - SetActiveWindow(activate, ActivationChangeReason::DRAWN_STATE_CHANGED);
|
| -
|
| - // Now make sure focus is in the active window.
|
| - ServerWindow* focus = nullptr;
|
| - if (active_window_) {
|
| - WindowTreeIterator iter(active_window_);
|
| - focus = nullptr;
|
| - do {
|
| - focus = iter.GetNext(focus);
|
| - } while (focus != active_window_ &&
|
| - (will_be_hidden(focus) || !CanBeFocused(focus)));
|
| - DCHECK(focus && CanBeFocused(focus));
|
| - }
|
| - SetFocusedWindowImpl(FocusControllerChangeSource::DRAWN_STATE_CHANGED,
|
| - focus);
|
| - return;
|
| - }
|
| -
|
| - // Move focus to the next focusable window in |active_window_|.
|
| - DCHECK_EQ(focused_window_, window);
|
| - WindowTreeIterator iter(active_window_);
|
| - ServerWindow* focus = focused_window_;
|
| - do {
|
| - focus = iter.GetNext(focus);
|
| - } while (focus != focused_window_ &&
|
| - (will_be_hidden(focus) || !CanBeFocused(focus)));
|
| - if (focus == window)
|
| - focus = nullptr;
|
| - SetFocusedWindowImpl(FocusControllerChangeSource::DRAWN_STATE_CHANGED, focus);
|
| -}
|
| -
|
| -void FocusController::OnDrawnStateChanged(ServerWindow* ancestor,
|
| - ServerWindow* window,
|
| - bool is_drawn) {
|
| - // DCHECK(false); TODO(sadrul):
|
| -}
|
| -
|
| -} // namespace ws
|
| -} // namespace mus
|
|
|