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

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 (null image case) 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
40 // Drag widget is positioned off screen when drag image is not set or is
41 // completely transparent.
42 const gfx::Size kNullDragWidgetSize = gfx::Size(1, 1);
43 const gfx::Point kNullDragWidgetLocation = gfx::Point(-100, -100);
pkotwicz 2014/05/12 16:04:29 I do not know if there is much precedent for non p
varkha 2014/05/20 17:13:35 Good catch. https://engdoc.corp.google.com/eng/doc
44
45 bool CheckIfIconValid(const gfx::ImageSkia& drag_image) {
pkotwicz 2014/05/12 16:04:29 Is CheckIfIconValid() still needed in a world wher
varkha 2014/05/20 17:13:35 Done.
46 // Because we need a GL context per window, we do a quick check so that we
47 // don't make another context if the window would just be displaying a mostly
48 // transparent image.
49 const SkBitmap* in_bitmap = drag_image.bitmap();
50 SkAutoLockPixels in_lock(*in_bitmap);
51 for (int y = 0; y < in_bitmap->height(); ++y) {
52 uint32* in_row = in_bitmap->getAddr32(0, y);
53
54 for (int x = 0; x < in_bitmap->width(); ++x) {
55 if (SkColorGetA(in_row[x]) > kMinAlpha)
56 return true;
57 }
58 }
59
60 return false;
61 }
62
32 const int kMinXdndVersion = 5; 63 const int kMinXdndVersion = 5;
33 64
34 const int kWillAcceptDrop = 1; 65 const int kWillAcceptDrop = 1;
35 const int kWantFurtherPosEvents = 2; 66 const int kWantFurtherPosEvents = 2;
36 67
37 const char kXdndActionCopy[] = "XdndActionCopy"; 68 const char kXdndActionCopy[] = "XdndActionCopy";
38 const char kXdndActionMove[] = "XdndActionMove"; 69 const char kXdndActionMove[] = "XdndActionMove";
39 const char kXdndActionLink[] = "XdndActionLink"; 70 const char kXdndActionLink[] = "XdndActionLink";
40 const char kXdndActionDirectSave[] = "XdndActionDirectSave"; 71 const char kXdndActionDirectSave[] = "XdndActionDirectSave";
41 72
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 // We were waiting on the status message so we could send the XdndDrop. 528 // We were waiting on the status message so we could send the XdndDrop.
498 if (negotiated_operation_ == ui::DragDropTypes::DRAG_NONE) { 529 if (negotiated_operation_ == ui::DragDropTypes::DRAG_NONE) {
499 move_loop_.EndMoveLoop(); 530 move_loop_.EndMoveLoop();
500 return; 531 return;
501 } 532 }
502 source_state_ = SOURCE_STATE_DROPPED; 533 source_state_ = SOURCE_STATE_DROPPED;
503 SendXdndDrop(source_window); 534 SendXdndDrop(source_window);
504 return; 535 return;
505 } 536 }
506 537
507 switch (negotiated_operation_) { 538 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 539
519 // Note: event.data.[2,3] specify a rectangle. It is a request by the other 540 // 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 541 // window to not send further XdndPosition messages while the cursor is
521 // within it. However, it is considered advisory and (at least according to 542 // within it. However, it is considered advisory and (at least according to
522 // the spec) the other side must handle further position messages within 543 // the spec) the other side must handle further position messages within
523 // it. GTK+ doesn't bother with this, so neither should we. 544 // it. GTK+ doesn't bother with this, so neither should we.
524 545
525 if (next_position_message_.get()) { 546 if (next_position_message_.get()) {
526 // We were waiting on the status message so we could send off the next 547 // We were waiting on the status message so we could send off the next
527 // position message we queued up. 548 // position message we queued up.
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 source_provider_->file_contents_name().AsUTF8Unsafe()); 644 source_provider_->file_contents_name().AsUTF8Unsafe());
624 } 645 }
625 ui::SetAtomArrayProperty(xwindow_, "XdndActionList", "ATOM", actions); 646 ui::SetAtomArrayProperty(xwindow_, "XdndActionList", "ATOM", actions);
626 647
627 // It is possible for the DesktopWindowTreeHostX11 to be destroyed during the 648 // 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 649 // move loop, which would also destroy this drag-client. So keep track of
629 // whether it is alive after the drag ends. 650 // whether it is alive after the drag ends.
630 base::WeakPtr<DesktopDragDropClientAuraX11> alive( 651 base::WeakPtr<DesktopDragDropClientAuraX11> alive(
631 weak_ptr_factory_.GetWeakPtr()); 652 weak_ptr_factory_.GetWeakPtr());
632 653
654 SetDragImage(source_provider_->GetDragImage(),
655 source_provider_->GetDragImageOffset());
656 CreateDragImageWindow();
633 // Windows has a specific method, DoDragDrop(), which performs the entire 657 // 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 658 // 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. 659 // track all cursor movement and reroute events to a specific handler.
636 move_loop_.SetDragImage(source_provider_->GetDragImage(), 660 move_loop_.RunMoveLoop();
637 source_provider_->GetDragImageOffset());
638 move_loop_.RunMoveLoop(source_window, grab_cursor_);
639 661
640 if (alive) { 662 if (alive) {
641 move_loop_.SetDragImage(gfx::ImageSkia(), gfx::Vector2dF()); 663 SetDragImage(gfx::ImageSkia(), gfx::Vector2dF());
642 664
643 source_provider_ = NULL; 665 source_provider_ = NULL;
644 g_current_drag_drop_client = NULL; 666 g_current_drag_drop_client = NULL;
645 drag_operation_ = 0; 667 drag_operation_ = 0;
646 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndActionList")); 668 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndActionList"));
647 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom(kXdndDirectSave0)); 669 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom(kXdndDirectSave0));
648 670
649 return negotiated_operation_; 671 return negotiated_operation_;
650 } 672 }
651 return ui::DragDropTypes::DRAG_NONE; 673 return ui::DragDropTypes::DRAG_NONE;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
715 // an XdndFinished message. 737 // an XdndFinished message.
716 StartEndMoveLoopTimer(); 738 StartEndMoveLoopTimer();
717 return; 739 return;
718 } 740 }
719 } 741 }
720 742
721 move_loop_.EndMoveLoop(); 743 move_loop_.EndMoveLoop();
722 } 744 }
723 745
724 void DesktopDragDropClientAuraX11::OnMoveLoopEnded() { 746 void DesktopDragDropClientAuraX11::OnMoveLoopEnded() {
747 drag_widget_.reset();
725 if (source_current_window_ != None) { 748 if (source_current_window_ != None) {
726 SendXdndLeave(source_current_window_); 749 SendXdndLeave(source_current_window_);
727 source_current_window_ = None; 750 source_current_window_ = None;
728 } 751 }
729 target_current_context_.reset(); 752 target_current_context_.reset();
730 repeat_mouse_move_timer_.Stop(); 753 repeat_mouse_move_timer_.Stop();
731 end_move_loop_timer_.Stop(); 754 end_move_loop_timer_.Stop();
732 } 755 }
733 756
734 void DesktopDragDropClientAuraX11::ProcessMouseMove( 757 void DesktopDragDropClientAuraX11::ProcessMouseMove(
735 const gfx::Point& screen_point, 758 const gfx::Point& screen_point,
736 unsigned long event_time) { 759 unsigned long event_time) {
737 if (source_state_ != SOURCE_STATE_OTHER) 760 if (source_state_ != SOURCE_STATE_OTHER)
738 return; 761 return;
739 762
763 if (drag_widget_.get()) {
pkotwicz 2014/05/12 16:04:29 If we intentionally moved |drag_widget_| offscreen
varkha 2014/05/20 17:13:35 I am using drag_image_.isNull() for that (and rese
764 gfx::Point location = drag_image_.isNull() ?
765 kNullDragWidgetLocation :
766 gfx::ToFlooredPoint(screen_point - drag_offset_);
767 drag_widget_->SetBounds(gfx::Rect(
768 location,
769 drag_image_.isNull() ? kNullDragWidgetSize : drag_image_.size()));
770 drag_widget_->StackAtTop();
771 }
772
740 // Find the current window the cursor is over. 773 // Find the current window the cursor is over.
741 ::Window mouse_window = None; 774 ::Window mouse_window = None;
742 ::Window dest_window = None; 775 ::Window dest_window = None;
743 FindWindowFor(screen_point, &mouse_window, &dest_window); 776 FindWindowFor(screen_point, &mouse_window, &dest_window);
744 777
745 if (source_current_window_ != dest_window) { 778 if (source_current_window_ != dest_window) {
746 if (source_current_window_ != None) 779 if (source_current_window_ != None)
747 SendXdndLeave(source_current_window_); 780 SendXdndLeave(source_current_window_);
748 781
749 source_current_window_ = dest_window; 782 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) 897 if (drag_operation_ & ui::DragDropTypes::DRAG_LINK)
865 operations.push_back(atom_cache_.GetAtom(kXdndActionLink)); 898 operations.push_back(atom_cache_.GetAtom(kXdndActionLink));
866 return operations; 899 return operations;
867 } 900 }
868 901
869 ui::SelectionFormatMap DesktopDragDropClientAuraX11::GetFormatMap() const { 902 ui::SelectionFormatMap DesktopDragDropClientAuraX11::GetFormatMap() const {
870 return source_provider_ ? source_provider_->GetFormatMap() : 903 return source_provider_ ? source_provider_->GetFormatMap() :
871 ui::SelectionFormatMap(); 904 ui::SelectionFormatMap();
872 } 905 }
873 906
907 void DesktopDragDropClientAuraX11::UpdateCursor() {
908 gfx::NativeCursor cursor = grab_cursor_;
909 switch (negotiated_operation_) {
910 case ui::DragDropTypes::DRAG_COPY:
911 cursor = copy_grab_cursor_;
912 break;
913 case ui::DragDropTypes::DRAG_MOVE:
914 cursor = move_grab_cursor_;
915 break;
916 default:
917 break;
918 }
919
920 // Update the pointer with the new cursor if a grab is active.
921 XChangeActivePointerGrab(
922 xdisplay_,
923 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
924 cursor.platform(),
925 CurrentTime);
926 }
927
874 void DesktopDragDropClientAuraX11::CompleteXdndPosition( 928 void DesktopDragDropClientAuraX11::CompleteXdndPosition(
875 ::Window source_window, 929 ::Window source_window,
876 const gfx::Point& screen_point) { 930 const gfx::Point& screen_point) {
877 int drag_operation = ui::DragDropTypes::DRAG_NONE; 931 int drag_operation = ui::DragDropTypes::DRAG_NONE;
878 scoped_ptr<ui::OSExchangeData> data; 932 scoped_ptr<ui::OSExchangeData> data;
879 scoped_ptr<ui::DropTargetEvent> drop_target_event; 933 scoped_ptr<ui::DropTargetEvent> drop_target_event;
880 DragDropDelegate* delegate = NULL; 934 DragDropDelegate* delegate = NULL;
881 DragTranslate(screen_point, &data, &drop_target_event, &delegate); 935 DragTranslate(screen_point, &data, &drop_target_event, &delegate);
882 if (delegate) 936 if (delegate)
883 drag_operation = delegate->OnDragUpdated(*drop_target_event); 937 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 1076 // 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 1077 // 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 1078 // to go through normal xlib machinery, but instead passes through the low
1025 // level xProto (the x11 wire format) that I don't understand. 1079 // level xProto (the x11 wire format) that I don't understand.
1026 // 1080 //
1027 // I'm unsure if I have to jump through those hoops, or if XSendEvent is 1081 // I'm unsure if I have to jump through those hoops, or if XSendEvent is
1028 // sufficient. 1082 // sufficient.
1029 XSendEvent(xdisplay_, xid, False, 0, xev); 1083 XSendEvent(xdisplay_, xid, False, 0, xev);
1030 } 1084 }
1031 1085
1086 void DesktopDragDropClientAuraX11::SetDragImage(const gfx::ImageSkia& image,
1087 gfx::Vector2dF offset) {
1088 /*if (drag_image_.isNull() || !CheckIfIconValid(drag_image_))*/ {
pkotwicz 2014/05/12 16:04:29 Remove the if block entirely. It is not needed.
varkha 2014/05/20 17:13:35 Done.
1089 drag_image_ = gfx::ImageSkia();
1090 drag_offset_ = gfx::Vector2dF();
1091 return;
1092 }
1093 drag_image_ = image;
1094 drag_offset_ = offset;
1095 // Reset the Y offset, so that the drag-image is always just below the cursor,
1096 // so that it is possible to see where the cursor is going.
1097 drag_offset_.set_y(0.f);
1098 }
1099
1100 void DesktopDragDropClientAuraX11::CreateDragImageWindow() {
1101 Widget* widget = new Widget;
1102 Widget::InitParams params(Widget::InitParams::TYPE_DRAG);
1103 params.opacity = Widget::InitParams::OPAQUE_WINDOW;
1104 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1105 params.accept_events = false;
1106
1107 gfx::Point location = drag_image_.isNull() ?
pkotwicz 2014/05/12 16:04:29 I will defer to sadrul@/erg@ as to whether they li
varkha 2014/05/20 17:13:35 Right. Keeping the drag widget offscreen matches t
1108 kNullDragWidgetLocation :
1109 gfx::ToFlooredPoint(
1110 gfx::Screen::GetNativeScreen()->GetCursorScreenPoint() -
1111 drag_offset_);
1112 params.bounds = gfx::Rect(
1113 location,
1114 drag_image_.isNull() ? kNullDragWidgetSize : drag_image_.size());
1115 widget->set_focus_on_creation(false);
1116 widget->set_frame_type(Widget::FRAME_TYPE_FORCE_NATIVE);
1117 widget->Init(params);
1118 widget->SetOpacity(kDragWidgetOpacity);
1119 widget->GetNativeWindow()->SetName("DragWindow");
1120
1121 if (!drag_image_.isNull()) {
1122 ImageView* image = new ImageView();
1123 image->SetImage(drag_image_);
1124 image->SetBounds(0, 0, drag_image_.width(), drag_image_.height());
1125 widget->SetContentsView(image);
1126 }
1127
1128 widget->Show();
1129 widget->GetNativeWindow()->layer()->SetFillsBoundsOpaquely(false);
pkotwicz 2014/05/12 16:04:29 We should have a comment as to why we set capture
varkha 2014/05/20 17:13:35 Done.
1130 widget->GetNativeWindow()->SetCapture();
1131 drag_widget_.reset(widget);
1132 }
1133
1032 } // namespace views 1134 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698