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