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

Unified 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, 7 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 side-by-side diff with in-line comments
Download patch
Index: ash/wm/dock/dock_layout_manager.cc
diff --git a/ash/wm/dock/dock_layout_manager.cc b/ash/wm/dock/dock_layout_manager.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f1b90d9cda9dea34a12118ea1b06534516d4fd4f
--- /dev/null
+++ b/ash/wm/dock/dock_layout_manager.cc
@@ -0,0 +1,704 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/wm/dock/dock_layout_manager.h"
+
+#include <algorithm>
+#include <map>
+
+#include "ash/launcher/launcher.h"
+#include "ash/root_window_controller.h"
+#include "ash/screen_ash.h"
+#include "ash/shelf/shelf_layout_manager.h"
+#include "ash/shelf/shelf_types.h"
+#include "ash/shelf/shelf_widget.h"
+#include "ash/shell.h"
+#include "ash/wm/dock/dock_edge_types.h"
+#include "ash/wm/frame_painter.h"
+#include "ash/wm/property_util.h"
+#include "ash/wm/window_animations.h"
+#include "ash/wm/window_properties.h"
+#include "ash/wm/window_util.h"
+#include "ash/wm/workspace_controller.h"
+#include "base/auto_reset.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkPaint.h"
+#include "third_party/skia/include/core/SkPath.h"
+#include "ui/aura/client/activation_client.h"
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/focus_manager.h"
+#include "ui/aura/root_window.h"
+#include "ui/aura/window.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/vector2d.h"
+#include "ui/views/background.h"
+#include "ui/views/widget/widget.h"
+
+namespace ash {
+namespace internal {
+
+namespace {
+const int kWindowMarginEdge = 4;
+const int kWindowMarginMiddle = 8;
+const int kWindowIdealSpacing = 4;
+
+const float kMaxHeightFactor = .80f;
+const float kMaxWidthFactor = .50f;
+
+// Duration for window animations.
+const int kWindowSlideDurationMilliseconds = 50;
+
+// Width of the dock area
+const int kMinDockWidth = 220;
+const int kMaxDockWidth = 600;
+const int kMinDockGap = 2;
+
+struct VisibleWindowPositionInfo {
+ VisibleWindowPositionInfo()
+ : min_major(0),
+ max_major(0),
+ major_pos(0),
+ major_length(0),
+ window(NULL),
+ slide_in(false) {}
+
+ int min_major;
+ int max_major;
+ int major_pos;
+ int major_length;
+ aura::Window* window;
+ bool slide_in;
+};
+
+bool CompareWindowMajor(const VisibleWindowPositionInfo& win1,
+ const VisibleWindowPositionInfo& win2) {
+ return win1.major_pos < win2.major_pos;
+}
+
+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
+ std::vector<VisibleWindowPositionInfo>::iterator last) {
+ int num_windows = last - first;
+ if (num_windows == 1) {
+ (*first).major_pos = std::max((*first).min_major, std::min(
+ (*first).max_major, (*first).major_pos));
+ }
+ if (num_windows <= 1)
+ return;
+
+ if (num_windows == 2) {
+ // If there are two adjacent overlapping windows, separate them by the
+ // minimum major_length necessary.
+ std::vector<VisibleWindowPositionInfo>::iterator second = first + 1;
+ int separation = (*first).major_length / 2 + (*second).major_length / 2 +
+ kWindowIdealSpacing;
+ int overlap = (*first).major_pos + separation - (*second).major_pos;
+ (*first).major_pos = std::max((*first).min_major,
+ (*first).major_pos - overlap / 2);
+ (*second).major_pos = std::min((*second).max_major,
+ (*first).major_pos + separation);
+ // Recalculate the first window position in case the second one was
+ // constrained on the right.
+ (*first).major_pos = std::max((*first).min_major,
+ (*second).major_pos - separation);
+ return;
+ }
+
+ // If there are more than two overlapping windows, fan them out from minimum
+ // position to maximum position equally spaced.
+ int delta =
+ ((*(last - 1)).max_major - (*first).min_major) / (num_windows - 1);
+ int major_pos = (*first).min_major;
+ for (std::vector<VisibleWindowPositionInfo>::iterator iter = first;
+ iter != last; ++iter) {
+ (*iter).major_pos = std::max((*iter).min_major,
+ std::min((*iter).max_major, major_pos));
+ major_pos += delta;
+ }
+}
+
+bool BoundsAdjacent(const gfx::Rect& bounds1, const gfx::Rect& bounds2) {
+ return bounds1.x() == bounds2.right() ||
+ bounds1.y() == bounds2.bottom() ||
+ bounds1.right() == bounds2.x() ||
+ bounds1.bottom() == bounds2.y();
+}
+
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// DockLayoutManager public implementation:
+DockLayoutManager::DockLayoutManager(aura::Window* dock_container)
+ : dock_container_(dock_container),
+ in_layout_(false),
+ dragged_window_(NULL),
+ launcher_(NULL),
+ shelf_layout_manager_(NULL),
+ shelf_hidden_(false),
+ last_active_window_(NULL),
+ dock_width_(0),
+ alignment_(DOCK_ALIGNMENT_NONE) {
+ LOG(INFO) << "DockLayoutManager";
+ DCHECK(dock_container);
+ aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())->
+ AddObserver(this);
+ Shell::GetInstance()->AddShellObserver(this);
+}
+
+DockLayoutManager::~DockLayoutManager() {
+ if (launcher_)
+ launcher_->RemoveIconObserver(this);
+ if (shelf_layout_manager_)
+ shelf_layout_manager_->RemoveObserver(this);
+ Shutdown();
+ aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())->
+ RemoveObserver(this);
+ Shell::GetInstance()->RemoveShellObserver(this);
+}
+
+void DockLayoutManager::Shutdown() {
+ dock_windows_.clear();
+ if (launcher_)
+ launcher_->RemoveIconObserver(this);
+ launcher_ = NULL;
+}
+
+void DockLayoutManager::AddObserver(DockObserver* observer) {
+ observer_list_.AddObserver(observer);
+}
+
+void DockLayoutManager::RemoveObserver(DockObserver* observer) {
+ observer_list_.RemoveObserver(observer);
+}
+
+void DockLayoutManager::StartDragging(aura::Window* window) {
+ LOG(INFO) << "StartDragging " << window;
+ DCHECK(!dragged_window_);
+ dragged_window_ = window;
+ Relayout();
+}
+
+void DockLayoutManager::FinishDragging() {
+ LOG(INFO) << "FinishDragging " << dragged_window_;
+
+ if (dragged_window_) {
+ int stuck_edges_mask = CalculateDockEdges(dragged_window_->bounds());
+ if (stuck_edges_mask == DOCK_EDGE_NONE)
+ // this will reparent the window back to workspace
+ SetDockEdges(dragged_window_, stuck_edges_mask);
+ else {
+ // suck the window back in the dock
+ DockList::iterator found = std::find(dock_windows_.begin(),
+ dock_windows_.end(),
+ dragged_window_);
+ if (found != dock_windows_.end()) {
+ found->slide_in = true;
+ }
+ }
+ }
+ dragged_window_ = NULL;
+ Relayout();
+}
+
+int DockLayoutManager::CalculateDockEdges(const gfx::Rect& bounds) const {
+ int stuck_edges_mask = DOCK_EDGE_NONE;
+ gfx::Rect dock_bounds = dock_container_->bounds();
+ if (alignment_ == DOCK_ALIGNMENT_LEFT)
+ dock_bounds.set_width(dock_width_);
+ else if (alignment_ == DOCK_ALIGNMENT_RIGHT) {
+ dock_bounds.set_x(dock_bounds.right() - dock_width_);
+ dock_bounds.set_width(dock_width_);
+ }
+ if (dock_width_ == 0) {
+ if (bounds.x() == dock_bounds.x())
+ stuck_edges_mask |= DOCK_EDGE_LEFT;
+ if (bounds.right() == dock_bounds.right())
+ stuck_edges_mask |= DOCK_EDGE_RIGHT;
+ } else {
+ if (bounds.Intersects(dock_bounds))
+ stuck_edges_mask |= (alignment_ == DOCK_ALIGNMENT_LEFT ?
+ DOCK_EDGE_LEFT : DOCK_EDGE_RIGHT);
+ }
+
+ // do not allow dock on the same side as launcher shelf
+ switch (launcher_->shelf_widget()->GetAlignment()) {
+ case SHELF_ALIGNMENT_LEFT:
+ stuck_edges_mask &= ~DOCK_EDGE_LEFT;
+ break;
+ case SHELF_ALIGNMENT_RIGHT:
+ stuck_edges_mask &= ~DOCK_EDGE_RIGHT;
+ break;
+ default:
+ break;
+ }
+ return stuck_edges_mask;
+}
+
+void DockLayoutManager::SetLauncher(ash::Launcher* launcher) {
+ DCHECK(!launcher_);
+ DCHECK(!shelf_layout_manager_);
+ launcher_ = launcher;
+ launcher_->AddIconObserver(this);
+ if (launcher_->shelf_widget()) {
+ shelf_layout_manager_ = ash::internal::ShelfLayoutManager::ForLauncher(
+ launcher_->shelf_widget()->GetNativeWindow());
+ WillChangeVisibilityState(shelf_layout_manager_->visibility_state());
+ shelf_layout_manager_->AddObserver(this);
+ }
+}
+
+void DockLayoutManager::ToggleMinimize(aura::Window* window) {
+ DCHECK(window->parent() == dock_container_);
+ if (window->GetProperty(aura::client::kShowStateKey) ==
+ ui::SHOW_STATE_MINIMIZED) {
+ window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
+ } else {
+ window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// DockLayoutManager, aura::LayoutManager implementation:
+void DockLayoutManager::OnWindowResized() {
+ LOG(INFO) << "OnWindowResized ";
+ Relayout();
+
+ gfx::Rect bounds = dock_container_->bounds();
+ switch (alignment_) {
+ case DOCK_ALIGNMENT_LEFT:
+ bounds.Inset(dock_container_->bounds().width() - dock_width_,0,0,0);
+ break;
+ case DOCK_ALIGNMENT_RIGHT:
+ bounds.Inset(0,0,dock_container_->bounds().width() - dock_width_,0);
+ break;
+ case DOCK_ALIGNMENT_NONE:
+ bounds.set_width(0);
+ break;
+ }
+ FOR_EACH_OBSERVER(
+ DockObserver,
+ observer_list_,
+ OnDockBoundsChanging(bounds));
+}
+
+void DockLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
+ LOG(INFO) << this << " OnWindowAddedToLayout dock " << child;
+ if (GetDockEdges(child) == DOCK_EDGE_NONE)
+ return;
+ DockInfo dock_info;
+ dock_info.window = child;
+ if (child != dragged_window_) {
+ // Set the window to 0 opacity until it has been positioned to prevent it
+ // from flashing briefly at position (0, 0).
+ child->layer()->SetOpacity(0);
+ dock_info.slide_in = true;
+ }
+ dock_windows_.push_back(dock_info);
+ child->AddObserver(this);
+ Relayout();
+}
+
+void DockLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) {
+}
+
+void DockLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) {
+ LOG(INFO) << this << " OnWindowRemovedFromLayout dock " << child;
+ DockList::iterator found =
+ std::find(dock_windows_.begin(), dock_windows_.end(), child);
+ if (found != dock_windows_.end()) {
+ dock_windows_.erase(found);
+ SetDockEdges(child, DOCK_EDGE_NONE);
+ }
+ child->RemoveObserver(this);
+
+ if (dragged_window_ == child)
+ dragged_window_ = NULL;
+
+ if (last_active_window_ == child)
+ last_active_window_ = NULL;
+
+ Relayout();
+}
+
+void DockLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child,
+ bool visible) {
+ LOG(INFO) << "OnChildWindowVisibilityChanged " << child;
+ Relayout();
+}
+
+void DockLayoutManager::SetChildBounds(aura::Window* child,
+ const gfx::Rect& requested_bounds) {
+ LOG(INFO) << "SetChildBounds";
+ gfx::Rect bounds(requested_bounds);
+ const gfx::Rect& max_bounds = dock_container_->GetRootWindow()->bounds();
+ const int max_width = max_bounds.width() * kMaxWidthFactor;
+ const int max_height = max_bounds.height() * kMaxHeightFactor;
+ if (bounds.width() > max_width)
+ bounds.set_width(max_width);
+ if (bounds.height() > max_height)
+ bounds.set_height(max_height);
+
+ // Reposition dragged window in the window order.
+ if (dragged_window_ == child) {
+ DockList::iterator dragged_window_iter =
+ std::find(dock_windows_.begin(), dock_windows_.end(), dragged_window_);
+ DCHECK(dragged_window_iter != dock_windows_.end());
+ DockList::iterator new_position;
+ for (new_position = dock_windows_.begin();
+ new_position != dock_windows_.end();
+ ++new_position) {
+ const gfx::Rect& bounds = (*new_position).window->bounds();
+ if (bounds.x() + bounds.width()/2 <= requested_bounds.x()) break;
+ }
+ if (new_position != dragged_window_iter) {
+ DockInfo dragged_window_info = *dragged_window_iter;
+ dock_windows_.erase(dragged_window_iter);
+ dock_windows_.insert(new_position, dragged_window_info);
+ }
+ }
+
+ SetChildBoundsDirect(child, bounds);
+ Relayout();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// DockLayoutManager, ash::LauncherIconObserver implementation:
+
+void DockLayoutManager::OnLauncherIconPositionsChanged() {
+ // TODO: As this is called for every animation step now. Relayout needs to be
+ // updated to use current icon position instead of use the ideal bounds so
+ // that the windows slide with their icons instead of jumping.
+ Relayout();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// DockLayoutManager, ash::ShellObserver implementation:
+
+void DockLayoutManager::OnShelfAlignmentChanged(
+ aura::RootWindow* root_window) {
+ if (dock_container_->GetRootWindow() == root_window) {
+ if (launcher_ && launcher_->shelf_widget()) {
+ // We do not allow launcher and dock on the same side. Switch side that
+ // the dock is attached to and move all dock windows to that new side
+ ShelfAlignment shelf_alignment =
+ launcher_->shelf_widget()->GetAlignment();
+ if (alignment_ == DOCK_ALIGNMENT_LEFT &&
+ shelf_alignment == SHELF_ALIGNMENT_LEFT) {
+ for (DockList::iterator iter = dock_windows_.begin();
+ iter != dock_windows_.end(); ++iter) {
+ SetDockEdges(iter->window, DOCK_EDGE_RIGHT);
+ iter->slide_in = true;
+ }
+ } else if (alignment_ == DOCK_ALIGNMENT_RIGHT &&
+ shelf_alignment == SHELF_ALIGNMENT_RIGHT) {
+ for (DockList::iterator iter = dock_windows_.begin();
+ iter != dock_windows_.end(); ++iter) {
+ SetDockEdges(iter->window, DOCK_EDGE_LEFT);
+ iter->slide_in = true;
+ }
+ }
+ }
+ Relayout();
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// DockLayoutManager, WindowObserver implementation:
+
+void DockLayoutManager::OnWindowPropertyChanged(aura::Window* window,
+ const void* key,
+ intptr_t old) {
+ if (key == ash::internal::kDockEdges &&
+ GetDockEdges(window) != static_cast<int>(old)) {
+ int edges = GetDockEdges(window);
+ LOG(INFO) << "Stuck property changed to " << GetDockEdges(window);
+ if (edges == DOCK_EDGE_NONE && window->GetRootWindow()) {
+ // Reparenting will cause Relayout and possible dock resize.
+ window->SetDefaultParentByRootWindow(window->GetRootWindow(),
+ window->GetBoundsInScreen());
+ // A maximized workspace may be active so we may need to switch
+ // to a parent workspace of the window being dragged out.
+ internal::WorkspaceController* workspace_controller =
+ GetRootWindowController(
+ window->GetRootWindow())->workspace_controller();
+ workspace_controller->SetActiveWorkspaceByWindow(window);
+ }
+ }
+
+ if (key == aura::client::kShowStateKey) {
+ // The window property will still be set, but no actual change will occur
+ // until WillChangeVisibilityState is called when the shelf is visible again
+ if (shelf_hidden_)
+ return;
+ ui::WindowShowState new_state =
+ window->GetProperty(aura::client::kShowStateKey);
+ if (new_state == ui::SHOW_STATE_MINIMIZED)
+ MinimizeWindow(window);
+ else
+ RestoreWindow(window);
+ }
+}
+
+void DockLayoutManager::OnWindowVisibilityChanged(
+ aura::Window* window, bool visible) {
+ if (visible)
+ window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// DockLayoutManager, aura::client::ActivationChangeObserver implementation:
+
+void DockLayoutManager::OnWindowActivated(aura::Window* gained_active,
+ aura::Window* lost_active) {
+ // Ignore if the window that is not managed by this was activated.
+ if (gained_active &&
+ gained_active->parent() == dock_container_) {
+ UpdateStacking(gained_active);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// DockLayoutManager, ShelfLayoutManagerObserver implementation:
+
+void DockLayoutManager::WillChangeVisibilityState(
+ ShelfVisibilityState new_state) {
+ // On entering / leaving full screen mode the shelf visibility state is
+ // changed to / from SHELF_HIDDEN. In this state, docked windows should hide
+ // to allow the full-screen application to use the full screen.
+ shelf_hidden_ = new_state == ash::SHELF_HIDDEN;
+ for (DockList::iterator iter = dock_windows_.begin();
+ iter != dock_windows_.end(); ++iter) {
+ if (shelf_hidden_) {
+ if (iter->window->IsVisible())
+ MinimizeWindow(iter->window);
+ } else {
+ if (iter->window->GetProperty(aura::client::kShowStateKey) !=
+ ui::SHOW_STATE_MINIMIZED) {
+ RestoreWindow(iter->window);
+ }
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// DockLayoutManager private implementation:
+
+void DockLayoutManager::MinimizeWindow(aura::Window* window) {
+ views::corewm::SetWindowVisibilityAnimationType(
+ window, WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE);
+ ui::Layer* layer = window->layer();
+ ui::ScopedLayerAnimationSettings window_slide_settings(layer->GetAnimator());
+ window_slide_settings.SetPreemptionStrategy(
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ window_slide_settings.SetTransitionDuration(
+ base::TimeDelta::FromMilliseconds(kWindowSlideDurationMilliseconds));
+ window->Hide();
+ DockList::iterator found =
+ std::find(dock_windows_.begin(), dock_windows_.end(), window);
+ if (found != dock_windows_.end()) {
+ layer->SetOpacity(0);
+ // The next time the window is visible it should slide into place.
+ found->slide_in = true;
+ }
+ if (wm::IsActiveWindow(window))
+ wm::DeactivateWindow(window);
+ Relayout();
+}
+
+void DockLayoutManager::RestoreWindow(aura::Window* window) {
+ window->Show();
+ Relayout();
+}
+
+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
+ if (in_layout_)
+ return;
+
+ if (!launcher_ || !launcher_->shelf_widget())
+ return;
+
+ LOG(INFO) << "Relayout (" << dock_windows_.size() << " windows in dock)";
+ base::AutoReset<bool> auto_reset_in_layout(&in_layout_, true);
+
+ int dock_width = kMinDockWidth;
+ DockAlignment alignment = alignment_;
+ if (dock_windows_.empty()) {
+ alignment_ = DOCK_ALIGNMENT_NONE;
+ if (dock_width_ != 0) {
+ dock_width_ = 0;
+ OnWindowResized();
+ }
+ return;
+ }
+
+ bool horizontal = false;
+ gfx::Rect launcher_bounds = dock_container_->bounds();
+// launcher_bounds.set_width(dock_width);
+// if (alignment == SHELF_ALIGNMENT_RIGHT)
+// launcher_bounds.set_x(dock_container_->bounds().width() -
+// launcher_bounds.width());
+ int window_start_bounds = kWindowIdealSpacing;
+ int window_end_bounds = horizontal ?
+ dock_container_->bounds().width() - kWindowIdealSpacing :
+ dock_container_->bounds().height() - kWindowIdealSpacing;
+ aura::Window* active_window = NULL;
+ std::vector<VisibleWindowPositionInfo> visible_windows;
+ alignment =
+ GetDockEdges(dock_windows_.begin()->window) == DOCK_EDGE_LEFT ?
+ DOCK_ALIGNMENT_LEFT : DOCK_ALIGNMENT_RIGHT;
+ LOG(INFO) << "alignment=" << alignment;
+ for (DockList::iterator iter = dock_windows_.begin();
+ iter != dock_windows_.end(); ++iter) {
+ aura::Window* window = iter->window;
+
+ // Consider the dragged window as part of the layout as long as it is
+ // touching the launcher.
+ if (!window->IsVisible() ||
+ (window == dragged_window_ &&
+ !BoundsAdjacent(window->bounds(), launcher_bounds))) {
+// continue;
+ }
+
+ // If the shelf is currently hidden (full-screen mode), hide window until
+ // full-screen mode is exited.
+ if (shelf_hidden_) {
+ // The call to Hide does not set the minimize property, so the window will
+ // be restored when the shelf becomes visible again.
+ window->Hide();
+ continue;
+ }
+
+ gfx::Rect icon_bounds =
+ launcher_->GetScreenBoundsOfItemIconForWindow(window);
+
+ // If both the icon width and height are 0 then there is no icon in the
+ // launcher. If the launcher is hidden, one of the height or width will be
+ // 0 but the position in the launcher and major dimension is still reported
+ // correctly and the window can be aligned above where the hidden icon is.
+ if (icon_bounds.width() == 0 && icon_bounds.height() == 0)
+ continue;
+
+ if (window->HasFocus() ||
+ window->Contains(
+ aura::client::GetFocusClient(window)->GetFocusedWindow())) {
+ DCHECK(!active_window);
+ active_window = window;
+ }
+ icon_bounds = ScreenAsh::ConvertRectFromScreen(dock_container_,
+ icon_bounds);
+ gfx::Point icon_origin = icon_bounds.origin();
+ VisibleWindowPositionInfo position_info;
+ int icon_start = horizontal ? icon_origin.x() : icon_origin.y();
+ int icon_end = icon_start + (horizontal ? icon_bounds.width() :
+ icon_bounds.height());
+ position_info.major_length = horizontal ?
+ window->bounds().width() : window->bounds().height();
+ position_info.min_major = std::max(
+ window_start_bounds + position_info.major_length / 2,
+ icon_end - position_info.major_length / 2);
+ position_info.max_major = std::min(
+ icon_start + position_info.major_length / 2,
+ window_end_bounds - position_info.major_length / 2);
+ position_info.major_pos = (icon_start + icon_end) / 2;
+ position_info.window = window;
+ position_info.slide_in = iter->slide_in;
+ iter->slide_in = false;
+ visible_windows.push_back(position_info);
+ }
+
+ bool visible_non_minimized_windows = false;
+ for (size_t i = 0; i < visible_windows.size(); ++i) {
+ gfx::Rect bounds = visible_windows[i].window->GetTargetBounds();
+ bool slide_in = visible_windows[i].slide_in;
+ switch (alignment) {
+ case DOCK_ALIGNMENT_LEFT:
+ if (bounds.width() > kMaxDockWidth) {
+ bounds.set_width(kMaxDockWidth);
+ }
+ if (slide_in || bounds.x() - launcher_bounds.x() < 32)
+ bounds.set_x(0);
+ break;
+ case DOCK_ALIGNMENT_RIGHT:
+ if (bounds.width() > kMaxDockWidth) {
+ bounds.set_x(bounds.x() + bounds.width() - kMaxDockWidth);
+ bounds.set_width(kMaxDockWidth);
+ }
+ if (slide_in || launcher_bounds.right() - bounds.right() < 32)
+ bounds.set_x(launcher_bounds.right() - bounds.width());
+ break;
+ case DOCK_ALIGNMENT_NONE:
+ break;
+ }
+ if (visible_windows[i].window->GetProperty(aura::client::kShowStateKey) !=
+ ui::SHOW_STATE_MINIMIZED) {
+ visible_non_minimized_windows = true;
+ if (dock_width < bounds.width() + kMinDockGap)
+ dock_width = bounds.width() + kMinDockGap;
+ }
+ if (visible_windows[i].window == dragged_window_) {
+ SetChildBoundsDirect(visible_windows[i].window, bounds);
+ continue;
+ }
+ bool on_launcher = visible_windows[i].window->GetTargetBounds() == bounds;
+
+ ui::Layer* layer = visible_windows[i].window->layer();
+ if (slide_in) {
+ // New windows shift up from the launcher into position.
+ SetChildBoundsDirect(visible_windows[i].window, bounds);
+ // Set on launcher so that the window animates into its target position.
+ on_launcher = true;
+ }
+
+ if (on_launcher) {
+ ui::ScopedLayerAnimationSettings window_slide_settings(
+ layer->GetAnimator());
+ window_slide_settings.SetPreemptionStrategy(
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ window_slide_settings.SetTransitionDuration(
+ base::TimeDelta::FromMilliseconds(kWindowSlideDurationMilliseconds));
+ SetChildBoundsDirect(visible_windows[i].window, bounds);
+ if (slide_in)
+ layer->SetOpacity(1);
+ } else {
+ // If the launcher moved don't animate, move immediately to the new
+ // target location.
+ SetChildBoundsDirect(visible_windows[i].window, bounds);
+ }
+ }
+ if (!visible_non_minimized_windows)
+ dock_width = 0;
+
+ UpdateStacking(active_window);
+ if (dock_width != dock_width_ || alignment != alignment_) {
+ alignment_ = alignment;
+ dock_width_ = dock_width;
+ OnWindowResized();
+ }
+}
+
+void DockLayoutManager::UpdateStacking(aura::Window* active_window) {
+ if (!active_window) {
+ if (!last_active_window_)
+ return;
+ active_window = last_active_window_;
+ }
+
+ // 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
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// keyboard::KeyboardControllerObserver implementation:
+
+void DockLayoutManager::OnKeyboardBoundsChanging(
+ const gfx::Rect& keyboard_bounds) {
+ // This bounds change will have caused a change to the Shelf which does not
+ // propagate automatically to this class, so manually recalculate bounds.
+ OnWindowResized();
+}
+
+} // namespace internal
+} // namespace ash

Powered by Google App Engine
This is Rietveld 408576698