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 |