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

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: tot.merge 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
« no previous file with comments | « components/mus/ws/focus_controller.h ('k') | components/mus/ws/focus_controller_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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* GetDeepestLastDescendant(ServerWindow* window) {
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 GetDeepestLastDescendant(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 GetDeepestLastDescendant(*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() {
72 }
71 73
72 void FocusController::SetFocusedWindow(ServerWindow* window) { 74 void FocusController::SetFocusedWindow(ServerWindow* window) {
73 if (GetFocusedWindow() == window) 75 if (GetFocusedWindow() == window)
74 return; 76 return;
75 77
76 SetFocusedWindowImpl(FocusControllerChangeSource::EXPLICIT, window); 78 SetFocusedWindowImpl(FocusControllerChangeSource::EXPLICIT, window);
77 } 79 }
78 80
79 ServerWindow* FocusController::GetFocusedWindow() { 81 ServerWindow* FocusController::GetFocusedWindow() {
80 return focused_window_; 82 return focused_window_;
81 } 83 }
82 84
83 void FocusController::ActivateNextWindow() { 85 void FocusController::ActivateNextWindow() {
84 WindowTreeIterator iter(root_); 86 WindowTreeIterator iter(root_);
85 ServerWindow* activate = active_window_; 87 ServerWindow* activate = active_window_;
86 do { 88 while (true) {
87 activate = iter.GetNext(activate); 89 activate = iter.GetNext(activate);
88 } while (activate != active_window_ && !CanBeActivated(activate)); 90 if (activation_reason_ == ActivationChangeReason::CYCLE) {
89 SetActiveWindow(activate); 91 if (activate == active_window_) {
92 // We have cycled over all the activatable windows. Remove the oldest
93 // window that was cycled.
94 if (!cycle_windows_->windows().empty()) {
95 cycle_windows_->Remove(cycle_windows_->windows().front());
96 continue;
97 }
98 } else if (cycle_windows_->Contains(activate)) {
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_.reset();
141 } else if (activation_reason_ != ActivationChangeReason::CYCLE) {
142 DCHECK(!cycle_windows_);
143 cycle_windows_.reset(new ServerWindowTracker());
144 if (active_window_)
145 cycle_windows_->Add(active_window_);
146 }
147
120 ServerWindow* old_active = active_window_; 148 ServerWindow* old_active = active_window_;
121 active_window_ = window; 149 active_window_ = window;
122 if (old_active != active_window_) { 150 activation_reason_ = reason;
123 FOR_EACH_OBSERVER(FocusControllerObserver, observers_, 151 FOR_EACH_OBSERVER(FocusControllerObserver, observers_,
124 OnActivationChanged(old_active, active_window_)); 152 OnActivationChanged(old_active, active_window_));
125 } 153 if (active_window_ && activation_reason_ == ActivationChangeReason::CYCLE)
154 cycle_windows_->Add(active_window_);
126 } 155 }
127 156
128 bool FocusController::CanBeFocused(ServerWindow* window) const { 157 bool FocusController::CanBeFocused(ServerWindow* window) const {
129 // All ancestors of |window| must be drawn, and be focusable. 158 // All ancestors of |window| must be drawn, and be focusable.
130 for (ServerWindow* w = window; w; w = w->parent()) { 159 for (ServerWindow* w = window; w; w = w->parent()) {
131 if (!w->IsDrawn()) 160 if (!w->IsDrawn())
132 return false; 161 return false;
133 if (!w->can_focus()) 162 if (!w->can_focus())
134 return false; 163 return false;
135 } 164 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 ServerWindow* window) { 209 ServerWindow* window) {
181 if (window && !CanBeFocused(window)) 210 if (window && !CanBeFocused(window))
182 return; 211 return;
183 ServerWindow* old_focused = GetFocusedWindow(); 212 ServerWindow* old_focused = GetFocusedWindow();
184 213
185 DCHECK(!window || window->IsDrawn()); 214 DCHECK(!window || window->IsDrawn());
186 215
187 // Activate the closest activatable ancestor window. 216 // Activate the closest activatable ancestor window.
188 // TODO(sad): The window to activate doesn't necessarily have to be a direct 217 // TODO(sad): The window to activate doesn't necessarily have to be a direct
189 // ancestor (e.g. could be a transient parent). 218 // ancestor (e.g. could be a transient parent).
190 SetActiveWindow(GetActivatableAncestorOf(window)); 219 SetActiveWindow(GetActivatableAncestorOf(window),
220 ActivationChangeReason::FOCUS);
191 221
192 FOR_EACH_OBSERVER(FocusControllerObserver, observers_, 222 FOR_EACH_OBSERVER(FocusControllerObserver, observers_,
193 OnFocusChanged(change_source, old_focused, window)); 223 OnFocusChanged(change_source, old_focused, window));
194 224
195 focused_window_ = window; 225 focused_window_ = window;
196 // We can currently use only a single ServerWindowDrawnTracker since focused 226 // We can currently use only a single ServerWindowDrawnTracker since focused
197 // window is expected to be a direct descendant of the active window. 227 // window is expected to be a direct descendant of the active window.
198 if (focused_window_ && active_window_) { 228 if (focused_window_ && active_window_) {
199 DCHECK(active_window_->Contains(focused_window_)); 229 DCHECK(active_window_->Contains(focused_window_));
200 } 230 }
(...skipping 21 matching lines...) Expand all
222 // that does not belong to the subtree which is getting hidden. 252 // that does not belong to the subtree which is getting hidden.
223 if (window == active_window_) { 253 if (window == active_window_) {
224 WindowTreeIterator iter(root_); 254 WindowTreeIterator iter(root_);
225 ServerWindow* activate = active_window_; 255 ServerWindow* activate = active_window_;
226 do { 256 do {
227 activate = iter.GetNext(activate); 257 activate = iter.GetNext(activate);
228 } while (activate != active_window_ && 258 } while (activate != active_window_ &&
229 (will_be_hidden(activate) || !CanBeActivated(activate))); 259 (will_be_hidden(activate) || !CanBeActivated(activate)));
230 if (activate == window) 260 if (activate == window)
231 activate = nullptr; 261 activate = nullptr;
232 SetActiveWindow(activate); 262 SetActiveWindow(activate, ActivationChangeReason::DRAWN_STATE_CHANGED);
233 263
234 // Now make sure focus is in the active window. 264 // Now make sure focus is in the active window.
235 ServerWindow* focus = nullptr; 265 ServerWindow* focus = nullptr;
236 if (active_window_) { 266 if (active_window_) {
237 WindowTreeIterator iter(active_window_); 267 WindowTreeIterator iter(active_window_);
238 focus = nullptr; 268 focus = nullptr;
239 do { 269 do {
240 focus = iter.GetNext(focus); 270 focus = iter.GetNext(focus);
241 } while (focus != active_window_ && 271 } while (focus != active_window_ &&
242 (will_be_hidden(focus) || !CanBeFocused(focus))); 272 (will_be_hidden(focus) || !CanBeFocused(focus)));
(...skipping 18 matching lines...) Expand all
261 } 291 }
262 292
263 void FocusController::OnDrawnStateChanged(ServerWindow* ancestor, 293 void FocusController::OnDrawnStateChanged(ServerWindow* ancestor,
264 ServerWindow* window, 294 ServerWindow* window,
265 bool is_drawn) { 295 bool is_drawn) {
266 DCHECK(false); 296 DCHECK(false);
267 } 297 }
268 298
269 } // namespace ws 299 } // namespace ws
270 } // namespace mus 300 } // namespace mus
OLDNEW
« no previous file with comments | « components/mus/ws/focus_controller.h ('k') | components/mus/ws/focus_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698