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..c7cf231eabcad15156e4929bf7c48c63137a0a0a 100644 |
--- a/components/mus/ws/focus_controller.cc |
+++ b/components/mus/ws/focus_controller.cc |
@@ -18,7 +18,7 @@ namespace { |
ServerWindow* GetDeepestFirstDescendant(ServerWindow* window) { |
sky
2016/01/05 16:42:38
Update function name to reflect new meaning.
|
while (!window->children().empty()) |
- window = window->children()[0]; |
+ window = window->children().back(); |
return window; |
} |
@@ -37,11 +37,11 @@ class WindowTreeIterator { |
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()) |
+ if (iter != siblings.rend()) |
return GetDeepestFirstDescendant(*iter); |
} |
@@ -62,7 +62,8 @@ 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_); |
} |
@@ -83,10 +84,27 @@ 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_.empty()) { |
+ cycle_windows_.erase(cycle_windows_.begin()); |
+ continue; |
+ } |
+ } else if (std::find(cycle_windows_.begin(), cycle_windows_.end(), |
+ activate->id()) != cycle_windows_.end()) { |
+ // 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,26 @@ 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_.clear(); |
+ } else if (activation_reason_ != ActivationChangeReason::CYCLE) { |
+ DCHECK(cycle_windows_.empty()); |
+ if (active_window_) |
+ cycle_windows_.push_back(active_window_->id()); |
+ } |
+ |
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_.push_back(active_window_->id()); |
} |
bool FocusController::CanBeFocused(ServerWindow* window) const { |
@@ -187,7 +215,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 +258,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; |