summaryrefslogtreecommitdiffstats
path: root/ash/drag_drop
diff options
context:
space:
mode:
authormazda@chromium.org <mazda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-27 20:30:25 +0000
committermazda@chromium.org <mazda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-27 20:30:25 +0000
commit96fe25bfc82b9eb144d9f321787fe64f6affd53f (patch)
tree8ffdd10615f1ff526f2cd48cc02ed02c5ea032b6 /ash/drag_drop
parente785b7690cd0af6f6914a270b7a81392342b56de (diff)
downloadchromium_src-96fe25bfc82b9eb144d9f321787fe64f6affd53f.zip
chromium_src-96fe25bfc82b9eb144d9f321787fe64f6affd53f.tar.gz
chromium_src-96fe25bfc82b9eb144d9f321787fe64f6affd53f.tar.bz2
Make drag image move back to the original screen when drag is cancelled.
This CL uses LinearAnimation instead of LayerAnimatior in order to support the animation across displays. BUG=158484 Review URL: https://chromiumcodereview.appspot.com/11412124 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@169724 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash/drag_drop')
-rw-r--r--ash/drag_drop/drag_drop_controller.cc52
-rw-r--r--ash/drag_drop/drag_drop_controller.h17
-rw-r--r--ash/drag_drop/drag_drop_controller_unittest.cc129
3 files changed, 167 insertions, 31 deletions
diff --git a/ash/drag_drop/drag_drop_controller.cc b/ash/drag_drop/drag_drop_controller.cc
index da30919..bde1b36 100644
--- a/ash/drag_drop/drag_drop_controller.cc
+++ b/ash/drag_drop/drag_drop_controller.cc
@@ -16,12 +16,10 @@
#include "ui/aura/env.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
+#include "ui/base/animation/linear_animation.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/os_exchange_data_provider_aura.h"
#include "ui/base/events/event.h"
-#include "ui/compositor/layer.h"
-#include "ui/compositor/layer_animator.h"
-#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
#include "ui/views/views_delegate.h"
@@ -33,8 +31,10 @@ namespace internal {
using aura::RootWindow;
namespace {
-const base::TimeDelta kDragDropAnimationDuration =
- base::TimeDelta::FromMilliseconds(250);
+// The duration of the drag cancel animation in millisecond.
+const int kCancelAnimationDuration = 250;
+// The frame rate of the drag cancel animation in hertz.
+const int kCancelAnimationFrameRate = 60;
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -52,6 +52,8 @@ DragDropController::DragDropController()
DragDropController::~DragDropController() {
Shell::GetInstance()->RemovePreTargetHandler(this);
Cleanup();
+ if (cancel_animation_.get())
+ cancel_animation_->End();
if (drag_image_.get())
drag_image_.reset();
}
@@ -82,6 +84,11 @@ int DragDropController::StartDragAndDrop(
drag_window_ = NULL;
drag_start_location_ = root_location - drag_image_offset_;
+ ash::wm::ConvertPointToScreen(root_window, &drag_start_location_);
+
+ // Ends cancel animation if it's in progress.
+ if (cancel_animation_.get())
+ cancel_animation_->End();
#if !defined(OS_MACOSX)
if (should_block_during_drag_drop_) {
@@ -263,8 +270,9 @@ void DragDropController::OnWindowDestroyed(aura::Window* window) {
////////////////////////////////////////////////////////////////////////////////
// DragDropController, private:
-void DragDropController::OnImplicitAnimationsCompleted() {
- DCHECK(drag_image_.get());
+void DragDropController::AnimationEnded(const ui::Animation* animation) {
+ drag_image_->SetScreenPosition(drag_start_location_);
+ cancel_animation_.reset();
// By the time we finish animation, another drag/drop session may have
// started. We do not want to destroy the drag image in that case.
@@ -272,19 +280,25 @@ void DragDropController::OnImplicitAnimationsCompleted() {
drag_image_.reset();
}
+void DragDropController::AnimationProgressed(const ui::Animation* animation) {
+ drag_image_->SetScreenPosition(gfx::Point(
+ animation->CurrentValueBetween(drag_cancel_location_.x(),
+ drag_start_location_.x()),
+ animation->CurrentValueBetween(drag_cancel_location_.y(),
+ drag_start_location_.y())));
+}
+
+void DragDropController::AnimationCanceled(const ui::Animation* animation) {
+ AnimationEnded(animation);
+}
+
void DragDropController::StartCanceledAnimation() {
- aura::Window* window = drag_image_->GetWidget()->GetNativeView();
- ui::LayerAnimator* animator = window->layer()->GetAnimator();
- animator->set_preemption_strategy(
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
-
- // Stop waiting for any as yet unfinished implicit animations.
- StopObservingImplicitAnimations();
-
- ui::ScopedLayerAnimationSettings animation_setter(animator);
- animation_setter.SetTransitionDuration(kDragDropAnimationDuration);
- animation_setter.AddObserver(this);
- window->SetBounds(gfx::Rect(drag_start_location_, window->bounds().size()));
+ DCHECK(drag_image_.get());
+ drag_cancel_location_ = drag_image_->GetBoundsInScreen().origin();
+ cancel_animation_.reset(new ui::LinearAnimation(kCancelAnimationDuration,
+ kCancelAnimationFrameRate,
+ this));
+ cancel_animation_->Start();
}
void DragDropController::Cleanup() {
diff --git a/ash/drag_drop/drag_drop_controller.h b/ash/drag_drop/drag_drop_controller.h
index ad897df..bdeb06f 100644
--- a/ash/drag_drop/drag_drop_controller.h
+++ b/ash/drag_drop/drag_drop_controller.h
@@ -9,10 +9,10 @@
#include "base/callback.h"
#include "ui/aura/client/drag_drop_client.h"
#include "ui/aura/window_observer.h"
+#include "ui/base/animation/animation_delegate.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/events/event_constants.h"
#include "ui/base/events/event_handler.h"
-#include "ui/compositor/layer_animation_observer.h"
#include "ui/gfx/point.h"
namespace aura {
@@ -21,7 +21,7 @@ class Window;
}
namespace ui {
-class LayerAnimationSequence;
+class LinearAnimation;
}
namespace ash {
@@ -38,7 +38,7 @@ class DragImageView;
class ASH_EXPORT DragDropController
: public aura::client::DragDropClient,
public ui::EventHandler,
- public ui::ImplicitAnimationObserver,
+ public ui::AnimationDelegate,
public aura::WindowObserver {
public:
DragDropController();
@@ -74,8 +74,10 @@ class ASH_EXPORT DragDropController
private:
friend class ash::test::DragDropControllerTest;
- // Implementation of ImplicitAnimationObserver
- virtual void OnImplicitAnimationsCompleted() OVERRIDE;
+ // Overridden from ui::AnimationDelegate:
+ virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE;
+ virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE;
+ virtual void AnimationCanceled(const ui::Animation* animation) OVERRIDE;
// Helper method to start drag widget flying back animation.
void StartCanceledAnimation();
@@ -90,7 +92,12 @@ class ASH_EXPORT DragDropController
// Window that is currently under the drag cursor.
aura::Window* drag_window_;
+ // The location where drag is started in screen coordinate.
gfx::Point drag_start_location_;
+ // The location where drag is canceled in screen coordinate.
+ gfx::Point drag_cancel_location_;
+
+ scoped_ptr<ui::LinearAnimation> cancel_animation_;
// Indicates whether the caller should be blocked on a drag/drop session.
// Only be used for tests.
diff --git a/ash/drag_drop/drag_drop_controller_unittest.cc b/ash/drag_drop/drag_drop_controller_unittest.cc
index de358e5..4474207 100644
--- a/ash/drag_drop/drag_drop_controller_unittest.cc
+++ b/ash/drag_drop/drag_drop_controller_unittest.cc
@@ -4,12 +4,14 @@
#include "ash/drag_drop/drag_drop_controller.h"
+#include "ash/drag_drop/drag_image_view.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "base/location.h"
#include "base/utf_string_conversions.h"
#include "ui/aura/root_window.h"
#include "ui/aura/test/event_generator.h"
+#include "ui/base/animation/linear_animation.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/dragdrop/drag_drop_types.h"
@@ -119,13 +121,6 @@ class TestDragDropController : public internal::DragDropController {
drag_string_.clear();
}
- bool drag_start_received_;
- int num_drag_updates_;
- bool drop_received_;
- bool drag_canceled_;
- string16 drag_string_;
-
- private:
int StartDragAndDrop(const ui::OSExchangeData& data,
aura::RootWindow* root_window,
aura::Window* source_window,
@@ -154,6 +149,13 @@ class TestDragDropController : public internal::DragDropController {
drag_canceled_ = true;
}
+ bool drag_start_received_;
+ int num_drag_updates_;
+ bool drop_received_;
+ bool drag_canceled_;
+ string16 drag_string_;
+
+ private:
DISALLOW_COPY_AND_ASSIGN(TestDragDropController);
};
@@ -244,6 +246,16 @@ class DragDropControllerTest : public AshTestBase {
return drag_drop_controller_->drag_window_;
}
+ aura::Window* GetDragImageWindow() {
+ return drag_drop_controller_->drag_image_.get() ?
+ drag_drop_controller_->drag_image_->GetWidget()->GetNativeWindow() :
+ NULL;
+ }
+
+ void EndCancelAnimation() {
+ drag_drop_controller_->cancel_animation_->End();
+ }
+
protected:
scoped_ptr<TestDragDropController> drag_drop_controller_;
scoped_ptr<views::TestViewsDelegate> views_delegate_;
@@ -677,5 +689,108 @@ TEST_F(DragDropControllerTest, PressingEscapeCancelsDragDrop) {
EXPECT_TRUE(drag_view->drag_done_received_);
}
+namespace {
+
+class DragImageWindowObserver : public aura::WindowObserver {
+ public:
+ virtual void OnWindowDestroying(aura::Window* window) {
+ window_location_on_destroying_ = window->GetBoundsInScreen().origin();
+ }
+
+ gfx::Point window_location_on_destroying() const {
+ return window_location_on_destroying_;
+ }
+
+ public:
+ gfx::Point window_location_on_destroying_;
+};
+
+}
+
+// Verifies the drag image moves back to the position where drag is started
+// across displays when drag is cancelled.
+TEST_F(DragDropControllerTest, DragCancelAcrossDisplays) {
+ UpdateDisplay("400x400,400x400");
+ Shell::RootWindowList root_windows =
+ Shell::GetInstance()->GetAllRootWindows();
+ for (Shell::RootWindowList::iterator iter = root_windows.begin();
+ iter != root_windows.end(); ++iter) {
+ aura::client::SetDragDropClient(*iter, drag_drop_controller_.get());
+ }
+
+ ui::OSExchangeData data;
+ data.SetString(UTF8ToUTF16("I am being dragged"));
+ {
+ scoped_ptr<views::Widget> widget(CreateNewWidget());
+ aura::Window* window = widget->GetNativeWindow();
+ drag_drop_controller_->StartDragAndDrop(
+ data,
+ window->GetRootWindow(),
+ window,
+ gfx::Point(5, 5),
+ ui::DragDropTypes::DRAG_MOVE,
+ ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
+
+ DragImageWindowObserver observer;
+ ASSERT_TRUE(GetDragImageWindow());
+ GetDragImageWindow()->AddObserver(&observer);
+
+ {
+ ui::MouseEvent e(ui::ET_MOUSE_DRAGGED,
+ gfx::Point(200, 0),
+ gfx::Point(200, 0),
+ ui::EF_NONE);
+ drag_drop_controller_->DragUpdate(window, e);
+ }
+ {
+ ui::MouseEvent e(ui::ET_MOUSE_DRAGGED,
+ gfx::Point(600, 0),
+ gfx::Point(600, 0),
+ ui::EF_NONE);
+ drag_drop_controller_->DragUpdate(window, e);
+ }
+
+ drag_drop_controller_->DragCancel();
+ EndCancelAnimation();
+
+ EXPECT_EQ("5,5", observer.window_location_on_destroying().ToString());
+ }
+
+ {
+ scoped_ptr<views::Widget> widget(CreateNewWidget());
+ aura::Window* window = widget->GetNativeWindow();
+ drag_drop_controller_->StartDragAndDrop(
+ data,
+ window->GetRootWindow(),
+ window,
+ gfx::Point(405, 405),
+ ui::DragDropTypes::DRAG_MOVE,
+ ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
+ DragImageWindowObserver observer;
+ ASSERT_TRUE(GetDragImageWindow());
+ GetDragImageWindow()->AddObserver(&observer);
+
+ {
+ ui::MouseEvent e(ui::ET_MOUSE_DRAGGED,
+ gfx::Point(600, 0),
+ gfx::Point(600, 0),
+ ui::EF_NONE);
+ drag_drop_controller_->DragUpdate(window, e);
+ }
+ {
+ ui::MouseEvent e(ui::ET_MOUSE_DRAGGED,
+ gfx::Point(200, 0),
+ gfx::Point(200, 0),
+ ui::EF_NONE);
+ drag_drop_controller_->DragUpdate(window, e);
+ }
+
+ drag_drop_controller_->DragCancel();
+ EndCancelAnimation();
+
+ EXPECT_EQ("405,405", observer.window_location_on_destroying().ToString());
+ }
+}
+
} // namespace test
} // namespace aura