diff options
author | mazda@chromium.org <mazda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-27 20:30:25 +0000 |
---|---|---|
committer | mazda@chromium.org <mazda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-27 20:30:25 +0000 |
commit | 96fe25bfc82b9eb144d9f321787fe64f6affd53f (patch) | |
tree | 8ffdd10615f1ff526f2cd48cc02ed02c5ea032b6 /ash/drag_drop | |
parent | e785b7690cd0af6f6914a270b7a81392342b56de (diff) | |
download | chromium_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.cc | 52 | ||||
-rw-r--r-- | ash/drag_drop/drag_drop_controller.h | 17 | ||||
-rw-r--r-- | ash/drag_drop/drag_drop_controller_unittest.cc | 129 |
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 |