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