| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "ash/wm/screen_pinning_controller.h" | 5 #include "ash/wm/screen_pinning_controller.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "ash/aura/wm_window_aura.h" | 10 #include "ash/aura/wm_window_aura.h" |
| 11 #include "ash/common/shell_window_ids.h" | 11 #include "ash/common/shell_window_ids.h" |
| 12 #include "ash/common/wm/window_dimmer.h" |
| 12 #include "ash/common/wm/window_state.h" | 13 #include "ash/common/wm/window_state.h" |
| 13 #include "ash/common/wm_shell.h" | 14 #include "ash/common/wm_shell.h" |
| 14 #include "ash/common/wm_window.h" | 15 #include "ash/common/wm_window.h" |
| 15 #include "ash/common/wm_window_observer.h" | 16 #include "ash/common/wm_window_observer.h" |
| 17 #include "ash/common/wm_window_user_data.h" |
| 16 #include "ash/display/window_tree_host_manager.h" | 18 #include "ash/display/window_tree_host_manager.h" |
| 17 #include "ash/shell.h" | 19 #include "ash/shell.h" |
| 18 #include "ash/wm/dim_window.h" | |
| 19 #include "base/auto_reset.h" | 20 #include "base/auto_reset.h" |
| 20 #include "base/logging.h" | 21 #include "base/logging.h" |
| 21 #include "base/stl_util.h" | 22 #include "base/memory/ptr_util.h" |
| 22 #include "ui/aura/window_observer.h" | 23 #include "ui/aura/window_observer.h" |
| 23 | 24 |
| 24 namespace ash { | 25 namespace ash { |
| 25 namespace { | 26 namespace { |
| 26 | 27 |
| 27 WmWindow* CreateDimWindow(WmWindow* container) { | |
| 28 DimWindow* dim_window = new DimWindow(WmWindowAura::GetAuraWindow(container)); | |
| 29 dim_window->SetDimOpacity(1); // Set whole black. | |
| 30 WmWindow* result = WmWindowAura::Get(dim_window); | |
| 31 result->SetFullscreen(); | |
| 32 result->Show(); | |
| 33 return result; | |
| 34 } | |
| 35 | |
| 36 // Returns a list of WmWindows corresponding to SystemModalContainers, | 28 // Returns a list of WmWindows corresponding to SystemModalContainers, |
| 37 // except ones whose root is shared with |pinned_window|. | 29 // except ones whose root is shared with |pinned_window|. |
| 38 std::vector<WmWindow*> GetSystemModalWindowsExceptPinned( | 30 std::vector<WmWindow*> GetSystemModalWindowsExceptPinned( |
| 39 WmWindow* pinned_window) { | 31 WmWindow* pinned_window) { |
| 40 WmWindow* pinned_root = pinned_window->GetRootWindow(); | 32 WmWindow* pinned_root = pinned_window->GetRootWindow(); |
| 41 | 33 |
| 42 std::vector<WmWindow*> result; | 34 std::vector<WmWindow*> result; |
| 43 for (WmWindow* system_modal : | 35 for (WmWindow* system_modal : |
| 44 WmWindowAura::FromAuraWindows(Shell::GetContainersFromAllRootWindows( | 36 WmWindowAura::FromAuraWindows(Shell::GetContainersFromAllRootWindows( |
| 45 kShellWindowId_SystemModalContainer, nullptr))) { | 37 kShellWindowId_SystemModalContainer, nullptr))) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 void OnWindowDestroying(aura::Window* window) override { | 139 void OnWindowDestroying(aura::Window* window) override { |
| 148 // Just in case. There is nothing we can do here. | 140 // Just in case. There is nothing we can do here. |
| 149 window->RemoveObserver(this); | 141 window->RemoveObserver(this); |
| 150 } | 142 } |
| 151 | 143 |
| 152 private: | 144 private: |
| 153 ScreenPinningController* controller_; | 145 ScreenPinningController* controller_; |
| 154 DISALLOW_COPY_AND_ASSIGN(SystemModalContainerWindowObserver); | 146 DISALLOW_COPY_AND_ASSIGN(SystemModalContainerWindowObserver); |
| 155 }; | 147 }; |
| 156 | 148 |
| 157 // Tracks DimWindow's life. | |
| 158 class ScreenPinningController::DimWindowObserver : public aura::WindowObserver { | |
| 159 public: | |
| 160 explicit DimWindowObserver(ScreenPinningController* controller) | |
| 161 : controller_(controller) {} | |
| 162 | |
| 163 void OnWindowParentChanged(aura::Window* window, | |
| 164 aura::Window* parent) override { | |
| 165 // In case of parent change, there is nothing we can do for that change. | |
| 166 // Also, it is unsafe to delete the moving window here, because it could | |
| 167 // cause SEGV. Instead, we just hide it. | |
| 168 // Note that, the window is still tracked by the ScreenPinningController, | |
| 169 // so that it should be deleted on "unpin", at least. | |
| 170 window->Hide(); | |
| 171 } | |
| 172 | |
| 173 void OnWindowDestroying(aura::Window* window) override { | |
| 174 controller_->OnDimWindowDestroying(WmWindowAura::Get(window)); | |
| 175 } | |
| 176 | |
| 177 private: | |
| 178 ScreenPinningController* controller_; | |
| 179 DISALLOW_COPY_AND_ASSIGN(DimWindowObserver); | |
| 180 }; | |
| 181 | |
| 182 ScreenPinningController::ScreenPinningController( | 149 ScreenPinningController::ScreenPinningController( |
| 183 WindowTreeHostManager* window_tree_host_manager) | 150 WindowTreeHostManager* window_tree_host_manager) |
| 184 : window_tree_host_manager_(window_tree_host_manager), | 151 : window_dimmers_(base::MakeUnique<WmWindowUserData<WindowDimmer>>()), |
| 152 window_tree_host_manager_(window_tree_host_manager), |
| 185 pinned_container_window_observer_( | 153 pinned_container_window_observer_( |
| 186 new PinnedContainerWindowObserver(this)), | 154 base::MakeUnique<PinnedContainerWindowObserver>(this)), |
| 187 pinned_container_child_window_observer_( | 155 pinned_container_child_window_observer_( |
| 188 new PinnedContainerChildWindowObserver(this)), | 156 base::MakeUnique<PinnedContainerChildWindowObserver>(this)), |
| 189 system_modal_container_window_observer_( | 157 system_modal_container_window_observer_( |
| 190 new SystemModalContainerWindowObserver(this)), | 158 base::MakeUnique<SystemModalContainerWindowObserver>(this)), |
| 191 system_modal_container_child_window_observer_( | 159 system_modal_container_child_window_observer_( |
| 192 new SystemModalContainerChildWindowObserver(this)), | 160 base::MakeUnique<SystemModalContainerChildWindowObserver>(this)) { |
| 193 dim_window_observer_(new DimWindowObserver(this)) { | |
| 194 window_tree_host_manager_->AddObserver(this); | 161 window_tree_host_manager_->AddObserver(this); |
| 195 } | 162 } |
| 196 | 163 |
| 197 ScreenPinningController::~ScreenPinningController() { | 164 ScreenPinningController::~ScreenPinningController() { |
| 198 window_tree_host_manager_->RemoveObserver(this); | 165 window_tree_host_manager_->RemoveObserver(this); |
| 199 } | 166 } |
| 200 | 167 |
| 201 bool ScreenPinningController::IsPinned() const { | 168 bool ScreenPinningController::IsPinned() const { |
| 202 return pinned_window_ != nullptr; | 169 return pinned_window_ != nullptr; |
| 203 } | 170 } |
| 204 | 171 |
| 205 void ScreenPinningController::SetPinnedWindow(WmWindow* pinned_window) { | 172 void ScreenPinningController::SetPinnedWindow(WmWindow* pinned_window) { |
| 173 window_dimmers_->clear(); |
| 174 |
| 206 if (pinned_window->GetWindowState()->IsPinned()) { | 175 if (pinned_window->GetWindowState()->IsPinned()) { |
| 207 if (pinned_window_) { | 176 if (pinned_window_) { |
| 208 LOG(DFATAL) << "Pinned mode is enabled, while it is already in " | 177 LOG(DFATAL) << "Pinned mode is enabled, while it is already in " |
| 209 << "the pinned mode"; | 178 << "the pinned mode"; |
| 210 return; | 179 return; |
| 211 } | 180 } |
| 212 | 181 |
| 213 WmWindow* container = pinned_window->GetParent(); | 182 WmWindow* container = pinned_window->GetParent(); |
| 214 std::vector<WmWindow*> system_modal_containers = | 183 std::vector<WmWindow*> system_modal_containers = |
| 215 GetSystemModalWindowsExceptPinned(pinned_window); | 184 GetSystemModalWindowsExceptPinned(pinned_window); |
| 216 | 185 |
| 217 // Set up the container which has the pinned window. | 186 // Set up the container which has the pinned window. |
| 218 pinned_window_ = pinned_window; | 187 pinned_window_ = pinned_window; |
| 219 background_window_ = CreateDimWindow(container); | |
| 220 container->StackChildAtTop(pinned_window); | 188 container->StackChildAtTop(pinned_window); |
| 221 container->StackChildBelow(background_window_, pinned_window); | 189 container->StackChildBelow(CreateWindowDimmer(container), pinned_window); |
| 222 | 190 |
| 223 // Set the dim windows to the system containers, other than the one which | 191 // Set the dim windows to the system containers, other than the one which |
| 224 // the root window of the pinned window holds. | 192 // the root window of the pinned window holds. |
| 225 for (WmWindow* system_modal : system_modal_containers) { | 193 for (WmWindow* system_modal : system_modal_containers) |
| 226 WmWindow* dim_window = CreateDimWindow(system_modal); | 194 system_modal->StackChildAtBottom(CreateWindowDimmer(system_modal)); |
| 227 system_modal->StackChildAtBottom(dim_window); | |
| 228 dim_windows_.push_back(dim_window); | |
| 229 WmWindowAura::GetAuraWindow(dim_window) | |
| 230 ->AddObserver(dim_window_observer_.get()); | |
| 231 } | |
| 232 | 195 |
| 233 // Set observers. | 196 // Set observers. |
| 234 WmWindowAura::GetAuraWindow(container)->AddObserver( | 197 WmWindowAura::GetAuraWindow(container)->AddObserver( |
| 235 pinned_container_window_observer_.get()); | 198 pinned_container_window_observer_.get()); |
| 236 AddObserverToChildren(container, | 199 AddObserverToChildren(container, |
| 237 pinned_container_child_window_observer_.get()); | 200 pinned_container_child_window_observer_.get()); |
| 238 for (WmWindow* system_modal : system_modal_containers) { | 201 for (WmWindow* system_modal : system_modal_containers) { |
| 239 WmWindowAura::GetAuraWindow(system_modal) | 202 WmWindowAura::GetAuraWindow(system_modal) |
| 240 ->AddObserver(system_modal_container_window_observer_.get()); | 203 ->AddObserver(system_modal_container_window_observer_.get()); |
| 241 AddObserverToChildren( | 204 AddObserverToChildren( |
| (...skipping 16 matching lines...) Expand all Loading... |
| 258 RemoveObserverFromChildren( | 221 RemoveObserverFromChildren( |
| 259 system_modal, system_modal_container_child_window_observer_.get()); | 222 system_modal, system_modal_container_child_window_observer_.get()); |
| 260 WmWindowAura::GetAuraWindow(system_modal) | 223 WmWindowAura::GetAuraWindow(system_modal) |
| 261 ->RemoveObserver(system_modal_container_window_observer_.get()); | 224 ->RemoveObserver(system_modal_container_window_observer_.get()); |
| 262 } | 225 } |
| 263 RemoveObserverFromChildren(container, | 226 RemoveObserverFromChildren(container, |
| 264 pinned_container_child_window_observer_.get()); | 227 pinned_container_child_window_observer_.get()); |
| 265 WmWindowAura::GetAuraWindow(container)->RemoveObserver( | 228 WmWindowAura::GetAuraWindow(container)->RemoveObserver( |
| 266 pinned_container_window_observer_.get()); | 229 pinned_container_window_observer_.get()); |
| 267 | 230 |
| 268 // Delete the dim windows. This works, but do not use RAII, because | |
| 269 // the window is owned by the parent. | |
| 270 // Note: dim_windows_ will be updated during the deletion. So, copy is | |
| 271 // needed. | |
| 272 for (WmWindow* dim_window : std::vector<WmWindow*>(dim_windows_)) { | |
| 273 delete WmWindowAura::GetAuraWindow(dim_window); | |
| 274 } | |
| 275 DCHECK(dim_windows_.empty()); | |
| 276 delete WmWindowAura::GetAuraWindow(background_window_); | |
| 277 background_window_ = nullptr; | |
| 278 | |
| 279 pinned_window_ = nullptr; | 231 pinned_window_ = nullptr; |
| 280 } | 232 } |
| 281 | 233 |
| 282 WmShell::Get()->NotifyPinnedStateChanged(pinned_window); | 234 WmShell::Get()->NotifyPinnedStateChanged(pinned_window); |
| 283 } | 235 } |
| 284 | 236 |
| 285 void ScreenPinningController::OnWindowAddedToPinnedContainer( | 237 void ScreenPinningController::OnWindowAddedToPinnedContainer( |
| 286 WmWindow* new_window) { | 238 WmWindow* new_window) { |
| 287 KeepPinnedWindowOnTop(); | 239 KeepPinnedWindowOnTop(); |
| 288 WmWindowAura::GetAuraWindow(new_window) | 240 WmWindowAura::GetAuraWindow(new_window) |
| 289 ->AddObserver(pinned_container_child_window_observer_.get()); | 241 ->AddObserver(pinned_container_child_window_observer_.get()); |
| 290 } | 242 } |
| 291 | 243 |
| 292 void ScreenPinningController::OnWillRemoveWindowFromPinnedContainer( | 244 void ScreenPinningController::OnWillRemoveWindowFromPinnedContainer( |
| 293 WmWindow* window) { | 245 WmWindow* window) { |
| 294 WmWindowAura::GetAuraWindow(window)->RemoveObserver( | 246 WmWindowAura::GetAuraWindow(window)->RemoveObserver( |
| 295 pinned_container_child_window_observer_.get()); | 247 pinned_container_child_window_observer_.get()); |
| 296 if (window == pinned_window_) { | 248 if (window == pinned_window_) { |
| 297 pinned_window_->GetWindowState()->Restore(); | 249 pinned_window_->GetWindowState()->Restore(); |
| 298 return; | 250 return; |
| 299 } | 251 } |
| 300 if (window == background_window_) { | |
| 301 background_window_ = nullptr; | |
| 302 return; | |
| 303 } | |
| 304 } | 252 } |
| 305 | 253 |
| 306 void ScreenPinningController::OnPinnedContainerWindowStackingChanged( | 254 void ScreenPinningController::OnPinnedContainerWindowStackingChanged( |
| 307 WmWindow* window) { | 255 WmWindow* window) { |
| 308 KeepPinnedWindowOnTop(); | 256 KeepPinnedWindowOnTop(); |
| 309 } | 257 } |
| 310 | 258 |
| 311 void ScreenPinningController::OnWindowAddedToSystemModalContainer( | 259 void ScreenPinningController::OnWindowAddedToSystemModalContainer( |
| 312 WmWindow* new_window) { | 260 WmWindow* new_window) { |
| 313 KeepDimWindowAtBottom(new_window->GetParent()); | 261 KeepDimWindowAtBottom(new_window->GetParent()); |
| 314 WmWindowAura::GetAuraWindow(new_window) | 262 WmWindowAura::GetAuraWindow(new_window) |
| 315 ->AddObserver(system_modal_container_child_window_observer_.get()); | 263 ->AddObserver(system_modal_container_child_window_observer_.get()); |
| 316 } | 264 } |
| 317 | 265 |
| 318 void ScreenPinningController::OnWillRemoveWindowFromSystemModalContainer( | 266 void ScreenPinningController::OnWillRemoveWindowFromSystemModalContainer( |
| 319 WmWindow* window) { | 267 WmWindow* window) { |
| 320 WmWindowAura::GetAuraWindow(window)->RemoveObserver( | 268 WmWindowAura::GetAuraWindow(window)->RemoveObserver( |
| 321 system_modal_container_child_window_observer_.get()); | 269 system_modal_container_child_window_observer_.get()); |
| 322 } | 270 } |
| 323 | 271 |
| 324 void ScreenPinningController::OnSystemModalContainerWindowStackingChanged( | 272 void ScreenPinningController::OnSystemModalContainerWindowStackingChanged( |
| 325 WmWindow* window) { | 273 WmWindow* window) { |
| 326 KeepDimWindowAtBottom(window->GetParent()); | 274 KeepDimWindowAtBottom(window->GetParent()); |
| 327 } | 275 } |
| 328 | 276 |
| 329 void ScreenPinningController::OnDimWindowDestroying(WmWindow* window) { | 277 WmWindow* ScreenPinningController::CreateWindowDimmer(WmWindow* container) { |
| 330 dim_windows_.erase( | 278 std::unique_ptr<WindowDimmer> window_dimmer = |
| 331 std::find(dim_windows_.begin(), dim_windows_.end(), window)); | 279 base::MakeUnique<WindowDimmer>(container); |
| 280 window_dimmer->SetDimOpacity(1); // Fully opaque. |
| 281 window_dimmer->window()->SetFullscreen(); |
| 282 window_dimmer->window()->Show(); |
| 283 WmWindow* window = window_dimmer->window(); |
| 284 window_dimmers_->Set(container, std::move(window_dimmer)); |
| 285 return window; |
| 332 } | 286 } |
| 333 | 287 |
| 334 void ScreenPinningController::OnDisplayConfigurationChanged() { | 288 void ScreenPinningController::OnDisplayConfigurationChanged() { |
| 335 // Note: this is called on display attached or detached. | 289 // Note: this is called on display attached or detached. |
| 336 if (!IsPinned()) | 290 if (!IsPinned()) |
| 337 return; | 291 return; |
| 338 | 292 |
| 339 // On display detaching, all necessary windows are transfered to the | 293 // On display detaching, all necessary windows are transfered to the |
| 340 // primary display's tree, and called this. | 294 // primary display's tree, and called this. |
| 341 // So, delete the dim windows which are not a part of target system modal | 295 // So, delete WindowDimmers which are not a part of target system modal |
| 342 // container. | 296 // container. |
| 343 // On display attaching, the new system modal container does not have the | 297 // On display attaching, the new system modal container does not have the |
| 344 // dim window. So create it. | 298 // WindowDimmer. So create it. |
| 345 | 299 |
| 346 // First, delete unnecessary dim windows. | 300 // First, delete unnecessary WindowDimmers. |
| 347 // The delete will update dim_windows_, so create the copy is needed. | 301 for (WmWindow* container : window_dimmers_->GetWindows()) { |
| 348 for (WmWindow* dim_window : std::vector<WmWindow*>(dim_windows_)) { | 302 if (container != pinned_window_->GetParent() && |
| 349 if (!dim_window->GetTargetVisibility()) | 303 !window_dimmers_->Get(container)->window()->GetTargetVisibility()) { |
| 350 delete WmWindowAura::GetAuraWindow(dim_window); | 304 window_dimmers_->Set(container, nullptr); |
| 305 } |
| 351 } | 306 } |
| 352 | 307 |
| 353 // Then, create missing dim_windows. | 308 // Then, create missing WindowDimmers. |
| 354 std::vector<WmWindow*> system_modal_containers = | 309 std::vector<WmWindow*> system_modal_containers = |
| 355 GetSystemModalWindowsExceptPinned(pinned_window_); | 310 GetSystemModalWindowsExceptPinned(pinned_window_); |
| 356 for (WmWindow* system_modal : system_modal_containers) { | 311 for (WmWindow* system_modal : system_modal_containers) { |
| 357 const std::vector<WmWindow*> children = system_modal->GetChildren(); | 312 if (window_dimmers_->Get(system_modal)) { |
| 358 if (!children.empty() && base::ContainsValue(dim_windows_, children[0])) { | 313 // |system_modal| already has a WindowDimmer. |
| 359 // The system modal dialog has the dim window. | |
| 360 continue; | 314 continue; |
| 361 } | 315 } |
| 362 | 316 |
| 363 // This is the new system modal dialog. | 317 // This is the new system modal dialog. |
| 364 WmWindow* dim_window = CreateDimWindow(system_modal); | 318 system_modal->StackChildAtBottom(CreateWindowDimmer(system_modal)); |
| 365 system_modal->StackChildAtBottom(dim_window); | |
| 366 dim_windows_.push_back(dim_window); | |
| 367 WmWindowAura::GetAuraWindow(dim_window) | |
| 368 ->AddObserver(dim_window_observer_.get()); | |
| 369 | 319 |
| 370 // Set observers to the tree. | 320 // Set observers to the tree. |
| 371 WmWindowAura::GetAuraWindow(system_modal) | 321 WmWindowAura::GetAuraWindow(system_modal) |
| 372 ->AddObserver(system_modal_container_window_observer_.get()); | 322 ->AddObserver(system_modal_container_window_observer_.get()); |
| 373 AddObserverToChildren(system_modal, | 323 AddObserverToChildren(system_modal, |
| 374 system_modal_container_child_window_observer_.get()); | 324 system_modal_container_child_window_observer_.get()); |
| 375 } | 325 } |
| 376 } | 326 } |
| 377 | 327 |
| 378 void ScreenPinningController::KeepPinnedWindowOnTop() { | 328 void ScreenPinningController::KeepPinnedWindowOnTop() { |
| 379 if (in_restacking_) | 329 if (in_restacking_) |
| 380 return; | 330 return; |
| 381 | 331 |
| 382 base::AutoReset<bool> auto_reset(&in_restacking_, true); | 332 base::AutoReset<bool> auto_reset(&in_restacking_, true); |
| 383 WmWindow* container = pinned_window_->GetParent(); | 333 WmWindow* container = pinned_window_->GetParent(); |
| 384 container->StackChildAtTop(pinned_window_); | 334 container->StackChildAtTop(pinned_window_); |
| 385 container->StackChildBelow(background_window_, pinned_window_); | 335 WindowDimmer* pinned_window_dimmer = window_dimmers_->Get(container); |
| 336 if (pinned_window_dimmer && pinned_window_dimmer->window()) |
| 337 container->StackChildBelow(pinned_window_dimmer->window(), pinned_window_); |
| 386 } | 338 } |
| 387 | 339 |
| 388 void ScreenPinningController::KeepDimWindowAtBottom(WmWindow* container) { | 340 void ScreenPinningController::KeepDimWindowAtBottom(WmWindow* container) { |
| 389 if (in_restacking_) | 341 if (in_restacking_) |
| 390 return; | 342 return; |
| 391 | 343 |
| 392 base::AutoReset<bool> auto_reset(&in_restacking_, true); | 344 WindowDimmer* window_dimmer = window_dimmers_->Get(container); |
| 393 for (WmWindow* dim_window : dim_windows_) { | 345 if (window_dimmer) { |
| 394 if (dim_window->GetParent() == container) { | 346 base::AutoReset<bool> auto_reset(&in_restacking_, true); |
| 395 container->StackChildAtBottom(dim_window); | 347 container->StackChildAtBottom(window_dimmer->window()); |
| 396 break; | |
| 397 } | |
| 398 } | 348 } |
| 399 } | 349 } |
| 400 | 350 |
| 401 } // namespace ash | 351 } // namespace ash |
| OLD | NEW |