Deleted check for if Aes128Gcm12Encrypter::IsSupported or not beacuse we
[chromium-blink-merge.git] / ash / drag_drop / drag_drop_controller_unittest.cc
blob0538002993f10cfd98f3f4fe17899809c07a7742
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.
5 #include "ash/drag_drop/drag_drop_controller.h"
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/root_window.h"
16 #include "ui/aura/test/event_generator.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/gfx/animation/linear_animation.h"
27 #include "ui/gfx/image/image_skia_rep.h"
28 #include "ui/views/test/test_views_delegate.h"
29 #include "ui/views/view.h"
30 #include "ui/views/views_delegate.h"
31 #include "ui/views/widget/native_widget_aura.h"
32 #include "ui/views/widget/native_widget_delegate.h"
33 #include "ui/views/widget/widget.h"
35 namespace ash {
36 namespace test {
38 namespace {
40 // A simple view that makes sure RunShellDrag is invoked on mouse drag.
41 class DragTestView : public views::View {
42 public:
43 DragTestView() : views::View() {
44 Reset();
47 void Reset() {
48 num_drag_enters_ = 0;
49 num_drag_exits_ = 0;
50 num_drag_updates_ = 0;
51 num_drops_ = 0;
52 drag_done_received_ = false;
53 long_tap_received_ = false;
56 int VerticalDragThreshold() {
57 return views::View::GetVerticalDragThreshold();
60 int HorizontalDragThreshold() {
61 return views::View::GetHorizontalDragThreshold();
64 int num_drag_enters_;
65 int num_drag_exits_;
66 int num_drag_updates_;
67 int num_drops_;
68 bool drag_done_received_;
69 bool long_tap_received_;
71 private:
72 // View overrides:
73 virtual int GetDragOperations(const gfx::Point& press_pt) OVERRIDE {
74 return ui::DragDropTypes::DRAG_COPY;
77 virtual void WriteDragData(const gfx::Point& p,
78 OSExchangeData* data) OVERRIDE {
79 data->SetString(UTF8ToUTF16("I am being dragged"));
80 gfx::ImageSkiaRep image_rep(gfx::Size(10, 20), 1.0f);
81 gfx::ImageSkia image_skia(image_rep);
83 drag_utils::SetDragImageOnDataObject(
84 image_skia, image_skia.size(), gfx::Vector2d(), data);
87 virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE {
88 return true;
91 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
92 if (event->type() == ui::ET_GESTURE_LONG_TAP)
93 long_tap_received_ = true;
94 return;
97 virtual bool GetDropFormats(
98 int* formats,
99 std::set<OSExchangeData::CustomFormat>* custom_formats) OVERRIDE {
100 *formats = ui::OSExchangeData::STRING;
101 return true;
104 virtual bool CanDrop(const OSExchangeData& data) OVERRIDE {
105 return true;
108 virtual void OnDragEntered(const ui::DropTargetEvent& event) OVERRIDE {
109 num_drag_enters_++;
112 virtual int OnDragUpdated(const ui::DropTargetEvent& event) OVERRIDE {
113 num_drag_updates_++;
114 return ui::DragDropTypes::DRAG_COPY;
117 virtual void OnDragExited() OVERRIDE {
118 num_drag_exits_++;
121 virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE {
122 num_drops_++;
123 return ui::DragDropTypes::DRAG_COPY;
126 virtual void OnDragDone() OVERRIDE {
127 drag_done_received_ = true;
130 DISALLOW_COPY_AND_ASSIGN(DragTestView);
133 class CompletableLinearAnimation : public gfx::LinearAnimation {
134 public:
135 CompletableLinearAnimation(int duration,
136 int frame_rate,
137 gfx::AnimationDelegate* delegate)
138 : gfx::LinearAnimation(duration, frame_rate, delegate),
139 duration_(duration) {
142 void Complete() {
143 Step(start_time() + base::TimeDelta::FromMilliseconds(duration_));
146 private:
147 int duration_;
150 class TestDragDropController : public internal::DragDropController {
151 public:
152 TestDragDropController() : internal::DragDropController() {
153 Reset();
156 void Reset() {
157 drag_start_received_ = false;
158 num_drag_updates_ = 0;
159 drop_received_ = false;
160 drag_canceled_ = false;
161 drag_string_.clear();
164 virtual int StartDragAndDrop(
165 const ui::OSExchangeData& data,
166 aura::RootWindow* root_window,
167 aura::Window* source_window,
168 const gfx::Point& location,
169 int operation,
170 ui::DragDropTypes::DragEventSource source) OVERRIDE {
171 drag_start_received_ = true;
172 data.GetString(&drag_string_);
173 return DragDropController::StartDragAndDrop(
174 data, root_window, source_window, location, operation, source);
177 virtual void DragUpdate(aura::Window* target,
178 const ui::LocatedEvent& event) OVERRIDE {
179 DragDropController::DragUpdate(target, event);
180 num_drag_updates_++;
183 virtual void Drop(aura::Window* target,
184 const ui::LocatedEvent& event) OVERRIDE {
185 DragDropController::Drop(target, event);
186 drop_received_ = true;
189 virtual void DragCancel() OVERRIDE {
190 DragDropController::DragCancel();
191 drag_canceled_ = true;
194 virtual gfx::LinearAnimation* CreateCancelAnimation(
195 int duration,
196 int frame_rate,
197 gfx::AnimationDelegate* delegate) OVERRIDE {
198 return new CompletableLinearAnimation(duration, frame_rate, delegate);
201 virtual void DoDragCancel(int animation_duration_ms) OVERRIDE {
202 DragDropController::DoDragCancel(animation_duration_ms);
203 drag_canceled_ = true;
206 bool drag_start_received_;
207 int num_drag_updates_;
208 bool drop_received_;
209 bool drag_canceled_;
210 base::string16 drag_string_;
212 private:
213 DISALLOW_COPY_AND_ASSIGN(TestDragDropController);
216 class TestNativeWidgetAura : public views::NativeWidgetAura {
217 public:
218 explicit TestNativeWidgetAura(views::internal::NativeWidgetDelegate* delegate)
219 : NativeWidgetAura(delegate),
220 check_if_capture_lost_(false) {
223 void set_check_if_capture_lost(bool value) {
224 check_if_capture_lost_ = value;
227 virtual void OnCaptureLost() OVERRIDE {
228 DCHECK(!check_if_capture_lost_);
229 views::NativeWidgetAura::OnCaptureLost();
232 private:
233 bool check_if_capture_lost_;
235 DISALLOW_COPY_AND_ASSIGN(TestNativeWidgetAura);
238 // TODO(sky): this is for debugging, remove when track down failure.
239 void SetCheckIfCaptureLost(views::Widget* widget, bool value) {
240 // On Windows, the DCHECK triggers when running on bot or locally through RDP,
241 // but not when logged in locally.
242 #if !defined(OS_WIN)
243 static_cast<TestNativeWidgetAura*>(widget->native_widget())->
244 set_check_if_capture_lost(value);
245 #endif
248 views::Widget* CreateNewWidget() {
249 views::Widget* widget = new views::Widget;
250 views::Widget::InitParams params;
251 params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
252 params.accept_events = true;
253 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
254 params.parent = Shell::GetPrimaryRootWindow();
255 params.child = true;
256 params.native_widget = new TestNativeWidgetAura(widget);
257 widget->Init(params);
258 widget->Show();
259 return widget;
262 void AddViewToWidgetAndResize(views::Widget* widget, views::View* view) {
263 if (!widget->GetContentsView()) {
264 views::View* contents_view = new views::View;
265 widget->SetContentsView(contents_view);
268 views::View* contents_view = widget->GetContentsView();
269 contents_view->AddChildView(view);
270 view->SetBounds(contents_view->width(), 0, 100, 100);
271 gfx::Rect contents_view_bounds = contents_view->bounds();
272 contents_view_bounds.Union(view->bounds());
273 contents_view->SetBoundsRect(contents_view_bounds);
274 widget->SetBounds(contents_view_bounds);
277 void DispatchGesture(ui::EventType gesture_type, gfx::Point location) {
278 ui::GestureEvent gesture_event(
279 gesture_type,
280 location.x(),
281 location.y(),
283 ui::EventTimeForNow(),
284 ui::GestureEventDetails(gesture_type, 0, 0),
286 Shell::GetPrimaryRootWindow()->DispatchGestureEvent(&gesture_event);
289 bool IsGestureEventType(ui::EventType type) {
290 switch (type) {
291 case ui::ET_GESTURE_SCROLL_BEGIN:
292 case ui::ET_GESTURE_SCROLL_END:
293 case ui::ET_GESTURE_SCROLL_UPDATE:
294 case ui::ET_GESTURE_TAP:
295 case ui::ET_GESTURE_TAP_CANCEL:
296 case ui::ET_GESTURE_TAP_DOWN:
297 case ui::ET_GESTURE_BEGIN:
298 case ui::ET_GESTURE_END:
299 case ui::ET_GESTURE_TWO_FINGER_TAP:
300 case ui::ET_GESTURE_PINCH_BEGIN:
301 case ui::ET_GESTURE_PINCH_END:
302 case ui::ET_GESTURE_PINCH_UPDATE:
303 case ui::ET_GESTURE_LONG_PRESS:
304 case ui::ET_GESTURE_LONG_TAP:
305 case ui::ET_GESTURE_MULTIFINGER_SWIPE:
306 case ui::ET_SCROLL_FLING_CANCEL:
307 case ui::ET_SCROLL_FLING_START:
308 return true;
309 default:
310 break;
312 return false;
315 } // namespace
317 class DragDropControllerTest : public AshTestBase {
318 public:
319 DragDropControllerTest() : AshTestBase() {}
320 virtual ~DragDropControllerTest() {}
322 virtual void SetUp() OVERRIDE {
323 AshTestBase::SetUp();
324 drag_drop_controller_.reset(new TestDragDropController);
325 drag_drop_controller_->set_should_block_during_drag_drop(false);
326 aura::client::SetDragDropClient(Shell::GetPrimaryRootWindow(),
327 drag_drop_controller_.get());
328 views_delegate_.reset(new views::TestViewsDelegate);
331 virtual void TearDown() OVERRIDE {
332 aura::client::SetDragDropClient(Shell::GetPrimaryRootWindow(), NULL);
333 drag_drop_controller_.reset();
334 AshTestBase::TearDown();
337 void UpdateDragData(ui::OSExchangeData* data) {
338 drag_drop_controller_->drag_data_ = data;
341 aura::Window* GetDragWindow() {
342 return drag_drop_controller_->drag_window_;
345 aura::Window* GetDragSourceWindow() {
346 return drag_drop_controller_->drag_source_window_;
349 void SetDragSourceWindow(aura::Window* drag_source_window) {
350 drag_drop_controller_->drag_source_window_ = drag_source_window;
351 drag_source_window->AddObserver(drag_drop_controller_.get());
354 aura::Window* GetDragImageWindow() {
355 return drag_drop_controller_->drag_image_.get() ?
356 drag_drop_controller_->drag_image_->GetWidget()->GetNativeWindow() :
357 NULL;
360 internal::DragDropTracker* drag_drop_tracker() {
361 return drag_drop_controller_->drag_drop_tracker_.get();
364 void CompleteCancelAnimation() {
365 CompletableLinearAnimation* animation =
366 static_cast<CompletableLinearAnimation*>(
367 drag_drop_controller_->cancel_animation_.get());
368 animation->Complete();
371 protected:
372 scoped_ptr<TestDragDropController> drag_drop_controller_;
373 scoped_ptr<views::TestViewsDelegate> views_delegate_;
375 private:
376 DISALLOW_COPY_AND_ASSIGN(DragDropControllerTest);
379 // TODO(win_aura) http://crbug.com/154081
380 #if defined(OS_WIN)
381 #define MAYBE_DragDropInSingleViewTest DISABLED_DragDropInSingleViewTest
382 #else
383 #define MAYBE_DragDropInSingleViewTest DragDropInSingleViewTest
384 #endif
385 TEST_F(DragDropControllerTest, MAYBE_DragDropInSingleViewTest) {
386 scoped_ptr<views::Widget> widget(CreateNewWidget());
387 DragTestView* drag_view = new DragTestView;
388 AddViewToWidgetAndResize(widget.get(), drag_view);
389 ui::OSExchangeData data;
390 data.SetString(UTF8ToUTF16("I am being dragged"));
391 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
392 widget->GetNativeView());
393 generator.PressLeftButton();
395 int num_drags = 17;
396 SetCheckIfCaptureLost(widget.get(), true);
397 for (int i = 0; i < num_drags; ++i) {
398 // Because we are not doing a blocking drag and drop, the original
399 // OSDragExchangeData object is lost as soon as we return from the drag
400 // initiation in DragDropController::StartDragAndDrop(). Hence we set the
401 // drag_data_ to a fake drag data object that we created.
402 if (i > 0)
403 UpdateDragData(&data);
404 // 7 comes from views::View::GetVerticalDragThreshold()).
405 if (i >= 7)
406 SetCheckIfCaptureLost(widget.get(), false);
408 generator.MoveMouseBy(0, 1);
410 // Execute any scheduled draws to process deferred mouse events.
411 RunAllPendingInMessageLoop();
414 generator.ReleaseLeftButton();
416 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
417 EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
418 drag_drop_controller_->num_drag_updates_);
419 EXPECT_TRUE(drag_drop_controller_->drop_received_);
420 EXPECT_EQ(UTF8ToUTF16("I am being dragged"),
421 drag_drop_controller_->drag_string_);
423 EXPECT_EQ(1, drag_view->num_drag_enters_);
424 EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
425 drag_view->num_drag_updates_);
426 EXPECT_EQ(1, drag_view->num_drops_);
427 EXPECT_EQ(0, drag_view->num_drag_exits_);
428 EXPECT_TRUE(drag_view->drag_done_received_);
431 TEST_F(DragDropControllerTest, DragDropWithZeroDragUpdates) {
432 scoped_ptr<views::Widget> widget(CreateNewWidget());
433 DragTestView* drag_view = new DragTestView;
434 AddViewToWidgetAndResize(widget.get(), drag_view);
435 ui::OSExchangeData data;
436 data.SetString(UTF8ToUTF16("I am being dragged"));
437 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
438 widget->GetNativeView());
439 generator.PressLeftButton();
441 int num_drags = drag_view->VerticalDragThreshold() + 1;
442 for (int i = 0; i < num_drags; ++i) {
443 // Because we are not doing a blocking drag and drop, the original
444 // OSDragExchangeData object is lost as soon as we return from the drag
445 // initiation in DragDropController::StartDragAndDrop(). Hence we set the
446 // drag_data_ to a fake drag data object that we created.
447 if (i > 0)
448 UpdateDragData(&data);
449 generator.MoveMouseBy(0, 1);
452 UpdateDragData(&data);
454 generator.ReleaseLeftButton();
456 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
457 EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold() + 1,
458 drag_drop_controller_->num_drag_updates_);
459 EXPECT_TRUE(drag_drop_controller_->drop_received_);
461 EXPECT_EQ(1, drag_view->num_drag_enters_);
462 EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold() + 1,
463 drag_view->num_drag_updates_);
464 EXPECT_EQ(1, drag_view->num_drops_);
465 EXPECT_EQ(0, drag_view->num_drag_exits_);
466 EXPECT_TRUE(drag_view->drag_done_received_);
469 // TODO(win_aura) http://crbug.com/154081
470 #if defined(OS_WIN)
471 #define MAYBE_DragDropInMultipleViewsSingleWidgetTest DISABLED_DragDropInMultipleViewsSingleWidgetTest
472 #else
473 #define MAYBE_DragDropInMultipleViewsSingleWidgetTest DragDropInMultipleViewsSingleWidgetTest
474 #endif
475 TEST_F(DragDropControllerTest, MAYBE_DragDropInMultipleViewsSingleWidgetTest) {
476 scoped_ptr<views::Widget> widget(CreateNewWidget());
477 DragTestView* drag_view1 = new DragTestView;
478 AddViewToWidgetAndResize(widget.get(), drag_view1);
479 DragTestView* drag_view2 = new DragTestView;
480 AddViewToWidgetAndResize(widget.get(), drag_view2);
482 ui::OSExchangeData data;
483 data.SetString(UTF8ToUTF16("I am being dragged"));
485 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
486 generator.MoveMouseRelativeTo(widget->GetNativeView(),
487 drag_view1->bounds().CenterPoint());
488 generator.PressLeftButton();
490 int num_drags = drag_view1->width();
491 for (int i = 0; i < num_drags; ++i) {
492 // Because we are not doing a blocking drag and drop, the original
493 // OSDragExchangeData object is lost as soon as we return from the drag
494 // initiation in DragDropController::StartDragAndDrop(). Hence we set the
495 // drag_data_ to a fake drag data object that we created.
496 if (i > 0)
497 UpdateDragData(&data);
498 generator.MoveMouseBy(1, 0);
500 // Execute any scheduled draws to process deferred mouse events.
501 RunAllPendingInMessageLoop();
504 generator.ReleaseLeftButton();
506 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
507 EXPECT_EQ(num_drags - 1 - drag_view1->HorizontalDragThreshold(),
508 drag_drop_controller_->num_drag_updates_);
509 EXPECT_TRUE(drag_drop_controller_->drop_received_);
510 EXPECT_EQ(UTF8ToUTF16("I am being dragged"),
511 drag_drop_controller_->drag_string_);
513 EXPECT_EQ(1, drag_view1->num_drag_enters_);
514 int num_expected_updates = drag_view1->bounds().width() -
515 drag_view1->bounds().CenterPoint().x() - 2;
516 EXPECT_EQ(num_expected_updates - drag_view1->HorizontalDragThreshold(),
517 drag_view1->num_drag_updates_);
518 EXPECT_EQ(0, drag_view1->num_drops_);
519 EXPECT_EQ(1, drag_view1->num_drag_exits_);
520 EXPECT_TRUE(drag_view1->drag_done_received_);
522 EXPECT_EQ(1, drag_view2->num_drag_enters_);
523 num_expected_updates = num_drags - num_expected_updates - 1;
524 EXPECT_EQ(num_expected_updates, drag_view2->num_drag_updates_);
525 EXPECT_EQ(1, drag_view2->num_drops_);
526 EXPECT_EQ(0, drag_view2->num_drag_exits_);
527 EXPECT_FALSE(drag_view2->drag_done_received_);
530 // TODO(win_aura) http://crbug.com/154081
531 #if defined(OS_WIN)
532 #define MAYBE_DragDropInMultipleViewsMultipleWidgetsTest DISABLED_DragDropInMultipleViewsMultipleWidgetsTest
533 #else
534 #define MAYBE_DragDropInMultipleViewsMultipleWidgetsTest DragDropInMultipleViewsMultipleWidgetsTest
535 #endif
536 TEST_F(DragDropControllerTest, MAYBE_DragDropInMultipleViewsMultipleWidgetsTest) {
537 scoped_ptr<views::Widget> widget1(CreateNewWidget());
538 DragTestView* drag_view1 = new DragTestView;
539 AddViewToWidgetAndResize(widget1.get(), drag_view1);
540 scoped_ptr<views::Widget> widget2(CreateNewWidget());
541 DragTestView* drag_view2 = new DragTestView;
542 AddViewToWidgetAndResize(widget2.get(), drag_view2);
543 gfx::Rect widget1_bounds = widget1->GetClientAreaBoundsInScreen();
544 gfx::Rect widget2_bounds = widget2->GetClientAreaBoundsInScreen();
545 widget2->SetBounds(gfx::Rect(widget1_bounds.width(), 0,
546 widget2_bounds.width(), widget2_bounds.height()));
548 ui::OSExchangeData data;
549 data.SetString(UTF8ToUTF16("I am being dragged"));
551 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
552 widget1->GetNativeView());
553 generator.PressLeftButton();
555 int num_drags = drag_view1->width();
556 for (int i = 0; i < num_drags; ++i) {
557 // Because we are not doing a blocking drag and drop, the original
558 // OSDragExchangeData object is lost as soon as we return from the drag
559 // initiation in DragDropController::StartDragAndDrop(). Hence we set the
560 // drag_data_ to a fake drag data object that we created.
561 if (i > 0)
562 UpdateDragData(&data);
563 generator.MoveMouseBy(1, 0);
565 // Execute any scheduled draws to process deferred mouse events.
566 RunAllPendingInMessageLoop();
569 generator.ReleaseLeftButton();
571 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
572 EXPECT_EQ(num_drags - 1 - drag_view1->HorizontalDragThreshold(),
573 drag_drop_controller_->num_drag_updates_);
574 EXPECT_TRUE(drag_drop_controller_->drop_received_);
575 EXPECT_EQ(UTF8ToUTF16("I am being dragged"),
576 drag_drop_controller_->drag_string_);
578 EXPECT_EQ(1, drag_view1->num_drag_enters_);
579 int num_expected_updates = drag_view1->bounds().width() -
580 drag_view1->bounds().CenterPoint().x() - 2;
581 EXPECT_EQ(num_expected_updates - drag_view1->HorizontalDragThreshold(),
582 drag_view1->num_drag_updates_);
583 EXPECT_EQ(0, drag_view1->num_drops_);
584 EXPECT_EQ(1, drag_view1->num_drag_exits_);
585 EXPECT_TRUE(drag_view1->drag_done_received_);
587 EXPECT_EQ(1, drag_view2->num_drag_enters_);
588 num_expected_updates = num_drags - num_expected_updates - 1;
589 EXPECT_EQ(num_expected_updates, drag_view2->num_drag_updates_);
590 EXPECT_EQ(1, drag_view2->num_drops_);
591 EXPECT_EQ(0, drag_view2->num_drag_exits_);
592 EXPECT_FALSE(drag_view2->drag_done_received_);
595 // TODO(win_aura) http://crbug.com/154081
596 #if defined(OS_WIN)
597 #define MAYBE_ViewRemovedWhileInDragDropTest DISABLED_ViewRemovedWhileInDragDropTest
598 #else
599 #define MAYBE_ViewRemovedWhileInDragDropTest ViewRemovedWhileInDragDropTest
600 #endif
601 TEST_F(DragDropControllerTest, MAYBE_ViewRemovedWhileInDragDropTest) {
602 scoped_ptr<views::Widget> widget(CreateNewWidget());
603 scoped_ptr<DragTestView> drag_view(new DragTestView);
604 AddViewToWidgetAndResize(widget.get(), drag_view.get());
605 gfx::Point point = gfx::Rect(drag_view->bounds()).CenterPoint();
606 ui::OSExchangeData data;
607 data.SetString(UTF8ToUTF16("I am being dragged"));
609 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
610 generator.MoveMouseToCenterOf(widget->GetNativeView());
611 generator.PressLeftButton();
613 int num_drags_1 = 17;
614 for (int i = 0; i < num_drags_1; ++i) {
615 // Because we are not doing a blocking drag and drop, the original
616 // OSDragExchangeData object is lost as soon as we return from the drag
617 // initiation in DragDropController::StartDragAndDrop(). Hence we set the
618 // drag_data_ to a fake drag data object that we created.
619 if (i > 0)
620 UpdateDragData(&data);
621 generator.MoveMouseBy(0, 1);
623 // Execute any scheduled draws to process deferred mouse events.
624 RunAllPendingInMessageLoop();
627 drag_view->parent()->RemoveChildView(drag_view.get());
628 // View has been removed. We will not get any of the following drag updates.
629 int num_drags_2 = 23;
630 for (int i = 0; i < num_drags_2; ++i) {
631 UpdateDragData(&data);
632 generator.MoveMouseBy(0, 1);
634 // Execute any scheduled draws to process deferred mouse events.
635 RunAllPendingInMessageLoop();
638 generator.ReleaseLeftButton();
640 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
641 EXPECT_EQ(num_drags_1 + num_drags_2 - 1 - drag_view->VerticalDragThreshold(),
642 drag_drop_controller_->num_drag_updates_);
643 EXPECT_TRUE(drag_drop_controller_->drop_received_);
644 EXPECT_EQ(UTF8ToUTF16("I am being dragged"),
645 drag_drop_controller_->drag_string_);
647 EXPECT_EQ(1, drag_view->num_drag_enters_);
648 EXPECT_EQ(num_drags_1 - 1 - drag_view->VerticalDragThreshold(),
649 drag_view->num_drag_updates_);
650 EXPECT_EQ(0, drag_view->num_drops_);
651 EXPECT_EQ(0, drag_view->num_drag_exits_);
652 EXPECT_TRUE(drag_view->drag_done_received_);
655 TEST_F(DragDropControllerTest, DragLeavesClipboardAloneTest) {
656 ui::Clipboard* cb = ui::Clipboard::GetForCurrentThread();
657 std::string clip_str("I am on the clipboard");
659 // We first copy some text to the clipboard.
660 ui::ScopedClipboardWriter scw(cb, ui::Clipboard::BUFFER_STANDARD);
661 scw.WriteText(ASCIIToUTF16(clip_str));
663 EXPECT_TRUE(cb->IsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(),
664 ui::Clipboard::BUFFER_STANDARD));
666 scoped_ptr<views::Widget> widget(CreateNewWidget());
667 DragTestView* drag_view = new DragTestView;
668 AddViewToWidgetAndResize(widget.get(), drag_view);
670 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
671 widget->GetNativeView());
672 ui::OSExchangeData data;
673 std::string data_str("I am being dragged");
674 data.SetString(ASCIIToUTF16(data_str));
676 generator.PressLeftButton();
677 generator.MoveMouseBy(0, drag_view->VerticalDragThreshold() + 1);
679 // Execute any scheduled draws to process deferred mouse events.
680 RunAllPendingInMessageLoop();
682 // Verify the clipboard contents haven't changed
683 std::string result;
684 EXPECT_TRUE(cb->IsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(),
685 ui::Clipboard::BUFFER_STANDARD));
686 cb->ReadAsciiText(ui::Clipboard::BUFFER_STANDARD, &result);
687 EXPECT_EQ(clip_str, result);
688 // Destory the clipboard here because ash doesn't delete it.
689 // crbug.com/158150.
690 ui::Clipboard::DestroyClipboardForCurrentThread();
693 TEST_F(DragDropControllerTest, WindowDestroyedDuringDragDrop) {
694 scoped_ptr<views::Widget> widget(CreateNewWidget());
695 DragTestView* drag_view = new DragTestView;
696 AddViewToWidgetAndResize(widget.get(), drag_view);
697 aura::Window* window = widget->GetNativeView();
699 ui::OSExchangeData data;
700 data.SetString(UTF8ToUTF16("I am being dragged"));
701 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
702 widget->GetNativeView());
703 generator.PressLeftButton();
705 int num_drags = 17;
706 for (int i = 0; i < num_drags; ++i) {
707 // Because we are not doing a blocking drag and drop, the original
708 // OSDragExchangeData object is lost as soon as we return from the drag
709 // initiation in DragDropController::StartDragAndDrop(). Hence we set the
710 // drag_data_ to a fake drag data object that we created.
711 if (i > 0)
712 UpdateDragData(&data);
713 generator.MoveMouseBy(0, 1);
715 // Execute any scheduled draws to process deferred mouse events.
716 RunAllPendingInMessageLoop();
718 if (i > drag_view->VerticalDragThreshold())
719 EXPECT_EQ(window, GetDragWindow());
722 widget->CloseNow();
723 EXPECT_FALSE(GetDragWindow());
725 num_drags = 23;
726 for (int i = 0; i < num_drags; ++i) {
727 if (i > 0)
728 UpdateDragData(&data);
729 generator.MoveMouseBy(0, 1);
730 // We should not crash here.
733 generator.ReleaseLeftButton();
735 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
736 EXPECT_TRUE(drag_drop_controller_->drop_received_);
739 TEST_F(DragDropControllerTest, SyntheticEventsDuringDragDrop) {
740 scoped_ptr<views::Widget> widget(CreateNewWidget());
741 DragTestView* drag_view = new DragTestView;
742 AddViewToWidgetAndResize(widget.get(), drag_view);
743 ui::OSExchangeData data;
744 data.SetString(UTF8ToUTF16("I am being dragged"));
745 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
746 widget->GetNativeView());
747 generator.PressLeftButton();
749 int num_drags = 17;
750 for (int i = 0; i < num_drags; ++i) {
751 // Because we are not doing a blocking drag and drop, the original
752 // OSDragExchangeData object is lost as soon as we return from the drag
753 // initiation in DragDropController::StartDragAndDrop(). Hence we set the
754 // drag_data_ to a fake drag data object that we created.
755 if (i > 0)
756 UpdateDragData(&data);
757 generator.MoveMouseBy(0, 1);
759 // We send a unexpected mouse move event. Note that we cannot use
760 // EventGenerator since it implicitly turns these into mouse drag events.
761 // The DragDropController should simply ignore these events.
762 gfx::Point mouse_move_location = drag_view->bounds().CenterPoint();
763 ui::MouseEvent mouse_move(ui::ET_MOUSE_MOVED, mouse_move_location,
764 mouse_move_location, 0);
765 Shell::GetPrimaryRootWindow()->AsRootWindowHostDelegate()->OnHostMouseEvent(
766 &mouse_move);
769 generator.ReleaseLeftButton();
771 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
772 EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
773 drag_drop_controller_->num_drag_updates_);
774 EXPECT_TRUE(drag_drop_controller_->drop_received_);
775 EXPECT_EQ(UTF8ToUTF16("I am being dragged"),
776 drag_drop_controller_->drag_string_);
778 EXPECT_EQ(1, drag_view->num_drag_enters_);
779 EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
780 drag_view->num_drag_updates_);
781 EXPECT_EQ(1, drag_view->num_drops_);
782 EXPECT_EQ(0, drag_view->num_drag_exits_);
783 EXPECT_TRUE(drag_view->drag_done_received_);
786 // TODO(win_aura) http://crbug.com/154081
787 #if defined(OS_WIN)
788 #define MAYBE_PressingEscapeCancelsDragDrop DISABLED_PressingEscapeCancelsDragDrop
789 #define MAYBE_CaptureLostCancelsDragDrop DISABLED_CaptureLostCancelsDragDrop
790 #else
791 #define MAYBE_PressingEscapeCancelsDragDrop PressingEscapeCancelsDragDrop
792 #define MAYBE_CaptureLostCancelsDragDrop CaptureLostCancelsDragDrop
793 #endif
794 TEST_F(DragDropControllerTest, MAYBE_PressingEscapeCancelsDragDrop) {
795 scoped_ptr<views::Widget> widget(CreateNewWidget());
796 DragTestView* drag_view = new DragTestView;
797 AddViewToWidgetAndResize(widget.get(), drag_view);
798 ui::OSExchangeData data;
799 data.SetString(UTF8ToUTF16("I am being dragged"));
800 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
801 widget->GetNativeView());
802 generator.PressLeftButton();
804 int num_drags = 17;
805 for (int i = 0; i < num_drags; ++i) {
806 // Because we are not doing a blocking drag and drop, the original
807 // OSDragExchangeData object is lost as soon as we return from the drag
808 // initiation in DragDropController::StartDragAndDrop(). Hence we set the
809 // drag_data_ to a fake drag data object that we created.
810 if (i > 0)
811 UpdateDragData(&data);
812 generator.MoveMouseBy(0, 1);
814 // Execute any scheduled draws to process deferred mouse events.
815 RunAllPendingInMessageLoop();
818 generator.PressKey(ui::VKEY_ESCAPE, 0);
820 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
821 EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
822 drag_drop_controller_->num_drag_updates_);
823 EXPECT_FALSE(drag_drop_controller_->drop_received_);
824 EXPECT_TRUE(drag_drop_controller_->drag_canceled_);
825 EXPECT_EQ(UTF8ToUTF16("I am being dragged"),
826 drag_drop_controller_->drag_string_);
828 EXPECT_EQ(1, drag_view->num_drag_enters_);
829 EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
830 drag_view->num_drag_updates_);
831 EXPECT_EQ(0, drag_view->num_drops_);
832 EXPECT_EQ(1, drag_view->num_drag_exits_);
833 EXPECT_TRUE(drag_view->drag_done_received_);
836 TEST_F(DragDropControllerTest, MAYBE_CaptureLostCancelsDragDrop) {
837 scoped_ptr<views::Widget> widget(CreateNewWidget());
838 DragTestView* drag_view = new DragTestView;
839 AddViewToWidgetAndResize(widget.get(), drag_view);
840 ui::OSExchangeData data;
841 data.SetString(UTF8ToUTF16("I am being dragged"));
842 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
843 widget->GetNativeView());
844 generator.PressLeftButton();
846 int num_drags = 17;
847 for (int i = 0; i < num_drags; ++i) {
848 // Because we are not doing a blocking drag and drop, the original
849 // OSDragExchangeData object is lost as soon as we return from the drag
850 // initiation in DragDropController::StartDragAndDrop(). Hence we set the
851 // drag_data_ to a fake drag data object that we created.
852 if (i > 0)
853 UpdateDragData(&data);
854 generator.MoveMouseBy(0, 1);
856 // Execute any scheduled draws to process deferred mouse events.
857 RunAllPendingInMessageLoop();
859 // Make sure the capture window won't handle mouse events.
860 aura::Window* capture_window = drag_drop_tracker()->capture_window();
861 ASSERT_TRUE(!!capture_window);
862 EXPECT_EQ("0x0", capture_window->bounds().size().ToString());
863 EXPECT_EQ(NULL,
864 capture_window->GetEventHandlerForPoint(gfx::Point()));
865 EXPECT_EQ(NULL,
866 capture_window->GetTopWindowContainingPoint(gfx::Point()));
868 aura::client::GetCaptureClient(widget->GetNativeView()->GetRootWindow())->
869 SetCapture(NULL);
871 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
872 EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
873 drag_drop_controller_->num_drag_updates_);
874 EXPECT_FALSE(drag_drop_controller_->drop_received_);
875 EXPECT_TRUE(drag_drop_controller_->drag_canceled_);
876 EXPECT_EQ(UTF8ToUTF16("I am being dragged"),
877 drag_drop_controller_->drag_string_);
879 EXPECT_EQ(1, drag_view->num_drag_enters_);
880 EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
881 drag_view->num_drag_updates_);
882 EXPECT_EQ(0, drag_view->num_drops_);
883 EXPECT_EQ(1, drag_view->num_drag_exits_);
884 EXPECT_TRUE(drag_view->drag_done_received_);
887 TEST_F(DragDropControllerTest, TouchDragDropInMultipleWindows) {
888 CommandLine::ForCurrentProcess()->AppendSwitch(
889 switches::kEnableTouchDragDrop);
890 scoped_ptr<views::Widget> widget1(CreateNewWidget());
891 DragTestView* drag_view1 = new DragTestView;
892 AddViewToWidgetAndResize(widget1.get(), drag_view1);
893 scoped_ptr<views::Widget> widget2(CreateNewWidget());
894 DragTestView* drag_view2 = new DragTestView;
895 AddViewToWidgetAndResize(widget2.get(), drag_view2);
896 gfx::Rect widget1_bounds = widget1->GetClientAreaBoundsInScreen();
897 gfx::Rect widget2_bounds = widget2->GetClientAreaBoundsInScreen();
898 widget2->SetBounds(gfx::Rect(widget1_bounds.width(), 0,
899 widget2_bounds.width(), widget2_bounds.height()));
901 ui::OSExchangeData data;
902 data.SetString(UTF8ToUTF16("I am being dragged"));
904 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
905 widget1->GetNativeView());
906 generator.PressTouch();
907 gfx::Point point = gfx::Rect(drag_view1->bounds()).CenterPoint();
908 DispatchGesture(ui::ET_GESTURE_LONG_PRESS, point);
909 // Because we are not doing a blocking drag and drop, the original
910 // OSDragExchangeData object is lost as soon as we return from the drag
911 // initiation in DragDropController::StartDragAndDrop(). Hence we set the
912 // drag_data_ to a fake drag data object that we created.
913 UpdateDragData(&data);
914 gfx::Point gesture_location = point;
915 int num_drags = drag_view1->width();
916 for (int i = 0; i < num_drags; ++i) {
917 gesture_location.Offset(1, 0);
918 DispatchGesture(ui::ET_GESTURE_SCROLL_UPDATE, gesture_location);
920 // Execute any scheduled draws to process deferred mouse events.
921 RunAllPendingInMessageLoop();
924 DispatchGesture(ui::ET_GESTURE_SCROLL_END, gesture_location);
926 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
927 EXPECT_EQ(num_drags, drag_drop_controller_->num_drag_updates_);
928 EXPECT_TRUE(drag_drop_controller_->drop_received_);
929 EXPECT_EQ(UTF8ToUTF16("I am being dragged"),
930 drag_drop_controller_->drag_string_);
932 EXPECT_EQ(1, drag_view1->num_drag_enters_);
933 int num_expected_updates = drag_view1->bounds().width() -
934 drag_view1->bounds().CenterPoint().x() - 1;
935 EXPECT_EQ(num_expected_updates, drag_view1->num_drag_updates_);
936 EXPECT_EQ(0, drag_view1->num_drops_);
937 EXPECT_EQ(1, drag_view1->num_drag_exits_);
938 EXPECT_TRUE(drag_view1->drag_done_received_);
940 EXPECT_EQ(1, drag_view2->num_drag_enters_);
941 num_expected_updates = num_drags - num_expected_updates;
942 EXPECT_EQ(num_expected_updates, drag_view2->num_drag_updates_);
943 EXPECT_EQ(1, drag_view2->num_drops_);
944 EXPECT_EQ(0, drag_view2->num_drag_exits_);
945 EXPECT_FALSE(drag_view2->drag_done_received_);
948 TEST_F(DragDropControllerTest, TouchDragDropCancelsOnLongTap) {
949 CommandLine::ForCurrentProcess()->AppendSwitch(
950 switches::kEnableTouchDragDrop);
951 scoped_ptr<views::Widget> widget(CreateNewWidget());
952 DragTestView* drag_view = new DragTestView;
953 AddViewToWidgetAndResize(widget.get(), drag_view);
954 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
955 widget->GetNativeView());
957 generator.PressTouch();
958 gfx::Point point = gfx::Rect(drag_view->bounds()).CenterPoint();
959 DispatchGesture(ui::ET_GESTURE_LONG_PRESS, point);
960 DispatchGesture(ui::ET_GESTURE_LONG_TAP, point);
962 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
963 EXPECT_TRUE(drag_drop_controller_->drag_canceled_);
964 EXPECT_EQ(0, drag_drop_controller_->num_drag_updates_);
965 EXPECT_FALSE(drag_drop_controller_->drop_received_);
966 EXPECT_EQ(UTF8ToUTF16("I am being dragged"),
967 drag_drop_controller_->drag_string_);
968 EXPECT_EQ(0, drag_view->num_drag_enters_);
969 EXPECT_EQ(0, drag_view->num_drops_);
970 EXPECT_EQ(0, drag_view->num_drag_exits_);
971 EXPECT_TRUE(drag_view->drag_done_received_);
974 TEST_F(DragDropControllerTest, TouchDragDropLongTapGestureIsForwarded) {
975 CommandLine::ForCurrentProcess()->AppendSwitch(
976 switches::kEnableTouchDragDrop);
977 scoped_ptr<views::Widget> widget(CreateNewWidget());
978 DragTestView* drag_view = new DragTestView;
979 AddViewToWidgetAndResize(widget.get(), drag_view);
980 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
981 widget->GetNativeView());
983 generator.PressTouch();
984 gfx::Point point = gfx::Rect(drag_view->bounds()).CenterPoint();
985 DispatchGesture(ui::ET_GESTURE_LONG_PRESS, point);
987 // Since we are not running inside a nested loop, the |drag_source_window_|
988 // will get destroyed immediately. Hence we reassign it.
989 EXPECT_EQ(NULL, GetDragSourceWindow());
990 SetDragSourceWindow(widget->GetNativeView());
991 EXPECT_FALSE(drag_view->long_tap_received_);
992 DispatchGesture(ui::ET_GESTURE_LONG_TAP, point);
993 CompleteCancelAnimation();
994 EXPECT_TRUE(drag_view->long_tap_received_);
997 namespace {
999 class DragImageWindowObserver : public aura::WindowObserver {
1000 public:
1001 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
1002 window_location_on_destroying_ = window->GetBoundsInScreen().origin();
1005 gfx::Point window_location_on_destroying() const {
1006 return window_location_on_destroying_;
1009 public:
1010 gfx::Point window_location_on_destroying_;
1015 // Verifies the drag image moves back to the position where drag is started
1016 // across displays when drag is cancelled.
1017 TEST_F(DragDropControllerTest, DragCancelAcrossDisplays) {
1018 if (!SupportsMultipleDisplays())
1019 return;
1021 UpdateDisplay("400x400,400x400");
1022 Shell::RootWindowList root_windows =
1023 Shell::GetInstance()->GetAllRootWindows();
1024 for (Shell::RootWindowList::iterator iter = root_windows.begin();
1025 iter != root_windows.end(); ++iter) {
1026 aura::client::SetDragDropClient(*iter, drag_drop_controller_.get());
1029 ui::OSExchangeData data;
1030 data.SetString(UTF8ToUTF16("I am being dragged"));
1032 scoped_ptr<views::Widget> widget(CreateNewWidget());
1033 aura::Window* window = widget->GetNativeWindow();
1034 drag_drop_controller_->StartDragAndDrop(
1035 data,
1036 window->GetRootWindow(),
1037 window,
1038 gfx::Point(5, 5),
1039 ui::DragDropTypes::DRAG_MOVE,
1040 ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
1042 DragImageWindowObserver observer;
1043 ASSERT_TRUE(GetDragImageWindow());
1044 GetDragImageWindow()->AddObserver(&observer);
1047 ui::MouseEvent e(ui::ET_MOUSE_DRAGGED,
1048 gfx::Point(200, 0),
1049 gfx::Point(200, 0),
1050 ui::EF_NONE);
1051 drag_drop_controller_->DragUpdate(window, e);
1054 ui::MouseEvent e(ui::ET_MOUSE_DRAGGED,
1055 gfx::Point(600, 0),
1056 gfx::Point(600, 0),
1057 ui::EF_NONE);
1058 drag_drop_controller_->DragUpdate(window, e);
1061 drag_drop_controller_->DragCancel();
1062 CompleteCancelAnimation();
1064 EXPECT_EQ("5,5", observer.window_location_on_destroying().ToString());
1068 scoped_ptr<views::Widget> widget(CreateNewWidget());
1069 aura::Window* window = widget->GetNativeWindow();
1070 drag_drop_controller_->StartDragAndDrop(
1071 data,
1072 window->GetRootWindow(),
1073 window,
1074 gfx::Point(405, 405),
1075 ui::DragDropTypes::DRAG_MOVE,
1076 ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
1077 DragImageWindowObserver observer;
1078 ASSERT_TRUE(GetDragImageWindow());
1079 GetDragImageWindow()->AddObserver(&observer);
1082 ui::MouseEvent e(ui::ET_MOUSE_DRAGGED,
1083 gfx::Point(600, 0),
1084 gfx::Point(600, 0),
1085 ui::EF_NONE);
1086 drag_drop_controller_->DragUpdate(window, e);
1089 ui::MouseEvent e(ui::ET_MOUSE_DRAGGED,
1090 gfx::Point(200, 0),
1091 gfx::Point(200, 0),
1092 ui::EF_NONE);
1093 drag_drop_controller_->DragUpdate(window, e);
1096 drag_drop_controller_->DragCancel();
1097 CompleteCancelAnimation();
1099 EXPECT_EQ("405,405", observer.window_location_on_destroying().ToString());
1101 for (Shell::RootWindowList::iterator iter = root_windows.begin();
1102 iter != root_windows.end(); ++iter) {
1103 aura::client::SetDragDropClient(*iter, NULL);
1107 } // namespace test
1108 } // namespace aura