| Index: components/mus/ws/focus_controller.cc
|
| diff --git a/components/mus/ws/focus_controller.cc b/components/mus/ws/focus_controller.cc
|
| index 49324fd73dd9fc842a0342275fd623fb748b4f5e..91dbb0a07a5956d7fecca0652a5e0e8628c6205a 100644
|
| --- a/components/mus/ws/focus_controller.cc
|
| +++ b/components/mus/ws/focus_controller.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "components/mus/ws/focus_controller.h"
|
|
|
| +#include "components/mus/ws/focus_controller_delegate.h"
|
| #include "components/mus/ws/focus_controller_observer.h"
|
| #include "components/mus/ws/server_window.h"
|
| #include "components/mus/ws/server_window_drawn_tracker.h"
|
| @@ -11,7 +12,8 @@
|
| namespace mus {
|
| namespace ws {
|
|
|
| -FocusController::FocusController() {}
|
| +FocusController::FocusController(FocusControllerDelegate* delegate)
|
| + : delegate_(delegate), focused_window_(nullptr), active_window_(nullptr) {}
|
|
|
| FocusController::~FocusController() {}
|
|
|
| @@ -23,7 +25,7 @@ void FocusController::SetFocusedWindow(ServerWindow* window) {
|
| }
|
|
|
| ServerWindow* FocusController::GetFocusedWindow() {
|
| - return drawn_tracker_ ? drawn_tracker_->window() : nullptr;
|
| + return focused_window_;
|
| }
|
|
|
| void FocusController::AddObserver(FocusControllerObserver* observer) {
|
| @@ -44,42 +46,73 @@ bool FocusController::CanBeFocused(ServerWindow* window) const {
|
| }
|
|
|
| // |window| must be a descendent of an activatable window.
|
| - for (ServerWindow* w = window; w; w = w->parent()) {
|
| - if (CanBeActivated(w))
|
| - return true;
|
| - }
|
| -
|
| - return false;
|
| + return GetActivatableAncestorOf(window) != nullptr;
|
| }
|
|
|
| bool FocusController::CanBeActivated(ServerWindow* window) const {
|
| + DCHECK(window);
|
| + // The parent window must be allowed to have active children.
|
| + if (!delegate_->CanHaveActiveChildren(window->parent()))
|
| + return false;
|
| +
|
| // TODO(sad): Implement this.
|
| return true;
|
| }
|
|
|
| +ServerWindow* FocusController::GetActivatableAncestorOf(
|
| + ServerWindow* window) const {
|
| + for (ServerWindow* w = window; w; w = w->parent()) {
|
| + if (CanBeActivated(w))
|
| + return w;
|
| + }
|
| + return nullptr;
|
| +}
|
| +
|
| void FocusController::SetFocusedWindowImpl(
|
| FocusControllerChangeSource change_source,
|
| ServerWindow* window) {
|
| if (window && !CanBeFocused(window))
|
| return;
|
| - ServerWindow* old = GetFocusedWindow();
|
| + ServerWindow* old_focused = GetFocusedWindow();
|
|
|
| DCHECK(!window || window->IsDrawn());
|
|
|
| - // TODO(sad): Activate the closest activatable ancestor window.
|
| - if (window)
|
| - drawn_tracker_.reset(new ServerWindowDrawnTracker(window, this));
|
| - else
|
| - drawn_tracker_.reset();
|
| + // 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).
|
| + ServerWindow* old_active = active_window_;
|
| + active_window_ = GetActivatableAncestorOf(window);
|
| + if (old_active != active_window_) {
|
| + FOR_EACH_OBSERVER(FocusControllerObserver, observers_,
|
| + OnActivationChanged(old_active, active_window_));
|
| + }
|
|
|
| FOR_EACH_OBSERVER(FocusControllerObserver, observers_,
|
| - OnFocusChanged(change_source, old, window));
|
| + OnFocusChanged(change_source, old_focused, window));
|
| +
|
| + focused_window_ = window;
|
| + // We can currently use only a single ServerWindowDrawnTracker since focused
|
| + // window is expected to be a direct descendant of the active window.
|
| + if (focused_window_ && active_window_) {
|
| + DCHECK(active_window_->Contains(focused_window_));
|
| + }
|
| + ServerWindow* track_window = focused_window_;
|
| + if (!track_window)
|
| + track_window = active_window_;
|
| + if (track_window)
|
| + drawn_tracker_.reset(new ServerWindowDrawnTracker(track_window, this));
|
| + else
|
| + drawn_tracker_.reset();
|
| }
|
|
|
| void FocusController::OnDrawnStateChanged(ServerWindow* ancestor,
|
| ServerWindow* window,
|
| bool is_drawn) {
|
| DCHECK(!is_drawn); // We only observe when drawn.
|
| + // TODO(sad): If |window| is |focused_window_|, then move focus to the next
|
| + // focusable window in |active_window_|, if |active_window_| is still visible.
|
| + // If |active_window_| is invisible, or if |window| is |active_window_|, then
|
| + // activate the next window that can be activated.
|
| SetFocusedWindowImpl(FocusControllerChangeSource::DRAWN_STATE_CHANGED,
|
| ancestor);
|
| }
|
|
|