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