summaryrefslogtreecommitdiffstats
path: root/ash
diff options
context:
space:
mode:
authorvarunjain@chromium.org <varunjain@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-03 18:31:09 +0000
committervarunjain@chromium.org <varunjain@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-03 18:31:09 +0000
commit341ad584d4d3145f373ed670198df3a00e66ffe0 (patch)
treeaac04fffab369787378c89e4849e45c6edd79184 /ash
parentefbbe0d3a7e678be15646d39814c0e7d22878e5d (diff)
downloadchromium_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.cc22
-rw-r--r--ash/drag_drop/drag_drop_controller.h7
-rw-r--r--ash/drag_drop/drag_drop_controller_unittest.cc90
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