OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 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 "ui/aura_shell/drag_drop_controller.h" |
| 6 |
| 7 #include "base/location.h" |
| 8 #include "base/utf_string_conversions.h" |
| 9 #include "ui/aura/client/aura_constants.h" |
| 10 #include "ui/aura/desktop.h" |
| 11 #include "ui/aura/event.h" |
| 12 #include "ui/aura/test/aura_test_base.h" |
| 13 #include "ui/aura_shell/desktop_event_filter.h" |
| 14 #include "ui/base/dragdrop/os_exchange_data.h" |
| 15 #include "ui/base/dragdrop/drag_drop_types.h" |
| 16 #include "views/events/event.h" |
| 17 #include "views/view.h" |
| 18 #include "views/widget/widget.h" |
| 19 |
| 20 namespace aura_shell { |
| 21 namespace internal { |
| 22 namespace test { |
| 23 |
| 24 namespace { |
| 25 |
| 26 // A simple view that makes sure RunShellDrag is invoked on mouse drag. |
| 27 class DragTestView : public views::View { |
| 28 public: |
| 29 DragTestView() : views::View() { |
| 30 Reset(); |
| 31 } |
| 32 |
| 33 void Reset() { |
| 34 num_drag_enters_ = 0; |
| 35 num_drag_exits_ = 0; |
| 36 num_drag_updates_ = 0; |
| 37 num_drops_ = 0; |
| 38 drag_done_received_ = false; |
| 39 } |
| 40 |
| 41 int num_drag_enters_; |
| 42 int num_drag_exits_; |
| 43 int num_drag_updates_; |
| 44 int num_drops_; |
| 45 bool drag_done_received_; |
| 46 |
| 47 private: |
| 48 // View overrides: |
| 49 int GetDragOperations(const gfx::Point& press_pt) OVERRIDE { |
| 50 return ui::DragDropTypes::DRAG_COPY; |
| 51 } |
| 52 |
| 53 void WriteDragData(const gfx::Point& p, OSExchangeData* data) OVERRIDE { |
| 54 data->SetString(UTF8ToUTF16("I am being dragged")); |
| 55 } |
| 56 |
| 57 bool OnMousePressed(const views::MouseEvent& event) OVERRIDE { |
| 58 return true; |
| 59 } |
| 60 |
| 61 bool GetDropFormats(int* formats, |
| 62 std::set<OSExchangeData::CustomFormat>* custom_formats) { |
| 63 *formats = ui::OSExchangeData::STRING; |
| 64 return true; |
| 65 } |
| 66 |
| 67 bool CanDrop(const OSExchangeData& data) OVERRIDE { |
| 68 return true; |
| 69 } |
| 70 |
| 71 void OnDragEntered(const views::DropTargetEvent& event) OVERRIDE { |
| 72 num_drag_enters_++; |
| 73 } |
| 74 |
| 75 int OnDragUpdated(const views::DropTargetEvent& event) OVERRIDE { |
| 76 num_drag_updates_++; |
| 77 return ui::DragDropTypes::DRAG_COPY; |
| 78 } |
| 79 |
| 80 void OnDragExited() OVERRIDE { |
| 81 num_drag_exits_++; |
| 82 } |
| 83 |
| 84 int OnPerformDrop(const views::DropTargetEvent& event) OVERRIDE { |
| 85 num_drops_++; |
| 86 return ui::DragDropTypes::DRAG_COPY; |
| 87 } |
| 88 |
| 89 void OnDragDone() OVERRIDE { |
| 90 drag_done_received_ = true; |
| 91 } |
| 92 |
| 93 DISALLOW_COPY_AND_ASSIGN(DragTestView); |
| 94 }; |
| 95 |
| 96 class TestDragDropController : public DragDropController { |
| 97 public: |
| 98 TestDragDropController() : DragDropController() { |
| 99 Reset(); |
| 100 } |
| 101 |
| 102 void Reset() { |
| 103 drag_start_received_ = false; |
| 104 num_drag_updates_ = 0; |
| 105 drop_received_ = false; |
| 106 drag_string_.clear(); |
| 107 } |
| 108 |
| 109 bool drag_start_received_; |
| 110 int num_drag_updates_; |
| 111 bool drop_received_; |
| 112 string16 drag_string_; |
| 113 |
| 114 private: |
| 115 void StartDragAndDrop(const ui::OSExchangeData& data, |
| 116 int operation) OVERRIDE { |
| 117 DragDropController::StartDragAndDrop(data, operation); |
| 118 drag_start_received_ = true; |
| 119 data.GetString(&drag_string_); |
| 120 } |
| 121 |
| 122 void DragUpdate(aura::Window* target, |
| 123 const aura::MouseEvent& event) OVERRIDE { |
| 124 DragDropController::DragUpdate(target, event); |
| 125 num_drag_updates_++; |
| 126 } |
| 127 |
| 128 void Drop(aura::Window* target, const aura::MouseEvent& event) OVERRIDE { |
| 129 DragDropController::Drop(target, event); |
| 130 drop_received_ = true; |
| 131 } |
| 132 |
| 133 DISALLOW_COPY_AND_ASSIGN(TestDragDropController); |
| 134 }; |
| 135 |
| 136 views::Widget* CreateNewWidget() { |
| 137 views::Widget* widget = new views::Widget; |
| 138 views::Widget::InitParams params; |
| 139 params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS; |
| 140 params.accept_events = true; |
| 141 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 142 params.parent = aura::Desktop::GetInstance(); |
| 143 params.child = true; |
| 144 widget->Init(params); |
| 145 widget->Show(); |
| 146 return widget; |
| 147 } |
| 148 |
| 149 void AddViewToWidgetAndResize(views::Widget* widget, views::View* view) { |
| 150 if (!widget->GetContentsView()) { |
| 151 views::View* contents_view = new views::View; |
| 152 widget->SetContentsView(contents_view); |
| 153 } |
| 154 |
| 155 views::View* contents_view = widget->GetContentsView(); |
| 156 contents_view->AddChildView(view); |
| 157 view->SetBounds(contents_view->width(), 0, 100, 100); |
| 158 gfx::Rect contents_view_bounds = contents_view->bounds(); |
| 159 contents_view_bounds = contents_view_bounds.Union(view->bounds()); |
| 160 contents_view->SetBoundsRect(contents_view_bounds); |
| 161 widget->SetBounds(contents_view_bounds); |
| 162 } |
| 163 |
| 164 } // namespace |
| 165 |
| 166 class DragDropControllerTest : public aura::test::AuraTestBase { |
| 167 public: |
| 168 DragDropControllerTest() : AuraTestBase() { |
| 169 drag_drop_controller_ = new TestDragDropController; |
| 170 drag_drop_controller_->set_should_block_during_drag_drop(false); |
| 171 aura::Desktop::GetInstance()->SetProperty(aura::kDesktopDragDropClientKey, |
| 172 drag_drop_controller_); |
| 173 aura::Desktop::GetInstance()->SetEventFilter( |
| 174 new internal::DesktopEventFilter); |
| 175 } |
| 176 |
| 177 virtual ~DragDropControllerTest() { |
| 178 aura::Desktop::GetInstance()->SetProperty(aura::kDesktopDragDropClientKey, |
| 179 NULL); |
| 180 } |
| 181 |
| 182 void UpdateDragData(ui::OSExchangeData* data) { |
| 183 drag_drop_controller_->drag_data_ = data; |
| 184 } |
| 185 |
| 186 protected: |
| 187 TestDragDropController* drag_drop_controller_; |
| 188 |
| 189 private: |
| 190 DISALLOW_COPY_AND_ASSIGN(DragDropControllerTest); |
| 191 }; |
| 192 |
| 193 TEST_F(DragDropControllerTest, DragDropInSingleViewTest) { |
| 194 views::Widget* widget = CreateNewWidget(); |
| 195 DragTestView* drag_view = new DragTestView; |
| 196 AddViewToWidgetAndResize(widget, drag_view); |
| 197 gfx::Point point = gfx::Rect(drag_view->bounds()).CenterPoint(); |
| 198 ui::OSExchangeData data; |
| 199 data.SetString(UTF8ToUTF16("I am being dragged")); |
| 200 |
| 201 aura::MouseEvent event1(ui::ET_MOUSE_PRESSED, point, ui::EF_LEFT_BUTTON_DOWN); |
| 202 aura::Desktop::GetInstance()->DispatchMouseEvent(&event1); |
| 203 |
| 204 int num_drags = 17; |
| 205 for (int i = 0; i < num_drags; ++i) { |
| 206 // Because we are not doing a blocking drag and drop, the original |
| 207 // OSDragExchangeData object is lost as soon as we return from the drag |
| 208 // initiation in DragDropController::StartDragAndDrop(). Hence we set the |
| 209 // drag_data_ to a fake drag data object that we created. |
| 210 if (i > 0) |
| 211 UpdateDragData(&data); |
| 212 point.Offset(0, 1); |
| 213 aura::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, point, |
| 214 ui::EF_LEFT_BUTTON_DOWN); |
| 215 aura::Desktop::GetInstance()->DispatchMouseEvent(&drag_event); |
| 216 } |
| 217 |
| 218 aura::MouseEvent event2(ui::ET_MOUSE_RELEASED, point, 0); |
| 219 aura::Desktop::GetInstance()->DispatchMouseEvent(&event2); |
| 220 |
| 221 EXPECT_TRUE(drag_drop_controller_->drag_start_received_); |
| 222 EXPECT_EQ(num_drags - 1, drag_drop_controller_->num_drag_updates_); |
| 223 EXPECT_TRUE(drag_drop_controller_->drop_received_); |
| 224 EXPECT_EQ(UTF8ToUTF16("I am being dragged"), |
| 225 drag_drop_controller_->drag_string_); |
| 226 |
| 227 EXPECT_EQ(1, drag_view->num_drag_enters_); |
| 228 EXPECT_EQ(num_drags - 1, drag_view->num_drag_updates_); |
| 229 EXPECT_EQ(1, drag_view->num_drops_); |
| 230 EXPECT_EQ(0, drag_view->num_drag_exits_); |
| 231 EXPECT_TRUE(drag_view->drag_done_received_); |
| 232 delete widget; |
| 233 } |
| 234 |
| 235 TEST_F(DragDropControllerTest, DragDropInMultipleViewsSingleWidgetTest) { |
| 236 views::Widget* widget = CreateNewWidget(); |
| 237 DragTestView* drag_view1 = new DragTestView; |
| 238 AddViewToWidgetAndResize(widget, drag_view1); |
| 239 gfx::Point point = drag_view1->bounds().CenterPoint(); |
| 240 DragTestView* drag_view2 = new DragTestView; |
| 241 AddViewToWidgetAndResize(widget, drag_view2); |
| 242 |
| 243 ui::OSExchangeData data; |
| 244 data.SetString(UTF8ToUTF16("I am being dragged")); |
| 245 |
| 246 aura::MouseEvent event1(ui::ET_MOUSE_PRESSED, point, ui::EF_LEFT_BUTTON_DOWN); |
| 247 aura::Desktop::GetInstance()->DispatchMouseEvent(&event1); |
| 248 |
| 249 int num_drags = drag_view1->width(); |
| 250 for (int i = 0; i < num_drags; ++i) { |
| 251 // Because we are not doing a blocking drag and drop, the original |
| 252 // OSDragExchangeData object is lost as soon as we return from the drag |
| 253 // initiation in DragDropController::StartDragAndDrop(). Hence we set the |
| 254 // drag_data_ to a fake drag data object that we created. |
| 255 if (i > 0) |
| 256 UpdateDragData(&data); |
| 257 point.Offset(1, 0); |
| 258 aura::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, point, |
| 259 ui::EF_LEFT_BUTTON_DOWN); |
| 260 aura::Desktop::GetInstance()->DispatchMouseEvent(&drag_event); |
| 261 } |
| 262 |
| 263 aura::MouseEvent event2(ui::ET_MOUSE_RELEASED, point, 0); |
| 264 aura::Desktop::GetInstance()->DispatchMouseEvent(&event2); |
| 265 |
| 266 EXPECT_TRUE(drag_drop_controller_->drag_start_received_); |
| 267 EXPECT_EQ(num_drags - 1, drag_drop_controller_->num_drag_updates_); |
| 268 EXPECT_TRUE(drag_drop_controller_->drop_received_); |
| 269 EXPECT_EQ(UTF8ToUTF16("I am being dragged"), |
| 270 drag_drop_controller_->drag_string_); |
| 271 |
| 272 EXPECT_EQ(1, drag_view1->num_drag_enters_); |
| 273 int num_expected_updates = drag_view1->bounds().width() - |
| 274 drag_view1->bounds().CenterPoint().x() - 2; |
| 275 EXPECT_EQ(num_expected_updates, drag_view1->num_drag_updates_); |
| 276 EXPECT_EQ(0, drag_view1->num_drops_); |
| 277 EXPECT_EQ(1, drag_view1->num_drag_exits_); |
| 278 EXPECT_TRUE(drag_view1->drag_done_received_); |
| 279 |
| 280 EXPECT_EQ(1, drag_view2->num_drag_enters_); |
| 281 num_expected_updates = num_drags - num_expected_updates - 1; |
| 282 EXPECT_EQ(num_expected_updates, drag_view2->num_drag_updates_); |
| 283 EXPECT_EQ(1, drag_view2->num_drops_); |
| 284 EXPECT_EQ(0, drag_view2->num_drag_exits_); |
| 285 EXPECT_FALSE(drag_view2->drag_done_received_); |
| 286 delete widget; |
| 287 } |
| 288 |
| 289 TEST_F(DragDropControllerTest, DragDropInMultipleViewsMultipleWidgetsTest) { |
| 290 views::Widget* widget1 = CreateNewWidget(); |
| 291 DragTestView* drag_view1 = new DragTestView; |
| 292 AddViewToWidgetAndResize(widget1, drag_view1); |
| 293 gfx::Point point = drag_view1->bounds().CenterPoint(); |
| 294 views::Widget* widget2 = CreateNewWidget(); |
| 295 DragTestView* drag_view2 = new DragTestView; |
| 296 AddViewToWidgetAndResize(widget2, drag_view2); |
| 297 gfx::Rect widget1_bounds = widget1->GetClientAreaScreenBounds(); |
| 298 gfx::Rect widget2_bounds = widget2->GetClientAreaScreenBounds(); |
| 299 widget2->SetBounds(gfx::Rect(widget1_bounds.width(), 0, |
| 300 widget2_bounds.width(), widget2_bounds.height())); |
| 301 |
| 302 ui::OSExchangeData data; |
| 303 data.SetString(UTF8ToUTF16("I am being dragged")); |
| 304 |
| 305 aura::MouseEvent event1(ui::ET_MOUSE_PRESSED, point, ui::EF_LEFT_BUTTON_DOWN); |
| 306 aura::Desktop::GetInstance()->DispatchMouseEvent(&event1); |
| 307 |
| 308 int num_drags = drag_view1->width(); |
| 309 for (int i = 0; i < num_drags; ++i) { |
| 310 // Because we are not doing a blocking drag and drop, the original |
| 311 // OSDragExchangeData object is lost as soon as we return from the drag |
| 312 // initiation in DragDropController::StartDragAndDrop(). Hence we set the |
| 313 // drag_data_ to a fake drag data object that we created. |
| 314 if (i > 0) |
| 315 UpdateDragData(&data); |
| 316 point.Offset(1, 0); |
| 317 aura::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, point, |
| 318 ui::EF_LEFT_BUTTON_DOWN); |
| 319 aura::Desktop::GetInstance()->DispatchMouseEvent(&drag_event); |
| 320 } |
| 321 |
| 322 aura::MouseEvent event2(ui::ET_MOUSE_RELEASED, point, 0); |
| 323 aura::Desktop::GetInstance()->DispatchMouseEvent(&event2); |
| 324 |
| 325 EXPECT_TRUE(drag_drop_controller_->drag_start_received_); |
| 326 EXPECT_EQ(num_drags - 1, drag_drop_controller_->num_drag_updates_); |
| 327 EXPECT_TRUE(drag_drop_controller_->drop_received_); |
| 328 EXPECT_EQ(UTF8ToUTF16("I am being dragged"), |
| 329 drag_drop_controller_->drag_string_); |
| 330 |
| 331 EXPECT_EQ(1, drag_view1->num_drag_enters_); |
| 332 int num_expected_updates = drag_view1->bounds().width() - |
| 333 drag_view1->bounds().CenterPoint().x() - 2; |
| 334 EXPECT_EQ(num_expected_updates, drag_view1->num_drag_updates_); |
| 335 EXPECT_EQ(0, drag_view1->num_drops_); |
| 336 EXPECT_EQ(1, drag_view1->num_drag_exits_); |
| 337 EXPECT_TRUE(drag_view1->drag_done_received_); |
| 338 |
| 339 EXPECT_EQ(1, drag_view2->num_drag_enters_); |
| 340 num_expected_updates = num_drags - num_expected_updates - 2; |
| 341 EXPECT_EQ(num_expected_updates, drag_view2->num_drag_updates_); |
| 342 EXPECT_EQ(1, drag_view2->num_drops_); |
| 343 EXPECT_EQ(0, drag_view2->num_drag_exits_); |
| 344 EXPECT_FALSE(drag_view2->drag_done_received_); |
| 345 delete widget1; |
| 346 delete widget2; |
| 347 } |
| 348 |
| 349 } // namespace test |
| 350 } // namespace internal |
| 351 } // namespace aura |
OLD | NEW |