Chromium Code Reviews| Index: chromecast/graphics/cast_window_manager_aura.cc |
| diff --git a/chromecast/graphics/cast_window_manager_aura.cc b/chromecast/graphics/cast_window_manager_aura.cc |
| index b4d9dbcd0896f1180c237be5c1cfcbb851fe8dae..cdcadd3fd0cf9b0afd18c095024ebf4e39780793 100644 |
| --- a/chromecast/graphics/cast_window_manager_aura.cc |
| +++ b/chromecast/graphics/cast_window_manager_aura.cc |
| @@ -6,6 +6,7 @@ |
| #include "base/memory/ptr_util.h" |
| #include "ui/aura/client/default_capture_client.h" |
| +#include "ui/aura/client/focus_change_observer.h" |
| #include "ui/aura/env.h" |
| #include "ui/aura/layout_manager.h" |
| #include "ui/aura/window.h" |
| @@ -15,6 +16,10 @@ |
| #include "ui/display/display.h" |
| #include "ui/display/screen.h" |
| +namespace { |
| +static bool kFocusFollowsVisibility = true; |
|
derekjchow1
2017/01/19 18:12:13
static keyword isn't needed here. const keyword sh
Joshua LeVasseur
2017/01/19 19:35:25
Done.
|
| +} |
| + |
| namespace chromecast { |
| // An aura::WindowTreeHost that correctly converts input events. |
| @@ -108,7 +113,7 @@ std::unique_ptr<CastWindowManager> CastWindowManager::Create( |
| } |
| CastWindowManagerAura::CastWindowManagerAura(bool enable_input) |
| - : enable_input_(enable_input) {} |
| + : enable_input_(enable_input), focused_window_(nullptr) {} |
| CastWindowManagerAura::~CastWindowManagerAura() { |
| TearDown(); |
| @@ -136,6 +141,7 @@ void CastWindowManagerAura::Setup() { |
| window_tree_host_->compositor()->SetHostHasTransparentBackground(true); |
| window_tree_host_->compositor()->SetBackgroundColor(SK_ColorTRANSPARENT); |
| + aura::client::SetFocusClient(window_tree_host_->window(), this); |
| capture_client_.reset( |
| new aura::client::DefaultCaptureClient(window_tree_host_->window())); |
| @@ -150,8 +156,10 @@ void CastWindowManagerAura::TearDown() { |
| if (!window_tree_host_) { |
| return; |
| } |
| + focused_window_ = nullptr; |
| CastVSyncSettings::GetInstance()->RemoveObserver(this); |
| capture_client_.reset(); |
| + aura::client::SetFocusClient(window_tree_host_->window(), nullptr); |
| window_tree_host_.reset(); |
| } |
| @@ -165,7 +173,30 @@ void CastWindowManagerAura::AddWindow(gfx::NativeView child) { |
| parent->AddChild(child); |
| } |
| - parent->StackChildAtTop(child); |
| + // Determine z-order relative to existing windows. |
| + aura::Window::Windows windows = parent->children(); |
| + aura::Window* above = nullptr; |
| + aura::Window* below = nullptr; |
| + for (auto&& other : windows) { |
|
derekjchow1
2017/01/19 18:12:13
Could this be done with std::reduce?
http://en.cp
Joshua LeVasseur
2017/01/19 19:35:25
I don't see it ... I'd need an example, but I don'
|
| + if (other == child) { |
| + continue; |
| + } else if ((other->id() < child->id()) && |
|
derekjchow1
2017/01/19 18:12:13
No need for else case after a continue statement.
Joshua LeVasseur
2017/01/19 19:35:25
Done.
|
| + (!below || other->id() > below->id())) { |
| + below = other; |
| + } else if ((other->id() > child->id()) && |
| + (!above || other->id() < above->id())) { |
| + above = other; |
| + } |
| + } |
| + |
| + // Adjust the z-order of the new child window. |
| + if (above) { |
| + parent->StackChildBelow(child, above); |
| + } else if (below) { |
| + parent->StackChildAbove(child, below); |
| + } else { |
| + parent->StackChildAtBottom(child); |
| + } |
| child->SetBounds(window_tree_host_->window()->bounds()); |
| } |
| @@ -174,4 +205,188 @@ void CastWindowManagerAura::OnVSyncIntervalChanged(base::TimeDelta interval) { |
| window_tree_host_->compositor()->SetAuthoritativeVSyncInterval(interval); |
| } |
| +////////////////////////////////////////////////////////////////////// |
|
derekjchow1
2017/01/19 18:12:13
I don't think this comment is needed in a .cc file
Joshua LeVasseur
2017/01/19 19:35:25
Done.
|
| +// Implementation for aura::WindowObserver |
| + |
| +void CastWindowManagerAura::OnWindowVisibilityChanged(aura::Window* window, |
| + bool visible) { |
| + if (!kFocusFollowsVisibility) { |
| + return; |
| + } |
| + if (!visible && (window == focused_window_)) { |
| + UpdateWindowFocus(focused_window_); |
| + } else if (visible) { |
| + UpdateWindowFocus(nullptr); |
| + } |
| +} |
| + |
| +void CastWindowManagerAura::OnWindowDestroying(aura::Window* window) { |
| + aura::Window* top_level = GetTopLevelWindow(window); |
| + DCHECK(top_level); |
| + LOG(INFO) << "Removing window top-level: " << top_level->id() << ": " |
| + << top_level->GetName() << ", window: " << window->id() << ": " |
| + << window->GetName(); |
| + |
| + auto iter = |
| + std::find(focusable_windows_.begin(), focusable_windows_.end(), window); |
| + if (iter != focusable_windows_.end()) { |
| + focusable_windows_.erase(iter); |
| + window->RemoveObserver(this); |
| + } |
| + if (window == focused_window_) { |
| + UpdateWindowFocus(focused_window_); |
| + } |
| +} |
| + |
| +void CastWindowManagerAura::OnWindowHierarchyChanging( |
| + const HierarchyChangeParams& params) { |
| + if (params.new_parent && |
| + (aura::client::GetFocusClient(params.new_parent) == this)) { |
| + return; |
| + } |
| + |
| + auto iter = focusable_windows_.begin(); |
| + bool was_focused = false; |
| + while (iter != focusable_windows_.end()) { |
| + aura::Window* window = *iter; |
| + if (params.target == window || params.target->Contains(window)) { |
| + window->RemoveObserver(this); |
| + was_focused |= window == focused_window_; |
| + iter = focusable_windows_.erase(iter); |
| + |
| + aura::Window* top_level = GetTopLevelWindow(window); |
| + DCHECK(top_level); |
| + LOG(INFO) << "Dropping window top-level: " << top_level->id() << ": " |
| + << top_level->GetName() << ", window: " << window->id() << ": " |
| + << window->GetName(); |
| + } else { |
| + ++iter; |
| + } |
| + } |
| + |
| + if (was_focused) { |
| + UpdateWindowFocus(focused_window_); |
| + } |
| +} |
| + |
| +////////////////////////////////////////////////////////////////////// |
| +// Implementation for aura::client::FocusClient |
| + |
| +void CastWindowManagerAura::AddObserver( |
| + aura::client::FocusChangeObserver* observer) { |
| + focus_observers_.AddObserver(observer); |
| +} |
| + |
| +void CastWindowManagerAura::RemoveObserver( |
| + aura::client::FocusChangeObserver* observer) { |
| + focus_observers_.RemoveObserver(observer); |
| +} |
| + |
| +void CastWindowManagerAura::FocusWindow(aura::Window* window) { |
| + if (window) { |
| + if (!window->CanFocus()) { |
| + return; |
| + } |
| + aura::Window* top_level = GetTopLevelWindow(window); |
| + DCHECK(top_level); |
| + LOG(INFO) << "Requesting focus for top-level: " << top_level->id() << ": " |
|
derekjchow1
2017/01/19 18:12:13
This is duplicated a lot, could you turn this into
Joshua LeVasseur
2017/01/19 19:35:25
Done.
|
| + << top_level->GetName() << ", window: " << window->id() << ": " |
| + << window->GetName(); |
| + auto iter = |
| + std::find(focusable_windows_.begin(), focusable_windows_.end(), window); |
| + if (iter == focusable_windows_.end()) { |
| + window->AddObserver(this); |
| + focusable_windows_.push_back(window); |
| + } |
| + } |
| + |
| + UpdateWindowFocus(nullptr); |
| +} |
| + |
| +void CastWindowManagerAura::ResetFocusWithinActiveWindow(aura::Window* window) { |
| + // Sets focus to |window| if it's within the active window (a child of the |
| + // focused window). |
| + if (focused_window_ && focused_window_->Contains(window)) { |
| + FocusWindow(window); |
| + } |
| +} |
| + |
| +aura::Window* CastWindowManagerAura::GetFocusedWindow() { |
| + return focused_window_; |
| +} |
| + |
| +void CastWindowManagerAura::UpdateWindowFocus(aura::Window* skip) { |
| + aura::Window* window = GetWindowToFocus(skip); |
| + if (window == focused_window_) { |
| + return; |
| + } |
| + |
| + if (window) { |
| + aura::Window* top_level = GetTopLevelWindow(window); |
| + DCHECK(top_level); |
| + LOG(INFO) << "Switching focus to top-level: " << top_level->id() << ": " |
| + << top_level->GetName() << ", window: " << window->id() << ": " |
| + << window->GetName(); |
| + } |
| + |
| + aura::Window* unfocus_window = focused_window_; |
| + focused_window_ = window; |
| + |
| + for (aura::client::FocusChangeObserver& observer : focus_observers_) { |
| + observer.OnWindowFocused(focused_window_, unfocus_window); |
| + if (focused_window_ != window) { |
|
derekjchow1
2017/01/19 18:12:13
Why is this here? A few lines above make focused_w
Joshua LeVasseur
2017/01/19 19:35:25
Yes, OnWindowFocused can change focused_window_.
|
| + return; |
| + } |
| + } |
| + |
| + if (unfocus_window) { |
| + aura::client::FocusChangeObserver* focus_observer = |
| + aura::client::GetFocusChangeObserver(unfocus_window); |
| + if (focus_observer) { |
| + focus_observer->OnWindowFocused(focused_window_, unfocus_window); |
| + if (focused_window_ != window) { |
| + return; |
| + } |
| + } |
| + } |
| + if (focused_window_) { |
| + aura::client::FocusChangeObserver* focus_observer = |
| + aura::client::GetFocusChangeObserver(focused_window_); |
| + if (focus_observer) { |
| + focus_observer->OnWindowFocused(focused_window_, unfocus_window); |
| + if (focused_window_ != window) { |
| + return; |
| + } |
| + } |
| + } |
| +} |
| + |
| +aura::Window* CastWindowManagerAura::GetWindowToFocus(aura::Window* skip) { |
| + aura::Window* next = nullptr; |
| + aura::Window* next_top_level = nullptr; |
| + for (auto iter = focusable_windows_.begin(); iter != focusable_windows_.end(); |
| + ++iter) { |
| + aura::Window* window = *iter; |
| + if (window == skip || !window->CanFocus() || |
| + (kFocusFollowsVisibility && !window->IsVisible())) { |
| + continue; |
| + } |
| + |
| + aura::Window* top_level = GetTopLevelWindow(window); |
| + DCHECK(window_tree_host_->window()->Contains(top_level)); |
| + if (top_level && (!next || top_level->id() >= next_top_level->id())) { |
| + next = window; |
| + next_top_level = top_level; |
| + } |
| + } |
| + return next; |
| +} |
| + |
| +aura::Window* CastWindowManagerAura::GetTopLevelWindow(aura::Window* window) { |
| + while (window->parent() && window->parent() != window_tree_host_->window()) { |
| + window = window->parent(); |
| + } |
| + return window; |
| +} |
| + |
| } // namespace chromecast |