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

Unified Diff: chromecast/graphics/cast_window_manager_aura.cc

Issue 2636303002: [Chromecast] Add support for z-order and window focus. (Closed)
Patch Set: rebased on final dependent cl Created 3 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 side-by-side diff with in-line comments
Download patch
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
« chromecast/graphics/cast_window_manager.h ('K') | « chromecast/graphics/cast_window_manager_aura.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698