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

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

Issue 262893002: Removes grab input window and extra grab and ungrab in X11WholeScreenMoveLoop Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Removes grab input window and extra grab and ungrab in X11WholeScreenMoveLoop (nits and comments) 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
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_util.h" 19 #include "ui/base/x/x11_util.h"
20 #include "ui/events/event.h" 20 #include "ui/events/event.h"
21 #include "ui/events/platform/platform_event_source.h" 21 #include "ui/events/platform/platform_event_source.h"
22 #include "ui/gfx/screen.h"
23 #include "ui/views/controls/image_view.h"
22 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h" 24 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
23 #include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h" 25 #include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h"
26 #include "ui/views/widget/widget.h"
24 #include "ui/wm/public/drag_drop_client.h" 27 #include "ui/wm/public/drag_drop_client.h"
25 #include "ui/wm/public/drag_drop_delegate.h" 28 #include "ui/wm/public/drag_drop_delegate.h"
26 29
27 using aura::client::DragDropDelegate; 30 using aura::client::DragDropDelegate;
28 using ui::OSExchangeData; 31 using ui::OSExchangeData;
29 32
30 namespace { 33 namespace {
31 34
35 // The minimum alpha before we declare a pixel transparent when searching in
36 // our source image.
37 const uint32 kMinAlpha = 32;
38 const unsigned char kDragWidgetOpacity = 0xc0;
39
32 const int kMinXdndVersion = 5; 40 const int kMinXdndVersion = 5;
33 41
34 const int kWillAcceptDrop = 1; 42 const int kWillAcceptDrop = 1;
35 const int kWantFurtherPosEvents = 2; 43 const int kWantFurtherPosEvents = 2;
36 44
37 const char kXdndActionCopy[] = "XdndActionCopy"; 45 const char kXdndActionCopy[] = "XdndActionCopy";
38 const char kXdndActionMove[] = "XdndActionMove"; 46 const char kXdndActionMove[] = "XdndActionMove";
39 const char kXdndActionLink[] = "XdndActionLink"; 47 const char kXdndActionLink[] = "XdndActionLink";
40 const char kXdndActionDirectSave[] = "XdndActionDirectSave"; 48 const char kXdndActionDirectSave[] = "XdndActionDirectSave";
41 49
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 waiting_on_status_(false), 391 waiting_on_status_(false),
384 status_received_since_enter_(false), 392 status_received_since_enter_(false),
385 source_provider_(NULL), 393 source_provider_(NULL),
386 source_current_window_(None), 394 source_current_window_(None),
387 source_state_(SOURCE_STATE_OTHER), 395 source_state_(SOURCE_STATE_OTHER),
388 drag_operation_(0), 396 drag_operation_(0),
389 negotiated_operation_(ui::DragDropTypes::DRAG_NONE), 397 negotiated_operation_(ui::DragDropTypes::DRAG_NONE),
390 grab_cursor_(cursor_manager->GetInitializedCursor(ui::kCursorGrabbing)), 398 grab_cursor_(cursor_manager->GetInitializedCursor(ui::kCursorGrabbing)),
391 copy_grab_cursor_(cursor_manager->GetInitializedCursor(ui::kCursorCopy)), 399 copy_grab_cursor_(cursor_manager->GetInitializedCursor(ui::kCursorCopy)),
392 move_grab_cursor_(cursor_manager->GetInitializedCursor(ui::kCursorMove)), 400 move_grab_cursor_(cursor_manager->GetInitializedCursor(ui::kCursorMove)),
401 null_drag_widget_bounds_(-100, -100, 1, 1),
393 weak_ptr_factory_(this) { 402 weak_ptr_factory_(this) {
394 DCHECK(g_live_client_map.Get().find(xwindow) == 403 DCHECK(g_live_client_map.Get().find(xwindow) ==
395 g_live_client_map.Get().end()); 404 g_live_client_map.Get().end());
396 g_live_client_map.Get().insert(std::make_pair(xwindow, this)); 405 g_live_client_map.Get().insert(std::make_pair(xwindow, this));
397 406
398 // Mark that we are aware of drag and drop concepts. 407 // Mark that we are aware of drag and drop concepts.
399 unsigned long xdnd_version = kMinXdndVersion; 408 unsigned long xdnd_version = kMinXdndVersion;
400 XChangeProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndAware"), 409 XChangeProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndAware"),
401 XA_ATOM, 32, PropModeReplace, 410 XA_ATOM, 32, PropModeReplace,
402 reinterpret_cast<unsigned char*>(&xdnd_version), 1); 411 reinterpret_cast<unsigned char*>(&xdnd_version), 1);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 // We were waiting on the status message so we could send the XdndDrop. 506 // We were waiting on the status message so we could send the XdndDrop.
498 if (negotiated_operation_ == ui::DragDropTypes::DRAG_NONE) { 507 if (negotiated_operation_ == ui::DragDropTypes::DRAG_NONE) {
499 move_loop_.EndMoveLoop(); 508 move_loop_.EndMoveLoop();
500 return; 509 return;
501 } 510 }
502 source_state_ = SOURCE_STATE_DROPPED; 511 source_state_ = SOURCE_STATE_DROPPED;
503 SendXdndDrop(source_window); 512 SendXdndDrop(source_window);
504 return; 513 return;
505 } 514 }
506 515
507 switch (negotiated_operation_) { 516 UpdateCursor();
508 case ui::DragDropTypes::DRAG_COPY:
509 move_loop_.UpdateCursor(copy_grab_cursor_);
510 break;
511 case ui::DragDropTypes::DRAG_MOVE:
512 move_loop_.UpdateCursor(move_grab_cursor_);
513 break;
514 default:
515 move_loop_.UpdateCursor(grab_cursor_);
516 break;
517 }
518 517
519 // Note: event.data.[2,3] specify a rectangle. It is a request by the other 518 // Note: event.data.[2,3] specify a rectangle. It is a request by the other
520 // window to not send further XdndPosition messages while the cursor is 519 // window to not send further XdndPosition messages while the cursor is
521 // within it. However, it is considered advisory and (at least according to 520 // within it. However, it is considered advisory and (at least according to
522 // the spec) the other side must handle further position messages within 521 // the spec) the other side must handle further position messages within
523 // it. GTK+ doesn't bother with this, so neither should we. 522 // it. GTK+ doesn't bother with this, so neither should we.
524 523
525 if (next_position_message_.get()) { 524 if (next_position_message_.get()) {
526 // We were waiting on the status message so we could send off the next 525 // We were waiting on the status message so we could send off the next
527 // position message we queued up. 526 // position message we queued up.
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 source_provider_->file_contents_name().AsUTF8Unsafe()); 622 source_provider_->file_contents_name().AsUTF8Unsafe());
624 } 623 }
625 ui::SetAtomArrayProperty(xwindow_, "XdndActionList", "ATOM", actions); 624 ui::SetAtomArrayProperty(xwindow_, "XdndActionList", "ATOM", actions);
626 625
627 // It is possible for the DesktopWindowTreeHostX11 to be destroyed during the 626 // It is possible for the DesktopWindowTreeHostX11 to be destroyed during the
628 // move loop, which would also destroy this drag-client. So keep track of 627 // move loop, which would also destroy this drag-client. So keep track of
629 // whether it is alive after the drag ends. 628 // whether it is alive after the drag ends.
630 base::WeakPtr<DesktopDragDropClientAuraX11> alive( 629 base::WeakPtr<DesktopDragDropClientAuraX11> alive(
631 weak_ptr_factory_.GetWeakPtr()); 630 weak_ptr_factory_.GetWeakPtr());
632 631
632 SetDragImage(source_provider_->GetDragImage(),
633 source_provider_->GetDragImageOffset());
634 CreateDragImageWindow();
635 // Capture drag widget to continue receiving events even if the drag source
636 // gets destroyed during the drag such as when we drag an item out of a menu
637 // and the menu closes.
638 drag_widget_->GetNativeWindow()->SetCapture();
639
633 // Windows has a specific method, DoDragDrop(), which performs the entire 640 // Windows has a specific method, DoDragDrop(), which performs the entire
634 // drag. We have to emulate this, so we spin off a nested runloop which will 641 // drag. We have to emulate this, so we spin off a nested runloop which will
635 // track all cursor movement and reroute events to a specific handler. 642 // track all cursor movement and reroute events to a specific handler.
636 move_loop_.SetDragImage(source_provider_->GetDragImage(), 643 move_loop_.RunMoveLoop();
637 source_provider_->GetDragImageOffset());
638 move_loop_.RunMoveLoop(source_window, grab_cursor_);
639 644
640 if (alive) { 645 if (alive) {
641 move_loop_.SetDragImage(gfx::ImageSkia(), gfx::Vector2dF()); 646 SetDragImage(gfx::ImageSkia(), gfx::Vector2dF());
642 647
643 source_provider_ = NULL; 648 source_provider_ = NULL;
644 g_current_drag_drop_client = NULL; 649 g_current_drag_drop_client = NULL;
645 drag_operation_ = 0; 650 drag_operation_ = 0;
646 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndActionList")); 651 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndActionList"));
647 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom(kXdndDirectSave0)); 652 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom(kXdndDirectSave0));
648 653
649 return negotiated_operation_; 654 return negotiated_operation_;
650 } 655 }
651 return ui::DragDropTypes::DRAG_NONE; 656 return ui::DragDropTypes::DRAG_NONE;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
715 // an XdndFinished message. 720 // an XdndFinished message.
716 StartEndMoveLoopTimer(); 721 StartEndMoveLoopTimer();
717 return; 722 return;
718 } 723 }
719 } 724 }
720 725
721 move_loop_.EndMoveLoop(); 726 move_loop_.EndMoveLoop();
722 } 727 }
723 728
724 void DesktopDragDropClientAuraX11::OnMoveLoopEnded() { 729 void DesktopDragDropClientAuraX11::OnMoveLoopEnded() {
730 drag_widget_.reset();
725 if (source_current_window_ != None) { 731 if (source_current_window_ != None) {
726 SendXdndLeave(source_current_window_); 732 SendXdndLeave(source_current_window_);
727 source_current_window_ = None; 733 source_current_window_ = None;
728 } 734 }
729 target_current_context_.reset(); 735 target_current_context_.reset();
730 repeat_mouse_move_timer_.Stop(); 736 repeat_mouse_move_timer_.Stop();
731 end_move_loop_timer_.Stop(); 737 end_move_loop_timer_.Stop();
732 } 738 }
733 739
734 void DesktopDragDropClientAuraX11::ProcessMouseMove( 740 void DesktopDragDropClientAuraX11::ProcessMouseMove(
735 const gfx::Point& screen_point, 741 const gfx::Point& screen_point,
736 unsigned long event_time) { 742 unsigned long event_time) {
737 if (source_state_ != SOURCE_STATE_OTHER) 743 if (source_state_ != SOURCE_STATE_OTHER)
738 return; 744 return;
739 745
746 if (drag_widget_.get()) {
747 if (drag_image_.isNull()) {
748 drag_widget_->SetBounds(null_drag_widget_bounds_);
749 } else {
750 drag_widget_->SetBounds(gfx::Rect(
751 gfx::ToFlooredPoint(screen_point - drag_offset_),
752 drag_image_.size()));
753 }
754 drag_widget_->StackAtTop();
755 }
756
740 // Find the current window the cursor is over. 757 // Find the current window the cursor is over.
741 ::Window mouse_window = None; 758 ::Window mouse_window = None;
742 ::Window dest_window = None; 759 ::Window dest_window = None;
743 FindWindowFor(screen_point, &mouse_window, &dest_window); 760 FindWindowFor(screen_point, &mouse_window, &dest_window);
744 761
745 if (source_current_window_ != dest_window) { 762 if (source_current_window_ != dest_window) {
746 if (source_current_window_ != None) 763 if (source_current_window_ != None)
747 SendXdndLeave(source_current_window_); 764 SendXdndLeave(source_current_window_);
748 765
749 source_current_window_ = dest_window; 766 source_current_window_ = dest_window;
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
864 if (drag_operation_ & ui::DragDropTypes::DRAG_LINK) 881 if (drag_operation_ & ui::DragDropTypes::DRAG_LINK)
865 operations.push_back(atom_cache_.GetAtom(kXdndActionLink)); 882 operations.push_back(atom_cache_.GetAtom(kXdndActionLink));
866 return operations; 883 return operations;
867 } 884 }
868 885
869 ui::SelectionFormatMap DesktopDragDropClientAuraX11::GetFormatMap() const { 886 ui::SelectionFormatMap DesktopDragDropClientAuraX11::GetFormatMap() const {
870 return source_provider_ ? source_provider_->GetFormatMap() : 887 return source_provider_ ? source_provider_->GetFormatMap() :
871 ui::SelectionFormatMap(); 888 ui::SelectionFormatMap();
872 } 889 }
873 890
891 void DesktopDragDropClientAuraX11::UpdateCursor() {
892 gfx::NativeCursor cursor = grab_cursor_;
893 switch (negotiated_operation_) {
894 case ui::DragDropTypes::DRAG_COPY:
895 cursor = copy_grab_cursor_;
896 break;
897 case ui::DragDropTypes::DRAG_MOVE:
898 cursor = move_grab_cursor_;
899 break;
900 default:
901 break;
902 }
903
904 // Update the pointer with the new cursor if a grab is active.
905 XChangeActivePointerGrab(
906 xdisplay_,
907 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
908 cursor.platform(),
909 CurrentTime);
910 }
911
874 void DesktopDragDropClientAuraX11::CompleteXdndPosition( 912 void DesktopDragDropClientAuraX11::CompleteXdndPosition(
875 ::Window source_window, 913 ::Window source_window,
876 const gfx::Point& screen_point) { 914 const gfx::Point& screen_point) {
877 int drag_operation = ui::DragDropTypes::DRAG_NONE; 915 int drag_operation = ui::DragDropTypes::DRAG_NONE;
878 scoped_ptr<ui::OSExchangeData> data; 916 scoped_ptr<ui::OSExchangeData> data;
879 scoped_ptr<ui::DropTargetEvent> drop_target_event; 917 scoped_ptr<ui::DropTargetEvent> drop_target_event;
880 DragDropDelegate* delegate = NULL; 918 DragDropDelegate* delegate = NULL;
881 DragTranslate(screen_point, &data, &drop_target_event, &delegate); 919 DragTranslate(screen_point, &data, &drop_target_event, &delegate);
882 if (delegate) 920 if (delegate)
883 drag_operation = delegate->OnDragUpdated(*drop_target_event); 921 drag_operation = delegate->OnDragUpdated(*drop_target_event);
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
1022 // success or failure, and when it fails, it then sends an internal 1060 // success or failure, and when it fails, it then sends an internal
1023 // GdkEvent about the failed drag. (And sending this message doesn't appear 1061 // GdkEvent about the failed drag. (And sending this message doesn't appear
1024 // to go through normal xlib machinery, but instead passes through the low 1062 // to go through normal xlib machinery, but instead passes through the low
1025 // level xProto (the x11 wire format) that I don't understand. 1063 // level xProto (the x11 wire format) that I don't understand.
1026 // 1064 //
1027 // I'm unsure if I have to jump through those hoops, or if XSendEvent is 1065 // I'm unsure if I have to jump through those hoops, or if XSendEvent is
1028 // sufficient. 1066 // sufficient.
1029 XSendEvent(xdisplay_, xid, False, 0, xev); 1067 XSendEvent(xdisplay_, xid, False, 0, xev);
1030 } 1068 }
1031 1069
1070 void DesktopDragDropClientAuraX11::SetDragImage(const gfx::ImageSkia& image,
1071 gfx::Vector2dF offset) {
1072 drag_image_ = image;
1073 drag_offset_ = offset;
1074 // Reset the Y offset, so that the drag-image is always just below the cursor,
1075 // so that it is possible to see where the cursor is going.
1076 drag_offset_.set_y(0.f);
1077 }
1078
1079 void DesktopDragDropClientAuraX11::CreateDragImageWindow() {
1080 Widget* widget = new Widget;
1081 Widget::InitParams params(Widget::InitParams::TYPE_DRAG);
1082 params.opacity = Widget::InitParams::OPAQUE_WINDOW;
sadrul 2014/05/23 14:39:53 Should this be TRANSLUCENT_WINDOW?
varkha 2014/05/23 15:38:36 Done.
1083 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1084 params.accept_events = false;
1085
1086 if (drag_image_.isNull()) {
1087 params.bounds = null_drag_widget_bounds_;
1088 } else {
1089 params.bounds = gfx::Rect(
1090 gfx::ToFlooredPoint(
1091 gfx::Screen::GetNativeScreen()->GetCursorScreenPoint() -
1092 drag_offset_),
1093 drag_image_.size());
1094 }
1095 widget->set_focus_on_creation(false);
1096 widget->set_frame_type(Widget::FRAME_TYPE_FORCE_NATIVE);
1097 widget->Init(params);
1098 widget->SetOpacity(kDragWidgetOpacity);
1099 widget->GetNativeWindow()->SetName("DragWindow");
1100
1101 if (!drag_image_.isNull()) {
1102 ImageView* image = new ImageView();
1103 image->SetImage(drag_image_);
1104 image->SetBounds(0, 0, drag_image_.width(), drag_image_.height());
1105 widget->SetContentsView(image);
1106 }
1107
1108 widget->Show();
1109 widget->GetNativeWindow()->layer()->SetFillsBoundsOpaquely(false);
1110 drag_widget_.reset(widget);
1111 }
1112
1032 } // namespace views 1113 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698