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

Side by Side Diff: chromecast/graphics/cast_window_manager_aura.cc

Issue 2636303002: [Chromecast] Add support for z-order and window focus. (Closed)
Patch Set: fix macro 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 unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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 "chromecast/graphics/cast_window_manager_aura.h" 5 #include "chromecast/graphics/cast_window_manager_aura.h"
6 6
7 #include "base/memory/ptr_util.h" 7 #include "base/memory/ptr_util.h"
8 #include "ui/aura/client/default_capture_client.h" 8 #include "ui/aura/client/default_capture_client.h"
9 #include "ui/aura/client/focus_change_observer.h"
9 #include "ui/aura/env.h" 10 #include "ui/aura/env.h"
10 #include "ui/aura/layout_manager.h" 11 #include "ui/aura/layout_manager.h"
11 #include "ui/aura/window.h" 12 #include "ui/aura/window.h"
12 #include "ui/aura/window_tree_host_platform.h" 13 #include "ui/aura/window_tree_host_platform.h"
13 #include "ui/base/ime/input_method.h" 14 #include "ui/base/ime/input_method.h"
14 #include "ui/base/ime/input_method_factory.h" 15 #include "ui/base/ime/input_method_factory.h"
15 #include "ui/display/display.h" 16 #include "ui/display/display.h"
16 #include "ui/display/screen.h" 17 #include "ui/display/screen.h"
17 18
19 #define LOG_WINDOW_INFO(top_level, window) \
20 "top-level: " << (top_level)->id() << ": " << (top_level)->GetName() \
21 << ", window: " << (window)->id() << ": " \
22 << (window)->GetName()
23
24 namespace {
25 const bool kFocusFollowsVisibility = true;
26 }
27
18 namespace chromecast { 28 namespace chromecast {
19 29
20 // An aura::WindowTreeHost that correctly converts input events. 30 // An aura::WindowTreeHost that correctly converts input events.
21 class CastWindowTreeHost : public aura::WindowTreeHostPlatform { 31 class CastWindowTreeHost : public aura::WindowTreeHostPlatform {
22 public: 32 public:
23 CastWindowTreeHost(bool enable_input, const gfx::Rect& bounds); 33 CastWindowTreeHost(bool enable_input, const gfx::Rect& bounds);
24 ~CastWindowTreeHost() override; 34 ~CastWindowTreeHost() override;
25 35
26 // aura::WindowTreeHostPlatform implementation: 36 // aura::WindowTreeHostPlatform implementation:
27 void DispatchEvent(ui::Event* event) override; 37 void DispatchEvent(ui::Event* event) override;
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 SetChildBoundsDirect(child, requested_bounds); 111 SetChildBoundsDirect(child, requested_bounds);
102 } 112 }
103 113
104 // static 114 // static
105 std::unique_ptr<CastWindowManager> CastWindowManager::Create( 115 std::unique_ptr<CastWindowManager> CastWindowManager::Create(
106 bool enable_input) { 116 bool enable_input) {
107 return base::WrapUnique(new CastWindowManagerAura(enable_input)); 117 return base::WrapUnique(new CastWindowManagerAura(enable_input));
108 } 118 }
109 119
110 CastWindowManagerAura::CastWindowManagerAura(bool enable_input) 120 CastWindowManagerAura::CastWindowManagerAura(bool enable_input)
111 : enable_input_(enable_input) {} 121 : enable_input_(enable_input), focused_window_(nullptr) {}
112 122
113 CastWindowManagerAura::~CastWindowManagerAura() { 123 CastWindowManagerAura::~CastWindowManagerAura() {
114 TearDown(); 124 TearDown();
115 } 125 }
116 126
117 void CastWindowManagerAura::Setup() { 127 void CastWindowManagerAura::Setup() {
118 if (window_tree_host_) { 128 if (window_tree_host_) {
119 return; 129 return;
120 } 130 }
121 DCHECK(display::Screen::GetScreen()); 131 DCHECK(display::Screen::GetScreen());
122 132
123 ui::InitializeInputMethodForTesting(); 133 ui::InitializeInputMethodForTesting();
124 134
125 gfx::Size display_size = 135 gfx::Size display_size =
126 display::Screen::GetScreen()->GetPrimaryDisplay().GetSizeInPixel(); 136 display::Screen::GetScreen()->GetPrimaryDisplay().GetSizeInPixel();
127 LOG(INFO) << "Starting window manager, screen size: " << display_size.width() 137 LOG(INFO) << "Starting window manager, screen size: " << display_size.width()
128 << "x" << display_size.height(); 138 << "x" << display_size.height();
129 CHECK(aura::Env::GetInstance()); 139 CHECK(aura::Env::GetInstance());
130 window_tree_host_.reset( 140 window_tree_host_.reset(
131 new CastWindowTreeHost(enable_input_, gfx::Rect(display_size))); 141 new CastWindowTreeHost(enable_input_, gfx::Rect(display_size)));
132 window_tree_host_->InitHost(); 142 window_tree_host_->InitHost();
133 window_tree_host_->window()->SetLayoutManager(new CastLayoutManager()); 143 window_tree_host_->window()->SetLayoutManager(new CastLayoutManager());
134 144
135 // Allow seeing through to the hardware video plane: 145 // Allow seeing through to the hardware video plane:
136 window_tree_host_->compositor()->SetHostHasTransparentBackground(true); 146 window_tree_host_->compositor()->SetHostHasTransparentBackground(true);
137 window_tree_host_->compositor()->SetBackgroundColor(SK_ColorTRANSPARENT); 147 window_tree_host_->compositor()->SetBackgroundColor(SK_ColorTRANSPARENT);
138 148
149 aura::client::SetFocusClient(window_tree_host_->window(), this);
139 capture_client_.reset( 150 capture_client_.reset(
140 new aura::client::DefaultCaptureClient(window_tree_host_->window())); 151 new aura::client::DefaultCaptureClient(window_tree_host_->window()));
141 152
142 CastVSyncSettings::GetInstance()->AddObserver(this); 153 CastVSyncSettings::GetInstance()->AddObserver(this);
143 window_tree_host_->compositor()->SetAuthoritativeVSyncInterval( 154 window_tree_host_->compositor()->SetAuthoritativeVSyncInterval(
144 CastVSyncSettings::GetInstance()->GetVSyncInterval()); 155 CastVSyncSettings::GetInstance()->GetVSyncInterval());
145 156
146 window_tree_host_->Show(); 157 window_tree_host_->Show();
147 } 158 }
148 159
149 void CastWindowManagerAura::TearDown() { 160 void CastWindowManagerAura::TearDown() {
150 if (!window_tree_host_) { 161 if (!window_tree_host_) {
151 return; 162 return;
152 } 163 }
164 focused_window_ = nullptr;
153 CastVSyncSettings::GetInstance()->RemoveObserver(this); 165 CastVSyncSettings::GetInstance()->RemoveObserver(this);
154 capture_client_.reset(); 166 capture_client_.reset();
167 aura::client::SetFocusClient(window_tree_host_->window(), nullptr);
155 window_tree_host_.reset(); 168 window_tree_host_.reset();
156 } 169 }
157 170
158 void CastWindowManagerAura::AddWindow(gfx::NativeView child) { 171 void CastWindowManagerAura::AddWindow(gfx::NativeView child) {
159 LOG(INFO) << "Adding window: " << child->id() << ": " << child->GetName(); 172 LOG(INFO) << "Adding window: " << child->id() << ": " << child->GetName();
160 Setup(); 173 Setup();
161 174
162 DCHECK(child); 175 DCHECK(child);
163 aura::Window* parent = window_tree_host_->window(); 176 aura::Window* parent = window_tree_host_->window();
164 if (!parent->Contains(child)) { 177 if (!parent->Contains(child)) {
165 parent->AddChild(child); 178 parent->AddChild(child);
166 } 179 }
167 180
168 parent->StackChildAtTop(child); 181 // Determine z-order relative to existing windows.
halliwell 2017/01/19 20:49:17 This is ordering windows by ID? Is the assumption
Joshua LeVasseur 2017/01/23 23:38:32 Yes, we use this enum for setting window IDs. If
182 aura::Window::Windows windows = parent->children();
183 aura::Window* above = nullptr;
184 aura::Window* below = nullptr;
185 for (auto&& other : windows) {
186 if (other == child) {
187 continue;
188 }
189 if ((other->id() < child->id()) && (!below || other->id() > below->id())) {
190 below = other;
191 } else if ((other->id() > child->id()) &&
192 (!above || other->id() < above->id())) {
193 above = other;
194 }
195 }
196
197 // Adjust the z-order of the new child window.
198 if (above) {
199 parent->StackChildBelow(child, above);
200 } else if (below) {
201 parent->StackChildAbove(child, below);
202 } else {
203 parent->StackChildAtBottom(child);
204 }
169 child->SetBounds(window_tree_host_->window()->bounds()); 205 child->SetBounds(window_tree_host_->window()->bounds());
170 } 206 }
171 207
172 void CastWindowManagerAura::OnVSyncIntervalChanged(base::TimeDelta interval) { 208 void CastWindowManagerAura::OnVSyncIntervalChanged(base::TimeDelta interval) {
173 DCHECK(window_tree_host_.get()); 209 DCHECK(window_tree_host_.get());
174 window_tree_host_->compositor()->SetAuthoritativeVSyncInterval(interval); 210 window_tree_host_->compositor()->SetAuthoritativeVSyncInterval(interval);
175 } 211 }
176 212
213 void CastWindowManagerAura::OnWindowVisibilityChanged(aura::Window* window,
214 bool visible) {
215 if (!kFocusFollowsVisibility) {
216 return;
217 }
218 if (!visible && (window == focused_window_)) {
219 UpdateWindowFocus(focused_window_);
220 } else if (visible) {
221 UpdateWindowFocus(nullptr);
222 }
223 }
224
225 void CastWindowManagerAura::OnWindowDestroying(aura::Window* window) {
226 aura::Window* top_level = GetTopLevelWindow(window);
227 DCHECK(top_level);
228 LOG(INFO) << "Removing window, " << LOG_WINDOW_INFO(top_level, window);
229
230 auto iter =
231 std::find(focusable_windows_.begin(), focusable_windows_.end(), window);
232 if (iter != focusable_windows_.end()) {
233 focusable_windows_.erase(iter);
234 window->RemoveObserver(this);
235 }
236 if (window == focused_window_) {
237 UpdateWindowFocus(focused_window_);
238 }
239 }
240
241 void CastWindowManagerAura::OnWindowHierarchyChanging(
242 const HierarchyChangeParams& params) {
243 if (params.new_parent &&
244 (aura::client::GetFocusClient(params.new_parent) == this)) {
245 return;
246 }
247
248 auto iter = focusable_windows_.begin();
249 bool was_focused = false;
250 while (iter != focusable_windows_.end()) {
251 aura::Window* window = *iter;
252 if (params.target == window || params.target->Contains(window)) {
253 window->RemoveObserver(this);
254 was_focused |= window == focused_window_;
255 iter = focusable_windows_.erase(iter);
256
257 aura::Window* top_level = GetTopLevelWindow(window);
258 DCHECK(top_level);
259 LOG(INFO) << "Dropping window, " << LOG_WINDOW_INFO(top_level, window);
260 } else {
261 ++iter;
262 }
263 }
halliwell 2017/01/19 20:49:17 All of these focus change logic functions are kind
Joshua LeVasseur 2017/01/23 23:38:32 Done.
264
265 if (was_focused) {
266 UpdateWindowFocus(focused_window_);
267 }
268 }
269
270 void CastWindowManagerAura::AddObserver(
271 aura::client::FocusChangeObserver* observer) {
272 focus_observers_.AddObserver(observer);
273 }
274
275 void CastWindowManagerAura::RemoveObserver(
276 aura::client::FocusChangeObserver* observer) {
277 focus_observers_.RemoveObserver(observer);
278 }
279
280 void CastWindowManagerAura::FocusWindow(aura::Window* window) {
281 if (window) {
282 if (!window->CanFocus()) {
283 return;
284 }
285 aura::Window* top_level = GetTopLevelWindow(window);
286 DCHECK(top_level);
287 LOG(INFO) << "Requesting focus for " << LOG_WINDOW_INFO(top_level, window);
288 auto iter =
289 std::find(focusable_windows_.begin(), focusable_windows_.end(), window);
290 if (iter == focusable_windows_.end()) {
291 window->AddObserver(this);
292 focusable_windows_.push_back(window);
293 }
294 }
295
296 UpdateWindowFocus(nullptr);
297 }
298
299 void CastWindowManagerAura::ResetFocusWithinActiveWindow(aura::Window* window) {
300 // Sets focus to |window| if it's within the active window (a child of the
301 // focused window).
302 if (focused_window_ && focused_window_->Contains(window)) {
303 FocusWindow(window);
304 }
305 }
306
307 aura::Window* CastWindowManagerAura::GetFocusedWindow() {
308 return focused_window_;
309 }
310
311 void CastWindowManagerAura::UpdateWindowFocus(aura::Window* skip) {
312 aura::Window* window = GetWindowToFocus(skip);
313 if (window == focused_window_) {
314 return;
315 }
316
317 if (window) {
318 aura::Window* top_level = GetTopLevelWindow(window);
319 DCHECK(top_level);
320 LOG(INFO) << "Switching focus to " << LOG_WINDOW_INFO(top_level, window);
321 }
322
323 aura::Window* unfocus_window = focused_window_;
324 focused_window_ = window;
325
326 for (aura::client::FocusChangeObserver& observer : focus_observers_) {
327 observer.OnWindowFocused(focused_window_, unfocus_window);
328 if (focused_window_ != window) {
329 // The observer changed focused_window_.
330 return;
331 }
332 }
333
334 if (unfocus_window) {
335 aura::client::FocusChangeObserver* focus_observer =
336 aura::client::GetFocusChangeObserver(unfocus_window);
337 if (focus_observer) {
338 focus_observer->OnWindowFocused(focused_window_, unfocus_window);
339 if (focused_window_ != window) {
340 // The observer changed focused_window_.
341 return;
342 }
343 }
344 }
345 if (focused_window_) {
346 aura::client::FocusChangeObserver* focus_observer =
347 aura::client::GetFocusChangeObserver(focused_window_);
348 if (focus_observer) {
349 focus_observer->OnWindowFocused(focused_window_, unfocus_window);
350 if (focused_window_ != window) {
351 // The observer changed focused_window_.
352 return;
353 }
354 }
355 }
356 }
357
358 aura::Window* CastWindowManagerAura::GetWindowToFocus(aura::Window* skip) {
359 aura::Window* next = nullptr;
360 aura::Window* next_top_level = nullptr;
361 for (auto iter = focusable_windows_.begin(); iter != focusable_windows_.end();
362 ++iter) {
363 aura::Window* window = *iter;
364 if (window == skip || !window->CanFocus() ||
365 (kFocusFollowsVisibility && !window->IsVisible())) {
366 continue;
367 }
368
369 aura::Window* top_level = GetTopLevelWindow(window);
370 DCHECK(window_tree_host_->window()->Contains(top_level));
371 if (top_level && (!next || top_level->id() >= next_top_level->id())) {
372 next = window;
373 next_top_level = top_level;
374 }
375 }
376 return next;
377 }
378
379 aura::Window* CastWindowManagerAura::GetTopLevelWindow(aura::Window* window) {
380 while (window->parent() && window->parent() != window_tree_host_->window()) {
381 window = window->parent();
382 }
383 return window;
384 }
385
177 } // namespace chromecast 386 } // namespace chromecast
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698