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

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

Issue 431973006: Fix flakiness of DesktopDragDropClientAuraX11Tests (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 4 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h" 5 #include "ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h"
6 6
7 #include <X11/Xatom.h> 7 #include <X11/Xatom.h>
8 8
9 #include "base/event_types.h" 9 #include "base/event_types.h"
10 #include "base/lazy_instance.h" 10 #include "base/lazy_instance.h"
11 #include "base/message_loop/message_loop.h" 11 #include "base/message_loop/message_loop.h"
12 #include "ui/aura/window.h" 12 #include "ui/aura/window.h"
13 #include "ui/aura/window_tree_host.h" 13 #include "ui/aura/window_tree_host.h"
14 #include "ui/base/clipboard/clipboard.h" 14 #include "ui/base/clipboard/clipboard.h"
15 #include "ui/base/dragdrop/drop_target_event.h" 15 #include "ui/base/dragdrop/drop_target_event.h"
16 #include "ui/base/dragdrop/os_exchange_data.h" 16 #include "ui/base/dragdrop/os_exchange_data.h"
17 #include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h" 17 #include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h"
18 #include "ui/base/x/selection_utils.h" 18 #include "ui/base/x/selection_utils.h"
19 #include "ui/base/x/x11_foreign_window_manager.h" 19 #include "ui/base/x/x11_foreign_window_manager.h"
20 #include "ui/base/x/x11_util.h" 20 #include "ui/base/x/x11_util.h"
21 #include "ui/events/event.h" 21 #include "ui/events/event.h"
22 #include "ui/events/platform/platform_event_source.h" 22 #include "ui/events/platform/platform_event_source.h"
23 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h" 23 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
24 #include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h" 24 #include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h"
25 #include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h"
25 #include "ui/wm/public/drag_drop_client.h" 26 #include "ui/wm/public/drag_drop_client.h"
26 #include "ui/wm/public/drag_drop_delegate.h" 27 #include "ui/wm/public/drag_drop_delegate.h"
27 28
28 using aura::client::DragDropDelegate; 29 using aura::client::DragDropDelegate;
29 using ui::OSExchangeData; 30 using ui::OSExchangeData;
30 31
31 namespace { 32 namespace {
32 33
33 const int kMinXdndVersion = 5; 34 const int kMinXdndVersion = 5;
34 35
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 return ui::POST_DISPATCH_NONE; 355 return ui::POST_DISPATCH_NONE;
355 } 356 }
356 357
357 /////////////////////////////////////////////////////////////////////////////// 358 ///////////////////////////////////////////////////////////////////////////////
358 359
359 DesktopDragDropClientAuraX11::DesktopDragDropClientAuraX11( 360 DesktopDragDropClientAuraX11::DesktopDragDropClientAuraX11(
360 aura::Window* root_window, 361 aura::Window* root_window,
361 views::DesktopNativeCursorManager* cursor_manager, 362 views::DesktopNativeCursorManager* cursor_manager,
362 Display* xdisplay, 363 Display* xdisplay,
363 ::Window xwindow) 364 ::Window xwindow)
364 : move_loop_(this), 365 : root_window_(root_window),
365 root_window_(root_window),
366 xdisplay_(xdisplay), 366 xdisplay_(xdisplay),
367 xwindow_(xwindow), 367 xwindow_(xwindow),
368 atom_cache_(xdisplay_, kAtomsToCache), 368 atom_cache_(xdisplay_, kAtomsToCache),
369 target_window_(NULL), 369 target_window_(NULL),
370 waiting_on_status_(false), 370 waiting_on_status_(false),
371 status_received_since_enter_(false), 371 status_received_since_enter_(false),
372 source_provider_(NULL), 372 source_provider_(NULL),
373 source_current_window_(None), 373 source_current_window_(None),
374 source_state_(SOURCE_STATE_OTHER), 374 source_state_(SOURCE_STATE_OTHER),
375 drag_operation_(0), 375 drag_operation_(0),
(...skipping 24 matching lines...) Expand all
400 // static 400 // static
401 DesktopDragDropClientAuraX11* DesktopDragDropClientAuraX11::GetForWindow( 401 DesktopDragDropClientAuraX11* DesktopDragDropClientAuraX11::GetForWindow(
402 ::Window window) { 402 ::Window window) {
403 std::map< ::Window, DesktopDragDropClientAuraX11*>::const_iterator it = 403 std::map< ::Window, DesktopDragDropClientAuraX11*>::const_iterator it =
404 g_live_client_map.Get().find(window); 404 g_live_client_map.Get().find(window);
405 if (it == g_live_client_map.Get().end()) 405 if (it == g_live_client_map.Get().end())
406 return NULL; 406 return NULL;
407 return it->second; 407 return it->second;
408 } 408 }
409 409
410 void DesktopDragDropClientAuraX11::Init() {
411 move_loop_ = CreateMoveLoop(this);
412 }
413
410 void DesktopDragDropClientAuraX11::OnXdndEnter( 414 void DesktopDragDropClientAuraX11::OnXdndEnter(
411 const XClientMessageEvent& event) { 415 const XClientMessageEvent& event) {
412 DVLOG(1) << "XdndEnter"; 416 DVLOG(1) << "XdndEnter";
413 417
414 int version = (event.data.l[1] & 0xff000000) >> 24; 418 int version = (event.data.l[1] & 0xff000000) >> 24;
415 if (version < 3) { 419 if (version < 3) {
416 LOG(ERROR) << "Received old XdndEnter message."; 420 LOG(ERROR) << "Received old XdndEnter message.";
417 return; 421 return;
418 } 422 }
419 423
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 if (event.data.l[1] & 1) { 480 if (event.data.l[1] & 1) {
477 ::Atom atom_operation = event.data.l[4]; 481 ::Atom atom_operation = event.data.l[4];
478 negotiated_operation_ = AtomToDragOperation(atom_operation); 482 negotiated_operation_ = AtomToDragOperation(atom_operation);
479 } else { 483 } else {
480 negotiated_operation_ = ui::DragDropTypes::DRAG_NONE; 484 negotiated_operation_ = ui::DragDropTypes::DRAG_NONE;
481 } 485 }
482 486
483 if (source_state_ == SOURCE_STATE_PENDING_DROP) { 487 if (source_state_ == SOURCE_STATE_PENDING_DROP) {
484 // We were waiting on the status message so we could send the XdndDrop. 488 // We were waiting on the status message so we could send the XdndDrop.
485 if (negotiated_operation_ == ui::DragDropTypes::DRAG_NONE) { 489 if (negotiated_operation_ == ui::DragDropTypes::DRAG_NONE) {
486 move_loop_.EndMoveLoop(); 490 move_loop_->EndMoveLoop();
487 return; 491 return;
488 } 492 }
489 source_state_ = SOURCE_STATE_DROPPED; 493 source_state_ = SOURCE_STATE_DROPPED;
490 SendXdndDrop(source_window); 494 SendXdndDrop(source_window);
491 return; 495 return;
492 } 496 }
493 497
494 switch (negotiated_operation_) { 498 switch (negotiated_operation_) {
495 case ui::DragDropTypes::DRAG_COPY: 499 case ui::DragDropTypes::DRAG_COPY:
496 move_loop_.UpdateCursor(copy_grab_cursor_); 500 move_loop_->UpdateCursor(copy_grab_cursor_);
497 break; 501 break;
498 case ui::DragDropTypes::DRAG_MOVE: 502 case ui::DragDropTypes::DRAG_MOVE:
499 move_loop_.UpdateCursor(move_grab_cursor_); 503 move_loop_->UpdateCursor(move_grab_cursor_);
500 break; 504 break;
501 default: 505 default:
502 move_loop_.UpdateCursor(grab_cursor_); 506 move_loop_->UpdateCursor(grab_cursor_);
503 break; 507 break;
504 } 508 }
505 509
506 // Note: event.data.[2,3] specify a rectangle. It is a request by the other 510 // Note: event.data.[2,3] specify a rectangle. It is a request by the other
507 // window to not send further XdndPosition messages while the cursor is 511 // window to not send further XdndPosition messages while the cursor is
508 // within it. However, it is considered advisory and (at least according to 512 // within it. However, it is considered advisory and (at least according to
509 // the spec) the other side must handle further position messages within 513 // the spec) the other side must handle further position messages within
510 // it. GTK+ doesn't bother with this, so neither should we. 514 // it. GTK+ doesn't bother with this, so neither should we.
511 515
512 if (next_position_message_.get()) { 516 if (next_position_message_.get()) {
(...skipping 14 matching lines...) Expand all
527 if (source_current_window_ != source_window) 531 if (source_current_window_ != source_window)
528 return; 532 return;
529 533
530 // Clear |negotiated_operation_| if the drag was rejected. 534 // Clear |negotiated_operation_| if the drag was rejected.
531 if ((event.data.l[1] & 1) == 0) 535 if ((event.data.l[1] & 1) == 0)
532 negotiated_operation_ = ui::DragDropTypes::DRAG_NONE; 536 negotiated_operation_ = ui::DragDropTypes::DRAG_NONE;
533 537
534 // Clear |source_current_window_| to avoid sending XdndLeave upon ending the 538 // Clear |source_current_window_| to avoid sending XdndLeave upon ending the
535 // move loop. 539 // move loop.
536 source_current_window_ = None; 540 source_current_window_ = None;
537 move_loop_.EndMoveLoop(); 541 move_loop_->EndMoveLoop();
538 } 542 }
539 543
540 void DesktopDragDropClientAuraX11::OnXdndDrop( 544 void DesktopDragDropClientAuraX11::OnXdndDrop(
541 const XClientMessageEvent& event) { 545 const XClientMessageEvent& event) {
542 DVLOG(1) << "XdndDrop"; 546 DVLOG(1) << "XdndDrop";
543 547
544 unsigned long source_window = event.data.l[0]; 548 unsigned long source_window = event.data.l[0];
545 549
546 int drag_operation = ui::DragDropTypes::DRAG_NONE; 550 int drag_operation = ui::DragDropTypes::DRAG_NONE;
547 if (target_window_) { 551 if (target_window_) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
620 624
621 // It is possible for the DesktopWindowTreeHostX11 to be destroyed during the 625 // It is possible for the DesktopWindowTreeHostX11 to be destroyed during the
622 // move loop, which would also destroy this drag-client. So keep track of 626 // move loop, which would also destroy this drag-client. So keep track of
623 // whether it is alive after the drag ends. 627 // whether it is alive after the drag ends.
624 base::WeakPtr<DesktopDragDropClientAuraX11> alive( 628 base::WeakPtr<DesktopDragDropClientAuraX11> alive(
625 weak_ptr_factory_.GetWeakPtr()); 629 weak_ptr_factory_.GetWeakPtr());
626 630
627 // Windows has a specific method, DoDragDrop(), which performs the entire 631 // Windows has a specific method, DoDragDrop(), which performs the entire
628 // drag. We have to emulate this, so we spin off a nested runloop which will 632 // drag. We have to emulate this, so we spin off a nested runloop which will
629 // track all cursor movement and reroute events to a specific handler. 633 // track all cursor movement and reroute events to a specific handler.
630 move_loop_.SetDragImage(source_provider_->GetDragImage(), 634 move_loop_->SetDragImage(source_provider_->GetDragImage(),
631 source_provider_->GetDragImageOffset()); 635 source_provider_->GetDragImageOffset());
632 move_loop_.RunMoveLoop(source_window, grab_cursor_); 636 move_loop_->RunMoveLoop(source_window, grab_cursor_);
633 637
634 if (alive) { 638 if (alive) {
635 move_loop_.SetDragImage(gfx::ImageSkia(), gfx::Vector2dF()); 639 move_loop_->SetDragImage(gfx::ImageSkia(), gfx::Vector2dF());
636 640
637 source_provider_ = NULL; 641 source_provider_ = NULL;
638 g_current_drag_drop_client = NULL; 642 g_current_drag_drop_client = NULL;
639 drag_operation_ = 0; 643 drag_operation_ = 0;
640 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndActionList")); 644 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndActionList"));
641 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom(kXdndDirectSave0)); 645 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom(kXdndDirectSave0));
642 646
643 return negotiated_operation_; 647 return negotiated_operation_;
644 } 648 }
645 return ui::DragDropTypes::DRAG_NONE; 649 return ui::DragDropTypes::DRAG_NONE;
646 } 650 }
647 651
648 void DesktopDragDropClientAuraX11::DragUpdate(aura::Window* target, 652 void DesktopDragDropClientAuraX11::DragUpdate(aura::Window* target,
649 const ui::LocatedEvent& event) { 653 const ui::LocatedEvent& event) {
650 NOTIMPLEMENTED(); 654 NOTIMPLEMENTED();
651 } 655 }
652 656
653 void DesktopDragDropClientAuraX11::Drop(aura::Window* target, 657 void DesktopDragDropClientAuraX11::Drop(aura::Window* target,
654 const ui::LocatedEvent& event) { 658 const ui::LocatedEvent& event) {
655 NOTIMPLEMENTED(); 659 NOTIMPLEMENTED();
656 } 660 }
657 661
658 void DesktopDragDropClientAuraX11::DragCancel() { 662 void DesktopDragDropClientAuraX11::DragCancel() {
659 move_loop_.EndMoveLoop(); 663 move_loop_->EndMoveLoop();
660 } 664 }
661 665
662 bool DesktopDragDropClientAuraX11::IsDragDropInProgress() { 666 bool DesktopDragDropClientAuraX11::IsDragDropInProgress() {
663 return !!g_current_drag_drop_client; 667 return !!g_current_drag_drop_client;
664 } 668 }
665 669
666 void DesktopDragDropClientAuraX11::OnWindowDestroyed(aura::Window* window) { 670 void DesktopDragDropClientAuraX11::OnWindowDestroyed(aura::Window* window) {
667 DCHECK_EQ(target_window_, window); 671 DCHECK_EQ(target_window_, window);
668 target_window_ = NULL; 672 target_window_ = NULL;
669 } 673 }
670 674
671 void DesktopDragDropClientAuraX11::OnMouseMovement(XMotionEvent* event) { 675 void DesktopDragDropClientAuraX11::OnMouseMovement(XMotionEvent* event) {
672 repeat_mouse_move_timer_.Stop(); 676 repeat_mouse_move_timer_.Stop();
673 ProcessMouseMove(gfx::Point(event->x_root, event->y_root), event->time); 677 ProcessMouseMove(gfx::Point(event->x_root, event->y_root), event->time);
674 } 678 }
675 679
676 void DesktopDragDropClientAuraX11::OnMouseReleased() { 680 void DesktopDragDropClientAuraX11::OnMouseReleased() {
677 repeat_mouse_move_timer_.Stop(); 681 repeat_mouse_move_timer_.Stop();
678 682
679 if (source_state_ != SOURCE_STATE_OTHER) { 683 if (source_state_ != SOURCE_STATE_OTHER) {
680 // The user has previously released the mouse and is clicking in 684 // The user has previously released the mouse and is clicking in
681 // frustration. 685 // frustration.
682 move_loop_.EndMoveLoop(); 686 move_loop_->EndMoveLoop();
683 return; 687 return;
684 } 688 }
685 689
686 if (source_current_window_ != None) { 690 if (source_current_window_ != None) {
687 if (waiting_on_status_) { 691 if (waiting_on_status_) {
688 if (status_received_since_enter_) { 692 if (status_received_since_enter_) {
689 // If we are waiting for an XdndStatus message, we need to wait for it 693 // If we are waiting for an XdndStatus message, we need to wait for it
690 // to complete. 694 // to complete.
691 source_state_ = SOURCE_STATE_PENDING_DROP; 695 source_state_ = SOURCE_STATE_PENDING_DROP;
692 696
693 // Start timer to end the move loop if the target takes too long to send 697 // Start timer to end the move loop if the target takes too long to send
694 // the XdndStatus and XdndFinished messages. 698 // the XdndStatus and XdndFinished messages.
695 StartEndMoveLoopTimer(); 699 StartEndMoveLoopTimer();
696 return; 700 return;
697 } 701 }
698 702
699 move_loop_.EndMoveLoop(); 703 move_loop_->EndMoveLoop();
700 return; 704 return;
701 } 705 }
702 706
703 if (negotiated_operation_ != ui::DragDropTypes::DRAG_NONE) { 707 if (negotiated_operation_ != ui::DragDropTypes::DRAG_NONE) {
704 // Start timer to end the move loop if the target takes too long to send 708 // Start timer to end the move loop if the target takes too long to send
705 // an XdndFinished message. It is important that StartEndMoveLoopTimer() 709 // an XdndFinished message. It is important that StartEndMoveLoopTimer()
706 // is called before SendXdndDrop() because SendXdndDrop() 710 // is called before SendXdndDrop() because SendXdndDrop()
707 // sends XdndFinished synchronously if the drop target is a Chrome 711 // sends XdndFinished synchronously if the drop target is a Chrome
708 // window. 712 // window.
709 StartEndMoveLoopTimer(); 713 StartEndMoveLoopTimer();
710 714
711 // We have negotiated an action with the other end. 715 // We have negotiated an action with the other end.
712 source_state_ = SOURCE_STATE_DROPPED; 716 source_state_ = SOURCE_STATE_DROPPED;
713 SendXdndDrop(source_current_window_); 717 SendXdndDrop(source_current_window_);
714 return; 718 return;
715 } 719 }
716 } 720 }
717 721
718 move_loop_.EndMoveLoop(); 722 move_loop_->EndMoveLoop();
719 } 723 }
720 724
721 void DesktopDragDropClientAuraX11::OnMoveLoopEnded() { 725 void DesktopDragDropClientAuraX11::OnMoveLoopEnded() {
722 if (source_current_window_ != None) { 726 if (source_current_window_ != None) {
723 SendXdndLeave(source_current_window_); 727 SendXdndLeave(source_current_window_);
724 source_current_window_ = None; 728 source_current_window_ = None;
725 } 729 }
726 target_current_context_.reset(); 730 target_current_context_.reset();
727 repeat_mouse_move_timer_.Stop(); 731 repeat_mouse_move_timer_.Stop();
728 end_move_loop_timer_.Stop(); 732 end_move_loop_timer_.Stop();
729 } 733 }
730 734
735 scoped_ptr<X11MoveLoop> DesktopDragDropClientAuraX11::CreateMoveLoop(
736 X11MoveLoopDelegate* delegate) {
737 return scoped_ptr<X11MoveLoop>(new X11WholeScreenMoveLoop(this));
738 }
739
731 XID DesktopDragDropClientAuraX11::FindWindowFor( 740 XID DesktopDragDropClientAuraX11::FindWindowFor(
732 const gfx::Point& screen_point) { 741 const gfx::Point& screen_point) {
733 views::X11TopmostWindowFinder finder; 742 views::X11TopmostWindowFinder finder;
734 ::Window target = finder.FindWindowAt(screen_point); 743 ::Window target = finder.FindWindowAt(screen_point);
735 744
736 if (target == None) 745 if (target == None)
737 return None; 746 return None;
738 747
739 // Figure out which window we should test as XdndAware. If |target| has 748 // Figure out which window we should test as XdndAware. If |target| has
740 // XdndProxy, it will set that proxy on target, and if not, |target|'s 749 // XdndProxy, it will set that proxy on target, and if not, |target|'s
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
825 834
826 void DesktopDragDropClientAuraX11::StartEndMoveLoopTimer() { 835 void DesktopDragDropClientAuraX11::StartEndMoveLoopTimer() {
827 end_move_loop_timer_.Start(FROM_HERE, 836 end_move_loop_timer_.Start(FROM_HERE,
828 base::TimeDelta::FromMilliseconds( 837 base::TimeDelta::FromMilliseconds(
829 kEndMoveLoopTimeoutMs), 838 kEndMoveLoopTimeoutMs),
830 this, 839 this,
831 &DesktopDragDropClientAuraX11::EndMoveLoop); 840 &DesktopDragDropClientAuraX11::EndMoveLoop);
832 } 841 }
833 842
834 void DesktopDragDropClientAuraX11::EndMoveLoop() { 843 void DesktopDragDropClientAuraX11::EndMoveLoop() {
835 move_loop_.EndMoveLoop(); 844 move_loop_->EndMoveLoop();
836 } 845 }
837 846
838 void DesktopDragDropClientAuraX11::DragTranslate( 847 void DesktopDragDropClientAuraX11::DragTranslate(
839 const gfx::Point& root_window_location, 848 const gfx::Point& root_window_location,
840 scoped_ptr<ui::OSExchangeData>* data, 849 scoped_ptr<ui::OSExchangeData>* data,
841 scoped_ptr<ui::DropTargetEvent>* event, 850 scoped_ptr<ui::DropTargetEvent>* event,
842 aura::client::DragDropDelegate** delegate) { 851 aura::client::DragDropDelegate** delegate) {
843 gfx::Point root_location = root_window_location; 852 gfx::Point root_location = root_window_location;
844 root_window_->GetHost()->ConvertPointFromNativeScreen(&root_location); 853 root_window_->GetHost()->ConvertPointFromNativeScreen(&root_location);
845 aura::Window* target_window = 854 aura::Window* target_window =
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
1039 xev.xclient.window = dest_window; 1048 xev.xclient.window = dest_window;
1040 xev.xclient.data.l[0] = xwindow_; 1049 xev.xclient.data.l[0] = xwindow_;
1041 xev.xclient.data.l[1] = 0; 1050 xev.xclient.data.l[1] = 0;
1042 xev.xclient.data.l[2] = CurrentTime; 1051 xev.xclient.data.l[2] = CurrentTime;
1043 xev.xclient.data.l[3] = None; 1052 xev.xclient.data.l[3] = None;
1044 xev.xclient.data.l[4] = None; 1053 xev.xclient.data.l[4] = None;
1045 SendXClientEvent(dest_window, &xev); 1054 SendXClientEvent(dest_window, &xev);
1046 } 1055 }
1047 1056
1048 } // namespace views 1057 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698