diff options
author | varunjain@chromium.org <varunjain@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-03 18:31:09 +0000 |
---|---|---|
committer | varunjain@chromium.org <varunjain@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-03 18:31:09 +0000 |
commit | 341ad584d4d3145f373ed670198df3a00e66ffe0 (patch) | |
tree | aac04fffab369787378c89e4849e45c6edd79184 /ash | |
parent | efbbe0d3a7e678be15646d39814c0e7d22878e5d (diff) | |
download | chromium_src-341ad584d4d3145f373ed670198df3a00e66ffe0.zip chromium_src-341ad584d4d3145f373ed670198df3a00e66ffe0.tar.gz chromium_src-341ad584d4d3145f373ed670198df3a00e66ffe0.tar.bz2 |
aura: This CL fixes a bunch of issues:
1. NWA should supply the right value for drag_operation to DropHelper.
2. The target window could be destroyed during a drag/drop session.
DragDropController should listen to such event and update its state.
3. The RootWindow might send some synthetic mouse events to the
DragDropController during a drag/drop session. The controller should ignore
these events.
BUG=110495
TEST=manual
Review URL: http://codereview.chromium.org/9307041
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@120358 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r-- | ash/drag_drop/drag_drop_controller.cc | 22 | ||||
-rw-r--r-- | ash/drag_drop/drag_drop_controller.h | 7 | ||||
-rw-r--r-- | ash/drag_drop/drag_drop_controller_unittest.cc | 90 |
3 files changed, 114 insertions, 5 deletions
diff --git a/ash/drag_drop/drag_drop_controller.cc b/ash/drag_drop/drag_drop_controller.cc index 255b0e2..719050e 100644 --- a/ash/drag_drop/drag_drop_controller.cc +++ b/ash/drag_drop/drag_drop_controller.cc @@ -90,11 +90,13 @@ void DragDropController::DragUpdate(aura::Window* target, const aura::MouseEvent& event) { aura::client::DragDropDelegate* delegate = NULL; if (target != dragged_window_) { - if (dragged_window_ && - (delegate = aura::client::GetDragDropDelegate(dragged_window_))) { - delegate->OnDragExited(); + if (dragged_window_) { + if ((delegate = aura::client::GetDragDropDelegate(dragged_window_))) + delegate->OnDragExited(); + dragged_window_->RemoveObserver(this); } dragged_window_ = target; + dragged_window_->AddObserver(this); if ((delegate = aura::client::GetDragDropDelegate(dragged_window_))) { aura::DropTargetEvent e(*drag_data_, event.location(), @@ -182,7 +184,9 @@ bool DragDropController::PreHandleMouseEvent(aura::Window* target, break; default: // We could reach here if the user drops outside the root window. - DragCancel(); + // We could also reach here because RootWindow may sometimes generate a + // bunch of fake mouse events + // (aura::RootWindow::PostMouseMoveEventAfterWindowChange). break; } return true; @@ -200,6 +204,13 @@ ui::GestureStatus DragDropController::PreHandleGestureEvent( return ui::GESTURE_STATUS_UNKNOWN; } +void DragDropController::OnWindowDestroyed(aura::Window* window) { + if (dragged_window_ == window) { + dragged_window_->RemoveObserver(this); + dragged_window_ = NULL; + } +} + //////////////////////////////////////////////////////////////////////////////// // DragDropController, private: @@ -224,6 +235,9 @@ void DragDropController::StartCanceledAnimation() { } void DragDropController::Cleanup() { + if (dragged_window_) + dragged_window_->RemoveObserver(this); + dragged_window_ = NULL; drag_data_ = NULL; drag_drop_in_progress_ = false; } diff --git a/ash/drag_drop/drag_drop_controller.h b/ash/drag_drop/drag_drop_controller.h index 9272257..4e5018a 100644 --- a/ash/drag_drop/drag_drop_controller.h +++ b/ash/drag_drop/drag_drop_controller.h @@ -10,6 +10,7 @@ #include "ui/aura/client/drag_drop_client.h" #include "ui/aura/event.h" #include "ui/aura/event_filter.h" +#include "ui/aura/window_observer.h" #include "ui/base/dragdrop/os_exchange_data.h" #include "ui/base/events.h" #include "ui/gfx/compositor/layer_animation_observer.h" @@ -36,7 +37,8 @@ class DragImageView; class ASH_EXPORT DragDropController : public aura::client::DragDropClient, public aura::EventFilter, - public ui::ImplicitAnimationObserver { + public ui::ImplicitAnimationObserver, + public aura::WindowObserver { public: DragDropController(); virtual ~DragDropController(); @@ -66,6 +68,9 @@ public: aura::Window* target, aura::GestureEvent* event) OVERRIDE; + // Overridden from aura::WindowObserver. + virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE; + private: friend class ash::test::DragDropControllerTest; diff --git a/ash/drag_drop/drag_drop_controller_unittest.cc b/ash/drag_drop/drag_drop_controller_unittest.cc index 1c0a054..62c6ccb 100644 --- a/ash/drag_drop/drag_drop_controller_unittest.cc +++ b/ash/drag_drop/drag_drop_controller_unittest.cc @@ -197,6 +197,10 @@ class DragDropControllerTest : public AuraShellTestBase { drag_drop_controller_->drag_data_ = data; } + aura::Window* GetDraggedWindow() { + return drag_drop_controller_->dragged_window_; + } + protected: scoped_ptr<TestDragDropController> drag_drop_controller_; scoped_ptr<views::TestViewsDelegate> views_delegate_; @@ -428,5 +432,91 @@ TEST_F(DragDropControllerTest, DragCopiesDataToClipboardTest) { EXPECT_EQ(data_str, result); } +TEST_F(DragDropControllerTest, WindowDestroyedDuringDragDrop) { + views::Widget* widget = CreateNewWidget(); + DragTestView* drag_view = new DragTestView; + AddViewToWidgetAndResize(widget, drag_view); + aura::Window* window = widget->GetNativeView(); + + ui::OSExchangeData data; + data.SetString(UTF8ToUTF16("I am being dragged")); + aura::test::EventGenerator generator(widget->GetNativeView()); + generator.PressLeftButton(); + + int num_drags = 17; + for (int i = 0; i < num_drags; ++i) { + // Because we are not doing a blocking drag and drop, the original + // OSDragExchangeData object is lost as soon as we return from the drag + // initiation in DragDropController::StartDragAndDrop(). Hence we set the + // drag_data_ to a fake drag data object that we created. + if (i > 0) + UpdateDragData(&data); + generator.MoveMouseBy(0, 1); + if (i > drag_view->VerticalDragThreshold()) + EXPECT_EQ(window, GetDraggedWindow()); + } + + delete window; + EXPECT_FALSE(GetDraggedWindow()); + + num_drags = 23; + for (int i = 0; i < num_drags; ++i) { + if (i > 0) + UpdateDragData(&data); + generator.MoveMouseBy(0, 1); + // We should not crash here. + } + + generator.ReleaseLeftButton(); + + EXPECT_TRUE(drag_drop_controller_->drag_start_received_); + EXPECT_TRUE(drag_drop_controller_->drop_received_); +} + +TEST_F(DragDropControllerTest, SyntheticEventsDuringDragDrop) { + scoped_ptr<views::Widget> widget(CreateNewWidget()); + DragTestView* drag_view = new DragTestView; + AddViewToWidgetAndResize(widget.get(), drag_view); + ui::OSExchangeData data; + data.SetString(UTF8ToUTF16("I am being dragged")); + aura::test::EventGenerator generator(widget->GetNativeView()); + generator.PressLeftButton(); + + int num_drags = 17; + for (int i = 0; i < num_drags; ++i) { + // Because we are not doing a blocking drag and drop, the original + // OSDragExchangeData object is lost as soon as we return from the drag + // initiation in DragDropController::StartDragAndDrop(). Hence we set the + // drag_data_ to a fake drag data object that we created. + if (i > 0) + UpdateDragData(&data); + generator.MoveMouseBy(0, 1); + + // We send a unexpected mouse move event. Note that we cannot use + // EventGenerator since it implicitly turns these into mouse drag events. + // The DragDropController should simply ignore these events. + gfx::Point mouse_move_location = drag_view->bounds().CenterPoint(); + aura::MouseEvent mouse_move(ui::ET_MOUSE_MOVED, + mouse_move_location, mouse_move_location, 0); + aura::RootWindow::GetInstance()->DispatchMouseEvent(&mouse_move); + } + + generator.ReleaseLeftButton(); + + EXPECT_TRUE(drag_drop_controller_->drag_start_received_); + EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(), + drag_drop_controller_->num_drag_updates_); + EXPECT_TRUE(drag_drop_controller_->drop_received_); + EXPECT_EQ(UTF8ToUTF16("I am being dragged"), + drag_drop_controller_->drag_string_); + + EXPECT_EQ(1, drag_view->num_drag_enters_); + EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(), + drag_view->num_drag_updates_); + EXPECT_EQ(1, drag_view->num_drops_); + EXPECT_EQ(0, drag_view->num_drag_exits_); + EXPECT_TRUE(drag_view->drag_done_received_); +} + } // namespace test } // namespace aura |