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

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

Issue 452413002: [Refactor]: Move drag_widget_ out of X11WholeScreenMoveLoop (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 "third_party/skia/include/core/SkBitmap.h"
12 #include "ui/aura/window.h" 13 #include "ui/aura/window.h"
13 #include "ui/aura/window_tree_host.h" 14 #include "ui/aura/window_tree_host.h"
14 #include "ui/base/clipboard/clipboard.h" 15 #include "ui/base/clipboard/clipboard.h"
15 #include "ui/base/dragdrop/drop_target_event.h" 16 #include "ui/base/dragdrop/drop_target_event.h"
16 #include "ui/base/dragdrop/os_exchange_data.h" 17 #include "ui/base/dragdrop/os_exchange_data.h"
17 #include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h" 18 #include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h"
18 #include "ui/base/x/selection_utils.h" 19 #include "ui/base/x/selection_utils.h"
19 #include "ui/base/x/x11_foreign_window_manager.h" 20 #include "ui/base/x/x11_foreign_window_manager.h"
20 #include "ui/base/x/x11_util.h" 21 #include "ui/base/x/x11_util.h"
21 #include "ui/events/event.h" 22 #include "ui/events/event.h"
22 #include "ui/events/platform/platform_event_source.h" 23 #include "ui/events/platform/platform_event_source.h"
24 #include "ui/gfx/image/image_skia.h"
25 #include "ui/gfx/screen.h"
26 #include "ui/views/controls/image_view.h"
23 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h" 27 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
24 #include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h" 28 #include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h"
25 #include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h" 29 #include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h"
30 #include "ui/views/widget/widget.h"
26 #include "ui/wm/public/drag_drop_client.h" 31 #include "ui/wm/public/drag_drop_client.h"
27 #include "ui/wm/public/drag_drop_delegate.h" 32 #include "ui/wm/public/drag_drop_delegate.h"
28 33
29 using aura::client::DragDropDelegate; 34 using aura::client::DragDropDelegate;
30 using ui::OSExchangeData; 35 using ui::OSExchangeData;
31 36
32 namespace { 37 namespace {
33 38
34 const int kMinXdndVersion = 5; 39 const int kMinXdndVersion = 5;
35 40
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 76
72 // The time to wait for the target to respond after the user has released the 77 // The time to wait for the target to respond after the user has released the
73 // mouse button before ending the move loop. 78 // mouse button before ending the move loop.
74 const int kEndMoveLoopTimeoutMs = 1000; 79 const int kEndMoveLoopTimeoutMs = 1000;
75 80
76 // The time to wait since sending the last XdndPosition message before 81 // The time to wait since sending the last XdndPosition message before
77 // reprocessing the most recent mouse move event in case that the window 82 // reprocessing the most recent mouse move event in case that the window
78 // stacking order has changed and |source_current_window_| needs to be updated. 83 // stacking order has changed and |source_current_window_| needs to be updated.
79 const int kRepeatMouseMoveTimeoutMs = 350; 84 const int kRepeatMouseMoveTimeoutMs = 350;
80 85
86 // The minimum alpha before we declare a pixel transparent when searching in
87 // our source image.
88 const uint32 kMinAlpha = 32;
89
90 // |drag_widget_|'s opacity.
91 const unsigned char kDragWidgetOpacity = 0xc0;
92
81 static base::LazyInstance< 93 static base::LazyInstance<
82 std::map< ::Window, views::DesktopDragDropClientAuraX11*> >::Leaky 94 std::map< ::Window, views::DesktopDragDropClientAuraX11*> >::Leaky
83 g_live_client_map = LAZY_INSTANCE_INITIALIZER; 95 g_live_client_map = LAZY_INSTANCE_INITIALIZER;
84 96
85 } // namespace 97 } // namespace
86 98
87 namespace views { 99 namespace views {
88 100
89 DesktopDragDropClientAuraX11* 101 DesktopDragDropClientAuraX11*
90 DesktopDragDropClientAuraX11::g_current_drag_drop_client = NULL; 102 DesktopDragDropClientAuraX11::g_current_drag_drop_client = NULL;
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 if (!source_provider_->file_contents_name().empty()) { 627 if (!source_provider_->file_contents_name().empty()) {
616 actions.push_back(atom_cache_.GetAtom(kXdndActionDirectSave)); 628 actions.push_back(atom_cache_.GetAtom(kXdndActionDirectSave));
617 ui::SetStringProperty( 629 ui::SetStringProperty(
618 xwindow_, 630 xwindow_,
619 atom_cache_.GetAtom(kXdndDirectSave0), 631 atom_cache_.GetAtom(kXdndDirectSave0),
620 atom_cache_.GetAtom(ui::Clipboard::kMimeTypeText), 632 atom_cache_.GetAtom(ui::Clipboard::kMimeTypeText),
621 source_provider_->file_contents_name().AsUTF8Unsafe()); 633 source_provider_->file_contents_name().AsUTF8Unsafe());
622 } 634 }
623 ui::SetAtomArrayProperty(xwindow_, "XdndActionList", "ATOM", actions); 635 ui::SetAtomArrayProperty(xwindow_, "XdndActionList", "ATOM", actions);
624 636
637 gfx::ImageSkia drag_image = source_provider_->GetDragImage();
638 if (IsValidDragImage(drag_image)) {
639 CreateDragWidget(drag_image);
640 drag_widget_offset_ = source_provider_->GetDragImageOffset();
641 }
642
625 // It is possible for the DesktopWindowTreeHostX11 to be destroyed during the 643 // It is possible for the DesktopWindowTreeHostX11 to be destroyed during the
626 // move loop, which would also destroy this drag-client. So keep track of 644 // move loop, which would also destroy this drag-client. So keep track of
627 // whether it is alive after the drag ends. 645 // whether it is alive after the drag ends.
628 base::WeakPtr<DesktopDragDropClientAuraX11> alive( 646 base::WeakPtr<DesktopDragDropClientAuraX11> alive(
629 weak_ptr_factory_.GetWeakPtr()); 647 weak_ptr_factory_.GetWeakPtr());
630 648
631 // Windows has a specific method, DoDragDrop(), which performs the entire 649 // Windows has a specific method, DoDragDrop(), which performs the entire
632 // drag. We have to emulate this, so we spin off a nested runloop which will 650 // drag. We have to emulate this, so we spin off a nested runloop which will
633 // track all cursor movement and reroute events to a specific handler. 651 // track all cursor movement and reroute events to a specific handler.
634 move_loop_->SetDragImage(source_provider_->GetDragImage(),
635 source_provider_->GetDragImageOffset());
636 move_loop_->RunMoveLoop(source_window, grab_cursor_); 652 move_loop_->RunMoveLoop(source_window, grab_cursor_);
637 653
638 if (alive) { 654 if (alive) {
639 move_loop_->SetDragImage(gfx::ImageSkia(), gfx::Vector2dF()); 655 drag_widget_.reset();
640 656
641 source_provider_ = NULL; 657 source_provider_ = NULL;
642 g_current_drag_drop_client = NULL; 658 g_current_drag_drop_client = NULL;
643 drag_operation_ = 0; 659 drag_operation_ = 0;
644 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndActionList")); 660 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndActionList"));
645 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom(kXdndDirectSave0)); 661 XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom(kXdndDirectSave0));
646 662
647 return negotiated_operation_; 663 return negotiated_operation_;
648 } 664 }
649 return ui::DragDropTypes::DRAG_NONE; 665 return ui::DragDropTypes::DRAG_NONE;
(...skipping 16 matching lines...) Expand all
666 bool DesktopDragDropClientAuraX11::IsDragDropInProgress() { 682 bool DesktopDragDropClientAuraX11::IsDragDropInProgress() {
667 return !!g_current_drag_drop_client; 683 return !!g_current_drag_drop_client;
668 } 684 }
669 685
670 void DesktopDragDropClientAuraX11::OnWindowDestroyed(aura::Window* window) { 686 void DesktopDragDropClientAuraX11::OnWindowDestroyed(aura::Window* window) {
671 DCHECK_EQ(target_window_, window); 687 DCHECK_EQ(target_window_, window);
672 target_window_ = NULL; 688 target_window_ = NULL;
673 } 689 }
674 690
675 void DesktopDragDropClientAuraX11::OnMouseMovement(XMotionEvent* event) { 691 void DesktopDragDropClientAuraX11::OnMouseMovement(XMotionEvent* event) {
692 gfx::Point screen_point(event->x_root, event->y_root);
693 if (drag_widget_.get()) {
694 drag_widget_->SetBounds(
695 gfx::Rect(screen_point - drag_widget_offset_,
696 drag_widget_->GetWindowBoundsInScreen().size()));
697 drag_widget_->StackAtTop();
698 }
699
676 repeat_mouse_move_timer_.Stop(); 700 repeat_mouse_move_timer_.Stop();
677 ProcessMouseMove(gfx::Point(event->x_root, event->y_root), event->time); 701 ProcessMouseMove(screen_point, event->time);
678 } 702 }
679 703
680 void DesktopDragDropClientAuraX11::OnMouseReleased() { 704 void DesktopDragDropClientAuraX11::OnMouseReleased() {
681 repeat_mouse_move_timer_.Stop(); 705 repeat_mouse_move_timer_.Stop();
682 706
683 if (source_state_ != SOURCE_STATE_OTHER) { 707 if (source_state_ != SOURCE_STATE_OTHER) {
684 // The user has previously released the mouse and is clicking in 708 // The user has previously released the mouse and is clicking in
685 // frustration. 709 // frustration.
686 move_loop_->EndMoveLoop(); 710 move_loop_->EndMoveLoop();
687 return; 711 return;
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after
1047 xev.xclient.format = 32; 1071 xev.xclient.format = 32;
1048 xev.xclient.window = dest_window; 1072 xev.xclient.window = dest_window;
1049 xev.xclient.data.l[0] = xwindow_; 1073 xev.xclient.data.l[0] = xwindow_;
1050 xev.xclient.data.l[1] = 0; 1074 xev.xclient.data.l[1] = 0;
1051 xev.xclient.data.l[2] = CurrentTime; 1075 xev.xclient.data.l[2] = CurrentTime;
1052 xev.xclient.data.l[3] = None; 1076 xev.xclient.data.l[3] = None;
1053 xev.xclient.data.l[4] = None; 1077 xev.xclient.data.l[4] = None;
1054 SendXClientEvent(dest_window, &xev); 1078 SendXClientEvent(dest_window, &xev);
1055 } 1079 }
1056 1080
1081 void DesktopDragDropClientAuraX11::CreateDragWidget(
1082 const gfx::ImageSkia& image) {
1083 Widget* widget = new Widget;
1084 Widget::InitParams params(Widget::InitParams::TYPE_DRAG);
1085 params.opacity = Widget::InitParams::OPAQUE_WINDOW;
1086 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1087 params.accept_events = false;
1088
1089 gfx::Point location = gfx::Screen::GetNativeScreen()->GetCursorScreenPoint() -
1090 drag_widget_offset_;
1091 params.bounds = gfx::Rect(location, image.size());
1092 widget->set_focus_on_creation(false);
1093 widget->set_frame_type(Widget::FRAME_TYPE_FORCE_NATIVE);
1094 widget->Init(params);
1095 widget->SetOpacity(kDragWidgetOpacity);
1096 widget->GetNativeWindow()->SetName("DragWindow");
1097
1098 ImageView* image_view = new ImageView();
1099 image_view->SetImage(image);
1100 image_view->SetBounds(0, 0, image.width(), image.height());
1101 widget->SetContentsView(image_view);
1102 widget->Show();
1103 widget->GetNativeWindow()->layer()->SetFillsBoundsOpaquely(false);
1104
1105 drag_widget_.reset(widget);
1106 }
1107
1108 bool DesktopDragDropClientAuraX11::IsValidDragImage(
1109 const gfx::ImageSkia& image) {
1110 if (image.isNull())
1111 return false;
1112
1113 // Because we need a GL context per window, we do a quick check so that we
1114 // don't make another context if the window would just be displaying a mostly
1115 // transparent image.
1116 const SkBitmap* in_bitmap = image.bitmap();
1117 SkAutoLockPixels in_lock(*in_bitmap);
1118 for (int y = 0; y < in_bitmap->height(); ++y) {
1119 uint32* in_row = in_bitmap->getAddr32(0, y);
1120
1121 for (int x = 0; x < in_bitmap->width(); ++x) {
1122 if (SkColorGetA(in_row[x]) > kMinAlpha)
1123 return true;
1124 }
1125 }
1126
1127 return false;
1128 }
1129
1057 } // namespace views 1130 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698