Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: ash/wm/dock/dock_layout_manager.cc

Issue 13896026: Stick windows to sides of workspaces (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Docking with dock width=0 Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "ash/wm/dock/dock_layout_manager.h"
6
7 #include "ash/launcher/launcher.h"
8 #include "ash/root_window_controller.h"
9 #include "ash/screen_ash.h"
10 #include "ash/shelf/shelf_layout_manager.h"
11 #include "ash/shelf/shelf_types.h"
12 #include "ash/shelf/shelf_widget.h"
13 #include "ash/shell.h"
14 #include "ash/wm/property_util.h"
15 #include "ash/wm/window_animations.h"
16 #include "ash/wm/window_properties.h"
17 #include "ash/wm/window_util.h"
18 #include "ash/wm/workspace_controller.h"
19 #include "base/auto_reset.h"
20 #include "base/bind.h"
21 #include "base/bind_helpers.h"
22 #include "ui/aura/client/activation_client.h"
23 #include "ui/aura/client/aura_constants.h"
24 #include "ui/aura/focus_manager.h"
25 #include "ui/aura/root_window.h"
26 #include "ui/aura/window.h"
27 #include "ui/compositor/scoped_layer_animation_settings.h"
28 #include "ui/gfx/rect.h"
29
30 namespace ash {
31 namespace internal {
32
33 namespace {
stevenjb 2013/06/03 18:19:03 nit: blank line
varkha 2013/06/03 21:03:17 Done.
34 const int kMagnetismWidth = 32;
35
36 // Duration for window animations.
37 const int kWindowSlideDurationMilliseconds = 50;
38
39 } // namespace
40
41 ////////////////////////////////////////////////////////////////////////////////
42 // DockLayoutManager public implementation:
43 DockLayoutManager::DockLayoutManager(aura::Window* dock_container)
44 : dock_container_(dock_container),
45 in_layout_(false),
46 dragged_window_(NULL),
47 launcher_(NULL),
48 shelf_layout_manager_(NULL),
49 shelf_hidden_(false),
50 alignment_(DOCK_ALIGNMENT_NONE) {
51 DCHECK(dock_container);
52 aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())->
53 AddObserver(this);
54 Shell::GetInstance()->AddShellObserver(this);
55 }
56
57 DockLayoutManager::~DockLayoutManager() {
58 if (shelf_layout_manager_)
59 shelf_layout_manager_->RemoveObserver(this);
60 Shutdown();
61 aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())->
62 RemoveObserver(this);
63 Shell::GetInstance()->RemoveShellObserver(this);
64 }
65
66 void DockLayoutManager::Shutdown() {
67 launcher_ = NULL;
68 }
69
70 void DockLayoutManager::StartDragging(aura::Window* window) {
71 DCHECK(!dragged_window_);
72 dragged_window_ = window;
73 Relayout(DO_NOT_FORCE_MOVE);
74 }
75
76 void DockLayoutManager::FinishDragging() {
77 ForceMove force_move(DO_NOT_FORCE_MOVE);
78 if (dragged_window_) {
79 DockEdge dock_edge = FindDockEdge(dragged_window_->bounds());
80 if (dock_edge == DOCK_EDGE_NONE)
81 // this will reparent the window back to workspace
flackr 2013/06/03 22:03:43 Doesn't the reparenting happen immediately? I'm no
varkha 2013/06/04 03:13:50 Done.
82 SetDockEdge(dragged_window_, dock_edge);
83 else {
84 force_move = FORCE_MOVE;
flackr 2013/06/03 22:03:43 nit: both if and else should either have or not ha
varkha 2013/06/04 03:13:50 Done (no need for else anymore).
85 }
86 }
87 dragged_window_ = NULL;
88 Relayout(force_move);
89 }
90
91 DockEdge DockLayoutManager::FindDockEdge(const gfx::Rect& bounds) const {
92 DockEdge dock_edge = DOCK_EDGE_NONE;
93 gfx::Rect dock_bounds = dock_container_->bounds();
94 if (bounds.x() == dock_bounds.x() && alignment_ != DOCK_ALIGNMENT_RIGHT)
95 dock_edge = DOCK_EDGE_LEFT;
96 if (bounds.right() == dock_bounds.right() &&
97 alignment_ != DOCK_ALIGNMENT_LEFT)
98 dock_edge = DOCK_EDGE_RIGHT;
flackr 2013/06/03 22:03:43 nit: curlies for multi-line if condition.
varkha 2013/06/04 03:13:50 Done. Here and in a few more places. Thanks, I mis
99
100 // do not allow dock on the same side as launcher shelf
101 if (launcher_ && launcher_->shelf_widget()) {
102 ShelfAlignment shelf_alignment = launcher_->shelf_widget()->GetAlignment();
103 if ((shelf_alignment == SHELF_ALIGNMENT_LEFT &&
104 dock_edge == DOCK_EDGE_LEFT) ||
105 (shelf_alignment == SHELF_ALIGNMENT_RIGHT &&
106 dock_edge == DOCK_EDGE_RIGHT))
stevenjb 2013/06/03 18:19:03 nit: alignment
varkha 2013/06/03 21:03:17 Done.
107 dock_edge = DOCK_EDGE_NONE;
108 }
109 return dock_edge;
110 }
111
112 void DockLayoutManager::SetLauncher(ash::Launcher* launcher) {
113 DCHECK(!launcher_);
114 DCHECK(!shelf_layout_manager_);
115 launcher_ = launcher;
116 if (launcher_->shelf_widget()) {
117 shelf_layout_manager_ = ash::internal::ShelfLayoutManager::ForLauncher(
118 launcher_->shelf_widget()->GetNativeWindow());
119 WillChangeVisibilityState(shelf_layout_manager_->visibility_state());
120 shelf_layout_manager_->AddObserver(this);
121 }
122 }
123
124 void DockLayoutManager::ToggleMinimize(aura::Window* window) {
125 DCHECK(window->parent() == dock_container_);
126 if (window->GetProperty(aura::client::kShowStateKey) ==
127 ui::SHOW_STATE_MINIMIZED) {
128 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
129 } else {
130 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
131 }
132 }
133
134 ////////////////////////////////////////////////////////////////////////////////
135 // DockLayoutManager, aura::LayoutManager implementation:
136 void DockLayoutManager::OnWindowResized() {
137 Relayout(FORCE_MOVE);
138 }
139
140 void DockLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
141 if (GetDockEdge(child) == DOCK_EDGE_NONE)
flackr 2013/06/03 22:03:43 Do we expect windows to get added to the dock cont
varkha 2013/06/04 03:13:50 Done.
142 return;
143 child->AddObserver(this);
144 Relayout(FORCE_MOVE);
145 }
146
147 void DockLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) {
148 }
149
150 void DockLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) {
151 SetDockEdge(child, DOCK_EDGE_NONE);
152 child->RemoveObserver(this);
153
154 if (dragged_window_ == child)
155 dragged_window_ = NULL;
156
157 Relayout(DO_NOT_FORCE_MOVE);
158 }
159
160 void DockLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child,
161 bool visible) {
162 Relayout(DO_NOT_FORCE_MOVE);
163 }
164
165 void DockLayoutManager::SetChildBounds(aura::Window* child,
166 const gfx::Rect& requested_bounds) {
stevenjb 2013/06/03 18:19:03 nit: align
varkha 2013/06/03 21:03:17 Done.
167 SetChildBoundsDirect(child, requested_bounds);
168 Relayout(DO_NOT_FORCE_MOVE);
169 }
170
171 ////////////////////////////////////////////////////////////////////////////////
172 // DockLayoutManager, ash::ShellObserver implementation:
173
174 void DockLayoutManager::OnShelfAlignmentChanged(
175 aura::RootWindow* root_window) {
176 ForceMove force_move(DO_NOT_FORCE_MOVE);
177 if (dock_container_->GetRootWindow() == root_window) {
stevenjb 2013/06/03 18:19:03 nit: Early exit instead
varkha 2013/06/03 21:03:17 Done.
178 if (launcher_ && launcher_->shelf_widget()) {
179 // We do not allow launcher and dock on the same side. Switch side that
180 // the dock is attached to and move all dock windows to that new side
181 ShelfAlignment shelf_alignment =
182 launcher_->shelf_widget()->GetAlignment();
183 if (alignment_ == DOCK_ALIGNMENT_LEFT &&
184 shelf_alignment == SHELF_ALIGNMENT_LEFT) {
185 force_move = FORCE_MOVE;
186 for (size_t i = 0; i < dock_container_->children().size(); ++i)
187 SetDockEdge(dock_container_->children()[i], DOCK_EDGE_RIGHT);
188 } else if (alignment_ == DOCK_ALIGNMENT_RIGHT &&
189 shelf_alignment == SHELF_ALIGNMENT_RIGHT) {
stevenjb 2013/06/03 18:19:03 nit: align
varkha 2013/06/03 21:03:17 Done.
190 force_move = FORCE_MOVE;
191 for (size_t i = 0; i < dock_container_->children().size(); ++i)
192 SetDockEdge(dock_container_->children()[i], DOCK_EDGE_LEFT);
193 }
194 }
195 Relayout(force_move);
196 }
197 }
198
199 /////////////////////////////////////////////////////////////////////////////
200 // DockLayoutManager, WindowObserver implementation:
201
202 void DockLayoutManager::OnWindowPropertyChanged(aura::Window* window,
203 const void* key,
204 intptr_t old) {
stevenjb 2013/06/03 18:19:03 nit: align
varkha 2013/06/03 21:03:17 Done.
205 if (key == ash::internal::kDockEdge &&
206 GetDockEdge(window) != static_cast<DockEdge>(old)) {
207 DockEdge edge = GetDockEdge(window);
208 if (edge == DOCK_EDGE_NONE && window->GetRootWindow()) {
209 // Reparenting will cause Relayout and possible dock resize.
210 window->SetDefaultParentByRootWindow(window->GetRootWindow(),
211 window->GetBoundsInScreen());
212 // A maximized workspace may be active so we may need to switch
213 // to a parent workspace of the window being dragged out.
214 internal::WorkspaceController* workspace_controller =
215 GetRootWindowController(
216 window->GetRootWindow())->workspace_controller();
217 workspace_controller->SetActiveWorkspaceByWindow(window);
218 }
219 }
220
221 if (key == aura::client::kShowStateKey) {
flackr 2013/06/03 22:03:43 nit: else if
varkha 2013/06/04 03:13:50 Done.
222 // The window property will still be set, but no actual change will occur
223 // until WillChangeVisibilityState is called when the shelf is visible again
224 if (shelf_hidden_)
225 return;
226 ui::WindowShowState new_state =
227 window->GetProperty(aura::client::kShowStateKey);
228 if (new_state == ui::SHOW_STATE_MINIMIZED)
229 MinimizeWindow(window);
230 else
231 RestoreWindow(window);
232 }
233 }
234
235 void DockLayoutManager::OnWindowVisibilityChanged(
236 aura::Window* window, bool visible) {
stevenjb 2013/06/03 18:19:03 One parameter per line in function declaration or
varkha 2013/06/03 21:03:17 Done.
237 if (visible)
238 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
239 }
240
241 ////////////////////////////////////////////////////////////////////////////////
242 // DockLayoutManager, aura::client::ActivationChangeObserver implementation:
243
244 void DockLayoutManager::OnWindowActivated(aura::Window* gained_active,
245 aura::Window* lost_active) {
246 // Ignore if the window that is not managed by this was activated.
247 if (gained_active &&
248 gained_active->parent() == dock_container_) {
stevenjb 2013/06/03 18:19:03 One line? In which case no {}
varkha 2013/06/03 21:03:17 Done.
249 UpdateStacking(gained_active);
250 }
251 }
252
253 ////////////////////////////////////////////////////////////////////////////////
254 // DockLayoutManager, ShelfLayoutManagerObserver implementation:
255
256 void DockLayoutManager::WillChangeVisibilityState(
257 ShelfVisibilityState new_state) {
258 // On entering / leaving full screen mode the shelf visibility state is
259 // changed to / from SHELF_HIDDEN. In this state, docked windows should hide
260 // to allow the full-screen application to use the full screen.
261
262 // TODO: ShelfLayoutManager::UpdateVisibilityState sets state to
stevenjb 2013/06/03 18:19:03 TODO(varkha)
varkha 2013/06/03 21:03:17 Done.
263 // SHELF_AUTO_HIDE when in immersive mode. We need to distinguish this from
264 // when shelf enters auto-hide state based on mouse hover when auto-hide
265 // setting is enabled and hide all windows (immersive mode should hide dock).
266 shelf_hidden_ = new_state == ash::SHELF_HIDDEN;
267 for (size_t i = 0; i < dock_container_->children().size(); ++i) {
268 aura::Window* window = dock_container_->children()[i];
269 if (shelf_hidden_) {
270 if (window->IsVisible())
271 MinimizeWindow(window);
272 } else {
273 if (window->GetProperty(aura::client::kShowStateKey) !=
274 ui::SHOW_STATE_MINIMIZED) {
275 RestoreWindow(window);
276 }
277 }
278 }
279 }
280
281 ////////////////////////////////////////////////////////////////////////////////
282 // DockLayoutManager private implementation:
283
284 void DockLayoutManager::MinimizeWindow(aura::Window* window) {
285 views::corewm::SetWindowVisibilityAnimationType(
286 window, WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE);
287 ui::Layer* layer = window->layer();
288 ui::ScopedLayerAnimationSettings window_slide_settings(layer->GetAnimator());
289 window_slide_settings.SetPreemptionStrategy(
290 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
291 window_slide_settings.SetTransitionDuration(
292 base::TimeDelta::FromMilliseconds(kWindowSlideDurationMilliseconds));
flackr 2013/06/03 22:03:43 It looks like there's nothing immediately here to
varkha 2013/06/04 03:13:50 Done.
293 window->Hide();
294 if (wm::IsActiveWindow(window))
295 wm::DeactivateWindow(window);
296 Relayout(DO_NOT_FORCE_MOVE);
297 }
298
299 void DockLayoutManager::RestoreWindow(aura::Window* window) {
300 window->Show();
301 Relayout(DO_NOT_FORCE_MOVE);
302 }
303
304 void DockLayoutManager::Relayout(ForceMove force_move) {
305 if (in_layout_)
306 return;
307 base::AutoReset<bool> auto_reset_in_layout(&in_layout_, true);
308
309 if (dock_container_->children().empty()) {
310 alignment_ = DOCK_ALIGNMENT_NONE;
311 return;
312 }
313
314 gfx::Rect dock_bounds = dock_container_->bounds();
315 aura::Window* active_window = NULL;
316 std::vector<aura::Window*> visible_windows;
317 alignment_ =
318 GetDockEdge(dock_container_->children()[0]) == DOCK_EDGE_LEFT ?
319 DOCK_ALIGNMENT_LEFT : DOCK_ALIGNMENT_RIGHT;
stevenjb 2013/06/03 18:19:03 nit: align
varkha 2013/06/03 21:03:17 Done.
320 for (size_t i = 0; i < dock_container_->children().size(); ++i) {
321 aura::Window* window(dock_container_->children()[i]);
322
323 // Consider the dragged window as part of the layout as long as it is
324 // touching the launcher.
flackr 2013/06/03 22:03:43 This comment seems obsolete.
varkha 2013/06/04 03:13:50 Done.
325 if (!window->IsVisible() ||
326 window->GetProperty(aura::client::kShowStateKey) ==
327 ui::SHOW_STATE_MINIMIZED)
328 continue;
329
330 // If the shelf is currently hidden (full-screen mode), hide window until
331 // full-screen mode is exited.
332 if (shelf_hidden_) {
333 // The call to Hide does not set the minimize property, so the window will
334 // be restored when the shelf becomes visible again.
335 window->Hide();
336 continue;
337 }
338
339 if (window->HasFocus() ||
340 window->Contains(
341 aura::client::GetFocusClient(window)->GetFocusedWindow())) {
342 DCHECK(!active_window);
343 active_window = window;
344 }
345 visible_windows.push_back(window);
flackr 2013/06/03 22:03:43 Building this list is unnecessary. Merge the body
varkha 2013/06/04 03:13:50 Done.
346 }
347
348 for (size_t i = 0; i < visible_windows.size(); ++i) {
349 gfx::Rect bounds = visible_windows[i]->GetTargetBounds();
350 switch (alignment_) {
351 case DOCK_ALIGNMENT_LEFT:
352 if (force_move == FORCE_MOVE ||
flackr 2013/06/03 22:03:43 As mentioned earlier, I think any windows in this
varkha 2013/06/04 03:13:50 Done. Convinced ;)
353 bounds.x() - dock_bounds.x() < kMagnetismWidth)
354 bounds.set_x(0);
355 break;
356 case DOCK_ALIGNMENT_RIGHT:
357 if (force_move == FORCE_MOVE ||
358 dock_bounds.right() - bounds.right() < kMagnetismWidth)
359 bounds.set_x(dock_bounds.right() - bounds.width());
360 break;
361 case DOCK_ALIGNMENT_NONE:
362 break;
363 }
364 SetChildBoundsDirect(visible_windows[i], bounds);
365 }
366
367 UpdateStacking(active_window);
368 }
369
370 void DockLayoutManager::UpdateStacking(aura::Window* active_window) {
371 // TODO: Implement restacking to ensure that all docked windows are at least
stevenjb 2013/06/03 18:19:03 TODO(varkha)
varkha 2013/06/03 21:03:17 Done.
372 // partially visible and selectable.
373 }
374
375 ////////////////////////////////////////////////////////////////////////////////
376 // keyboard::KeyboardControllerObserver implementation:
377
378 void DockLayoutManager::OnKeyboardBoundsChanging(
379 const gfx::Rect& keyboard_bounds) {
380 // This bounds change will have caused a change to the Shelf which does not
381 // propagate automatically to this class, so manually recalculate bounds.
382 OnWindowResized();
383 }
384
385 } // namespace internal
386 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698