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

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: 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 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 namespace {
20 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.
21 }
22
18 namespace chromecast { 23 namespace chromecast {
19 24
20 // An aura::WindowTreeHost that correctly converts input events. 25 // An aura::WindowTreeHost that correctly converts input events.
21 class CastWindowTreeHost : public aura::WindowTreeHostPlatform { 26 class CastWindowTreeHost : public aura::WindowTreeHostPlatform {
22 public: 27 public:
23 CastWindowTreeHost(bool enable_input, const gfx::Rect& bounds); 28 CastWindowTreeHost(bool enable_input, const gfx::Rect& bounds);
24 ~CastWindowTreeHost() override; 29 ~CastWindowTreeHost() override;
25 30
26 // aura::WindowTreeHostPlatform implementation: 31 // aura::WindowTreeHostPlatform implementation:
27 void DispatchEvent(ui::Event* event) override; 32 void DispatchEvent(ui::Event* event) override;
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 SetChildBoundsDirect(child, requested_bounds); 106 SetChildBoundsDirect(child, requested_bounds);
102 } 107 }
103 108
104 // static 109 // static
105 std::unique_ptr<CastWindowManager> CastWindowManager::Create( 110 std::unique_ptr<CastWindowManager> CastWindowManager::Create(
106 bool enable_input) { 111 bool enable_input) {
107 return base::WrapUnique(new CastWindowManagerAura(enable_input)); 112 return base::WrapUnique(new CastWindowManagerAura(enable_input));
108 } 113 }
109 114
110 CastWindowManagerAura::CastWindowManagerAura(bool enable_input) 115 CastWindowManagerAura::CastWindowManagerAura(bool enable_input)
111 : enable_input_(enable_input) {} 116 : enable_input_(enable_input), focused_window_(nullptr) {}
112 117
113 CastWindowManagerAura::~CastWindowManagerAura() { 118 CastWindowManagerAura::~CastWindowManagerAura() {
114 TearDown(); 119 TearDown();
115 } 120 }
116 121
117 void CastWindowManagerAura::Setup() { 122 void CastWindowManagerAura::Setup() {
118 if (window_tree_host_) { 123 if (window_tree_host_) {
119 return; 124 return;
120 } 125 }
121 DCHECK(display::Screen::GetScreen()); 126 DCHECK(display::Screen::GetScreen());
122 127
123 ui::InitializeInputMethodForTesting(); 128 ui::InitializeInputMethodForTesting();
124 129
125 gfx::Size display_size = 130 gfx::Size display_size =
126 display::Screen::GetScreen()->GetPrimaryDisplay().GetSizeInPixel(); 131 display::Screen::GetScreen()->GetPrimaryDisplay().GetSizeInPixel();
127 LOG(INFO) << "Starting window manager, screen size: " << display_size.width() 132 LOG(INFO) << "Starting window manager, screen size: " << display_size.width()
128 << "x" << display_size.height(); 133 << "x" << display_size.height();
129 CHECK(aura::Env::GetInstance()); 134 CHECK(aura::Env::GetInstance());
130 window_tree_host_.reset( 135 window_tree_host_.reset(
131 new CastWindowTreeHost(enable_input_, gfx::Rect(display_size))); 136 new CastWindowTreeHost(enable_input_, gfx::Rect(display_size)));
132 window_tree_host_->InitHost(); 137 window_tree_host_->InitHost();
133 window_tree_host_->window()->SetLayoutManager(new CastLayoutManager()); 138 window_tree_host_->window()->SetLayoutManager(new CastLayoutManager());
134 139
135 // Allow seeing through to the hardware video plane: 140 // Allow seeing through to the hardware video plane:
136 window_tree_host_->compositor()->SetHostHasTransparentBackground(true); 141 window_tree_host_->compositor()->SetHostHasTransparentBackground(true);
137 window_tree_host_->compositor()->SetBackgroundColor(SK_ColorTRANSPARENT); 142 window_tree_host_->compositor()->SetBackgroundColor(SK_ColorTRANSPARENT);
138 143
144 aura::client::SetFocusClient(window_tree_host_->window(), this);
139 capture_client_.reset( 145 capture_client_.reset(
140 new aura::client::DefaultCaptureClient(window_tree_host_->window())); 146 new aura::client::DefaultCaptureClient(window_tree_host_->window()));
141 147
142 CastVSyncSettings::GetInstance()->AddObserver(this); 148 CastVSyncSettings::GetInstance()->AddObserver(this);
143 window_tree_host_->compositor()->SetAuthoritativeVSyncInterval( 149 window_tree_host_->compositor()->SetAuthoritativeVSyncInterval(
144 CastVSyncSettings::GetInstance()->GetVSyncInterval()); 150 CastVSyncSettings::GetInstance()->GetVSyncInterval());
145 151
146 window_tree_host_->Show(); 152 window_tree_host_->Show();
147 } 153 }
148 154
149 void CastWindowManagerAura::TearDown() { 155 void CastWindowManagerAura::TearDown() {
150 if (!window_tree_host_) { 156 if (!window_tree_host_) {
151 return; 157 return;
152 } 158 }
159 focused_window_ = nullptr;
153 CastVSyncSettings::GetInstance()->RemoveObserver(this); 160 CastVSyncSettings::GetInstance()->RemoveObserver(this);
154 capture_client_.reset(); 161 capture_client_.reset();
162 aura::client::SetFocusClient(window_tree_host_->window(), nullptr);
155 window_tree_host_.reset(); 163 window_tree_host_.reset();
156 } 164 }
157 165
158 void CastWindowManagerAura::AddWindow(gfx::NativeView child) { 166 void CastWindowManagerAura::AddWindow(gfx::NativeView child) {
159 LOG(INFO) << "Adding window: " << child->id() << ": " << child->GetName(); 167 LOG(INFO) << "Adding window: " << child->id() << ": " << child->GetName();
160 Setup(); 168 Setup();
161 169
162 DCHECK(child); 170 DCHECK(child);
163 aura::Window* parent = window_tree_host_->window(); 171 aura::Window* parent = window_tree_host_->window();
164 if (!parent->Contains(child)) { 172 if (!parent->Contains(child)) {
165 parent->AddChild(child); 173 parent->AddChild(child);
166 } 174 }
167 175
168 parent->StackChildAtTop(child); 176 // Determine z-order relative to existing windows.
177 aura::Window::Windows windows = parent->children();
178 aura::Window* above = nullptr;
179 aura::Window* below = nullptr;
180 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'
181 if (other == child) {
182 continue;
183 } 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.
184 (!below || other->id() > below->id())) {
185 below = other;
186 } else if ((other->id() > child->id()) &&
187 (!above || other->id() < above->id())) {
188 above = other;
189 }
190 }
191
192 // Adjust the z-order of the new child window.
193 if (above) {
194 parent->StackChildBelow(child, above);
195 } else if (below) {
196 parent->StackChildAbove(child, below);
197 } else {
198 parent->StackChildAtBottom(child);
199 }
169 child->SetBounds(window_tree_host_->window()->bounds()); 200 child->SetBounds(window_tree_host_->window()->bounds());
170 } 201 }
171 202
172 void CastWindowManagerAura::OnVSyncIntervalChanged(base::TimeDelta interval) { 203 void CastWindowManagerAura::OnVSyncIntervalChanged(base::TimeDelta interval) {
173 DCHECK(window_tree_host_.get()); 204 DCHECK(window_tree_host_.get());
174 window_tree_host_->compositor()->SetAuthoritativeVSyncInterval(interval); 205 window_tree_host_->compositor()->SetAuthoritativeVSyncInterval(interval);
175 } 206 }
176 207
208 //////////////////////////////////////////////////////////////////////
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.
209 // Implementation for aura::WindowObserver
210
211 void CastWindowManagerAura::OnWindowVisibilityChanged(aura::Window* window,
212 bool visible) {
213 if (!kFocusFollowsVisibility) {
214 return;
215 }
216 if (!visible && (window == focused_window_)) {
217 UpdateWindowFocus(focused_window_);
218 } else if (visible) {
219 UpdateWindowFocus(nullptr);
220 }
221 }
222
223 void CastWindowManagerAura::OnWindowDestroying(aura::Window* window) {
224 aura::Window* top_level = GetTopLevelWindow(window);
225 DCHECK(top_level);
226 LOG(INFO) << "Removing window top-level: " << top_level->id() << ": "
227 << top_level->GetName() << ", window: " << window->id() << ": "
228 << window->GetName();
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 top-level: " << top_level->id() << ": "
260 << top_level->GetName() << ", window: " << window->id() << ": "
261 << window->GetName();
262 } else {
263 ++iter;
264 }
265 }
266
267 if (was_focused) {
268 UpdateWindowFocus(focused_window_);
269 }
270 }
271
272 //////////////////////////////////////////////////////////////////////
273 // Implementation for aura::client::FocusClient
274
275 void CastWindowManagerAura::AddObserver(
276 aura::client::FocusChangeObserver* observer) {
277 focus_observers_.AddObserver(observer);
278 }
279
280 void CastWindowManagerAura::RemoveObserver(
281 aura::client::FocusChangeObserver* observer) {
282 focus_observers_.RemoveObserver(observer);
283 }
284
285 void CastWindowManagerAura::FocusWindow(aura::Window* window) {
286 if (window) {
287 if (!window->CanFocus()) {
288 return;
289 }
290 aura::Window* top_level = GetTopLevelWindow(window);
291 DCHECK(top_level);
292 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.
293 << top_level->GetName() << ", window: " << window->id() << ": "
294 << window->GetName();
295 auto iter =
296 std::find(focusable_windows_.begin(), focusable_windows_.end(), window);
297 if (iter == focusable_windows_.end()) {
298 window->AddObserver(this);
299 focusable_windows_.push_back(window);
300 }
301 }
302
303 UpdateWindowFocus(nullptr);
304 }
305
306 void CastWindowManagerAura::ResetFocusWithinActiveWindow(aura::Window* window) {
307 // Sets focus to |window| if it's within the active window (a child of the
308 // focused window).
309 if (focused_window_ && focused_window_->Contains(window)) {
310 FocusWindow(window);
311 }
312 }
313
314 aura::Window* CastWindowManagerAura::GetFocusedWindow() {
315 return focused_window_;
316 }
317
318 void CastWindowManagerAura::UpdateWindowFocus(aura::Window* skip) {
319 aura::Window* window = GetWindowToFocus(skip);
320 if (window == focused_window_) {
321 return;
322 }
323
324 if (window) {
325 aura::Window* top_level = GetTopLevelWindow(window);
326 DCHECK(top_level);
327 LOG(INFO) << "Switching focus to top-level: " << top_level->id() << ": "
328 << top_level->GetName() << ", window: " << window->id() << ": "
329 << window->GetName();
330 }
331
332 aura::Window* unfocus_window = focused_window_;
333 focused_window_ = window;
334
335 for (aura::client::FocusChangeObserver& observer : focus_observers_) {
336 observer.OnWindowFocused(focused_window_, unfocus_window);
337 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_.
338 return;
339 }
340 }
341
342 if (unfocus_window) {
343 aura::client::FocusChangeObserver* focus_observer =
344 aura::client::GetFocusChangeObserver(unfocus_window);
345 if (focus_observer) {
346 focus_observer->OnWindowFocused(focused_window_, unfocus_window);
347 if (focused_window_ != window) {
348 return;
349 }
350 }
351 }
352 if (focused_window_) {
353 aura::client::FocusChangeObserver* focus_observer =
354 aura::client::GetFocusChangeObserver(focused_window_);
355 if (focus_observer) {
356 focus_observer->OnWindowFocused(focused_window_, unfocus_window);
357 if (focused_window_ != window) {
358 return;
359 }
360 }
361 }
362 }
363
364 aura::Window* CastWindowManagerAura::GetWindowToFocus(aura::Window* skip) {
365 aura::Window* next = nullptr;
366 aura::Window* next_top_level = nullptr;
367 for (auto iter = focusable_windows_.begin(); iter != focusable_windows_.end();
368 ++iter) {
369 aura::Window* window = *iter;
370 if (window == skip || !window->CanFocus() ||
371 (kFocusFollowsVisibility && !window->IsVisible())) {
372 continue;
373 }
374
375 aura::Window* top_level = GetTopLevelWindow(window);
376 DCHECK(window_tree_host_->window()->Contains(top_level));
377 if (top_level && (!next || top_level->id() >= next_top_level->id())) {
378 next = window;
379 next_top_level = top_level;
380 }
381 }
382 return next;
383 }
384
385 aura::Window* CastWindowManagerAura::GetTopLevelWindow(aura::Window* window) {
386 while (window->parent() && window->parent() != window_tree_host_->window()) {
387 window = window->parent();
388 }
389 return window;
390 }
391
177 } // namespace chromecast 392 } // namespace chromecast
OLDNEW
« 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