Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: services/ui/ws/drag_controller_unittest.cc

Issue 2376583003: mus: Keep track of the drag cursor during DnD operations. (Closed)
Patch Set: Add test for when target window closes to reset cursor Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "services/ui/ws/drag_controller.h" 5 #include "services/ui/ws/drag_controller.h"
6 6
7 #include "services/ui/public/interfaces/cursor.mojom.h"
7 #include "services/ui/ws/drag_source.h" 8 #include "services/ui/ws/drag_source.h"
8 #include "services/ui/ws/drag_target_connection.h" 9 #include "services/ui/ws/drag_target_connection.h"
9 #include "services/ui/ws/ids.h" 10 #include "services/ui/ws/ids.h"
10 #include "services/ui/ws/server_window.h" 11 #include "services/ui/ws/server_window.h"
11 #include "services/ui/ws/test_server_window_delegate.h" 12 #include "services/ui/ws/test_server_window_delegate.h"
12 #include "services/ui/ws/test_utils.h" 13 #include "services/ui/ws/test_utils.h"
13 #include "testing/gtest/include/gtest/gtest.h" 14 #include "testing/gtest/include/gtest/gtest.h"
14 #include "ui/events/base_event_utils.h" 15 #include "ui/events/base_event_utils.h"
15 16
16 namespace ui { 17 namespace ui {
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 private: 122 private:
122 DragControllerTest* parent_; 123 DragControllerTest* parent_;
123 TestServerWindowDelegate window_delegate_; 124 TestServerWindowDelegate window_delegate_;
124 ServerWindow window_; 125 ServerWindow window_;
125 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data_; 126 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data_;
126 uint32_t times_received_drag_drop_start_ = 0; 127 uint32_t times_received_drag_drop_start_ = 0;
127 128
128 std::queue<DragEvent> queued_callbacks_; 129 std::queue<DragEvent> queued_callbacks_;
129 }; 130 };
130 131
131 class DragControllerTest : public testing::Test, public DragSource { 132 class DragControllerTest : public testing::Test,
133 public DragCursorUpdater,
134 public DragSource {
132 public: 135 public:
133 std::unique_ptr<DragTestWindow> BuildWindow() { 136 std::unique_ptr<DragTestWindow> BuildWindow() {
134 WindowId id(1, ++window_id_); 137 WindowId id(1, ++window_id_);
135 std::unique_ptr<DragTestWindow> p = 138 std::unique_ptr<DragTestWindow> p =
136 base::MakeUnique<DragTestWindow>(this, id); 139 base::MakeUnique<DragTestWindow>(this, id);
137 server_window_by_id_[id] = p->window(); 140 server_window_by_id_[id] = p->window();
138 connection_by_window_[p->window()] = p.get(); 141 connection_by_window_[p->window()] = p.get();
139 return p; 142 return p;
140 } 143 }
141 144
142 void StartDragOperation( 145 void StartDragOperation(
143 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data, 146 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data,
144 DragTestWindow* window, 147 DragTestWindow* window,
145 uint32_t drag_operations) { 148 uint32_t drag_operations) {
146 window->PerformOnDragDropStart(mime_data.Clone()); 149 window->PerformOnDragDropStart(mime_data.Clone());
147 drag_operation_ = base::MakeUnique<DragController>( 150 drag_operation_ = base::MakeUnique<DragController>(
148 this, window->window(), window, PointerEvent::kMousePointerId, 151 this, this, window->window(), window, PointerEvent::kMousePointerId,
149 std::move(mime_data), drag_operations); 152 std::move(mime_data), drag_operations);
153
154 // It would be nice if we could just let the observer method fire, but it
155 // fires during the constructor when we haven't assigned the unique_ptr
156 // yet.
157 cursor_ = ui::mojom::Cursor(drag_operation_->current_cursor());
150 } 158 }
151 159
152 void DispatchDrag(DragTestWindow* window, 160 void DispatchDrag(DragTestWindow* window,
153 bool mouse_released, 161 bool mouse_released,
154 uint32_t flags, 162 uint32_t flags,
155 const gfx::Point& position) { 163 const gfx::Point& position) {
156 ui::PointerEvent event( 164 ui::PointerEvent event(
157 ui::MouseEvent(mouse_released ? ET_MOUSE_RELEASED : ET_MOUSE_PRESSED, 165 ui::MouseEvent(mouse_released ? ET_MOUSE_RELEASED : ET_MOUSE_PRESSED,
158 position, position, ui::EventTimeForNow(), flags, 0)); 166 position, position, ui::EventTimeForNow(), flags, 0));
159 drag_operation_->DispatchPointerEvent(event, 167 drag_operation_->DispatchPointerEvent(event,
(...skipping 20 matching lines...) Expand all
180 188
181 DragController* drag_operation() const { return drag_operation_.get(); } 189 DragController* drag_operation() const { return drag_operation_.get(); }
182 190
183 const base::Optional<uint32_t>& drag_completed_action() { 191 const base::Optional<uint32_t>& drag_completed_action() {
184 return drag_completed_action_; 192 return drag_completed_action_;
185 } 193 }
186 const base::Optional<bool>& drag_completed_value() { 194 const base::Optional<bool>& drag_completed_value() {
187 return drag_completed_value_; 195 return drag_completed_value_;
188 } 196 }
189 197
198 ui::mojom::Cursor cursor() { return cursor_; }
199
190 private: 200 private:
191 // Overridden from testing::Test: 201 // Overridden from testing::Test:
192 void SetUp() override { 202 void SetUp() override {
193 testing::Test::SetUp(); 203 testing::Test::SetUp();
194 204
195 window_delegate_ = base::MakeUnique<TestServerWindowDelegate>(); 205 window_delegate_ = base::MakeUnique<TestServerWindowDelegate>();
196 root_window_ = 206 root_window_ =
197 base::MakeUnique<ServerWindow>(window_delegate_.get(), WindowId(1, 2)); 207 base::MakeUnique<ServerWindow>(window_delegate_.get(), WindowId(1, 2));
198 window_delegate_->set_root_window(root_window_.get()); 208 window_delegate_->set_root_window(root_window_.get());
199 root_window_->SetVisible(true); 209 root_window_->SetVisible(true);
200 } 210 }
201 211
202 void TearDown() override { 212 void TearDown() override {
203 drag_operation_.reset(); 213 drag_operation_.reset();
204 root_window_.reset(); 214 root_window_.reset();
205 window_delegate_.reset(); 215 window_delegate_.reset();
206 216
207 DCHECK(server_window_by_id_.empty()); 217 DCHECK(server_window_by_id_.empty());
208 DCHECK(connection_by_window_.empty()); 218 DCHECK(connection_by_window_.empty());
209 219
210 testing::Test::TearDown(); 220 testing::Test::TearDown();
211 } 221 }
212 222
223 // Overridden from DragCursorUpdater:
224 void OnDragCursorUpdated() override {
225 if (drag_operation_)
226 cursor_ = ui::mojom::Cursor(drag_operation_->current_cursor());
227 }
228
213 // Overridden from DragControllerSource: 229 // Overridden from DragControllerSource:
214 void OnDragCompleted(bool success, uint32_t action_taken) override { 230 void OnDragCompleted(bool success, uint32_t action_taken) override {
215 drag_completed_action_ = action_taken; 231 drag_completed_action_ = action_taken;
216 drag_completed_value_ = success; 232 drag_completed_value_ = success;
217 } 233 }
218 234
219 ServerWindow* GetWindowById(const WindowId& id) override { 235 ServerWindow* GetWindowById(const WindowId& id) override {
220 auto it = server_window_by_id_.find(id); 236 auto it = server_window_by_id_.find(id);
221 if (it == server_window_by_id_.end()) 237 if (it == server_window_by_id_.end())
222 return nullptr; 238 return nullptr;
223 return it->second; 239 return it->second;
224 } 240 }
225 241
226 DragTargetConnection* GetDragTargetForWindow( 242 DragTargetConnection* GetDragTargetForWindow(
227 const ServerWindow* window) override { 243 const ServerWindow* window) override {
228 auto it = connection_by_window_.find(const_cast<ServerWindow*>(window)); 244 auto it = connection_by_window_.find(const_cast<ServerWindow*>(window));
229 if (it == connection_by_window_.end()) 245 if (it == connection_by_window_.end())
230 return nullptr; 246 return nullptr;
231 return it->second; 247 return it->second;
232 } 248 }
233 249
234 int window_id_ = 3; 250 int window_id_ = 3;
235 251
252 ui::mojom::Cursor cursor_;
253
236 std::map<WindowId, ServerWindow*> server_window_by_id_; 254 std::map<WindowId, ServerWindow*> server_window_by_id_;
237 std::map<ServerWindow*, DragTargetConnection*> connection_by_window_; 255 std::map<ServerWindow*, DragTargetConnection*> connection_by_window_;
238 256
239 std::unique_ptr<TestServerWindowDelegate> window_delegate_; 257 std::unique_ptr<TestServerWindowDelegate> window_delegate_;
240 std::unique_ptr<ServerWindow> root_window_; 258 std::unique_ptr<ServerWindow> root_window_;
241 259
242 std::unique_ptr<DragController> drag_operation_; 260 std::unique_ptr<DragController> drag_operation_;
243 261
244 base::Optional<uint32_t> drag_completed_action_; 262 base::Optional<uint32_t> drag_completed_action_;
245 base::Optional<bool> drag_completed_value_; 263 base::Optional<bool> drag_completed_value_;
246 }; 264 };
247 265
248 DragTestWindow::~DragTestWindow() { 266 DragTestWindow::~DragTestWindow() {
249 parent_->OnTestWindowDestroyed(this); 267 parent_->OnTestWindowDestroyed(this);
250 } 268 }
251 269
252 TEST_F(DragControllerTest, SimpleDragDrop) { 270 TEST_F(DragControllerTest, SimpleDragDrop) {
253 std::unique_ptr<DragTestWindow> window = BuildWindow(); 271 std::unique_ptr<DragTestWindow> window = BuildWindow();
254 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data; 272 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data;
255 StartDragOperation(std::move(mime_data), window.get(), 273 StartDragOperation(std::move(mime_data), window.get(),
256 ui::mojom::kDropEffectMove); 274 ui::mojom::kDropEffectMove);
257 275
276 EXPECT_EQ(ui::mojom::Cursor::NO_DROP, cursor());
277
258 DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(1, 1)); 278 DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(1, 1));
259 EXPECT_EQ(QueuedType::ENTER, window->queue_response_type()); 279 EXPECT_EQ(QueuedType::ENTER, window->queue_response_type());
260 window->Respond(true); 280 window->Respond(true);
261 281
282 // (Even though we're doing a move, the cursor name is COPY.)
283 EXPECT_EQ(ui::mojom::Cursor::COPY, cursor());
284
262 DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(2, 2)); 285 DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(2, 2));
263 EXPECT_EQ(QueuedType::OVER, window->queue_response_type()); 286 EXPECT_EQ(QueuedType::OVER, window->queue_response_type());
264 window->Respond(true); 287 window->Respond(true);
265 288
266 DispatchDrag(window.get(), true, 0, gfx::Point(2, 2)); 289 DispatchDrag(window.get(), true, 0, gfx::Point(2, 2));
267 EXPECT_EQ(QueuedType::DROP, window->queue_response_type()); 290 EXPECT_EQ(QueuedType::DROP, window->queue_response_type());
268 window->Respond(true); 291 window->Respond(true);
269 292
270 EXPECT_EQ(ui::mojom::kDropEffectMove, 293 EXPECT_EQ(ui::mojom::kDropEffectMove,
271 drag_completed_action().value_or(ui::mojom::kDropEffectNone)); 294 drag_completed_action().value_or(ui::mojom::kDropEffectNone));
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 window2.reset(); 538 window2.reset();
516 539
517 // DragController doesn't know anything about the server window now. 540 // DragController doesn't know anything about the server window now.
518 EXPECT_EQ(0u, api.GetSizeOfQueueForWindow(server_window)); 541 EXPECT_EQ(0u, api.GetSizeOfQueueForWindow(server_window));
519 EXPECT_EQ(nullptr, api.GetCurrentTarget()); 542 EXPECT_EQ(nullptr, api.GetCurrentTarget());
520 543
521 // But a target window closing out from under us doesn't fail the drag. 544 // But a target window closing out from under us doesn't fail the drag.
522 EXPECT_FALSE(drag_completed_value().has_value()); 545 EXPECT_FALSE(drag_completed_value().has_value());
523 } 546 }
524 547
548 TEST_F(DragControllerTest, TargetWindowClosedResetsCursor) {
549 std::unique_ptr<DragTestWindow> window1 = BuildWindow();
550 std::unique_ptr<DragTestWindow> window2 = BuildWindow();
551 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data;
552 StartDragOperation(std::move(mime_data), window1.get(),
553 ui::mojom::kDropEffectMove);
554 EXPECT_EQ(ui::mojom::Cursor::NO_DROP, cursor());
555
556 // Send some events to |window|.
557 DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
558 gfx::Point(1, 1));
559 EXPECT_EQ(QueuedType::ENTER, window2->queue_response_type());
560 window2->Respond(true);
561 DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
562 gfx::Point(1, 1));
563 window2->Respond(true);
564 EXPECT_EQ(ui::mojom::Cursor::COPY, cursor());
565
566 // Force the destruction of |window.window|.
567 window2.reset();
568
569 // The cursor no loner indicates that it can drop on |window2|.
570 EXPECT_EQ(ui::mojom::Cursor::NO_DROP, cursor());
571 }
572
525 TEST_F(DragControllerTest, SourceWindowClosedWhileDrag) { 573 TEST_F(DragControllerTest, SourceWindowClosedWhileDrag) {
526 std::unique_ptr<DragTestWindow> window1 = BuildWindow(); 574 std::unique_ptr<DragTestWindow> window1 = BuildWindow();
527 std::unique_ptr<DragTestWindow> window2 = BuildWindow(); 575 std::unique_ptr<DragTestWindow> window2 = BuildWindow();
528 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data; 576 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data;
529 StartDragOperation(std::move(mime_data), window1.get(), 577 StartDragOperation(std::move(mime_data), window1.get(),
530 ui::mojom::kDropEffectMove); 578 ui::mojom::kDropEffectMove);
531 579
532 test::DragControllerTestApi api(drag_operation()); 580 test::DragControllerTestApi api(drag_operation());
533 581
534 // Send some events to |window|. 582 // Send some events to |windoww|.
535 DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON, 583 DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
536 gfx::Point(1, 1)); 584 gfx::Point(1, 1));
537 EXPECT_EQ(QueuedType::ENTER, window2->queue_response_type()); 585 EXPECT_EQ(QueuedType::ENTER, window2->queue_response_type());
538 DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON, 586 DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
539 gfx::Point(1, 1)); 587 gfx::Point(1, 1));
540 588
541 ServerWindow* server_window = window2->window(); 589 ServerWindow* server_window = window2->window();
542 590
543 // Ensure that DragController is waiting for a response from |window|. 591 // Ensure that DragController is waiting for a response from |window2|.
544 EXPECT_EQ(2u, api.GetSizeOfQueueForWindow(server_window)); 592 EXPECT_EQ(2u, api.GetSizeOfQueueForWindow(server_window));
545 EXPECT_EQ(server_window, api.GetCurrentTarget()); 593 EXPECT_EQ(server_window, api.GetCurrentTarget());
546 594
547 // Force the destruction of the source window. 595 // Force the destruction of the source window.
548 window1.reset(); 596 window1.reset();
549 597
550 // The source window going away fails the drag. 598 // The source window going away fails the drag.
551 EXPECT_FALSE(drag_completed_value().value_or(true)); 599 EXPECT_FALSE(drag_completed_value().value_or(true));
552 } 600 }
553 601
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
602 // This starts the operation with PointerEvent::kMousePointerId. 650 // This starts the operation with PointerEvent::kMousePointerId.
603 StartDragOperation(std::move(mime_data), window.get(), 651 StartDragOperation(std::move(mime_data), window.get(),
604 ui::mojom::kDropEffectMove); 652 ui::mojom::kDropEffectMove);
605 653
606 // Ignore events from pointer 5. 654 // Ignore events from pointer 5.
607 DispatchDragWithPointer(window.get(), 5, false, ui::EF_LEFT_MOUSE_BUTTON, 655 DispatchDragWithPointer(window.get(), 5, false, ui::EF_LEFT_MOUSE_BUTTON,
608 gfx::Point(1, 1)); 656 gfx::Point(1, 1));
609 ASSERT_EQ(0u, window->queue_size()); 657 ASSERT_EQ(0u, window->queue_size());
610 } 658 }
611 659
612 // TODO(erg): Add a test to ensure windows that the cursor isn't over 660 TEST_F(DragControllerTest, RejectingWindowHasProperCursor) {
613 // responding to messages don't change the cursor when we have cursor handling 661 std::unique_ptr<DragTestWindow> window = BuildWindow();
614 // code. 662 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data;
663 StartDragOperation(std::move(mime_data), window.get(),
664 ui::mojom::kDropEffectMove);
665
666 EXPECT_EQ(ui::mojom::Cursor::NO_DROP, cursor());
667
668 DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(1, 1));
669 EXPECT_EQ(QueuedType::ENTER, window->queue_response_type());
670 window->Respond(true);
671
672 EXPECT_EQ(ui::mojom::Cursor::COPY, cursor());
673
674 DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(2, 2));
675 EXPECT_EQ(QueuedType::OVER, window->queue_response_type());
676
677 // At this point, we respond with no available drag actions at this pixel.
678 window->Respond(false);
679 EXPECT_EQ(ui::mojom::Cursor::NO_DROP, cursor());
680 }
681
682 TEST_F(DragControllerTest, ResopnseFromOtherWindowDoesntChangeCursor) {
683 std::unique_ptr<DragTestWindow> window1 = BuildWindow();
684 std::unique_ptr<DragTestWindow> window2 = BuildWindow();
685 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data;
686 StartDragOperation(std::move(mime_data), window1.get(),
687 ui::mojom::kDropEffectMove);
688
689 // Send some events to |window2|.
690 DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
691 gfx::Point(1, 1));
692 EXPECT_EQ(QueuedType::ENTER, window2->queue_response_type());
693 DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
694 gfx::Point(1, 1));
695
696 EXPECT_EQ(ui::mojom::Cursor::NO_DROP, cursor());
697
698 // Now enter |window1|, and respond.
699 DispatchDrag(window1.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
700 gfx::Point(5, 5));
701 EXPECT_EQ(QueuedType::ENTER, window1->queue_response_type());
702 window1->Respond(true);
703
704 EXPECT_EQ(ui::mojom::Cursor::COPY, cursor());
705
706 // Window 2 responding negatively to its queued messages shouldn't change the
707 // cursor.
708 window2->Respond(false);
709
710 EXPECT_EQ(ui::mojom::Cursor::COPY, cursor());
711 }
615 712
616 } // namespace ws 713 } // namespace ws
617 } // namespace ui 714 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698