Chromium Code Reviews| 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 |