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

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

Issue 2266603002: mus: Implement interwindow drag and drop (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: more comments Created 4 years, 3 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
« no previous file with comments | « services/ui/ws/drag_controller.cc ('k') | services/ui/ws/drag_source.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "services/ui/ws/drag_controller.h"
6
7 #include "services/ui/ws/drag_source.h"
8 #include "services/ui/ws/drag_target_connection.h"
9 #include "services/ui/ws/ids.h"
10 #include "services/ui/ws/server_window.h"
11 #include "services/ui/ws/test_server_window_delegate.h"
12 #include "services/ui/ws/test_utils.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "ui/events/base_event_utils.h"
15
16 namespace ui {
17 namespace ws {
18
19 enum class QueuedType { NONE, ENTER, OVER, LEAVE, DROP };
20
21 class DragControllerTest;
22
23 // All the classes to represent a window.
24 class DragTestWindow : public DragTargetConnection {
25 public:
26 struct DragEvent {
27 QueuedType type;
28 uint32_t key_state;
29 gfx::Point cursor_offset;
30 uint32_t effect_bitmask;
31 base::Callback<void(uint32_t)> callback;
32 };
33
34 DragTestWindow(DragControllerTest* parent, const WindowId& id)
35 : parent_(parent), window_delegate_(), window_(&window_delegate_, id) {
36 window_.SetCanAcceptDrops(true);
37 }
38 ~DragTestWindow() override;
39
40 TestServerWindowDelegate* delegate() { return &window_delegate_; }
41 ServerWindow* window() { return &window_; }
42
43 QueuedType queue_response_type() {
44 if (queued_callbacks_.empty())
45 return QueuedType::NONE;
46 return queued_callbacks_.front().type;
47 }
48
49 const DragEvent& queue_front() { return queued_callbacks_.front(); }
50
51 size_t queue_size() { return queued_callbacks_.size(); }
52
53 uint32_t times_received_drag_drop_start() {
54 return times_received_drag_drop_start_;
55 }
56
57 void SetParent(DragTestWindow* p) { p->window_.Add(&window_); }
58
59 void OptOutOfDrag() { window_.SetCanAcceptDrops(false); }
60
61 // Calls the callback at the front of the queue.
62 void Respond(bool respond_with_effect) {
63 if (queued_callbacks_.size()) {
64 if (!queued_callbacks_.front().callback.is_null()) {
65 queued_callbacks_.front().callback.Run(
66 respond_with_effect ? queued_callbacks_.front().effect_bitmask : 0);
67 }
68
69 queued_callbacks_.pop();
70 }
71 }
72
73 // Overridden from DragTestConnection:
74 void PerformOnDragDropStart(
75 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data) override {
76 times_received_drag_drop_start_++;
77 mime_data_ = std::move(mime_data);
78 }
79
80 void PerformOnDragEnter(
81 const ServerWindow* window,
82 uint32_t key_state,
83 const gfx::Point& cursor_offset,
84 uint32_t effect_bitmask,
85 const base::Callback<void(uint32_t)>& callback) override {
86 DCHECK_EQ(window, &window_);
87 queued_callbacks_.push({QueuedType::ENTER, key_state, cursor_offset,
88 effect_bitmask, callback});
89 }
90
91 void PerformOnDragOver(
92 const ServerWindow* window,
93 uint32_t key_state,
94 const gfx::Point& cursor_offset,
95 uint32_t effect_bitmask,
96 const base::Callback<void(uint32_t)>& callback) override {
97 DCHECK_EQ(window, &window_);
98 queued_callbacks_.push(
99 {QueuedType::OVER, key_state, cursor_offset, effect_bitmask, callback});
100 }
101
102 void PerformOnDragLeave(const ServerWindow* window) override {
103 DCHECK_EQ(window, &window_);
104 queued_callbacks_.push({QueuedType::LEAVE, 0, gfx::Point(), 0,
105 base::Callback<void(uint32_t)>()});
106 }
107
108 void PerformOnCompleteDrop(
109 const ServerWindow* window,
110 uint32_t key_state,
111 const gfx::Point& cursor_offset,
112 uint32_t effect_bitmask,
113 const base::Callback<void(uint32_t)>& callback) override {
114 DCHECK_EQ(window, &window_);
115 queued_callbacks_.push(
116 {QueuedType::DROP, key_state, cursor_offset, effect_bitmask, callback});
117 }
118
119 void PerformOnDragDropDone() override { mime_data_.SetToEmpty(); }
120
121 private:
122 DragControllerTest* parent_;
123 TestServerWindowDelegate window_delegate_;
124 ServerWindow window_;
125 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data_;
126 uint32_t times_received_drag_drop_start_ = 0;
127
128 std::queue<DragEvent> queued_callbacks_;
129 };
130
131 class DragControllerTest : public testing::Test, public DragSource {
132 public:
133 std::unique_ptr<DragTestWindow> BuildWindow() {
134 WindowId id(1, ++window_id_);
135 std::unique_ptr<DragTestWindow> p =
136 base::MakeUnique<DragTestWindow>(this, id);
137 server_window_by_id_[id] = p->window();
138 connection_by_window_[p->window()] = p.get();
139 return p;
140 }
141
142 void StartDragOperation(
143 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data,
144 DragTestWindow* window,
145 uint32_t drag_operations) {
146 window->PerformOnDragDropStart(mime_data.Clone());
147 drag_operation_.reset(new DragController(
148 this, window->window(), window, PointerEvent::kMousePointerId,
149 std::move(mime_data), drag_operations));
150 }
151
152 void DispatchDrag(DragTestWindow* window,
153 bool mouse_released,
154 uint32_t flags,
155 const gfx::Point& position) {
156 ui::PointerEvent event(
157 ui::MouseEvent(mouse_released ? ET_MOUSE_RELEASED : ET_MOUSE_PRESSED,
158 position, position, ui::EventTimeForNow(), flags, 0));
159 drag_operation_->DispatchPointerEvent(event,
160 window ? window->window() : nullptr);
161 }
162
163 void DispatchDragWithPointer(DragTestWindow* window,
164 int32_t drag_pointer,
165 bool mouse_released,
166 uint32_t flags,
167 const gfx::Point& position) {
168 ui::PointerEvent event(ET_POINTER_DOWN, position, position, flags,
169 drag_pointer, 0, PointerDetails(),
170 base::TimeTicks());
171 drag_operation_->DispatchPointerEvent(event,
172 window ? window->window() : nullptr);
173 }
174
175 void OnTestWindowDestroyed(DragTestWindow* test_window) {
176 drag_operation_->OnWillDestroyDragTargetConnection(test_window);
177 server_window_by_id_.erase(test_window->window()->id());
178 connection_by_window_.erase(test_window->window());
179 }
180
181 DragController* drag_operation() const { return drag_operation_.get(); }
182 const base::Optional<bool>& drag_completed_value() {
183 return drag_completed_value_;
184 }
185
186 private:
187 // Overridden from testing::Test:
188 void SetUp() override {
189 testing::Test::SetUp();
190
191 window_delegate_.reset(new TestServerWindowDelegate());
192 root_window_.reset(
193 new ServerWindow(window_delegate_.get(), WindowId(1, 2)));
194 window_delegate_->set_root_window(root_window_.get());
195 root_window_->SetVisible(true);
196 }
197
198 void TearDown() override {
199 drag_operation_.reset();
200 root_window_.reset();
201 window_delegate_.reset();
202
203 DCHECK(server_window_by_id_.empty());
204 DCHECK(connection_by_window_.empty());
205
206 testing::Test::TearDown();
207 }
208
209 // Overridden from DragControllerSource:
210 void OnDragCompleted(bool success) override {
211 drag_completed_value_ = success;
212 }
213
214 ServerWindow* GetWindowById(const WindowId& id) override {
215 auto it = server_window_by_id_.find(id);
216 if (it == server_window_by_id_.end())
217 return nullptr;
218 return it->second;
219 }
220
221 DragTargetConnection* GetDragTargetForWindow(
222 const ServerWindow* window) override {
223 auto it = connection_by_window_.find(const_cast<ServerWindow*>(window));
224 if (it == connection_by_window_.end())
225 return nullptr;
226 return it->second;
227 }
228
229 int window_id_ = 3;
230
231 std::map<WindowId, ServerWindow*> server_window_by_id_;
232 std::map<ServerWindow*, DragTargetConnection*> connection_by_window_;
233
234 std::unique_ptr<TestServerWindowDelegate> window_delegate_;
235 std::unique_ptr<ServerWindow> root_window_;
236
237 std::unique_ptr<DragController> drag_operation_;
238
239 base::Optional<bool> drag_completed_value_;
240 };
241
242 DragTestWindow::~DragTestWindow() {
243 parent_->OnTestWindowDestroyed(this);
244 }
245
246 TEST_F(DragControllerTest, SimpleDragDrop) {
247 std::unique_ptr<DragTestWindow> window = BuildWindow();
248 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data;
249 StartDragOperation(std::move(mime_data), window.get(),
250 ui::mojom::kDropEffectMove);
251
252 DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(1, 1));
253 EXPECT_EQ(QueuedType::ENTER, window->queue_response_type());
254 window->Respond(true);
255
256 DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(2, 2));
257 EXPECT_EQ(QueuedType::OVER, window->queue_response_type());
258 window->Respond(true);
259
260 DispatchDrag(window.get(), true, 0, gfx::Point(2, 2));
261 EXPECT_EQ(QueuedType::DROP, window->queue_response_type());
262 window->Respond(true);
263
264 EXPECT_TRUE(drag_completed_value().value_or(false));
265 }
266
267 TEST_F(DragControllerTest, OnlyDeliverMimeDataOnce) {
268 std::unique_ptr<DragTestWindow> window1 = BuildWindow();
269 std::unique_ptr<DragTestWindow> window2 = BuildWindow();
270 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data;
271
272 // The client lib is responsible for sending the data to the window that's
273 // the drag source to minimize IPC.
274 EXPECT_EQ(0u, window1->times_received_drag_drop_start());
275 StartDragOperation(std::move(mime_data), window1.get(),
276 ui::mojom::kDropEffectMove);
277 EXPECT_EQ(1u, window1->times_received_drag_drop_start());
278 DispatchDrag(window1.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
279 gfx::Point(1, 1));
280 EXPECT_EQ(1u, window1->times_received_drag_drop_start());
281 window1->Respond(true);
282
283 // Window2 doesn't receive the drag data until mouse is over it.
284 EXPECT_EQ(0u, window2->times_received_drag_drop_start());
285 DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
286 gfx::Point(2, 2));
287 EXPECT_EQ(1u, window2->times_received_drag_drop_start());
288
289 // Moving back to the source window doesn't send an additional start message.
290 DispatchDrag(window1.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
291 gfx::Point(1, 1));
292 EXPECT_EQ(1u, window1->times_received_drag_drop_start());
293
294 // Moving back to window2 doesn't send an additional start message.
295 DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
296 gfx::Point(1, 1));
297 EXPECT_EQ(1u, window2->times_received_drag_drop_start());
298 }
299
300 TEST_F(DragControllerTest, DeliverMessageToParent) {
301 std::unique_ptr<DragTestWindow> window1 = BuildWindow();
302 std::unique_ptr<DragTestWindow> window2 = BuildWindow();
303 std::unique_ptr<DragTestWindow> window3 = BuildWindow();
304 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data;
305
306 window3->SetParent(window2.get());
307 window3->OptOutOfDrag();
308
309 StartDragOperation(std::move(mime_data), window1.get(),
310 ui::mojom::kDropEffectMove);
311
312 // Dispatching a drag to window3 (which has can accept drags off) redirects
313 // to window2, which is its parent.
314 DispatchDrag(window3.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
315 gfx::Point(1, 1));
316 EXPECT_EQ(1u, window2->times_received_drag_drop_start());
317 }
318
319 TEST_F(DragControllerTest, FailWhenDropOverNoWindow) {
320 std::unique_ptr<DragTestWindow> window = BuildWindow();
321 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data;
322 StartDragOperation(std::move(mime_data), window.get(),
323 ui::mojom::kDropEffectMove);
324
325 DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(1, 1));
326 EXPECT_EQ(QueuedType::ENTER, window->queue_response_type());
327 window->Respond(true);
328
329 DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(2, 2));
330 EXPECT_EQ(QueuedType::OVER, window->queue_response_type());
331 window->Respond(true);
332
333 DispatchDrag(nullptr, true, 0, gfx::Point(2, 2));
334 // Moving outside of |window| should result in |window| getting a leave.
335 EXPECT_EQ(QueuedType::LEAVE, window->queue_response_type());
336 window->Respond(true);
337
338 EXPECT_FALSE(drag_completed_value().value_or(true));
339 }
340
341 TEST_F(DragControllerTest, EnterLeaveWhenMovingBetweenTwoWindows) {
342 std::unique_ptr<DragTestWindow> window1 = BuildWindow();
343 std::unique_ptr<DragTestWindow> window2 = BuildWindow();
344 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data;
345 StartDragOperation(std::move(mime_data), window1.get(),
346 ui::mojom::kDropEffectMove);
347
348 DispatchDrag(window1.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
349 gfx::Point(1, 1));
350 EXPECT_EQ(QueuedType::ENTER, window1->queue_response_type());
351 window1->Respond(true);
352
353 DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
354 gfx::Point(2, 2));
355 EXPECT_EQ(QueuedType::ENTER, window2->queue_response_type());
356 EXPECT_EQ(QueuedType::LEAVE, window1->queue_response_type());
357 window1->Respond(true);
358 window2->Respond(true);
359 }
360
361 TEST_F(DragControllerTest, DeadWindowDoesntBlock) {
362 std::unique_ptr<DragTestWindow> window1 = BuildWindow();
363 std::unique_ptr<DragTestWindow> window2 = BuildWindow();
364 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data;
365 StartDragOperation(std::move(mime_data), window1.get(),
366 ui::mojom::kDropEffectMove);
367
368 test::DragControllerTestApi api(drag_operation());
369
370 // Simulate a dead window by giving it a few messages, but don't respond to
371 // them.
372 DispatchDrag(window1.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
373 gfx::Point(1, 1));
374 DispatchDrag(window1.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
375 gfx::Point(2, 2));
376 EXPECT_EQ(1u, window1->queue_size());
377 EXPECT_EQ(2u, api.GetSizeOfQueueForWindow(window1->window()));
378
379 // Moving to window2 should dispatch the enter event to it immediately.
380 DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
381 gfx::Point(3, 3));
382 EXPECT_EQ(QueuedType::ENTER, window2->queue_response_type());
383 EXPECT_EQ(1u, window1->queue_size());
384 }
385
386 TEST_F(DragControllerTest, EnterToOverQueued) {
387 std::unique_ptr<DragTestWindow> window = BuildWindow();
388 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data;
389 StartDragOperation(std::move(mime_data), window.get(),
390 ui::mojom::kDropEffectMove);
391
392 DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(1, 1));
393 ASSERT_EQ(1u, window->queue_size());
394 EXPECT_EQ(QueuedType::ENTER, window->queue_response_type());
395 // Don't respond.
396
397 // We don't receive another message since we haven't acknowledged the first.
398 DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(1, 2));
399 ASSERT_EQ(1u, window->queue_size());
400
401 // Responding causes us to receive our next event.
402 window->Respond(true);
403 ASSERT_EQ(1u, window->queue_size());
404 EXPECT_EQ(QueuedType::OVER, window->queue_response_type());
405 }
406
407 TEST_F(DragControllerTest, CoalesceMouseOverEvents) {
408 std::unique_ptr<DragTestWindow> window = BuildWindow();
409 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data;
410 StartDragOperation(std::move(mime_data), window.get(),
411 ui::mojom::kDropEffectMove);
412
413 DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(1, 1));
414 EXPECT_EQ(QueuedType::ENTER, window->queue_response_type());
415
416 DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(1, 2));
417 DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(2, 2));
418 DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(2, 3));
419
420 // Responding to the first delivers us the last mouse over event's position.
421 window->Respond(true);
422 ASSERT_EQ(1u, window->queue_size());
423 EXPECT_EQ(QueuedType::OVER, window->queue_response_type());
424 EXPECT_EQ(gfx::Point(2, 3), window->queue_front().cursor_offset);
425
426 // There are no queued events because they were coalesced.
427 window->Respond(true);
428 EXPECT_EQ(0u, window->queue_size());
429 }
430
431 TEST_F(DragControllerTest, RemovePendingMouseOversOnLeave) {
432 std::unique_ptr<DragTestWindow> window1 = BuildWindow();
433 std::unique_ptr<DragTestWindow> window2 = BuildWindow();
434 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data;
435 StartDragOperation(std::move(mime_data), window1.get(),
436 ui::mojom::kDropEffectMove);
437
438 // Enter
439 DispatchDrag(window1.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
440 gfx::Point(1, 1));
441 EXPECT_EQ(QueuedType::ENTER, window1->queue_response_type());
442
443 // Over
444 DispatchDrag(window1.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
445 gfx::Point(1, 1));
446
447 // Leave
448 DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
449 gfx::Point(1, 1));
450
451 // The window finally responds to the enter message; we should not receive
452 // any over messages since we didn't respond to the enter message in time.
453 window1->Respond(true);
454 ASSERT_EQ(1u, window1->queue_size());
455 EXPECT_EQ(QueuedType::LEAVE, window1->queue_response_type());
456 }
457
458 TEST_F(DragControllerTest, TargetWindowClosedWhileDrag) {
459 std::unique_ptr<DragTestWindow> window1 = BuildWindow();
460 std::unique_ptr<DragTestWindow> window2 = BuildWindow();
461 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data;
462 StartDragOperation(std::move(mime_data), window1.get(),
463 ui::mojom::kDropEffectMove);
464
465 test::DragControllerTestApi api(drag_operation());
466
467 // Send some events to |window|.
468 DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
469 gfx::Point(1, 1));
470 EXPECT_EQ(QueuedType::ENTER, window2->queue_response_type());
471 DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
472 gfx::Point(1, 1));
473
474 ServerWindow* server_window = window2->window();
475
476 // Ensure that DragController is waiting for a response from |window|.
477 EXPECT_EQ(2u, api.GetSizeOfQueueForWindow(server_window));
478 EXPECT_EQ(server_window, api.GetCurrentTarget());
479
480 // Force the destruction of |window.window|.
481 window2.reset();
482
483 // DragController doesn't know anything about the server window now.
484 EXPECT_EQ(0u, api.GetSizeOfQueueForWindow(server_window));
485 EXPECT_EQ(nullptr, api.GetCurrentTarget());
486
487 // But a target window closing out from under us doesn't fail the drag.
488 EXPECT_FALSE(drag_completed_value().has_value());
489 }
490
491 TEST_F(DragControllerTest, SourceWindowClosedWhileDrag) {
492 std::unique_ptr<DragTestWindow> window1 = BuildWindow();
493 std::unique_ptr<DragTestWindow> window2 = BuildWindow();
494 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data;
495 StartDragOperation(std::move(mime_data), window1.get(),
496 ui::mojom::kDropEffectMove);
497
498 test::DragControllerTestApi api(drag_operation());
499
500 // Send some events to |window|.
501 DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
502 gfx::Point(1, 1));
503 EXPECT_EQ(QueuedType::ENTER, window2->queue_response_type());
504 DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON,
505 gfx::Point(1, 1));
506
507 ServerWindow* server_window = window2->window();
508
509 // Ensure that DragController is waiting for a response from |window|.
510 EXPECT_EQ(2u, api.GetSizeOfQueueForWindow(server_window));
511 EXPECT_EQ(server_window, api.GetCurrentTarget());
512
513 // Force the destruction of the source window.
514 window1.reset();
515
516 // The source window going away fails the drag.
517 EXPECT_FALSE(drag_completed_value().value_or(true));
518 }
519
520 TEST_F(DragControllerTest, DontQueueEventsAfterDrop) {
521 // The DragController needs to stick around to coordinate the drop, but
522 // it should ignore further mouse events during this time.
523 std::unique_ptr<DragTestWindow> window = BuildWindow();
524 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data;
525 StartDragOperation(std::move(mime_data), window.get(),
526 ui::mojom::kDropEffectMove);
527
528 test::DragControllerTestApi api(drag_operation());
529
530 DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(1, 1));
531 EXPECT_EQ(QueuedType::ENTER, window->queue_response_type());
532 window->Respond(true);
533
534 DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(2, 2));
535 EXPECT_EQ(QueuedType::OVER, window->queue_response_type());
536 window->Respond(true);
537
538 DispatchDrag(window.get(), true, 0, gfx::Point(2, 2));
539 EXPECT_EQ(QueuedType::DROP, window->queue_response_type());
540 EXPECT_EQ(1u, api.GetSizeOfQueueForWindow(window->window()));
541
542 // Further located events don't result in additional drag messages.
543 DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(2, 2));
544 DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(2, 2));
545 EXPECT_EQ(1u, api.GetSizeOfQueueForWindow(window->window()));
546 }
547
548 TEST_F(DragControllerTest, CancelDrag) {
549 // The DragController needs to stick around to coordinate the drop, but
550 // it should ignore further mouse events during this time.
551 std::unique_ptr<DragTestWindow> window = BuildWindow();
552 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data;
553 StartDragOperation(std::move(mime_data), window.get(),
554 ui::mojom::kDropEffectMove);
555
556 DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(1, 1));
557 EXPECT_EQ(QueuedType::ENTER, window->queue_response_type());
558 window->Respond(true);
559
560 drag_operation()->Cancel();
561
562 EXPECT_FALSE(drag_completed_value().value_or(true));
563 }
564
565 TEST_F(DragControllerTest, IgnoreEventsFromOtherPointers) {
566 std::unique_ptr<DragTestWindow> window = BuildWindow();
567 mojo::Map<mojo::String, mojo::Array<uint8_t>> mime_data;
568 // This starts the operation with PointerEvent::kMousePointerId.
569 StartDragOperation(std::move(mime_data), window.get(),
570 ui::mojom::kDropEffectMove);
571
572 // Ignore events from pointer 5.
573 DispatchDragWithPointer(window.get(), 5, false, ui::EF_LEFT_MOUSE_BUTTON,
574 gfx::Point(1, 1));
575 ASSERT_EQ(0u, window->queue_size());
576 }
577
578 // TODO(erg): Add a test to ensure windows that the cursor isn't over
579 // responding to messages don't change the cursor when we have cursor handling
580 // code.
581
582 } // namespace ws
583 } // namespace ui
OLDNEW
« no previous file with comments | « services/ui/ws/drag_controller.cc ('k') | services/ui/ws/drag_source.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698