summaryrefslogtreecommitdiff
path: root/chromium/ash/wm
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ash/wm')
-rw-r--r--chromium/ash/wm/boot_splash_screen.cc (renamed from chromium/ash/wm/boot_splash_screen_chromeos.cc)9
-rw-r--r--chromium/ash/wm/boot_splash_screen.h (renamed from chromium/ash/wm/boot_splash_screen_chromeos.h)8
-rw-r--r--chromium/ash/wm/dock/docked_window_layout_manager.cc350
-rw-r--r--chromium/ash/wm/dock/docked_window_layout_manager.h57
-rw-r--r--chromium/ash/wm/dock/docked_window_layout_manager_unittest.cc91
-rw-r--r--chromium/ash/wm/dock/docked_window_resizer.cc220
-rw-r--r--chromium/ash/wm/dock/docked_window_resizer.h25
-rw-r--r--chromium/ash/wm/dock/docked_window_resizer_unittest.cc56
-rw-r--r--chromium/ash/wm/event_client_impl.cc43
-rw-r--r--chromium/ash/wm/frame_painter.h2
-rw-r--r--chromium/ash/wm/frame_painter_unittest.cc58
-rw-r--r--chromium/ash/wm/panels/panel_layout_manager_unittest.cc2
-rw-r--r--chromium/ash/wm/status_area_layout_manager.cc2
-rw-r--r--chromium/ash/wm/window_animations.cc3
-rw-r--r--chromium/ash/wm/window_resizer.cc23
-rw-r--r--chromium/ash/wm/window_selector.cc8
-rw-r--r--chromium/ash/wm/window_selector.h2
-rw-r--r--chromium/ash/wm/window_util.cc22
-rw-r--r--chromium/ash/wm/window_util.h12
-rw-r--r--chromium/ash/wm/workspace/phantom_window_controller.cc92
-rw-r--r--chromium/ash/wm/workspace/phantom_window_controller.h41
-rw-r--r--chromium/ash/wm/workspace/workspace_layout_manager.cc34
-rw-r--r--chromium/ash/wm/workspace/workspace_layout_manager_unittest.cc9
-rw-r--r--chromium/ash/wm/workspace/workspace_window_resizer.cc26
-rw-r--r--chromium/ash/wm/workspace/workspace_window_resizer.h5
-rw-r--r--chromium/ash/wm/workspace/workspace_window_resizer_unittest.cc173
-rw-r--r--chromium/ash/wm/workspace_controller.cc2
-rw-r--r--chromium/ash/wm/workspace_controller_unittest.cc8
28 files changed, 472 insertions, 911 deletions
diff --git a/chromium/ash/wm/boot_splash_screen_chromeos.cc b/chromium/ash/wm/boot_splash_screen.cc
index 00743409ae5..202ebe28eeb 100644
--- a/chromium/ash/wm/boot_splash_screen_chromeos.cc
+++ b/chromium/ash/wm/boot_splash_screen.cc
@@ -1,12 +1,11 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// 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/boot_splash_screen_chromeos.h"
+#include "ash/wm/boot_splash_screen.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/aura/root_window.h"
-#include "ui/base/x/x11_util.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_type.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
@@ -34,9 +33,9 @@ class BootSplashScreen::CopyHostContentLayerDelegate
// TODO(derat): Instead of copying the data, use GLX_EXT_texture_from_pixmap
// to create a zero-copy texture (when possible):
// https://codereview.chromium.org/10543125
- ui::CopyAreaToCanvas(root_window_->GetAcceleratedWidget(),
+ root_window_->CopyAreaToSkCanvas(
gfx::Rect(root_window_->GetHostOrigin(), root_window_->GetHostSize()),
- gfx::Point(), canvas);
+ gfx::Point(), canvas->sk_canvas());
}
virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {}
diff --git a/chromium/ash/wm/boot_splash_screen_chromeos.h b/chromium/ash/wm/boot_splash_screen.h
index e844275ad5f..f56f49fe195 100644
--- a/chromium/ash/wm/boot_splash_screen_chromeos.h
+++ b/chromium/ash/wm/boot_splash_screen.h
@@ -1,9 +1,9 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// 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.
-#ifndef ASH_WM_BOOT_SPLASH_SCREEN_CHROMEOS_H_
-#define ASH_WM_BOOT_SPLASH_SCREEN_CHROMEOS_H_
+#ifndef ASH_WM_BOOT_SPLASH_SCREEN_H_
+#define ASH_WM_BOOT_SPLASH_SCREEN_H_
#include <string>
@@ -50,4 +50,4 @@ class BootSplashScreen {
} // namespace internal
} // namespace ash
-#endif // ASH_WM_BOOT_SPLASH_SCREEN_CHROMEOS_H_
+#endif // ASH_WM_BOOT_SPLASH_SCREEN_H_
diff --git a/chromium/ash/wm/dock/docked_window_layout_manager.cc b/chromium/ash/wm/dock/docked_window_layout_manager.cc
index 1dacf5e9fbd..d73a0ccac7d 100644
--- a/chromium/ash/wm/dock/docked_window_layout_manager.cc
+++ b/chromium/ash/wm/dock/docked_window_layout_manager.cc
@@ -84,58 +84,10 @@ bool IsUsedByLayout(aura::Window* window) {
window->type() != aura::client::WINDOW_TYPE_POPUP);
}
-// 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()(const aura::Window* win1, const aura::Window* win2) {
- const gfx::Rect win1_bounds = win1->GetBoundsInScreen();
- const gfx::Rect win2_bounds = win2->GetBoundsInScreen();
- // 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_;
-};
+bool CompareWindowPos(const aura::Window* win1, const aura::Window* win2) {
+ return win1->GetTargetBounds().CenterPoint().y() <
+ win2->GetTargetBounds().CenterPoint().y();
+}
} // namespace
@@ -146,8 +98,6 @@ DockedWindowLayoutManager::DockedWindowLayoutManager(
: dock_container_(dock_container),
in_layout_(false),
dragged_window_(NULL),
- is_dragged_window_docked_(false),
- is_dragged_from_dock_(false),
launcher_(NULL),
shelf_layout_manager_(NULL),
shelf_hidden_(false),
@@ -189,79 +139,106 @@ void DockedWindowLayoutManager::RemoveObserver(
}
void DockedWindowLayoutManager::StartDragging(aura::Window* window) {
+ if (window->parent() != dock_container_)
+ return;
DCHECK(!dragged_window_);
dragged_window_ = 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);
- is_dragged_from_dock_ = window->parent() == dock_container_;
- DCHECK(!is_dragged_window_docked_);
-}
-
-void DockedWindowLayoutManager::DockDraggedWindow(aura::Window* window) {
- OnWindowDocked(window);
Relayout();
}
-void DockedWindowLayoutManager::UndockDraggedWindow() {
- OnWindowUndocked();
- Relayout();
- is_dragged_from_dock_ = false;
-}
-
void DockedWindowLayoutManager::FinishDragging() {
- DCHECK(dragged_window_);
- if (is_dragged_window_docked_)
- OnWindowUndocked();
- 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);
- dragged_window_ = NULL;
+ if (!dragged_window_)
+ return;
+
+ // If this is the first window getting docked - update alignment.
+ if (alignment_ == DOCKED_ALIGNMENT_NONE) {
+ alignment_ = AlignmentOfWindow(dragged_window_);
+ } else {
+ // There were some docked windows before. Check if the |dragged_window_|
+ // was the only one remaining and if so possibly switch alignment to
+ // opposite side. Ignore popups.
+ bool found_docked_window = false;
+ for (size_t i = 0; i < dock_container_->children().size(); ++i) {
+ aura::Window* window(dock_container_->children()[i]);
+ if (window != dragged_window_ &&
+ window->type() != aura::client::WINDOW_TYPE_POPUP) {
+ found_docked_window = true;
+ break;
+ }
+ }
+ if (!found_docked_window)
+ alignment_ = AlignmentOfWindow(dragged_window_);
+ }
+
+ // We no longer need to observe |dragged_window_| unless it is added back;
+ if (dragged_window_) {
+ if (dragged_window_->parent() != dock_container_)
+ dragged_window_->RemoveObserver(this);
+ dragged_window_ = NULL;
+ }
+
Relayout();
UpdateDockBounds();
}
-void DockedWindowLayoutManager::SetLauncher(ash::Launcher* launcher) {
- DCHECK(!launcher_);
- DCHECK(!shelf_layout_manager_);
- launcher_ = launcher;
- 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);
+// static
+bool DockedWindowLayoutManager::ShouldWindowDock(aura::Window* window,
+ const gfx::Point& location) {
+ DockedWindowLayoutManager* layout_manager = GetDockLayoutManager(window,
+ location);
+ const DockedAlignment alignment = layout_manager->CalculateAlignment();
+ const gfx::Rect& bounds(window->GetBoundsInScreen());
+ const gfx::Rect docked_bounds = (alignment == DOCKED_ALIGNMENT_NONE) ?
+ layout_manager->dock_container_->GetBoundsInScreen() :
+ layout_manager->docked_bounds_;
+ DockedAlignment dock_edge = DOCKED_ALIGNMENT_NONE;
+ if (alignment == DOCKED_ALIGNMENT_NONE) {
+ // Check if the window is touching the edge - it may need to get docked.
+ dock_edge = layout_manager->AlignmentOfWindow(window);
+ } else if ((docked_bounds.Intersects(bounds) &&
+ docked_bounds.Contains(location)) ||
+ alignment == layout_manager->AlignmentOfWindow(window)) {
+ // A window is being added to other docked windows (on the same side).
+ // Both bounds and pointer location are checked because some drags involve
+ // sticky edges and so the |location| may be outside of the |bounds|.
+ // It is also possible that all the docked windows are minimized or hidden
+ // in which case the dragged window needs to be exactly touching the same
+ // edge that those docked windows were aligned before they got minimized.
+ dock_edge = alignment;
}
-}
-DockedAlignment DockedWindowLayoutManager::GetAlignmentOfWindow(
- const aura::Window* window) const {
- const gfx::Rect& bounds(window->GetBoundsInScreen());
- const gfx::Rect docked_bounds = dock_container_->GetBoundsInScreen();
+ // Do not allow docking on the same side as launcher shelf.
+ if (layout_manager->launcher_ && layout_manager->launcher_->shelf_widget()) {
+ ShelfAlignment shelf_alignment =
+ layout_manager->launcher_->shelf_widget()->GetAlignment();
+ if ((shelf_alignment == SHELF_ALIGNMENT_LEFT &&
+ dock_edge == DOCKED_ALIGNMENT_LEFT) ||
+ (shelf_alignment == SHELF_ALIGNMENT_RIGHT &&
+ dock_edge == DOCKED_ALIGNMENT_RIGHT)) {
+ dock_edge = DOCKED_ALIGNMENT_NONE;
+ }
+ }
// Do not allow docking if a window is vertically maximized (as is the case
// when it is snapped).
const gfx::Rect work_area =
- Shell::GetScreen()->GetDisplayNearestWindow(dock_container_).work_area();
+ Shell::GetScreen()->GetDisplayNearestWindow(window).work_area();
if (bounds.y() == work_area.y() && bounds.height() == work_area.height())
- return DOCKED_ALIGNMENT_NONE;
+ dock_edge = DOCKED_ALIGNMENT_NONE;
- // Do not allow docking on the same side as launcher shelf.
- ShelfAlignment shelf_alignment = SHELF_ALIGNMENT_BOTTOM;
- if (launcher_)
- shelf_alignment = launcher_->alignment();
+ return dock_edge != DOCKED_ALIGNMENT_NONE;
+}
- if (bounds.x() == docked_bounds.x() &&
- shelf_alignment != SHELF_ALIGNMENT_LEFT) {
- return DOCKED_ALIGNMENT_LEFT;
- }
- if (bounds.right() == docked_bounds.right() &&
- shelf_alignment != SHELF_ALIGNMENT_RIGHT) {
- return DOCKED_ALIGNMENT_RIGHT;
+void DockedWindowLayoutManager::SetLauncher(ash::Launcher* launcher) {
+ DCHECK(!launcher_);
+ DCHECK(!shelf_layout_manager_);
+ launcher_ = launcher;
+ 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);
}
- return DOCKED_ALIGNMENT_NONE;
}
DockedAlignment DockedWindowLayoutManager::CalculateAlignment() const {
@@ -285,24 +262,22 @@ DockedAlignment DockedWindowLayoutManager::CalculateAlignment() const {
// DockLayoutManager, aura::LayoutManager implementation:
void DockedWindowLayoutManager::OnWindowResized() {
Relayout();
- // When screen resizes update the insets even when dock width or alignment
- // does not change.
+ // When screen resizes we need to update the insets even when dock width or
+ // alignment does not change.
UpdateDockBounds();
}
void DockedWindowLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
if (child->type() == aura::client::WINDOW_TYPE_POPUP)
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);
- }
- child->AddObserver(this);
+ if (alignment_ == DOCKED_ALIGNMENT_NONE)
+ alignment_ = AlignmentOfWindow(child);
+ // We need to observe a child unless it is a |dragged_window_| that just got
+ // added back in which case we are already observing it.
+ if (child != dragged_window_)
+ child->AddObserver(this);
Relayout();
UpdateDockBounds();
}
@@ -310,20 +285,36 @@ void DockedWindowLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
void DockedWindowLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) {
if (child->type() == aura::client::WINDOW_TYPE_POPUP)
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;
- docked_width_ = 0;
+
+ // Try to find a child that is not a popup and is not being dragged.
+ bool found_docked_window = false;
+ for (size_t i = 0; i < dock_container_->children().size(); ++i) {
+ aura::Window* window(dock_container_->children()[i]);
+ if (window != dragged_window_ &&
+ window->type() != aura::client::WINDOW_TYPE_POPUP) {
+ found_docked_window = true;
+ break;
+ }
}
+ if (!found_docked_window)
+ alignment_ = DOCKED_ALIGNMENT_NONE;
+
+ // Keep track of former children if they are dragged as they can be reparented
+ // temporarily just for the drag.
+ if (child != dragged_window_)
+ child->RemoveObserver(this);
+
if (last_active_window_ == child)
last_active_window_ = NULL;
- child->RemoveObserver(this);
+
+ // Close the dock and expand workspace work area.
Relayout();
+
+ // When a panel is removed from this layout manager it may still be dragged.
+ // Delay updating dock and workspace bounds until the drag is completed. This
+ // preserves the docked area width until the panel drag is finished.
+ if (child->type() != aura::client::WINDOW_TYPE_PANEL)
+ UpdateDockBounds();
}
void DockedWindowLayoutManager::OnChildWindowVisibilityChanged(
@@ -340,8 +331,11 @@ void DockedWindowLayoutManager::OnChildWindowVisibilityChanged(
void DockedWindowLayoutManager::SetChildBounds(
aura::Window* child,
const gfx::Rect& requested_bounds) {
- // Whenever one of our windows is moved or resized enforce layout.
+ // Whenever one of our windows is moved or resized we need to enforce layout.
SetChildBoundsDirect(child, requested_bounds);
+ if (child->type() == aura::client::WINDOW_TYPE_POPUP)
+ return;
+ Relayout();
}
////////////////////////////////////////////////////////////////////////////////
@@ -394,18 +388,13 @@ 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_)
+ if (window == dragged_window_)
Relayout();
}
void DockedWindowLayoutManager::OnWindowDestroying(aura::Window* window) {
if (dragged_window_ == window)
- FinishDragging();
- DCHECK(!dragged_window_);
- DCHECK (!is_dragged_window_docked_);
- if (window == last_active_window_)
- last_active_window_ = NULL;
+ dragged_window_ = NULL;
}
@@ -437,7 +426,7 @@ void DockedWindowLayoutManager::WillChangeVisibilityState(
// to allow the full-screen application to use the full screen.
// TODO(varkha): ShelfLayoutManager::UpdateVisibilityState sets state to
- // SHELF_AUTO_HIDE when in immersive mode. Distinguish this from
+ // SHELF_AUTO_HIDE when in immersive mode. We need to distinguish this from
// when shelf enters auto-hide state based on mouse hover when auto-hide
// setting is enabled and hide all windows (immersive mode should hide docked
// windows).
@@ -473,43 +462,30 @@ void DockedWindowLayoutManager::RestoreWindow(aura::Window* window) {
window->Show();
}
-void DockedWindowLayoutManager::OnWindowDocked(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::OnWindowUndocked() {
- // 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;
+DockedAlignment DockedWindowLayoutManager::AlignmentOfWindow(
+ const aura::Window* window) const {
+ const gfx::Rect& bounds(window->GetBoundsInScreen());
+ const gfx::Rect docked_bounds = dock_container_->GetBoundsInScreen();
+ if (bounds.x() == docked_bounds.x())
+ return DOCKED_ALIGNMENT_LEFT;
+ if (bounds.right() == docked_bounds.right())
+ return DOCKED_ALIGNMENT_RIGHT;
+ return DOCKED_ALIGNMENT_NONE;
}
void DockedWindowLayoutManager::Relayout() {
- if (in_layout_)
- return;
- if (alignment_ == DOCKED_ALIGNMENT_NONE && !is_dragged_window_docked_)
+ if (in_layout_ || alignment_ == DOCKED_ALIGNMENT_NONE)
return;
base::AutoReset<bool> auto_reset_in_layout(&in_layout_, true);
- gfx::Rect dock_bounds = dock_container_->GetBoundsInScreen();
+ gfx::Rect dock_bounds = dock_container_->bounds();
aura::Window* active_window = NULL;
aura::Window::Windows visible_windows;
docked_width_ = 0;
for (size_t i = 0; i < dock_container_->children().size(); ++i) {
aura::Window* window(dock_container_->children()[i]);
- if (!IsUsedByLayout(window) || window == dragged_window_)
+ if (!IsUsedByLayout(window))
continue;
// If the shelf is currently hidden (full-screen mode), hide window until
@@ -529,14 +505,14 @@ void DockedWindowLayoutManager::Relayout() {
visible_windows.push_back(window);
}
- // Consider docked dragged_window_ when fanning out other child windows.
- if (is_dragged_window_docked_) {
+ // Consider windows that were formerly children of the |dock_container_|
+ // when fanning out other child windows.
+ if (dragged_window_ && dragged_window_->parent() != dock_container_)
visible_windows.push_back(dragged_window_);
- DCHECK(!active_window);
- active_window = dragged_window_;
- }
- // Calculate free space or overlap.
+ // Sort windows by their center positions and fan out overlapping
+ // windows.
+ std::sort(visible_windows.begin(), visible_windows.end(), CompareWindowPos);
gfx::Display display = Shell::GetScreen()->GetDisplayNearestWindow(
dock_container_);
const gfx::Rect work_area = display.work_area();
@@ -549,19 +525,15 @@ void DockedWindowLayoutManager::Relayout() {
const float delta = (float)available_room /
((available_room > 0 || num_windows <= 1) ?
num_windows + 1 : num_windows - 1);
- float y_pos = work_area.y() + ((available_room > 0) ? delta : 0);
+ float y_pos = (available_room > 0) ? delta : 0;
- // 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));
- is_dragged_from_dock_ = true;
for (aura::Window::Windows::const_iterator iter = visible_windows.begin();
iter != visible_windows.end(); ++iter) {
aura::Window* window = *iter;
- gfx::Rect bounds = window->GetBoundsInScreen();
+ gfx::Rect bounds = window->GetTargetBounds();
+ // Do not force position of a single window.
+ if (num_windows == 1)
+ y_pos = bounds.y();
// Fan out windows evenly distributing the overlap or remaining free space.
bounds.set_y(std::max(work_area.y(),
@@ -571,27 +543,24 @@ void DockedWindowLayoutManager::Relayout() {
// All docked windows other than the one currently dragged remain stuck
// to the screen edge.
+ if (window == dragged_window_)
+ continue;
switch (alignment_) {
case DOCKED_ALIGNMENT_LEFT:
- bounds.set_x(dock_bounds.x());
+ bounds.set_x(0);
break;
case DOCKED_ALIGNMENT_RIGHT:
bounds.set_x(dock_bounds.right() - bounds.width());
break;
case DOCKED_ALIGNMENT_NONE:
+ NOTREACHED() << "Relayout called when dock alignment is 'NONE'";
break;
}
- if (window == dragged_window_) {
- dragged_bounds_ = bounds;
- continue;
- }
- DCHECK_NE(alignment_, DOCKED_ALIGNMENT_NONE);
// Keep the dock at least kMinDockWidth when all windows in it overhang.
docked_width_ = std::min(kMaxDockWidth,
std::max(docked_width_,
bounds.width() > kMaxDockWidth ?
kMinDockWidth : bounds.width()));
- bounds = ScreenAsh::ConvertRectFromScreen(dock_container_, bounds);
SetChildBoundsDirect(window, bounds);
}
UpdateStacking(active_window);
@@ -600,7 +569,7 @@ void DockedWindowLayoutManager::Relayout() {
void DockedWindowLayoutManager::UpdateDockBounds() {
int dock_inset = docked_width_ + (docked_width_ > 0 ? kMinDockGap : 0);
gfx::Rect bounds = gfx::Rect(
- alignment_ == DOCKED_ALIGNMENT_RIGHT && dock_inset > 0 ?
+ alignment_ == DOCKED_ALIGNMENT_RIGHT ?
dock_container_->bounds().right() - dock_inset:
dock_container_->bounds().x(),
dock_container_->bounds().y(),
@@ -632,7 +601,7 @@ void DockedWindowLayoutManager::UpdateStacking(aura::Window* active_window) {
active_window = last_active_window_;
}
- // Windows are stacked like a deck of cards:
+ // We want to to stack the windows like a deck of cards:
// ,------.
// |,------.|
// |,------.|
@@ -641,7 +610,7 @@ void DockedWindowLayoutManager::UpdateStacking(aura::Window* active_window) {
// |`------'|
// |`------'|
// `------'
- // Use the middle of each window to figure out how to stack the window.
+ // We 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;
@@ -656,7 +625,7 @@ void DockedWindowLayoutManager::UpdateStacking(aura::Window* active_window) {
}
int active_center_y = active_window->bounds().CenterPoint().y();
- aura::Window* previous_window = NULL;
+ aura::Window* previous_window = background_widget_->GetNativeWindow();
for (std::map<int, aura::Window*>::const_iterator it =
window_ordering.begin();
it != window_ordering.end() && it->first < active_center_y; ++it) {
@@ -676,8 +645,9 @@ void DockedWindowLayoutManager::UpdateStacking(aura::Window* active_window) {
if (active_window->parent() == dock_container_)
dock_container_->StackChildAtTop(active_window);
- if (active_window != dragged_window_)
- last_active_window_ = active_window;
+ if (dragged_window_ && dragged_window_->parent() == dock_container_)
+ dock_container_->StackChildAtTop(dragged_window_);
+ last_active_window_ = active_window;
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/ash/wm/dock/docked_window_layout_manager.h b/chromium/ash/wm/dock/docked_window_layout_manager.h
index a3019aa7175..aa02b343423 100644
--- a/chromium/ash/wm/dock/docked_window_layout_manager.h
+++ b/chromium/ash/wm/dock/docked_window_layout_manager.h
@@ -50,9 +50,7 @@ class ShelfLayoutManager;
// its layout manager to this instance, e.g.:
// dock_container->SetLayoutManager(
// new DockedWindowLayoutManager(dock_container));
-//
-// TODO(varkha): extend BaseLayoutManager instead of LayoutManager to inherit
-// common functionality.
+
class ASH_EXPORT DockedWindowLayoutManager
: public aura::LayoutManager,
public ash::ShellObserver,
@@ -72,35 +70,26 @@ class ASH_EXPORT DockedWindowLayoutManager
virtual void RemoveObserver(DockedWindowLayoutManagerObserver* observer);
// Called by a DockedWindowResizer to update which window is being dragged.
- // Starts observing the window unless it is a child.
void StartDragging(aura::Window* window);
-
- // Called by a DockedWindowResizer when a dragged window is docked.
- void DockDraggedWindow(aura::Window* window);
-
- // Called by a DockedWindowResizer when a dragged window is no longer docked.
- void UndockDraggedWindow();
-
- // Called by a DockedWindowResizer when a window is no longer being dragged.
- // Stops observing the window unless it is a child.
void FinishDragging();
+ // Returns true if a window is touching the side of the screen except 2 cases:
+ // when some other windows are already docked on the other side or
+ // when launcher (shelf) is aligned on the same side.
+ static bool ShouldWindowDock(aura::Window* window,
+ const gfx::Point& location);
+
ash::Launcher* launcher() { return launcher_; }
void SetLauncher(ash::Launcher* launcher);
- // Calculates if a window is touching the screen edges and returns edge.
- DockedAlignment GetAlignmentOfWindow(const aura::Window* window) const;
-
// Used to snap docked windows to the side of screen during drag.
DockedAlignment CalculateAlignment() const;
- aura::Window* dock_container() const { return dock_container_; }
-
// Returns current bounding rectangle of docked windows area.
const gfx::Rect& docked_bounds() const { return docked_bounds_; }
- // Returns last known coordinates of |dragged_window_| after Relayout.
- const gfx::Rect dragged_bounds() const { return dragged_bounds_;}
+ // Currently dragged window should be able to dock on another screen
+ aura::Window* dragged_window() const { return dragged_window_;}
// aura::LayoutManager:
virtual void OnWindowResized() OVERRIDE;
@@ -154,14 +143,8 @@ class ASH_EXPORT DockedWindowLayoutManager
void MinimizeWindow(aura::Window* window);
void RestoreWindow(aura::Window* window);
- // Updates docked layout state when a window gets inside the dock.
- void OnWindowDocked(aura::Window* window);
-
- // Updates docked layout state when a window gets outside the dock.
- void OnWindowUndocked();
-
- // Returns true if there are any windows currently docked.
- bool IsAnyWindowDocked();
+ // Calculates if a window is touching the screen edges and returns edge.
+ DockedAlignment AlignmentOfWindow(const aura::Window* window) const;
// Called whenever the window layout might change.
void Relayout();
@@ -182,21 +165,8 @@ class ASH_EXPORT DockedWindowLayoutManager
aura::Window* dock_container_;
// Protect against recursive calls to Relayout().
bool in_layout_;
-
- // A window that is being dragged (whether docked or not).
- // Windows are tracked by docked layout manager only if they are docked;
- // however we need to know if a window is being dragged in order to avoid
- // positioning it or even considering it for layout.
+ // The docked window being dragged.
aura::Window* dragged_window_;
-
- // True if the window being dragged is currently docked.
- bool is_dragged_window_docked_;
-
- // Previously docked windows use a more relaxed dragging sorting algorithm
- // that uses assumption that a window starts being dragged out of position
- // that was previously established in Relayout. This allows easier reordering.
- bool is_dragged_from_dock_;
-
// The launcher we are observing for launcher icon changes.
Launcher* launcher_;
// The shelf layout manager being observed for visibility changes.
@@ -210,9 +180,6 @@ class ASH_EXPORT DockedWindowLayoutManager
// Last bounds that were sent to observers.
gfx::Rect docked_bounds_;
- // Target bounds of a docked window being dragged.
- gfx::Rect dragged_bounds_;
-
// Side of the screen that the dock is positioned at.
DockedAlignment alignment_;
diff --git a/chromium/ash/wm/dock/docked_window_layout_manager_unittest.cc b/chromium/ash/wm/dock/docked_window_layout_manager_unittest.cc
index b2f6ffd9cf4..cf7b476f26a 100644
--- a/chromium/ash/wm/dock/docked_window_layout_manager_unittest.cc
+++ b/chromium/ash/wm/dock/docked_window_layout_manager_unittest.cc
@@ -5,7 +5,6 @@
#include "ash/wm/dock/docked_window_layout_manager.h"
#include "ash/ash_switches.h"
-#include "ash/display/display_controller.h"
#include "ash/launcher/launcher.h"
#include "ash/launcher/launcher_model.h"
#include "ash/root_window_controller.h"
@@ -28,7 +27,6 @@
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
#include "ui/base/hit_test.h"
-#include "ui/gfx/screen.h"
#include "ui/views/widget/widget.h"
namespace ash {
@@ -62,6 +60,11 @@ class DockedWindowLayoutManagerTest
DOCKED_EDGE_RIGHT,
};
+ enum DockedState {
+ UNDOCKED,
+ DOCKED,
+ };
+
aura::Window* CreateTestWindow(const gfx::Rect& bounds) {
aura::Window* window = CreateTestWindowInShellWithDelegateAndType(
NULL,
@@ -133,10 +136,12 @@ class DockedWindowLayoutManagerTest
// Docked windows are parented by dock container during drags.
// All other windows that we are testing here have default container as a
// parent.
- int CorrectContainerIdDuringDrag() {
+ int CorrectContainerIdDuringDrag(DockedState is_docked) {
if (window_type_ == aura::client::WINDOW_TYPE_PANEL)
return internal::kShellWindowId_PanelContainer;
- return internal::kShellWindowId_DockedContainer;
+ if (is_docked == DOCKED)
+ return internal::kShellWindowId_DockedContainer;
+ return internal::kShellWindowId_DefaultContainer;
}
// Test dragging the window vertically (to detach if it is a panel) and then
@@ -181,7 +186,7 @@ class DockedWindowLayoutManagerTest
// Drag enough to detach since our tests assume panels to be initially
// detached.
DragMove(0, dy);
- EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id());
+ EXPECT_EQ(CorrectContainerIdDuringDrag(UNDOCKED), window->parent()->id());
EXPECT_EQ(initial_bounds.x(), window->GetBoundsInScreen().x());
EXPECT_EQ(initial_bounds.y() + dy, window->GetBoundsInScreen().y());
@@ -203,7 +208,7 @@ class DockedWindowLayoutManagerTest
else if (edge == DOCKED_EDGE_RIGHT)
dx += window->GetRootWindow()->bounds().right() - initial_bounds.right();
DragMove(dx, window_type_ == aura::client::WINDOW_TYPE_PANEL ? 0 : dy);
- EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id());
+ EXPECT_EQ(CorrectContainerIdDuringDrag(UNDOCKED), window->parent()->id());
// Release the mouse and the panel should be attached to the dock.
DragEnd();
@@ -309,7 +314,7 @@ TEST_P(DockedWindowLayoutManagerTest, ThreeWindowsDragging) {
scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 202)));
- DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 200);
+ DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 100);
scoped_ptr<aura::Window> w3(CreateTestWindow(gfx::Rect(0, 0, 220, 204)));
DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w3.get(), 300);
@@ -336,10 +341,9 @@ TEST_P(DockedWindowLayoutManagerTest, ThreeWindowsDragging) {
EXPECT_LE(abs(overlap2 - overlap3), 1);
EXPECT_EQ(0, overlap4);
- // Drag w1 below the point where w1 and w2 would swap places. This point is
- // half way between the tops of those two windows. Add 1 because w2 is taller.
+ // Drag w1 below w2.
ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(w1.get(), 0, 20));
- DragMove(0, (w2->bounds().y() - w1->bounds().y()) / 2 + 1);
+ DragMove(0, w2->bounds().y() - w1->bounds().y() + 20);
// During the drag the windows get rearranged and the top and the bottom
// should be clamped by the work area.
@@ -360,73 +364,6 @@ TEST_P(DockedWindowLayoutManagerTest, ThreeWindowsDragging) {
EXPECT_EQ(0, overlap4);
}
-// Adds three windows in bottom display and tests layout after a drag.
-TEST_P(DockedWindowLayoutManagerTest, ThreeWindowsDraggingSecondScreen) {
- if (!SupportsMultipleDisplays())
- return;
- if (!SupportsHostWindowResize())
- return;
-
- // Create two screen vertical layout.
- UpdateDisplay("100+100-600x600,100+700-600x600");
- // Layout the secondary display to the bottom of the primary.
- DisplayLayout layout(DisplayLayout::BOTTOM, 0);
- ASSERT_GT(Shell::GetScreen()->GetNumDisplays(), 1);
- Shell::GetInstance()->display_controller()->
- SetLayoutForCurrentDisplays(layout);
-
- scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 600, 201, 201)));
- DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 600 + 20);
- scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 600, 210, 202)));
- DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 600 + 200);
- scoped_ptr<aura::Window> w3(CreateTestWindow(gfx::Rect(0, 600, 220, 204)));
- DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w3.get(), 600 + 300);
-
- // All windows should be attached and snapped to the right side of the screen.
- EXPECT_EQ(w1->GetRootWindow()->bounds().right(),
- w1->GetBoundsInScreen().right());
- EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
- EXPECT_EQ(w2->GetRootWindow()->bounds().right(),
- w2->GetBoundsInScreen().right());
- EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
- EXPECT_EQ(w3->GetRootWindow()->bounds().right(),
- w3->GetBoundsInScreen().right());
- EXPECT_EQ(internal::kShellWindowId_DockedContainer, w3->parent()->id());
-
- gfx::Rect work_area =
- Shell::GetScreen()->GetDisplayNearestWindow(w1.get()).work_area();
- // Test that the top and bottom windows are clamped in work area and
- // that the overlaps between the windows differ at most by a pixel.
- int overlap1 = w1->GetBoundsInScreen().y() - work_area.y();
- int overlap2 = w1->GetBoundsInScreen().bottom() - w2->GetBoundsInScreen().y();
- int overlap3 = w2->GetBoundsInScreen().bottom() - w3->GetBoundsInScreen().y();
- int overlap4 = work_area.bottom() - w3->GetBoundsInScreen().bottom();
- EXPECT_EQ(0, overlap1);
- EXPECT_LE(abs(overlap2 - overlap3), 1);
- EXPECT_EQ(0, overlap4);
-
- // Drag w1 below the point where w1 and w2 would swap places. This point is
- // half way between the tops of those two windows. Add 1 because w2 is taller.
- ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(w1.get(), 0, 20));
- DragMove(0, (w2->bounds().y() - w1->bounds().y()) / 2 + 1);
-
- // During the drag the windows get rearranged and the top and the bottom
- // should be clamped by the work area.
- EXPECT_EQ(work_area.y(), w2->GetBoundsInScreen().y());
- EXPECT_GT(w1->GetBoundsInScreen().y(), w2->GetBoundsInScreen().y());
- EXPECT_EQ(work_area.bottom(), w3->GetBoundsInScreen().bottom());
- DragEnd();
-
- // Test the new windows order and that the overlaps differ at most by a pixel.
- overlap1 = w2->GetBoundsInScreen().y() - work_area.y();
- overlap2 = w2->GetBoundsInScreen().bottom() - w1->GetBoundsInScreen().y();
- overlap3 = w1->GetBoundsInScreen().bottom() - w3->GetBoundsInScreen().y();
- overlap4 = work_area.bottom() - w3->GetBoundsInScreen().bottom();
- EXPECT_EQ(0, overlap1);
- EXPECT_LE(abs(overlap2 - overlap3), 1);
- EXPECT_EQ(0, overlap4);
-}
-
// Tests run twice - on both panels and normal windows
INSTANTIATE_TEST_CASE_P(NormalOrPanel,
DockedWindowLayoutManagerTest,
diff --git a/chromium/ash/wm/dock/docked_window_resizer.cc b/chromium/ash/wm/dock/docked_window_resizer.cc
index 3e1ef29b0ad..beae1d13a18 100644
--- a/chromium/ash/wm/dock/docked_window_resizer.cc
+++ b/chromium/ash/wm/dock/docked_window_resizer.cc
@@ -16,9 +16,7 @@
#include "ash/wm/dock/docked_window_layout_manager.h"
#include "ash/wm/property_util.h"
#include "ash/wm/window_properties.h"
-#include "ash/wm/workspace/magnetism_matcher.h"
-#include "ash/wm/workspace/phantom_window_controller.h"
-#include "ash/wm/workspace/workspace_window_resizer.h"
+#include "ash/wm/workspace_controller.h"
#include "base/command_line.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/env.h"
@@ -31,18 +29,15 @@
#include "ui/views/widget/widget.h"
namespace ash {
-namespace internal {
namespace {
-DockedWindowLayoutManager* GetDockedLayoutManagerAtPoint(
- const gfx::Point& point) {
- aura::Window* dock_container = Shell::GetContainer(
- wm::GetRootWindowAt(point),
- kShellWindowId_DockedContainer);
- return static_cast<DockedWindowLayoutManager*>(
- dock_container->layout_manager());
-}
+// Distance in pixels that the cursor must move past an edge for a window
+// to move beyond that edge.
+const int kStickyDistance = 64;
+
+// How far in pixels we have to drag to undock a window.
+const int kSnapToDockDistance = 32;
} // namespace
@@ -94,78 +89,37 @@ void DockedWindowResizer::Drag(const gfx::Point& location, int event_flags) {
destroyed_ = NULL;
if (set_tracked_by_workspace)
SetTrackedByWorkspace(GetTarget(), tracked_by_workspace);
-
- DockedWindowLayoutManager* new_dock_layout =
- GetDockedLayoutManagerAtPoint(last_location_);
- if (new_dock_layout != dock_layout_) {
- // The window is being dragged to a new display. If the previous
- // container is the current parent of the window it will be informed of
- // the end of drag when the window is reparented, otherwise let the
- // previous container know the drag is complete. If we told the
- // window's parent that the drag was complete it would begin
- // positioning the window.
- if (is_docked_)
- dock_layout_->UndockDraggedWindow();
- if (dock_layout_ != initial_dock_layout_)
- dock_layout_->FinishDragging();
- is_docked_ = false;
- dock_layout_ = new_dock_layout;
- // The window's initial layout manager already knows that the drag is
- // in progress for this window.
- if (new_dock_layout != initial_dock_layout_)
- new_dock_layout->StartDragging(GetTarget());
- }
-
- // Show snapping animation when a window touches a screen edge or when
- // it is about to get docked.
- DockedAlignment new_docked_alignment = GetDraggedWindowAlignment();
- if (new_docked_alignment != DOCKED_ALIGNMENT_NONE) {
- if (!is_docked_) {
- dock_layout_->DockDraggedWindow(GetTarget());
- is_docked_ = true;
- }
- UpdateSnapPhantomWindow();
- } else {
- if (is_docked_) {
- dock_layout_->UndockDraggedWindow();
- is_docked_ = false;
- }
- // Clear phantom window when a window gets undocked.
- snap_phantom_window_controller_.reset();
- }
}
void DockedWindowResizer::CompleteDrag(int event_flags) {
- snap_phantom_window_controller_.reset();
-
// Temporarily clear kWindowTrackedByWorkspaceKey for panels so that they
// don't get forced into the workspace that may be shrunken because of docked
// windows.
bool tracked_by_workspace = GetTrackedByWorkspace(GetTarget());
- bool set_tracked_by_workspace = was_docked_;
+ bool set_tracked_by_workspace =
+ (was_docked_ && GetTarget()->type() == aura::client::WINDOW_TYPE_PANEL);
if (set_tracked_by_workspace)
SetTrackedByWorkspace(GetTarget(), false);
// The root window can change when dragging into a different screen.
next_window_resizer_->CompleteDrag(event_flags);
- FinishedDragging();
if (set_tracked_by_workspace)
SetTrackedByWorkspace(GetTarget(), tracked_by_workspace);
+ FinishDragging();
}
void DockedWindowResizer::RevertDrag() {
- snap_phantom_window_controller_.reset();
-
// Temporarily clear kWindowTrackedByWorkspaceKey for panels so that they
// don't get forced into the workspace that may be shrunken because of docked
// windows.
bool tracked_by_workspace = GetTrackedByWorkspace(GetTarget());
- bool set_tracked_by_workspace = was_docked_;
+ bool set_tracked_by_workspace =
+ (was_docked_ && GetTarget()->type() == aura::client::WINDOW_TYPE_PANEL);
if (set_tracked_by_workspace)
SetTrackedByWorkspace(GetTarget(), false);
next_window_resizer_->RevertDrag();
- FinishedDragging();
if (set_tracked_by_workspace)
SetTrackedByWorkspace(GetTarget(), tracked_by_workspace);
+ FinishDragging();
}
aura::Window* DockedWindowResizer::GetTarget() {
@@ -181,57 +135,29 @@ DockedWindowResizer::DockedWindowResizer(WindowResizer* next_window_resizer,
: details_(details),
next_window_resizer_(next_window_resizer),
dock_layout_(NULL),
- initial_dock_layout_(NULL),
did_move_or_resize_(false),
was_docked_(false),
- is_docked_(false),
destroyed_(NULL) {
DCHECK(details_.is_resizable);
aura::Window* dock_container = Shell::GetContainer(
details.window->GetRootWindow(),
- kShellWindowId_DockedContainer);
- dock_layout_ = static_cast<DockedWindowLayoutManager*>(
+ internal::kShellWindowId_DockedContainer);
+ DCHECK(dock_container->id() == internal::kShellWindowId_DockedContainer);
+ dock_layout_ = static_cast<internal::DockedWindowLayoutManager*>(
dock_container->layout_manager());
- initial_dock_layout_ = dock_layout_;
was_docked_ = details.window->parent() == dock_container;
- is_docked_ = was_docked_;
-}
-
-DockedAlignment DockedWindowResizer::GetDraggedWindowAlignment() {
- aura::Window* window = GetTarget();
- DockedWindowLayoutManager* layout_manager =
- GetDockedLayoutManagerAtPoint(last_location_);
- const DockedAlignment alignment = layout_manager->CalculateAlignment();
- const gfx::Rect& bounds(window->GetBoundsInScreen());
-
- // Check if the window is touching the edge - it may need to get docked.
- if (alignment == DOCKED_ALIGNMENT_NONE)
- return layout_manager->GetAlignmentOfWindow(window);
-
- // Both bounds and pointer location are checked because some drags involve
- // stickiness at the workspace-to-dock boundary and so the |location| may be
- // outside of the |bounds|.
- // It is also possible that all the docked windows are minimized or hidden
- // in which case the dragged window needs to be exactly touching the same
- // edge that those docked windows were aligned before they got minimized.
- // TODO(varkha): Consider eliminating sticky behavior on that boundary when
- // a pointer enters docked area.
- if ((layout_manager->docked_bounds().Intersects(bounds) &&
- layout_manager->docked_bounds().Contains(last_location_)) ||
- alignment == layout_manager->GetAlignmentOfWindow(window)) {
- // A window is being added to other docked windows (on the same side).
- return alignment;
- }
- return DOCKED_ALIGNMENT_NONE;
}
bool DockedWindowResizer::MaybeSnapToEdge(const gfx::Rect& bounds,
gfx::Point* offset) {
aura::Window* dock_container = Shell::GetContainer(
wm::GetRootWindowAt(last_location_),
- kShellWindowId_DockedContainer);
- DockedAlignment dock_alignment =
- GetDockedLayoutManagerAtPoint(last_location_)->CalculateAlignment();
+ internal::kShellWindowId_DockedContainer);
+ DCHECK(dock_container->id() == internal::kShellWindowId_DockedContainer);
+ internal::DockedWindowLayoutManager* dock_layout =
+ static_cast<internal::DockedWindowLayoutManager*>(
+ dock_container->layout_manager());
+ internal::DockedAlignment dock_alignment = dock_layout->CalculateAlignment();
gfx::Rect dock_bounds = ScreenAsh::ConvertRectFromScreen(
GetTarget()->parent(), dock_container->GetBoundsInScreen());
// Windows only snap magnetically when they are close to the edge of the
@@ -239,33 +165,23 @@ bool DockedWindowResizer::MaybeSnapToEdge(const gfx::Rect& bounds,
// When a window being dragged is the last window that was previously
// docked it is still allowed to magnetically snap to either side.
bool can_snap = was_docked_ ||
- (GetDraggedWindowAlignment() != DOCKED_ALIGNMENT_NONE);
+ internal::DockedWindowLayoutManager::ShouldWindowDock(GetTarget(),
+ last_location_);
if (!can_snap)
return false;
- // Distance in pixels that the cursor must move past an edge for a window
- // to move beyond that edge. Same constant as in WorkspaceWindowResizer
- // is used for consistency.
- const int kStickyDistance = WorkspaceWindowResizer::kStickyDistancePixels;
-
- // Short-range magnetism when retaining docked state. Same constant as in
- // MagnetismMatcher is used for consistency.
- const int kSnapToDockDistance = MagnetismMatcher::kMagneticDistance;
-
- if (dock_alignment == DOCKED_ALIGNMENT_LEFT ||
- (dock_alignment == DOCKED_ALIGNMENT_NONE && was_docked_)) {
+ if (dock_alignment == internal::DOCKED_ALIGNMENT_LEFT ||
+ (dock_alignment == internal::DOCKED_ALIGNMENT_NONE && was_docked_)) {
const int distance = bounds.x() - dock_bounds.x();
- if (distance < (was_docked_ ? kSnapToDockDistance : 0) &&
- distance > -kStickyDistance) {
+ if (distance < kSnapToDockDistance && distance > -kStickyDistance) {
offset->set_x(-distance);
return true;
}
}
- if (dock_alignment == DOCKED_ALIGNMENT_RIGHT ||
- (dock_alignment == DOCKED_ALIGNMENT_NONE && was_docked_)) {
+ if (dock_alignment == internal::DOCKED_ALIGNMENT_RIGHT ||
+ (dock_alignment == internal::DOCKED_ALIGNMENT_NONE && was_docked_)) {
const int distance = dock_bounds.right() - bounds.right();
- if (distance < (was_docked_ ? kSnapToDockDistance : 0) &&
- distance > -kStickyDistance) {
+ if (distance < kSnapToDockDistance && distance > -kStickyDistance) {
offset->set_x(distance);
return true;
}
@@ -275,54 +191,37 @@ bool DockedWindowResizer::MaybeSnapToEdge(const gfx::Rect& bounds,
void DockedWindowResizer::StartedDragging() {
// Tell the dock layout manager that we are dragging this window.
- // At this point we are not yet animating the window as it may not be
- // inside the docked area.
dock_layout_->StartDragging(GetTarget());
- // Reparent workspace windows during the drag to elevate them above workspace.
- // Other windows for which the DockedWindowResizer is instantiated include
- // panels and windows that are already docked. Those do not need reparenting.
- if (GetTarget()->type() != aura::client::WINDOW_TYPE_PANEL &&
- GetTarget()->parent()->id() == kShellWindowId_DefaultContainer) {
- // The window is going to be reparented - avoid completing the drag.
- GetTarget()->SetProperty(kContinueDragAfterReparent, true);
-
- // Reparent the window into the docked windows container in order to get it
- // on top of other docked windows.
- aura::Window* docked_container = Shell::GetContainer(
- GetTarget()->GetRootWindow(),
- kShellWindowId_DockedContainer);
- docked_container->AddChild(GetTarget());
- }
- if (is_docked_)
- dock_layout_->DockDraggedWindow(GetTarget());
}
-void DockedWindowResizer::FinishedDragging() {
+void DockedWindowResizer::FinishDragging() {
if (!did_move_or_resize_)
return;
aura::Window* window = GetTarget();
bool should_dock = was_docked_;
- const bool attached_panel =
- window->type() == aura::client::WINDOW_TYPE_PANEL &&
- window->GetProperty(kPanelAttachedKey);
- // If a window was previously docked then keep it docked if it is resized and
- // still aligned at the screen edge.
- if ((was_docked_ ||
- ((details_.bounds_change & WindowResizer::kBoundsChange_Repositions) &&
- !(details_.bounds_change & WindowResizer::kBoundsChange_Resizes)))) {
- should_dock = GetDraggedWindowAlignment() != DOCKED_ALIGNMENT_NONE;
+ if ((details_.bounds_change & WindowResizer::kBoundsChange_Repositions) &&
+ !(details_.bounds_change & WindowResizer::kBoundsChange_Resizes) &&
+ CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kAshEnableDockedWindows)) {
+ const bool attached_panel =
+ window->type() == aura::client::WINDOW_TYPE_PANEL &&
+ window->GetProperty(internal::kPanelAttachedKey);
+ should_dock = !attached_panel &&
+ internal::DockedWindowLayoutManager::ShouldWindowDock(window,
+ last_location_);
}
- // Check if the window needs to be docked or returned to workspace.
- aura::Window* dock_container = Shell::GetContainer(
- window->GetRootWindow(),
- kShellWindowId_DockedContainer);
- if (!attached_panel &&
- should_dock != (window->parent() == dock_container)) {
+ // Check if desired docked state is not same as current.
+ // If not same dock or undock accordingly.
+ if (should_dock !=
+ (window->parent()->id() == internal::kShellWindowId_DockedContainer)) {
if (should_dock) {
+ aura::Window* dock_container = Shell::GetContainer(
+ window->GetRootWindow(),
+ internal::kShellWindowId_DockedContainer);
dock_container->AddChild(window);
- } else if (window->parent()->id() == kShellWindowId_DockedContainer) {
+ } else {
// Reparent the window back to workspace.
// We need to be careful to give SetDefaultParentByRootWindow location in
// the right root window (matching the logic in DragWindowResizer) based
@@ -336,25 +235,6 @@ void DockedWindowResizer::FinishedDragging() {
}
}
dock_layout_->FinishDragging();
-
- // If we started the drag in one root window and moved into another root
- // but then canceled the drag we may need to inform the original layout
- // manager that the drag is finished.
- if (initial_dock_layout_ != dock_layout_)
- initial_dock_layout_->FinishDragging();
- is_docked_ = false;
-}
-
-void DockedWindowResizer::UpdateSnapPhantomWindow() {
- if (!did_move_or_resize_ || details_.window_component != HTCAPTION)
- return;
-
- if (!snap_phantom_window_controller_) {
- snap_phantom_window_controller_.reset(
- new PhantomWindowController(GetTarget()));
- }
- snap_phantom_window_controller_->Show(dock_layout_->dragged_bounds());
}
-} // namespace internal
-} // namespace ash
+} // namespace aura
diff --git a/chromium/ash/wm/dock/docked_window_resizer.h b/chromium/ash/wm/dock/docked_window_resizer.h
index 41bb4fecd5f..41dd47d5b38 100644
--- a/chromium/ash/wm/dock/docked_window_resizer.h
+++ b/chromium/ash/wm/dock/docked_window_resizer.h
@@ -5,10 +5,8 @@
#ifndef ASH_WM_DOCK_DOCK_WINDOW_RESIZER_H_
#define ASH_WM_DOCK_DOCK_WINDOW_RESIZER_H_
-#include "ash/wm/dock/dock_types.h"
#include "ash/wm/window_resizer.h"
#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
namespace gfx {
class Point;
@@ -20,10 +18,10 @@ class RootWindow;
}
namespace ash {
-namespace internal {
+namespace internal {
class DockedWindowLayoutManager;
-class PhantomWindowController;
+}
// DockWindowResizer is used by ToplevelWindowEventFilter to handle dragging,
// moving or resizing of a window while it is docked to the side of a screen.
@@ -54,12 +52,6 @@ class ASH_EXPORT DockedWindowResizer : public WindowResizer {
DockedWindowResizer(WindowResizer* next_window_resizer,
const Details& details);
- // Returns the side of the screen that the window should dock to or
- // DOCKED_ALIGNMENT_NONE when the window is not on a side or when some other
- // windows are already docked on the other side or when launcher (shelf) is
- // aligned on the same side.
- DockedAlignment GetDraggedWindowAlignment();
-
// Checks if the provided window bounds should snap to the side of a screen.
// If so the offset returned gives the necessary adjustment to snap.
bool MaybeSnapToEdge(const gfx::Rect& bounds, gfx::Point* offset);
@@ -70,10 +62,7 @@ class ASH_EXPORT DockedWindowResizer : public WindowResizer {
// Informs the DockLayoutManager that the drag is complete if it was informed
// of the drag start.
- void FinishedDragging();
-
- // Updates the bounds of the phantom window that is used as a docking hint.
- void UpdateSnapPhantomWindow();
+ void FinishDragging();
const Details details_;
@@ -84,20 +73,13 @@ class ASH_EXPORT DockedWindowResizer : public WindowResizer {
// Dock container window.
internal::DockedWindowLayoutManager* dock_layout_;
- internal::DockedWindowLayoutManager* initial_dock_layout_;
// Set to true once Drag() is invoked and the bounds of the window change.
bool did_move_or_resize_;
- // Gives a preview of where the the window will end up.
- scoped_ptr<PhantomWindowController> snap_phantom_window_controller_;
-
// Set to true if the window that is being dragged was docked before drag.
bool was_docked_;
- // True if the dragged window is docked during the drag.
- bool is_docked_;
-
// If non-NULL the destructor sets this to true. Used to determine if this has
// been deleted.
bool* destroyed_;
@@ -105,7 +87,6 @@ class ASH_EXPORT DockedWindowResizer : public WindowResizer {
DISALLOW_COPY_AND_ASSIGN(DockedWindowResizer);
};
-} // namespace internal
} // namespace ash
#endif // ASH_WM_DOCK_DOCK_WINDOW_RESIZER_H_
diff --git a/chromium/ash/wm/dock/docked_window_resizer_unittest.cc b/chromium/ash/wm/dock/docked_window_resizer_unittest.cc
index 49aeca25318..606e6f4f9d7 100644
--- a/chromium/ash/wm/dock/docked_window_resizer_unittest.cc
+++ b/chromium/ash/wm/dock/docked_window_resizer_unittest.cc
@@ -63,6 +63,11 @@ class DockedWindowResizerTest
DOCKED_EDGE_RIGHT,
};
+ enum DockedState {
+ UNDOCKED,
+ DOCKED,
+ };
+
aura::Window* CreateTestWindow(const gfx::Rect& bounds) {
aura::Window* window = CreateTestWindowInShellWithDelegateAndType(
&delegate_,
@@ -140,12 +145,15 @@ class DockedWindowResizerTest
}
// Panels are parented by panel container during drags.
- // All other windows that are tested here are parented by dock container
- // during drags.
- int CorrectContainerIdDuringDrag() {
+ // Docked windows are parented by dock container during drags.
+ // All other windows that we are testing here have default container as a
+ // parent.
+ int CorrectContainerIdDuringDrag(DockedState is_docked) {
if (window_type_ == aura::client::WINDOW_TYPE_PANEL)
return internal::kShellWindowId_PanelContainer;
- return internal::kShellWindowId_DockedContainer;
+ if (is_docked == DOCKED)
+ return internal::kShellWindowId_DockedContainer;
+ return internal::kShellWindowId_DefaultContainer;
}
// Test dragging the window vertically (to detach if it is a panel) and then
@@ -190,7 +198,7 @@ class DockedWindowResizerTest
// Drag enough to detach since our tests assume panels to be initially
// detached.
DragMove(0, dy);
- EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id());
+ EXPECT_EQ(CorrectContainerIdDuringDrag(UNDOCKED), window->parent()->id());
EXPECT_EQ(initial_bounds.x(), window->GetBoundsInScreen().x());
EXPECT_EQ(initial_bounds.y() + dy, window->GetBoundsInScreen().y());
@@ -212,7 +220,7 @@ class DockedWindowResizerTest
else if (edge == DOCKED_EDGE_RIGHT)
dx += window->GetRootWindow()->bounds().right() - initial_bounds.right();
DragMove(dx, window_type_ == aura::client::WINDOW_TYPE_PANEL ? 0 : dy);
- EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id());
+ EXPECT_EQ(CorrectContainerIdDuringDrag(UNDOCKED), window->parent()->id());
// Release the mouse and the panel should be attached to the dock.
DragEnd();
@@ -381,10 +389,9 @@ TEST_P(DockedWindowResizerTest, AttachTryDetach) {
window->GetBoundsInScreen().right());
EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
- // Try to detach by dragging left less than kSnapToDockDistance.
- // The window should stay docked.
+ // Try to detach by dragging left a bit (should stay docked)
ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
- DragMove(-4, -10);
+ DragMove(-10, -10);
// Release the mouse and the window should be still attached to the dock.
DragEnd();
@@ -393,8 +400,7 @@ TEST_P(DockedWindowResizerTest, AttachTryDetach) {
window->GetBoundsInScreen().right());
EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
- // Try to detach by dragging left by kSnapToDockDistance or more.
- // The window should get undocked.
+ // Try to detach by dragging left a bit more (should get undocked)
ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
DragMove(-32, -10);
// Release the mouse and the window should be no longer attached to the dock.
@@ -539,7 +545,7 @@ TEST_P(DockedWindowResizerTest, DragAcrossDisplays) {
// but not enough to land in the other screen
ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
DragMove(70, 0);
- EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id());
+ EXPECT_EQ(CorrectContainerIdDuringDrag(DOCKED), window->parent()->id());
DragEnd();
EXPECT_NE(window->GetRootWindow()->bounds().right(),
window->GetBoundsInScreen().right());
@@ -550,7 +556,7 @@ TEST_P(DockedWindowResizerTest, DragAcrossDisplays) {
// Move back left - should dock again.
ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
DragMove(-70, 0);
- EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id());
+ EXPECT_EQ(CorrectContainerIdDuringDrag(UNDOCKED), window->parent()->id());
DragEnd();
EXPECT_EQ(window->GetRootWindow()->bounds().right(),
window->GetBoundsInScreen().right());
@@ -566,7 +572,7 @@ TEST_P(DockedWindowResizerTest, DragAcrossDisplays) {
window->bounds().width()/2 + 10,
0));
DragMove(window->bounds().width()/2 - 5, 0);
- EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id());
+ EXPECT_EQ(CorrectContainerIdDuringDrag(DOCKED), window->parent()->id());
DragEnd();
EXPECT_NE(window->GetRootWindow()->bounds().right(),
window->GetBoundsInScreen().right());
@@ -583,7 +589,7 @@ TEST_P(DockedWindowResizerTest, DragAcrossDisplays) {
DragMove(window->GetRootWindow()->GetBoundsInScreen().x() -
window->GetBoundsInScreen().x(),
0);
- EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id());
+ EXPECT_EQ(CorrectContainerIdDuringDrag(UNDOCKED), window->parent()->id());
DragEnd();
EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().x(),
window->GetBoundsInScreen().x());
@@ -614,7 +620,7 @@ TEST_P(DockedWindowResizerTest, AttachTwoWindowsDetachOne)
EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_);
EXPECT_EQ(w1->bounds().width(), manager->docked_width_);
- DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_RIGHT, w2.get(), 0, 100);
+ DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_RIGHT, w2.get(), 0, 50);
// Both windows should now be attached and snapped to the right edge.
EXPECT_EQ(w2->GetRootWindow()->bounds().right(),
w2->GetBoundsInScreen().right());
@@ -721,11 +727,12 @@ TEST_P(DockedWindowResizerTest, AttachWindowMaximizeOther)
ASSERT_NO_FATAL_FAILURE(DragStart(w1.get()));
EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_);
DragMove(-35, 10);
- // Alignment is set to "NONE" when drag starts.
- EXPECT_EQ(DOCKED_ALIGNMENT_NONE, manager->alignment_);
+ // For NORMAL windows alignment is set to "RIGHT" until the drag is completed.
+ // For PANEL windows alignment is set to "NONE" when drag starts.
+ EXPECT_EQ(test_panels() ? DOCKED_ALIGNMENT_NONE : DOCKED_ALIGNMENT_RIGHT,
+ manager->alignment_);
// Release the mouse and the window should be no longer attached to the edge.
DragEnd();
- EXPECT_EQ(DOCKED_ALIGNMENT_NONE, manager->alignment_);
// Dock should get shrunk and desktop should get expanded.
EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w1->parent()->id());
EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id());
@@ -817,7 +824,7 @@ TEST_P(DockedWindowResizerTest, AttachOneTestSticky)
// Drag w2 by a bit more - it should resist the drag (stuck edges)
int start_x = w2->bounds().x();
- ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(w2.get(), 100, 5));
+ ASSERT_NO_FATAL_FAILURE(DragStart(w2.get()));
DragMove(-2, 0);
// Window should not actually move.
EXPECT_EQ(start_x, w2->bounds().x());
@@ -881,7 +888,7 @@ TEST_P(DockedWindowResizerTest, ResizeTwoWindows)
EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_);
EXPECT_EQ(w1->bounds().width(), manager->docked_width_);
- DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_RIGHT, w2.get(), 0, 100);
+ DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_RIGHT, w2.get(), 0, 50);
// Both windows should now be attached and snapped to the right edge.
EXPECT_EQ(w2->GetRootWindow()->bounds().right(),
w2->GetBoundsInScreen().right());
@@ -1024,11 +1031,12 @@ TEST_P(DockedWindowResizerTest, DragToShelf)
// Detach and drag down to shelf.
ASSERT_NO_FATAL_FAILURE(DragStart(w1.get()));
DragMove(-40, 0);
- // Alignment is set to "NONE" when drag starts.
- EXPECT_EQ(DOCKED_ALIGNMENT_NONE, manager->alignment_);
+ // For NORMAL windows alignment is set to "RIGHT" until the drag is completed.
+ // For PANEL windows alignment is set to "NONE" when drag starts.
+ EXPECT_EQ(test_panels() ? DOCKED_ALIGNMENT_NONE : DOCKED_ALIGNMENT_RIGHT,
+ manager->alignment_);
// Release the mouse and the window should be no longer attached to the edge.
DragEnd();
- EXPECT_EQ(DOCKED_ALIGNMENT_NONE, manager->alignment_);
// Drag down almost to shelf. A panel will snap, a regular window won't.
ShelfWidget* shelf = Launcher::ForPrimaryDisplay()->shelf_widget();
diff --git a/chromium/ash/wm/event_client_impl.cc b/chromium/ash/wm/event_client_impl.cc
index 03d4dea0b03..fcdc1b425d3 100644
--- a/chromium/ash/wm/event_client_impl.cc
+++ b/chromium/ash/wm/event_client_impl.cc
@@ -8,7 +8,6 @@
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ui/aura/window.h"
-#include "ui/keyboard/keyboard_util.h"
namespace ash {
namespace internal {
@@ -22,34 +21,26 @@ EventClientImpl::~EventClientImpl() {
bool EventClientImpl::CanProcessEventsWithinSubtree(
const aura::Window* window) const {
const aura::RootWindow* root_window = window ? window->GetRootWindow() : NULL;
- if (!root_window ||
- !Shell::GetInstance()->session_state_delegate()->IsUserSessionBlocked()) {
+ if (!root_window)
return true;
- }
-
- const aura::Window* lock_screen_containers = Shell::GetContainer(
- root_window,
- kShellWindowId_LockScreenContainersContainer);
- const aura::Window* lock_background_containers = Shell::GetContainer(
- root_window,
- kShellWindowId_LockScreenBackgroundContainer);
- const aura::Window* lock_screen_related_containers = Shell::GetContainer(
- root_window,
- kShellWindowId_LockScreenRelatedContainersContainer);
- bool can_process_events = (window->Contains(lock_screen_containers) &&
- window->Contains(lock_background_containers) &&
- window->Contains(lock_screen_related_containers)) ||
- lock_screen_containers->Contains(window) ||
- lock_background_containers->Contains(window) ||
- lock_screen_related_containers->Contains(window);
- if (keyboard::IsKeyboardEnabled()) {
- const aura::Window* virtual_keyboard_container = Shell::GetContainer(
+ if (Shell::GetInstance()->session_state_delegate()->IsUserSessionBlocked()) {
+ const aura::Window* lock_screen_containers = Shell::GetContainer(
+ root_window,
+ kShellWindowId_LockScreenContainersContainer);
+ const aura::Window* lock_background_containers = Shell::GetContainer(
+ root_window,
+ kShellWindowId_LockScreenBackgroundContainer);
+ const aura::Window* lock_screen_related_containers = Shell::GetContainer(
root_window,
- kShellWindowId_VirtualKeyboardContainer);
- can_process_events |= (window->Contains(virtual_keyboard_container) ||
- virtual_keyboard_container->Contains(window));
+ kShellWindowId_LockScreenRelatedContainersContainer);
+ return (window->Contains(lock_screen_containers) &&
+ window->Contains(lock_background_containers) &&
+ window->Contains(lock_screen_related_containers)) ||
+ lock_screen_containers->Contains(window) ||
+ lock_background_containers->Contains(window) ||
+ lock_screen_related_containers->Contains(window);
}
- return can_process_events;
+ return true;
}
ui::EventTarget* EventClientImpl::GetToplevelEventTarget() {
diff --git a/chromium/ash/wm/frame_painter.h b/chromium/ash/wm/frame_painter.h
index e79b012d2e9..38f2fb1e697 100644
--- a/chromium/ash/wm/frame_painter.h
+++ b/chromium/ash/wm/frame_painter.h
@@ -160,6 +160,8 @@ class ASH_EXPORT FramePainter : public aura::WindowObserver,
FRIEND_TEST_ALL_PREFIXES(FramePainterTest, GetHeaderOpacity);
FRIEND_TEST_ALL_PREFIXES(FramePainterTest, TitleIconAlignment);
FRIEND_TEST_ALL_PREFIXES(FramePainterTest, ChildWindowVisibility);
+ FRIEND_TEST_ALL_PREFIXES(FramePainterTest,
+ NoCrashShutdownWithAlwaysOnTopWindow);
// Sets the images for a button based on IDs from the |frame_| theme provider.
void SetButtonImages(views::ImageButton* button,
diff --git a/chromium/ash/wm/frame_painter_unittest.cc b/chromium/ash/wm/frame_painter_unittest.cc
index ee9313fcf10..5826be6787d 100644
--- a/chromium/ash/wm/frame_painter_unittest.cc
+++ b/chromium/ash/wm/frame_painter_unittest.cc
@@ -12,6 +12,7 @@
#include "ash/wm/window_properties.h"
#include "ash/wm/window_util.h"
#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
#include "grit/ash_resources.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/aura_constants.h"
@@ -25,6 +26,7 @@
#include "ui/views/controls/button/image_button.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
+#include "ui/views/widget/widget_observer.h"
#include "ui/views/window/non_client_view.h"
using ash::FramePainter;
@@ -148,6 +150,33 @@ FramePainter* CreateTestPainter(Widget* widget) {
return painter;
}
+// Self-owned manager of the frame painter which deletes the painter and itself
+// when its widget is closed.
+class FramePainterOwner : views::WidgetObserver {
+ public:
+ explicit FramePainterOwner(Widget* widget)
+ : frame_painter_(CreateTestPainter(widget)) {
+ widget->AddObserver(this);
+ }
+
+ virtual ~FramePainterOwner() {}
+
+ FramePainter* frame_painter() { return frame_painter_.get(); }
+
+ private:
+ virtual void OnWidgetDestroying(Widget* widget) OVERRIDE {
+ widget->RemoveObserver(this);
+ // Do not delete directly here, since the task of FramePainter causing
+ // the crash of crbug.com/273310 may run after this class handles this
+ // event.
+ base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+ }
+
+ scoped_ptr<FramePainter> frame_painter_;
+
+ DISALLOW_COPY_AND_ASSIGN(FramePainterOwner);
+};
+
} // namespace
namespace ash {
@@ -690,4 +719,33 @@ TEST_F(FramePainterTest, ChildWindowVisibility) {
0));
}
+TEST_F(FramePainterTest, NoCrashShutdownWithAlwaysOnTopWindow) {
+ // Create normal window and an always-on-top window, and leave it as is
+ // and finish the test, then verify it doesn't cause a crash. See
+ // crbug.com/273310. Note that those widgets will be deleted at
+ // RootWindowController::CloseChildWindows(), so this code is memory-safe.
+ Widget* w1 = new Widget;
+ Widget::InitParams params1;
+ params1.context = CurrentContext();
+ w1->Init(params1);
+ FramePainterOwner* o1 = new FramePainterOwner(w1);
+ FramePainter* p1 = o1->frame_painter();
+ w1->SetBounds(gfx::Rect(0, 0, 100, 100));
+ w1->Show();
+ EXPECT_TRUE(p1->UseSoloWindowHeader());
+
+ Widget* w2 = new Widget;
+ Widget::InitParams params2;
+ params2.context = CurrentContext();
+ params2.keep_on_top = true;
+ w2->Init(params2);
+ FramePainterOwner* o2 = new FramePainterOwner(w2);
+ FramePainter* p2 = o2->frame_painter();
+ w2->Show();
+ EXPECT_FALSE(p1->UseSoloWindowHeader());
+ EXPECT_FALSE(p2->UseSoloWindowHeader());
+
+ // Exit with no resource release. They'll be released at shutdown.
+}
+
} // namespace ash
diff --git a/chromium/ash/wm/panels/panel_layout_manager_unittest.cc b/chromium/ash/wm/panels/panel_layout_manager_unittest.cc
index 08f53f7aa8b..ca231ce005d 100644
--- a/chromium/ash/wm/panels/panel_layout_manager_unittest.cc
+++ b/chromium/ash/wm/panels/panel_layout_manager_unittest.cc
@@ -128,8 +128,6 @@ class PanelLayoutManagerTest : public test::AshTestBase {
ASSERT_FALSE(icon_bounds.width() == 0 && icon_bounds.height() == 0);
gfx::Rect window_bounds = panel->GetBoundsInScreen();
- ASSERT_LT(icon_bounds.width(), window_bounds.width());
- ASSERT_LT(icon_bounds.height(), window_bounds.height());
gfx::Rect launcher_bounds = launcher->shelf_widget()->
GetWindowBoundsInScreen();
ShelfAlignment alignment = GetAlignment(panel->GetRootWindow());
diff --git a/chromium/ash/wm/status_area_layout_manager.cc b/chromium/ash/wm/status_area_layout_manager.cc
index d9e0424d240..e17d84e26d2 100644
--- a/chromium/ash/wm/status_area_layout_manager.cc
+++ b/chromium/ash/wm/status_area_layout_manager.cc
@@ -70,7 +70,7 @@ void StatusAreaLayoutManager::SetChildBounds(
void StatusAreaLayoutManager::LayoutStatusArea() {
// Shelf layout manager may be already doing layout.
- if (shelf_->shelf_layout_manager()->updating_bounds())
+ if (shelf_->shelf_layout_manager()->in_layout())
return;
base::AutoReset<bool> auto_reset_in_layout(&in_layout_, true);
diff --git a/chromium/ash/wm/window_animations.cc b/chromium/ash/wm/window_animations.cc
index a3c0ca80621..73deafd75c1 100644
--- a/chromium/ash/wm/window_animations.cc
+++ b/chromium/ash/wm/window_animations.cc
@@ -295,6 +295,9 @@ class CrossFadeObserver : public ui::CompositorObserver,
// Triggers OnImplicitAnimationsCompleted() to be called and deletes us.
layer_->GetAnimator()->StopAnimating();
}
+ virtual void OnWindowRemovingFromRootWindow(aura::Window* window) OVERRIDE {
+ layer_->GetAnimator()->StopAnimating();
+ }
// ui::ImplicitAnimationObserver overrides:
virtual void OnImplicitAnimationsCompleted() OVERRIDE {
diff --git a/chromium/ash/wm/window_resizer.cc b/chromium/ash/wm/window_resizer.cc
index 1ea317a1a3f..e312fc179e5 100644
--- a/chromium/ash/wm/window_resizer.cc
+++ b/chromium/ash/wm/window_resizer.cc
@@ -7,7 +7,6 @@
#include "ash/screen_ash.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
-#include "ash/wm/coordinate_conversion.h"
#include "ash/wm/dock/docked_window_layout_manager.h"
#include "ash/wm/property_util.h"
#include "ash/wm/window_util.h"
@@ -181,6 +180,14 @@ gfx::Rect WindowResizer::CalculateBoundsForDrag(
return details.initial_bounds_in_parent;
gfx::Point location = passed_location;
+ aura::Window* dock_container = Shell::GetContainer(
+ details.window->GetRootWindow(),
+ internal::kShellWindowId_DockedContainer);
+ DCHECK_EQ(dock_container->id(), internal::kShellWindowId_DockedContainer);
+ internal::DockedWindowLayoutManager* dock_layout =
+ static_cast<internal::DockedWindowLayoutManager*>(
+ dock_container->layout_manager());
+
int delta_x = location.x() - details.initial_location_in_parent.x();
int delta_y = location.y() - details.initial_location_in_parent.y();
@@ -199,13 +206,6 @@ gfx::Rect WindowResizer::CalculateBoundsForDrag(
if (details.bounds_change & kBoundsChange_Resizes) {
gfx::Rect work_area =
Shell::GetScreen()->GetDisplayNearestWindow(details.window).work_area();
- aura::Window* dock_container = Shell::GetContainer(
- details.window->GetRootWindow(),
- internal::kShellWindowId_DockedContainer);
- internal::DockedWindowLayoutManager* dock_layout =
- static_cast<internal::DockedWindowLayoutManager*>(
- dock_container->layout_manager());
-
work_area.Union(dock_layout->docked_bounds());
work_area = ScreenAsh::ConvertRectFromScreen(details.window->parent(),
work_area);
@@ -265,13 +265,6 @@ gfx::Rect WindowResizer::CalculateBoundsForDrag(
ScreenAsh::ConvertRectToScreen(parent, new_bounds);
const gfx::Display& display =
Shell::GetScreen()->GetDisplayMatching(new_bounds_in_screen);
- aura::Window* dock_container = Shell::GetContainer(
- wm::GetRootWindowMatching(new_bounds_in_screen),
- internal::kShellWindowId_DockedContainer);
- internal::DockedWindowLayoutManager* dock_layout =
- static_cast<internal::DockedWindowLayoutManager*>(
- dock_container->layout_manager());
-
gfx::Rect screen_work_area = display.work_area();
screen_work_area.Union(dock_layout->docked_bounds());
screen_work_area.Inset(kMinimumOnScreenArea, 0);
diff --git a/chromium/ash/wm/window_selector.cc b/chromium/ash/wm/window_selector.cc
index 47e20159572..8e87a95163c 100644
--- a/chromium/ash/wm/window_selector.cc
+++ b/chromium/ash/wm/window_selector.cc
@@ -361,10 +361,6 @@ void WindowSelector::OnEvent(ui::Event* event) {
aura::Window* target = static_cast<aura::Window*>(event->target());
for (size_t i = 0; i < windows_.size(); ++i) {
if (windows_[i]->Contains(target)) {
- // TODO(flackr): StopPropogation prevents generation of gesture events.
- // We should find a better way to prevent events from being delivered to
- // the window, perhaps a transparent window in front of the target window
- // or using EventClientImpl::CanProcessEventsWithinSubtree.
event->StopPropagation();
break;
}
@@ -385,8 +381,8 @@ void WindowSelector::OnMouseEvent(ui::MouseEvent* event) {
HandleSelectionEvent(target);
}
-void WindowSelector::OnTouchEvent(ui::TouchEvent* event) {
- if (event->type() != ui::ET_TOUCH_PRESSED)
+void WindowSelector::OnGestureEvent(ui::GestureEvent* event) {
+ if (event->type() != ui::ET_GESTURE_TAP)
return;
WindowSelectorWindow* target = GetEventTarget(event);
if (!target)
diff --git a/chromium/ash/wm/window_selector.h b/chromium/ash/wm/window_selector.h
index 9cd1e04fd22..92ed607eabc 100644
--- a/chromium/ash/wm/window_selector.h
+++ b/chromium/ash/wm/window_selector.h
@@ -64,7 +64,7 @@ class WindowSelector : public ui::EventHandler,
// ui::EventHandler:
virtual void OnEvent(ui::Event* event) OVERRIDE;
virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
- virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
+ virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
// aura::WindowObserver:
virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
diff --git a/chromium/ash/wm/window_util.cc b/chromium/ash/wm/window_util.cc
index 67dcd95c4c1..7b8e616aa7e 100644
--- a/chromium/ash/wm/window_util.cc
+++ b/chromium/ash/wm/window_util.cc
@@ -161,29 +161,29 @@ void SetPreAutoManageWindowBounds(aura::Window* window,
new gfx::Rect(bounds));
}
-void AdjustBoundsToEnsureMinimumWindowVisibility(const gfx::Rect& work_area,
+void AdjustBoundsToEnsureMinimumWindowVisibility(const gfx::Rect& visible_area,
gfx::Rect* bounds) {
AdjustBoundsToEnsureWindowVisibility(
- work_area, kMinimumOnScreenArea, kMinimumOnScreenArea, bounds);
+ visible_area, kMinimumOnScreenArea, kMinimumOnScreenArea, bounds);
}
-void AdjustBoundsToEnsureWindowVisibility(const gfx::Rect& work_area,
+void AdjustBoundsToEnsureWindowVisibility(const gfx::Rect& visible_area,
int min_width,
int min_height,
gfx::Rect* bounds) {
- bounds->set_width(std::min(bounds->width(), work_area.width()));
- bounds->set_height(std::min(bounds->height(), work_area.height()));
+ bounds->set_width(std::min(bounds->width(), visible_area.width()));
+ bounds->set_height(std::min(bounds->height(), visible_area.height()));
- min_width = std::min(min_width, work_area.width());
- min_height = std::min(min_height, work_area.height());
+ min_width = std::min(min_width, visible_area.width());
+ min_height = std::min(min_height, visible_area.height());
- if (bounds->x() + min_width > work_area.right()) {
- bounds->set_x(work_area.right() - min_width);
+ if (bounds->x() + min_width > visible_area.right()) {
+ bounds->set_x(visible_area.right() - min_width);
} else if (bounds->right() - min_width < 0) {
bounds->set_x(min_width - bounds->width());
}
- if (bounds->y() + min_height > work_area.bottom()) {
- bounds->set_y(work_area.bottom() - min_height);
+ if (bounds->y() + min_height > visible_area.bottom()) {
+ bounds->set_y(visible_area.bottom() - min_height);
} else if (bounds->bottom() - min_height < 0) {
bounds->set_y(min_height - bounds->height());
}
diff --git a/chromium/ash/wm/window_util.h b/chromium/ash/wm/window_util.h
index 1ffeb7db8a3..659d3e11e2d 100644
--- a/chromium/ash/wm/window_util.h
+++ b/chromium/ash/wm/window_util.h
@@ -108,16 +108,16 @@ ASH_EXPORT const gfx::Rect* GetPreAutoManageWindowBounds(
ASH_EXPORT void SetPreAutoManageWindowBounds(aura::Window* window,
const gfx::Rect& bounds);
-// Move the given bounds inside the given work area, including a safety margin
-// given by |kMinimumOnScreenArea|.
+// Move the given bounds inside the given |visible_area|, including a
+// safety margin given by |kMinimumOnScreenArea|.
ASH_EXPORT void AdjustBoundsToEnsureMinimumWindowVisibility(
- const gfx::Rect& work_area,
+ const gfx::Rect& visible_area,
gfx::Rect* bounds);
-// Move the given bounds inside the given work area, including a safety margin
-// given by |min_width| and |min_height|.
+// Move the given bounds inside the given |visible_area|, including a
+// safety margin given by |min_width| and |min_height|.
ASH_EXPORT void AdjustBoundsToEnsureWindowVisibility(
- const gfx::Rect& work_area,
+ const gfx::Rect& visible_area,
int min_width,
int min_height,
gfx::Rect* bounds);
diff --git a/chromium/ash/wm/workspace/phantom_window_controller.cc b/chromium/ash/wm/workspace/phantom_window_controller.cc
index 67272c18a39..4287d5b40d0 100644
--- a/chromium/ash/wm/workspace/phantom_window_controller.cc
+++ b/chromium/ash/wm/workspace/phantom_window_controller.cc
@@ -8,7 +8,6 @@
#include "ash/shell_window_ids.h"
#include "ash/wm/coordinate_conversion.h"
#include "third_party/skia/include/core/SkCanvas.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
#include "ui/base/animation/slide_animation.h"
#include "ui/compositor/layer.h"
@@ -92,56 +91,25 @@ void EdgePainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
PhantomWindowController::PhantomWindowController(aura::Window* window)
: window_(window),
phantom_below_window_(NULL),
- phantom_widget_(NULL),
- phantom_widget_start_(NULL) {
+ phantom_widget_(NULL) {
}
PhantomWindowController::~PhantomWindowController() {
Hide();
}
-void PhantomWindowController::Show(const gfx::Rect& bounds_in_screen) {
- if (bounds_in_screen == bounds_in_screen_)
+void PhantomWindowController::Show(const gfx::Rect& bounds) {
+ if (bounds == bounds_)
return;
- bounds_in_screen_ = bounds_in_screen;
- aura::RootWindow* target_root = wm::GetRootWindowMatching(bounds_in_screen);
- // Show the phantom at the current bounds of the window. We'll animate to the
- // target bounds. If phantom exists, update the start bounds.
- if (!phantom_widget_)
+ bounds_ = bounds;
+ if (!phantom_widget_) {
+ // Show the phantom at the bounds of the window. We'll animate to the target
+ // bounds.
start_bounds_ = window_->GetBoundsInScreen();
- else
+ CreatePhantomWidget(start_bounds_);
+ } else {
start_bounds_ = phantom_widget_->GetWindowBoundsInScreen();
- if (phantom_widget_ &&
- phantom_widget_->GetNativeWindow()->GetRootWindow() != target_root) {
- phantom_widget_->Close();
- phantom_widget_ = NULL;
- }
- if (!phantom_widget_)
- phantom_widget_ = CreatePhantomWidget(target_root, start_bounds_);
-
- // Create a secondary widget in a second screen if start_bounds_ lie at least
- // partially in that other screen. This allows animations to start or restart
- // in one root window and progress into another root.
- aura::RootWindow* start_root = wm::GetRootWindowMatching(start_bounds_);
- if (start_root == target_root) {
- Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
- for (size_t i = 0; i < root_windows.size(); ++i) {
- if (root_windows[i] != target_root &&
- root_windows[i]->GetBoundsInScreen().Intersects(start_bounds_)) {
- start_root = root_windows[i];
- break;
- }
- }
}
- if (phantom_widget_start_ &&
- (phantom_widget_start_->GetNativeWindow()->GetRootWindow() != start_root
- || start_root == target_root)) {
- phantom_widget_start_->Close();
- phantom_widget_start_ = NULL;
- }
- if (!phantom_widget_start_ && start_root != target_root)
- phantom_widget_start_ = CreatePhantomWidget(start_root, start_bounds_);
-
animation_.reset(new ui::SlideAnimation(this));
animation_->SetTweenType(ui::Tween::EASE_IN);
const int kAnimationDurationMS = 200;
@@ -153,9 +121,6 @@ void PhantomWindowController::Hide() {
if (phantom_widget_)
phantom_widget_->Close();
phantom_widget_ = NULL;
- if (phantom_widget_start_)
- phantom_widget_start_->Close();
- phantom_widget_start_ = NULL;
}
bool PhantomWindowController::IsShowing() const {
@@ -164,50 +129,45 @@ bool PhantomWindowController::IsShowing() const {
void PhantomWindowController::AnimationProgressed(
const ui::Animation* animation) {
- const gfx::Rect current_bounds =
- animation->CurrentValueBetween(start_bounds_, bounds_in_screen_);
- if (phantom_widget_start_)
- phantom_widget_start_->SetBounds(current_bounds);
- phantom_widget_->SetBounds(current_bounds);
+ phantom_widget_->SetBounds(
+ animation->CurrentValueBetween(start_bounds_, bounds_));
}
-views::Widget* PhantomWindowController::CreatePhantomWidget(
- aura::RootWindow* root_window,
- const gfx::Rect& bounds_in_screen) {
- views::Widget* phantom_widget = new views::Widget;
+void PhantomWindowController::CreatePhantomWidget(const gfx::Rect& bounds) {
+ DCHECK(!phantom_widget_);
+ phantom_widget_ = new views::Widget;
views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
// PhantomWindowController is used by FrameMaximizeButton to highlight the
// launcher button. Put the phantom in the same window as the launcher so that
// the phantom is visible.
- params.parent = Shell::GetContainer(root_window,
+ params.parent = Shell::GetContainer(wm::GetRootWindowMatching(bounds),
kShellWindowId_ShelfContainer);
params.can_activate = false;
params.keep_on_top = true;
- phantom_widget->set_focus_on_creation(false);
- phantom_widget->Init(params);
- phantom_widget->SetVisibilityChangedAnimationsEnabled(false);
- phantom_widget->GetNativeWindow()->SetName("PhantomWindow");
- phantom_widget->GetNativeWindow()->set_id(kShellWindowId_PhantomWindow);
+ phantom_widget_->set_focus_on_creation(false);
+ phantom_widget_->Init(params);
+ phantom_widget_->SetVisibilityChangedAnimationsEnabled(false);
+ phantom_widget_->GetNativeWindow()->SetName("PhantomWindow");
+ phantom_widget_->GetNativeWindow()->set_id(kShellWindowId_PhantomWindow);
views::View* content_view = new views::View;
content_view->set_background(
views::Background::CreateBackgroundPainter(true, new EdgePainter));
- phantom_widget->SetContentsView(content_view);
- phantom_widget->SetBounds(bounds_in_screen);
+ phantom_widget_->SetContentsView(content_view);
+ phantom_widget_->SetBounds(bounds);
if (phantom_below_window_)
- phantom_widget->StackBelow(phantom_below_window_);
+ phantom_widget_->StackBelow(phantom_below_window_);
else
- phantom_widget->StackAbove(window_);
+ phantom_widget_->StackAbove(window_);
// Show the widget after all the setups.
- phantom_widget->Show();
+ phantom_widget_->Show();
// Fade the window in.
- ui::Layer* widget_layer = phantom_widget->GetNativeWindow()->layer();
+ ui::Layer* widget_layer = phantom_widget_->GetNativeWindow()->layer();
widget_layer->SetOpacity(0);
ui::ScopedLayerAnimationSettings scoped_setter(widget_layer->GetAnimator());
widget_layer->SetOpacity(1);
- return phantom_widget;
}
} // namespace internal
diff --git a/chromium/ash/wm/workspace/phantom_window_controller.h b/chromium/ash/wm/workspace/phantom_window_controller.h
index 5cd40daa2cd..d7622fcc556 100644
--- a/chromium/ash/wm/workspace/phantom_window_controller.h
+++ b/chromium/ash/wm/workspace/phantom_window_controller.h
@@ -13,7 +13,6 @@
#include "ui/gfx/rect.h"
namespace aura {
-class RootWindow;
class Window;
}
@@ -36,14 +35,13 @@ class ASH_EXPORT PhantomWindowController : public ui::AnimationDelegate {
virtual ~PhantomWindowController();
// Bounds last passed to Show().
- const gfx::Rect& bounds_in_screen() const { return bounds_in_screen_; }
+ const gfx::Rect& bounds() const { return bounds_; }
- // Animates the phantom window towards |bounds_in_screen|.
- // Creates two (if start bounds intersect any root window other than the
- // root window that matches the target bounds) or one (otherwise) phantom
- // widgets to display animated rectangle in each root.
+ // Shows the phantom window at the specified location (coordinates of the
+ // parent). If |layer| is non-NULL, it is shown on top of the phantom window.
+ // |layer| is owned by the caller.
// This does not immediately show the window.
- void Show(const gfx::Rect& bounds_in_screen);
+ void Show(const gfx::Rect& bounds);
// Hides the phantom.
void Hide();
@@ -61,12 +59,12 @@ class ASH_EXPORT PhantomWindowController : public ui::AnimationDelegate {
virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE;
private:
- FRIEND_TEST_ALL_PREFIXES(WorkspaceWindowResizerTest, PhantomWindowShow);
+ FRIEND_TEST_ALL_PREFIXES(WorkspaceWindowResizerTest, PhantomStyle);
- // Creates, shows and returns a phantom widget at |bounds|
- // with kShellWindowId_ShelfContainer in |root_window| as a parent.
- views::Widget* CreatePhantomWidget(aura::RootWindow* root_window,
- const gfx::Rect& bounds_in_screen);
+ // Creates and shows the |phantom_widget_| at |bounds|.
+ // |layer| is shown on top of the phantom window if it is non-NULL.
+ // |layer| is not owned by this object.
+ void CreatePhantomWidget(const gfx::Rect& bounds);
// Window the phantom is placed beneath.
aura::Window* window_;
@@ -74,24 +72,15 @@ class ASH_EXPORT PhantomWindowController : public ui::AnimationDelegate {
// If set, the phantom window should get stacked below this window.
aura::Window* phantom_below_window_;
- // Initially the bounds of |window_| (in screen coordinates).
- // Each time Show() is invoked |start_bounds_| is then reset to the bounds of
- // |phantom_widget_| and |bounds_| is set to the value passed into Show().
- // The animation animates between these two values.
+ // Initially the bounds of |window_|. Each time Show() is invoked
+ // |start_bounds_| is then reset to the bounds of |phantom_widget_| and
+ // |bounds_| is set to the value passed into Show(). The animation animates
+ // between these two values.
gfx::Rect start_bounds_;
+ gfx::Rect bounds_;
- // Target bounds of the animation in screen coordinates.
- gfx::Rect bounds_in_screen_;
-
- // The primary phantom representation of the window. It is parented by the
- // root window matching the target bounds.
views::Widget* phantom_widget_;
- // If the animation starts on another display, this is the secondary phantom
- // representation of the window used on the initial display, otherwise this is
- // NULL. This allows animation to progress from one display into the other.
- views::Widget* phantom_widget_start_;
-
// Used to transition the bounds.
scoped_ptr<ui::SlideAnimation> animation_;
diff --git a/chromium/ash/wm/workspace/workspace_layout_manager.cc b/chromium/ash/wm/workspace/workspace_layout_manager.cc
index 69bcc16069a..0dd9dbf3464 100644
--- a/chromium/ash/wm/workspace/workspace_layout_manager.cc
+++ b/chromium/ash/wm/workspace/workspace_layout_manager.cc
@@ -48,13 +48,15 @@ void MoveToDisplayForRestore(aura::Window* window) {
return;
// Move only if the restore bounds is outside of
- // the root window. There is no information about in which
+ // the display. There is no information about in which
// display it should be restored, so this is best guess.
// TODO(oshima): Restore information should contain the
// work area information like WindowResizer does for the
// last window location.
- if (!window->GetRootWindow()->GetBoundsInScreen().Intersects(
- *restore_bounds)) {
+ gfx::Rect display_area =
+ Shell::GetScreen()->GetDisplayNearestWindow(window).bounds();
+
+ if (!display_area.Intersects(*restore_bounds)) {
DisplayController* display_controller =
Shell::GetInstance()->display_controller();
const gfx::Display& display =
@@ -87,14 +89,7 @@ void WorkspaceLayoutManager::SetShelf(internal::ShelfLayoutManager* shelf) {
}
void WorkspaceLayoutManager::OnWindowAddedToLayout(Window* child) {
- // Adjust window bounds in case that the new child is given the bounds that
- // is out of the workspace. Exclude the case where bounds is empty
- // (this happens when a views::Widget is created), or the window
- // is added with the bounds because a user explicitly moved to
- // this position (drag and drop for example).
- if (!child->bounds().IsEmpty() &&
- !wm::HasUserChangedWindowPositionOrSize(child))
- AdjustWindowBoundsWhenAdded(child);
+ AdjustWindowBoundsWhenAdded(child);
BaseLayoutManager::OnWindowAddedToLayout(child);
UpdateDesktopVisibility();
RearrangeVisibleWindowOnShow(child);
@@ -252,6 +247,14 @@ void WorkspaceLayoutManager::AdjustWindowBoundsForWorkAreaChange(
void WorkspaceLayoutManager::AdjustWindowBoundsWhenAdded(
Window* window) {
+ // Don't adjust window bounds if the bounds are empty as this
+ // happens when a new views::Widget is created.
+ // When a window is dragged and dropped onto a different
+ // root window, the bounds will be updated after they are added
+ // to the root window.
+ if (window->bounds().IsEmpty())
+ return;
+
if (!GetTrackedByWorkspace(window))
return;
@@ -261,9 +264,14 @@ void WorkspaceLayoutManager::AdjustWindowBoundsWhenAdded(
gfx::Rect bounds = window->bounds();
int min_width = bounds.width() * kMinimumPercentOnScreenArea;
int min_height = bounds.height() * kMinimumPercentOnScreenArea;
+ // Use entire display instead of workarea because the workarea can
+ // be further shrunk by the docked area. The logic ensures 30%
+ // visibility which should be enough to see where the window gets
+ // moved.
+ gfx::Rect display_area =
+ Shell::GetScreen()->GetDisplayNearestWindow(window).bounds();
ash::wm::AdjustBoundsToEnsureWindowVisibility(
- work_area_, min_width, min_height, &bounds);
-
+ display_area, min_width, min_height, &bounds);
if (window->bounds() != bounds)
window->SetBounds(bounds);
}
diff --git a/chromium/ash/wm/workspace/workspace_layout_manager_unittest.cc b/chromium/ash/wm/workspace/workspace_layout_manager_unittest.cc
index 3dce5b015c9..13cfdea04a3 100644
--- a/chromium/ash/wm/workspace/workspace_layout_manager_unittest.cc
+++ b/chromium/ash/wm/workspace/workspace_layout_manager_unittest.cc
@@ -304,6 +304,15 @@ TEST_F(WorkspaceLayoutManagerTest, WindowShouldBeOnScreenWhenAdded) {
EXPECT_GT(bounds.width(), out_window->bounds().width() * 0.29);
EXPECT_GT(bounds.height(), out_window->bounds().height() * 0.29);
+ aura::Window* parent = out_window->parent();
+ parent->RemoveChild(out_window.get());
+ out_window->SetBounds(gfx::Rect(-200, -200, 200, 200));
+ // UserHasChangedWindowPositionOrSize flag shouldn't turn off this behavior.
+ wm::SetUserHasChangedWindowPositionOrSize(window.get(), true);
+ parent->AddChild(out_window.get());
+ EXPECT_GT(bounds.width(), out_window->bounds().width() * 0.29);
+ EXPECT_GT(bounds.height(), out_window->bounds().height() * 0.29);
+
// Make sure we always make more than 1/3 of the window edge visible even
// if the initial bounds intersects with display.
window_bounds.SetRect(-150, -150, 200, 200);
diff --git a/chromium/ash/wm/workspace/workspace_window_resizer.cc b/chromium/ash/wm/workspace/workspace_window_resizer.cc
index 4b8c0aaf7e9..2143e45668b 100644
--- a/chromium/ash/wm/workspace/workspace_window_resizer.cc
+++ b/chromium/ash/wm/workspace/workspace_window_resizer.cc
@@ -87,13 +87,8 @@ scoped_ptr<WindowResizer> CreateWindowResizer(
window_resizer = PanelWindowResizer::Create(
window_resizer, window, point_in_parent, window_component, source);
}
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kAshEnableDockedWindows) &&
- window_resizer && window->parent() &&
- (window->parent()->id() == internal::kShellWindowId_DefaultContainer ||
- window->parent()->id() == internal::kShellWindowId_DockedContainer ||
- window->parent()->id() == internal::kShellWindowId_PanelContainer)) {
- window_resizer = internal::DockedWindowResizer::Create(
+ if (window_resizer) {
+ window_resizer = DockedWindowResizer::Create(
window_resizer, window, point_in_parent, window_component, source);
}
return make_scoped_ptr<WindowResizer>(window_resizer);
@@ -103,6 +98,10 @@ namespace internal {
namespace {
+// Distance in pixels that the cursor must move past an edge for a window
+// to move or resize beyond that edge.
+const int kStickyDistancePixels = 64;
+
// Snapping distance used instead of WorkspaceWindowResizer::kScreenEdgeInset
// when resizing a window using touchscreen.
const int kScreenEdgeInsetForTouchResize = 32;
@@ -117,7 +116,7 @@ bool ShouldStickToEdge(int distance_from_edge, int sticky_size) {
distance_from_edge > -sticky_size;
}
return distance_from_edge < sticky_size &&
- distance_from_edge > -sticky_size * 2;
+ distance_from_edge > -sticky_size * 2;
}
// Returns the coordinate along the secondary axis to snap to.
@@ -260,9 +259,6 @@ const int WorkspaceWindowResizer::kMinOnscreenHeight = 32;
// static
const int WorkspaceWindowResizer::kScreenEdgeInset = 8;
-// static
-const int WorkspaceWindowResizer::kStickyDistancePixels = 64;
-
// Represents the width or height of a window with constraints on its minimum
// and maximum size. 0 represents a lack of a constraint.
class WindowSize {
@@ -509,7 +505,7 @@ gfx::Rect WorkspaceWindowResizer::GetFinalBounds(
const gfx::Rect& bounds) const {
if (snap_phantom_window_controller_.get() &&
snap_phantom_window_controller_->IsShowing()) {
- return snap_phantom_window_controller_->bounds_in_screen();
+ return snap_phantom_window_controller_->bounds();
}
return bounds;
}
@@ -750,12 +746,8 @@ void WorkspaceWindowResizer::AdjustBoundsForMainWindow(
}
if (sticky_size > 0) {
- // Possibly stick to edge except when a mouse pointer is outside the
- // work area.
- if (!(display.work_area().Contains(last_mouse_location_in_screen) &&
- StickToWorkAreaOnMove(work_area, sticky_size, bounds))) {
+ if (!StickToWorkAreaOnMove(work_area, sticky_size, bounds))
MagneticallySnapToOtherWindows(bounds);
- }
}
} else if (sticky_size > 0) {
MagneticallySnapResizeToOtherWindows(bounds);
diff --git a/chromium/ash/wm/workspace/workspace_window_resizer.h b/chromium/ash/wm/workspace/workspace_window_resizer.h
index 76176b1a2b4..61f18969cbc 100644
--- a/chromium/ash/wm/workspace/workspace_window_resizer.h
+++ b/chromium/ash/wm/workspace/workspace_window_resizer.h
@@ -41,10 +41,6 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer {
// this close to an edge of the screen it snaps to the edge.
static const int kScreenEdgeInset;
- // Distance in pixels that the cursor must move past an edge for a window
- // to move or resize beyond that edge.
- static const int kStickyDistancePixels;
-
virtual ~WorkspaceWindowResizer();
static WorkspaceWindowResizer* Create(
@@ -69,7 +65,6 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer {
private:
FRIEND_TEST_ALL_PREFIXES(WorkspaceWindowResizerTest, CancelSnapPhantom);
FRIEND_TEST_ALL_PREFIXES(WorkspaceWindowResizerTest, PhantomSnapMaxSize);
- FRIEND_TEST_ALL_PREFIXES(WorkspaceWindowResizerTest, PhantomWindowShow);
// Type of snapping.
enum SnapType {
diff --git a/chromium/ash/wm/workspace/workspace_window_resizer_unittest.cc b/chromium/ash/wm/workspace/workspace_window_resizer_unittest.cc
index 8459c54ef5f..a00d0121429 100644
--- a/chromium/ash/wm/workspace/workspace_window_resizer_unittest.cc
+++ b/chromium/ash/wm/workspace/workspace_window_resizer_unittest.cc
@@ -30,36 +30,6 @@
#include "ui/gfx/screen.h"
#include "ui/views/widget/widget.h"
-namespace ui {
-
-// Class to provide access to SlideAnimation internals for testing.
-class SlideAnimation::TestApi {
- public:
- explicit TestApi(SlideAnimation* animation) : animation_(animation) {}
-
- void SetStartTime(base::TimeTicks ticks) {
- animation_->SetStartTime(ticks);
- }
-
- void Step(base::TimeTicks ticks) {
- animation_->Step(ticks);
- }
-
- void RunTillComplete() {
- SetStartTime(base::TimeTicks());
- Step(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(animation_->GetSlideDuration()));
- EXPECT_EQ(1.0, animation_->GetCurrentValue());
- }
-
- private:
- SlideAnimation* animation_;
-
- DISALLOW_COPY_AND_ASSIGN(TestApi);
-};
-
-}
-
namespace ash {
namespace internal {
namespace {
@@ -200,12 +170,6 @@ class WorkspaceWindowResizerTest : public test::AshTestBase {
touch_resize_window_->set_hit_test_bounds_override_inner(mouse_insets);
}
- // Simulate running the animation.
- void RunAnimationTillComplete(ui::SlideAnimation* animation) {
- ui::SlideAnimation::TestApi test_api(animation);
- test_api.RunTillComplete();
- }
-
TestWindowDelegate delegate_;
TestWindowDelegate delegate2_;
TestWindowDelegate delegate3_;
@@ -878,12 +842,8 @@ TEST_F(WorkspaceWindowResizerTest, SnapToEdge) {
Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()->
SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
window_->SetBounds(gfx::Rect(96, 112, 320, 160));
- // Click 50px to the right so that the mouse pointer does not leave the
- // workspace ensuring sticky behavior.
scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
- window_.get(),
- window_->bounds().origin() + gfx::Vector2d(50, 0),
- HTCAPTION,
+ window_.get(), gfx::Point(), HTCAPTION,
aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
ASSERT_TRUE(resizer.get());
// Move to an x-coordinate of 15, which should not snap.
@@ -998,12 +958,8 @@ TEST_F(WorkspaceWindowResizerTestSticky, StickToEdge) {
Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()->
SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
window_->SetBounds(gfx::Rect(96, 112, 320, 160));
- // Click 50px to the right so that the mouse pointer does not leave the
- // workspace ensuring sticky behavior.
scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
- window_.get(),
- window_->bounds().origin() + gfx::Vector2d(50, 0),
- HTCAPTION,
+ window_.get(), gfx::Point(), HTCAPTION,
aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
ASSERT_TRUE(resizer.get());
// Move to an x-coordinate of 15, which should not stick.
@@ -1038,22 +994,6 @@ TEST_F(WorkspaceWindowResizerTestSticky, StickToEdge) {
// No need to test dragging < 0 as we force that to 0.
}
-// Verifies not sticking to edges when a mouse pointer is outside of work area.
-TEST_F(WorkspaceWindowResizerTestSticky, NoStickToEdgeWhenOutside) {
- Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()->
- SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
- window_->SetBounds(gfx::Rect(96, 112, 320, 160));
- scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
- window_.get(), gfx::Point(), HTCAPTION,
- aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
- ASSERT_TRUE(resizer.get());
- // Move to an x-coordinate of 15, which should not stick.
- resizer->Drag(CalculateDragPoint(*resizer, 15 - 96, 0), 0);
- // Move to -15, should still stick to 0.
- resizer->Drag(CalculateDragPoint(*resizer, -15 - 96, 0), 0);
- EXPECT_EQ("-15,112 320x160", window_->bounds().ToString());
-}
-
// Verifies a resize sticks when dragging TOPLEFT.
TEST_F(WorkspaceWindowResizerTestSticky, StickToWorkArea_TOPLEFT) {
window_->SetBounds(gfx::Rect(100, 200, 20, 30));
@@ -1865,114 +1805,5 @@ TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_BOTTOM) {
EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 100).ToString(),
touch_resize_window_->bounds().ToString());
}
-
-TEST_F(WorkspaceWindowResizerTest, PhantomWindowShow) {
- if (!SupportsMultipleDisplays())
- return;
-
- UpdateDisplay("500x400,500x400");
- window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
- Shell::GetScreen()->GetPrimaryDisplay());
- Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
- EXPECT_EQ(root_windows[0], window_->GetRootWindow());
-
- scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
- window_.get(), gfx::Point(), HTCAPTION,
- aura::client::WINDOW_MOVE_SOURCE_MOUSE, empty_windows()));
- ASSERT_TRUE(resizer.get());
- EXPECT_FALSE(resizer->snap_phantom_window_controller_.get());
-
- // The pointer is on the edge but not shared. The snap phantom window
- // controller should be non-NULL.
- resizer->Drag(CalculateDragPoint(*resizer, 499, 0), 0);
- EXPECT_TRUE(resizer->snap_phantom_window_controller_.get());
- PhantomWindowController* phantom_controller(
- resizer->snap_phantom_window_controller_.get());
-
- // phantom widget only in the left screen.
- phantom_controller->Show(gfx::Rect(100, 100, 50, 60));
- EXPECT_TRUE(phantom_controller->phantom_widget_);
- EXPECT_FALSE(phantom_controller->phantom_widget_start_);
- EXPECT_EQ(
- root_windows[0],
- phantom_controller->phantom_widget_->GetNativeWindow()->GetRootWindow());
-
- // Move phantom widget into the right screen. Test that 2 widgets got created.
- phantom_controller->Show(gfx::Rect(600, 100, 50, 60));
- EXPECT_TRUE(phantom_controller->phantom_widget_);
- EXPECT_TRUE(phantom_controller->phantom_widget_start_);
- EXPECT_EQ(
- root_windows[1],
- phantom_controller->phantom_widget_->GetNativeWindow()->GetRootWindow());
- EXPECT_EQ(
- root_windows[0],
- phantom_controller->phantom_widget_start_->GetNativeWindow()->
- GetRootWindow());
- RunAnimationTillComplete(phantom_controller->animation_.get());
-
- // Move phantom widget only in the right screen. Start widget should close.
- phantom_controller->Show(gfx::Rect(700, 100, 50, 60));
- EXPECT_TRUE(phantom_controller->phantom_widget_);
- EXPECT_FALSE(phantom_controller->phantom_widget_start_);
- EXPECT_EQ(
- root_windows[1],
- phantom_controller->phantom_widget_->GetNativeWindow()->GetRootWindow());
- RunAnimationTillComplete(phantom_controller->animation_.get());
-
- // Move phantom widget into the left screen. Start widget should open.
- phantom_controller->Show(gfx::Rect(100, 100, 50, 60));
- EXPECT_TRUE(phantom_controller->phantom_widget_);
- EXPECT_TRUE(phantom_controller->phantom_widget_start_);
- EXPECT_EQ(
- root_windows[0],
- phantom_controller->phantom_widget_->GetNativeWindow()->GetRootWindow());
- EXPECT_EQ(
- root_windows[1],
- phantom_controller->phantom_widget_start_->GetNativeWindow()->
- GetRootWindow());
- RunAnimationTillComplete(phantom_controller->animation_.get());
-
- // Move phantom widget while in the left screen. Start widget should close.
- phantom_controller->Show(gfx::Rect(200, 100, 50, 60));
- EXPECT_TRUE(phantom_controller->phantom_widget_);
- EXPECT_FALSE(phantom_controller->phantom_widget_start_);
- EXPECT_EQ(
- root_windows[0],
- phantom_controller->phantom_widget_->GetNativeWindow()->GetRootWindow());
- RunAnimationTillComplete(phantom_controller->animation_.get());
-
- // Move phantom widget spanning both screens with most of the window in the
- // right screen. Two widgets are created.
- phantom_controller->Show(gfx::Rect(495, 100, 50, 60));
- EXPECT_TRUE(phantom_controller->phantom_widget_);
- EXPECT_TRUE(phantom_controller->phantom_widget_start_);
- EXPECT_EQ(
- root_windows[1],
- phantom_controller->phantom_widget_->GetNativeWindow()->GetRootWindow());
- EXPECT_EQ(
- root_windows[0],
- phantom_controller->phantom_widget_start_->GetNativeWindow()->
- GetRootWindow());
- RunAnimationTillComplete(phantom_controller->animation_.get());
-
- // Move phantom widget back into the left screen. Phantom widgets should swap.
- phantom_controller->Show(gfx::Rect(200, 100, 50, 60));
- EXPECT_TRUE(phantom_controller->phantom_widget_);
- EXPECT_TRUE(phantom_controller->phantom_widget_start_);
- EXPECT_EQ(
- root_windows[0],
- phantom_controller->phantom_widget_->GetNativeWindow()->GetRootWindow());
- EXPECT_EQ(
- root_windows[1],
- phantom_controller->phantom_widget_start_->GetNativeWindow()->
- GetRootWindow());
- RunAnimationTillComplete(phantom_controller->animation_.get());
-
- // Hide phantom controller. Both widgets should close.
- phantom_controller->Hide();
- EXPECT_FALSE(phantom_controller->phantom_widget_);
- EXPECT_FALSE(phantom_controller->phantom_widget_start_);
-}
-
} // namespace internal
} // namespace ash
diff --git a/chromium/ash/wm/workspace_controller.cc b/chromium/ash/wm/workspace_controller.cc
index 7fbbda2f7af..e2ee3f5c222 100644
--- a/chromium/ash/wm/workspace_controller.cc
+++ b/chromium/ash/wm/workspace_controller.cc
@@ -39,6 +39,8 @@ WorkspaceController::WorkspaceController(aura::Window* viewport)
event_handler_(new WorkspaceEventHandler(viewport_)) {
SetWindowVisibilityAnimationTransition(
viewport_, views::corewm::ANIMATE_NONE);
+ // Do this so when animating out windows don't extend beyond the bounds.
+ viewport_->layer()->SetMasksToBounds(true);
// The layout-manager cannot be created in the initializer list since it
// depends on the window to have been initialized.
diff --git a/chromium/ash/wm/workspace_controller_unittest.cc b/chromium/ash/wm/workspace_controller_unittest.cc
index 7dca75a08ba..f6a4ffb0ef2 100644
--- a/chromium/ash/wm/workspace_controller_unittest.cc
+++ b/chromium/ash/wm/workspace_controller_unittest.cc
@@ -1118,16 +1118,8 @@ class DragMaximizedNonTrackedWindowObserver
}
// aura::WindowObserver overrides:
- // Counts number of times a window is reparented. Ignores reparenting into and
- // from a docked container which is expected when a tab is dragged.
virtual void OnWindowHierarchyChanged(
const HierarchyChangeParams& params) OVERRIDE {
- if ((params.old_parent->id() == kShellWindowId_DefaultContainer &&
- params.new_parent->id() == kShellWindowId_DockedContainer) ||
- (params.old_parent->id() == kShellWindowId_DockedContainer &&
- params.new_parent->id() == kShellWindowId_DefaultContainer)) {
- return;
- }
change_count_++;
}