Index: ash/common/wm_root_window_controller.cc |
diff --git a/ash/common/wm_root_window_controller.cc b/ash/common/wm_root_window_controller.cc |
index f2c512b6e692c98feb219c5f1941d0985105c1b8..30ec6c1544cb3f0b796a5534f66a3d1f299c0c3a 100644 |
--- a/ash/common/wm_root_window_controller.cc |
+++ b/ash/common/wm_root_window_controller.cc |
@@ -13,6 +13,7 @@ |
#include "ash/common/wm/container_finder.h" |
#include "ash/common/wm/root_window_layout_manager.h" |
#include "ash/common/wm/system_modal_container_layout_manager.h" |
+#include "ash/common/wm/window_state.h" |
#include "ash/common/wm/workspace/workspace_layout_manager.h" |
#include "ash/common/wm/workspace_controller.h" |
#include "ash/common/wm_shell.h" |
@@ -25,6 +26,103 @@ |
namespace ash { |
namespace { |
+// Scales |value| that is originally between 0 and |src_max| to be between |
+// 0 and |dst_max|. |
+float ToRelativeValue(int value, int src_max, int dst_max) { |
+ return static_cast<float>(value) / static_cast<float>(src_max) * dst_max; |
+} |
+ |
+// Uses ToRelativeValue() to scale the origin of |bounds_in_out|. The |
+// width/height are not changed. |
+void MoveOriginRelativeToSize(const gfx::Size& src_size, |
+ const gfx::Size& dst_size, |
+ gfx::Rect* bounds_in_out) { |
+ gfx::Point origin = bounds_in_out->origin(); |
+ bounds_in_out->set_origin(gfx::Point( |
+ ToRelativeValue(origin.x(), src_size.width(), dst_size.width()), |
+ ToRelativeValue(origin.y(), src_size.height(), dst_size.height()))); |
+} |
+ |
+// Reparents |window| to |new_parent|. |
+void ReparentWindow(WmWindow* window, WmWindow* new_parent) { |
+ const gfx::Size src_size = window->GetParent()->GetBounds().size(); |
+ const gfx::Size dst_size = new_parent->GetBounds().size(); |
+ // Update the restore bounds to make it relative to the display. |
+ wm::WindowState* state = window->GetWindowState(); |
+ gfx::Rect restore_bounds; |
+ bool has_restore_bounds = state->HasRestoreBounds(); |
+ |
+ bool update_bounds = |
+ (state->IsNormalOrSnapped() || state->IsMinimized()) && |
+ new_parent->GetShellWindowId() != kShellWindowId_DockedContainer; |
+ gfx::Rect local_bounds; |
+ if (update_bounds) { |
+ local_bounds = state->window()->GetBounds(); |
+ MoveOriginRelativeToSize(src_size, dst_size, &local_bounds); |
+ } |
+ |
+ if (has_restore_bounds) { |
+ restore_bounds = state->GetRestoreBoundsInParent(); |
+ MoveOriginRelativeToSize(src_size, dst_size, &restore_bounds); |
+ } |
+ |
+ new_parent->AddChild(window); |
+ |
+ // Docked windows have bounds handled by the layout manager in AddChild(). |
+ if (update_bounds) |
+ window->SetBounds(local_bounds); |
+ |
+ if (has_restore_bounds) |
+ state->SetRestoreBoundsInParent(restore_bounds); |
+} |
+ |
+// Reparents the appropriate set of windows from |src| to |dst|. |
+void ReparentAllWindows(WmWindow* src, WmWindow* dst) { |
+ // Set of windows to move. |
+ const int kContainerIdsToMove[] = { |
+ kShellWindowId_DefaultContainer, |
+ kShellWindowId_DockedContainer, |
+ kShellWindowId_PanelContainer, |
+ kShellWindowId_AlwaysOnTopContainer, |
+ kShellWindowId_SystemModalContainer, |
+ kShellWindowId_LockSystemModalContainer, |
+ kShellWindowId_UnparentedControlContainer, |
+ kShellWindowId_OverlayContainer, |
+ }; |
+ const int kExtraContainerIdsToMoveInUnifiedMode[] = { |
+ kShellWindowId_LockScreenContainer, |
+ kShellWindowId_LockScreenWallpaperContainer, |
+ }; |
+ std::vector<int> container_ids( |
+ kContainerIdsToMove, |
+ kContainerIdsToMove + arraysize(kContainerIdsToMove)); |
+ // Check the display mode as this is also necessary when trasitioning between |
+ // mirror and unified mode. |
+ if (WmShell::Get()->IsInUnifiedModeIgnoreMirroring()) { |
+ for (int id : kExtraContainerIdsToMoveInUnifiedMode) |
+ container_ids.push_back(id); |
+ } |
+ |
+ for (int id : container_ids) { |
+ WmWindow* src_container = src->GetChildByShellWindowId(id); |
+ WmWindow* dst_container = dst->GetChildByShellWindowId(id); |
+ while (!src_container->GetChildren().empty()) { |
+ // Restart iteration from the source container windows each time as they |
+ // may change as a result of moving other windows. |
+ WmWindow::Windows src_container_children = src_container->GetChildren(); |
+ WmWindow::Windows::const_iterator iter = src_container_children.begin(); |
+ while (iter != src_container_children.end() && |
+ SystemModalContainerLayoutManager::IsModalBackground(*iter)) { |
+ ++iter; |
+ } |
+ // If the entire window list is modal background windows then stop. |
+ if (iter == src_container_children.end()) |
+ break; |
+ ReparentWindow(*iter, dst_container); |
+ } |
+ } |
+} |
+ |
// Creates a new window for use as a container. |
WmWindow* CreateContainer(int window_id, const char* name, WmWindow* parent) { |
WmWindow* window = WmShell::Get()->NewWindow(ui::wm::WINDOW_TYPE_UNKNOWN, |
@@ -140,6 +238,12 @@ void WmRootWindowController::OnWallpaperAnimationFinished( |
} |
} |
+void WmRootWindowController::MoveWindowsTo(WmWindow* dest) { |
+ // Clear the workspace controller, so it doesn't incorrectly update the shelf. |
+ DeleteWorkspaceController(); |
+ ReparentAllWindows(GetWindow(), dest); |
+} |
+ |
void WmRootWindowController::CreateContainers() { |
// These containers are just used by PowerButtonController to animate groups |
// of containers simultaneously without messing up the current transformations |