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

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

Powered by Google App Engine
This is Rietveld 408576698