| Index: components/mus/ws/focus_controller.cc
|
| diff --git a/components/mus/ws/focus_controller.cc b/components/mus/ws/focus_controller.cc
|
| index 5cf98446e9a526548a9dd4164bbcb01010906942..6b01883fcd1442706d524ad9b1697504265e8555 100644
|
| --- a/components/mus/ws/focus_controller.cc
|
| +++ b/components/mus/ws/focus_controller.cc
|
| @@ -16,9 +16,9 @@ namespace ws {
|
|
|
| namespace {
|
|
|
| -ServerWindow* GetDeepestFirstDescendant(ServerWindow* window) {
|
| +ServerWindow* GetDeepestLastDescendant(ServerWindow* window) {
|
| while (!window->children().empty())
|
| - window = window->children()[0];
|
| + window = window->children().back();
|
| return window;
|
| }
|
|
|
| @@ -31,18 +31,18 @@ class WindowTreeIterator {
|
|
|
| ServerWindow* GetNext(ServerWindow* window) const {
|
| if (window == root_ || window == nullptr)
|
| - return GetDeepestFirstDescendant(root_);
|
| + return GetDeepestLastDescendant(root_);
|
|
|
| // Return the next sibling.
|
| ServerWindow* parent = window->parent();
|
| if (parent) {
|
| const ServerWindow::Windows& siblings = parent->children();
|
| - ServerWindow::Windows::const_iterator iter =
|
| - std::find(siblings.begin(), siblings.end(), window);
|
| - DCHECK(iter != siblings.end());
|
| + ServerWindow::Windows::const_reverse_iterator iter =
|
| + std::find(siblings.rbegin(), siblings.rend(), window);
|
| + DCHECK(iter != siblings.rend());
|
| ++iter;
|
| - if (iter != siblings.end())
|
| - return GetDeepestFirstDescendant(*iter);
|
| + if (iter != siblings.rend())
|
| + return GetDeepestLastDescendant(*iter);
|
| }
|
|
|
| // All children and siblings have been explored. Next is the parent.
|
| @@ -62,12 +62,14 @@ FocusController::FocusController(FocusControllerDelegate* delegate,
|
| : delegate_(delegate),
|
| root_(root),
|
| focused_window_(nullptr),
|
| - active_window_(nullptr) {
|
| + active_window_(nullptr),
|
| + activation_reason_(ActivationChangeReason::UNKNONW) {
|
| DCHECK(delegate_);
|
| DCHECK(root_);
|
| }
|
|
|
| -FocusController::~FocusController() {}
|
| +FocusController::~FocusController() {
|
| +}
|
|
|
| void FocusController::SetFocusedWindow(ServerWindow* window) {
|
| if (GetFocusedWindow() == window)
|
| @@ -83,10 +85,26 @@ ServerWindow* FocusController::GetFocusedWindow() {
|
| void FocusController::ActivateNextWindow() {
|
| WindowTreeIterator iter(root_);
|
| ServerWindow* activate = active_window_;
|
| - do {
|
| + while (true) {
|
| activate = iter.GetNext(activate);
|
| - } while (activate != active_window_ && !CanBeActivated(activate));
|
| - SetActiveWindow(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
|
| @@ -113,16 +131,27 @@ void FocusController::RemoveObserver(FocusControllerObserver* observer) {
|
| observers_.RemoveObserver(observer);
|
| }
|
|
|
| -void FocusController::SetActiveWindow(ServerWindow* window) {
|
| +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;
|
| - if (old_active != active_window_) {
|
| - FOR_EACH_OBSERVER(FocusControllerObserver, observers_,
|
| - OnActivationChanged(old_active, active_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 {
|
| @@ -187,7 +216,8 @@ void FocusController::SetFocusedWindowImpl(
|
| // 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));
|
| + SetActiveWindow(GetActivatableAncestorOf(window),
|
| + ActivationChangeReason::FOCUS);
|
|
|
| FOR_EACH_OBSERVER(FocusControllerObserver, observers_,
|
| OnFocusChanged(change_source, old_focused, window));
|
| @@ -229,7 +259,7 @@ void FocusController::OnDrawnStateWillChange(ServerWindow* ancestor,
|
| (will_be_hidden(activate) || !CanBeActivated(activate)));
|
| if (activate == window)
|
| activate = nullptr;
|
| - SetActiveWindow(activate);
|
| + SetActiveWindow(activate, ActivationChangeReason::DRAWN_STATE_CHANGED);
|
|
|
| // Now make sure focus is in the active window.
|
| ServerWindow* focus = nullptr;
|
|
|