• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ash/drag_drop/drag_drop_controller.h"
6 
7 #include "ash/drag_drop/drag_drop_tracker.h"
8 #include "ash/drag_drop/drag_image_view.h"
9 #include "ash/shell.h"
10 #include "ash/test/ash_test_base.h"
11 #include "base/command_line.h"
12 #include "base/location.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "ui/aura/client/capture_client.h"
15 #include "ui/aura/window_event_dispatcher.h"
16 #include "ui/aura/window_tree_host.h"
17 #include "ui/base/clipboard/clipboard.h"
18 #include "ui/base/clipboard/scoped_clipboard_writer.h"
19 #include "ui/base/dragdrop/drag_drop_types.h"
20 #include "ui/base/dragdrop/drag_utils.h"
21 #include "ui/base/dragdrop/os_exchange_data.h"
22 #include "ui/base/ui_base_switches.h"
23 #include "ui/events/event.h"
24 #include "ui/events/event_utils.h"
25 #include "ui/events/gestures/gesture_types.h"
26 #include "ui/events/test/event_generator.h"
27 #include "ui/events/test/events_test_utils.h"
28 #include "ui/gfx/animation/linear_animation.h"
29 #include "ui/gfx/image/image_skia_rep.h"
30 #include "ui/views/view.h"
31 #include "ui/views/views_delegate.h"
32 #include "ui/views/widget/native_widget_aura.h"
33 #include "ui/views/widget/native_widget_delegate.h"
34 #include "ui/views/widget/widget.h"
35 
36 namespace ash {
37 namespace test {
38 
39 namespace {
40 
41 // A simple view that makes sure RunShellDrag is invoked on mouse drag.
42 class DragTestView : public views::View {
43  public:
DragTestView()44   DragTestView() : views::View() {
45     Reset();
46   }
47 
Reset()48   void Reset() {
49     num_drag_enters_ = 0;
50     num_drag_exits_ = 0;
51     num_drag_updates_ = 0;
52     num_drops_ = 0;
53     drag_done_received_ = false;
54     long_tap_received_ = false;
55   }
56 
VerticalDragThreshold()57   int VerticalDragThreshold() {
58     return views::View::GetVerticalDragThreshold();
59   }
60 
HorizontalDragThreshold()61   int HorizontalDragThreshold() {
62     return views::View::GetHorizontalDragThreshold();
63   }
64 
65   int num_drag_enters_;
66   int num_drag_exits_;
67   int num_drag_updates_;
68   int num_drops_;
69   bool drag_done_received_;
70   bool long_tap_received_;
71 
72  private:
73   // View overrides:
GetDragOperations(const gfx::Point & press_pt)74   virtual int GetDragOperations(const gfx::Point& press_pt) OVERRIDE {
75     return ui::DragDropTypes::DRAG_COPY;
76   }
77 
WriteDragData(const gfx::Point & p,OSExchangeData * data)78   virtual void WriteDragData(const gfx::Point& p,
79                              OSExchangeData* data) OVERRIDE {
80     data->SetString(base::UTF8ToUTF16("I am being dragged"));
81     gfx::ImageSkiaRep image_rep(gfx::Size(10, 20), 1.0f);
82     gfx::ImageSkia image_skia(image_rep);
83 
84     drag_utils::SetDragImageOnDataObject(image_skia, gfx::Vector2d(), data);
85   }
86 
OnMousePressed(const ui::MouseEvent & event)87   virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE {
88     return true;
89   }
90 
OnGestureEvent(ui::GestureEvent * event)91   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
92     if (event->type() == ui::ET_GESTURE_LONG_TAP)
93       long_tap_received_ = true;
94     return;
95   }
96 
GetDropFormats(int * formats,std::set<OSExchangeData::CustomFormat> * custom_formats)97   virtual bool GetDropFormats(
98       int* formats,
99       std::set<OSExchangeData::CustomFormat>* custom_formats) OVERRIDE {
100     *formats = ui::OSExchangeData::STRING;
101     return true;
102   }
103 
CanDrop(const OSExchangeData & data)104   virtual bool CanDrop(const OSExchangeData& data) OVERRIDE {
105     return true;
106   }
107 
OnDragEntered(const ui::DropTargetEvent & event)108   virtual void OnDragEntered(const ui::DropTargetEvent& event) OVERRIDE {
109     num_drag_enters_++;
110   }
111 
OnDragUpdated(const ui::DropTargetEvent & event)112   virtual int OnDragUpdated(const ui::DropTargetEvent& event) OVERRIDE {
113     num_drag_updates_++;
114     return ui::DragDropTypes::DRAG_COPY;
115   }
116 
OnDragExited()117   virtual void OnDragExited() OVERRIDE {
118     num_drag_exits_++;
119   }
120 
OnPerformDrop(const ui::DropTargetEvent & event)121   virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE {
122     num_drops_++;
123     return ui::DragDropTypes::DRAG_COPY;
124   }
125 
OnDragDone()126   virtual void OnDragDone() OVERRIDE {
127     drag_done_received_ = true;
128   }
129 
130   DISALLOW_COPY_AND_ASSIGN(DragTestView);
131 };
132 
133 class CompletableLinearAnimation : public gfx::LinearAnimation {
134  public:
CompletableLinearAnimation(int duration,int frame_rate,gfx::AnimationDelegate * delegate)135   CompletableLinearAnimation(int duration,
136                              int frame_rate,
137                              gfx::AnimationDelegate* delegate)
138       : gfx::LinearAnimation(duration, frame_rate, delegate),
139         duration_(duration) {
140   }
141 
Complete()142   void Complete() {
143     Step(start_time() + base::TimeDelta::FromMilliseconds(duration_));
144   }
145 
146  private:
147   int duration_;
148 };
149 
150 class TestDragDropController : public DragDropController {
151  public:
TestDragDropController()152   TestDragDropController() : DragDropController() { Reset(); }
153 
Reset()154   void Reset() {
155     drag_start_received_ = false;
156     num_drag_updates_ = 0;
157     drop_received_ = false;
158     drag_canceled_ = false;
159     drag_string_.clear();
160   }
161 
StartDragAndDrop(const ui::OSExchangeData & data,aura::Window * root_window,aura::Window * source_window,const gfx::Point & location,int operation,ui::DragDropTypes::DragEventSource source)162   virtual int StartDragAndDrop(
163       const ui::OSExchangeData& data,
164       aura::Window* root_window,
165       aura::Window* source_window,
166       const gfx::Point& location,
167       int operation,
168       ui::DragDropTypes::DragEventSource source) OVERRIDE {
169     drag_start_received_ = true;
170     data.GetString(&drag_string_);
171     return DragDropController::StartDragAndDrop(
172         data, root_window, source_window, location, operation, source);
173   }
174 
DragUpdate(aura::Window * target,const ui::LocatedEvent & event)175   virtual void DragUpdate(aura::Window* target,
176                           const ui::LocatedEvent& event) OVERRIDE {
177     DragDropController::DragUpdate(target, event);
178     num_drag_updates_++;
179   }
180 
Drop(aura::Window * target,const ui::LocatedEvent & event)181   virtual void Drop(aura::Window* target,
182                     const ui::LocatedEvent& event) OVERRIDE {
183     DragDropController::Drop(target, event);
184     drop_received_ = true;
185   }
186 
DragCancel()187   virtual void DragCancel() OVERRIDE {
188     DragDropController::DragCancel();
189     drag_canceled_ = true;
190   }
191 
CreateCancelAnimation(int duration,int frame_rate,gfx::AnimationDelegate * delegate)192   virtual gfx::LinearAnimation* CreateCancelAnimation(
193       int duration,
194       int frame_rate,
195       gfx::AnimationDelegate* delegate) OVERRIDE {
196     return new CompletableLinearAnimation(duration, frame_rate, delegate);
197   }
198 
DoDragCancel(int animation_duration_ms)199   virtual void DoDragCancel(int animation_duration_ms) OVERRIDE {
200     DragDropController::DoDragCancel(animation_duration_ms);
201     drag_canceled_ = true;
202   }
203 
204   bool drag_start_received_;
205   int num_drag_updates_;
206   bool drop_received_;
207   bool drag_canceled_;
208   base::string16 drag_string_;
209 
210  private:
211   DISALLOW_COPY_AND_ASSIGN(TestDragDropController);
212 };
213 
214 class TestNativeWidgetAura : public views::NativeWidgetAura {
215  public:
TestNativeWidgetAura(views::internal::NativeWidgetDelegate * delegate)216   explicit TestNativeWidgetAura(views::internal::NativeWidgetDelegate* delegate)
217       : NativeWidgetAura(delegate),
218         check_if_capture_lost_(false) {
219   }
220 
set_check_if_capture_lost(bool value)221   void set_check_if_capture_lost(bool value) {
222     check_if_capture_lost_ = value;
223   }
224 
OnCaptureLost()225   virtual void OnCaptureLost() OVERRIDE {
226     DCHECK(!check_if_capture_lost_);
227     views::NativeWidgetAura::OnCaptureLost();
228   }
229 
230  private:
231   bool check_if_capture_lost_;
232 
233   DISALLOW_COPY_AND_ASSIGN(TestNativeWidgetAura);
234 };
235 
236 // TODO(sky): this is for debugging, remove when track down failure.
SetCheckIfCaptureLost(views::Widget * widget,bool value)237 void SetCheckIfCaptureLost(views::Widget* widget, bool value) {
238   // On Windows, the DCHECK triggers when running on bot or locally through RDP,
239   // but not when logged in locally.
240 #if !defined(OS_WIN)
241   static_cast<TestNativeWidgetAura*>(widget->native_widget())->
242       set_check_if_capture_lost(value);
243 #endif
244 }
245 
CreateNewWidget()246 views::Widget* CreateNewWidget() {
247   views::Widget* widget = new views::Widget;
248   views::Widget::InitParams params;
249   params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
250   params.accept_events = true;
251   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
252   params.parent = Shell::GetPrimaryRootWindow();
253   params.child = true;
254   params.native_widget = new TestNativeWidgetAura(widget);
255   widget->Init(params);
256   widget->Show();
257   return widget;
258 }
259 
AddViewToWidgetAndResize(views::Widget * widget,views::View * view)260 void AddViewToWidgetAndResize(views::Widget* widget, views::View* view) {
261   if (!widget->GetContentsView()) {
262     views::View* contents_view = new views::View;
263     widget->SetContentsView(contents_view);
264   }
265 
266   views::View* contents_view = widget->GetContentsView();
267   contents_view->AddChildView(view);
268   view->SetBounds(contents_view->width(), 0, 100, 100);
269   gfx::Rect contents_view_bounds = contents_view->bounds();
270   contents_view_bounds.Union(view->bounds());
271   contents_view->SetBoundsRect(contents_view_bounds);
272   widget->SetBounds(contents_view_bounds);
273 }
274 
DispatchGesture(ui::EventType gesture_type,gfx::Point location)275 void DispatchGesture(ui::EventType gesture_type, gfx::Point location) {
276   ui::GestureEventDetails event_details(gesture_type);
277   event_details.set_oldest_touch_id(1);
278   ui::GestureEvent gesture_event(
279       location.x(), location.y(), 0, ui::EventTimeForNow(), event_details);
280   ui::EventSource* event_source =
281       Shell::GetPrimaryRootWindow()->GetHost()->GetEventSource();
282   ui::EventSourceTestApi event_source_test(event_source);
283   ui::EventDispatchDetails details =
284       event_source_test.SendEventToProcessor(&gesture_event);
285   CHECK(!details.dispatcher_destroyed);
286 }
287 
288 }  // namespace
289 
290 class DragDropControllerTest : public AshTestBase {
291  public:
DragDropControllerTest()292   DragDropControllerTest() : AshTestBase() {}
~DragDropControllerTest()293   virtual ~DragDropControllerTest() {}
294 
SetUp()295   virtual void SetUp() OVERRIDE {
296     AshTestBase::SetUp();
297     drag_drop_controller_.reset(new TestDragDropController);
298     drag_drop_controller_->set_should_block_during_drag_drop(false);
299     aura::client::SetDragDropClient(Shell::GetPrimaryRootWindow(),
300                                     drag_drop_controller_.get());
301   }
302 
TearDown()303   virtual void TearDown() OVERRIDE {
304     aura::client::SetDragDropClient(Shell::GetPrimaryRootWindow(), NULL);
305     drag_drop_controller_.reset();
306     AshTestBase::TearDown();
307   }
308 
UpdateDragData(ui::OSExchangeData * data)309   void UpdateDragData(ui::OSExchangeData* data) {
310     drag_drop_controller_->drag_data_ = data;
311   }
312 
GetDragWindow()313   aura::Window* GetDragWindow() {
314     return drag_drop_controller_->drag_window_;
315   }
316 
GetDragSourceWindow()317   aura::Window* GetDragSourceWindow() {
318     return drag_drop_controller_->drag_source_window_;
319   }
320 
SetDragSourceWindow(aura::Window * drag_source_window)321   void SetDragSourceWindow(aura::Window* drag_source_window) {
322     drag_drop_controller_->drag_source_window_ = drag_source_window;
323     drag_source_window->AddObserver(drag_drop_controller_.get());
324   }
325 
GetDragImageWindow()326   aura::Window* GetDragImageWindow() {
327     return drag_drop_controller_->drag_image_.get() ?
328         drag_drop_controller_->drag_image_->GetWidget()->GetNativeWindow() :
329         NULL;
330   }
331 
drag_drop_tracker()332   DragDropTracker* drag_drop_tracker() {
333     return drag_drop_controller_->drag_drop_tracker_.get();
334   }
335 
CompleteCancelAnimation()336   void CompleteCancelAnimation() {
337     CompletableLinearAnimation* animation =
338         static_cast<CompletableLinearAnimation*>(
339             drag_drop_controller_->cancel_animation_.get());
340     animation->Complete();
341   }
342 
343  protected:
344   scoped_ptr<TestDragDropController> drag_drop_controller_;
345 
346  private:
347   DISALLOW_COPY_AND_ASSIGN(DragDropControllerTest);
348 };
349 
350 // TODO(win_aura) http://crbug.com/154081
351 #if defined(OS_WIN)
352 #define MAYBE_DragDropInSingleViewTest DISABLED_DragDropInSingleViewTest
353 #else
354 #define MAYBE_DragDropInSingleViewTest DragDropInSingleViewTest
355 #endif
TEST_F(DragDropControllerTest,MAYBE_DragDropInSingleViewTest)356 TEST_F(DragDropControllerTest, MAYBE_DragDropInSingleViewTest) {
357   scoped_ptr<views::Widget> widget(CreateNewWidget());
358   DragTestView* drag_view = new DragTestView;
359   AddViewToWidgetAndResize(widget.get(), drag_view);
360   ui::OSExchangeData data;
361   data.SetString(base::UTF8ToUTF16("I am being dragged"));
362   ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
363                                      widget->GetNativeView());
364   generator.PressLeftButton();
365 
366   int num_drags = 17;
367   SetCheckIfCaptureLost(widget.get(), true);
368   for (int i = 0; i < num_drags; ++i) {
369     // Because we are not doing a blocking drag and drop, the original
370     // OSDragExchangeData object is lost as soon as we return from the drag
371     // initiation in DragDropController::StartDragAndDrop(). Hence we set the
372     // drag_data_ to a fake drag data object that we created.
373     if (i > 0)
374       UpdateDragData(&data);
375     // 7 comes from views::View::GetVerticalDragThreshold()).
376     if (i >= 7)
377       SetCheckIfCaptureLost(widget.get(), false);
378 
379     generator.MoveMouseBy(0, 1);
380 
381     // Execute any scheduled draws to process deferred mouse events.
382     RunAllPendingInMessageLoop();
383   }
384 
385   generator.ReleaseLeftButton();
386 
387   EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
388   EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
389       drag_drop_controller_->num_drag_updates_);
390   EXPECT_TRUE(drag_drop_controller_->drop_received_);
391   EXPECT_EQ(base::UTF8ToUTF16("I am being dragged"),
392       drag_drop_controller_->drag_string_);
393 
394   EXPECT_EQ(1, drag_view->num_drag_enters_);
395   EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
396       drag_view->num_drag_updates_);
397   EXPECT_EQ(1, drag_view->num_drops_);
398   EXPECT_EQ(0, drag_view->num_drag_exits_);
399   EXPECT_TRUE(drag_view->drag_done_received_);
400 }
401 
TEST_F(DragDropControllerTest,DragDropWithZeroDragUpdates)402 TEST_F(DragDropControllerTest, DragDropWithZeroDragUpdates) {
403   scoped_ptr<views::Widget> widget(CreateNewWidget());
404   DragTestView* drag_view = new DragTestView;
405   AddViewToWidgetAndResize(widget.get(), drag_view);
406   ui::OSExchangeData data;
407   data.SetString(base::UTF8ToUTF16("I am being dragged"));
408   ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
409                                      widget->GetNativeView());
410   generator.PressLeftButton();
411 
412   int num_drags = drag_view->VerticalDragThreshold() + 1;
413   for (int i = 0; i < num_drags; ++i) {
414     // Because we are not doing a blocking drag and drop, the original
415     // OSDragExchangeData object is lost as soon as we return from the drag
416     // initiation in DragDropController::StartDragAndDrop(). Hence we set the
417     // drag_data_ to a fake drag data object that we created.
418     if (i > 0)
419       UpdateDragData(&data);
420     generator.MoveMouseBy(0, 1);
421   }
422 
423   UpdateDragData(&data);
424 
425   generator.ReleaseLeftButton();
426 
427   EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
428   EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold() + 1,
429       drag_drop_controller_->num_drag_updates_);
430   EXPECT_TRUE(drag_drop_controller_->drop_received_);
431 
432   EXPECT_EQ(1, drag_view->num_drag_enters_);
433   EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold() + 1,
434       drag_view->num_drag_updates_);
435   EXPECT_EQ(1, drag_view->num_drops_);
436   EXPECT_EQ(0, drag_view->num_drag_exits_);
437   EXPECT_TRUE(drag_view->drag_done_received_);
438 }
439 
440 // TODO(win_aura) http://crbug.com/154081
441 #if defined(OS_WIN)
442 #define MAYBE_DragDropInMultipleViewsSingleWidgetTest DISABLED_DragDropInMultipleViewsSingleWidgetTest
443 #else
444 #define MAYBE_DragDropInMultipleViewsSingleWidgetTest DragDropInMultipleViewsSingleWidgetTest
445 #endif
TEST_F(DragDropControllerTest,MAYBE_DragDropInMultipleViewsSingleWidgetTest)446 TEST_F(DragDropControllerTest, MAYBE_DragDropInMultipleViewsSingleWidgetTest) {
447   scoped_ptr<views::Widget> widget(CreateNewWidget());
448   DragTestView* drag_view1 = new DragTestView;
449   AddViewToWidgetAndResize(widget.get(), drag_view1);
450   DragTestView* drag_view2 = new DragTestView;
451   AddViewToWidgetAndResize(widget.get(), drag_view2);
452 
453   ui::OSExchangeData data;
454   data.SetString(base::UTF8ToUTF16("I am being dragged"));
455 
456   ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
457   generator.MoveMouseRelativeTo(widget->GetNativeView(),
458                                 drag_view1->bounds().CenterPoint());
459   generator.PressLeftButton();
460 
461   int num_drags = drag_view1->width();
462   for (int i = 0; i < num_drags; ++i) {
463     // Because we are not doing a blocking drag and drop, the original
464     // OSDragExchangeData object is lost as soon as we return from the drag
465     // initiation in DragDropController::StartDragAndDrop(). Hence we set the
466     // drag_data_ to a fake drag data object that we created.
467     if (i > 0)
468       UpdateDragData(&data);
469     generator.MoveMouseBy(1, 0);
470 
471     // Execute any scheduled draws to process deferred mouse events.
472     RunAllPendingInMessageLoop();
473   }
474 
475   generator.ReleaseLeftButton();
476 
477   EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
478   EXPECT_EQ(num_drags - 1 - drag_view1->HorizontalDragThreshold(),
479       drag_drop_controller_->num_drag_updates_);
480   EXPECT_TRUE(drag_drop_controller_->drop_received_);
481   EXPECT_EQ(base::UTF8ToUTF16("I am being dragged"),
482       drag_drop_controller_->drag_string_);
483 
484   EXPECT_EQ(1, drag_view1->num_drag_enters_);
485   int num_expected_updates = drag_view1->bounds().width() -
486       drag_view1->bounds().CenterPoint().x() - 2;
487   EXPECT_EQ(num_expected_updates - drag_view1->HorizontalDragThreshold(),
488       drag_view1->num_drag_updates_);
489   EXPECT_EQ(0, drag_view1->num_drops_);
490   EXPECT_EQ(1, drag_view1->num_drag_exits_);
491   EXPECT_TRUE(drag_view1->drag_done_received_);
492 
493   EXPECT_EQ(1, drag_view2->num_drag_enters_);
494   num_expected_updates = num_drags - num_expected_updates - 1;
495   EXPECT_EQ(num_expected_updates, drag_view2->num_drag_updates_);
496   EXPECT_EQ(1, drag_view2->num_drops_);
497   EXPECT_EQ(0, drag_view2->num_drag_exits_);
498   EXPECT_FALSE(drag_view2->drag_done_received_);
499 }
500 
501 // TODO(win_aura) http://crbug.com/154081
502 #if defined(OS_WIN)
503 #define MAYBE_DragDropInMultipleViewsMultipleWidgetsTest DISABLED_DragDropInMultipleViewsMultipleWidgetsTest
504 #else
505 #define MAYBE_DragDropInMultipleViewsMultipleWidgetsTest DragDropInMultipleViewsMultipleWidgetsTest
506 #endif
TEST_F(DragDropControllerTest,MAYBE_DragDropInMultipleViewsMultipleWidgetsTest)507 TEST_F(DragDropControllerTest, MAYBE_DragDropInMultipleViewsMultipleWidgetsTest) {
508   scoped_ptr<views::Widget> widget1(CreateNewWidget());
509   DragTestView* drag_view1 = new DragTestView;
510   AddViewToWidgetAndResize(widget1.get(), drag_view1);
511   scoped_ptr<views::Widget> widget2(CreateNewWidget());
512   DragTestView* drag_view2 = new DragTestView;
513   AddViewToWidgetAndResize(widget2.get(), drag_view2);
514   gfx::Rect widget1_bounds = widget1->GetClientAreaBoundsInScreen();
515   gfx::Rect widget2_bounds = widget2->GetClientAreaBoundsInScreen();
516   widget2->SetBounds(gfx::Rect(widget1_bounds.width(), 0,
517       widget2_bounds.width(), widget2_bounds.height()));
518 
519   ui::OSExchangeData data;
520   data.SetString(base::UTF8ToUTF16("I am being dragged"));
521 
522   ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
523                                      widget1->GetNativeView());
524   generator.PressLeftButton();
525 
526   int num_drags = drag_view1->width();
527   for (int i = 0; i < num_drags; ++i) {
528     // Because we are not doing a blocking drag and drop, the original
529     // OSDragExchangeData object is lost as soon as we return from the drag
530     // initiation in DragDropController::StartDragAndDrop(). Hence we set the
531     // drag_data_ to a fake drag data object that we created.
532     if (i > 0)
533       UpdateDragData(&data);
534     generator.MoveMouseBy(1, 0);
535 
536     // Execute any scheduled draws to process deferred mouse events.
537     RunAllPendingInMessageLoop();
538   }
539 
540   generator.ReleaseLeftButton();
541 
542   EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
543   EXPECT_EQ(num_drags - 1 - drag_view1->HorizontalDragThreshold(),
544       drag_drop_controller_->num_drag_updates_);
545   EXPECT_TRUE(drag_drop_controller_->drop_received_);
546   EXPECT_EQ(base::UTF8ToUTF16("I am being dragged"),
547       drag_drop_controller_->drag_string_);
548 
549   EXPECT_EQ(1, drag_view1->num_drag_enters_);
550   int num_expected_updates = drag_view1->bounds().width() -
551       drag_view1->bounds().CenterPoint().x() - 2;
552   EXPECT_EQ(num_expected_updates - drag_view1->HorizontalDragThreshold(),
553       drag_view1->num_drag_updates_);
554   EXPECT_EQ(0, drag_view1->num_drops_);
555   EXPECT_EQ(1, drag_view1->num_drag_exits_);
556   EXPECT_TRUE(drag_view1->drag_done_received_);
557 
558   EXPECT_EQ(1, drag_view2->num_drag_enters_);
559   num_expected_updates = num_drags - num_expected_updates - 1;
560   EXPECT_EQ(num_expected_updates, drag_view2->num_drag_updates_);
561   EXPECT_EQ(1, drag_view2->num_drops_);
562   EXPECT_EQ(0, drag_view2->num_drag_exits_);
563   EXPECT_FALSE(drag_view2->drag_done_received_);
564 }
565 
566 // TODO(win_aura) http://crbug.com/154081
567 #if defined(OS_WIN)
568 #define MAYBE_ViewRemovedWhileInDragDropTest DISABLED_ViewRemovedWhileInDragDropTest
569 #else
570 #define MAYBE_ViewRemovedWhileInDragDropTest ViewRemovedWhileInDragDropTest
571 #endif
TEST_F(DragDropControllerTest,MAYBE_ViewRemovedWhileInDragDropTest)572 TEST_F(DragDropControllerTest, MAYBE_ViewRemovedWhileInDragDropTest) {
573   scoped_ptr<views::Widget> widget(CreateNewWidget());
574   scoped_ptr<DragTestView> drag_view(new DragTestView);
575   AddViewToWidgetAndResize(widget.get(), drag_view.get());
576   gfx::Point point = gfx::Rect(drag_view->bounds()).CenterPoint();
577   ui::OSExchangeData data;
578   data.SetString(base::UTF8ToUTF16("I am being dragged"));
579 
580   ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
581   generator.MoveMouseToCenterOf(widget->GetNativeView());
582   generator.PressLeftButton();
583 
584   int num_drags_1 = 17;
585   for (int i = 0; i < num_drags_1; ++i) {
586     // Because we are not doing a blocking drag and drop, the original
587     // OSDragExchangeData object is lost as soon as we return from the drag
588     // initiation in DragDropController::StartDragAndDrop(). Hence we set the
589     // drag_data_ to a fake drag data object that we created.
590     if (i > 0)
591       UpdateDragData(&data);
592     generator.MoveMouseBy(0, 1);
593 
594     // Execute any scheduled draws to process deferred mouse events.
595     RunAllPendingInMessageLoop();
596   }
597 
598   drag_view->parent()->RemoveChildView(drag_view.get());
599   // View has been removed. We will not get any of the following drag updates.
600   int num_drags_2 = 23;
601   for (int i = 0; i < num_drags_2; ++i) {
602     UpdateDragData(&data);
603     generator.MoveMouseBy(0, 1);
604 
605     // Execute any scheduled draws to process deferred mouse events.
606     RunAllPendingInMessageLoop();
607   }
608 
609   generator.ReleaseLeftButton();
610 
611   EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
612   EXPECT_EQ(num_drags_1 + num_drags_2 - 1 - drag_view->VerticalDragThreshold(),
613       drag_drop_controller_->num_drag_updates_);
614   EXPECT_TRUE(drag_drop_controller_->drop_received_);
615   EXPECT_EQ(base::UTF8ToUTF16("I am being dragged"),
616       drag_drop_controller_->drag_string_);
617 
618   EXPECT_EQ(1, drag_view->num_drag_enters_);
619   EXPECT_EQ(num_drags_1 - 1 - drag_view->VerticalDragThreshold(),
620       drag_view->num_drag_updates_);
621   EXPECT_EQ(0, drag_view->num_drops_);
622   EXPECT_EQ(0, drag_view->num_drag_exits_);
623   EXPECT_TRUE(drag_view->drag_done_received_);
624 }
625 
TEST_F(DragDropControllerTest,DragLeavesClipboardAloneTest)626 TEST_F(DragDropControllerTest, DragLeavesClipboardAloneTest) {
627   ui::Clipboard* cb = ui::Clipboard::GetForCurrentThread();
628   std::string clip_str("I am on the clipboard");
629   {
630     // We first copy some text to the clipboard.
631     ui::ScopedClipboardWriter scw(ui::CLIPBOARD_TYPE_COPY_PASTE);
632     scw.WriteText(base::ASCIIToUTF16(clip_str));
633   }
634   EXPECT_TRUE(cb->IsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(),
635       ui::CLIPBOARD_TYPE_COPY_PASTE));
636 
637   scoped_ptr<views::Widget> widget(CreateNewWidget());
638   DragTestView* drag_view = new DragTestView;
639   AddViewToWidgetAndResize(widget.get(), drag_view);
640 
641   ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
642                                      widget->GetNativeView());
643   ui::OSExchangeData data;
644   std::string data_str("I am being dragged");
645   data.SetString(base::ASCIIToUTF16(data_str));
646 
647   generator.PressLeftButton();
648   generator.MoveMouseBy(0, drag_view->VerticalDragThreshold() + 1);
649 
650   // Execute any scheduled draws to process deferred mouse events.
651   RunAllPendingInMessageLoop();
652 
653   // Verify the clipboard contents haven't changed
654   std::string result;
655   EXPECT_TRUE(cb->IsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(),
656       ui::CLIPBOARD_TYPE_COPY_PASTE));
657   cb->ReadAsciiText(ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
658   EXPECT_EQ(clip_str, result);
659   // Destory the clipboard here because ash doesn't delete it.
660   // crbug.com/158150.
661   ui::Clipboard::DestroyClipboardForCurrentThread();
662 }
663 
TEST_F(DragDropControllerTest,WindowDestroyedDuringDragDrop)664 TEST_F(DragDropControllerTest, WindowDestroyedDuringDragDrop) {
665   scoped_ptr<views::Widget> widget(CreateNewWidget());
666   DragTestView* drag_view = new DragTestView;
667   AddViewToWidgetAndResize(widget.get(), drag_view);
668   aura::Window* window = widget->GetNativeView();
669 
670   ui::OSExchangeData data;
671   data.SetString(base::UTF8ToUTF16("I am being dragged"));
672   ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
673                                      widget->GetNativeView());
674   generator.PressLeftButton();
675 
676   int num_drags = 17;
677   for (int i = 0; i < num_drags; ++i) {
678     // Because we are not doing a blocking drag and drop, the original
679     // OSDragExchangeData object is lost as soon as we return from the drag
680     // initiation in DragDropController::StartDragAndDrop(). Hence we set the
681     // drag_data_ to a fake drag data object that we created.
682     if (i > 0)
683       UpdateDragData(&data);
684     generator.MoveMouseBy(0, 1);
685 
686     // Execute any scheduled draws to process deferred mouse events.
687     RunAllPendingInMessageLoop();
688 
689     if (i > drag_view->VerticalDragThreshold())
690       EXPECT_EQ(window, GetDragWindow());
691   }
692 
693   widget->CloseNow();
694   EXPECT_FALSE(GetDragWindow());
695 
696   num_drags = 23;
697   for (int i = 0; i < num_drags; ++i) {
698     if (i > 0)
699       UpdateDragData(&data);
700     generator.MoveMouseBy(0, 1);
701     // We should not crash here.
702   }
703 
704   generator.ReleaseLeftButton();
705 
706   EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
707   EXPECT_TRUE(drag_drop_controller_->drop_received_);
708 }
709 
TEST_F(DragDropControllerTest,SyntheticEventsDuringDragDrop)710 TEST_F(DragDropControllerTest, SyntheticEventsDuringDragDrop) {
711   scoped_ptr<views::Widget> widget(CreateNewWidget());
712   DragTestView* drag_view = new DragTestView;
713   AddViewToWidgetAndResize(widget.get(), drag_view);
714   ui::OSExchangeData data;
715   data.SetString(base::UTF8ToUTF16("I am being dragged"));
716   ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
717                                      widget->GetNativeView());
718   generator.PressLeftButton();
719 
720   int num_drags = 17;
721   for (int i = 0; i < num_drags; ++i) {
722     // Because we are not doing a blocking drag and drop, the original
723     // OSDragExchangeData object is lost as soon as we return from the drag
724     // initiation in DragDropController::StartDragAndDrop(). Hence we set the
725     // drag_data_ to a fake drag data object that we created.
726     if (i > 0)
727       UpdateDragData(&data);
728     generator.MoveMouseBy(0, 1);
729 
730     // We send a unexpected mouse move event. Note that we cannot use
731     // EventGenerator since it implicitly turns these into mouse drag events.
732     // The DragDropController should simply ignore these events.
733     gfx::Point mouse_move_location = drag_view->bounds().CenterPoint();
734     ui::MouseEvent mouse_move(ui::ET_MOUSE_MOVED, mouse_move_location,
735                               mouse_move_location, 0, 0);
736     ui::EventDispatchDetails details = Shell::GetPrimaryRootWindow()->
737         GetHost()->event_processor()->OnEventFromSource(&mouse_move);
738     ASSERT_FALSE(details.dispatcher_destroyed);
739   }
740 
741   generator.ReleaseLeftButton();
742 
743   EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
744   EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
745       drag_drop_controller_->num_drag_updates_);
746   EXPECT_TRUE(drag_drop_controller_->drop_received_);
747   EXPECT_EQ(base::UTF8ToUTF16("I am being dragged"),
748       drag_drop_controller_->drag_string_);
749 
750   EXPECT_EQ(1, drag_view->num_drag_enters_);
751   EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
752       drag_view->num_drag_updates_);
753   EXPECT_EQ(1, drag_view->num_drops_);
754   EXPECT_EQ(0, drag_view->num_drag_exits_);
755   EXPECT_TRUE(drag_view->drag_done_received_);
756 }
757 
758 // TODO(win_aura) http://crbug.com/154081
759 #if defined(OS_WIN)
760 #define MAYBE_PressingEscapeCancelsDragDrop DISABLED_PressingEscapeCancelsDragDrop
761 #define MAYBE_CaptureLostCancelsDragDrop DISABLED_CaptureLostCancelsDragDrop
762 #else
763 #define MAYBE_PressingEscapeCancelsDragDrop PressingEscapeCancelsDragDrop
764 #define MAYBE_CaptureLostCancelsDragDrop CaptureLostCancelsDragDrop
765 #endif
TEST_F(DragDropControllerTest,MAYBE_PressingEscapeCancelsDragDrop)766 TEST_F(DragDropControllerTest, MAYBE_PressingEscapeCancelsDragDrop) {
767   scoped_ptr<views::Widget> widget(CreateNewWidget());
768   DragTestView* drag_view = new DragTestView;
769   AddViewToWidgetAndResize(widget.get(), drag_view);
770   ui::OSExchangeData data;
771   data.SetString(base::UTF8ToUTF16("I am being dragged"));
772   ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
773                                      widget->GetNativeView());
774   generator.PressLeftButton();
775 
776   int num_drags = 17;
777   for (int i = 0; i < num_drags; ++i) {
778     // Because we are not doing a blocking drag and drop, the original
779     // OSDragExchangeData object is lost as soon as we return from the drag
780     // initiation in DragDropController::StartDragAndDrop(). Hence we set the
781     // drag_data_ to a fake drag data object that we created.
782     if (i > 0)
783       UpdateDragData(&data);
784     generator.MoveMouseBy(0, 1);
785 
786     // Execute any scheduled draws to process deferred mouse events.
787     RunAllPendingInMessageLoop();
788   }
789 
790   generator.PressKey(ui::VKEY_ESCAPE, 0);
791 
792   EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
793   EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
794       drag_drop_controller_->num_drag_updates_);
795   EXPECT_FALSE(drag_drop_controller_->drop_received_);
796   EXPECT_TRUE(drag_drop_controller_->drag_canceled_);
797   EXPECT_EQ(base::UTF8ToUTF16("I am being dragged"),
798       drag_drop_controller_->drag_string_);
799 
800   EXPECT_EQ(1, drag_view->num_drag_enters_);
801   EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
802       drag_view->num_drag_updates_);
803   EXPECT_EQ(0, drag_view->num_drops_);
804   EXPECT_EQ(1, drag_view->num_drag_exits_);
805   EXPECT_TRUE(drag_view->drag_done_received_);
806 }
807 
TEST_F(DragDropControllerTest,MAYBE_CaptureLostCancelsDragDrop)808 TEST_F(DragDropControllerTest, MAYBE_CaptureLostCancelsDragDrop) {
809   scoped_ptr<views::Widget> widget(CreateNewWidget());
810   DragTestView* drag_view = new DragTestView;
811   AddViewToWidgetAndResize(widget.get(), drag_view);
812   ui::OSExchangeData data;
813   data.SetString(base::UTF8ToUTF16("I am being dragged"));
814   ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
815                                      widget->GetNativeView());
816   generator.PressLeftButton();
817 
818   int num_drags = 17;
819   for (int i = 0; i < num_drags; ++i) {
820     // Because we are not doing a blocking drag and drop, the original
821     // OSDragExchangeData object is lost as soon as we return from the drag
822     // initiation in DragDropController::StartDragAndDrop(). Hence we set the
823     // drag_data_ to a fake drag data object that we created.
824     if (i > 0)
825       UpdateDragData(&data);
826     generator.MoveMouseBy(0, 1);
827 
828     // Execute any scheduled draws to process deferred mouse events.
829     RunAllPendingInMessageLoop();
830   }
831   // Make sure the capture window won't handle mouse events.
832   aura::Window* capture_window = drag_drop_tracker()->capture_window();
833   ASSERT_TRUE(!!capture_window);
834   EXPECT_EQ("0x0", capture_window->bounds().size().ToString());
835   EXPECT_EQ(NULL,
836             capture_window->GetEventHandlerForPoint(gfx::Point()));
837   EXPECT_EQ(NULL,
838             capture_window->GetTopWindowContainingPoint(gfx::Point()));
839 
840   aura::client::GetCaptureClient(widget->GetNativeView()->GetRootWindow())->
841       SetCapture(NULL);
842 
843   EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
844   EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
845       drag_drop_controller_->num_drag_updates_);
846   EXPECT_FALSE(drag_drop_controller_->drop_received_);
847   EXPECT_TRUE(drag_drop_controller_->drag_canceled_);
848   EXPECT_EQ(base::UTF8ToUTF16("I am being dragged"),
849       drag_drop_controller_->drag_string_);
850 
851   EXPECT_EQ(1, drag_view->num_drag_enters_);
852   EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
853       drag_view->num_drag_updates_);
854   EXPECT_EQ(0, drag_view->num_drops_);
855   EXPECT_EQ(1, drag_view->num_drag_exits_);
856   EXPECT_TRUE(drag_view->drag_done_received_);
857 }
858 
TEST_F(DragDropControllerTest,TouchDragDropInMultipleWindows)859 TEST_F(DragDropControllerTest, TouchDragDropInMultipleWindows) {
860   CommandLine::ForCurrentProcess()->AppendSwitch(
861       switches::kEnableTouchDragDrop);
862   scoped_ptr<views::Widget> widget1(CreateNewWidget());
863   DragTestView* drag_view1 = new DragTestView;
864   AddViewToWidgetAndResize(widget1.get(), drag_view1);
865   scoped_ptr<views::Widget> widget2(CreateNewWidget());
866   DragTestView* drag_view2 = new DragTestView;
867   AddViewToWidgetAndResize(widget2.get(), drag_view2);
868   gfx::Rect widget1_bounds = widget1->GetClientAreaBoundsInScreen();
869   gfx::Rect widget2_bounds = widget2->GetClientAreaBoundsInScreen();
870   widget2->SetBounds(gfx::Rect(widget1_bounds.width(), 0,
871       widget2_bounds.width(), widget2_bounds.height()));
872 
873   ui::OSExchangeData data;
874   data.SetString(base::UTF8ToUTF16("I am being dragged"));
875 
876   ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
877                                      widget1->GetNativeView());
878   generator.PressTouch();
879   gfx::Point point = gfx::Rect(drag_view1->bounds()).CenterPoint();
880   DispatchGesture(ui::ET_GESTURE_LONG_PRESS, point);
881   // Because we are not doing a blocking drag and drop, the original
882   // OSDragExchangeData object is lost as soon as we return from the drag
883   // initiation in DragDropController::StartDragAndDrop(). Hence we set the
884   // drag_data_ to a fake drag data object that we created.
885   UpdateDragData(&data);
886   gfx::Point gesture_location = point;
887   int num_drags = drag_view1->width();
888   for (int i = 0; i < num_drags; ++i) {
889     gesture_location.Offset(1, 0);
890     DispatchGesture(ui::ET_GESTURE_SCROLL_UPDATE, gesture_location);
891 
892     // Execute any scheduled draws to process deferred mouse events.
893     RunAllPendingInMessageLoop();
894   }
895 
896   DispatchGesture(ui::ET_GESTURE_SCROLL_END, gesture_location);
897 
898   EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
899   EXPECT_EQ(num_drags, drag_drop_controller_->num_drag_updates_);
900   EXPECT_TRUE(drag_drop_controller_->drop_received_);
901   EXPECT_EQ(base::UTF8ToUTF16("I am being dragged"),
902       drag_drop_controller_->drag_string_);
903 
904   EXPECT_EQ(1, drag_view1->num_drag_enters_);
905   int num_expected_updates = drag_view1->bounds().width() -
906       drag_view1->bounds().CenterPoint().x() - 1;
907   EXPECT_EQ(num_expected_updates, drag_view1->num_drag_updates_);
908   EXPECT_EQ(0, drag_view1->num_drops_);
909   EXPECT_EQ(1, drag_view1->num_drag_exits_);
910   EXPECT_TRUE(drag_view1->drag_done_received_);
911 
912   EXPECT_EQ(1, drag_view2->num_drag_enters_);
913   num_expected_updates = num_drags - num_expected_updates;
914   EXPECT_EQ(num_expected_updates, drag_view2->num_drag_updates_);
915   EXPECT_EQ(1, drag_view2->num_drops_);
916   EXPECT_EQ(0, drag_view2->num_drag_exits_);
917   EXPECT_FALSE(drag_view2->drag_done_received_);
918 }
919 
TEST_F(DragDropControllerTest,TouchDragDropCancelsOnLongTap)920 TEST_F(DragDropControllerTest, TouchDragDropCancelsOnLongTap) {
921   CommandLine::ForCurrentProcess()->AppendSwitch(
922       switches::kEnableTouchDragDrop);
923   scoped_ptr<views::Widget> widget(CreateNewWidget());
924   DragTestView* drag_view = new DragTestView;
925   AddViewToWidgetAndResize(widget.get(), drag_view);
926   ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
927                                      widget->GetNativeView());
928 
929   generator.PressTouch();
930   gfx::Point point = gfx::Rect(drag_view->bounds()).CenterPoint();
931   DispatchGesture(ui::ET_GESTURE_LONG_PRESS, point);
932   DispatchGesture(ui::ET_GESTURE_LONG_TAP, point);
933 
934   EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
935   EXPECT_TRUE(drag_drop_controller_->drag_canceled_);
936   EXPECT_EQ(0, drag_drop_controller_->num_drag_updates_);
937   EXPECT_FALSE(drag_drop_controller_->drop_received_);
938   EXPECT_EQ(base::UTF8ToUTF16("I am being dragged"),
939             drag_drop_controller_->drag_string_);
940   EXPECT_EQ(0, drag_view->num_drag_enters_);
941   EXPECT_EQ(0, drag_view->num_drops_);
942   EXPECT_EQ(0, drag_view->num_drag_exits_);
943   EXPECT_TRUE(drag_view->drag_done_received_);
944 }
945 
TEST_F(DragDropControllerTest,TouchDragDropLongTapGestureIsForwarded)946 TEST_F(DragDropControllerTest, TouchDragDropLongTapGestureIsForwarded) {
947   CommandLine::ForCurrentProcess()->AppendSwitch(
948       switches::kEnableTouchDragDrop);
949   scoped_ptr<views::Widget> widget(CreateNewWidget());
950   DragTestView* drag_view = new DragTestView;
951   AddViewToWidgetAndResize(widget.get(), drag_view);
952   ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
953                                      widget->GetNativeView());
954 
955   generator.PressTouch();
956   gfx::Point point = gfx::Rect(drag_view->bounds()).CenterPoint();
957   DispatchGesture(ui::ET_GESTURE_LONG_PRESS, point);
958 
959   // Since we are not running inside a nested loop, the |drag_source_window_|
960   // will get destroyed immediately. Hence we reassign it.
961   EXPECT_EQ(NULL, GetDragSourceWindow());
962   SetDragSourceWindow(widget->GetNativeView());
963   EXPECT_FALSE(drag_view->long_tap_received_);
964   DispatchGesture(ui::ET_GESTURE_LONG_TAP, point);
965   CompleteCancelAnimation();
966   EXPECT_TRUE(drag_view->long_tap_received_);
967 }
968 
969 namespace {
970 
971 class DragImageWindowObserver : public aura::WindowObserver {
972  public:
OnWindowDestroying(aura::Window * window)973   virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
974     window_location_on_destroying_ = window->GetBoundsInScreen().origin();
975   }
976 
window_location_on_destroying() const977   gfx::Point window_location_on_destroying() const {
978     return window_location_on_destroying_;
979   }
980 
981  public:
982   gfx::Point window_location_on_destroying_;
983 };
984 
985 }
986 
987 // Verifies the drag image moves back to the position where drag is started
988 // across displays when drag is cancelled.
TEST_F(DragDropControllerTest,DragCancelAcrossDisplays)989 TEST_F(DragDropControllerTest, DragCancelAcrossDisplays) {
990   if (!SupportsMultipleDisplays())
991     return;
992 
993   UpdateDisplay("400x400,400x400");
994   aura::Window::Windows root_windows =
995       Shell::GetInstance()->GetAllRootWindows();
996   for (aura::Window::Windows::iterator iter = root_windows.begin();
997        iter != root_windows.end(); ++iter) {
998     aura::client::SetDragDropClient(*iter, drag_drop_controller_.get());
999   }
1000 
1001   ui::OSExchangeData data;
1002   data.SetString(base::UTF8ToUTF16("I am being dragged"));
1003   {
1004     scoped_ptr<views::Widget> widget(CreateNewWidget());
1005     aura::Window* window = widget->GetNativeWindow();
1006     drag_drop_controller_->StartDragAndDrop(
1007         data,
1008         window->GetRootWindow(),
1009         window,
1010         gfx::Point(5, 5),
1011         ui::DragDropTypes::DRAG_MOVE,
1012         ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
1013 
1014     DragImageWindowObserver observer;
1015     ASSERT_TRUE(GetDragImageWindow());
1016     GetDragImageWindow()->AddObserver(&observer);
1017 
1018     {
1019       ui::MouseEvent e(ui::ET_MOUSE_DRAGGED,
1020                        gfx::Point(200, 0),
1021                        gfx::Point(200, 0),
1022                        ui::EF_NONE,
1023                        ui::EF_NONE);
1024       drag_drop_controller_->DragUpdate(window, e);
1025     }
1026     {
1027       ui::MouseEvent e(ui::ET_MOUSE_DRAGGED,
1028                        gfx::Point(600, 0),
1029                        gfx::Point(600, 0),
1030                        ui::EF_NONE,
1031                        ui::EF_NONE);
1032       drag_drop_controller_->DragUpdate(window, e);
1033     }
1034 
1035     drag_drop_controller_->DragCancel();
1036     CompleteCancelAnimation();
1037 
1038     EXPECT_EQ("5,5", observer.window_location_on_destroying().ToString());
1039   }
1040 
1041   {
1042     scoped_ptr<views::Widget> widget(CreateNewWidget());
1043     aura::Window* window = widget->GetNativeWindow();
1044     drag_drop_controller_->StartDragAndDrop(
1045         data,
1046         window->GetRootWindow(),
1047         window,
1048         gfx::Point(405, 405),
1049         ui::DragDropTypes::DRAG_MOVE,
1050         ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
1051     DragImageWindowObserver observer;
1052     ASSERT_TRUE(GetDragImageWindow());
1053     GetDragImageWindow()->AddObserver(&observer);
1054 
1055     {
1056       ui::MouseEvent e(ui::ET_MOUSE_DRAGGED,
1057                        gfx::Point(600, 0),
1058                        gfx::Point(600, 0),
1059                        ui::EF_NONE,
1060                        ui::EF_NONE);
1061       drag_drop_controller_->DragUpdate(window, e);
1062     }
1063     {
1064       ui::MouseEvent e(ui::ET_MOUSE_DRAGGED,
1065                        gfx::Point(200, 0),
1066                        gfx::Point(200, 0),
1067                        ui::EF_NONE,
1068                        ui::EF_NONE);
1069       drag_drop_controller_->DragUpdate(window, e);
1070     }
1071 
1072     drag_drop_controller_->DragCancel();
1073     CompleteCancelAnimation();
1074 
1075     EXPECT_EQ("405,405", observer.window_location_on_destroying().ToString());
1076   }
1077   for (aura::Window::Windows::iterator iter = root_windows.begin();
1078        iter != root_windows.end(); ++iter) {
1079     aura::client::SetDragDropClient(*iter, NULL);
1080   }
1081 }
1082 
1083 }  // namespace test
1084 }  // namespace aura
1085