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 #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 |