summaryrefslogtreecommitdiffstats
path: root/ash
diff options
context:
space:
mode:
authormazda@chromium.org <mazda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-06 23:03:42 +0000
committermazda@chromium.org <mazda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-06 23:03:42 +0000
commit309d43a835d5cee3d197e6a463191cb75dbd7833 (patch)
tree6d4ad1ac00946764f6ce0ad8de57ff0bc4dabfae /ash
parent19646afca54936d548c7d520aa78211d22d036df (diff)
downloadchromium_src-309d43a835d5cee3d197e6a463191cb75dbd7833.zip
chromium_src-309d43a835d5cee3d197e6a463191cb75dbd7833.tar.gz
chromium_src-309d43a835d5cee3d197e6a463191cb75dbd7833.tar.bz2
Extract the code for supporing extended desktop from WorkspaceWindowResizer into DragWindowResizer.
DragWindowResizer decorates another WindowResizer and adds the ability to move a window across displays. This CL depends on https://codereview.chromium.org/11280283/. BUG=156519 Review URL: https://chromiumcodereview.appspot.com/11411344 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@171624 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r--ash/ash.gyp3
-rw-r--r--ash/display/mouse_cursor_event_filter.h4
-rw-r--r--ash/wm/drag_window_controller.h2
-rw-r--r--ash/wm/drag_window_resizer.cc196
-rw-r--r--ash/wm/drag_window_resizer.h77
-rw-r--r--ash/wm/drag_window_resizer_unittest.cc354
-rw-r--r--ash/wm/window_resizer.h2
-rw-r--r--ash/wm/workspace/workspace_window_resizer.cc152
-rw-r--r--ash/wm/workspace/workspace_window_resizer.h35
-rw-r--r--ash/wm/workspace/workspace_window_resizer_unittest.cc293
10 files changed, 656 insertions, 462 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp
index d888b3f..69a4917 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -301,6 +301,8 @@
'wm/dialog_frame_view.h',
'wm/drag_window_controller.cc',
'wm/drag_window_controller.h',
+ 'wm/drag_window_resizer.cc',
+ 'wm/drag_window_resizer.h',
'wm/event_client_impl.cc',
'wm/event_client_impl.h',
'wm/event_rewriter_event_filter.cc',
@@ -566,6 +568,7 @@
'wm/base_layout_manager_unittest.cc',
'wm/cursor_manager_unittest.cc',
'wm/custom_frame_view_ash_unittest.cc',
+ 'wm/drag_window_resizer_unittest.cc',
'wm/frame_painter_unittest.cc',
'wm/panel_layout_manager_unittest.cc',
'wm/power_button_controller_unittest.cc',
diff --git a/ash/display/mouse_cursor_event_filter.h b/ash/display/mouse_cursor_event_filter.h
index a1be91c..27835bb 100644
--- a/ash/display/mouse_cursor_event_filter.h
+++ b/ash/display/mouse_cursor_event_filter.h
@@ -61,8 +61,8 @@ class ASH_EXPORT MouseCursorEventFilter : public ui::EventHandler {
FRIEND_TEST_ALL_PREFIXES(MouseCursorEventFilterTest,
IndicatorBoundsTestOnTopBottom);
FRIEND_TEST_ALL_PREFIXES(MouseCursorEventFilterTest, CursorDeviceScaleFactor);
- FRIEND_TEST_ALL_PREFIXES(WorkspaceWindowResizerTest, WarpMousePointer);
- FRIEND_TEST_ALL_PREFIXES(WorkspaceWindowResizerTest, CursorDeviceScaleFactor);
+ FRIEND_TEST_ALL_PREFIXES(DragWindowResizerTest, WarpMousePointer);
+ FRIEND_TEST_ALL_PREFIXES(DragWindowResizerTest, CursorDeviceScaleFactor);
// Warps the mouse cursor to an alternate root window when the
// |point_in_screen|, which is the location of the mouse cursor,
diff --git a/ash/wm/drag_window_controller.h b/ash/wm/drag_window_controller.h
index 41eebd9..08e115d 100644
--- a/ash/wm/drag_window_controller.h
+++ b/ash/wm/drag_window_controller.h
@@ -54,7 +54,7 @@ class ASH_EXPORT DragWindowController {
void SetOpacity(float opacity);
private:
- FRIEND_TEST_ALL_PREFIXES(WorkspaceWindowResizerTest, DragWindowController);
+ FRIEND_TEST_ALL_PREFIXES(DragWindowResizerTest, DragWindowController);
// Creates and shows the |drag_widget_| at |bounds|.
// |layer| is shown on top of the drag window if it is non-NULL.
diff --git a/ash/wm/drag_window_resizer.cc b/ash/wm/drag_window_resizer.cc
new file mode 100644
index 0000000..cbe8fe4
--- /dev/null
+++ b/ash/wm/drag_window_resizer.cc
@@ -0,0 +1,196 @@
+// 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/drag_window_resizer.h"
+
+#include "ash/display/mouse_cursor_event_filter.h"
+#include "ash/screen_ash.h"
+#include "ash/shell.h"
+#include "ash/wm/coordinate_conversion.h"
+#include "ash/wm/cursor_manager.h"
+#include "ash/wm/drag_window_controller.h"
+#include "ash/wm/property_util.h"
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/env.h"
+#include "ui/aura/root_window.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_delegate.h"
+#include "ui/base/hit_test.h"
+#include "ui/base/ui_base_types.h"
+#include "ui/gfx/screen.h"
+
+namespace ash {
+namespace internal {
+
+namespace {
+
+// The maximum opacity of the drag phantom window.
+const float kMaxOpacity = 0.8f;
+
+// Returns true if Ash has more than one root window.
+bool HasSecondaryRootWindow() {
+ return Shell::GetAllRootWindows().size() > 1;
+}
+
+// When there are two root windows, returns one of the root windows which is not
+// |root_window|. Returns NULL if only one root window exists.
+aura::RootWindow* GetAnotherRootWindow(aura::RootWindow* root_window) {
+ Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
+ if (root_windows.size() < 2)
+ return NULL;
+ DCHECK_EQ(2U, root_windows.size());
+ if (root_windows[0] == root_window)
+ return root_windows[1];
+ return root_windows[0];
+}
+
+}
+
+DragWindowResizer::~DragWindowResizer() {
+ Shell* shell = Shell::GetInstance();
+ shell->mouse_cursor_filter()->set_mouse_warp_mode(
+ MouseCursorEventFilter::WARP_ALWAYS);
+ shell->mouse_cursor_filter()->HideSharedEdgeIndicator();
+
+ if (destroyed_)
+ *destroyed_ = true;
+}
+
+// static
+DragWindowResizer* DragWindowResizer::Create(WindowResizer* window_resizer,
+ aura::Window* window,
+ const gfx::Point& location,
+ int window_component) {
+ Details details(window, location, window_component);
+ return details.is_resizable ?
+ new DragWindowResizer(window_resizer, details) : NULL;
+}
+
+void DragWindowResizer::Drag(const gfx::Point& location, int event_flags) {
+ bool destroyed = false;
+ destroyed_ = &destroyed;
+ window_resizer_->Drag(location, event_flags);
+ if (destroyed)
+ return;
+ destroyed_ = NULL;
+ last_mouse_location_ = location;
+
+ // Show a phantom window for dragging in another root window.
+ if (HasSecondaryRootWindow()) {
+ gfx::Point location_in_screen = location;
+ wm::ConvertPointToScreen(GetTarget()->parent(), &location_in_screen);
+ const bool in_original_root =
+ wm::GetRootWindowAt(location_in_screen) == GetTarget()->GetRootWindow();
+ UpdateDragWindow(GetTarget()->bounds(), in_original_root);
+ } else {
+ drag_window_controller_.reset();
+ }
+}
+
+void DragWindowResizer::CompleteDrag(int event_flags) {
+ window_resizer_->CompleteDrag(event_flags);
+
+ GetTarget()->layer()->SetOpacity(details_.initial_opacity);
+ drag_window_controller_.reset();
+
+ // Check if the destination is another display.
+ gfx::Point last_mouse_location_in_screen = last_mouse_location_;
+ wm::ConvertPointToScreen(GetTarget()->parent(),
+ &last_mouse_location_in_screen);
+ gfx::Screen* screen = Shell::GetScreen();
+ const gfx::Display dst_display =
+ screen->GetDisplayNearestPoint(last_mouse_location_in_screen);
+
+ if (dst_display.id() !=
+ screen->GetDisplayNearestWindow(GetTarget()->GetRootWindow()).id()) {
+ const gfx::Rect dst_bounds =
+ ScreenAsh::ConvertRectToScreen(GetTarget()->parent(),
+ GetTarget()->bounds());
+ GetTarget()->SetBoundsInScreen(dst_bounds, dst_display);
+ }
+}
+
+void DragWindowResizer::RevertDrag() {
+ window_resizer_->RevertDrag();
+
+ drag_window_controller_.reset();
+ GetTarget()->layer()->SetOpacity(details_.initial_opacity);
+}
+
+aura::Window* DragWindowResizer::GetTarget() {
+ return window_resizer_->GetTarget();
+}
+
+DragWindowResizer::DragWindowResizer(WindowResizer* window_resizer,
+ const Details& details)
+ : window_resizer_(window_resizer),
+ details_(details),
+ destroyed_(NULL) {
+ // The pointer should be confined in one display during resizing a window
+ // because the window cannot span two displays at the same time anyway. The
+ // exception is window/tab dragging operation. During that operation,
+ // |mouse_warp_mode_| should be set to WARP_DRAG so that the user could move a
+ // window/tab to another display.
+ MouseCursorEventFilter* mouse_cursor_filter =
+ Shell::GetInstance()->mouse_cursor_filter();
+ mouse_cursor_filter->set_mouse_warp_mode(
+ ShouldAllowMouseWarp() ?
+ MouseCursorEventFilter::WARP_DRAG : MouseCursorEventFilter::WARP_NONE);
+ if (ShouldAllowMouseWarp()) {
+ mouse_cursor_filter->ShowSharedEdgeIndicator(
+ details.window->GetRootWindow());
+ }
+}
+
+void DragWindowResizer::UpdateDragWindow(const gfx::Rect& bounds,
+ bool in_original_root) {
+ if (details_.window_component != HTCAPTION || !ShouldAllowMouseWarp())
+ return;
+
+ // It's available. Show a phantom window on the display if needed.
+ aura::RootWindow* another_root =
+ GetAnotherRootWindow(GetTarget()->GetRootWindow());
+ const gfx::Rect root_bounds_in_screen(another_root->GetBoundsInScreen());
+ const gfx::Rect bounds_in_screen =
+ ScreenAsh::ConvertRectToScreen(GetTarget()->parent(), bounds);
+ gfx::Rect bounds_in_another_root =
+ gfx::IntersectRects(root_bounds_in_screen, bounds_in_screen);
+ const float fraction_in_another_window =
+ (bounds_in_another_root.width() * bounds_in_another_root.height()) /
+ static_cast<float>(bounds.width() * bounds.height());
+
+ if (fraction_in_another_window > 0) {
+ if (!drag_window_controller_.get()) {
+ drag_window_controller_.reset(
+ new DragWindowController(GetTarget()));
+ // Always show the drag phantom on the |another_root| window.
+ drag_window_controller_->SetDestinationDisplay(
+ Shell::GetScreen()->GetDisplayMatching(
+ another_root->GetBoundsInScreen()));
+ drag_window_controller_->Show();
+ } else {
+ // No animation.
+ drag_window_controller_->SetBounds(bounds_in_screen);
+ }
+ const float phantom_opacity =
+ !in_original_root ? 1 : (kMaxOpacity * fraction_in_another_window);
+ const float window_opacity =
+ in_original_root ? 1 : (kMaxOpacity * (1 - fraction_in_another_window));
+ drag_window_controller_->SetOpacity(phantom_opacity);
+ GetTarget()->layer()->SetOpacity(window_opacity);
+ } else {
+ drag_window_controller_.reset();
+ GetTarget()->layer()->SetOpacity(1.0f);
+ }
+}
+
+bool DragWindowResizer::ShouldAllowMouseWarp() {
+ return (details_.window_component == HTCAPTION) &&
+ (GetTarget()->GetProperty(aura::client::kModalKey) ==
+ ui::MODAL_TYPE_NONE) &&
+ (GetTarget()->type() == aura::client::WINDOW_TYPE_NORMAL);
+}
+
+} // namespace internal
+} // namespace ash
diff --git a/ash/wm/drag_window_resizer.h b/ash/wm/drag_window_resizer.h
new file mode 100644
index 0000000..3705bac
--- /dev/null
+++ b/ash/wm/drag_window_resizer.h
@@ -0,0 +1,77 @@
+// 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_DRAG_WINDOW_RESIZER_H_
+#define ASH_WM_DRAG_WINDOW_RESIZER_H_
+
+#include "ash/wm/window_resizer.h"
+#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
+#include "ui/gfx/point.h"
+
+namespace ash {
+namespace internal {
+
+class DragWindowController;
+
+// DragWindowResizer is a decorator of WindowResizer and adds the ability to
+// drag windows across displays.
+class ASH_EXPORT DragWindowResizer : public WindowResizer {
+ public:
+ virtual ~DragWindowResizer();
+
+ // Creates a new DragWindowResizer. The caller takes ownership of the
+ // returned object. The ownership of |window_resizer| is taken by the
+ // returned object. Returns NULL if not resizable.
+ static DragWindowResizer* Create(WindowResizer* window_resizer,
+ aura::Window* window,
+ const gfx::Point& location,
+ int window_component);
+
+ // WindowResizer overides:
+ virtual void Drag(const gfx::Point& location, int event_flags) OVERRIDE;
+ virtual void CompleteDrag(int event_flags) OVERRIDE;
+ virtual void RevertDrag() OVERRIDE;
+ virtual aura::Window* GetTarget() OVERRIDE;
+
+ const gfx::Point& GetInitialLocationInParentForTest() const {
+ return details_.initial_location_in_parent;
+ }
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(DragWindowResizerTest, DragWindowController);
+
+ // Creates DragWindowResizer that adds the ability of dragging windows across
+ // displays to |window_resizer|. This object takes the ownership of
+ // |window_resizer|.
+ explicit DragWindowResizer(WindowResizer* window_resizer,
+ const Details& details);
+
+ // Updates the bounds of the phantom window for window dragging. Set true on
+ // |in_original_root| if the pointer is still in |window()->GetRootWindow()|.
+ void UpdateDragWindow(const gfx::Rect& bounds, bool in_original_root);
+
+ // Returns true if we should allow the mouse pointer to warp.
+ bool ShouldAllowMouseWarp();
+
+ scoped_ptr<WindowResizer> window_resizer_;
+
+ // Shows a semi-transparent image of the window being dragged.
+ scoped_ptr<DragWindowController> drag_window_controller_;
+
+ const Details details_;
+
+ gfx::Point last_mouse_location_;
+
+ // If non-NULL the destructor sets this to true. Used to determine if this has
+ // been deleted.
+ bool* destroyed_;
+
+ DISALLOW_COPY_AND_ASSIGN(DragWindowResizer);
+};
+
+} // namespace internal
+} // namespace aura
+
+#endif // ASH_WM_DRAG_WINDOW_RESIZER_H_
diff --git a/ash/wm/drag_window_resizer_unittest.cc b/ash/wm/drag_window_resizer_unittest.cc
new file mode 100644
index 0000000..2877bc5
--- /dev/null
+++ b/ash/wm/drag_window_resizer_unittest.cc
@@ -0,0 +1,354 @@
+// 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/drag_window_resizer.h"
+
+#include "ash/display/mouse_cursor_event_filter.h"
+#include "ash/root_window_controller.h"
+#include "ash/shell.h"
+#include "ash/shell_window_ids.h"
+#include "ash/test/ash_test_base.h"
+#include "ash/test/cursor_manager_test_api.h"
+#include "ash/wm/cursor_manager.h"
+#include "ash/wm/drag_window_controller.h"
+#include "ash/wm/shelf_layout_manager.h"
+#include "base/stringprintf.h"
+#include "ui/aura/root_window.h"
+#include "ui/aura/test/test_window_delegate.h"
+#include "ui/base/hit_test.h"
+#include "ui/gfx/insets.h"
+#include "ui/gfx/screen.h"
+#include "ui/views/widget/widget.h"
+
+namespace ash {
+namespace internal {
+namespace {
+
+const int kRootHeight = 600;
+
+} // namespace
+
+class DragWindowResizerTest : public test::AshTestBase {
+ public:
+ DragWindowResizerTest() : window_(NULL) {}
+ virtual ~DragWindowResizerTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ AshTestBase::SetUp();
+ UpdateDisplay(StringPrintf("800x%d", kRootHeight));
+
+ aura::RootWindow* root = Shell::GetPrimaryRootWindow();
+ gfx::Rect root_bounds(root->bounds());
+ EXPECT_EQ(kRootHeight, root_bounds.height());
+ EXPECT_EQ(800, root_bounds.width());
+ Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
+ window_.reset(new aura::Window(&delegate_));
+ window_->SetType(aura::client::WINDOW_TYPE_NORMAL);
+ window_->Init(ui::LAYER_NOT_DRAWN);
+ SetDefaultParentByPrimaryRootWindow(window_.get());
+ window_->set_id(1);
+ }
+
+ virtual void TearDown() OVERRIDE {
+ window_.reset();
+ AshTestBase::TearDown();
+ }
+
+ protected:
+ gfx::Point CalculateDragPoint(const DragWindowResizer& resizer,
+ int delta_x,
+ int delta_y) const {
+ gfx::Point location = resizer.GetInitialLocationInParentForTest();
+ location.set_x(location.x() + delta_x);
+ location.set_y(location.y() + delta_y);
+ return location;
+ }
+
+ internal::ShelfLayoutManager* shelf_layout_manager() {
+ return Shell::GetPrimaryRootWindowController()->shelf();
+ }
+
+ static DragWindowResizer* CreateDragWindowResizer(
+ aura::Window* window,
+ const gfx::Point& point_in_parent,
+ int window_component) {
+ return static_cast<DragWindowResizer*>(CreateWindowResizer(
+ window, point_in_parent, window_component).release());
+ }
+
+ aura::test::TestWindowDelegate delegate_;
+ scoped_ptr<aura::Window> window_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DragWindowResizerTest);
+};
+
+// Verifies a window can be moved from the primary display to another.
+TEST_F(DragWindowResizerTest, WindowDragWithMultiDisplays) {
+ // The secondary display is logically on the right, but on the system (e.g. X)
+ // layer, it's below the primary one. See UpdateDisplay() in ash_test_base.cc.
+ UpdateDisplay("800x600,800x600");
+ shelf_layout_manager()->LayoutShelf();
+ Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
+ ASSERT_EQ(2U, root_windows.size());
+
+ window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
+ Shell::GetScreen()->GetPrimaryDisplay());
+ EXPECT_EQ(root_windows[0], window_->GetRootWindow());
+ {
+ // Grab (0, 0) of the window.
+ scoped_ptr<DragWindowResizer> resizer(CreateDragWindowResizer(
+ window_.get(), gfx::Point(), HTCAPTION));
+ ASSERT_TRUE(resizer.get());
+ // Drag the pointer to the right. Once it reaches the right edge of the
+ // primary display, it warps to the secondary.
+ resizer->Drag(CalculateDragPoint(*resizer, 800, 10), 0);
+ resizer->CompleteDrag(0);
+ // The whole window is on the secondary display now. The parent should be
+ // changed.
+ EXPECT_EQ(root_windows[1], window_->GetRootWindow());
+ EXPECT_EQ("0,10 50x60", window_->bounds().ToString());
+ }
+
+ window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
+ Shell::GetScreen()->GetPrimaryDisplay());
+ EXPECT_EQ(root_windows[0], window_->GetRootWindow());
+ {
+ // Grab (0, 0) of the window and move the pointer to (790, 10).
+ scoped_ptr<DragWindowResizer> resizer(CreateDragWindowResizer(
+ window_.get(), gfx::Point(), HTCAPTION));
+ ASSERT_TRUE(resizer.get());
+ resizer->Drag(CalculateDragPoint(*resizer, 790, 10), 0);
+ resizer->CompleteDrag(0);
+ // Since the pointer is still on the primary root window, the parent should
+ // not be changed.
+ EXPECT_EQ(root_windows[0], window_->GetRootWindow());
+ EXPECT_EQ("790,10 50x60", window_->bounds().ToString());
+ }
+
+ window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
+ Shell::GetScreen()->GetPrimaryDisplay());
+ EXPECT_EQ(root_windows[0], window_->GetRootWindow());
+ {
+ // Grab the top-right edge of the window and move the pointer to (0, 10)
+ // in the secondary root window's coordinates.
+ scoped_ptr<DragWindowResizer> resizer(CreateDragWindowResizer(
+ window_.get(), gfx::Point(49, 0), HTCAPTION));
+ ASSERT_TRUE(resizer.get());
+ resizer->Drag(CalculateDragPoint(*resizer, 751, 10), ui::EF_CONTROL_DOWN);
+ resizer->CompleteDrag(0);
+ // Since the pointer is on the secondary, the parent should be changed
+ // even though only small fraction of the window is within the secondary
+ // root window's bounds.
+ EXPECT_EQ(root_windows[1], window_->GetRootWindow());
+ EXPECT_EQ("-49,10 50x60", window_->bounds().ToString());
+ }
+}
+
+// Verifies a window can be moved from the secondary display to primary.
+TEST_F(DragWindowResizerTest, WindowDragWithMultiDisplaysRightToLeft) {
+ UpdateDisplay("800x600,800x600");
+ shelf_layout_manager()->LayoutShelf();
+ Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
+ ASSERT_EQ(2U, root_windows.size());
+
+ window_->SetBoundsInScreen(
+ gfx::Rect(800, 00, 50, 60),
+ Shell::GetScreen()->GetDisplayNearestWindow(root_windows[1]));
+ EXPECT_EQ(root_windows[1], window_->GetRootWindow());
+ {
+ // Grab (0, 0) of the window.
+ scoped_ptr<DragWindowResizer> resizer(CreateDragWindowResizer(
+ window_.get(), gfx::Point(), HTCAPTION));
+ ASSERT_TRUE(resizer.get());
+ // Move the mouse near the right edge, (798, 0), of the primary display.
+ resizer->Drag(CalculateDragPoint(*resizer, -2, 0), ui::EF_CONTROL_DOWN);
+ resizer->CompleteDrag(0);
+ EXPECT_EQ(root_windows[0], window_->GetRootWindow());
+ EXPECT_EQ("798,0 50x60", window_->bounds().ToString());
+ }
+}
+
+// Verifies the drag window is shown correctly.
+TEST_F(DragWindowResizerTest, DragWindowController) {
+ UpdateDisplay("800x600,800x600");
+ Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
+ ASSERT_EQ(2U, root_windows.size());
+
+ window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
+ Shell::GetScreen()->GetPrimaryDisplay());
+ EXPECT_EQ(root_windows[0], window_->GetRootWindow());
+ EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity());
+ {
+ scoped_ptr<DragWindowResizer> resizer(CreateDragWindowResizer(
+ window_.get(), gfx::Point(), HTCAPTION));
+ ASSERT_TRUE(resizer.get());
+ EXPECT_FALSE(resizer->drag_window_controller_.get());
+
+ // The pointer is inside the primary root. The drag window controller
+ // should be NULL.
+ resizer->Drag(CalculateDragPoint(*resizer, 10, 10), 0);
+ EXPECT_FALSE(resizer->drag_window_controller_.get());
+
+ // The window spans both root windows.
+ resizer->Drag(CalculateDragPoint(*resizer, 798, 10), 0);
+ DragWindowController* controller =
+ resizer->drag_window_controller_.get();
+ ASSERT_TRUE(controller);
+
+ ASSERT_TRUE(controller->drag_widget_);
+ ui::Layer* drag_layer =
+ controller->drag_widget_->GetNativeWindow()->layer();
+ ASSERT_TRUE(drag_layer);
+ // Check if |resizer->layer_| is properly set to the drag widget.
+ const std::vector<ui::Layer*>& layers = drag_layer->children();
+ EXPECT_FALSE(layers.empty());
+ EXPECT_EQ(controller->layer_, layers.back());
+
+ // |window_| should be opaque since the pointer is still on the primary
+ // root window. The drag window should be semi-transparent.
+ EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity());
+ ASSERT_TRUE(controller->drag_widget_);
+ EXPECT_GT(1.0f, drag_layer->opacity());
+
+ // Enter the pointer to the secondary display.
+ resizer->Drag(CalculateDragPoint(*resizer, 800, 10), 0);
+ controller = resizer->drag_window_controller_.get();
+ ASSERT_TRUE(controller);
+ // |window_| should be transparent, and the drag window should be opaque.
+ EXPECT_GT(1.0f, window_->layer()->opacity());
+ EXPECT_FLOAT_EQ(1.0f, drag_layer->opacity());
+
+ resizer->CompleteDrag(0);
+ EXPECT_EQ(root_windows[1], window_->GetRootWindow());
+ EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity());
+ }
+
+ // Do the same test with RevertDrag().
+ window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
+ Shell::GetScreen()->GetPrimaryDisplay());
+ EXPECT_EQ(root_windows[0], window_->GetRootWindow());
+ EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity());
+ {
+ scoped_ptr<DragWindowResizer> resizer(CreateDragWindowResizer(
+ window_.get(), gfx::Point(), HTCAPTION));
+ ASSERT_TRUE(resizer.get());
+ EXPECT_FALSE(resizer->drag_window_controller_.get());
+
+ resizer->Drag(CalculateDragPoint(*resizer, 0, 610), 0);
+ resizer->RevertDrag();
+ EXPECT_EQ(root_windows[0], window_->GetRootWindow());
+ EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity());
+ }
+}
+
+// Verifies if the resizer sets and resets
+// MouseCursorEventFilter::mouse_warp_mode_ as expected.
+TEST_F(DragWindowResizerTest, WarpMousePointer) {
+ MouseCursorEventFilter* event_filter =
+ Shell::GetInstance()->mouse_cursor_filter();
+ ASSERT_TRUE(event_filter);
+ window_->SetBounds(gfx::Rect(0, 0, 50, 60));
+
+ EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS,
+ event_filter->mouse_warp_mode_);
+ {
+ scoped_ptr<DragWindowResizer> resizer(CreateDragWindowResizer(
+ window_.get(), gfx::Point(), HTCAPTION));
+ // While dragging a window, warp should be allowed.
+ EXPECT_EQ(MouseCursorEventFilter::WARP_DRAG,
+ event_filter->mouse_warp_mode_);
+ resizer->CompleteDrag(0);
+ }
+ EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS,
+ event_filter->mouse_warp_mode_);
+
+ {
+ scoped_ptr<DragWindowResizer> resizer(CreateDragWindowResizer(
+ window_.get(), gfx::Point(), HTCAPTION));
+ EXPECT_EQ(MouseCursorEventFilter::WARP_DRAG,
+ event_filter->mouse_warp_mode_);
+ resizer->RevertDrag();
+ }
+ EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS,
+ event_filter->mouse_warp_mode_);
+
+ {
+ scoped_ptr<DragWindowResizer> resizer(CreateDragWindowResizer(
+ window_.get(), gfx::Point(), HTRIGHT));
+ // While resizing a window, warp should NOT be allowed.
+ EXPECT_EQ(MouseCursorEventFilter::WARP_NONE,
+ event_filter->mouse_warp_mode_);
+ resizer->CompleteDrag(0);
+ }
+ EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS,
+ event_filter->mouse_warp_mode_);
+
+ {
+ scoped_ptr<DragWindowResizer> resizer(CreateDragWindowResizer(
+ window_.get(), gfx::Point(), HTRIGHT));
+ EXPECT_EQ(MouseCursorEventFilter::WARP_NONE,
+ event_filter->mouse_warp_mode_);
+ resizer->RevertDrag();
+ }
+ EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS,
+ event_filter->mouse_warp_mode_);
+}
+
+// Verifies cursor's device scale factor is updated whe a window is moved across
+// root windows with different device scale factors (http://crbug.com/154183).
+TEST_F(DragWindowResizerTest, CursorDeviceScaleFactor) {
+ // The secondary display is logically on the right, but on the system (e.g. X)
+ // layer, it's below the primary one. See UpdateDisplay() in ash_test_base.cc.
+ UpdateDisplay("400x400,800x800*2");
+ shelf_layout_manager()->LayoutShelf();
+ Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
+ ASSERT_EQ(2U, root_windows.size());
+
+ test::CursorManagerTestApi cursor_test_api(
+ Shell::GetInstance()->cursor_manager());
+ MouseCursorEventFilter* event_filter =
+ Shell::GetInstance()->mouse_cursor_filter();
+ // Move window from the root window with 1.0 device scale factor to the root
+ // window with 2.0 device scale factor.
+ {
+ window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
+ Shell::GetScreen()->GetPrimaryDisplay());
+ EXPECT_EQ(root_windows[0], window_->GetRootWindow());
+ // Grab (0, 0) of the window.
+ scoped_ptr<DragWindowResizer> resizer(CreateDragWindowResizer(
+ window_.get(), gfx::Point(), HTCAPTION));
+ EXPECT_EQ(1.0f, cursor_test_api.GetDeviceScaleFactor());
+ ASSERT_TRUE(resizer.get());
+ resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0);
+ event_filter->WarpMouseCursorIfNecessary(root_windows[0],
+ gfx::Point(399, 200));
+ EXPECT_EQ(2.0f, cursor_test_api.GetDeviceScaleFactor());
+ resizer->CompleteDrag(0);
+ EXPECT_EQ(2.0f, cursor_test_api.GetDeviceScaleFactor());
+ }
+
+ // Move window from the root window with 2.0 device scale factor to the root
+ // window with 1.0 device scale factor.
+ {
+ window_->SetBoundsInScreen(
+ gfx::Rect(600, 0, 50, 60),
+ Shell::GetScreen()->GetDisplayNearestWindow(root_windows[1]));
+ EXPECT_EQ(root_windows[1], window_->GetRootWindow());
+ // Grab (0, 0) of the window.
+ scoped_ptr<DragWindowResizer> resizer(CreateDragWindowResizer(
+ window_.get(), gfx::Point(), HTCAPTION));
+ EXPECT_EQ(2.0f, cursor_test_api.GetDeviceScaleFactor());
+ ASSERT_TRUE(resizer.get());
+ resizer->Drag(CalculateDragPoint(*resizer, -200, 200), 0);
+ event_filter->WarpMouseCursorIfNecessary(root_windows[1],
+ gfx::Point(400, 200));
+ EXPECT_EQ(1.0f, cursor_test_api.GetDeviceScaleFactor());
+ resizer->CompleteDrag(0);
+ EXPECT_EQ(1.0f, cursor_test_api.GetDeviceScaleFactor());
+ }
+}
+
+} // namespace internal
+} // namespace ash
diff --git a/ash/wm/window_resizer.h b/ash/wm/window_resizer.h
index d8c398f..bc46df8 100644
--- a/ash/wm/window_resizer.h
+++ b/ash/wm/window_resizer.h
@@ -124,7 +124,7 @@ class ASH_EXPORT WindowResizer {
// Creates a WindowResizer for |window|. This can return a scoped_ptr
// initialized with NULL if |window| should not be resized nor dragged.
-scoped_ptr<WindowResizer> CreateWindowResizer(
+ASH_EXPORT scoped_ptr<WindowResizer> CreateWindowResizer(
aura::Window* window,
const gfx::Point& point_in_parent,
int window_component);
diff --git a/ash/wm/workspace/workspace_window_resizer.cc b/ash/wm/workspace/workspace_window_resizer.cc
index 76b8e5a..62ef772 100644
--- a/ash/wm/workspace/workspace_window_resizer.cc
+++ b/ash/wm/workspace/workspace_window_resizer.cc
@@ -10,14 +10,13 @@
#include <vector>
#include "ash/display/display_controller.h"
-#include "ash/display/mouse_cursor_event_filter.h"
#include "ash/screen_ash.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/wm/coordinate_conversion.h"
#include "ash/wm/cursor_manager.h"
#include "ash/wm/default_window_resizer.h"
-#include "ash/wm/drag_window_controller.h"
+#include "ash/wm/drag_window_resizer.h"
#include "ash/wm/property_util.h"
#include "ash/wm/window_util.h"
#include "ash/wm/workspace/phantom_window_controller.h"
@@ -41,6 +40,7 @@ scoped_ptr<WindowResizer> CreateWindowResizer(aura::Window* window,
if (!wm::CanResizeWindow(window) && window_component != HTCAPTION)
return scoped_ptr<WindowResizer>();
+ WindowResizer* window_resizer = NULL;
if (window->parent() &&
window->parent()->id() == internal::kShellWindowId_WorkspaceContainer) {
// Allow dragging maximized windows if it's not tracked by workspace. This
@@ -48,19 +48,20 @@ scoped_ptr<WindowResizer> CreateWindowResizer(aura::Window* window,
if (!wm::IsWindowNormal(window) &&
(window_component != HTCAPTION || GetTrackedByWorkspace(window)))
return scoped_ptr<WindowResizer>();
- return make_scoped_ptr<WindowResizer>(
- internal::WorkspaceWindowResizer::Create(window,
- point_in_parent,
- window_component,
- std::vector<aura::Window*>()));
- } else if (wm::IsWindowNormal(window)) {
- return make_scoped_ptr<WindowResizer>(DefaultWindowResizer::Create(
+ window_resizer = internal::WorkspaceWindowResizer::Create(
window,
point_in_parent,
- window_component));
- } else {
- return scoped_ptr<WindowResizer>();
+ window_component,
+ std::vector<aura::Window*>());
+ } else if (wm::IsWindowNormal(window)) {
+ window_resizer = DefaultWindowResizer::Create(
+ window, point_in_parent, window_component);
+ }
+ if (window_resizer) {
+ window_resizer = internal::DragWindowResizer::Create(
+ window_resizer, window, point_in_parent, window_component);
}
+ return make_scoped_ptr<WindowResizer>(window_resizer);
}
namespace internal {
@@ -70,32 +71,12 @@ namespace {
// Duration of the animation when snapping the window into place.
const int kSnapDurationMS = 100;
-// The maximum opacity of the drag phantom window.
-const float kMaxOpacity = 0.8f;
-
// Returns true if should snap to the edge.
bool ShouldSnapToEdge(int distance_from_edge, int grid_size) {
return distance_from_edge < grid_size &&
distance_from_edge > -grid_size * 2;
}
-// Returns true if Ash has more than one root window.
-bool HasSecondaryRootWindow() {
- return Shell::GetAllRootWindows().size() > 1;
-}
-
-// When there are two root windows, returns one of the root windows which is not
-// |root_window|. Returns NULL if only one root window exists.
-aura::RootWindow* GetAnotherRootWindow(aura::RootWindow* root_window) {
- Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
- if (root_windows.size() < 2)
- return NULL;
- DCHECK_EQ(2U, root_windows.size());
- if (root_windows[0] == root_window)
- return root_windows[1];
- return root_windows[0];
-}
-
// Returns the coordinate along the secondary axis to snap to.
int CoordinateAlongSecondaryAxis(SecondaryMagnetismEdge edge,
int leading,
@@ -307,13 +288,7 @@ class WindowSize {
WorkspaceWindowResizer::~WorkspaceWindowResizer() {
Shell* shell = Shell::GetInstance();
- shell->mouse_cursor_filter()->set_mouse_warp_mode(
- MouseCursorEventFilter::WARP_ALWAYS);
- shell->mouse_cursor_filter()->HideSharedEdgeIndicator();
shell->cursor_manager()->UnlockCursor();
-
- if (destroyed_)
- *destroyed_ = true;
}
// static
@@ -362,26 +337,12 @@ void WorkspaceWindowResizer::Drag(const gfx::Point& location_in_parent,
if (!attached_windows_.empty())
LayoutAttachedWindows(&bounds);
- if (bounds != window()->bounds()) {
- bool destroyed = false;
- destroyed_ = &destroyed;
+ if (bounds != window()->bounds())
window()->SetBounds(bounds);
- if (destroyed)
- return;
- destroyed_ = NULL;
- }
- // Show a phantom window for dragging in another root window.
- if (HasSecondaryRootWindow())
- UpdateDragWindow(bounds, in_original_root);
- else
- drag_window_controller_.reset();
-
}
void WorkspaceWindowResizer::CompleteDrag(int event_flags) {
wm::SetUserHasChangedWindowPositionOrSize(details_.window, true);
- window()->layer()->SetOpacity(details_.initial_opacity);
- drag_window_controller_.reset();
snap_phantom_window_controller_.reset();
if (!did_move_or_resize_ || details_.window_component != HTCAPTION)
return;
@@ -403,29 +364,10 @@ void WorkspaceWindowResizer::CompleteDrag(int event_flags) {
window()->SetBounds(snap_sizer_->target_bounds());
return;
}
- gfx::Rect bounds(GetFinalBounds(window()->bounds()));
-
- // Check if the destination is another display.
- gfx::Point last_mouse_location_in_screen = last_mouse_location_;
- wm::ConvertPointToScreen(window()->parent(), &last_mouse_location_in_screen);
- gfx::Screen* screen = Shell::GetScreen();
- const gfx::Display dst_display =
- screen->GetDisplayNearestPoint(last_mouse_location_in_screen);
-
- if (dst_display.id() !=
- screen->GetDisplayNearestWindow(window()->GetRootWindow()).id()) {
- // Don't animate when moving to another display.
- const gfx::Rect dst_bounds =
- ScreenAsh::ConvertRectToScreen(window()->parent(), bounds);
- window()->SetBoundsInScreen(dst_bounds, dst_display);
- }
}
void WorkspaceWindowResizer::RevertDrag() {
- window()->layer()->SetOpacity(details_.initial_opacity);
- drag_window_controller_.reset();
snap_phantom_window_controller_.reset();
- Shell::GetInstance()->mouse_cursor_filter()->HideSharedEdgeIndicator();
if (!did_move_or_resize_)
return;
@@ -469,27 +411,12 @@ WorkspaceWindowResizer::WorkspaceWindowResizer(
total_initial_size_(0),
snap_type_(SNAP_NONE),
num_mouse_moves_since_bounds_change_(0),
- destroyed_(NULL),
magnetism_window_(NULL) {
DCHECK(details_.is_resizable);
Shell* shell = Shell::GetInstance();
shell->cursor_manager()->LockCursor();
- // The pointer should be confined in one display during resizing a window
- // because the window cannot span two displays at the same time anyway. The
- // exception is window/tab dragging operation. During that operation,
- // |mouse_warp_mode_| should be set to WARP_DRAG so that the user could move a
- // window/tab to another display.
- MouseCursorEventFilter* mouse_cursor_filter = shell->mouse_cursor_filter();
- mouse_cursor_filter->set_mouse_warp_mode(
- ShouldAllowMouseWarp() ?
- MouseCursorEventFilter::WARP_DRAG : MouseCursorEventFilter::WARP_NONE);
- if (ShouldAllowMouseWarp()) {
- mouse_cursor_filter->ShowSharedEdgeIndicator(
- details.window->GetRootWindow());
- }
-
// Only support attaching to the right/bottom.
DCHECK(attached_windows_.empty() ||
(details.window_component == HTRIGHT ||
@@ -823,51 +750,6 @@ int WorkspaceWindowResizer::PrimaryAxisCoordinate(int x, int y) const {
return 0;
}
-void WorkspaceWindowResizer::UpdateDragWindow(const gfx::Rect& bounds,
- bool in_original_root) {
- if (!did_move_or_resize_ || details_.window_component != HTCAPTION ||
- !ShouldAllowMouseWarp()) {
- return;
- }
-
- // It's available. Show a phantom window on the display if needed.
- aura::RootWindow* another_root =
- GetAnotherRootWindow(window()->GetRootWindow());
- const gfx::Rect root_bounds_in_screen(another_root->GetBoundsInScreen());
- const gfx::Rect bounds_in_screen =
- ScreenAsh::ConvertRectToScreen(window()->parent(), bounds);
- gfx::Rect bounds_in_another_root =
- gfx::IntersectRects(root_bounds_in_screen, bounds_in_screen);
-
- const float fraction_in_another_window =
- (bounds_in_another_root.width() * bounds_in_another_root.height()) /
- static_cast<float>(bounds.width() * bounds.height());
- const float phantom_opacity =
- !in_original_root ? 1 : (kMaxOpacity * fraction_in_another_window);
- const float window_opacity =
- in_original_root ? 1 : (kMaxOpacity * (1 - fraction_in_another_window));
-
- if (fraction_in_another_window > 0) {
- if (!drag_window_controller_.get()) {
- drag_window_controller_.reset(
- new DragWindowController(window()));
- // Always show the drag phantom on the |another_root| window.
- drag_window_controller_->SetDestinationDisplay(
- Shell::GetScreen()->GetDisplayMatching(
- another_root->GetBoundsInScreen()));
- drag_window_controller_->Show();
- } else {
- // No animation.
- drag_window_controller_->SetBounds(bounds_in_screen);
- }
- drag_window_controller_->SetOpacity(phantom_opacity);
- window()->layer()->SetOpacity(window_opacity);
- } else {
- drag_window_controller_.reset();
- window()->layer()->SetOpacity(1.0f);
- }
-}
-
void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location,
const gfx::Rect& bounds) {
if (!did_move_or_resize_ || details_.window_component != HTCAPTION)
@@ -945,11 +827,5 @@ WorkspaceWindowResizer::SnapType WorkspaceWindowResizer::GetSnapType(
return SNAP_NONE;
}
-bool WorkspaceWindowResizer::ShouldAllowMouseWarp() const {
- return (details_.window_component == HTCAPTION) &&
- (window()->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_NONE) &&
- (window()->type() == aura::client::WINDOW_TYPE_NORMAL);
-}
-
} // namespace internal
} // namespace ash
diff --git a/ash/wm/workspace/workspace_window_resizer.h b/ash/wm/workspace/workspace_window_resizer.h
index f234a9e..4c71285 100644
--- a/ash/wm/workspace/workspace_window_resizer.h
+++ b/ash/wm/workspace/workspace_window_resizer.h
@@ -14,18 +14,9 @@
#include "base/memory/scoped_ptr.h"
#include "ui/aura/window_tracker.h"
-namespace aura {
-class RootWindow;
-} // namespace aura
-
-namespace ui {
-class Layer;
-} // namespace ui
-
namespace ash {
namespace internal {
-class DragWindowController;
class PhantomWindowController;
class SnapSizer;
class WindowSize;
@@ -58,13 +49,6 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer {
int window_component,
const std::vector<aura::Window*>& attached_windows);
- // Returns true if the drag will result in changing the window in anyway.
- bool is_resizable() const { return details_.is_resizable; }
-
- const gfx::Point& initial_location_in_parent() const {
- return details_.initial_location_in_parent;
- }
-
// Overridden from WindowResizer:
virtual void Drag(const gfx::Point& location_in_parent,
int event_flags) OVERRIDE;
@@ -72,12 +56,15 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer {
virtual void RevertDrag() OVERRIDE;
virtual aura::Window* GetTarget() OVERRIDE;
+ const gfx::Point& GetInitialLocationInParentForTest() const {
+ return details_.initial_location_in_parent;
+ }
+
private:
WorkspaceWindowResizer(const Details& details,
const std::vector<aura::Window*>& attached_windows);
private:
- FRIEND_TEST_ALL_PREFIXES(WorkspaceWindowResizerTest, DragWindowController);
FRIEND_TEST_ALL_PREFIXES(WorkspaceWindowResizerTest, CancelSnapPhantom);
FRIEND_TEST_ALL_PREFIXES(WorkspaceWindowResizerTest, PhantomSnapMaxSize);
@@ -167,10 +154,6 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer {
void UpdateSnapPhantomWindow(const gfx::Point& location,
const gfx::Rect& bounds);
- // Updates the bounds of the phantom window for window dragging. Set true on
- // |in_original_root| if the pointer is still in |window()->GetRootWindow()|.
- void UpdateDragWindow(const gfx::Rect& bounds, bool in_original_root);
-
// Restacks the windows z-order position so that one of the windows is at the
// top of the z-order, and the rest directly underneath it.
void RestackWindows();
@@ -179,9 +162,6 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer {
// snapping should be used.
SnapType GetSnapType(const gfx::Point& location) const;
- // Returns true if we should allow the mouse pointer to warp.
- bool ShouldAllowMouseWarp() const;
-
aura::Window* window() const { return details_.window; }
const Details details_;
@@ -205,9 +185,6 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer {
// is a grid and the caption is being dragged.
scoped_ptr<PhantomWindowController> snap_phantom_window_controller_;
- // Shows a semi-transparent image of the window being dragged.
- scoped_ptr<DragWindowController> drag_window_controller_;
-
// Used to determine the target position of a snap.
scoped_ptr<SnapSizer> snap_sizer_;
@@ -222,10 +199,6 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer {
// The mouse location passed to Drag().
gfx::Point last_mouse_location_;
- // If non-NULL the destructor sets this to true. Used to determine if this has
- // been deleted.
- bool* destroyed_;
-
// Window the drag has magnetically attached to.
aura::Window* magnetism_window_;
diff --git a/ash/wm/workspace/workspace_window_resizer_unittest.cc b/ash/wm/workspace/workspace_window_resizer_unittest.cc
index 8e9aac1..668db96 100644
--- a/ash/wm/workspace/workspace_window_resizer_unittest.cc
+++ b/ash/wm/workspace/workspace_window_resizer_unittest.cc
@@ -5,15 +5,11 @@
#include "ash/wm/workspace/workspace_window_resizer.h"
#include "ash/display/display_controller.h"
-#include "ash/display/mouse_cursor_event_filter.h"
#include "ash/root_window_controller.h"
#include "ash/screen_ash.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/test/ash_test_base.h"
-#include "ash/test/cursor_manager_test_api.h"
-#include "ash/wm/cursor_manager.h"
-#include "ash/wm/drag_window_controller.h"
#include "ash/wm/property_util.h"
#include "ash/wm/shelf_layout_manager.h"
#include "ash/wm/window_util.h"
@@ -135,7 +131,7 @@ class WorkspaceWindowResizerTest : public test::AshTestBase {
gfx::Point CalculateDragPoint(const WorkspaceWindowResizer& resizer,
int delta_x,
int delta_y) const {
- gfx::Point location = resizer.initial_location_in_parent();
+ gfx::Point location = resizer.GetInitialLocationInParentForTest();
location.set_x(location.x() + delta_x);
location.set_y(location.y() + delta_y);
return location;
@@ -521,170 +517,6 @@ TEST_F(WorkspaceWindowResizerTest, NonResizableWindows) {
EXPECT_EQ("0,30 50x60", window_->bounds().ToString());
}
-// Verifies a window can be moved from the primary display to another.
-TEST_F(WorkspaceWindowResizerTest, WindowDragWithMultiDisplays) {
- // The secondary display is logically on the right, but on the system (e.g. X)
- // layer, it's below the primary one. See UpdateDisplay() in ash_test_base.cc.
- UpdateDisplay("800x600,800x600");
- shelf_layout_manager()->LayoutShelf();
- Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
- ASSERT_EQ(2U, root_windows.size());
-
- window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
- Shell::GetScreen()->GetPrimaryDisplay());
- EXPECT_EQ(root_windows[0], window_->GetRootWindow());
- {
- // Grab (0, 0) of the window.
- scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
- window_.get(), gfx::Point(), HTCAPTION, empty_windows()));
- ASSERT_TRUE(resizer.get());
- // Drag the pointer to the right. Once it reaches the right edge of the
- // primary display, it warps to the secondary.
- resizer->Drag(CalculateDragPoint(*resizer, 800, 10), 0);
- resizer->CompleteDrag(0);
- // The whole window is on the secondary display now. The parent should be
- // changed.
- EXPECT_EQ(root_windows[1], window_->GetRootWindow());
- EXPECT_EQ("0,10 50x60", window_->bounds().ToString());
- }
-
- window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
- Shell::GetScreen()->GetPrimaryDisplay());
- EXPECT_EQ(root_windows[0], window_->GetRootWindow());
- {
- // Grab (0, 0) of the window and move the pointer to (790, 10).
- scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
- window_.get(), gfx::Point(), HTCAPTION, empty_windows()));
- ASSERT_TRUE(resizer.get());
- resizer->Drag(CalculateDragPoint(*resizer, 790, 10), 0);
- resizer->CompleteDrag(0);
- // Since the pointer is still on the primary root window, the parent should
- // not be changed.
- EXPECT_EQ(root_windows[0], window_->GetRootWindow());
- EXPECT_EQ("790,10 50x60", window_->bounds().ToString());
- }
-
- window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
- Shell::GetScreen()->GetPrimaryDisplay());
- EXPECT_EQ(root_windows[0], window_->GetRootWindow());
- {
- // Grab the top-right edge of the window and move the pointer to (0, 10)
- // in the secondary root window's coordinates.
- scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
- window_.get(), gfx::Point(49, 0), HTCAPTION, empty_windows()));
- ASSERT_TRUE(resizer.get());
- resizer->Drag(CalculateDragPoint(*resizer, 751, 10), ui::EF_CONTROL_DOWN);
- resizer->CompleteDrag(0);
- // Since the pointer is on the secondary, the parent should be changed
- // even though only small fraction of the window is within the secondary
- // root window's bounds.
- EXPECT_EQ(root_windows[1], window_->GetRootWindow());
- EXPECT_EQ("-49,10 50x60", window_->bounds().ToString());
- }
-}
-
-// Verifies a window can be moved from the secondary display to primary.
-TEST_F(WorkspaceWindowResizerTest,
- WindowDragWithMultiDisplaysRightToLeft) {
- UpdateDisplay("800x600,800x600");
- shelf_layout_manager()->LayoutShelf();
- Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
- ASSERT_EQ(2U, root_windows.size());
-
- window_->SetBoundsInScreen(
- gfx::Rect(800, 00, 50, 60),
- Shell::GetScreen()->GetDisplayNearestWindow(root_windows[1]));
- EXPECT_EQ(root_windows[1], window_->GetRootWindow());
- {
- // Grab (0, 0) of the window.
- scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
- window_.get(), gfx::Point(), HTCAPTION, empty_windows()));
- ASSERT_TRUE(resizer.get());
- // Move the mouse near the right edge, (798, 0), of the primary display.
- resizer->Drag(CalculateDragPoint(*resizer, -2, 0), ui::EF_CONTROL_DOWN);
- resizer->CompleteDrag(0);
- EXPECT_EQ(root_windows[0], window_->GetRootWindow());
- EXPECT_EQ("798,0 50x60", window_->bounds().ToString());
- }
-}
-
-// Verifies the drag window controller is instanciated appropriately.
-TEST_F(WorkspaceWindowResizerTest, DragWindowController) {
- UpdateDisplay("800x600,800x600");
- Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
- ASSERT_EQ(2U, root_windows.size());
-
- window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
- Shell::GetScreen()->GetPrimaryDisplay());
- EXPECT_EQ(root_windows[0], window_->GetRootWindow());
- EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity());
- {
- scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
- window_.get(), gfx::Point(), HTCAPTION, empty_windows()));
- ASSERT_TRUE(resizer.get());
- EXPECT_FALSE(resizer->snap_phantom_window_controller_.get());
- EXPECT_FALSE(resizer->drag_window_controller_.get());
-
- // The pointer is inside the primary root. Both phantoms should be NULL.
- resizer->Drag(CalculateDragPoint(*resizer, 10, 10), 0);
- EXPECT_FALSE(resizer->snap_phantom_window_controller_.get());
- EXPECT_FALSE(resizer->drag_window_controller_.get());
-
- // The window spans both root windows.
- resizer->Drag(CalculateDragPoint(*resizer, 798, 10), 0);
- EXPECT_FALSE(resizer->snap_phantom_window_controller_.get());
- DragWindowController* controller =
- resizer->drag_window_controller_.get();
- ASSERT_TRUE(controller);
- ASSERT_TRUE(controller->drag_widget_);
- ui::Layer* drag_layer =
- controller->drag_widget_->GetNativeWindow()->layer();
- ASSERT_TRUE(drag_layer);
-
- // Check if |resizer->layer_| is properly set to the phantom widget.
- const std::vector<ui::Layer*>& layers = drag_layer->children();
- EXPECT_FALSE(layers.empty());
- EXPECT_EQ(controller->layer_, layers.back());
-
- // |window_| should be opaque since the pointer is still on the primary
- // root window. The phantom should be semi-transparent.
- EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity());
- EXPECT_GT(1.0f, drag_layer->opacity());
-
- // Enter the pointer to the secondary display.
- resizer->Drag(CalculateDragPoint(*resizer, 800, 10), 0);
- EXPECT_FALSE(resizer->snap_phantom_window_controller_.get());
- controller = resizer->drag_window_controller_.get();
- ASSERT_TRUE(controller);
- // |window_| should be transparent, and the phantom should be opaque.
- EXPECT_GT(1.0f, window_->layer()->opacity());
- EXPECT_FLOAT_EQ(1.0f, drag_layer->opacity());
-
- resizer->CompleteDrag(0);
- EXPECT_EQ(root_windows[1], window_->GetRootWindow());
- EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity());
- }
-
- // Do the same test with RevertDrag().
- window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
- Shell::GetScreen()->GetPrimaryDisplay());
- EXPECT_EQ(root_windows[0], window_->GetRootWindow());
- EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity());
- {
- scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
- window_.get(), gfx::Point(), HTCAPTION, empty_windows()));
- ASSERT_TRUE(resizer.get());
- EXPECT_FALSE(resizer->snap_phantom_window_controller_.get());
- EXPECT_FALSE(resizer->drag_window_controller_.get());
-
- resizer->Drag(CalculateDragPoint(*resizer, 0, 610), 0);
- resizer->RevertDrag();
- EXPECT_EQ(root_windows[0], window_->GetRootWindow());
- EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity());
- }
-}
-
-// Verifies the style of the drag phantom window is correct.
TEST_F(WorkspaceWindowResizerTest, CancelSnapPhantom) {
UpdateDisplay("800x600,800x600");
Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
@@ -699,82 +531,19 @@ TEST_F(WorkspaceWindowResizerTest, CancelSnapPhantom) {
window_.get(), gfx::Point(), HTCAPTION, empty_windows()));
ASSERT_TRUE(resizer.get());
EXPECT_FALSE(resizer->snap_phantom_window_controller_.get());
- EXPECT_FALSE(resizer->drag_window_controller_.get());
- EXPECT_EQ(WorkspaceWindowResizer::SNAP_NONE, resizer->snap_type_);
- // The pointer is on the edge but not shared. Both controllers should be
- // non-NULL.
+ // The pointer is on the edge but not shared. The snap phantom window
+ // controller should be non-NULL.
resizer->Drag(CalculateDragPoint(*resizer, 799, 0), 0);
EXPECT_TRUE(resizer->snap_phantom_window_controller_.get());
- EXPECT_EQ(WorkspaceWindowResizer::SNAP_RIGHT_EDGE, resizer->snap_type_);
- DragWindowController* controller =
- resizer->drag_window_controller_.get();
- ASSERT_TRUE(controller);
- // Move the cursor across the edge. Now the snap phantom controller
+ // Move the cursor across the edge. Now the snap phantom window controller
// should be canceled.
resizer->Drag(CalculateDragPoint(*resizer, 800, 0), 0);
EXPECT_FALSE(resizer->snap_phantom_window_controller_.get());
- EXPECT_EQ(WorkspaceWindowResizer::SNAP_NONE, resizer->snap_type_);
- controller =
- resizer->drag_window_controller_.get();
- ASSERT_TRUE(controller);
}
}
-// Verifies if the resizer sets and resets
-// MouseCursorEventFilter::mouse_warp_mode_ as expected.
-TEST_F(WorkspaceWindowResizerTest, WarpMousePointer) {
- MouseCursorEventFilter* event_filter =
- Shell::GetInstance()->mouse_cursor_filter();
- ASSERT_TRUE(event_filter);
- window_->SetBounds(gfx::Rect(0, 0, 50, 60));
-
- EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS,
- event_filter->mouse_warp_mode_);
- {
- scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
- window_.get(), gfx::Point(), HTCAPTION, empty_windows()));
- // While dragging a window, warp should be allowed.
- EXPECT_EQ(MouseCursorEventFilter::WARP_DRAG,
- event_filter->mouse_warp_mode_);
- resizer->CompleteDrag(0);
- }
- EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS,
- event_filter->mouse_warp_mode_);
-
- {
- scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
- window_.get(), gfx::Point(), HTCAPTION, empty_windows()));
- EXPECT_EQ(MouseCursorEventFilter::WARP_DRAG,
- event_filter->mouse_warp_mode_);
- resizer->RevertDrag();
- }
- EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS,
- event_filter->mouse_warp_mode_);
-
- {
- scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
- window_.get(), gfx::Point(), HTRIGHT, empty_windows()));
- // While resizing a window, warp should NOT be allowed.
- EXPECT_EQ(MouseCursorEventFilter::WARP_NONE,
- event_filter->mouse_warp_mode_);
- resizer->CompleteDrag(0);
- }
- EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS,
- event_filter->mouse_warp_mode_);
-
- {
- scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
- window_.get(), gfx::Point(), HTRIGHT, empty_windows()));
- EXPECT_EQ(MouseCursorEventFilter::WARP_NONE,
- event_filter->mouse_warp_mode_);
- resizer->RevertDrag();
- }
- EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS,
- event_filter->mouse_warp_mode_);
-}
-
// Verifies windows are correctly restacked when reordering multiple windows.
TEST_F(WorkspaceWindowResizerTest, RestackAttached) {
window_->SetBounds(gfx::Rect( 0, 0, 200, 300));
@@ -1369,60 +1138,6 @@ TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_LEFT) {
EXPECT_EQ("99,200 21x30", window_->bounds().ToString());
}
-// Verifies cursor's device scale factor is updated whe a window is moved across
-// root windows with different device scale factors (http://crbug.com/154183).
-TEST_F(WorkspaceWindowResizerTest, CursorDeviceScaleFactor) {
- // The secondary display is logically on the right, but on the system (e.g. X)
- // layer, it's below the primary one. See UpdateDisplay() in ash_test_base.cc.
- UpdateDisplay("400x400,800x800*2");
- shelf_layout_manager()->LayoutShelf();
- Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
- ASSERT_EQ(2U, root_windows.size());
-
- test::CursorManagerTestApi cursor_test_api(
- Shell::GetInstance()->cursor_manager());
- MouseCursorEventFilter* event_filter =
- Shell::GetInstance()->mouse_cursor_filter();
- // Move window from the root window with 1.0 device scale factor to the root
- // window with 2.0 device scale factor.
- {
- window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
- Shell::GetScreen()->GetPrimaryDisplay());
- EXPECT_EQ(root_windows[0], window_->GetRootWindow());
- // Grab (0, 0) of the window.
- scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
- window_.get(), gfx::Point(), HTCAPTION, empty_windows()));
- EXPECT_EQ(1.0f, cursor_test_api.GetDeviceScaleFactor());
- ASSERT_TRUE(resizer.get());
- resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0);
- event_filter->WarpMouseCursorIfNecessary(root_windows[0],
- gfx::Point(399, 200));
- EXPECT_EQ(2.0f, cursor_test_api.GetDeviceScaleFactor());
- resizer->CompleteDrag(0);
- EXPECT_EQ(2.0f, cursor_test_api.GetDeviceScaleFactor());
- }
-
- // Move window from the root window with 2.0 device scale factor to the root
- // window with 1.0 device scale factor.
- {
- window_->SetBoundsInScreen(
- gfx::Rect(600, 0, 50, 60),
- Shell::GetScreen()->GetDisplayNearestWindow(root_windows[1]));
- EXPECT_EQ(root_windows[1], window_->GetRootWindow());
- // Grab (0, 0) of the window.
- scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create(
- window_.get(), gfx::Point(), HTCAPTION, empty_windows()));
- EXPECT_EQ(2.0f, cursor_test_api.GetDeviceScaleFactor());
- ASSERT_TRUE(resizer.get());
- resizer->Drag(CalculateDragPoint(*resizer, -200, 200), 0);
- event_filter->WarpMouseCursorIfNecessary(root_windows[1],
- gfx::Point(400, 200));
- EXPECT_EQ(1.0f, cursor_test_api.GetDeviceScaleFactor());
- resizer->CompleteDrag(0);
- EXPECT_EQ(1.0f, cursor_test_api.GetDeviceScaleFactor());
- }
-}
-
// Test that the user user moved window flag is getting properly set.
TEST_F(WorkspaceWindowResizerTest, CheckUserWindowMangedFlags) {
window_->SetBounds(gfx::Rect( 0, 50, 400, 200));