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 |