1 // Copyright (c) 2013 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/shell.h" 8 #include "ash/test/ash_test_base.h" 9 #include "base/bind.h" 10 #include "base/message_loop/message_loop.h" 11 #include "base/strings/utf_string_conversions.h" 12 #include "ui/aura/root_window.h" 13 #include "ui/base/dragdrop/drag_drop_types.h" 14 #include "ui/base/test/ui_controls.h" 15 #include "ui/views/view.h" 16 #include "ui/views/widget/widget.h" 17 18 namespace ash { 19 namespace internal { 20 namespace { 21 22 class DraggableView : public views::View { 23 public: 24 DraggableView() {} 25 virtual ~DraggableView() {} 26 27 // views::View overrides: 28 virtual int GetDragOperations(const gfx::Point& press_pt) OVERRIDE { 29 return ui::DragDropTypes::DRAG_MOVE; 30 } 31 virtual void WriteDragData(const gfx::Point& press_pt, 32 OSExchangeData* data)OVERRIDE { 33 data->SetString(UTF8ToUTF16("test")); 34 } 35 36 private: 37 DISALLOW_COPY_AND_ASSIGN(DraggableView); 38 }; 39 40 class TargetView : public views::View { 41 public: 42 TargetView() : dropped_(false) {} 43 virtual ~TargetView() {} 44 45 // views::View overrides: 46 virtual bool GetDropFormats( 47 int* formats, 48 std::set<OSExchangeData::CustomFormat>* custom_formats) OVERRIDE { 49 *formats = ui::OSExchangeData::STRING; 50 return true; 51 } 52 virtual bool AreDropTypesRequired() OVERRIDE { 53 return false; 54 } 55 virtual bool CanDrop(const OSExchangeData& data) OVERRIDE { 56 return true; 57 } 58 virtual int OnDragUpdated(const ui::DropTargetEvent& event) OVERRIDE { 59 return ui::DragDropTypes::DRAG_MOVE; 60 } 61 virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE { 62 dropped_ = true; 63 return ui::DragDropTypes::DRAG_MOVE; 64 } 65 66 bool dropped() const { return dropped_; } 67 68 private: 69 bool dropped_; 70 71 DISALLOW_COPY_AND_ASSIGN(TargetView); 72 }; 73 74 views::Widget* CreateWidget(views::View* contents_view, 75 const gfx::Rect& bounds) { 76 views::Widget* widget = new views::Widget; 77 views::Widget::InitParams params; 78 params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS; 79 params.accept_events = true; 80 params.context = Shell::GetPrimaryRootWindow(); 81 params.bounds = bounds; 82 widget->Init(params); 83 84 widget->SetContentsView(contents_view); 85 widget->Show(); 86 return widget; 87 } 88 89 void QuitLoop() { 90 base::MessageLoop::current()->Quit(); 91 } 92 93 void DragDropAcrossMultiDisplay_Step4() { 94 ui_controls::SendMouseEventsNotifyWhenDone( 95 ui_controls::LEFT, ui_controls::UP, 96 base::Bind(&QuitLoop)); 97 } 98 99 void DragDropAcrossMultiDisplay_Step3() { 100 // Move to the edge of the 1st display so that the mouse 101 // is moved to 2nd display by ash. 102 ui_controls::SendMouseMoveNotifyWhenDone( 103 399, 10, 104 base::Bind(&DragDropAcrossMultiDisplay_Step4)); 105 } 106 107 void DragDropAcrossMultiDisplay_Step2() { 108 ui_controls::SendMouseMoveNotifyWhenDone( 109 20, 10, 110 base::Bind(&DragDropAcrossMultiDisplay_Step3)); 111 } 112 113 void DragDropAcrossMultiDisplay_Step1() { 114 ui_controls::SendMouseEventsNotifyWhenDone( 115 ui_controls::LEFT, ui_controls::DOWN, 116 base::Bind(&DragDropAcrossMultiDisplay_Step2)); 117 } 118 119 } // namespace 120 121 typedef test::AshTestBase DragDropTest; 122 123 #if defined(OS_WIN) 124 #define MAYBE_DragDropAcrossMultiDisplay DISABLED_DragDropAcrossMultiDisplay 125 #else 126 #define MAYBE_DragDropAcrossMultiDisplay DragDropAcrossMultiDisplay 127 #endif 128 129 // Test if the mouse gets moved properly to another display 130 // during drag & drop operation. 131 TEST_F(DragDropTest, MAYBE_DragDropAcrossMultiDisplay) { 132 if (!SupportsMultipleDisplays()) 133 return; 134 135 UpdateDisplay("400x400,400x400"); 136 aura::Window::Windows root_windows = 137 Shell::GetInstance()->GetAllRootWindows(); 138 views::View* draggable_view = new DraggableView(); 139 draggable_view->set_drag_controller(NULL); 140 draggable_view->SetBounds(0, 0, 100, 100); 141 views::Widget* source = 142 CreateWidget(draggable_view, gfx::Rect(0, 0, 100, 100)); 143 144 TargetView* target_view = new TargetView(); 145 target_view->SetBounds(0, 0, 100, 100); 146 views::Widget* target = 147 CreateWidget(target_view, gfx::Rect(400, 0, 100, 100)); 148 149 // Make sure they're on the different root windows. 150 EXPECT_EQ(root_windows[0], source->GetNativeView()->GetRootWindow()); 151 EXPECT_EQ(root_windows[1], target->GetNativeView()->GetRootWindow()); 152 153 ui_controls::SendMouseMoveNotifyWhenDone( 154 10, 10, base::Bind(&DragDropAcrossMultiDisplay_Step1)); 155 156 base::MessageLoop::current()->Run(); 157 158 EXPECT_TRUE(target_view->dropped()); 159 160 source->Close(); 161 target->Close(); 162 } 163 164 } // namespace internal 165 } // namespace ash 166