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

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) 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 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 waiting_on_status_(false), 364 waiting_on_status_(false),
357 status_received_since_enter_(false), 365 status_received_since_enter_(false),
358 source_provider_(NULL), 366 source_provider_(NULL),
359 source_current_window_(None), 367 source_current_window_(None),
360 source_state_(SOURCE_STATE_OTHER), 368 source_state_(SOURCE_STATE_OTHER),
361 drag_operation_(0), 369 drag_operation_(0),
362 negotiated_operation_(ui::DragDropTypes::DRAG_NONE), 370 negotiated_operation_(ui::DragDropTypes::DRAG_NONE),
363 grab_cursor_(cursor_manager->GetInitializedCursor(ui::kCursorGrabbing)), 371 grab_cursor_(cursor_manager->GetInitializedCursor(ui::kCursorGrabbing)),
364 copy_grab_cursor_(cursor_manager->GetInitializedCursor(ui::kCursorCopy)), 372 copy_grab_cursor_(cursor_manager->GetInitializedCursor(ui::kCursorCopy)),
365 move_grab_cursor_(cursor_manager->GetInitializedCursor(ui::kCursorMove)), 373 move_grab_cursor_(cursor_manager->GetInitializedCursor(ui::kCursorMove)),
374 null_drag_widget_bounds_(-100, -100, 1, 1),
366 weak_ptr_factory_(this) { 375 weak_ptr_factory_(this) {
367 // Some tests change the DesktopDragDropClientAuraX11 associated with an 376 // Some tests change the DesktopDragDropClientAuraX11 associated with an
368 // |xwindow|. 377 // |xwindow|.
369 g_live_client_map.Get()[xwindow] = this; 378 g_live_client_map.Get()[xwindow] = this;
370 379
371 // Mark that we are aware of drag and drop concepts. 380 // Mark that we are aware of drag and drop concepts.
372 unsigned long xdnd_version = kMinXdndVersion; 381 unsigned long xdnd_version = kMinXdndVersion;
373 XChangeProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndAware"), 382 XChangeProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndAware"),
374 XA_ATOM, 32, PropModeReplace, 383 XA_ATOM, 32, PropModeReplace,
375 reinterpret_cast<unsigned char*>(&xdnd_version), 1); 384 reinterpret_cast<unsigned char*>(&xdnd_version), 1);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
470 // We were waiting on the status message so we could send the XdndDrop. 479 // We were waiting on the status message so we could send the XdndDrop.
471 if (negotiated_operation_ == ui::DragDropTypes::DRAG_NONE) { 480 if (negotiated_operation_ == ui::DragDropTypes::DRAG_NONE) {
472 move_loop_.EndMoveLoop(); 481 move_loop_.EndMoveLoop();
473 return; 482 return;
474 } 483 }
475 source_state_ = SOURCE_STATE_DROPPED; 484 source_state_ = SOURCE_STATE_DROPPED;
476 SendXdndDrop(source_window); 485 SendXdndDrop(source_window);
477 return; 486 return;
478 } 487 }
479 488
480 switch (negotiated_operation_) { 489 UpdateCursor();
481 case ui::DragDropTypes::DRAG_COPY:
482 move_loop_.UpdateCursor(copy_grab_cursor_);
483 break;
484 case ui::DragDropTypes::DRAG_MOVE:
485 move_loop_.UpdateCursor(move_grab_cursor_);
486 break;
487 default:
488 move_loop_.UpdateCursor(grab_cursor_);
489 break;
490 }
491 490
492 // Note: event.data.[2,3] specify a rectangle. It is a request by the other 491 // Note: event.data.[2,3] specify a rectangle. It is a request by the other
493 // window to not send further XdndPosition messages while the cursor is 492 // window to not send further XdndPosition messages while the cursor is
494 // within it. However, it is considered advisory and (at least according to 493 // within it. However, it is considered advisory and (at least according to
495 // the spec) the other side must handle further position messages within 494 // the spec) the other side must handle further position messages within
496 // it. GTK+ doesn't bother with this, so neither should we. 495 // it. GTK+ doesn't bother with this, so neither should we.
497 496
498 if (next_position_message_.get()) { 497 if (next_position_message_.get()) {
499 // We were waiting on the status message so we could send off the next 498 // We were waiting on the status message so we could send off the next
500 // position message we queued up. 499 // position message we queued up.
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
603 source_provider_->file_contents_name().AsUTF8Unsafe()); 602 source_provider_->file_contents_name().AsUTF8Unsafe());
604 } 603 }
605 ui::SetAtomArrayProperty(xwindow_, "XdndActionList", "ATOM", actions); 604 ui::SetAtomArrayProperty(xwindow_, "XdndActionList", "ATOM", actions);
606 605
607 // It is possible for the DesktopWindowTreeHostX11 to be destroyed during the 606 // It is possible for the DesktopWindowTreeHostX11 to be destroyed during the
608 // move loop, which would also destroy this drag-client. So keep track of 607 // move loop, which would also destroy this drag-client. So keep track of
609 // whether it is alive after the drag ends. 608 // whether it is alive after the drag ends.
610 base::WeakPtr<DesktopDragDropClientAuraX11> alive( 609 base::WeakPtr<DesktopDragDropClientAuraX11> alive(
611 weak_ptr_factory_.GetWeakPtr()); 610 weak_ptr_factory_.GetWeakPtr());
612 611
612 SetDragImage(source_provider_->GetDragImage(),
613 source_provider_->GetDragImageOffset());
614 CreateDragImageWindow();
615 // Capture drag widget to continue receiving events even if the drag source
616 // gets destroyed during the drag such as when we drag an item out of a menu
617 // and the menu closes.
618 drag_widget_->GetNativeWindow()->SetCapture();
619
613 // Windows has a specific method, DoDragDrop(), which performs the entire 620 // Windows has a specific method, DoDragDrop(), which performs the entire
614 // drag. We have to emulate this, so we spin off a nested runloop which will 621 // drag. We have to emulate this, so we spin off a nested runloop which will
615 // track all cursor movement and reroute events to a specific handler. 622 // track all cursor movement and reroute events to a specific handler.
616 move_loop_.SetDragImage(source_provider_->GetDragImage(), 623 move_loop_.RunMoveLoop();
617 source_provider_->GetDragImageOffset());
618 move_loop_.RunMoveLoop(source_window, grab_cursor_);
619 624
620 if (alive) { 625 if (alive) {
621 move_loop_.SetDragImage(gfx::ImageSkia(), gfx::Vector2dF()); 626 SetDragImage(gfx::ImageSkia(), gfx::Vector2dF());
622 627
623 source_provider_ = NULL; 628 source_provider_ = NULL;
624 g_current_drag_drop_client = NULL; 629 g_current_drag_drop_client = NULL;
625 drag_operation_ = 0; 630 drag_operation_ = 0;
626 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndActionList")); 631 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndActionList"));
627 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom(kXdndDirectSave0)); 632 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom(kXdndDirectSave0));
628 633
629 return negotiated_operation_; 634 return negotiated_operation_;
630 } 635 }
631 return ui::DragDropTypes::DRAG_NONE; 636 return ui::DragDropTypes::DRAG_NONE;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
695 // an XdndFinished message. 700 // an XdndFinished message.
696 StartEndMoveLoopTimer(); 701 StartEndMoveLoopTimer();
697 return; 702 return;
698 } 703 }
699 } 704 }
700 705
701 move_loop_.EndMoveLoop(); 706 move_loop_.EndMoveLoop();
702 } 707 }
703 708
704 void DesktopDragDropClientAuraX11::OnMoveLoopEnded() { 709 void DesktopDragDropClientAuraX11::OnMoveLoopEnded() {
710 drag_widget_.reset();
705 if (source_current_window_ != None) { 711 if (source_current_window_ != None) {
706 SendXdndLeave(source_current_window_); 712 SendXdndLeave(source_current_window_);
707 source_current_window_ = None; 713 source_current_window_ = None;
708 } 714 }
709 target_current_context_.reset(); 715 target_current_context_.reset();
710 repeat_mouse_move_timer_.Stop(); 716 repeat_mouse_move_timer_.Stop();
711 end_move_loop_timer_.Stop(); 717 end_move_loop_timer_.Stop();
712 } 718 }
713 719
714 XID DesktopDragDropClientAuraX11::FindWindowFor( 720 XID DesktopDragDropClientAuraX11::FindWindowFor(
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
772 // sufficient. 778 // sufficient.
773 XSendEvent(xdisplay_, xid, False, 0, xev); 779 XSendEvent(xdisplay_, xid, False, 0, xev);
774 } 780 }
775 781
776 void DesktopDragDropClientAuraX11::ProcessMouseMove( 782 void DesktopDragDropClientAuraX11::ProcessMouseMove(
777 const gfx::Point& screen_point, 783 const gfx::Point& screen_point,
778 unsigned long event_time) { 784 unsigned long event_time) {
779 if (source_state_ != SOURCE_STATE_OTHER) 785 if (source_state_ != SOURCE_STATE_OTHER)
780 return; 786 return;
781 787
788 if (drag_widget_.get()) {
789 if (drag_image_.isNull()) {
790 drag_widget_->SetBounds(null_drag_widget_bounds_);
791 } else {
792 drag_widget_->SetBounds(gfx::Rect(
793 gfx::ToFlooredPoint(screen_point - drag_offset_),
794 drag_image_.size()));
795 }
796 drag_widget_->StackAtTop();
797 }
798
782 // Find the current window the cursor is over. 799 // Find the current window the cursor is over.
783 ::Window dest_window = FindWindowFor(screen_point); 800 ::Window dest_window = FindWindowFor(screen_point);
784 801
785 if (source_current_window_ != dest_window) { 802 if (source_current_window_ != dest_window) {
786 if (source_current_window_ != None) 803 if (source_current_window_ != None)
787 SendXdndLeave(source_current_window_); 804 SendXdndLeave(source_current_window_);
788 805
789 source_current_window_ = dest_window; 806 source_current_window_ = dest_window;
790 waiting_on_status_ = false; 807 waiting_on_status_ = false;
791 next_position_message_.reset(); 808 next_position_message_.reset();
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
904 if (drag_operation_ & ui::DragDropTypes::DRAG_LINK) 921 if (drag_operation_ & ui::DragDropTypes::DRAG_LINK)
905 operations.push_back(atom_cache_.GetAtom(kXdndActionLink)); 922 operations.push_back(atom_cache_.GetAtom(kXdndActionLink));
906 return operations; 923 return operations;
907 } 924 }
908 925
909 ui::SelectionFormatMap DesktopDragDropClientAuraX11::GetFormatMap() const { 926 ui::SelectionFormatMap DesktopDragDropClientAuraX11::GetFormatMap() const {
910 return source_provider_ ? source_provider_->GetFormatMap() : 927 return source_provider_ ? source_provider_->GetFormatMap() :
911 ui::SelectionFormatMap(); 928 ui::SelectionFormatMap();
912 } 929 }
913 930
931 void DesktopDragDropClientAuraX11::UpdateCursor() {
932 gfx::NativeCursor cursor = grab_cursor_;
933 switch (negotiated_operation_) {
934 case ui::DragDropTypes::DRAG_COPY:
935 cursor = copy_grab_cursor_;
936 break;
937 case ui::DragDropTypes::DRAG_MOVE:
938 cursor = move_grab_cursor_;
939 break;
940 default:
941 break;
942 }
943
944 // Update the pointer with the new cursor if a grab is active.
945 XChangeActivePointerGrab(
946 xdisplay_,
947 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
948 cursor.platform(),
949 CurrentTime);
950 }
951
914 void DesktopDragDropClientAuraX11::CompleteXdndPosition( 952 void DesktopDragDropClientAuraX11::CompleteXdndPosition(
915 ::Window source_window, 953 ::Window source_window,
916 const gfx::Point& screen_point) { 954 const gfx::Point& screen_point) {
917 int drag_operation = ui::DragDropTypes::DRAG_NONE; 955 int drag_operation = ui::DragDropTypes::DRAG_NONE;
918 scoped_ptr<ui::OSExchangeData> data; 956 scoped_ptr<ui::OSExchangeData> data;
919 scoped_ptr<ui::DropTargetEvent> drop_target_event; 957 scoped_ptr<ui::DropTargetEvent> drop_target_event;
920 DragDropDelegate* delegate = NULL; 958 DragDropDelegate* delegate = NULL;
921 DragTranslate(screen_point, &data, &drop_target_event, &delegate); 959 DragTranslate(screen_point, &data, &drop_target_event, &delegate);
922 if (delegate) 960 if (delegate)
923 drag_operation = delegate->OnDragUpdated(*drop_target_event); 961 drag_operation = delegate->OnDragUpdated(*drop_target_event);
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
1021 xev.xclient.format = 32; 1059 xev.xclient.format = 32;
1022 xev.xclient.window = dest_window; 1060 xev.xclient.window = dest_window;
1023 xev.xclient.data.l[0] = xwindow_; 1061 xev.xclient.data.l[0] = xwindow_;
1024 xev.xclient.data.l[1] = 0; 1062 xev.xclient.data.l[1] = 0;
1025 xev.xclient.data.l[2] = CurrentTime; 1063 xev.xclient.data.l[2] = CurrentTime;
1026 xev.xclient.data.l[3] = None; 1064 xev.xclient.data.l[3] = None;
1027 xev.xclient.data.l[4] = None; 1065 xev.xclient.data.l[4] = None;
1028 SendXClientEvent(dest_window, &xev); 1066 SendXClientEvent(dest_window, &xev);
1029 } 1067 }
1030 1068
1069 void DesktopDragDropClientAuraX11::SetDragImage(const gfx::ImageSkia& image,
1070 const gfx::Vector2dF& offset) {
1071 drag_image_ = image;
1072 drag_offset_ = offset;
1073 // Reset the Y offset, so that the drag-image is always just below the cursor,
1074 // so that it is possible to see where the cursor is going.
1075 drag_offset_.set_y(0.f);
1076 }
1077
1078 void DesktopDragDropClientAuraX11::CreateDragImageWindow() {
1079 Widget* widget = new Widget;
1080 Widget::InitParams params(Widget::InitParams::TYPE_DRAG);
1081 params.opacity = Widget::InitParams::TRANSLUCENT_WINDOW;
1082 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1083 params.accept_events = false;
1084
1085 if (drag_image_.isNull()) {
1086 params.bounds = null_drag_widget_bounds_;
1087 } else {
1088 params.bounds = gfx::Rect(
1089 gfx::ToFlooredPoint(
1090 gfx::Screen::GetNativeScreen()->GetCursorScreenPoint() -
1091 drag_offset_),
1092 drag_image_.size());
1093 }
1094 widget->set_focus_on_creation(false);
1095 widget->set_frame_type(Widget::FRAME_TYPE_FORCE_NATIVE);
1096 widget->Init(params);
1097 widget->SetOpacity(kDragWidgetOpacity);
1098 widget->GetNativeWindow()->SetName("DragWindow");
1099
1100 if (!drag_image_.isNull()) {
1101 ImageView* image = new ImageView();
1102 image->SetImage(drag_image_);
1103 image->SetBounds(0, 0, drag_image_.width(), drag_image_.height());
1104 widget->SetContentsView(image);
1105 }
1106
1107 widget->Show();
1108 widget->GetNativeWindow()->layer()->SetFillsBoundsOpaquely(false);
1109 drag_widget_.reset(widget);
1110 }
1111
1031 } // namespace views 1112 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698