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

Unified Diff: components/mus/ws/focus_controller.cc

Issue 1560063003: mus: Fix activation cycle direction. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 11 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 side-by-side diff with in-line comments
Download patch
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;

Powered by Google App Engine
This is Rietveld 408576698