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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/mus/ws/focus_controller.h" 5 #include "components/mus/ws/focus_controller.h"
6 6
7 #include "base/macros.h" 7 #include "base/macros.h"
8 #include "components/mus/public/interfaces/window_manager.mojom.h" 8 #include "components/mus/public/interfaces/window_manager.mojom.h"
9 #include "components/mus/ws/focus_controller_delegate.h" 9 #include "components/mus/ws/focus_controller_delegate.h"
10 #include "components/mus/ws/focus_controller_observer.h" 10 #include "components/mus/ws/focus_controller_observer.h"
11 #include "components/mus/ws/server_window.h" 11 #include "components/mus/ws/server_window.h"
12 #include "components/mus/ws/server_window_drawn_tracker.h" 12 #include "components/mus/ws/server_window_drawn_tracker.h"
13 13
14 namespace mus { 14 namespace mus {
15 namespace ws { 15 namespace ws {
16 16
17 namespace { 17 namespace {
18 18
19 ServerWindow* GetDeepestFirstDescendant(ServerWindow* window) { 19 ServerWindow* GetDeepestFirstDescendant(ServerWindow* window) {
sky 2016/01/05 16:42:38 Update function name to reflect new meaning.
20 while (!window->children().empty()) 20 while (!window->children().empty())
21 window = window->children()[0]; 21 window = window->children().back();
22 return window; 22 return window;
23 } 23 }
24 24
25 // This can be used to iterate over each node in a rooted tree for the purpose 25 // This can be used to iterate over each node in a rooted tree for the purpose
26 // of shifting focus/activation. 26 // of shifting focus/activation.
27 class WindowTreeIterator { 27 class WindowTreeIterator {
28 public: 28 public:
29 explicit WindowTreeIterator(ServerWindow* root) : root_(root) {} 29 explicit WindowTreeIterator(ServerWindow* root) : root_(root) {}
30 ~WindowTreeIterator() {} 30 ~WindowTreeIterator() {}
31 31
32 ServerWindow* GetNext(ServerWindow* window) const { 32 ServerWindow* GetNext(ServerWindow* window) const {
33 if (window == root_ || window == nullptr) 33 if (window == root_ || window == nullptr)
34 return GetDeepestFirstDescendant(root_); 34 return GetDeepestFirstDescendant(root_);
35 35
36 // Return the next sibling. 36 // Return the next sibling.
37 ServerWindow* parent = window->parent(); 37 ServerWindow* parent = window->parent();
38 if (parent) { 38 if (parent) {
39 const ServerWindow::Windows& siblings = parent->children(); 39 const ServerWindow::Windows& siblings = parent->children();
40 ServerWindow::Windows::const_iterator iter = 40 ServerWindow::Windows::const_reverse_iterator iter =
41 std::find(siblings.begin(), siblings.end(), window); 41 std::find(siblings.rbegin(), siblings.rend(), window);
42 DCHECK(iter != siblings.end()); 42 DCHECK(iter != siblings.rend());
43 ++iter; 43 ++iter;
44 if (iter != siblings.end()) 44 if (iter != siblings.rend())
45 return GetDeepestFirstDescendant(*iter); 45 return GetDeepestFirstDescendant(*iter);
46 } 46 }
47 47
48 // All children and siblings have been explored. Next is the parent. 48 // All children and siblings have been explored. Next is the parent.
49 return parent; 49 return parent;
50 } 50 }
51 51
52 private: 52 private:
53 ServerWindow* root_; 53 ServerWindow* root_;
54 54
55 DISALLOW_COPY_AND_ASSIGN(WindowTreeIterator); 55 DISALLOW_COPY_AND_ASSIGN(WindowTreeIterator);
56 }; 56 };
57 57
58 } // namespace 58 } // namespace
59 59
60 FocusController::FocusController(FocusControllerDelegate* delegate, 60 FocusController::FocusController(FocusControllerDelegate* delegate,
61 ServerWindow* root) 61 ServerWindow* root)
62 : delegate_(delegate), 62 : delegate_(delegate),
63 root_(root), 63 root_(root),
64 focused_window_(nullptr), 64 focused_window_(nullptr),
65 active_window_(nullptr) { 65 active_window_(nullptr),
66 activation_reason_(ActivationChangeReason::UNKNONW) {
66 DCHECK(delegate_); 67 DCHECK(delegate_);
67 DCHECK(root_); 68 DCHECK(root_);
68 } 69 }
69 70
70 FocusController::~FocusController() {} 71 FocusController::~FocusController() {}
71 72
72 void FocusController::SetFocusedWindow(ServerWindow* window) { 73 void FocusController::SetFocusedWindow(ServerWindow* window) {
73 if (GetFocusedWindow() == window) 74 if (GetFocusedWindow() == window)
74 return; 75 return;
75 76
76 SetFocusedWindowImpl(FocusControllerChangeSource::EXPLICIT, window); 77 SetFocusedWindowImpl(FocusControllerChangeSource::EXPLICIT, window);
77 } 78 }
78 79
79 ServerWindow* FocusController::GetFocusedWindow() { 80 ServerWindow* FocusController::GetFocusedWindow() {
80 return focused_window_; 81 return focused_window_;
81 } 82 }
82 83
83 void FocusController::ActivateNextWindow() { 84 void FocusController::ActivateNextWindow() {
84 WindowTreeIterator iter(root_); 85 WindowTreeIterator iter(root_);
85 ServerWindow* activate = active_window_; 86 ServerWindow* activate = active_window_;
86 do { 87 while (true) {
87 activate = iter.GetNext(activate); 88 activate = iter.GetNext(activate);
88 } while (activate != active_window_ && !CanBeActivated(activate)); 89 if (activation_reason_ == ActivationChangeReason::CYCLE) {
89 SetActiveWindow(activate); 90 if (activate == active_window_) {
91 // We have cycled over all the activatable windows. Remove the oldest
92 // window that was cycled.
93 if (!cycle_windows_.empty()) {
94 cycle_windows_.erase(cycle_windows_.begin());
95 continue;
96 }
97 } else if (std::find(cycle_windows_.begin(), cycle_windows_.end(),
98 activate->id()) != cycle_windows_.end()) {
99 // We are cycling between activated windows, and this window has already
100 // been through the cycle. So skip over it.
101 continue;
102 }
103 }
104 if (activate == active_window_ || CanBeActivated(activate))
105 break;
106 }
107 SetActiveWindow(activate, ActivationChangeReason::CYCLE);
90 108
91 if (active_window_) { 109 if (active_window_) {
92 // Do not shift focus if the focused window already lives in the active 110 // Do not shift focus if the focused window already lives in the active
93 // window. 111 // window.
94 if (focused_window_ && active_window_->Contains(focused_window_)) 112 if (focused_window_ && active_window_->Contains(focused_window_))
95 return; 113 return;
96 // Focus the first focusable window in the tree. 114 // Focus the first focusable window in the tree.
97 WindowTreeIterator iter(active_window_); 115 WindowTreeIterator iter(active_window_);
98 ServerWindow* focus = nullptr; 116 ServerWindow* focus = nullptr;
99 do { 117 do {
100 focus = iter.GetNext(focus); 118 focus = iter.GetNext(focus);
101 } while (focus != active_window_ && !CanBeFocused(focus)); 119 } while (focus != active_window_ && !CanBeFocused(focus));
102 SetFocusedWindow(focus); 120 SetFocusedWindow(focus);
103 } else { 121 } else {
104 SetFocusedWindow(nullptr); 122 SetFocusedWindow(nullptr);
105 } 123 }
106 } 124 }
107 125
108 void FocusController::AddObserver(FocusControllerObserver* observer) { 126 void FocusController::AddObserver(FocusControllerObserver* observer) {
109 observers_.AddObserver(observer); 127 observers_.AddObserver(observer);
110 } 128 }
111 129
112 void FocusController::RemoveObserver(FocusControllerObserver* observer) { 130 void FocusController::RemoveObserver(FocusControllerObserver* observer) {
113 observers_.RemoveObserver(observer); 131 observers_.RemoveObserver(observer);
114 } 132 }
115 133
116 void FocusController::SetActiveWindow(ServerWindow* window) { 134 void FocusController::SetActiveWindow(ServerWindow* window,
135 ActivationChangeReason reason) {
117 DCHECK(!window || CanBeActivated(window)); 136 DCHECK(!window || CanBeActivated(window));
118 if (active_window_ == window) 137 if (active_window_ == window)
119 return; 138 return;
139 if (reason != ActivationChangeReason::CYCLE) {
140 cycle_windows_.clear();
141 } else if (activation_reason_ != ActivationChangeReason::CYCLE) {
142 DCHECK(cycle_windows_.empty());
143 if (active_window_)
144 cycle_windows_.push_back(active_window_->id());
145 }
146
120 ServerWindow* old_active = active_window_; 147 ServerWindow* old_active = active_window_;
121 active_window_ = window; 148 active_window_ = window;
122 if (old_active != active_window_) { 149 activation_reason_ = reason;
123 FOR_EACH_OBSERVER(FocusControllerObserver, observers_, 150 FOR_EACH_OBSERVER(FocusControllerObserver, observers_,
124 OnActivationChanged(old_active, active_window_)); 151 OnActivationChanged(old_active, active_window_));
125 } 152 if (active_window_ && activation_reason_ == ActivationChangeReason::CYCLE)
153 cycle_windows_.push_back(active_window_->id());
126 } 154 }
127 155
128 bool FocusController::CanBeFocused(ServerWindow* window) const { 156 bool FocusController::CanBeFocused(ServerWindow* window) const {
129 // All ancestors of |window| must be drawn, and be focusable. 157 // All ancestors of |window| must be drawn, and be focusable.
130 for (ServerWindow* w = window; w; w = w->parent()) { 158 for (ServerWindow* w = window; w; w = w->parent()) {
131 if (!w->IsDrawn()) 159 if (!w->IsDrawn())
132 return false; 160 return false;
133 if (!w->can_focus()) 161 if (!w->can_focus())
134 return false; 162 return false;
135 } 163 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 ServerWindow* window) { 208 ServerWindow* window) {
181 if (window && !CanBeFocused(window)) 209 if (window && !CanBeFocused(window))
182 return; 210 return;
183 ServerWindow* old_focused = GetFocusedWindow(); 211 ServerWindow* old_focused = GetFocusedWindow();
184 212
185 DCHECK(!window || window->IsDrawn()); 213 DCHECK(!window || window->IsDrawn());
186 214
187 // Activate the closest activatable ancestor window. 215 // Activate the closest activatable ancestor window.
188 // TODO(sad): The window to activate doesn't necessarily have to be a direct 216 // TODO(sad): The window to activate doesn't necessarily have to be a direct
189 // ancestor (e.g. could be a transient parent). 217 // ancestor (e.g. could be a transient parent).
190 SetActiveWindow(GetActivatableAncestorOf(window)); 218 SetActiveWindow(GetActivatableAncestorOf(window),
219 ActivationChangeReason::FOCUS);
191 220
192 FOR_EACH_OBSERVER(FocusControllerObserver, observers_, 221 FOR_EACH_OBSERVER(FocusControllerObserver, observers_,
193 OnFocusChanged(change_source, old_focused, window)); 222 OnFocusChanged(change_source, old_focused, window));
194 223
195 focused_window_ = window; 224 focused_window_ = window;
196 // We can currently use only a single ServerWindowDrawnTracker since focused 225 // We can currently use only a single ServerWindowDrawnTracker since focused
197 // window is expected to be a direct descendant of the active window. 226 // window is expected to be a direct descendant of the active window.
198 if (focused_window_ && active_window_) { 227 if (focused_window_ && active_window_) {
199 DCHECK(active_window_->Contains(focused_window_)); 228 DCHECK(active_window_->Contains(focused_window_));
200 } 229 }
(...skipping 21 matching lines...) Expand all
222 // that does not belong to the subtree which is getting hidden. 251 // that does not belong to the subtree which is getting hidden.
223 if (window == active_window_) { 252 if (window == active_window_) {
224 WindowTreeIterator iter(root_); 253 WindowTreeIterator iter(root_);
225 ServerWindow* activate = active_window_; 254 ServerWindow* activate = active_window_;
226 do { 255 do {
227 activate = iter.GetNext(activate); 256 activate = iter.GetNext(activate);
228 } while (activate != active_window_ && 257 } while (activate != active_window_ &&
229 (will_be_hidden(activate) || !CanBeActivated(activate))); 258 (will_be_hidden(activate) || !CanBeActivated(activate)));
230 if (activate == window) 259 if (activate == window)
231 activate = nullptr; 260 activate = nullptr;
232 SetActiveWindow(activate); 261 SetActiveWindow(activate, ActivationChangeReason::DRAWN_STATE_CHANGED);
233 262
234 // Now make sure focus is in the active window. 263 // Now make sure focus is in the active window.
235 ServerWindow* focus = nullptr; 264 ServerWindow* focus = nullptr;
236 if (active_window_) { 265 if (active_window_) {
237 WindowTreeIterator iter(active_window_); 266 WindowTreeIterator iter(active_window_);
238 focus = nullptr; 267 focus = nullptr;
239 do { 268 do {
240 focus = iter.GetNext(focus); 269 focus = iter.GetNext(focus);
241 } while (focus != active_window_ && 270 } while (focus != active_window_ &&
242 (will_be_hidden(focus) || !CanBeFocused(focus))); 271 (will_be_hidden(focus) || !CanBeFocused(focus)));
(...skipping 18 matching lines...) Expand all
261 } 290 }
262 291
263 void FocusController::OnDrawnStateChanged(ServerWindow* ancestor, 292 void FocusController::OnDrawnStateChanged(ServerWindow* ancestor,
264 ServerWindow* window, 293 ServerWindow* window,
265 bool is_drawn) { 294 bool is_drawn) {
266 DCHECK(false); 295 DCHECK(false);
267 } 296 }
268 297
269 } // namespace ws 298 } // namespace ws
270 } // namespace mus 299 } // namespace mus
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698