Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 ClearCycleWindows(); | |
| 73 } | |
| 71 | 74 |
| 72 void FocusController::SetFocusedWindow(ServerWindow* window) { | 75 void FocusController::SetFocusedWindow(ServerWindow* window) { |
| 73 if (GetFocusedWindow() == window) | 76 if (GetFocusedWindow() == window) |
| 74 return; | 77 return; |
| 75 | 78 |
| 76 SetFocusedWindowImpl(FocusControllerChangeSource::EXPLICIT, window); | 79 SetFocusedWindowImpl(FocusControllerChangeSource::EXPLICIT, window); |
| 77 } | 80 } |
| 78 | 81 |
| 79 ServerWindow* FocusController::GetFocusedWindow() { | 82 ServerWindow* FocusController::GetFocusedWindow() { |
| 80 return focused_window_; | 83 return focused_window_; |
| 81 } | 84 } |
| 82 | 85 |
| 83 void FocusController::ActivateNextWindow() { | 86 void FocusController::ActivateNextWindow() { |
| 84 WindowTreeIterator iter(root_); | 87 WindowTreeIterator iter(root_); |
| 85 ServerWindow* activate = active_window_; | 88 ServerWindow* activate = active_window_; |
| 86 do { | 89 while (true) { |
| 87 activate = iter.GetNext(activate); | 90 activate = iter.GetNext(activate); |
| 88 } while (activate != active_window_ && !CanBeActivated(activate)); | 91 if (activation_reason_ == ActivationChangeReason::CYCLE) { |
| 89 SetActiveWindow(activate); | 92 if (activate == active_window_) { |
| 93 // We have cycled over all the activatable windows. Remove the oldest | |
| 94 // window that was cycled. | |
| 95 if (!cycle_windows_.empty()) { | |
| 96 cycle_windows_.front()->RemoveObserver(this); | |
| 97 cycle_windows_.erase(cycle_windows_.begin()); | |
| 98 continue; | |
| 99 } | |
| 100 } else if (std::find(cycle_windows_.begin(), cycle_windows_.end(), | |
|
sky
2016/01/06 21:02:39
FYI: you can use ContainsValue(cycle_windows_, act
| |
| 101 activate) != cycle_windows_.end()) { | |
| 102 // We are cycling between activated windows, and this window has already | |
| 103 // been through the cycle. So skip over it. | |
| 104 continue; | |
| 105 } | |
| 106 } | |
| 107 if (activate == active_window_ || CanBeActivated(activate)) | |
| 108 break; | |
| 109 } | |
| 110 SetActiveWindow(activate, ActivationChangeReason::CYCLE); | |
| 90 | 111 |
| 91 if (active_window_) { | 112 if (active_window_) { |
| 92 // Do not shift focus if the focused window already lives in the active | 113 // Do not shift focus if the focused window already lives in the active |
| 93 // window. | 114 // window. |
| 94 if (focused_window_ && active_window_->Contains(focused_window_)) | 115 if (focused_window_ && active_window_->Contains(focused_window_)) |
| 95 return; | 116 return; |
| 96 // Focus the first focusable window in the tree. | 117 // Focus the first focusable window in the tree. |
| 97 WindowTreeIterator iter(active_window_); | 118 WindowTreeIterator iter(active_window_); |
| 98 ServerWindow* focus = nullptr; | 119 ServerWindow* focus = nullptr; |
| 99 do { | 120 do { |
| 100 focus = iter.GetNext(focus); | 121 focus = iter.GetNext(focus); |
| 101 } while (focus != active_window_ && !CanBeFocused(focus)); | 122 } while (focus != active_window_ && !CanBeFocused(focus)); |
| 102 SetFocusedWindow(focus); | 123 SetFocusedWindow(focus); |
| 103 } else { | 124 } else { |
| 104 SetFocusedWindow(nullptr); | 125 SetFocusedWindow(nullptr); |
| 105 } | 126 } |
| 106 } | 127 } |
| 107 | 128 |
| 108 void FocusController::AddObserver(FocusControllerObserver* observer) { | 129 void FocusController::AddObserver(FocusControllerObserver* observer) { |
| 109 observers_.AddObserver(observer); | 130 observers_.AddObserver(observer); |
| 110 } | 131 } |
| 111 | 132 |
| 112 void FocusController::RemoveObserver(FocusControllerObserver* observer) { | 133 void FocusController::RemoveObserver(FocusControllerObserver* observer) { |
| 113 observers_.RemoveObserver(observer); | 134 observers_.RemoveObserver(observer); |
| 114 } | 135 } |
| 115 | 136 |
| 116 void FocusController::SetActiveWindow(ServerWindow* window) { | 137 void FocusController::SetActiveWindow(ServerWindow* window, |
| 138 ActivationChangeReason reason) { | |
| 117 DCHECK(!window || CanBeActivated(window)); | 139 DCHECK(!window || CanBeActivated(window)); |
| 118 if (active_window_ == window) | 140 if (active_window_ == window) |
| 119 return; | 141 return; |
| 142 if (reason != ActivationChangeReason::CYCLE) { | |
| 143 ClearCycleWindows(); | |
| 144 } else if (activation_reason_ != ActivationChangeReason::CYCLE) { | |
| 145 DCHECK(cycle_windows_.empty()); | |
| 146 if (active_window_) { | |
| 147 active_window_->AddObserver(this); | |
| 148 cycle_windows_.push_back(active_window_); | |
| 149 } | |
| 150 } | |
| 151 | |
| 120 ServerWindow* old_active = active_window_; | 152 ServerWindow* old_active = active_window_; |
| 121 active_window_ = window; | 153 active_window_ = window; |
| 122 if (old_active != active_window_) { | 154 activation_reason_ = reason; |
| 123 FOR_EACH_OBSERVER(FocusControllerObserver, observers_, | 155 FOR_EACH_OBSERVER(FocusControllerObserver, observers_, |
| 124 OnActivationChanged(old_active, active_window_)); | 156 OnActivationChanged(old_active, active_window_)); |
| 157 if (active_window_ && activation_reason_ == ActivationChangeReason::CYCLE) { | |
| 158 active_window_->AddObserver(this); | |
|
sky
2016/01/06 21:02:39
nit: add an AddWindowToCycleWindows (or something
| |
| 159 cycle_windows_.push_back(active_window_); | |
| 125 } | 160 } |
| 126 } | 161 } |
| 127 | 162 |
| 128 bool FocusController::CanBeFocused(ServerWindow* window) const { | 163 bool FocusController::CanBeFocused(ServerWindow* window) const { |
| 129 // All ancestors of |window| must be drawn, and be focusable. | 164 // All ancestors of |window| must be drawn, and be focusable. |
| 130 for (ServerWindow* w = window; w; w = w->parent()) { | 165 for (ServerWindow* w = window; w; w = w->parent()) { |
| 131 if (!w->IsDrawn()) | 166 if (!w->IsDrawn()) |
| 132 return false; | 167 return false; |
| 133 if (!w->can_focus()) | 168 if (!w->can_focus()) |
| 134 return false; | 169 return false; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 180 ServerWindow* window) { | 215 ServerWindow* window) { |
| 181 if (window && !CanBeFocused(window)) | 216 if (window && !CanBeFocused(window)) |
| 182 return; | 217 return; |
| 183 ServerWindow* old_focused = GetFocusedWindow(); | 218 ServerWindow* old_focused = GetFocusedWindow(); |
| 184 | 219 |
| 185 DCHECK(!window || window->IsDrawn()); | 220 DCHECK(!window || window->IsDrawn()); |
| 186 | 221 |
| 187 // Activate the closest activatable ancestor window. | 222 // Activate the closest activatable ancestor window. |
| 188 // TODO(sad): The window to activate doesn't necessarily have to be a direct | 223 // TODO(sad): The window to activate doesn't necessarily have to be a direct |
| 189 // ancestor (e.g. could be a transient parent). | 224 // ancestor (e.g. could be a transient parent). |
| 190 SetActiveWindow(GetActivatableAncestorOf(window)); | 225 SetActiveWindow(GetActivatableAncestorOf(window), |
| 226 ActivationChangeReason::FOCUS); | |
| 191 | 227 |
| 192 FOR_EACH_OBSERVER(FocusControllerObserver, observers_, | 228 FOR_EACH_OBSERVER(FocusControllerObserver, observers_, |
| 193 OnFocusChanged(change_source, old_focused, window)); | 229 OnFocusChanged(change_source, old_focused, window)); |
| 194 | 230 |
| 195 focused_window_ = window; | 231 focused_window_ = window; |
| 196 // We can currently use only a single ServerWindowDrawnTracker since focused | 232 // We can currently use only a single ServerWindowDrawnTracker since focused |
| 197 // window is expected to be a direct descendant of the active window. | 233 // window is expected to be a direct descendant of the active window. |
| 198 if (focused_window_ && active_window_) { | 234 if (focused_window_ && active_window_) { |
| 199 DCHECK(active_window_->Contains(focused_window_)); | 235 DCHECK(active_window_->Contains(focused_window_)); |
| 200 } | 236 } |
| 201 ServerWindow* track_window = focused_window_; | 237 ServerWindow* track_window = focused_window_; |
| 202 if (!track_window) | 238 if (!track_window) |
| 203 track_window = active_window_; | 239 track_window = active_window_; |
| 204 if (track_window) | 240 if (track_window) |
| 205 drawn_tracker_.reset(new ServerWindowDrawnTracker(track_window, this)); | 241 drawn_tracker_.reset(new ServerWindowDrawnTracker(track_window, this)); |
| 206 else | 242 else |
| 207 drawn_tracker_.reset(); | 243 drawn_tracker_.reset(); |
| 208 } | 244 } |
| 209 | 245 |
| 246 void FocusController::ClearCycleWindows() { | |
| 247 while (!cycle_windows_.empty()) { | |
| 248 cycle_windows_.front()->RemoveObserver(this); | |
| 249 cycle_windows_.erase(cycle_windows_.begin()); | |
| 250 } | |
| 251 } | |
| 252 | |
| 210 void FocusController::OnDrawnStateWillChange(ServerWindow* ancestor, | 253 void FocusController::OnDrawnStateWillChange(ServerWindow* ancestor, |
| 211 ServerWindow* window, | 254 ServerWindow* window, |
| 212 bool is_drawn) { | 255 bool is_drawn) { |
| 213 DCHECK(!is_drawn); | 256 DCHECK(!is_drawn); |
| 214 DCHECK(root_->Contains(window)); | 257 DCHECK(root_->Contains(window)); |
| 215 drawn_tracker_.reset(); | 258 drawn_tracker_.reset(); |
| 216 | 259 |
| 217 auto will_be_hidden = [ancestor, window](ServerWindow* w) { | 260 auto will_be_hidden = [ancestor, window](ServerWindow* w) { |
| 218 return w != ancestor && ancestor->Contains(w) && w->Contains(window); | 261 return w != ancestor && ancestor->Contains(w) && w->Contains(window); |
| 219 }; | 262 }; |
| 220 | 263 |
| 221 // If |window| is |active_window_|, then activate the next activatable window | 264 // If |window| is |active_window_|, then activate the next activatable window |
| 222 // that does not belong to the subtree which is getting hidden. | 265 // that does not belong to the subtree which is getting hidden. |
| 223 if (window == active_window_) { | 266 if (window == active_window_) { |
| 224 WindowTreeIterator iter(root_); | 267 WindowTreeIterator iter(root_); |
| 225 ServerWindow* activate = active_window_; | 268 ServerWindow* activate = active_window_; |
| 226 do { | 269 do { |
| 227 activate = iter.GetNext(activate); | 270 activate = iter.GetNext(activate); |
| 228 } while (activate != active_window_ && | 271 } while (activate != active_window_ && |
| 229 (will_be_hidden(activate) || !CanBeActivated(activate))); | 272 (will_be_hidden(activate) || !CanBeActivated(activate))); |
| 230 if (activate == window) | 273 if (activate == window) |
| 231 activate = nullptr; | 274 activate = nullptr; |
| 232 SetActiveWindow(activate); | 275 SetActiveWindow(activate, ActivationChangeReason::DRAWN_STATE_CHANGED); |
| 233 | 276 |
| 234 // Now make sure focus is in the active window. | 277 // Now make sure focus is in the active window. |
| 235 ServerWindow* focus = nullptr; | 278 ServerWindow* focus = nullptr; |
| 236 if (active_window_) { | 279 if (active_window_) { |
| 237 WindowTreeIterator iter(active_window_); | 280 WindowTreeIterator iter(active_window_); |
| 238 focus = nullptr; | 281 focus = nullptr; |
| 239 do { | 282 do { |
| 240 focus = iter.GetNext(focus); | 283 focus = iter.GetNext(focus); |
| 241 } while (focus != active_window_ && | 284 } while (focus != active_window_ && |
| 242 (will_be_hidden(focus) || !CanBeFocused(focus))); | 285 (will_be_hidden(focus) || !CanBeFocused(focus))); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 259 focus = nullptr; | 302 focus = nullptr; |
| 260 SetFocusedWindowImpl(FocusControllerChangeSource::DRAWN_STATE_CHANGED, focus); | 303 SetFocusedWindowImpl(FocusControllerChangeSource::DRAWN_STATE_CHANGED, focus); |
| 261 } | 304 } |
| 262 | 305 |
| 263 void FocusController::OnDrawnStateChanged(ServerWindow* ancestor, | 306 void FocusController::OnDrawnStateChanged(ServerWindow* ancestor, |
| 264 ServerWindow* window, | 307 ServerWindow* window, |
| 265 bool is_drawn) { | 308 bool is_drawn) { |
| 266 DCHECK(false); | 309 DCHECK(false); |
| 267 } | 310 } |
| 268 | 311 |
| 312 void FocusController::OnWillDestroyWindow(ServerWindow* window) { | |
| 313 cycle_windows_.erase( | |
| 314 std::find(cycle_windows_.begin(), cycle_windows_.end(), window)); | |
|
sky
2016/01/06 21:02:39
also remove the observer here too.
| |
| 315 } | |
| 316 | |
| 269 } // namespace ws | 317 } // namespace ws |
| 270 } // namespace mus | 318 } // namespace mus |
| OLD | NEW |