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/desktop.h" |
| 10 #include "ui/aura/event.h" |
| 11 #include "ui/aura/test/aura_test_base.h" |
| 12 #include "ui/aura_shell/desktop_event_filter.h" |
| 13 #include "ui/base/dragdrop/os_exchange_data.h" |
| 14 #include "ui/base/dragdrop/drag_drop_types.h" |
| 15 #include "views/events/event.h" |
| 16 #include "views/view.h" |
| 17 #include "views/widget/widget.h" |
| 18 |
| 19 namespace aura_shell { |
| 20 namespace internal { |
| 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 DragDropController { |
| 96 public: |
| 97 TestDragDropController() : 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 widget->SetContentsView(new views::View); |
| 151 |
| 152 views::View* contents_view = widget->GetContentsView(); |
| 153 contents_view->AddChildView(view); |
| 154 view->SetBounds(contents_view->width(), 0, 100, 100); |
| 155 gfx::Rect contents_view_bounds = contents_view->bounds(); |
| 156 contents_view_bounds = contents_view_bounds.Union(view->bounds()); |
| 157 contents_view->SetBoundsRect(contents_view_bounds); |
| 158 widget->SetBounds(contents_view_bounds); |
| 159 } |
| 160 |
| 161 } // namespace |
| 162 |
| 163 class DragDropControllerTest : public aura::test::AuraTestBase { |
| 164 public: |
| 165 DragDropControllerTest() : AuraTestBase() { |
| 166 drag_drop_controller_ = new TestDragDropController; |
| 167 drag_drop_controller_->set_should_block_during_drag_drop(false); |
| 168 aura::Desktop::GetInstance()->SetDragDropClient(drag_drop_controller_); |
| 169 aura::Desktop::GetInstance()->SetEventFilter( |
| 170 new internal::DesktopEventFilter); |
| 171 } |
| 172 |
| 173 virtual ~DragDropControllerTest() { |
| 174 } |
| 175 |
| 176 void UpdateDragData(ui::OSExchangeData* data) { |
| 177 drag_drop_controller_->drag_data_ = data; |
| 178 } |
| 179 |
| 180 protected: |
| 181 TestDragDropController* drag_drop_controller_; |
| 182 |
| 183 private: |
| 184 DISALLOW_COPY_AND_ASSIGN(DragDropControllerTest); |
| 185 }; |
| 186 |
| 187 TEST_F(DragDropControllerTest, DragDropInSingleViewTest) { |
| 188 views::Widget* widget = CreateNewWidget(); |
| 189 DragTestView* drag_view = new DragTestView; |
| 190 AddViewToWidgetAndResize(widget, drag_view); |
| 191 gfx::Point point = gfx::Rect(drag_view->bounds()).CenterPoint(); |
| 192 ui::OSExchangeData data; |
| 193 data.SetString(UTF8ToUTF16("I am being dragged")); |
| 194 |
| 195 aura::MouseEvent event1(ui::ET_MOUSE_PRESSED, point, ui::EF_LEFT_BUTTON_DOWN); |
| 196 aura::Desktop::GetInstance()->DispatchMouseEvent(&event1); |
| 197 |
| 198 int num_drags = 17; |
| 199 for (int i = 0; i < num_drags; ++i) { |
| 200 // Because we are not doing a blocking drag and drop, the original |
| 201 // OSDragExchangeData object is lost as seen as we return from the drag |
| 202 // initiation in Desktop::StartDragAndDrop(). Hence we set the Shell's |
| 203 // drag_data_ to a fake drag data object that we created. |
| 204 if (i > 0) |
| 205 UpdateDragData(&data); |
| 206 point.Offset(0, 1); |
| 207 aura::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, point, |
| 208 ui::EF_LEFT_BUTTON_DOWN); |
| 209 aura::Desktop::GetInstance()->DispatchMouseEvent(&drag_event); |
| 210 } |
| 211 |
| 212 aura::MouseEvent event2(ui::ET_MOUSE_RELEASED, point, 0); |
| 213 aura::Desktop::GetInstance()->DispatchMouseEvent(&event2); |
| 214 |
| 215 EXPECT_TRUE(drag_drop_controller_->drag_start_received_); |
| 216 EXPECT_EQ(num_drags - 1, drag_drop_controller_->num_drag_updates_); |
| 217 EXPECT_TRUE(drag_drop_controller_->drop_received_); |
| 218 EXPECT_EQ(UTF8ToUTF16("I am being dragged"), |
| 219 drag_drop_controller_->drag_string_); |
| 220 |
| 221 EXPECT_EQ(1, drag_view->num_drag_enters_); |
| 222 EXPECT_EQ(num_drags - 1, drag_view->num_drag_updates_); |
| 223 EXPECT_EQ(1, drag_view->num_drops_); |
| 224 EXPECT_EQ(0, drag_view->num_drag_exits_); |
| 225 EXPECT_TRUE(drag_view->drag_done_received_); |
| 226 delete widget; |
| 227 } |
| 228 |
| 229 TEST_F(DragDropControllerTest, DragDropInMultipleViewsSingleWidgetTest) { |
| 230 views::Widget* widget = CreateNewWidget(); |
| 231 DragTestView* drag_view1 = new DragTestView; |
| 232 AddViewToWidgetAndResize(widget, drag_view1); |
| 233 gfx::Point point = drag_view1->bounds().CenterPoint(); |
| 234 DragTestView* drag_view2 = new DragTestView; |
| 235 AddViewToWidgetAndResize(widget, drag_view2); |
| 236 |
| 237 ui::OSExchangeData data; |
| 238 data.SetString(UTF8ToUTF16("I am being dragged")); |
| 239 |
| 240 aura::MouseEvent event1(ui::ET_MOUSE_PRESSED, point, ui::EF_LEFT_BUTTON_DOWN); |
| 241 aura::Desktop::GetInstance()->DispatchMouseEvent(&event1); |
| 242 |
| 243 int num_drags = drag_view1->width(); |
| 244 for (int i = 0; i < num_drags; ++i) { |
| 245 // Because we are not doing a blocking drag and drop, the original |
| 246 // OSDragExchangeData object is lost as seen as we return from the drag |
| 247 // initiation in Desktop::StartDragAndDrop(). Hence we set the Shell's |
| 248 // drag_data_ to a fake drag data object that we created. |
| 249 if (i > 0) |
| 250 UpdateDragData(&data); |
| 251 point.Offset(1, 0); |
| 252 aura::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, point, |
| 253 ui::EF_LEFT_BUTTON_DOWN); |
| 254 aura::Desktop::GetInstance()->DispatchMouseEvent(&drag_event); |
| 255 } |
| 256 |
| 257 aura::MouseEvent event2(ui::ET_MOUSE_RELEASED, point, 0); |
| 258 aura::Desktop::GetInstance()->DispatchMouseEvent(&event2); |
| 259 |
| 260 EXPECT_TRUE(drag_drop_controller_->drag_start_received_); |
| 261 EXPECT_EQ(num_drags - 1, drag_drop_controller_->num_drag_updates_); |
| 262 EXPECT_TRUE(drag_drop_controller_->drop_received_); |
| 263 EXPECT_EQ(UTF8ToUTF16("I am being dragged"), |
| 264 drag_drop_controller_->drag_string_); |
| 265 |
| 266 EXPECT_EQ(1, drag_view1->num_drag_enters_); |
| 267 int num_expected_updates = drag_view1->bounds().width() - |
| 268 drag_view1->bounds().CenterPoint().x() - 2; |
| 269 EXPECT_EQ(num_expected_updates, drag_view1->num_drag_updates_); |
| 270 EXPECT_EQ(0, drag_view1->num_drops_); |
| 271 EXPECT_EQ(1, drag_view1->num_drag_exits_); |
| 272 EXPECT_TRUE(drag_view1->drag_done_received_); |
| 273 |
| 274 EXPECT_EQ(1, drag_view2->num_drag_enters_); |
| 275 num_expected_updates = num_drags - num_expected_updates - 1; |
| 276 EXPECT_EQ(num_expected_updates, drag_view2->num_drag_updates_); |
| 277 EXPECT_EQ(1, drag_view2->num_drops_); |
| 278 EXPECT_EQ(0, drag_view2->num_drag_exits_); |
| 279 EXPECT_FALSE(drag_view2->drag_done_received_); |
| 280 delete widget; |
| 281 } |
| 282 |
| 283 TEST_F(DragDropControllerTest, DragDropInMultipleViewsMultipleWidgetsTest) { |
| 284 views::Widget* widget1 = CreateNewWidget(); |
| 285 DragTestView* drag_view1 = new DragTestView; |
| 286 AddViewToWidgetAndResize(widget1, drag_view1); |
| 287 gfx::Point point = drag_view1->bounds().CenterPoint(); |
| 288 views::Widget* widget2 = CreateNewWidget(); |
| 289 DragTestView* drag_view2 = new DragTestView; |
| 290 AddViewToWidgetAndResize(widget2, drag_view2); |
| 291 gfx::Rect widget1_bounds = widget1->GetClientAreaScreenBounds(); |
| 292 gfx::Rect widget2_bounds = widget2->GetClientAreaScreenBounds(); |
| 293 widget2->SetBounds(gfx::Rect(widget1_bounds.width(), 0, |
| 294 widget2_bounds.width(), widget2_bounds.height())); |
| 295 |
| 296 ui::OSExchangeData data; |
| 297 data.SetString(UTF8ToUTF16("I am being dragged")); |
| 298 |
| 299 aura::MouseEvent event1(ui::ET_MOUSE_PRESSED, point, ui::EF_LEFT_BUTTON_DOWN); |
| 300 aura::Desktop::GetInstance()->DispatchMouseEvent(&event1); |
| 301 |
| 302 int num_drags = drag_view1->width(); |
| 303 for (int i = 0; i < num_drags; ++i) { |
| 304 // Because we are not doing a blocking drag and drop, the original |
| 305 // OSDragExchangeData object is lost as seen as we return from the drag |
| 306 // initiation in Desktop::StartDragAndDrop(). Hence we set the Shell's |
| 307 // drag_data_ to a fake drag data object that we created. |
| 308 if (i > 0) |
| 309 UpdateDragData(&data); |
| 310 point.Offset(1, 0); |
| 311 aura::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, point, |
| 312 ui::EF_LEFT_BUTTON_DOWN); |
| 313 aura::Desktop::GetInstance()->DispatchMouseEvent(&drag_event); |
| 314 } |
| 315 |
| 316 aura::MouseEvent event2(ui::ET_MOUSE_RELEASED, point, 0); |
| 317 aura::Desktop::GetInstance()->DispatchMouseEvent(&event2); |
| 318 |
| 319 EXPECT_TRUE(drag_drop_controller_->drag_start_received_); |
| 320 EXPECT_EQ(num_drags - 1, drag_drop_controller_->num_drag_updates_); |
| 321 EXPECT_TRUE(drag_drop_controller_->drop_received_); |
| 322 EXPECT_EQ(UTF8ToUTF16("I am being dragged"), |
| 323 drag_drop_controller_->drag_string_); |
| 324 |
| 325 EXPECT_EQ(1, drag_view1->num_drag_enters_); |
| 326 int num_expected_updates = drag_view1->bounds().width() - |
| 327 drag_view1->bounds().CenterPoint().x() - 2; |
| 328 EXPECT_EQ(num_expected_updates, drag_view1->num_drag_updates_); |
| 329 EXPECT_EQ(0, drag_view1->num_drops_); |
| 330 EXPECT_EQ(1, drag_view1->num_drag_exits_); |
| 331 EXPECT_TRUE(drag_view1->drag_done_received_); |
| 332 |
| 333 EXPECT_EQ(1, drag_view2->num_drag_enters_); |
| 334 num_expected_updates = num_drags - num_expected_updates - 2; |
| 335 EXPECT_EQ(num_expected_updates, drag_view2->num_drag_updates_); |
| 336 EXPECT_EQ(1, drag_view2->num_drops_); |
| 337 EXPECT_EQ(0, drag_view2->num_drag_exits_); |
| 338 EXPECT_FALSE(drag_view2->drag_done_received_); |
| 339 delete widget1; |
| 340 delete widget2; |
| 341 } |
| 342 |
| 343 } // namespace test |
| 344 } // namespace internal |
| 345 } // namespace aura |
OLD | NEW |