summaryrefslogtreecommitdiffstats
path: root/chromium/ash/wm/dock/docked_window_layout_manager.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ash/wm/dock/docked_window_layout_manager.cc')
-rw-r--r--chromium/ash/wm/dock/docked_window_layout_manager.cc1240
1 files changed, 0 insertions, 1240 deletions
diff --git a/chromium/ash/wm/dock/docked_window_layout_manager.cc b/chromium/ash/wm/dock/docked_window_layout_manager.cc
deleted file mode 100644
index 3298f05602f..00000000000
--- a/chromium/ash/wm/dock/docked_window_layout_manager.cc
+++ /dev/null
@@ -1,1240 +0,0 @@
-// Copyright (c) 2013 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/docked_window_layout_manager.h"
-
-#include "ash/ash_switches.h"
-#include "ash/launcher/launcher.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/shell_window_ids.h"
-#include "ash/wm/coordinate_conversion.h"
-#include "ash/wm/window_animations.h"
-#include "ash/wm/window_properties.h"
-#include "ash/wm/window_state.h"
-#include "ash/wm/window_util.h"
-#include "ash/wm/workspace_controller.h"
-#include "base/auto_reset.h"
-#include "base/command_line.h"
-#include "base/metrics/histogram.h"
-#include "grit/ash_resources.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "third_party/skia/include/core/SkPaint.h"
-#include "ui/aura/client/activation_client.h"
-#include "ui/aura/client/focus_client.h"
-#include "ui/aura/client/window_tree_client.h"
-#include "ui/aura/root_window.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_delegate.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/compositor/scoped_layer_animation_settings.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/image/image_skia_operations.h"
-#include "ui/gfx/rect.h"
-#include "ui/views/background.h"
-
-namespace ash {
-namespace internal {
-
-// Minimum, maximum width of the dock area and a width of the gap
-// static
-const int DockedWindowLayoutManager::kMaxDockWidth = 360;
-// static
-const int DockedWindowLayoutManager::kMinDockWidth = 200;
-// static
-const int DockedWindowLayoutManager::kMinDockGap = 2;
-// static
-const int DockedWindowLayoutManager::kIdealWidth = 250;
-const int kMinimumHeight = 250;
-const int kSlideDurationMs = 120;
-const int kFadeDurationMs = 60;
-const int kMinimizeDurationMs = 720;
-
-class DockedBackgroundWidget : public views::Widget,
- public internal::BackgroundAnimatorDelegate {
- public:
- explicit DockedBackgroundWidget(aura::Window* container)
- : alignment_(DOCKED_ALIGNMENT_NONE),
- background_animator_(this, 0, kLauncherBackgroundAlpha),
- alpha_(0),
- opaque_background_(ui::LAYER_SOLID_COLOR) {
- InitWidget(container);
- }
-
- // Sets widget bounds and sizes opaque background layer to fill the widget.
- void SetBackgroundBounds(const gfx::Rect bounds, DockedAlignment alignment) {
- SetBounds(bounds);
- opaque_background_.SetBounds(gfx::Rect(bounds.size()));
- alignment_ = alignment;
- }
-
- // Sets the docked area background type and starts transition animation.
- void SetPaintsBackground(
- ShelfBackgroundType background_type,
- BackgroundAnimatorChangeType change_type) {
- float target_opacity =
- (background_type == SHELF_BACKGROUND_MAXIMIZED) ? 1.0f : 0.0f;
- scoped_ptr<ui::ScopedLayerAnimationSettings> opaque_background_animation;
- if (change_type != BACKGROUND_CHANGE_IMMEDIATE) {
- opaque_background_animation.reset(new ui::ScopedLayerAnimationSettings(
- opaque_background_.GetAnimator()));
- opaque_background_animation->SetTransitionDuration(
- base::TimeDelta::FromMilliseconds(kTimeToSwitchBackgroundMs));
- }
- opaque_background_.SetOpacity(target_opacity);
-
- // TODO(varkha): use ui::Layer on both opaque_background and normal
- // background retire background_animator_ at all. It would be simpler.
- // See also ShelfWidget::SetPaintsBackground.
- background_animator_.SetPaintsBackground(
- background_type != SHELF_BACKGROUND_DEFAULT,
- change_type);
- SchedulePaintInRect(gfx::Rect(GetWindowBoundsInScreen().size()));
- }
-
- // views::Widget:
- virtual void OnNativeWidgetPaint(gfx::Canvas* canvas) OVERRIDE {
- const gfx::ImageSkia& launcher_background(
- alignment_ == DOCKED_ALIGNMENT_LEFT ?
- launcher_background_left_ : launcher_background_right_);
- gfx::Rect rect = gfx::Rect(GetWindowBoundsInScreen().size());
- SkPaint paint;
- paint.setAlpha(alpha_);
- canvas->DrawImageInt(
- launcher_background,
- 0, 0, launcher_background.width(), launcher_background.height(),
- alignment_ == DOCKED_ALIGNMENT_LEFT ?
- rect.width() - launcher_background.width() : 0, 0,
- launcher_background.width(), rect.height(),
- false,
- paint);
- canvas->DrawImageInt(
- launcher_background,
- alignment_ == DOCKED_ALIGNMENT_LEFT ?
- 0 : launcher_background.width() - 1, 0,
- 1, launcher_background.height(),
- alignment_ == DOCKED_ALIGNMENT_LEFT ?
- 0 : launcher_background.width(), 0,
- rect.width() - launcher_background.width(), rect.height(),
- false,
- paint);
- }
-
- // BackgroundAnimatorDelegate:
- virtual void UpdateBackground(int alpha) OVERRIDE {
- alpha_ = alpha;
- SchedulePaintInRect(gfx::Rect(GetWindowBoundsInScreen().size()));
- }
-
- private:
- void InitWidget(aura::Window* parent) {
- views::Widget::InitParams params;
- params.type = views::Widget::InitParams::TYPE_POPUP;
- params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
- params.can_activate = false;
- params.keep_on_top = false;
- params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params.parent = parent;
- params.accept_events = false;
- set_focus_on_creation(false);
- Init(params);
- GetNativeWindow()->SetProperty(internal::kStayInSameRootWindowKey, true);
- opaque_background_.SetColor(SK_ColorBLACK);
- opaque_background_.SetBounds(gfx::Rect(GetWindowBoundsInScreen().size()));
- opaque_background_.SetOpacity(0.0f);
- GetNativeWindow()->layer()->Add(&opaque_background_);
- Hide();
-
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- gfx::ImageSkia launcher_background =
- *rb.GetImageSkiaNamed(IDR_AURA_LAUNCHER_BACKGROUND);
- launcher_background_left_ = gfx::ImageSkiaOperations::CreateRotatedImage(
- launcher_background, SkBitmapOperations::ROTATION_90_CW);
- launcher_background_right_ = gfx::ImageSkiaOperations::CreateRotatedImage(
- launcher_background, SkBitmapOperations::ROTATION_270_CW);
- }
-
- DockedAlignment alignment_;
-
- // The animator for the background transitions.
- internal::BackgroundAnimator background_animator_;
-
- // The alpha to use for drawing image assets covering the docked background.
- int alpha_;
-
- // Solid black background that can be made fully opaque.
- ui::Layer opaque_background_;
-
- // Backgrounds created from shelf background by 90 or 270 degree rotation.
- gfx::ImageSkia launcher_background_left_;
- gfx::ImageSkia launcher_background_right_;
-
- DISALLOW_COPY_AND_ASSIGN(DockedBackgroundWidget);
-};
-
-namespace {
-
-// Returns true if a window is a popup or a transient child.
-bool IsPopupOrTransient(const aura::Window* window) {
- return (window->type() == aura::client::WINDOW_TYPE_POPUP ||
- window->transient_parent());
-}
-
-// Certain windows (minimized, hidden or popups) do not matter to docking.
-bool IsUsedByLayout(const aura::Window* window) {
- return (window->IsVisible() &&
- !wm::GetWindowState(window)->IsMinimized() &&
- !IsPopupOrTransient(window));
-}
-
-void UndockWindow(aura::Window* window) {
- gfx::Rect previous_bounds = window->bounds();
- aura::Window* old_parent = window->parent();
- aura::client::ParentWindowWithContext(window, window, gfx::Rect());
- if (window->parent() != old_parent)
- wm::ReparentTransientChildrenOfChild(window, old_parent, window->parent());
- // Start maximize or fullscreen (affecting packaged apps) animation from
- // previous window bounds.
- window->layer()->SetBounds(previous_bounds);
-}
-
-// Returns width that is as close as possible to |target_width| while being
-// consistent with docked min and max restrictions and respects the |window|'s
-// minimum and maximum size.
-int GetWindowWidthCloseTo(const aura::Window* window, int target_width) {
- if (!wm::GetWindowState(window)->CanResize()) {
- DCHECK_LE(window->bounds().width(),
- DockedWindowLayoutManager::kMaxDockWidth);
- return window->bounds().width();
- }
- int width = std::max(DockedWindowLayoutManager::kMinDockWidth,
- std::min(target_width,
- DockedWindowLayoutManager::kMaxDockWidth));
- if (window->delegate()) {
- if (window->delegate()->GetMinimumSize().width() != 0)
- width = std::max(width, window->delegate()->GetMinimumSize().width());
- if (window->delegate()->GetMaximumSize().width() != 0)
- width = std::min(width, window->delegate()->GetMaximumSize().width());
- }
- DCHECK_LE(width, DockedWindowLayoutManager::kMaxDockWidth);
- return width;
-}
-
-// Returns height that is as close as possible to |target_height| while
-// respecting the |window|'s minimum and maximum size.
-int GetWindowHeightCloseTo(const aura::Window* window, int target_height) {
- if (!wm::GetWindowState(window)->CanResize())
- return window->bounds().height();
- int minimum_height = kMinimumHeight;
- int maximum_height = 0;
- const aura::WindowDelegate* delegate(window->delegate());
- if (delegate) {
- if (delegate->GetMinimumSize().height() != 0) {
- minimum_height = std::max(kMinimumHeight,
- delegate->GetMinimumSize().height());
- }
- if (delegate->GetMaximumSize().height() != 0)
- maximum_height = delegate->GetMaximumSize().height();
- }
- if (minimum_height)
- target_height = std::max(target_height, minimum_height);
- if (maximum_height)
- target_height = std::min(target_height, maximum_height);
- return target_height;
-}
-
-// A functor used to sort the windows in order of their minimum height.
-struct CompareMinimumHeight {
- bool operator()(WindowWithHeight win1, WindowWithHeight win2) {
- return GetWindowHeightCloseTo(win1.window(), 0) <
- GetWindowHeightCloseTo(win2.window(), 0);
- }
-};
-
-// A functor used to sort the windows in order of their center Y position.
-// |delta| is a pre-calculated distance from the bottom of one window to the top
-// of the next. Its value can be positive (gap) or negative (overlap).
-// Half of |delta| is used as a transition point at which windows could ideally
-// swap positions.
-struct CompareWindowPos {
- CompareWindowPos(aura::Window* dragged_window, float delta)
- : dragged_window_(dragged_window),
- delta_(delta / 2) {}
-
- bool operator()(WindowWithHeight window_with_height1,
- WindowWithHeight window_with_height2) {
- // Use target coordinates since animations may be active when windows are
- // reordered.
- aura::Window* win1(window_with_height1.window());
- aura::Window* win2(window_with_height2.window());
- gfx::Rect win1_bounds = ScreenAsh::ConvertRectToScreen(
- win1->parent(), win1->GetTargetBounds());
- gfx::Rect win2_bounds = ScreenAsh::ConvertRectToScreen(
- win2->parent(), win2->GetTargetBounds());
- win1_bounds.set_height(window_with_height1.height_);
- win2_bounds.set_height(window_with_height2.height_);
- // If one of the windows is the |dragged_window_| attempt to make an
- // earlier swap between the windows than just based on their centers.
- // This is possible if the dragged window is at least as tall as the other
- // window.
- if (win1 == dragged_window_)
- return compare_two_windows(win1_bounds, win2_bounds);
- if (win2 == dragged_window_)
- return !compare_two_windows(win2_bounds, win1_bounds);
- // Otherwise just compare the centers.
- return win1_bounds.CenterPoint().y() < win2_bounds.CenterPoint().y();
- }
-
- // Based on center point tries to deduce where the drag is coming from.
- // When dragging from below up the transition point is lower.
- // When dragging from above down the transition point is higher.
- bool compare_bounds(const gfx::Rect dragged, const gfx::Rect other) {
- if (dragged.CenterPoint().y() < other.CenterPoint().y())
- return dragged.CenterPoint().y() < other.y() - delta_;
- return dragged.CenterPoint().y() < other.bottom() + delta_;
- }
-
- // Performs comparison both ways and selects stable result.
- bool compare_two_windows(const gfx::Rect bounds1, const gfx::Rect bounds2) {
- // Try comparing windows in both possible orders and see if the comparison
- // is stable.
- bool result1 = compare_bounds(bounds1, bounds2);
- bool result2 = compare_bounds(bounds2, bounds1);
- if (result1 != result2)
- return result1;
-
- // Otherwise it is not possible to be sure that the windows will not bounce.
- // In this case just compare the centers.
- return bounds1.CenterPoint().y() < bounds2.CenterPoint().y();
- }
-
- private:
- aura::Window* dragged_window_;
- float delta_;
-};
-
-} // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-// A class that observes launcher shelf for bounds changes.
-class DockedWindowLayoutManager::ShelfWindowObserver : public WindowObserver {
- public:
- explicit ShelfWindowObserver(
- DockedWindowLayoutManager* docked_layout_manager)
- : docked_layout_manager_(docked_layout_manager) {
- DCHECK(docked_layout_manager_->launcher()->shelf_widget());
- docked_layout_manager_->launcher()->shelf_widget()->GetNativeView()
- ->AddObserver(this);
- }
-
- virtual ~ShelfWindowObserver() {
- if (docked_layout_manager_->launcher() &&
- docked_layout_manager_->launcher()->shelf_widget())
- docked_layout_manager_->launcher()->shelf_widget()->GetNativeView()
- ->RemoveObserver(this);
- }
-
- // aura::WindowObserver:
- virtual void OnWindowBoundsChanged(aura::Window* window,
- const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds) OVERRIDE {
- shelf_bounds_in_screen_ = ScreenAsh::ConvertRectToScreen(
- window->parent(), new_bounds);
- docked_layout_manager_->OnShelfBoundsChanged();
- }
-
- const gfx::Rect& shelf_bounds_in_screen() const {
- return shelf_bounds_in_screen_;
- }
-
- private:
- DockedWindowLayoutManager* docked_layout_manager_;
- gfx::Rect shelf_bounds_in_screen_;
-
- DISALLOW_COPY_AND_ASSIGN(ShelfWindowObserver);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// DockedWindowLayoutManager public implementation:
-DockedWindowLayoutManager::DockedWindowLayoutManager(
- aura::Window* dock_container, WorkspaceController* workspace_controller)
- : dock_container_(dock_container),
- in_layout_(false),
- dragged_window_(NULL),
- is_dragged_window_docked_(false),
- is_dragged_from_dock_(false),
- launcher_(NULL),
- workspace_controller_(workspace_controller),
- in_fullscreen_(workspace_controller_->GetWindowState() ==
- WORKSPACE_WINDOW_STATE_FULL_SCREEN),
- docked_width_(0),
- alignment_(DOCKED_ALIGNMENT_NONE),
- last_active_window_(NULL),
- last_action_time_(base::Time::Now()),
- background_widget_(new DockedBackgroundWidget(dock_container_)) {
- DCHECK(dock_container);
- aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())->
- AddObserver(this);
- Shell::GetInstance()->AddShellObserver(this);
-}
-
-DockedWindowLayoutManager::~DockedWindowLayoutManager() {
- Shutdown();
-}
-
-void DockedWindowLayoutManager::Shutdown() {
- if (launcher_ && launcher_->shelf_widget()) {
- ShelfLayoutManager* shelf_layout_manager = ShelfLayoutManager::ForLauncher(
- launcher_->shelf_widget()->GetNativeWindow());
- shelf_layout_manager->RemoveObserver(this);
- shelf_observer_.reset();
- }
- launcher_ = NULL;
- for (size_t i = 0; i < dock_container_->children().size(); ++i) {
- aura::Window* child = dock_container_->children()[i];
- child->RemoveObserver(this);
- wm::GetWindowState(child)->RemoveObserver(this);
- }
- aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())->
- RemoveObserver(this);
- Shell::GetInstance()->RemoveShellObserver(this);
-}
-
-void DockedWindowLayoutManager::AddObserver(
- DockedWindowLayoutManagerObserver* observer) {
- observer_list_.AddObserver(observer);
-}
-
-void DockedWindowLayoutManager::RemoveObserver(
- DockedWindowLayoutManagerObserver* observer) {
- observer_list_.RemoveObserver(observer);
-}
-
-void DockedWindowLayoutManager::StartDragging(aura::Window* window) {
- DCHECK(!dragged_window_);
- dragged_window_ = window;
- DCHECK(!IsPopupOrTransient(window));
- // Start observing a window unless it is docked container's child in which
- // case it is already observed.
- if (dragged_window_->parent() != dock_container_) {
- dragged_window_->AddObserver(this);
- wm::GetWindowState(dragged_window_)->AddObserver(this);
- }
- is_dragged_from_dock_ = window->parent() == dock_container_;
- DCHECK(!is_dragged_window_docked_);
-}
-
-void DockedWindowLayoutManager::DockDraggedWindow(aura::Window* window) {
- DCHECK(!IsPopupOrTransient(window));
- OnDraggedWindowDocked(window);
- Relayout();
-}
-
-void DockedWindowLayoutManager::UndockDraggedWindow() {
- DCHECK(!IsPopupOrTransient(dragged_window_));
- OnDraggedWindowUndocked();
- Relayout();
- UpdateDockBounds(DockedWindowLayoutManagerObserver::CHILD_CHANGED);
- is_dragged_from_dock_ = false;
-}
-
-void DockedWindowLayoutManager::FinishDragging(DockedAction action,
- DockedActionSource source) {
- DCHECK(dragged_window_);
- DCHECK(!IsPopupOrTransient(dragged_window_));
- if (is_dragged_window_docked_)
- OnDraggedWindowUndocked();
- DCHECK (!is_dragged_window_docked_);
- // Stop observing a window unless it is docked container's child in which
- // case it needs to keep being observed after the drag completes.
- if (dragged_window_->parent() != dock_container_) {
- dragged_window_->RemoveObserver(this);
- wm::GetWindowState(dragged_window_)->RemoveObserver(this);
- if (last_active_window_ == dragged_window_)
- last_active_window_ = NULL;
- } else {
- // A window is no longer dragged and is a child.
- // When a window becomes a child at drag start this is
- // the only opportunity we will have to enforce a window
- // count limit so do it here.
- MaybeMinimizeChildrenExcept(dragged_window_);
- }
- dragged_window_ = NULL;
- dragged_bounds_ = gfx::Rect();
- Relayout();
- UpdateDockBounds(DockedWindowLayoutManagerObserver::CHILD_CHANGED);
- RecordUmaAction(action, source);
-}
-
-void DockedWindowLayoutManager::SetLauncher(ash::Launcher* launcher) {
- DCHECK(!launcher_);
- launcher_ = launcher;
- if (launcher_->shelf_widget()) {
- ShelfLayoutManager* shelf_layout_manager = ShelfLayoutManager::ForLauncher(
- launcher_->shelf_widget()->GetNativeWindow());
- shelf_layout_manager->AddObserver(this);
- shelf_observer_.reset(new ShelfWindowObserver(this));
- }
-}
-
-DockedAlignment DockedWindowLayoutManager::GetAlignmentOfWindow(
- const aura::Window* window) const {
- const gfx::Rect& bounds(window->GetBoundsInScreen());
-
- // Test overlap with an existing docked area first.
- if (docked_bounds_.Intersects(bounds) &&
- alignment_ != DOCKED_ALIGNMENT_NONE) {
- // A window is being added to other docked windows (on the same side).
- return alignment_;
- }
-
- const gfx::Rect container_bounds = dock_container_->GetBoundsInScreen();
- if (bounds.x() <= container_bounds.x() &&
- bounds.right() > container_bounds.x()) {
- return DOCKED_ALIGNMENT_LEFT;
- } else if (bounds.x() < container_bounds.right() &&
- bounds.right() >= container_bounds.right()) {
- return DOCKED_ALIGNMENT_RIGHT;
- }
- return DOCKED_ALIGNMENT_NONE;
-}
-
-DockedAlignment DockedWindowLayoutManager::CalculateAlignment() const {
- // Find a child that is not being dragged and is not a popup.
- // If such exists the current alignment is returned - even if some of the
- // children are hidden or minimized (so they can be restored without losing
- // the docked state).
- for (size_t i = 0; i < dock_container_->children().size(); ++i) {
- aura::Window* window(dock_container_->children()[i]);
- if (window != dragged_window_ && !IsPopupOrTransient(window))
- return alignment_;
- }
- // No docked windows remain other than possibly the window being dragged.
- // Return |NONE| to indicate that windows may get docked on either side.
- return DOCKED_ALIGNMENT_NONE;
-}
-
-bool DockedWindowLayoutManager::CanDockWindow(aura::Window* window,
- SnapType edge) {
- if (!switches::UseDockedWindows())
- return false;
- // Don't allow interactive docking of windows with transient parents such as
- // modal browser dialogs.
- if (IsPopupOrTransient(window))
- return false;
- // If a window is wide and cannot be resized down to maximum width allowed
- // then it cannot be docked.
- // TODO(varkha). Prevent windows from changing size programmatically while
- // they are docked. The size will take effect only once a window is undocked.
- // See http://crbug.com/307792.
- if (window->bounds().width() > kMaxDockWidth &&
- (!wm::GetWindowState(window)->CanResize() ||
- (window->delegate() &&
- window->delegate()->GetMinimumSize().width() != 0 &&
- window->delegate()->GetMinimumSize().width() > kMaxDockWidth))) {
- return false;
- }
- // If a window is tall and cannot be resized down to maximum height allowed
- // then it cannot be docked.
- const gfx::Rect work_area =
- Shell::GetScreen()->GetDisplayNearestWindow(dock_container_).work_area();
- if (GetWindowHeightCloseTo(window, work_area.height() - 2 * kMinDockGap) >
- work_area.height() - 2 * kMinDockGap) {
- return false;
- }
- // Cannot dock on the other size from an existing dock.
- const DockedAlignment alignment = CalculateAlignment();
- if ((edge == SNAP_LEFT && alignment == DOCKED_ALIGNMENT_RIGHT) ||
- (edge == SNAP_RIGHT && alignment == DOCKED_ALIGNMENT_LEFT)) {
- return false;
- }
- // Do not allow docking on the same side as launcher shelf.
- ShelfAlignment shelf_alignment = SHELF_ALIGNMENT_BOTTOM;
- if (launcher_)
- shelf_alignment = launcher_->alignment();
- if ((edge == SNAP_LEFT && shelf_alignment == SHELF_ALIGNMENT_LEFT) ||
- (edge == SNAP_RIGHT && shelf_alignment == SHELF_ALIGNMENT_RIGHT)) {
- return false;
- }
- return true;
-}
-
-void DockedWindowLayoutManager::OnShelfBoundsChanged() {
- Relayout();
- UpdateDockBounds(DockedWindowLayoutManagerObserver::DISPLAY_INSETS_CHANGED);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// DockedWindowLayoutManager, aura::LayoutManager implementation:
-void DockedWindowLayoutManager::OnWindowResized() {
- MaybeMinimizeChildrenExcept(dragged_window_);
- Relayout();
- // When screen resizes update the insets even when dock width or alignment
- // does not change.
- UpdateDockBounds(DockedWindowLayoutManagerObserver::DISPLAY_RESIZED);
-}
-
-void DockedWindowLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
- if (IsPopupOrTransient(child))
- return;
- // Dragged windows are already observed by StartDragging and do not change
- // docked alignment during the drag.
- if (child == dragged_window_)
- return;
- // If this is the first window getting docked - update alignment.
- if (alignment_ == DOCKED_ALIGNMENT_NONE) {
- alignment_ = GetAlignmentOfWindow(child);
- DCHECK(alignment_ != DOCKED_ALIGNMENT_NONE);
- }
- MaybeMinimizeChildrenExcept(child);
- child->AddObserver(this);
- wm::GetWindowState(child)->AddObserver(this);
- Relayout();
- UpdateDockBounds(DockedWindowLayoutManagerObserver::CHILD_CHANGED);
-}
-
-void DockedWindowLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) {
- if (IsPopupOrTransient(child))
- return;
- // Dragged windows are stopped being observed by FinishDragging and do not
- // change alignment during the drag. They also cannot be set to be the
- // |last_active_window_|.
- if (child == dragged_window_)
- return;
- // If this is the last window, set alignment and maximize the workspace.
- if (!IsAnyWindowDocked()) {
- alignment_ = DOCKED_ALIGNMENT_NONE;
- UpdateDockedWidth(0);
- }
- if (last_active_window_ == child)
- last_active_window_ = NULL;
- child->RemoveObserver(this);
- wm::GetWindowState(child)->RemoveObserver(this);
- Relayout();
- UpdateDockBounds(DockedWindowLayoutManagerObserver::CHILD_CHANGED);
-}
-
-void DockedWindowLayoutManager::OnChildWindowVisibilityChanged(
- aura::Window* child,
- bool visible) {
- if (IsPopupOrTransient(child))
- return;
- if (visible)
- wm::GetWindowState(child)->Restore();
- Relayout();
- UpdateDockBounds(DockedWindowLayoutManagerObserver::CHILD_CHANGED);
-}
-
-void DockedWindowLayoutManager::SetChildBounds(
- aura::Window* child,
- const gfx::Rect& requested_bounds) {
- // Whenever one of our windows is moved or resized enforce layout.
- SetChildBoundsDirect(child, requested_bounds);
- if (IsPopupOrTransient(child))
- return;
- ShelfLayoutManager* shelf_layout = internal::ShelfLayoutManager::ForLauncher(
- dock_container_);
- if (shelf_layout)
- shelf_layout->UpdateVisibilityState();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// DockedWindowLayoutManager, ash::ShellObserver implementation:
-
-void DockedWindowLayoutManager::OnDisplayWorkAreaInsetsChanged() {
- Relayout();
- UpdateDockBounds(DockedWindowLayoutManagerObserver::DISPLAY_INSETS_CHANGED);
- MaybeMinimizeChildrenExcept(dragged_window_);
-}
-
-void DockedWindowLayoutManager::OnFullscreenStateChanged(
- bool is_fullscreen, aura::Window* root_window) {
- if (dock_container_->GetRootWindow() != root_window)
- return;
- // Entering fullscreen mode (including immersive) hides docked windows.
- in_fullscreen_ = workspace_controller_->GetWindowState() ==
- WORKSPACE_WINDOW_STATE_FULL_SCREEN;
- {
- // prevent Relayout from getting called multiple times during this
- base::AutoReset<bool> auto_reset_in_layout(&in_layout_, true);
- // Use a copy of children array because a call to MinimizeDockedWindow or
- // RestoreDockedWindow can change order.
- aura::Window::Windows children(dock_container_->children());
- for (aura::Window::Windows::const_iterator iter = children.begin();
- iter != children.end(); ++iter) {
- aura::Window* window(*iter);
- if (IsPopupOrTransient(window))
- continue;
- wm::WindowState* window_state = wm::GetWindowState(window);
- if (in_fullscreen_) {
- if (window->IsVisible())
- MinimizeDockedWindow(window_state);
- } else {
- if (!window_state->IsMinimized())
- RestoreDockedWindow(window_state);
- }
- }
- }
- Relayout();
- UpdateDockBounds(DockedWindowLayoutManagerObserver::CHILD_CHANGED);
-}
-
-void DockedWindowLayoutManager::OnShelfAlignmentChanged(
- aura::Window* root_window) {
- if (dock_container_->GetRootWindow() != root_window)
- return;
-
- if (!launcher_ || !launcher_->shelf_widget())
- return;
-
- if (alignment_ == DOCKED_ALIGNMENT_NONE)
- return;
-
- // 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_ == DOCKED_ALIGNMENT_LEFT &&
- shelf_alignment == SHELF_ALIGNMENT_LEFT) {
- alignment_ = DOCKED_ALIGNMENT_RIGHT;
- } else if (alignment_ == DOCKED_ALIGNMENT_RIGHT &&
- shelf_alignment == SHELF_ALIGNMENT_RIGHT) {
- alignment_ = DOCKED_ALIGNMENT_LEFT;
- }
- Relayout();
- UpdateDockBounds(DockedWindowLayoutManagerObserver::SHELF_ALIGNMENT_CHANGED);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// DockedWindowLayoutManager, ShelfLayoutManagerObserver implementation:
-void DockedWindowLayoutManager::OnBackgroundUpdated(
- ShelfBackgroundType background_type,
- BackgroundAnimatorChangeType change_type) {
- background_widget_->SetPaintsBackground(background_type, change_type);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// DockedWindowLayoutManager, WindowStateObserver implementation:
-
-void DockedWindowLayoutManager::OnWindowShowTypeChanged(
- wm::WindowState* window_state,
- wm::WindowShowType old_type) {
- aura::Window* window = window_state->window();
- if (IsPopupOrTransient(window))
- return;
- // The window property will still be set, but no actual change will occur
- // until OnFullscreenStateChange is called when exiting fullscreen.
- if (in_fullscreen_)
- return;
- if (window_state->IsMinimized()) {
- MinimizeDockedWindow(window_state);
- } else if (window_state->IsMaximizedOrFullscreen() ||
- window_state->IsSnapped()) {
- if (window != dragged_window_) {
- UndockWindow(window);
- RecordUmaAction(DOCKED_ACTION_MAXIMIZE, DOCKED_ACTION_SOURCE_UNKNOWN);
- }
- } else if (old_type == wm::SHOW_TYPE_MINIMIZED) {
- RestoreDockedWindow(window_state);
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// DockedWindowLayoutManager, WindowObserver implementation:
-
-void DockedWindowLayoutManager::OnWindowBoundsChanged(
- aura::Window* window,
- const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds) {
- // Only relayout if the dragged window would get docked.
- if (window == dragged_window_ && is_dragged_window_docked_)
- Relayout();
-}
-
-void DockedWindowLayoutManager::OnWindowVisibilityChanging(
- aura::Window* window, bool visible) {
- if (IsPopupOrTransient(window))
- return;
- int animation_type = views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT;
- if (visible) {
- animation_type = views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_DROP;
- views::corewm::SetWindowVisibilityAnimationDuration(
- window, base::TimeDelta::FromMilliseconds(kFadeDurationMs));
- } else if (wm::GetWindowState(window)->IsMinimized()) {
- animation_type = WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE;
- }
- views::corewm::SetWindowVisibilityAnimationType(window, animation_type);
-}
-
-void DockedWindowLayoutManager::OnWindowDestroying(aura::Window* window) {
- if (dragged_window_ == window) {
- FinishDragging(DOCKED_ACTION_NONE, DOCKED_ACTION_SOURCE_UNKNOWN);
- DCHECK(!dragged_window_);
- DCHECK (!is_dragged_window_docked_);
- }
- if (window == last_active_window_)
- last_active_window_ = NULL;
- RecordUmaAction(DOCKED_ACTION_CLOSE, DOCKED_ACTION_SOURCE_UNKNOWN);
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-// DockedWindowLayoutManager, aura::client::ActivationChangeObserver
-// implementation:
-
-void DockedWindowLayoutManager::OnWindowActivated(aura::Window* gained_active,
- aura::Window* lost_active) {
- if (gained_active && IsPopupOrTransient(gained_active))
- return;
- // Ignore if the window that is not managed by this was activated.
- aura::Window* ancestor = NULL;
- for (aura::Window* parent = gained_active;
- parent; parent = parent->parent()) {
- if (parent->parent() == dock_container_) {
- ancestor = parent;
- break;
- }
- }
- if (ancestor)
- UpdateStacking(ancestor);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// DockedWindowLayoutManager private implementation:
-
-void DockedWindowLayoutManager::MaybeMinimizeChildrenExcept(
- aura::Window* child) {
- // Minimize any windows that don't fit without overlap.
- const gfx::Rect work_area =
- Shell::GetScreen()->GetDisplayNearestWindow(dock_container_).work_area();
- int available_room = work_area.height() - kMinDockGap;
- if (child)
- available_room -= (GetWindowHeightCloseTo(child, 0) + kMinDockGap);
- // Use a copy of children array because a call to Minimize can change order.
- aura::Window::Windows children(dock_container_->children());
- aura::Window::Windows::const_reverse_iterator iter = children.rbegin();
- while (iter != children.rend()) {
- aura::Window* window(*iter++);
- if (window == child || !IsUsedByLayout(window))
- continue;
- int room_needed = GetWindowHeightCloseTo(window, 0) + kMinDockGap;
- if (available_room > room_needed) {
- available_room -= room_needed;
- } else {
- // Slow down minimizing animations. Lock duration so that it is not
- // overridden by other ScopedLayerAnimationSettings down the stack.
- ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
- settings.SetTransitionDuration(
- base::TimeDelta::FromMilliseconds(kMinimizeDurationMs));
- settings.LockTransitionDuration();
- wm::GetWindowState(window)->Minimize();
- }
- }
-}
-
-void DockedWindowLayoutManager::MinimizeDockedWindow(
- wm::WindowState* window_state) {
- DCHECK(!IsPopupOrTransient(window_state->window()));
- window_state->window()->Hide();
- if (window_state->IsActive())
- window_state->Deactivate();
- RecordUmaAction(DOCKED_ACTION_MINIMIZE, DOCKED_ACTION_SOURCE_UNKNOWN);
-}
-
-void DockedWindowLayoutManager::RestoreDockedWindow(
- wm::WindowState* window_state) {
- aura::Window* window = window_state->window();
- DCHECK(!IsPopupOrTransient(window));
- // Always place restored window at the bottom shuffling the other windows up.
- // TODO(varkha): add a separate container for docked windows to keep track
- // of ordering.
- gfx::Display display = Shell::GetScreen()->GetDisplayNearestWindow(
- dock_container_);
- const gfx::Rect work_area = display.work_area();
-
- // Evict the window if it can no longer be docked because of its height.
- if (!CanDockWindow(window, SNAP_NONE)) {
- UndockWindow(window);
- RecordUmaAction(DOCKED_ACTION_EVICT, DOCKED_ACTION_SOURCE_UNKNOWN);
- return;
- }
- gfx::Rect bounds(window->bounds());
- bounds.set_y(work_area.bottom());
- window->SetBounds(bounds);
- window->Show();
- MaybeMinimizeChildrenExcept(window);
- RecordUmaAction(DOCKED_ACTION_RESTORE, DOCKED_ACTION_SOURCE_UNKNOWN);
-}
-
-void DockedWindowLayoutManager::RecordUmaAction(DockedAction action,
- DockedActionSource source) {
- if (action == DOCKED_ACTION_NONE)
- return;
- UMA_HISTOGRAM_ENUMERATION("Ash.Dock.Action", action, DOCKED_ACTION_COUNT);
- UMA_HISTOGRAM_ENUMERATION("Ash.Dock.ActionSource", source,
- DOCKED_ACTION_SOURCE_COUNT);
- base::Time time_now = base::Time::Now();
- base::TimeDelta time_between_use = time_now - last_action_time_;
- UMA_HISTOGRAM_CUSTOM_COUNTS("Ash.Dock.TimeBetweenUse",
- time_between_use.InSeconds(),
- 1,
- base::TimeDelta::FromHours(10).InSeconds(),
- 100);
- last_action_time_ = time_now;
- int docked_all_count = 0;
- int docked_visible_count = 0;
- int docked_panels_count = 0;
- int large_windows_count = 0;
- for (size_t i = 0; i < dock_container_->children().size(); ++i) {
- const aura::Window* window(dock_container_->children()[i]);
- if (IsPopupOrTransient(window))
- continue;
- docked_all_count++;
- if (!IsUsedByLayout(window))
- continue;
- docked_visible_count++;
- if (window->type() == aura::client::WINDOW_TYPE_PANEL)
- docked_panels_count++;
- const wm::WindowState* window_state = wm::GetWindowState(window);
- if (window_state->HasRestoreBounds()) {
- const gfx::Rect restore_bounds = window_state->GetRestoreBoundsInScreen();
- if (restore_bounds.width() > kMaxDockWidth)
- large_windows_count++;
- }
- }
- UMA_HISTOGRAM_COUNTS_100("Ash.Dock.ItemsAll", docked_all_count);
- UMA_HISTOGRAM_COUNTS_100("Ash.Dock.ItemsLarge", large_windows_count);
- UMA_HISTOGRAM_COUNTS_100("Ash.Dock.ItemsPanels", docked_panels_count);
- UMA_HISTOGRAM_COUNTS_100("Ash.Dock.ItemsVisible", docked_visible_count);
-}
-
-void DockedWindowLayoutManager::UpdateDockedWidth(int width) {
- if (docked_width_ == width)
- return;
- docked_width_ = width;
- UMA_HISTOGRAM_COUNTS_10000("Ash.Dock.Width", docked_width_);
-}
-
-void DockedWindowLayoutManager::OnDraggedWindowDocked(aura::Window* window) {
- DCHECK(!is_dragged_window_docked_);
- is_dragged_window_docked_ = true;
-
- // If there are no other docked windows update alignment.
- if (!IsAnyWindowDocked())
- alignment_ = DOCKED_ALIGNMENT_NONE;
-}
-
-void DockedWindowLayoutManager::OnDraggedWindowUndocked() {
- // If this is the first window getting docked - update alignment.
- if (!IsAnyWindowDocked())
- alignment_ = GetAlignmentOfWindow(dragged_window_);
-
- DCHECK (is_dragged_window_docked_);
- is_dragged_window_docked_ = false;
-}
-
-bool DockedWindowLayoutManager::IsAnyWindowDocked() {
- return CalculateAlignment() != DOCKED_ALIGNMENT_NONE;
-}
-
-void DockedWindowLayoutManager::Relayout() {
- if (in_layout_)
- return;
- if (alignment_ == DOCKED_ALIGNMENT_NONE && !is_dragged_window_docked_)
- return;
- base::AutoReset<bool> auto_reset_in_layout(&in_layout_, true);
-
- gfx::Rect dock_bounds = dock_container_->GetBoundsInScreen();
- aura::Window* active_window = NULL;
- std::vector<WindowWithHeight> visible_windows;
- for (size_t i = 0; i < dock_container_->children().size(); ++i) {
- aura::Window* window(dock_container_->children()[i]);
-
- if (!IsUsedByLayout(window) || window == dragged_window_)
- continue;
-
- // If the shelf is currently hidden (full-screen mode), hide window until
- // full-screen mode is exited.
- if (in_fullscreen_) {
- // 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;
- }
- if (window->HasFocus() ||
- window->Contains(
- aura::client::GetFocusClient(window)->GetFocusedWindow())) {
- DCHECK(!active_window);
- active_window = window;
- }
- visible_windows.push_back(WindowWithHeight(window));
- }
- // Consider docked dragged_window_ when fanning out other child windows.
- if (is_dragged_window_docked_) {
- visible_windows.push_back(WindowWithHeight(dragged_window_));
- DCHECK(!active_window);
- active_window = dragged_window_;
- }
-
- // Position docked windows as well as the window being dragged.
- gfx::Rect work_area =
- Shell::GetScreen()->GetDisplayNearestWindow(dock_container_).work_area();
- if (shelf_observer_)
- work_area.Subtract(shelf_observer_->shelf_bounds_in_screen());
- int available_room = CalculateWindowHeightsAndRemainingRoom(work_area,
- &visible_windows);
- FanOutChildren(work_area,
- CalculateIdealWidth(visible_windows),
- available_room,
- &visible_windows);
-
- // After the first Relayout allow the windows to change their order easier
- // since we know they are docked.
- is_dragged_from_dock_ = true;
- UpdateStacking(active_window);
-}
-
-int DockedWindowLayoutManager::CalculateWindowHeightsAndRemainingRoom(
- const gfx::Rect work_area,
- std::vector<WindowWithHeight>* visible_windows) {
- int available_room = work_area.height() - kMinDockGap;
- int remaining_windows = visible_windows->size();
-
- // Sort windows by their minimum heights and calculate target heights.
- std::sort(visible_windows->begin(), visible_windows->end(),
- CompareMinimumHeight());
- // Distribute the free space among the docked windows. Since the windows are
- // sorted (tall windows first) we can now assume that any window which
- // required more space than the current window will have already been
- // accounted for previously in this loop, so we can safely give that window
- // its proportional share of the remaining space.
- for (std::vector<WindowWithHeight>::reverse_iterator iter =
- visible_windows->rbegin();
- iter != visible_windows->rend(); ++iter) {
- iter->height_ = GetWindowHeightCloseTo(
- iter->window(), available_room / remaining_windows - kMinDockGap);
- available_room -= (iter->height_ + kMinDockGap);
- remaining_windows--;
- }
- return available_room;
-}
-
-int DockedWindowLayoutManager::CalculateIdealWidth(
- const std::vector<WindowWithHeight>& visible_windows) {
- int smallest_max_width = kMaxDockWidth;
- int largest_min_width = kMinDockWidth;
- // Ideal width of the docked area is as close to kIdealWidth as possible
- // while still respecting the minimum and maximum width restrictions on the
- // individual docked windows as well as the width that was possibly set by a
- // user (which needs to be preserved when dragging and rearranging windows).
- for (std::vector<WindowWithHeight>::const_iterator iter =
- visible_windows.begin();
- iter != visible_windows.end(); ++iter) {
- const aura::Window* window = iter->window();
- int min_window_width = window->bounds().width();
- int max_window_width = min_window_width;
- if (!wm::GetWindowState(window)->bounds_changed_by_user()) {
- min_window_width = GetWindowWidthCloseTo(window, kMinDockWidth);
- max_window_width = GetWindowWidthCloseTo(window, kMaxDockWidth);
- }
- largest_min_width = std::max(largest_min_width, min_window_width);
- smallest_max_width = std::min(smallest_max_width, max_window_width);
- }
- int ideal_width = std::max(largest_min_width,
- std::min(smallest_max_width, kIdealWidth));
- // Restrict docked area width regardless of window restrictions.
- ideal_width = std::max(std::min(ideal_width, kMaxDockWidth), kMinDockWidth);
- return ideal_width;
-}
-
-void DockedWindowLayoutManager::FanOutChildren(
- const gfx::Rect& work_area,
- int ideal_docked_width,
- int available_room,
- std::vector<WindowWithHeight>* visible_windows) {
- gfx::Rect dock_bounds = dock_container_->GetBoundsInScreen();
-
- // Calculate initial vertical offset and the gap or overlap between windows.
- const int num_windows = visible_windows->size();
- const float delta = kMinDockGap + (float)available_room /
- ((available_room > 0 || num_windows <= 1) ?
- num_windows + 1 : num_windows - 1);
- float y_pos = work_area.y() + ((delta > 0) ? delta : kMinDockGap);
-
- // Docked area is shown only if there is at least one non-dragged visible
- // docked window.
- int new_width = ideal_docked_width;
- if (visible_windows->empty() ||
- (visible_windows->size() == 1 &&
- (*visible_windows)[0].window() == dragged_window_)) {
- new_width = 0;
- }
- UpdateDockedWidth(new_width);
- // Sort windows by their center positions and fan out overlapping
- // windows.
- std::sort(visible_windows->begin(), visible_windows->end(),
- CompareWindowPos(is_dragged_from_dock_ ? dragged_window_ : NULL,
- delta));
- for (std::vector<WindowWithHeight>::iterator iter = visible_windows->begin();
- iter != visible_windows->end(); ++iter) {
- aura::Window* window = iter->window();
- gfx::Rect bounds = ScreenAsh::ConvertRectToScreen(
- window->parent(), window->GetTargetBounds());
- // A window is extended or shrunk to be as close as possible to the ideal
- // docked area width. Windows that were resized by a user are kept at their
- // existing size.
- // This also enforces the min / max restrictions on the docked area width.
- bounds.set_width(GetWindowWidthCloseTo(
- window,
- wm::GetWindowState(window)->bounds_changed_by_user() ?
- bounds.width() : ideal_docked_width));
- DCHECK_LE(bounds.width(), ideal_docked_width);
-
- DockedAlignment alignment = alignment_;
- if (alignment == DOCKED_ALIGNMENT_NONE && window == dragged_window_) {
- alignment = GetAlignmentOfWindow(window);
- if (alignment == DOCKED_ALIGNMENT_NONE)
- bounds.set_size(gfx::Size());
- }
-
- // Fan out windows evenly distributing the overlap or remaining free space.
- bounds.set_height(iter->height_);
- bounds.set_y(std::max(work_area.y(),
- std::min(work_area.bottom() - bounds.height(),
- static_cast<int>(y_pos + 0.5))));
- y_pos += bounds.height() + delta;
-
- // All docked windows other than the one currently dragged remain stuck
- // to the screen edge (flush with the edge or centered in the dock area).
- switch (alignment) {
- case DOCKED_ALIGNMENT_LEFT:
- bounds.set_x(dock_bounds.x() +
- (ideal_docked_width - bounds.width()) / 2);
- break;
- case DOCKED_ALIGNMENT_RIGHT:
- bounds.set_x(dock_bounds.right() -
- (ideal_docked_width + bounds.width()) / 2);
- break;
- case DOCKED_ALIGNMENT_NONE:
- break;
- }
- if (window == dragged_window_) {
- dragged_bounds_ = bounds;
- continue;
- }
- // If the following asserts it is probably because not all the children
- // have been removed when dock was closed.
- DCHECK_NE(alignment_, DOCKED_ALIGNMENT_NONE);
- bounds = ScreenAsh::ConvertRectFromScreen(dock_container_, bounds);
- if (bounds != window->GetTargetBounds()) {
- ui::Layer* layer = window->layer();
- ui::ScopedLayerAnimationSettings slide_settings(layer->GetAnimator());
- slide_settings.SetPreemptionStrategy(
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
- slide_settings.SetTransitionDuration(
- base::TimeDelta::FromMilliseconds(kSlideDurationMs));
- SetChildBoundsDirect(window, bounds);
- }
- }
-}
-
-void DockedWindowLayoutManager::UpdateDockBounds(
- DockedWindowLayoutManagerObserver::Reason reason) {
- int dock_inset = docked_width_ + (docked_width_ > 0 ? kMinDockGap : 0);
- const gfx::Rect work_area =
- Shell::GetScreen()->GetDisplayNearestWindow(dock_container_).work_area();
- gfx::Rect bounds = gfx::Rect(
- alignment_ == DOCKED_ALIGNMENT_RIGHT && dock_inset > 0 ?
- dock_container_->bounds().right() - dock_inset:
- dock_container_->bounds().x(),
- dock_container_->bounds().y(),
- dock_inset,
- work_area.height());
- docked_bounds_ = bounds +
- dock_container_->GetBoundsInScreen().OffsetFromOrigin();
- FOR_EACH_OBSERVER(
- DockedWindowLayoutManagerObserver,
- observer_list_,
- OnDockBoundsChanging(bounds, reason));
- // Show or hide background for docked area.
- gfx::Rect background_bounds(docked_bounds_);
- if (shelf_observer_)
- background_bounds.Subtract(shelf_observer_->shelf_bounds_in_screen());
- background_widget_->SetBackgroundBounds(background_bounds, alignment_);
- if (docked_width_ > 0)
- background_widget_->Show();
- else
- background_widget_->Hide();
-}
-
-void DockedWindowLayoutManager::UpdateStacking(aura::Window* active_window) {
- if (!active_window) {
- if (!last_active_window_)
- return;
- active_window = last_active_window_;
- }
-
- // Windows are stacked like a deck of cards:
- // ,------.
- // |,------.|
- // |,------.|
- // | active |
- // | window |
- // |`------'|
- // |`------'|
- // `------'
- // Use the middle of each window to figure out how to stack the window.
- // This allows us to update the stacking when a window is being dragged around
- // by the titlebar.
- std::map<int, aura::Window*> window_ordering;
- for (aura::Window::Windows::const_iterator it =
- dock_container_->children().begin();
- it != dock_container_->children().end(); ++it) {
- if (!IsUsedByLayout(*it) ||
- ((*it) == dragged_window_ && !is_dragged_window_docked_)) {
- continue;
- }
- gfx::Rect bounds = (*it)->bounds();
- window_ordering.insert(std::make_pair(bounds.y() + bounds.height() / 2,
- *it));
- }
- int active_center_y = active_window->bounds().CenterPoint().y();
-
- aura::Window* previous_window = NULL;
- for (std::map<int, aura::Window*>::const_iterator it =
- window_ordering.begin();
- it != window_ordering.end() && it->first < active_center_y; ++it) {
- if (previous_window)
- dock_container_->StackChildAbove(it->second, previous_window);
- previous_window = it->second;
- }
- for (std::map<int, aura::Window*>::const_reverse_iterator it =
- window_ordering.rbegin();
- it != window_ordering.rend() && it->first > active_center_y; ++it) {
- if (previous_window)
- dock_container_->StackChildAbove(it->second, previous_window);
- previous_window = it->second;
- }
-
- if (previous_window && active_window->parent() == dock_container_)
- dock_container_->StackChildAbove(active_window, previous_window);
- if (active_window != dragged_window_)
- last_active_window_ = active_window;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// keyboard::KeyboardControllerObserver implementation:
-
-void DockedWindowLayoutManager::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.
- Relayout();
- UpdateDockBounds(DockedWindowLayoutManagerObserver::KEYBOARD_BOUNDS_CHANGING);
-}
-
-} // namespace internal
-} // namespace ash