Update parsing of dumpsys batterystats
[chromium-blink-merge.git] / ash / drag_drop / drag_drop_controller_unittest.cc
blobc45ba680734373535f1ee948f42b1034dbf02086
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/test/event_generator.h"
16 #include "ui/aura/window_event_dispatcher.h"
17 #include "ui/aura/window_tree_host.h"
18 #include "ui/base/clipboard/clipboard.h"
19 #include "ui/base/clipboard/scoped_clipboard_writer.h"
20 #include "ui/base/dragdrop/drag_drop_types.h"
21 #include "ui/base/dragdrop/drag_utils.h"
22 #include "ui/base/dragdrop/os_exchange_data.h"
23 #include "ui/base/ui_base_switches.h"
24 #include "ui/events/event.h"
25 #include "ui/events/event_utils.h"
26 #include "ui/events/gestures/gesture_types.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"
36 namespace ash {
37 namespace test {
39 namespace {
41 // A simple view that makes sure RunShellDrag is invoked on mouse drag.
42 class DragTestView : public views::View {
43 public:
44 DragTestView() : views::View() {
45 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;
57 int VerticalDragThreshold() {
58 return views::View::GetVerticalDragThreshold();
61 int HorizontalDragThreshold() {
62 return views::View::GetHorizontalDragThreshold();
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_;
72 private:
73 // View overrides:
74 virtual int GetDragOperations(const gfx::Point& press_pt) OVERRIDE {
75 return ui::DragDropTypes::DRAG_COPY;
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);
84 drag_utils::SetDragImageOnDataObject(image_skia, 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 DragDropController {
151 public:
152 TestDragDropController() : DragDropController() { 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();
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);
175 virtual void DragUpdate(aura::Window* target,
176 const ui::LocatedEvent& event) OVERRIDE {
177 DragDropController::DragUpdate(target, event);
178 num_drag_updates_++;
181 virtual void Drop(aura::Window* target,
182 const ui::LocatedEvent& event) OVERRIDE {
183 DragDropController::Drop(target, event);
184 drop_received_ = true;
187 virtual void DragCancel() OVERRIDE {
188 DragDropController::DragCancel();
189 drag_canceled_ = true;
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);
199 virtual void DoDragCancel(int animation_duration_ms) OVERRIDE {
200 DragDropController::DoDragCancel(animation_duration_ms);
201 drag_canceled_ = true;
204 bool drag_start_received_;
205 int num_drag_updates_;
206 bool drop_received_;
207 bool drag_canceled_;
208 base::string16 drag_string_;
210 private:
211 DISALLOW_COPY_AND_ASSIGN(TestDragDropController);
214 class TestNativeWidgetAura : public views::NativeWidgetAura {
215 public:
216 explicit TestNativeWidgetAura(views::internal::NativeWidgetDelegate* delegate)
217 : NativeWidgetAura(delegate),
218 check_if_capture_lost_(false) {
221 void set_check_if_capture_lost(bool value) {
222 check_if_capture_lost_ = value;
225 virtual void OnCaptureLost() OVERRIDE {
226 DCHECK(!check_if_capture_lost_);
227 views::NativeWidgetAura::OnCaptureLost();
230 private:
231 bool check_if_capture_lost_;
233 DISALLOW_COPY_AND_ASSIGN(TestNativeWidgetAura);
236 // TODO(sky): this is for debugging, remove when track down failure.
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
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;
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);
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);
275 void DispatchGesture(ui::EventType gesture_type, gfx::Point location) {
276 ui::GestureEventDetails event_details(gesture_type, 0, 0);
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);
288 } // namespace
290 class DragDropControllerTest : public AshTestBase {
291 public:
292 DragDropControllerTest() : AshTestBase() {}
293 virtual ~DragDropControllerTest() {}
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());
303 virtual void TearDown() OVERRIDE {
304 aura::client::SetDragDropClient(Shell::GetPrimaryRootWindow(), NULL);
305 drag_drop_controller_.reset();
306 AshTestBase::TearDown();
309 void UpdateDragData(ui::OSExchangeData* data) {
310 drag_drop_controller_->drag_data_ = data;
313 aura::Window* GetDragWindow() {
314 return drag_drop_controller_->drag_window_;
317 aura::Window* GetDragSourceWindow() {
318 return drag_drop_controller_->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());
326 aura::Window* GetDragImageWindow() {
327 return drag_drop_controller_->drag_image_.get() ?
328 drag_drop_controller_->drag_image_->GetWidget()->GetNativeWindow() :
329 NULL;
332 DragDropTracker* drag_drop_tracker() {
333 return drag_drop_controller_->drag_drop_tracker_.get();
336 void CompleteCancelAnimation() {
337 CompletableLinearAnimation* animation =
338 static_cast<CompletableLinearAnimation*>(
339 drag_drop_controller_->cancel_animation_.get());
340 animation->Complete();
343 protected:
344 scoped_ptr<TestDragDropController> drag_drop_controller_;
346 private:
347 DISALLOW_COPY_AND_ASSIGN(DragDropControllerTest);
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
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 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
363 widget->GetNativeView());
364 generator.PressLeftButton();
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);
379 generator.MoveMouseBy(0, 1);
381 // Execute any scheduled draws to process deferred mouse events.
382 RunAllPendingInMessageLoop();
385 generator.ReleaseLeftButton();
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_);
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_);
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 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
409 widget->GetNativeView());
410 generator.PressLeftButton();
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);
423 UpdateDragData(&data);
425 generator.ReleaseLeftButton();
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_);
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_);
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
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);
453 ui::OSExchangeData data;
454 data.SetString(base::UTF8ToUTF16("I am being dragged"));
456 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
457 generator.MoveMouseRelativeTo(widget->GetNativeView(),
458 drag_view1->bounds().CenterPoint());
459 generator.PressLeftButton();
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);
471 // Execute any scheduled draws to process deferred mouse events.
472 RunAllPendingInMessageLoop();
475 generator.ReleaseLeftButton();
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_);
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_);
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_);
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
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()));
519 ui::OSExchangeData data;
520 data.SetString(base::UTF8ToUTF16("I am being dragged"));
522 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
523 widget1->GetNativeView());
524 generator.PressLeftButton();
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);
536 // Execute any scheduled draws to process deferred mouse events.
537 RunAllPendingInMessageLoop();
540 generator.ReleaseLeftButton();
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_);
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_);
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_);
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
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"));
580 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
581 generator.MoveMouseToCenterOf(widget->GetNativeView());
582 generator.PressLeftButton();
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);
594 // Execute any scheduled draws to process deferred mouse events.
595 RunAllPendingInMessageLoop();
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);
605 // Execute any scheduled draws to process deferred mouse events.
606 RunAllPendingInMessageLoop();
609 generator.ReleaseLeftButton();
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_);
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_);
626 TEST_F(DragDropControllerTest, DragLeavesClipboardAloneTest) {
627 ui::Clipboard* cb = ui::Clipboard::GetForCurrentThread();
628 std::string clip_str("I am on the clipboard");
630 // We first copy some text to the clipboard.
631 ui::ScopedClipboardWriter scw(cb, ui::CLIPBOARD_TYPE_COPY_PASTE);
632 scw.WriteText(base::ASCIIToUTF16(clip_str));
634 EXPECT_TRUE(cb->IsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(),
635 ui::CLIPBOARD_TYPE_COPY_PASTE));
637 scoped_ptr<views::Widget> widget(CreateNewWidget());
638 DragTestView* drag_view = new DragTestView;
639 AddViewToWidgetAndResize(widget.get(), drag_view);
641 aura::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));
647 generator.PressLeftButton();
648 generator.MoveMouseBy(0, drag_view->VerticalDragThreshold() + 1);
650 // Execute any scheduled draws to process deferred mouse events.
651 RunAllPendingInMessageLoop();
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();
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();
670 ui::OSExchangeData data;
671 data.SetString(base::UTF8ToUTF16("I am being dragged"));
672 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
673 widget->GetNativeView());
674 generator.PressLeftButton();
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);
686 // Execute any scheduled draws to process deferred mouse events.
687 RunAllPendingInMessageLoop();
689 if (i > drag_view->VerticalDragThreshold())
690 EXPECT_EQ(window, GetDragWindow());
693 widget->CloseNow();
694 EXPECT_FALSE(GetDragWindow());
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.
704 generator.ReleaseLeftButton();
706 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
707 EXPECT_TRUE(drag_drop_controller_->drop_received_);
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 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
717 widget->GetNativeView());
718 generator.PressLeftButton();
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);
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);
741 generator.ReleaseLeftButton();
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_);
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_);
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
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 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
773 widget->GetNativeView());
774 generator.PressLeftButton();
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);
786 // Execute any scheduled draws to process deferred mouse events.
787 RunAllPendingInMessageLoop();
790 generator.PressKey(ui::VKEY_ESCAPE, 0);
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_);
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_);
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 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
815 widget->GetNativeView());
816 generator.PressLeftButton();
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);
828 // Execute any scheduled draws to process deferred mouse events.
829 RunAllPendingInMessageLoop();
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()));
840 aura::client::GetCaptureClient(widget->GetNativeView()->GetRootWindow())->
841 SetCapture(NULL);
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_);
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_);
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()));
873 ui::OSExchangeData data;
874 data.SetString(base::UTF8ToUTF16("I am being dragged"));
876 aura::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);
892 // Execute any scheduled draws to process deferred mouse events.
893 RunAllPendingInMessageLoop();
896 DispatchGesture(ui::ET_GESTURE_SCROLL_END, gesture_location);
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_);
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_);
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_);
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 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
927 widget->GetNativeView());
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);
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_);
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 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
953 widget->GetNativeView());
955 generator.PressTouch();
956 gfx::Point point = gfx::Rect(drag_view->bounds()).CenterPoint();
957 DispatchGesture(ui::ET_GESTURE_LONG_PRESS, point);
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_);
969 namespace {
971 class DragImageWindowObserver : public aura::WindowObserver {
972 public:
973 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
974 window_location_on_destroying_ = window->GetBoundsInScreen().origin();
977 gfx::Point window_location_on_destroying() const {
978 return window_location_on_destroying_;
981 public:
982 gfx::Point window_location_on_destroying_;
987 // Verifies the drag image moves back to the position where drag is started
988 // across displays when drag is cancelled.
989 TEST_F(DragDropControllerTest, DragCancelAcrossDisplays) {
990 if (!SupportsMultipleDisplays())
991 return;
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());
1001 ui::OSExchangeData data;
1002 data.SetString(base::UTF8ToUTF16("I am being dragged"));
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);
1014 DragImageWindowObserver observer;
1015 ASSERT_TRUE(GetDragImageWindow());
1016 GetDragImageWindow()->AddObserver(&observer);
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);
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);
1035 drag_drop_controller_->DragCancel();
1036 CompleteCancelAnimation();
1038 EXPECT_EQ("5,5", observer.window_location_on_destroying().ToString());
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);
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);
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);
1072 drag_drop_controller_->DragCancel();
1073 CompleteCancelAnimation();
1075 EXPECT_EQ("405,405", observer.window_location_on_destroying().ToString());
1077 for (aura::Window::Windows::iterator iter = root_windows.begin();
1078 iter != root_windows.end(); ++iter) {
1079 aura::client::SetDragDropClient(*iter, NULL);
1083 } // namespace test
1084 } // namespace aura