| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/workspace/workspace_layout_manager.h" | 5 #include "ash/wm/workspace/workspace_layout_manager.h" |
| 6 | 6 |
| 7 #include "ash/wm/property_util.h" | 7 #include "ash/wm/property_util.h" |
| 8 #include "ash/wm/show_state_controller.h" | |
| 9 #include "ash/wm/window_util.h" | 8 #include "ash/wm/window_util.h" |
| 10 #include "ash/wm/workspace/workspace.h" | 9 #include "ash/wm/workspace/workspace.h" |
| 11 #include "ash/wm/workspace/workspace_manager.h" | 10 #include "ash/wm/workspace/workspace_manager.h" |
| 12 #include "ui/aura/client/aura_constants.h" | 11 #include "ui/aura/client/aura_constants.h" |
| 13 #include "ui/aura/event.h" | 12 #include "ui/aura/event.h" |
| 14 #include "ui/aura/root_window.h" | 13 #include "ui/aura/root_window.h" |
| 15 #include "ui/aura/screen_aura.h" | 14 #include "ui/aura/screen_aura.h" |
| 16 #include "ui/aura/window.h" | 15 #include "ui/aura/window.h" |
| 17 #include "ui/aura/window_observer.h" | 16 #include "ui/aura/window_observer.h" |
| 18 #include "ui/base/ui_base_types.h" | 17 #include "ui/base/ui_base_types.h" |
| 19 #include "ui/gfx/rect.h" | 18 #include "ui/gfx/rect.h" |
| 20 #include "ui/views/widget/native_widget_aura.h" | 19 #include "ui/views/widget/native_widget_aura.h" |
| 21 | 20 |
| 22 namespace ash { | 21 namespace ash { |
| 23 namespace internal { | 22 namespace internal { |
| 24 | 23 |
| 25 //////////////////////////////////////////////////////////////////////////////// | 24 //////////////////////////////////////////////////////////////////////////////// |
| 26 // WorkspaceLayoutManager, public: | 25 // WorkspaceLayoutManager, public: |
| 27 | 26 |
| 28 WorkspaceLayoutManager::WorkspaceLayoutManager( | 27 WorkspaceLayoutManager::WorkspaceLayoutManager( |
| 29 WorkspaceManager* workspace_manager) | 28 WorkspaceManager* workspace_manager) |
| 30 : workspace_manager_(workspace_manager), | 29 : workspace_manager_(workspace_manager) { |
| 31 show_state_controller_(new ShowStateController(workspace_manager)) { | |
| 32 } | 30 } |
| 33 | 31 |
| 34 WorkspaceLayoutManager::~WorkspaceLayoutManager() {} | 32 WorkspaceLayoutManager::~WorkspaceLayoutManager() {} |
| 35 | 33 |
| 36 void WorkspaceLayoutManager::PrepareForMoveOrResize( | 34 void WorkspaceLayoutManager::PrepareForMoveOrResize( |
| 37 aura::Window* drag, | 35 aura::Window* drag, |
| 38 aura::MouseEvent* event) { | 36 aura::MouseEvent* event) { |
| 39 workspace_manager_->set_ignored_window(drag); | 37 workspace_manager_->set_ignored_window(drag); |
| 40 } | 38 } |
| 41 | 39 |
| 42 void WorkspaceLayoutManager::CancelMoveOrResize( | 40 void WorkspaceLayoutManager::CancelMoveOrResize( |
| 43 aura::Window* drag, | 41 aura::Window* drag, |
| 44 aura::MouseEvent* event) { | 42 aura::MouseEvent* event) { |
| 45 workspace_manager_->set_ignored_window(NULL); | 43 workspace_manager_->set_ignored_window(NULL); |
| 46 } | 44 } |
| 47 | 45 |
| 48 void WorkspaceLayoutManager::ProcessMove( | 46 void WorkspaceLayoutManager::ProcessMove( |
| 49 aura::Window* drag, | 47 aura::Window* drag, |
| 50 aura::MouseEvent* event) { | 48 aura::MouseEvent* event) { |
| 51 // TODO(oshima): Just zooming out may (and will) move/swap window without | 49 // TODO: needs implementation for TYPE_SPLIT. For TYPE_SPLIT I want to |
| 52 // a users's intent. We probably should scroll viewport, but that may not | 50 // disallow eventfilter from moving and instead deal with it here. |
| 53 // be enough. See crbug.com/101826 for more discussion. | |
| 54 workspace_manager_->SetOverview(true); | |
| 55 | |
| 56 gfx::Point point_in_owner = event->location(); | |
| 57 aura::Window::ConvertPointToWindow( | |
| 58 drag, | |
| 59 workspace_manager_->contents_view(), | |
| 60 &point_in_owner); | |
| 61 // TODO(oshima): We should support simply moving to another | |
| 62 // workspace when the destination workspace has enough room to accomodate. | |
| 63 aura::Window* rotate_target = | |
| 64 workspace_manager_->FindRotateWindowForLocation(point_in_owner); | |
| 65 if (rotate_target) | |
| 66 workspace_manager_->RotateWindows(drag, rotate_target); | |
| 67 } | 51 } |
| 68 | 52 |
| 69 void WorkspaceLayoutManager::EndMove( | 53 void WorkspaceLayoutManager::EndMove( |
| 70 aura::Window* drag, | 54 aura::Window* drag, |
| 71 aura::MouseEvent* evnet) { | 55 aura::MouseEvent* evnet) { |
| 72 // TODO(oshima): finish moving window between workspaces. | 56 // TODO: see comment in ProcessMove. |
| 73 workspace_manager_->set_ignored_window(NULL); | 57 workspace_manager_->set_ignored_window(NULL); |
| 74 Workspace* workspace = workspace_manager_->FindBy(drag); | |
| 75 workspace->Layout(NULL); | |
| 76 workspace->Activate(); | |
| 77 workspace_manager_->SetOverview(false); | |
| 78 } | 58 } |
| 79 | 59 |
| 80 void WorkspaceLayoutManager::EndResize( | 60 void WorkspaceLayoutManager::EndResize( |
| 81 aura::Window* drag, | 61 aura::Window* drag, |
| 82 aura::MouseEvent* evnet) { | 62 aura::MouseEvent* evnet) { |
| 63 // TODO: see comment in ProcessMove. |
| 83 workspace_manager_->set_ignored_window(NULL); | 64 workspace_manager_->set_ignored_window(NULL); |
| 84 Workspace* workspace = workspace_manager_->GetActiveWorkspace(); | |
| 85 if (workspace) | |
| 86 workspace->Layout(NULL); | |
| 87 workspace_manager_->SetOverview(false); | |
| 88 } | 65 } |
| 89 | 66 |
| 90 //////////////////////////////////////////////////////////////////////////////// | 67 //////////////////////////////////////////////////////////////////////////////// |
| 91 // WorkspaceLayoutManager, aura::LayoutManager implementation: | 68 // WorkspaceLayoutManager, aura::LayoutManager implementation: |
| 92 | 69 |
| 93 void WorkspaceLayoutManager::OnWindowResized() { | 70 void WorkspaceLayoutManager::OnWindowResized() { |
| 94 // Workspace is updated via RootWindowObserver::OnRootWindowResized. | 71 // Workspace is updated via RootWindowObserver::OnRootWindowResized. |
| 95 } | 72 } |
| 96 | 73 |
| 97 void WorkspaceLayoutManager::OnWindowAddedToLayout(aura::Window* child) { | 74 void WorkspaceLayoutManager::OnWindowAddedToLayout(aura::Window* child) { |
| 98 if (child->type() != aura::client::WINDOW_TYPE_NORMAL || | 75 if (!workspace_manager_->IsManagedWindow(child)) |
| 99 child->transient_parent()) { | |
| 100 return; | 76 return; |
| 101 } | |
| 102 | 77 |
| 103 if (!child->GetProperty(aura::client::kShowStateKey)) | 78 if (child->IsVisible()) |
| 104 child->SetIntProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); | 79 workspace_manager_->AddWindow(child); |
| 105 | |
| 106 child->AddObserver(show_state_controller_.get()); | |
| 107 | |
| 108 Workspace* workspace = workspace_manager_->GetActiveWorkspace(); | |
| 109 if (workspace) { | |
| 110 aura::Window* active = ash::GetActiveWindow(); | |
| 111 // Active window may not be in the default container layer. | |
| 112 if (!workspace->Contains(active)) | |
| 113 active = NULL; | |
| 114 if (workspace->AddWindowAfter(child, active)) | |
| 115 return; | |
| 116 } | |
| 117 // Create new workspace if new |child| doesn't fit to current workspace. | |
| 118 Workspace* new_workspace = workspace_manager_->CreateWorkspace(); | |
| 119 new_workspace->AddWindowAfter(child, NULL); | |
| 120 new_workspace->Activate(); | |
| 121 } | 80 } |
| 122 | 81 |
| 123 void WorkspaceLayoutManager::OnWillRemoveWindowFromLayout( | 82 void WorkspaceLayoutManager::OnWillRemoveWindowFromLayout( |
| 124 aura::Window* child) { | 83 aura::Window* child) { |
| 125 child->RemoveObserver(show_state_controller_.get()); | |
| 126 ClearRestoreBounds(child); | 84 ClearRestoreBounds(child); |
| 127 | 85 workspace_manager_->RemoveWindow(child); |
| 128 Workspace* workspace = workspace_manager_->FindBy(child); | |
| 129 if (!workspace) | |
| 130 return; | |
| 131 workspace->RemoveWindow(child); | |
| 132 if (workspace->is_empty()) | |
| 133 delete workspace; | |
| 134 } | 86 } |
| 135 | 87 |
| 136 void WorkspaceLayoutManager::OnChildWindowVisibilityChanged( | 88 void WorkspaceLayoutManager::OnChildWindowVisibilityChanged( |
| 137 aura::Window* child, | 89 aura::Window* child, |
| 138 bool visible) { | 90 bool visible) { |
| 139 NOTIMPLEMENTED(); | 91 if (!workspace_manager_->IsManagedWindow(child)) |
| 92 return; |
| 93 if (visible) |
| 94 workspace_manager_->AddWindow(child); |
| 95 else |
| 96 workspace_manager_->RemoveWindow(child); |
| 140 } | 97 } |
| 141 | 98 |
| 142 void WorkspaceLayoutManager::SetChildBounds( | 99 void WorkspaceLayoutManager::SetChildBounds( |
| 143 aura::Window* child, | 100 aura::Window* child, |
| 144 const gfx::Rect& requested_bounds) { | 101 const gfx::Rect& requested_bounds) { |
| 145 gfx::Rect adjusted_bounds = requested_bounds; | 102 // Allow setting the bounds for any window we don't care about, isn't visible, |
| 146 | 103 // or we're setting the bounds of. All other request are dropped on the floor. |
| 147 // First, calculate the adjusted bounds. | 104 if (child == workspace_manager_->ignored_window() || |
| 148 if (child->type() != aura::client::WINDOW_TYPE_NORMAL || | 105 !workspace_manager_->IsManagedWindow(child) || !child->IsVisible() || |
| 149 workspace_manager_->layout_in_progress() || | 106 (!window_util::IsWindowMaximized(child) && |
| 150 child->transient_parent()) { | 107 !window_util::IsWindowFullscreen(child))) { |
| 151 // Use the requested bounds as is. | 108 SetChildBoundsDirect(child, requested_bounds); |
| 152 } else if (child == workspace_manager_->ignored_window()) { | |
| 153 // If a drag window is requesting bounds, make sure its attached to | |
| 154 // the workarea's top and fits within the total drag area. | |
| 155 gfx::Rect drag_area = workspace_manager_->GetDragAreaBounds(); | |
| 156 adjusted_bounds.set_y(drag_area.y()); | |
| 157 adjusted_bounds = adjusted_bounds.AdjustToFit(drag_area); | |
| 158 } else { | |
| 159 Workspace* workspace = workspace_manager_->FindBy(child); | |
| 160 gfx::Rect work_area = workspace->GetWorkAreaBounds(); | |
| 161 adjusted_bounds.set_origin( | |
| 162 gfx::Point(child->GetTargetBounds().x(), work_area.y())); | |
| 163 adjusted_bounds = adjusted_bounds.AdjustToFit(work_area); | |
| 164 } | 109 } |
| 165 | |
| 166 ui::WindowShowState show_state = static_cast<ui::WindowShowState>( | |
| 167 child->GetIntProperty(aura::client::kShowStateKey)); | |
| 168 | |
| 169 // Second, check if the window is either maximized or in fullscreen mode. | |
| 170 if (show_state == ui::SHOW_STATE_MAXIMIZED || | |
| 171 show_state == ui::SHOW_STATE_FULLSCREEN) { | |
| 172 // If the request is not from workspace manager, | |
| 173 // remember the requested bounds. | |
| 174 if (!workspace_manager_->layout_in_progress()) | |
| 175 SetRestoreBounds(child, adjusted_bounds); | |
| 176 | |
| 177 Workspace* workspace = workspace_manager_->FindBy(child); | |
| 178 if (show_state == ui::SHOW_STATE_MAXIMIZED) | |
| 179 adjusted_bounds = workspace->GetWorkAreaBounds(); | |
| 180 else | |
| 181 adjusted_bounds = workspace->bounds(); | |
| 182 // Don't | |
| 183 if (child->GetTargetBounds() == adjusted_bounds) | |
| 184 return; | |
| 185 } | |
| 186 SetChildBoundsDirect(child, adjusted_bounds); | |
| 187 } | 110 } |
| 188 | 111 |
| 189 } // namespace internal | 112 } // namespace internal |
| 190 } // namespace ash | 113 } // namespace ash |
| OLD | NEW |