OLD | NEW |
---|---|
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 Loading... | |
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 |
OLD | NEW |