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

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: Additional SetCapture after Attach and Show in TabDragController 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 bool CheckIfIconValid(const gfx::ImageSkia& drag_image) {
41 // Because we need a GL context per window, we do a quick check so that we
42 // don't make another context if the window would just be displaying a mostly
43 // transparent image.
44 const SkBitmap* in_bitmap = drag_image.bitmap();
45 SkAutoLockPixels in_lock(*in_bitmap);
46 for (int y = 0; y < in_bitmap->height(); ++y) {
47 uint32* in_row = in_bitmap->getAddr32(0, y);
48
49 for (int x = 0; x < in_bitmap->width(); ++x) {
50 if (SkColorGetA(in_row[x]) > kMinAlpha)
51 return true;
52 }
53 }
54
55 return false;
56 }
57
32 const int kMinXdndVersion = 5; 58 const int kMinXdndVersion = 5;
33 59
34 const int kWillAcceptDrop = 1; 60 const int kWillAcceptDrop = 1;
35 const int kWantFurtherPosEvents = 2; 61 const int kWantFurtherPosEvents = 2;
36 62
37 const char kXdndActionCopy[] = "XdndActionCopy"; 63 const char kXdndActionCopy[] = "XdndActionCopy";
38 const char kXdndActionMove[] = "XdndActionMove"; 64 const char kXdndActionMove[] = "XdndActionMove";
39 const char kXdndActionLink[] = "XdndActionLink"; 65 const char kXdndActionLink[] = "XdndActionLink";
40 const char kXdndActionDirectSave[] = "XdndActionDirectSave"; 66 const char kXdndActionDirectSave[] = "XdndActionDirectSave";
41 67
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 // We were waiting on the status message so we could send the XdndDrop. 516 // We were waiting on the status message so we could send the XdndDrop.
491 if (negotiated_operation_ == ui::DragDropTypes::DRAG_NONE) { 517 if (negotiated_operation_ == ui::DragDropTypes::DRAG_NONE) {
492 move_loop_.EndMoveLoop(); 518 move_loop_.EndMoveLoop();
493 return; 519 return;
494 } 520 }
495 source_state_ = SOURCE_STATE_DROPPED; 521 source_state_ = SOURCE_STATE_DROPPED;
496 SendXdndDrop(source_window); 522 SendXdndDrop(source_window);
497 return; 523 return;
498 } 524 }
499 525
500 switch (negotiated_operation_) { 526 UpdateCursor();
501 case ui::DragDropTypes::DRAG_COPY:
502 move_loop_.UpdateCursor(copy_grab_cursor_);
503 break;
504 case ui::DragDropTypes::DRAG_MOVE:
505 move_loop_.UpdateCursor(move_grab_cursor_);
506 break;
507 default:
508 move_loop_.UpdateCursor(grab_cursor_);
509 break;
510 }
511 527
512 // Note: event.data.[2,3] specify a rectangle. It is a request by the other 528 // Note: event.data.[2,3] specify a rectangle. It is a request by the other
513 // window to not send further XdndPosition messages while the cursor is 529 // window to not send further XdndPosition messages while the cursor is
514 // within it. However, it is considered advisory and (at least according to 530 // within it. However, it is considered advisory and (at least according to
515 // the spec) the other side must handle further position messages within 531 // the spec) the other side must handle further position messages within
516 // it. GTK+ doesn't bother with this, so neither should we. 532 // it. GTK+ doesn't bother with this, so neither should we.
517 533
518 if (next_position_message_.get()) { 534 if (next_position_message_.get()) {
519 // We were waiting on the status message so we could send off the next 535 // We were waiting on the status message so we could send off the next
520 // position message we queued up. 536 // position message we queued up.
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
617 ui::SetAtomArrayProperty(xwindow_, "XdndActionList", "ATOM", actions); 633 ui::SetAtomArrayProperty(xwindow_, "XdndActionList", "ATOM", actions);
618 634
619 // It is possible for the DesktopWindowTreeHostX11 to be destroyed during the 635 // It is possible for the DesktopWindowTreeHostX11 to be destroyed during the
620 // move loop, which would also destroy this drag-client. So keep track of 636 // move loop, which would also destroy this drag-client. So keep track of
621 // whether it is alive after the drag ends. 637 // whether it is alive after the drag ends.
622 base::WeakPtr<DesktopDragDropClientAuraX11> alive( 638 base::WeakPtr<DesktopDragDropClientAuraX11> alive(
623 weak_ptr_factory_.GetWeakPtr()); 639 weak_ptr_factory_.GetWeakPtr());
624 640
625 // Windows has a specific method, DoDragDrop(), which performs the entire 641 // Windows has a specific method, DoDragDrop(), which performs the entire
626 // drag. We have to emulate this, so we spin off a nested runloop which will 642 // drag. We have to emulate this, so we spin off a nested runloop which will
627 // track all cursor movement and reroute events to a specific handler. 643 // track all cursor movement and reroute events to a specific handler.
pkotwicz 2014/05/08 00:03:49 Nits: - The comment above should be right above th
varkha 2014/05/09 19:01:01 Done.
628 move_loop_.SetDragImage(source_provider_->GetDragImage(), 644 SetDragImage(source_provider_->GetDragImage(),
629 source_provider_->GetDragImageOffset()); 645 source_provider_->GetDragImageOffset());
630 move_loop_.RunMoveLoop(source_window, grab_cursor_); 646 if (!drag_image_.isNull() && CheckIfIconValid(drag_image_))
647 CreateDragImageWindow();
pkotwicz 2014/05/08 00:03:49 We may need to move |grab_input_window_| to this c
varkha 2014/05/09 19:01:01 We talked about this offline. I've set up the drag
648 move_loop_.RunMoveLoop(grab_cursor_);
631 649
632 if (alive) { 650 if (alive) {
633 move_loop_.SetDragImage(gfx::ImageSkia(), gfx::Vector2dF()); 651 SetDragImage(gfx::ImageSkia(), gfx::Vector2dF());
634 652
635 source_provider_ = NULL; 653 source_provider_ = NULL;
636 g_current_drag_drop_client = NULL; 654 g_current_drag_drop_client = NULL;
637 drag_operation_ = 0; 655 drag_operation_ = 0;
638 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndActionList")); 656 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndActionList"));
639 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom(kXdndDirectSave0)); 657 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom(kXdndDirectSave0));
640 658
641 return negotiated_operation_; 659 return negotiated_operation_;
642 } 660 }
643 return ui::DragDropTypes::DRAG_NONE; 661 return ui::DragDropTypes::DRAG_NONE;
(...skipping 21 matching lines...) Expand all
665 DCHECK_EQ(target_window_, window); 683 DCHECK_EQ(target_window_, window);
666 target_window_ = NULL; 684 target_window_ = NULL;
667 } 685 }
668 686
669 void DesktopDragDropClientAuraX11::OnMouseMovement(XMotionEvent* event) { 687 void DesktopDragDropClientAuraX11::OnMouseMovement(XMotionEvent* event) {
670 gfx::Point screen_point(event->x_root, event->y_root); 688 gfx::Point screen_point(event->x_root, event->y_root);
671 689
672 if (source_state_ != SOURCE_STATE_OTHER) 690 if (source_state_ != SOURCE_STATE_OTHER)
673 return; 691 return;
674 692
693 if (drag_widget_.get()) {
694 gfx::Point location = gfx::ToFlooredPoint(screen_point - drag_offset_);
695 drag_widget_->SetBounds(gfx::Rect(location, drag_image_.size()));
696 drag_widget_->StackAtTop();
697 }
698
675 // Find the current window the cursor is over. 699 // Find the current window the cursor is over.
676 ::Window mouse_window = None; 700 ::Window mouse_window = None;
677 ::Window dest_window = None; 701 ::Window dest_window = None;
678 FindWindowFor(screen_point, &mouse_window, &dest_window); 702 FindWindowFor(screen_point, &mouse_window, &dest_window);
679 703
680 if (source_current_window_ != dest_window) { 704 if (source_current_window_ != dest_window) {
681 if (source_current_window_ != None) 705 if (source_current_window_ != None)
682 SendXdndLeave(source_current_window_); 706 SendXdndLeave(source_current_window_);
683 707
684 source_current_window_ = dest_window; 708 source_current_window_ = dest_window;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 // an XdndFinished message. 753 // an XdndFinished message.
730 StartEndMoveLoopTimer(); 754 StartEndMoveLoopTimer();
731 return; 755 return;
732 } 756 }
733 } 757 }
734 758
735 move_loop_.EndMoveLoop(); 759 move_loop_.EndMoveLoop();
736 } 760 }
737 761
738 void DesktopDragDropClientAuraX11::OnMoveLoopEnded() { 762 void DesktopDragDropClientAuraX11::OnMoveLoopEnded() {
763 drag_widget_.reset();
739 if (source_current_window_ != None) { 764 if (source_current_window_ != None) {
740 SendXdndLeave(source_current_window_); 765 SendXdndLeave(source_current_window_);
741 source_current_window_ = None; 766 source_current_window_ = None;
742 } 767 }
743 target_current_context_.reset(); 768 target_current_context_.reset();
744 end_move_loop_timer_.Stop(); 769 end_move_loop_timer_.Stop();
745 } 770 }
746 771
747 void DesktopDragDropClientAuraX11::StartEndMoveLoopTimer() { 772 void DesktopDragDropClientAuraX11::StartEndMoveLoopTimer() {
748 end_move_loop_timer_.Start(FROM_HERE, 773 end_move_loop_timer_.Start(FROM_HERE,
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
842 if (drag_operation_ & ui::DragDropTypes::DRAG_LINK) 867 if (drag_operation_ & ui::DragDropTypes::DRAG_LINK)
843 operations.push_back(atom_cache_.GetAtom(kXdndActionLink)); 868 operations.push_back(atom_cache_.GetAtom(kXdndActionLink));
844 return operations; 869 return operations;
845 } 870 }
846 871
847 ui::SelectionFormatMap DesktopDragDropClientAuraX11::GetFormatMap() const { 872 ui::SelectionFormatMap DesktopDragDropClientAuraX11::GetFormatMap() const {
848 return source_provider_ ? source_provider_->GetFormatMap() : 873 return source_provider_ ? source_provider_->GetFormatMap() :
849 ui::SelectionFormatMap(); 874 ui::SelectionFormatMap();
850 } 875 }
851 876
877 void DesktopDragDropClientAuraX11::UpdateCursor() {
878 gfx::NativeCursor cursor = grab_cursor_;
879 switch (negotiated_operation_) {
880 case ui::DragDropTypes::DRAG_COPY:
881 cursor = copy_grab_cursor_;
882 break;
883 case ui::DragDropTypes::DRAG_MOVE:
884 cursor = move_grab_cursor_;
885 break;
886 default:
887 break;
888 }
889
890 // Update the pointer with the updated cursor if a grab is active.
pkotwicz 2014/05/08 00:03:49 Nit: updated -> new
varkha 2014/05/09 19:01:01 Done.
891 XChangeActivePointerGrab(
892 xdisplay_,
893 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
894 cursor.platform(),
895 CurrentTime);
896 }
897
852 void DesktopDragDropClientAuraX11::CompleteXdndPosition( 898 void DesktopDragDropClientAuraX11::CompleteXdndPosition(
853 ::Window source_window, 899 ::Window source_window,
854 const gfx::Point& screen_point) { 900 const gfx::Point& screen_point) {
855 int drag_operation = ui::DragDropTypes::DRAG_NONE; 901 int drag_operation = ui::DragDropTypes::DRAG_NONE;
856 scoped_ptr<ui::OSExchangeData> data; 902 scoped_ptr<ui::OSExchangeData> data;
857 scoped_ptr<ui::DropTargetEvent> drop_target_event; 903 scoped_ptr<ui::DropTargetEvent> drop_target_event;
858 DragDropDelegate* delegate = NULL; 904 DragDropDelegate* delegate = NULL;
859 DragTranslate(screen_point, &data, &drop_target_event, &delegate); 905 DragTranslate(screen_point, &data, &drop_target_event, &delegate);
860 if (delegate) 906 if (delegate)
861 drag_operation = delegate->OnDragUpdated(*drop_target_event); 907 drag_operation = delegate->OnDragUpdated(*drop_target_event);
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
989 // success or failure, and when it fails, it then sends an internal 1035 // success or failure, and when it fails, it then sends an internal
990 // GdkEvent about the failed drag. (And sending this message doesn't appear 1036 // GdkEvent about the failed drag. (And sending this message doesn't appear
991 // to go through normal xlib machinery, but instead passes through the low 1037 // to go through normal xlib machinery, but instead passes through the low
992 // level xProto (the x11 wire format) that I don't understand. 1038 // level xProto (the x11 wire format) that I don't understand.
993 // 1039 //
994 // I'm unsure if I have to jump through those hoops, or if XSendEvent is 1040 // I'm unsure if I have to jump through those hoops, or if XSendEvent is
995 // sufficient. 1041 // sufficient.
996 XSendEvent(xdisplay_, xid, False, 0, xev); 1042 XSendEvent(xdisplay_, xid, False, 0, xev);
997 } 1043 }
998 1044
1045 void DesktopDragDropClientAuraX11::SetDragImage(const gfx::ImageSkia& image,
1046 gfx::Vector2dF offset) {
1047 drag_image_ = image;
1048 drag_offset_ = offset;
1049 // Reset the Y offset, so that the drag-image is always just below the cursor,
1050 // so that it is possible to see where the cursor is going.
1051 drag_offset_.set_y(0.f);
1052 }
1053
1054 void DesktopDragDropClientAuraX11::CreateDragImageWindow() {
1055 Widget* widget = new Widget;
1056 Widget::InitParams params(Widget::InitParams::TYPE_DRAG);
1057 params.opacity = Widget::InitParams::OPAQUE_WINDOW;
1058 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1059 params.accept_events = false;
1060
1061 gfx::Point location = gfx::ToFlooredPoint(
1062 gfx::Screen::GetNativeScreen()->GetCursorScreenPoint() - drag_offset_);
1063 params.bounds = gfx::Rect(location, drag_image_.size());
1064 widget->set_focus_on_creation(false);
1065 widget->set_frame_type(Widget::FRAME_TYPE_FORCE_NATIVE);
1066 widget->Init(params);
1067 widget->SetOpacity(kDragWidgetOpacity);
1068 widget->GetNativeWindow()->SetName("DragWindow");
1069
1070 ImageView* image = new ImageView();
1071 image->SetImage(drag_image_);
1072 image->SetBounds(0, 0, drag_image_.width(), drag_image_.height());
1073 widget->SetContentsView(image);
1074 widget->Show();
1075 widget->GetNativeWindow()->layer()->SetFillsBoundsOpaquely(false);
1076 widget->GetNativeWindow()->SetCapture();
1077 drag_widget_.reset(widget);
1078 }
1079
999 } // namespace views 1080 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698