Index: ash/wm/workspace/workspace_layout_manager2.cc |
=================================================================== |
--- ash/wm/workspace/workspace_layout_manager2.cc (revision 165163) |
+++ ash/wm/workspace/workspace_layout_manager2.cc (working copy) |
@@ -1,388 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "ash/wm/workspace/workspace_layout_manager2.h" |
- |
-#include "ash/ash_switches.h" |
-#include "ash/screen_ash.h" |
-#include "ash/shell.h" |
-#include "ash/wm/always_on_top_controller.h" |
-#include "ash/wm/base_layout_manager.h" |
-#include "ash/wm/window_animations.h" |
-#include "ash/wm/window_properties.h" |
-#include "ash/wm/window_util.h" |
-#include "ash/wm/workspace/workspace2.h" |
-#include "ash/wm/workspace/workspace_manager2.h" |
-#include "ash/wm/workspace/workspace_window_resizer.h" |
-#include "base/auto_reset.h" |
-#include "base/command_line.h" |
-#include "ui/aura/client/aura_constants.h" |
-#include "ui/aura/root_window.h" |
-#include "ui/aura/window.h" |
-#include "ui/aura/window_observer.h" |
-#include "ui/base/events/event.h" |
-#include "ui/base/ui_base_types.h" |
- |
-using aura::Window; |
- |
-namespace ash { |
- |
-namespace internal { |
- |
-namespace { |
- |
-typedef std::map<const aura::Window*, gfx::Rect> BoundsMap; |
- |
-// Adds an entry from |window| to its bounds and recursively invokes this for |
-// all children. |
-void BuildWindowBoundsMap(const aura::Window* window, BoundsMap* bounds_map) { |
- (*bounds_map)[window] = window->bounds(); |
- for (size_t i = 0; i < window->children().size(); ++i) |
- BuildWindowBoundsMap(window->children()[i], bounds_map); |
-} |
- |
-// Resets |window|s bounds from |bounds_map| if currently empty. Recusively |
-// invokes this for all children. |
-void ResetBoundsIfNecessary(const BoundsMap& bounds_map, aura::Window* window) { |
- if (window->bounds().IsEmpty() && window->GetTargetBounds().IsEmpty()) { |
- BoundsMap::const_iterator i = bounds_map.find(window); |
- if (i != bounds_map.end()) |
- window->SetBounds(i->second); |
- } |
- for (size_t i = 0; i < window->children().size(); ++i) |
- ResetBoundsIfNecessary(bounds_map, window->children()[i]); |
-} |
- |
-// Resets |window|s bounds from |bounds_map| if |window| is marked as a |
-// constrained window. Recusively invokes this for all children. |
-// TODO(sky): this should key off window type. |
-void ResetConstrainedWindowBoundsIfNecessary(const BoundsMap& bounds_map, |
- aura::Window* window) { |
- if (window->GetProperty(aura::client::kConstrainedWindowKey)) { |
- BoundsMap::const_iterator i = bounds_map.find(window); |
- if (i != bounds_map.end()) |
- window->SetBounds(i->second); |
- } |
- for (size_t i = 0; i < window->children().size(); ++i) |
- ResetConstrainedWindowBoundsIfNecessary(bounds_map, window->children()[i]); |
-} |
- |
-} // namespace |
- |
-WorkspaceLayoutManager2::WorkspaceLayoutManager2(Workspace2* workspace) |
- : root_window_(workspace->window()->GetRootWindow()), |
- workspace_(workspace), |
- work_area_(ScreenAsh::GetDisplayWorkAreaBoundsInParent( |
- workspace->window()->parent())) { |
- Shell::GetInstance()->AddShellObserver(this); |
- root_window_->AddRootWindowObserver(this); |
- root_window_->AddObserver(this); |
-} |
- |
-WorkspaceLayoutManager2::~WorkspaceLayoutManager2() { |
- if (root_window_) { |
- root_window_->RemoveObserver(this); |
- root_window_->RemoveRootWindowObserver(this); |
- } |
- for (WindowSet::const_iterator i = windows_.begin(); i != windows_.end(); ++i) |
- (*i)->RemoveObserver(this); |
- Shell::GetInstance()->RemoveShellObserver(this); |
-} |
- |
-void WorkspaceLayoutManager2::OnWindowAddedToLayout(Window* child) { |
- // Adjust window bounds in case that the new child is out of the workspace. |
- AdjustWindowSizeForScreenChange(child, ADJUST_WINDOW_DISPLAY_INSETS_CHANGED); |
- |
- windows_.insert(child); |
- child->AddObserver(this); |
- |
- // Only update the bounds if the window has a show state that depends on the |
- // workspace area. |
- if (wm::IsWindowMaximized(child) || wm::IsWindowFullscreen(child)) |
- UpdateBoundsFromShowState(child); |
- |
- workspace_manager()->OnWindowAddedToWorkspace(workspace_, child); |
-} |
- |
-void WorkspaceLayoutManager2::OnWillRemoveWindowFromLayout(Window* child) { |
- windows_.erase(child); |
- child->RemoveObserver(this); |
- workspace_manager()->OnWillRemoveWindowFromWorkspace(workspace_, child); |
-} |
- |
-void WorkspaceLayoutManager2::OnWindowRemovedFromLayout(Window* child) { |
- workspace_manager()->OnWindowRemovedFromWorkspace(workspace_, child); |
-} |
- |
-void WorkspaceLayoutManager2::OnChildWindowVisibilityChanged(Window* child, |
- bool visible) { |
- if (visible && wm::IsWindowMinimized(child)) { |
- // Attempting to show a minimized window. Unminimize it. |
- child->SetProperty(aura::client::kShowStateKey, |
- child->GetProperty(internal::kRestoreShowStateKey)); |
- child->ClearProperty(internal::kRestoreShowStateKey); |
- } |
- workspace_manager()->OnWorkspaceChildWindowVisibilityChanged(workspace_, |
- child); |
-} |
- |
-void WorkspaceLayoutManager2::SetChildBounds( |
- Window* child, |
- const gfx::Rect& requested_bounds) { |
- if (!GetTrackedByWorkspace(child)) { |
- SetChildBoundsDirect(child, requested_bounds); |
- return; |
- } |
- gfx::Rect child_bounds(requested_bounds); |
- // Some windows rely on this to set their initial bounds. |
- if (!SetMaximizedOrFullscreenBounds(child)) { |
- // Non-maximized/full-screen windows have their size constrained to the |
- // work-area. |
- child_bounds.set_width(std::min(work_area_.width(), child_bounds.width())); |
- child_bounds.set_height( |
- std::min(work_area_.height(), child_bounds.height())); |
- SetChildBoundsDirect(child, child_bounds); |
- } |
- workspace_manager()->OnWorkspaceWindowChildBoundsChanged(workspace_, child); |
-} |
- |
-void WorkspaceLayoutManager2::OnRootWindowResized(const aura::RootWindow* root, |
- const gfx::Size& old_size) { |
- AdjustWindowSizesForScreenChange(ADJUST_WINDOW_SCREEN_SIZE_CHANGED); |
-} |
- |
-void WorkspaceLayoutManager2::OnDisplayWorkAreaInsetsChanged() { |
- if (workspace_manager()->active_workspace_ == workspace_) { |
- const gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent( |
- workspace_->window()->parent())); |
- if (work_area != work_area_) |
- AdjustWindowSizesForScreenChange(ADJUST_WINDOW_DISPLAY_INSETS_CHANGED); |
- } |
-} |
- |
-void WorkspaceLayoutManager2::OnWindowPropertyChanged(Window* window, |
- const void* key, |
- intptr_t old) { |
- if (key == aura::client::kShowStateKey) { |
- ui::WindowShowState old_state = static_cast<ui::WindowShowState>(old); |
- ui::WindowShowState new_state = |
- window->GetProperty(aura::client::kShowStateKey); |
- if (old_state != ui::SHOW_STATE_MINIMIZED && |
- GetRestoreBoundsInScreen(window) == NULL && |
- WorkspaceManager2::IsMaximizedState(new_state) && |
- !WorkspaceManager2::IsMaximizedState(old_state)) { |
- SetRestoreBoundsInParent(window, window->bounds()); |
- } |
- // When restoring from a minimized state, we want to restore to the |
- // previous (maybe L/R maximized) state. Since we do also want to keep the |
- // restore rectangle, we set the restore rectangle to the rectangle we want |
- // to restore to and restore it after we switched so that it is preserved. |
- gfx::Rect restore; |
- if (old_state == ui::SHOW_STATE_MINIMIZED && |
- (new_state == ui::SHOW_STATE_NORMAL || |
- new_state == ui::SHOW_STATE_DEFAULT) && |
- GetRestoreBoundsInScreen(window)) { |
- restore = *GetRestoreBoundsInScreen(window); |
- SetRestoreBoundsInScreen(window, window->bounds()); |
- } |
- |
- // If maximizing or restoring, clone the layer. WorkspaceManager will use it |
- // (and take ownership of it) when animating. Ideally we could use that of |
- // BaseLayoutManager, but that proves problematic. In particular when |
- // restoring we need to animate on top of the workspace animating in. |
- ui::Layer* cloned_layer = NULL; |
- BoundsMap bounds_map; |
- if (wm::IsActiveWindow(window) && |
- ((WorkspaceManager2::IsMaximizedState(new_state) && |
- wm::IsWindowStateNormal(old_state)) || |
- (!WorkspaceManager2::IsMaximizedState(new_state) && |
- WorkspaceManager2::IsMaximizedState(old_state) && |
- new_state != ui::SHOW_STATE_MINIMIZED))) { |
- BuildWindowBoundsMap(window, &bounds_map); |
- cloned_layer = wm::RecreateWindowLayers(window, false); |
- // Constrained windows don't get their bounds reset when we update the |
- // window bounds. Leaving them empty is unexpected, so we reset them now. |
- ResetConstrainedWindowBoundsIfNecessary(bounds_map, window); |
- } |
- UpdateBoundsFromShowState(window); |
- |
- if (cloned_layer) { |
- // Even though we just set the bounds not all descendants may have valid |
- // bounds. For example, constrained windows don't resize with the parent. |
- // Ensure that all windows that had a bounds before we cloned the layer |
- // have a bounds now. |
- ResetBoundsIfNecessary(bounds_map, window); |
- } |
- |
- ShowStateChanged(window, old_state, cloned_layer); |
- |
- // Set the restore rectangle to the previously set restore rectangle. |
- if (!restore.IsEmpty()) |
- SetRestoreBoundsInScreen(window, restore); |
- } |
- |
- if (key == internal::kWindowTrackedByWorkspaceKey && |
- GetTrackedByWorkspace(window)) { |
- workspace_manager()->OnTrackedByWorkspaceChanged(workspace_, window); |
- } |
- |
- if (key == aura::client::kAlwaysOnTopKey && |
- window->GetProperty(aura::client::kAlwaysOnTopKey)) { |
- internal::AlwaysOnTopController* controller = |
- window->GetRootWindow()->GetProperty( |
- internal::kAlwaysOnTopControllerKey); |
- controller->GetContainer(window)->AddChild(window); |
- } |
-} |
- |
-void WorkspaceLayoutManager2::OnWindowDestroying(aura::Window* window) { |
- if (root_window_ == window) { |
- root_window_->RemoveObserver(this); |
- root_window_ = NULL; |
- } |
-} |
- |
-void WorkspaceLayoutManager2::ShowStateChanged( |
- Window* window, |
- ui::WindowShowState last_show_state, |
- ui::Layer* cloned_layer) { |
- if (wm::IsWindowMinimized(window)) { |
- DCHECK(!cloned_layer); |
- // Save the previous show state so that we can correctly restore it. |
- window->SetProperty(internal::kRestoreShowStateKey, last_show_state); |
- SetWindowVisibilityAnimationType( |
- window, WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE); |
- workspace_manager()->OnWorkspaceWindowShowStateChanged( |
- workspace_, window, last_show_state, NULL); |
- window->Hide(); |
- if (wm::IsActiveWindow(window)) |
- wm::DeactivateWindow(window); |
- } else { |
- if ((window->TargetVisibility() || |
- last_show_state == ui::SHOW_STATE_MINIMIZED) && |
- !window->layer()->visible()) { |
- // The layer may be hidden if the window was previously minimized. Make |
- // sure it's visible. |
- window->Show(); |
- } |
- workspace_manager()->OnWorkspaceWindowShowStateChanged( |
- workspace_, window, last_show_state, cloned_layer); |
- } |
-} |
- |
-void WorkspaceLayoutManager2::AdjustWindowSizesForScreenChange( |
- AdjustWindowReason reason) { |
- work_area_ = ScreenAsh::GetDisplayWorkAreaBoundsInParent( |
- workspace_->window()->parent()); |
- // If a user plugs an external display into a laptop running Aura the |
- // display size will change. Maximized windows need to resize to match. |
- // We also do this when developers running Aura on a desktop manually resize |
- // the host window. |
- // We also need to do this when the work area insets changes. |
- for (WindowSet::const_iterator it = windows_.begin(); |
- it != windows_.end(); |
- ++it) { |
- AdjustWindowSizeForScreenChange(*it, reason); |
- } |
-} |
- |
-void WorkspaceLayoutManager2::AdjustWindowSizeForScreenChange( |
- Window* window, |
- AdjustWindowReason reason) { |
- if (GetTrackedByWorkspace(window) && |
- !SetMaximizedOrFullscreenBounds(window)) { |
- if (reason == ADJUST_WINDOW_SCREEN_SIZE_CHANGED) { |
- // The work area may be smaller than the full screen. Put as much of the |
- // window as possible within the display area. |
- gfx::Rect bounds = window->bounds(); |
- bounds.AdjustToFit(work_area_); |
- window->SetBounds(bounds); |
- } else if (reason == ADJUST_WINDOW_DISPLAY_INSETS_CHANGED) { |
- // Make sure the window isn't bigger than the display work area and that |
- // at least a portion of it is visible. |
- gfx::Rect bounds = window->bounds(); |
- bounds.set_width(std::min(bounds.width(), work_area_.width())); |
- bounds.set_height(std::min(bounds.height(), work_area_.height())); |
- if (!work_area_.Intersects(bounds)) { |
- int y_offset = 0; |
- if (work_area_.bottom() < bounds.y()) { |
- y_offset = work_area_.bottom() - bounds.y() - kMinimumOnScreenArea; |
- } else if (bounds.bottom() < work_area_.y()) { |
- y_offset = work_area_.y() - bounds.bottom() + kMinimumOnScreenArea; |
- } |
- |
- int x_offset = 0; |
- if (work_area_.right() < bounds.x()) { |
- x_offset = work_area_.right() - bounds.x() - kMinimumOnScreenArea; |
- } else if (bounds.right() < work_area_.x()) { |
- x_offset = work_area_.x() - bounds.right() + kMinimumOnScreenArea; |
- } |
- bounds.Offset(x_offset, y_offset); |
- } |
- if (window->bounds() != bounds) |
- window->SetBounds(bounds); |
- } |
- } |
-} |
- |
-void WorkspaceLayoutManager2::UpdateBoundsFromShowState(Window* window) { |
- // See comment in SetMaximizedOrFullscreenBounds() as to why we use parent in |
- // these calculation. |
- switch (window->GetProperty(aura::client::kShowStateKey)) { |
- case ui::SHOW_STATE_DEFAULT: |
- case ui::SHOW_STATE_NORMAL: { |
- const gfx::Rect* restore = GetRestoreBoundsInScreen(window); |
- if (restore) { |
- gfx::Rect bounds_in_parent = |
- ScreenAsh::ConvertRectFromScreen(window->parent()->parent(), |
- *restore); |
- SetChildBoundsDirect( |
- window, |
- BaseLayoutManager::BoundsWithScreenEdgeVisible( |
- window->parent()->parent(), |
- bounds_in_parent)); |
- } |
- window->ClearProperty(aura::client::kRestoreBoundsKey); |
- break; |
- } |
- |
- case ui::SHOW_STATE_MAXIMIZED: |
- case ui::SHOW_STATE_FULLSCREEN: |
- SetMaximizedOrFullscreenBounds(window); |
- break; |
- |
- default: |
- break; |
- } |
-} |
- |
-bool WorkspaceLayoutManager2::SetMaximizedOrFullscreenBounds( |
- aura::Window* window) { |
- if (!GetTrackedByWorkspace(window)) |
- return false; |
- |
- // During animations there is a transform installed on the workspace |
- // windows. For this reason this code uses the parent so that the transform is |
- // ignored. |
- if (wm::IsWindowMaximized(window)) { |
- SetChildBoundsDirect( |
- window, ScreenAsh::GetMaximizedWindowBoundsInParent( |
- window->parent()->parent())); |
- return true; |
- } |
- if (wm::IsWindowFullscreen(window)) { |
- SetChildBoundsDirect( |
- window, |
- ScreenAsh::GetDisplayBoundsInParent(window->parent()->parent())); |
- return true; |
- } |
- return false; |
-} |
- |
-WorkspaceManager2* WorkspaceLayoutManager2::workspace_manager() { |
- return workspace_->workspace_manager(); |
-} |
- |
-} // namespace internal |
-} // namespace ash |