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

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: Dock on left or right edge 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 <algorithm>
8 #include <map>
9
10 #include "ash/launcher/launcher.h"
11 #include "ash/root_window_controller.h"
12 #include "ash/screen_ash.h"
13 #include "ash/shelf/shelf_layout_manager.h"
14 #include "ash/shelf/shelf_types.h"
15 #include "ash/shelf/shelf_widget.h"
16 #include "ash/shell.h"
17 #include "ash/wm/dock/dock_edge_types.h"
18 #include "ash/wm/frame_painter.h"
19 #include "ash/wm/property_util.h"
20 #include "ash/wm/window_animations.h"
21 #include "ash/wm/window_properties.h"
22 #include "ash/wm/window_util.h"
23 #include "ash/wm/workspace_controller.h"
24 #include "base/auto_reset.h"
25 #include "base/bind.h"
26 #include "base/bind_helpers.h"
27 #include "third_party/skia/include/core/SkColor.h"
28 #include "third_party/skia/include/core/SkPaint.h"
29 #include "third_party/skia/include/core/SkPath.h"
30 #include "ui/aura/client/activation_client.h"
31 #include "ui/aura/client/aura_constants.h"
32 #include "ui/aura/focus_manager.h"
33 #include "ui/aura/root_window.h"
34 #include "ui/aura/window.h"
35 #include "ui/compositor/scoped_layer_animation_settings.h"
36 #include "ui/gfx/canvas.h"
37 #include "ui/gfx/rect.h"
38 #include "ui/gfx/vector2d.h"
39 #include "ui/views/background.h"
40 #include "ui/views/widget/widget.h"
41
42 namespace ash {
43 namespace internal {
44
45 namespace {
46 const int kWindowMarginEdge = 4;
47 const int kWindowMarginMiddle = 8;
48 const int kWindowIdealSpacing = 4;
49
50 const float kMaxHeightFactor = .80f;
51 const float kMaxWidthFactor = .50f;
52
53 // Duration for window animations.
54 const int kWindowSlideDurationMilliseconds = 50;
55
56 // Width of the dock area
57 const int kMinDockWidth = 220;
58 const int kMaxDockWidth = 600;
59 const int kMinDockGap = 2;
60
61 struct VisibleWindowPositionInfo {
62 VisibleWindowPositionInfo()
63 : min_major(0),
64 max_major(0),
65 major_pos(0),
66 major_length(0),
67 window(NULL),
68 slide_in(false) {}
69
70 int min_major;
71 int max_major;
72 int major_pos;
73 int major_length;
74 aura::Window* window;
75 bool slide_in;
76 };
77
78 bool CompareWindowMajor(const VisibleWindowPositionInfo& win1,
79 const VisibleWindowPositionInfo& win2) {
80 return win1.major_pos < win2.major_pos;
81 }
82
83 void FanOutWindows(std::vector<VisibleWindowPositionInfo>::iterator first,
flackr 2013/05/31 14:23:45 The code here (from panel_layout_manager.cc I assu
varkha 2013/05/31 23:33:42 I will address this in a separate CL. Removed for
84 std::vector<VisibleWindowPositionInfo>::iterator last) {
85 int num_windows = last - first;
86 if (num_windows == 1) {
87 (*first).major_pos = std::max((*first).min_major, std::min(
88 (*first).max_major, (*first).major_pos));
89 }
90 if (num_windows <= 1)
91 return;
92
93 if (num_windows == 2) {
94 // If there are two adjacent overlapping windows, separate them by the
95 // minimum major_length necessary.
96 std::vector<VisibleWindowPositionInfo>::iterator second = first + 1;
97 int separation = (*first).major_length / 2 + (*second).major_length / 2 +
98 kWindowIdealSpacing;
99 int overlap = (*first).major_pos + separation - (*second).major_pos;
100 (*first).major_pos = std::max((*first).min_major,
101 (*first).major_pos - overlap / 2);
102 (*second).major_pos = std::min((*second).max_major,
103 (*first).major_pos + separation);
104 // Recalculate the first window position in case the second one was
105 // constrained on the right.
106 (*first).major_pos = std::max((*first).min_major,
107 (*second).major_pos - separation);
108 return;
109 }
110
111 // If there are more than two overlapping windows, fan them out from minimum
112 // position to maximum position equally spaced.
113 int delta =
114 ((*(last - 1)).max_major - (*first).min_major) / (num_windows - 1);
115 int major_pos = (*first).min_major;
116 for (std::vector<VisibleWindowPositionInfo>::iterator iter = first;
117 iter != last; ++iter) {
118 (*iter).major_pos = std::max((*iter).min_major,
119 std::min((*iter).max_major, major_pos));
120 major_pos += delta;
121 }
122 }
123
124 bool BoundsAdjacent(const gfx::Rect& bounds1, const gfx::Rect& bounds2) {
125 return bounds1.x() == bounds2.right() ||
126 bounds1.y() == bounds2.bottom() ||
127 bounds1.right() == bounds2.x() ||
128 bounds1.bottom() == bounds2.y();
129 }
130
131 } // namespace
132
133 ////////////////////////////////////////////////////////////////////////////////
134 // DockLayoutManager public implementation:
135 DockLayoutManager::DockLayoutManager(aura::Window* dock_container)
136 : dock_container_(dock_container),
137 in_layout_(false),
138 dragged_window_(NULL),
139 launcher_(NULL),
140 shelf_layout_manager_(NULL),
141 shelf_hidden_(false),
142 last_active_window_(NULL),
143 dock_width_(0),
144 alignment_(DOCK_ALIGNMENT_NONE) {
145 LOG(INFO) << "DockLayoutManager";
146 DCHECK(dock_container);
147 aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())->
148 AddObserver(this);
149 Shell::GetInstance()->AddShellObserver(this);
150 }
151
152 DockLayoutManager::~DockLayoutManager() {
153 if (launcher_)
154 launcher_->RemoveIconObserver(this);
155 if (shelf_layout_manager_)
156 shelf_layout_manager_->RemoveObserver(this);
157 Shutdown();
158 aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())->
159 RemoveObserver(this);
160 Shell::GetInstance()->RemoveShellObserver(this);
161 }
162
163 void DockLayoutManager::Shutdown() {
164 dock_windows_.clear();
165 if (launcher_)
166 launcher_->RemoveIconObserver(this);
167 launcher_ = NULL;
168 }
169
170 void DockLayoutManager::AddObserver(DockObserver* observer) {
171 observer_list_.AddObserver(observer);
172 }
173
174 void DockLayoutManager::RemoveObserver(DockObserver* observer) {
175 observer_list_.RemoveObserver(observer);
176 }
177
178 void DockLayoutManager::StartDragging(aura::Window* window) {
179 LOG(INFO) << "StartDragging " << window;
180 DCHECK(!dragged_window_);
181 dragged_window_ = window;
182 Relayout();
183 }
184
185 void DockLayoutManager::FinishDragging() {
186 LOG(INFO) << "FinishDragging " << dragged_window_;
187
188 if (dragged_window_) {
189 int stuck_edges_mask = CalculateDockEdges(dragged_window_->bounds());
190 if (stuck_edges_mask == DOCK_EDGE_NONE)
191 // this will reparent the window back to workspace
192 SetDockEdges(dragged_window_, stuck_edges_mask);
193 else {
194 // suck the window back in the dock
195 DockList::iterator found = std::find(dock_windows_.begin(),
196 dock_windows_.end(),
197 dragged_window_);
198 if (found != dock_windows_.end()) {
199 found->slide_in = true;
200 }
201 }
202 }
203 dragged_window_ = NULL;
204 Relayout();
205 }
206
207 int DockLayoutManager::CalculateDockEdges(const gfx::Rect& bounds) const {
208 int stuck_edges_mask = DOCK_EDGE_NONE;
209 gfx::Rect dock_bounds = dock_container_->bounds();
210 if (alignment_ == DOCK_ALIGNMENT_LEFT)
211 dock_bounds.set_width(dock_width_);
212 else if (alignment_ == DOCK_ALIGNMENT_RIGHT) {
213 dock_bounds.set_x(dock_bounds.right() - dock_width_);
214 dock_bounds.set_width(dock_width_);
215 }
216 if (dock_width_ == 0) {
217 if (bounds.x() == dock_bounds.x())
218 stuck_edges_mask |= DOCK_EDGE_LEFT;
219 if (bounds.right() == dock_bounds.right())
220 stuck_edges_mask |= DOCK_EDGE_RIGHT;
221 } else {
222 if (bounds.Intersects(dock_bounds))
223 stuck_edges_mask |= (alignment_ == DOCK_ALIGNMENT_LEFT ?
224 DOCK_EDGE_LEFT : DOCK_EDGE_RIGHT);
225 }
226
227 // do not allow dock on the same side as launcher shelf
228 switch (launcher_->shelf_widget()->GetAlignment()) {
229 case SHELF_ALIGNMENT_LEFT:
230 stuck_edges_mask &= ~DOCK_EDGE_LEFT;
231 break;
232 case SHELF_ALIGNMENT_RIGHT:
233 stuck_edges_mask &= ~DOCK_EDGE_RIGHT;
234 break;
235 default:
236 break;
237 }
238 return stuck_edges_mask;
239 }
240
241 void DockLayoutManager::SetLauncher(ash::Launcher* launcher) {
242 DCHECK(!launcher_);
243 DCHECK(!shelf_layout_manager_);
244 launcher_ = launcher;
245 launcher_->AddIconObserver(this);
246 if (launcher_->shelf_widget()) {
247 shelf_layout_manager_ = ash::internal::ShelfLayoutManager::ForLauncher(
248 launcher_->shelf_widget()->GetNativeWindow());
249 WillChangeVisibilityState(shelf_layout_manager_->visibility_state());
250 shelf_layout_manager_->AddObserver(this);
251 }
252 }
253
254 void DockLayoutManager::ToggleMinimize(aura::Window* window) {
255 DCHECK(window->parent() == dock_container_);
256 if (window->GetProperty(aura::client::kShowStateKey) ==
257 ui::SHOW_STATE_MINIMIZED) {
258 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
259 } else {
260 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
261 }
262 }
263
264 ////////////////////////////////////////////////////////////////////////////////
265 // DockLayoutManager, aura::LayoutManager implementation:
266 void DockLayoutManager::OnWindowResized() {
267 LOG(INFO) << "OnWindowResized ";
268 Relayout();
269
270 gfx::Rect bounds = dock_container_->bounds();
271 switch (alignment_) {
272 case DOCK_ALIGNMENT_LEFT:
273 bounds.Inset(dock_container_->bounds().width() - dock_width_,0,0,0);
274 break;
275 case DOCK_ALIGNMENT_RIGHT:
276 bounds.Inset(0,0,dock_container_->bounds().width() - dock_width_,0);
277 break;
278 case DOCK_ALIGNMENT_NONE:
279 bounds.set_width(0);
280 break;
281 }
282 FOR_EACH_OBSERVER(
283 DockObserver,
284 observer_list_,
285 OnDockBoundsChanging(bounds));
286 }
287
288 void DockLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
289 LOG(INFO) << this << " OnWindowAddedToLayout dock " << child;
290 if (GetDockEdges(child) == DOCK_EDGE_NONE)
291 return;
292 DockInfo dock_info;
293 dock_info.window = child;
294 if (child != dragged_window_) {
295 // Set the window to 0 opacity until it has been positioned to prevent it
296 // from flashing briefly at position (0, 0).
297 child->layer()->SetOpacity(0);
298 dock_info.slide_in = true;
299 }
300 dock_windows_.push_back(dock_info);
301 child->AddObserver(this);
302 Relayout();
303 }
304
305 void DockLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) {
306 }
307
308 void DockLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) {
309 LOG(INFO) << this << " OnWindowRemovedFromLayout dock " << child;
310 DockList::iterator found =
311 std::find(dock_windows_.begin(), dock_windows_.end(), child);
312 if (found != dock_windows_.end()) {
313 dock_windows_.erase(found);
314 SetDockEdges(child, DOCK_EDGE_NONE);
315 }
316 child->RemoveObserver(this);
317
318 if (dragged_window_ == child)
319 dragged_window_ = NULL;
320
321 if (last_active_window_ == child)
322 last_active_window_ = NULL;
323
324 Relayout();
325 }
326
327 void DockLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child,
328 bool visible) {
329 LOG(INFO) << "OnChildWindowVisibilityChanged " << child;
330 Relayout();
331 }
332
333 void DockLayoutManager::SetChildBounds(aura::Window* child,
334 const gfx::Rect& requested_bounds) {
335 LOG(INFO) << "SetChildBounds";
336 gfx::Rect bounds(requested_bounds);
337 const gfx::Rect& max_bounds = dock_container_->GetRootWindow()->bounds();
338 const int max_width = max_bounds.width() * kMaxWidthFactor;
339 const int max_height = max_bounds.height() * kMaxHeightFactor;
340 if (bounds.width() > max_width)
341 bounds.set_width(max_width);
342 if (bounds.height() > max_height)
343 bounds.set_height(max_height);
344
345 // Reposition dragged window in the window order.
346 if (dragged_window_ == child) {
347 DockList::iterator dragged_window_iter =
348 std::find(dock_windows_.begin(), dock_windows_.end(), dragged_window_);
349 DCHECK(dragged_window_iter != dock_windows_.end());
350 DockList::iterator new_position;
351 for (new_position = dock_windows_.begin();
352 new_position != dock_windows_.end();
353 ++new_position) {
354 const gfx::Rect& bounds = (*new_position).window->bounds();
355 if (bounds.x() + bounds.width()/2 <= requested_bounds.x()) break;
356 }
357 if (new_position != dragged_window_iter) {
358 DockInfo dragged_window_info = *dragged_window_iter;
359 dock_windows_.erase(dragged_window_iter);
360 dock_windows_.insert(new_position, dragged_window_info);
361 }
362 }
363
364 SetChildBoundsDirect(child, bounds);
365 Relayout();
366 }
367
368 ////////////////////////////////////////////////////////////////////////////////
369 // DockLayoutManager, ash::LauncherIconObserver implementation:
370
371 void DockLayoutManager::OnLauncherIconPositionsChanged() {
372 // TODO: As this is called for every animation step now. Relayout needs to be
373 // updated to use current icon position instead of use the ideal bounds so
374 // that the windows slide with their icons instead of jumping.
375 Relayout();
376 }
377
378 ////////////////////////////////////////////////////////////////////////////////
379 // DockLayoutManager, ash::ShellObserver implementation:
380
381 void DockLayoutManager::OnShelfAlignmentChanged(
382 aura::RootWindow* root_window) {
383 if (dock_container_->GetRootWindow() == root_window) {
384 if (launcher_ && launcher_->shelf_widget()) {
385 // We do not allow launcher and dock on the same side. Switch side that
386 // the dock is attached to and move all dock windows to that new side
387 ShelfAlignment shelf_alignment =
388 launcher_->shelf_widget()->GetAlignment();
389 if (alignment_ == DOCK_ALIGNMENT_LEFT &&
390 shelf_alignment == SHELF_ALIGNMENT_LEFT) {
391 for (DockList::iterator iter = dock_windows_.begin();
392 iter != dock_windows_.end(); ++iter) {
393 SetDockEdges(iter->window, DOCK_EDGE_RIGHT);
394 iter->slide_in = true;
395 }
396 } else if (alignment_ == DOCK_ALIGNMENT_RIGHT &&
397 shelf_alignment == SHELF_ALIGNMENT_RIGHT) {
398 for (DockList::iterator iter = dock_windows_.begin();
399 iter != dock_windows_.end(); ++iter) {
400 SetDockEdges(iter->window, DOCK_EDGE_LEFT);
401 iter->slide_in = true;
402 }
403 }
404 }
405 Relayout();
406 }
407 }
408
409 /////////////////////////////////////////////////////////////////////////////
410 // DockLayoutManager, WindowObserver implementation:
411
412 void DockLayoutManager::OnWindowPropertyChanged(aura::Window* window,
413 const void* key,
414 intptr_t old) {
415 if (key == ash::internal::kDockEdges &&
416 GetDockEdges(window) != static_cast<int>(old)) {
417 int edges = GetDockEdges(window);
418 LOG(INFO) << "Stuck property changed to " << GetDockEdges(window);
419 if (edges == DOCK_EDGE_NONE && window->GetRootWindow()) {
420 // Reparenting will cause Relayout and possible dock resize.
421 window->SetDefaultParentByRootWindow(window->GetRootWindow(),
422 window->GetBoundsInScreen());
423 // A maximized workspace may be active so we may need to switch
424 // to a parent workspace of the window being dragged out.
425 internal::WorkspaceController* workspace_controller =
426 GetRootWindowController(
427 window->GetRootWindow())->workspace_controller();
428 workspace_controller->SetActiveWorkspaceByWindow(window);
429 }
430 }
431
432 if (key == aura::client::kShowStateKey) {
433 // The window property will still be set, but no actual change will occur
434 // until WillChangeVisibilityState is called when the shelf is visible again
435 if (shelf_hidden_)
436 return;
437 ui::WindowShowState new_state =
438 window->GetProperty(aura::client::kShowStateKey);
439 if (new_state == ui::SHOW_STATE_MINIMIZED)
440 MinimizeWindow(window);
441 else
442 RestoreWindow(window);
443 }
444 }
445
446 void DockLayoutManager::OnWindowVisibilityChanged(
447 aura::Window* window, bool visible) {
448 if (visible)
449 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
450 }
451
452 ////////////////////////////////////////////////////////////////////////////////
453 // DockLayoutManager, aura::client::ActivationChangeObserver implementation:
454
455 void DockLayoutManager::OnWindowActivated(aura::Window* gained_active,
456 aura::Window* lost_active) {
457 // Ignore if the window that is not managed by this was activated.
458 if (gained_active &&
459 gained_active->parent() == dock_container_) {
460 UpdateStacking(gained_active);
461 }
462 }
463
464 ////////////////////////////////////////////////////////////////////////////////
465 // DockLayoutManager, ShelfLayoutManagerObserver implementation:
466
467 void DockLayoutManager::WillChangeVisibilityState(
468 ShelfVisibilityState new_state) {
469 // On entering / leaving full screen mode the shelf visibility state is
470 // changed to / from SHELF_HIDDEN. In this state, docked windows should hide
471 // to allow the full-screen application to use the full screen.
472 shelf_hidden_ = new_state == ash::SHELF_HIDDEN;
473 for (DockList::iterator iter = dock_windows_.begin();
474 iter != dock_windows_.end(); ++iter) {
475 if (shelf_hidden_) {
476 if (iter->window->IsVisible())
477 MinimizeWindow(iter->window);
478 } else {
479 if (iter->window->GetProperty(aura::client::kShowStateKey) !=
480 ui::SHOW_STATE_MINIMIZED) {
481 RestoreWindow(iter->window);
482 }
483 }
484 }
485 }
486
487 ////////////////////////////////////////////////////////////////////////////////
488 // DockLayoutManager private implementation:
489
490 void DockLayoutManager::MinimizeWindow(aura::Window* window) {
491 views::corewm::SetWindowVisibilityAnimationType(
492 window, WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE);
493 ui::Layer* layer = window->layer();
494 ui::ScopedLayerAnimationSettings window_slide_settings(layer->GetAnimator());
495 window_slide_settings.SetPreemptionStrategy(
496 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
497 window_slide_settings.SetTransitionDuration(
498 base::TimeDelta::FromMilliseconds(kWindowSlideDurationMilliseconds));
499 window->Hide();
500 DockList::iterator found =
501 std::find(dock_windows_.begin(), dock_windows_.end(), window);
502 if (found != dock_windows_.end()) {
503 layer->SetOpacity(0);
504 // The next time the window is visible it should slide into place.
505 found->slide_in = true;
506 }
507 if (wm::IsActiveWindow(window))
508 wm::DeactivateWindow(window);
509 Relayout();
510 }
511
512 void DockLayoutManager::RestoreWindow(aura::Window* window) {
513 window->Show();
514 Relayout();
515 }
516
517 void DockLayoutManager::Relayout() {
flackr 2013/05/31 14:23:45 I think you'll want to rewrite this function to la
varkha 2013/05/31 23:33:42 That is the plan. For now I kept just the code tha
518 if (in_layout_)
519 return;
520
521 if (!launcher_ || !launcher_->shelf_widget())
522 return;
523
524 LOG(INFO) << "Relayout (" << dock_windows_.size() << " windows in dock)";
525 base::AutoReset<bool> auto_reset_in_layout(&in_layout_, true);
526
527 int dock_width = kMinDockWidth;
528 DockAlignment alignment = alignment_;
529 if (dock_windows_.empty()) {
530 alignment_ = DOCK_ALIGNMENT_NONE;
531 if (dock_width_ != 0) {
532 dock_width_ = 0;
533 OnWindowResized();
534 }
535 return;
536 }
537
538 bool horizontal = false;
539 gfx::Rect launcher_bounds = dock_container_->bounds();
540 // launcher_bounds.set_width(dock_width);
541 // if (alignment == SHELF_ALIGNMENT_RIGHT)
542 // launcher_bounds.set_x(dock_container_->bounds().width() -
543 // launcher_bounds.width());
544 int window_start_bounds = kWindowIdealSpacing;
545 int window_end_bounds = horizontal ?
546 dock_container_->bounds().width() - kWindowIdealSpacing :
547 dock_container_->bounds().height() - kWindowIdealSpacing;
548 aura::Window* active_window = NULL;
549 std::vector<VisibleWindowPositionInfo> visible_windows;
550 alignment =
551 GetDockEdges(dock_windows_.begin()->window) == DOCK_EDGE_LEFT ?
552 DOCK_ALIGNMENT_LEFT : DOCK_ALIGNMENT_RIGHT;
553 LOG(INFO) << "alignment=" << alignment;
554 for (DockList::iterator iter = dock_windows_.begin();
555 iter != dock_windows_.end(); ++iter) {
556 aura::Window* window = iter->window;
557
558 // Consider the dragged window as part of the layout as long as it is
559 // touching the launcher.
560 if (!window->IsVisible() ||
561 (window == dragged_window_ &&
562 !BoundsAdjacent(window->bounds(), launcher_bounds))) {
563 // continue;
564 }
565
566 // If the shelf is currently hidden (full-screen mode), hide window until
567 // full-screen mode is exited.
568 if (shelf_hidden_) {
569 // The call to Hide does not set the minimize property, so the window will
570 // be restored when the shelf becomes visible again.
571 window->Hide();
572 continue;
573 }
574
575 gfx::Rect icon_bounds =
576 launcher_->GetScreenBoundsOfItemIconForWindow(window);
577
578 // If both the icon width and height are 0 then there is no icon in the
579 // launcher. If the launcher is hidden, one of the height or width will be
580 // 0 but the position in the launcher and major dimension is still reported
581 // correctly and the window can be aligned above where the hidden icon is.
582 if (icon_bounds.width() == 0 && icon_bounds.height() == 0)
583 continue;
584
585 if (window->HasFocus() ||
586 window->Contains(
587 aura::client::GetFocusClient(window)->GetFocusedWindow())) {
588 DCHECK(!active_window);
589 active_window = window;
590 }
591 icon_bounds = ScreenAsh::ConvertRectFromScreen(dock_container_,
592 icon_bounds);
593 gfx::Point icon_origin = icon_bounds.origin();
594 VisibleWindowPositionInfo position_info;
595 int icon_start = horizontal ? icon_origin.x() : icon_origin.y();
596 int icon_end = icon_start + (horizontal ? icon_bounds.width() :
597 icon_bounds.height());
598 position_info.major_length = horizontal ?
599 window->bounds().width() : window->bounds().height();
600 position_info.min_major = std::max(
601 window_start_bounds + position_info.major_length / 2,
602 icon_end - position_info.major_length / 2);
603 position_info.max_major = std::min(
604 icon_start + position_info.major_length / 2,
605 window_end_bounds - position_info.major_length / 2);
606 position_info.major_pos = (icon_start + icon_end) / 2;
607 position_info.window = window;
608 position_info.slide_in = iter->slide_in;
609 iter->slide_in = false;
610 visible_windows.push_back(position_info);
611 }
612
613 bool visible_non_minimized_windows = false;
614 for (size_t i = 0; i < visible_windows.size(); ++i) {
615 gfx::Rect bounds = visible_windows[i].window->GetTargetBounds();
616 bool slide_in = visible_windows[i].slide_in;
617 switch (alignment) {
618 case DOCK_ALIGNMENT_LEFT:
619 if (bounds.width() > kMaxDockWidth) {
620 bounds.set_width(kMaxDockWidth);
621 }
622 if (slide_in || bounds.x() - launcher_bounds.x() < 32)
623 bounds.set_x(0);
624 break;
625 case DOCK_ALIGNMENT_RIGHT:
626 if (bounds.width() > kMaxDockWidth) {
627 bounds.set_x(bounds.x() + bounds.width() - kMaxDockWidth);
628 bounds.set_width(kMaxDockWidth);
629 }
630 if (slide_in || launcher_bounds.right() - bounds.right() < 32)
631 bounds.set_x(launcher_bounds.right() - bounds.width());
632 break;
633 case DOCK_ALIGNMENT_NONE:
634 break;
635 }
636 if (visible_windows[i].window->GetProperty(aura::client::kShowStateKey) !=
637 ui::SHOW_STATE_MINIMIZED) {
638 visible_non_minimized_windows = true;
639 if (dock_width < bounds.width() + kMinDockGap)
640 dock_width = bounds.width() + kMinDockGap;
641 }
642 if (visible_windows[i].window == dragged_window_) {
643 SetChildBoundsDirect(visible_windows[i].window, bounds);
644 continue;
645 }
646 bool on_launcher = visible_windows[i].window->GetTargetBounds() == bounds;
647
648 ui::Layer* layer = visible_windows[i].window->layer();
649 if (slide_in) {
650 // New windows shift up from the launcher into position.
651 SetChildBoundsDirect(visible_windows[i].window, bounds);
652 // Set on launcher so that the window animates into its target position.
653 on_launcher = true;
654 }
655
656 if (on_launcher) {
657 ui::ScopedLayerAnimationSettings window_slide_settings(
658 layer->GetAnimator());
659 window_slide_settings.SetPreemptionStrategy(
660 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
661 window_slide_settings.SetTransitionDuration(
662 base::TimeDelta::FromMilliseconds(kWindowSlideDurationMilliseconds));
663 SetChildBoundsDirect(visible_windows[i].window, bounds);
664 if (slide_in)
665 layer->SetOpacity(1);
666 } else {
667 // If the launcher moved don't animate, move immediately to the new
668 // target location.
669 SetChildBoundsDirect(visible_windows[i].window, bounds);
670 }
671 }
672 if (!visible_non_minimized_windows)
673 dock_width = 0;
674
675 UpdateStacking(active_window);
676 if (dock_width != dock_width_ || alignment != alignment_) {
677 alignment_ = alignment;
678 dock_width_ = dock_width;
679 OnWindowResized();
680 }
681 }
682
683 void DockLayoutManager::UpdateStacking(aura::Window* active_window) {
684 if (!active_window) {
685 if (!last_active_window_)
686 return;
687 active_window = last_active_window_;
688 }
689
690 // TODO: Implement restacking if ever necessary
flackr 2013/05/31 14:23:45 This will most likely be necessary. Given that we'
varkha 2013/05/31 23:33:42 This is for a separate CL. I have updated TODO com
691 }
692
693 ////////////////////////////////////////////////////////////////////////////////
694 // keyboard::KeyboardControllerObserver implementation:
695
696 void DockLayoutManager::OnKeyboardBoundsChanging(
697 const gfx::Rect& keyboard_bounds) {
698 // This bounds change will have caused a change to the Shelf which does not
699 // propagate automatically to this class, so manually recalculate bounds.
700 OnWindowResized();
701 }
702
703 } // namespace internal
704 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698