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

Side by Side Diff: ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc

Issue 268083002: Add tests for drag and drop for Linux Aura (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc ('k') | no next file » | 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 2014 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 <map>
6 #include <vector>
7
8 // Include views_test_base.h first because the definition of None in X.h
9 // conflicts with the definition of None in gtest-type-util.h
10 #include "ui/views/test/views_test_base.h"
11
12 #include "base/memory/scoped_ptr.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "ui/aura/window.h"
15 #include "ui/aura/window_tree_host.h"
16 #include "ui/base/dragdrop/os_exchange_data.h"
17 #include "ui/base/x/x11_util.h"
18 #include "ui/gfx/x/x11_atom_cache.h"
19 #include "ui/gfx/x/x11_types.h"
20 #include "ui/views/widget/desktop_aura/desktop_cursor_loader_updater.h"
21 #include "ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h"
22 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
23 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
24 #include "ui/views/widget/widget.h"
25
26 #include <X11/Xlib.h>
27
28 namespace views {
29
30 namespace {
31
32 const char* kAtomsToCache[] = {
33 "XdndActionCopy",
34 "XdndDrop",
35 "XdndEnter",
36 "XdndFinished",
37 "XdndLeave",
38 "XdndPosition",
39 "XdndStatus",
40 "XdndTypeList",
41 NULL
42 };
43
44 class TestDragDropClient;
45
46 // Collects messages which would otherwise be sent to |xid_| via
47 // SendXClientEvent().
48 class ClientMessageEventCollector {
49 public:
50 ClientMessageEventCollector(::Window xid, TestDragDropClient* client);
51 virtual ~ClientMessageEventCollector();
52
53 // Returns true if |events_| is non-empty.
54 bool HasEvents() const {
55 return !events_.empty();
56 }
57
58 // Pops all of |events_| and returns the popped events in the order that they
59 // were on the stack
60 std::vector<XClientMessageEvent> PopAllEvents();
61
62 // Adds |event| to the stack.
63 void RecordEvent(const XClientMessageEvent& event);
64
65 private:
66 ::Window xid_;
67
68 // Not owned.
69 TestDragDropClient* client_;
70
71 std::vector<XClientMessageEvent> events_;
72
73 DISALLOW_COPY_AND_ASSIGN(ClientMessageEventCollector);
74 };
75
76 // Implementation of DesktopDragDropClientAuraX11 which works with a fake
77 // |DesktopDragDropClientAuraX11::source_current_window_|.
78 class TestDragDropClient : public DesktopDragDropClientAuraX11 {
79 public:
80 // The location in screen coordinates used for the synthetic mouse moves
81 // generated in SetTopmostXWindowAndMoveMouse().
82 static const int kMouseMoveX;
83 static const int kMouseMoveY;
84
85 TestDragDropClient(aura::Window* window,
86 DesktopNativeCursorManager* cursor_manager);
87 virtual ~TestDragDropClient();
88
89 // Returns the XID of the window which initiated the drag.
90 ::Window source_xwindow() {
91 return source_xid_;
92 }
93
94 // Returns the Atom with |name|.
95 Atom GetAtom(const char* name);
96
97 // Returns true if the event's message has |type|.
98 bool MessageHasType(const XClientMessageEvent& event,
99 const char* type);
100
101 // Sets |collector| to collect XClientMessageEvents which would otherwise
102 // have been sent to the drop target window.
103 void SetEventCollectorFor(::Window xid,
104 ClientMessageEventCollector* collector);
105
106 // Builds an XdndStatus message and sends it to
107 // DesktopDragDropClientAuraX11.
108 void OnStatus(XID target_window,
109 bool will_accept_drop,
110 ::Atom accepted_action);
111
112 // Builds an XdndFinished message and sends it to
113 // DesktopDragDropClientAuraX11.
114 void OnFinished(XID target_window,
115 bool accepted_drop,
116 ::Atom performed_action);
117
118 // Sets |xid| as the topmost window at the current mouse position and
119 // generates a synthetic mouse move.
120 void SetTopmostXWindowAndMoveMouse(::Window xid);
121
122 // Returns true if the move loop is running.
123 bool IsMoveLoopRunning();
124
125 // DesktopDragDropClientAuraX11:
126 virtual int StartDragAndDrop(
127 const ui::OSExchangeData& data,
128 aura::Window* root_window,
129 aura::Window* source_window,
130 const gfx::Point& root_location,
131 int operation,
132 ui::DragDropTypes::DragEventSource source) OVERRIDE;
133 virtual void OnMoveLoopEnded() OVERRIDE;
134
135 private:
136 // DesktopDragDropClientAuraX11:
137 virtual ::Window FindWindowFor(const gfx::Point& screen_point) OVERRIDE;
138 virtual void SendXClientEvent(::Window xid, XEvent* event) OVERRIDE;
139
140 // The XID of the window which initiated the drag.
141 ::Window source_xid_;
142
143 // The XID of the window which is simulated to be the topmost window at the
144 // current mouse position.
145 ::Window target_xid_;
146
147 // Whether the move loop is running.
148 bool move_loop_running_;
149
150 // Map of ::Windows to the collector which intercepts XClientMessageEvents
151 // for that window.
152 std::map< ::Window, ClientMessageEventCollector*> collectors_;
153
154 ui::X11AtomCache atom_cache_;
155
156 DISALLOW_COPY_AND_ASSIGN(TestDragDropClient);
157 };
158
159 ///////////////////////////////////////////////////////////////////////////////
160 // ClientMessageEventCollector
161
162 ClientMessageEventCollector::ClientMessageEventCollector(
163 ::Window xid,
164 TestDragDropClient* client)
165 : xid_(xid),
166 client_(client) {
167 client->SetEventCollectorFor(xid, this);
168 }
169
170 ClientMessageEventCollector::~ClientMessageEventCollector() {
171 client_->SetEventCollectorFor(xid_, NULL);
172 }
173
174 std::vector<XClientMessageEvent> ClientMessageEventCollector::PopAllEvents() {
175 std::vector<XClientMessageEvent> to_return;
176 to_return.swap(events_);
177 return to_return;
178 }
179
180 void ClientMessageEventCollector::RecordEvent(
181 const XClientMessageEvent& event) {
182 events_.push_back(event);
183 }
184
185 ///////////////////////////////////////////////////////////////////////////////
186 // TestDragDropClient
187
188 // static
189 const int TestDragDropClient::kMouseMoveX = 100;
190
191 // static
192 const int TestDragDropClient::kMouseMoveY = 200;
193
194 TestDragDropClient::TestDragDropClient(
195 aura::Window* window,
196 DesktopNativeCursorManager* cursor_manager)
197 : DesktopDragDropClientAuraX11(window,
198 cursor_manager,
199 gfx::GetXDisplay(),
200 window->GetHost()->GetAcceleratedWidget()),
201 source_xid_(window->GetHost()->GetAcceleratedWidget()),
202 target_xid_(None),
203 move_loop_running_(false),
204 atom_cache_(gfx::GetXDisplay(), kAtomsToCache) {
205 }
206
207 TestDragDropClient::~TestDragDropClient() {
208 }
209
210 Atom TestDragDropClient::GetAtom(const char* name) {
211 return atom_cache_.GetAtom(name);
212 }
213
214 bool TestDragDropClient::MessageHasType(const XClientMessageEvent& event,
215 const char* type) {
216 return event.message_type == atom_cache_.GetAtom(type);
217 }
218
219 void TestDragDropClient::SetEventCollectorFor(
220 ::Window xid,
221 ClientMessageEventCollector* collector) {
222 if (collector)
223 collectors_[xid] = collector;
224 else
225 collectors_.erase(xid);
226 }
227
228 void TestDragDropClient::OnStatus(XID target_window,
229 bool will_accept_drop,
230 ::Atom accepted_action) {
231 XClientMessageEvent event;
232 event.message_type = atom_cache_.GetAtom("XdndStatus");
233 event.format = 32;
234 event.window = source_xid_;
235 event.data.l[0] = target_window;
236 event.data.l[1] = will_accept_drop ? 1 : 0;
237 event.data.l[2] = 0;
238 event.data.l[3] = 0;
239 event.data.l[4] = accepted_action;
240 OnXdndStatus(event);
241 }
242
243 void TestDragDropClient::OnFinished(XID target_window,
244 bool accepted_drop,
245 ::Atom performed_action) {
246 XClientMessageEvent event;
247 event.message_type = atom_cache_.GetAtom("XdndFinished");
248 event.format = 32;
249 event.window = source_xid_;
250 event.data.l[0] = target_window;
251 event.data.l[1] = accepted_drop ? 1 : 0;
252 event.data.l[2] = performed_action;
253 event.data.l[3] = 0;
254 event.data.l[4] = 0;
255 OnXdndFinished(event);
256 }
257
258 void TestDragDropClient::SetTopmostXWindowAndMoveMouse(::Window xid) {
259 target_xid_ = xid;
260
261 XMotionEvent event;
262 event.time = CurrentTime;
263 event.x_root = kMouseMoveX;
264 event.y_root = kMouseMoveY;
265 OnMouseMovement(&event);
266 }
267
268 bool TestDragDropClient::IsMoveLoopRunning() {
269 return move_loop_running_;
270 }
271
272 int TestDragDropClient::StartDragAndDrop(
273 const ui::OSExchangeData& data,
274 aura::Window* root_window,
275 aura::Window* source_window,
276 const gfx::Point& root_location,
277 int operation,
278 ui::DragDropTypes::DragEventSource source) {
279 move_loop_running_ = true;
280 return DesktopDragDropClientAuraX11::StartDragAndDrop(data, root_window,
281 source_window, root_location, operation, source);
282 }
283
284 void TestDragDropClient::OnMoveLoopEnded() {
285 DesktopDragDropClientAuraX11::OnMoveLoopEnded();
286 move_loop_running_ = false;
287 }
288
289 ::Window TestDragDropClient::FindWindowFor(const gfx::Point& screen_point) {
290 return target_xid_;
291 }
292
293 void TestDragDropClient::SendXClientEvent(::Window xid, XEvent* event) {
294 std::map< ::Window, ClientMessageEventCollector*>::iterator it =
295 collectors_.find(xid);
296 if (it != collectors_.end())
297 it->second->RecordEvent(event->xclient);
298 }
299
300 } // namespace
301
302 class DesktopDragDropClientAuraX11Test : public ViewsTestBase {
303 public:
304 DesktopDragDropClientAuraX11Test() {
305 }
306
307 virtual ~DesktopDragDropClientAuraX11Test() {
308 }
309
310 int StartDragAndDrop() {
311 ui::OSExchangeData data;
312 data.SetString(base::ASCIIToUTF16("Test"));
313
314 return client_->StartDragAndDrop(
315 data,
316 widget_->GetNativeWindow()->GetRootWindow(),
317 widget_->GetNativeWindow(),
318 gfx::Point(),
319 ui::DragDropTypes::DRAG_COPY,
320 ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
321 }
322
323 // ViewsTestBase:
324 virtual void SetUp() OVERRIDE {
325 ViewsTestBase::SetUp();
326
327 // Create widget to initiate the drags.
328 widget_.reset(new Widget);
329 Widget::InitParams params(Widget::InitParams::TYPE_WINDOW);
330 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
331 params.native_widget = new DesktopNativeWidgetAura(widget_.get());
332 params.bounds = gfx::Rect(100, 100);
333 widget_->Init(params);
334 widget_->Show();
335
336 cursor_manager_.reset(new DesktopNativeCursorManager(
337 DesktopCursorLoaderUpdater::Create()));
338
339 client_.reset(new TestDragDropClient(widget_->GetNativeWindow(),
340 cursor_manager_.get()));
341 }
342
343 virtual void TearDown() OVERRIDE {
344 client_.reset();
345 cursor_manager_.reset();
346 widget_.reset();
347 ViewsTestBase::TearDown();
348 }
349
350 TestDragDropClient* client() {
351 return client_.get();
352 }
353
354 private:
355 scoped_ptr<TestDragDropClient> client_;
356 scoped_ptr<DesktopNativeCursorManager> cursor_manager_;
357
358 // The widget used to initiate drags.
359 scoped_ptr<Widget> widget_;
360
361 DISALLOW_COPY_AND_ASSIGN(DesktopDragDropClientAuraX11Test);
362 };
363
364 namespace {
365
366 void BasicStep2(TestDragDropClient* client, XID toplevel) {
367 EXPECT_TRUE(client->IsMoveLoopRunning());
368
369 ClientMessageEventCollector collector(toplevel, client);
370 client->SetTopmostXWindowAndMoveMouse(toplevel);
371
372 // XdndEnter should have been sent to |toplevel| before the XdndPosition
373 // message.
374 std::vector<XClientMessageEvent> events = collector.PopAllEvents();
375 ASSERT_EQ(2u, events.size());
376
377 EXPECT_TRUE(client->MessageHasType(events[0], "XdndEnter"));
378 EXPECT_EQ(client->source_xwindow(),
379 static_cast<XID>(events[0].data.l[0]));
380 EXPECT_EQ(1, events[0].data.l[1] & 1);
381 std::vector<Atom> targets;
382 ui::GetAtomArrayProperty(client->source_xwindow(), "XdndTypeList", &targets);
383 EXPECT_FALSE(targets.empty());
384
385 EXPECT_TRUE(client->MessageHasType(events[1], "XdndPosition"));
386 EXPECT_EQ(client->source_xwindow(),
387 static_cast<XID>(events[0].data.l[0]));
388 const long kCoords =
389 TestDragDropClient::kMouseMoveX << 16 | TestDragDropClient::kMouseMoveY;
390 EXPECT_EQ(kCoords, events[1].data.l[2]);
391 EXPECT_EQ(client->GetAtom("XdndActionCopy"),
392 static_cast<Atom>(events[1].data.l[4]));
393
394 client->OnStatus(toplevel, true, client->GetAtom("XdndActionCopy"));
395
396 // Because there is no unprocessed XdndPosition, the drag drop client should
397 // send XdndDrop immediately after the mouse is released.
398 client->OnMouseReleased();
399
400 events = collector.PopAllEvents();
401 ASSERT_EQ(1u, events.size());
402 EXPECT_TRUE(client->MessageHasType(events[0], "XdndDrop"));
403 EXPECT_EQ(client->source_xwindow(),
404 static_cast<XID>(events[0].data.l[0]));
405
406 // Send XdndFinished to indicate that the drag drop client can cleanup any
407 // data related to this drag. The move loop should end only after the
408 // XdndFinished message was received.
409 EXPECT_TRUE(client->IsMoveLoopRunning());
410 client->OnFinished(toplevel, true, client->GetAtom("XdndActionCopy"));
411 EXPECT_FALSE(client->IsMoveLoopRunning());
412 }
413
414 void BasicStep3(TestDragDropClient* client, XID toplevel) {
415 EXPECT_TRUE(client->IsMoveLoopRunning());
416
417 ClientMessageEventCollector collector(toplevel, client);
418 client->SetTopmostXWindowAndMoveMouse(toplevel);
419
420 std::vector<XClientMessageEvent> events = collector.PopAllEvents();
421 ASSERT_EQ(2u, events.size());
422 EXPECT_TRUE(client->MessageHasType(events[0], "XdndEnter"));
423 EXPECT_TRUE(client->MessageHasType(events[1], "XdndPosition"));
424
425 client->OnStatus(toplevel, true, client->GetAtom("XdndActionCopy"));
426 client->SetTopmostXWindowAndMoveMouse(toplevel);
427 events = collector.PopAllEvents();
428 ASSERT_EQ(1u, events.size());
429 EXPECT_TRUE(client->MessageHasType(events[0], "XdndPosition"));
430
431 // We have not received an XdndStatus ack for the second XdndPosition message.
432 // Test that sending XdndDrop is delayed till the XdndStatus ack is received.
433 client->OnMouseReleased();
434 EXPECT_FALSE(collector.HasEvents());
435
436 client->OnStatus(toplevel, true, client->GetAtom("XdndActionCopy"));
437 events = collector.PopAllEvents();
438 ASSERT_EQ(1u, events.size());
439 EXPECT_TRUE(client->MessageHasType(events[0], "XdndDrop"));
440
441 EXPECT_TRUE(client->IsMoveLoopRunning());
442 client->OnFinished(toplevel, true, client->GetAtom("XdndActionCopy"));
443 EXPECT_FALSE(client->IsMoveLoopRunning());
444 }
445
446 } // namespace
447
448 TEST_F(DesktopDragDropClientAuraX11Test, Basic) {
449 XID toplevel = 1;
450
451 base::MessageLoop::current()->PostTask(FROM_HERE,
452 base::Bind(&BasicStep2,
453 client(),
454 toplevel));
455 int result = StartDragAndDrop();
456 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, result);
457
458 // Do another drag and drop to test that the data is properly cleaned up as a
459 // result of the XdndFinished message.
460 base::MessageLoop::current()->PostTask(FROM_HERE,
461 base::Bind(&BasicStep3,
462 client(),
463 toplevel));
464 result = StartDragAndDrop();
465 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, result);
466 }
467
468 namespace {
469
470 void TargetDoesNotRespondStep2(TestDragDropClient* client) {
471 EXPECT_TRUE(client->IsMoveLoopRunning());
472
473 XID toplevel = 1;
474 ClientMessageEventCollector collector(toplevel, client);
475 client->SetTopmostXWindowAndMoveMouse(toplevel);
476
477 std::vector<XClientMessageEvent> events = collector.PopAllEvents();
478 ASSERT_EQ(2u, events.size());
479 EXPECT_TRUE(client->MessageHasType(events[0], "XdndEnter"));
480 EXPECT_TRUE(client->MessageHasType(events[1], "XdndPosition"));
481
482 client->OnMouseReleased();
483 events = collector.PopAllEvents();
484 ASSERT_EQ(1u, events.size());
485 EXPECT_TRUE(client->MessageHasType(events[0], "XdndLeave"));
486 EXPECT_FALSE(client->IsMoveLoopRunning());
487 }
488
489 } // namespace
490
491 // Test that we do not wait for the target to send XdndStatus if we have not
492 // received any XdndStatus messages at all from the target. The Unity
493 // DNDCollectionWindow is an example of an XdndAware target which does not
494 // respond to XdndPosition messages at all.
495 TEST_F(DesktopDragDropClientAuraX11Test, TargetDoesNotRespond) {
496 base::MessageLoop::current()->PostTask(
497 FROM_HERE,
498 base::Bind(&TargetDoesNotRespondStep2, client()));
499 int result = StartDragAndDrop();
500 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE, result);
501 }
502
503 namespace {
504
505 void QueuePositionStep2(TestDragDropClient* client) {
506 EXPECT_TRUE(client->IsMoveLoopRunning());
507
508 XID toplevel = 1;
509 ClientMessageEventCollector collector(toplevel, client);
510 client->SetTopmostXWindowAndMoveMouse(toplevel);
511 client->SetTopmostXWindowAndMoveMouse(toplevel);
512 client->SetTopmostXWindowAndMoveMouse(toplevel);
513
514 std::vector<XClientMessageEvent> events = collector.PopAllEvents();
515 ASSERT_EQ(2u, events.size());
516 EXPECT_TRUE(client->MessageHasType(events[0], "XdndEnter"));
517 EXPECT_TRUE(client->MessageHasType(events[1], "XdndPosition"));
518
519 client->OnStatus(toplevel, true, client->GetAtom("XdndActionCopy"));
520 events = collector.PopAllEvents();
521 ASSERT_EQ(1u, events.size());
522 EXPECT_TRUE(client->MessageHasType(events[0], "XdndPosition"));
523
524 client->OnStatus(toplevel, true, client->GetAtom("XdndActionCopy"));
525 EXPECT_FALSE(collector.HasEvents());
526
527 client->OnMouseReleased();
528 events = collector.PopAllEvents();
529 ASSERT_EQ(1u, events.size());
530 EXPECT_TRUE(client->MessageHasType(events[0], "XdndDrop"));
531
532 EXPECT_TRUE(client->IsMoveLoopRunning());
533 client->OnFinished(toplevel, true, client->GetAtom("XdndActionCopy"));
534 EXPECT_FALSE(client->IsMoveLoopRunning());
535 }
536
537 } // namespace
538
539 // Test that XdndPosition messages are queued till the pending XdndPosition
540 // message is acked via an XdndStatus message.
541 TEST_F(DesktopDragDropClientAuraX11Test, QueuePosition) {
542 base::MessageLoop::current()->PostTask(
543 FROM_HERE,
544 base::Bind(&QueuePositionStep2, client()));
545 int result = StartDragAndDrop();
546 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, result);
547 }
548
549 namespace {
550
551 void TargetChangesStep2(TestDragDropClient* client) {
552 EXPECT_TRUE(client->IsMoveLoopRunning());
553
554 XID toplevel1 = 1;
555 ClientMessageEventCollector collector1(toplevel1, client);
556 client->SetTopmostXWindowAndMoveMouse(toplevel1);
557
558 std::vector<XClientMessageEvent> events1 = collector1.PopAllEvents();
559 ASSERT_EQ(2u, events1.size());
560 EXPECT_TRUE(client->MessageHasType(events1[0], "XdndEnter"));
561 EXPECT_TRUE(client->MessageHasType(events1[1], "XdndPosition"));
562
563 XID toplevel2 = 2;
564 ClientMessageEventCollector collector2(toplevel2, client);
565 client->SetTopmostXWindowAndMoveMouse(toplevel2);
566
567 // It is possible for |toplevel1| to send XdndStatus after the source has sent
568 // XdndLeave but before |toplevel1| has received the XdndLeave message. The
569 // XdndStatus message should be ignored.
570 client->OnStatus(toplevel1, true, client->GetAtom("XdndActionCopy"));
571 events1 = collector1.PopAllEvents();
572 ASSERT_EQ(1u, events1.size());
573 EXPECT_TRUE(client->MessageHasType(events1[0], "XdndLeave"));
574
575 std::vector<XClientMessageEvent> events2 = collector2.PopAllEvents();
576 ASSERT_EQ(2u, events2.size());
577 EXPECT_TRUE(client->MessageHasType(events2[0], "XdndEnter"));
578 EXPECT_TRUE(client->MessageHasType(events2[1], "XdndPosition"));
579
580 client->OnStatus(toplevel2, true, client->GetAtom("XdndActionCopy"));
581 client->OnMouseReleased();
582 events2 = collector2.PopAllEvents();
583 ASSERT_EQ(1u, events2.size());
584 EXPECT_TRUE(client->MessageHasType(events2[0], "XdndDrop"));
585
586 EXPECT_TRUE(client->IsMoveLoopRunning());
587 client->OnFinished(toplevel2, true, client->GetAtom("XdndActionCopy"));
588 EXPECT_FALSE(client->IsMoveLoopRunning());
589 }
590
591 } // namespace
592
593 // Test the behavior when the target changes during a drag.
594 TEST_F(DesktopDragDropClientAuraX11Test, TargetChanges) {
595 base::MessageLoop::current()->PostTask(
596 FROM_HERE,
597 base::Bind(&TargetChangesStep2, client()));
598 int result = StartDragAndDrop();
599 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, result);
600 }
601
602 namespace {
603
604 void RejectAfterMouseReleaseStep2(TestDragDropClient* client) {
605 EXPECT_TRUE(client->IsMoveLoopRunning());
606
607 XID toplevel = 1;
608 ClientMessageEventCollector collector(toplevel, client);
609 client->SetTopmostXWindowAndMoveMouse(toplevel);
610
611 std::vector<XClientMessageEvent> events = collector.PopAllEvents();
612 ASSERT_EQ(2u, events.size());
613 EXPECT_TRUE(client->MessageHasType(events[0], "XdndEnter"));
614 EXPECT_TRUE(client->MessageHasType(events[1], "XdndPosition"));
615
616 client->OnStatus(toplevel, true, client->GetAtom("XdndActionCopy"));
617 EXPECT_FALSE(collector.HasEvents());
618
619 // Send another mouse move such that there is a pending XdndPosition.
620 client->SetTopmostXWindowAndMoveMouse(toplevel);
621 events = collector.PopAllEvents();
622 ASSERT_EQ(1u, events.size());
623 EXPECT_TRUE(client->MessageHasType(events[0], "XdndPosition"));
624
625 client->OnMouseReleased();
626 // Reject the drop.
627 client->OnStatus(toplevel, false, None);
628
629 events = collector.PopAllEvents();
630 ASSERT_EQ(1u, events.size());
631 EXPECT_TRUE(client->MessageHasType(events[0], "XdndLeave"));
632 EXPECT_FALSE(client->IsMoveLoopRunning());
633 }
634
635 void RejectAfterMouseReleaseStep3(TestDragDropClient* client) {
636 EXPECT_TRUE(client->IsMoveLoopRunning());
637
638 XID toplevel = 2;
639 ClientMessageEventCollector collector(toplevel, client);
640 client->SetTopmostXWindowAndMoveMouse(toplevel);
641
642 std::vector<XClientMessageEvent> events = collector.PopAllEvents();
643 ASSERT_EQ(2u, events.size());
644 EXPECT_TRUE(client->MessageHasType(events[0], "XdndEnter"));
645 EXPECT_TRUE(client->MessageHasType(events[1], "XdndPosition"));
646
647 client->OnStatus(toplevel, true, client->GetAtom("XdndActionCopy"));
648 EXPECT_FALSE(collector.HasEvents());
649
650 client->OnMouseReleased();
651 events = collector.PopAllEvents();
652 ASSERT_EQ(1u, events.size());
653 EXPECT_TRUE(client->MessageHasType(events[0], "XdndDrop"));
654
655 EXPECT_TRUE(client->IsMoveLoopRunning());
656 client->OnFinished(toplevel, false, None);
657 EXPECT_FALSE(client->IsMoveLoopRunning());
658 }
659
660 } // namespace
661
662 // Test that the source sends XdndLeave instead of XdndDrop if the drag
663 // operation is rejected after the mouse is released.
664 TEST_F(DesktopDragDropClientAuraX11Test, RejectAfterMouseRelease) {
665 base::MessageLoop::current()->PostTask(
666 FROM_HERE,
667 base::Bind(&RejectAfterMouseReleaseStep2, client()));
668 int result = StartDragAndDrop();
669 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE, result);
670
671 // Repeat the test but reject the drop in the XdndFinished message instead.
672 base::MessageLoop::current()->PostTask(
673 FROM_HERE,
674 base::Bind(&RejectAfterMouseReleaseStep3, client()));
675 result = StartDragAndDrop();
676 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE, result);
677 }
678
679 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698