diff options
author | pkotwicz@chromium.org <pkotwicz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-12 18:16:27 +0000 |
---|---|---|
committer | pkotwicz@chromium.org <pkotwicz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-12 18:18:13 +0000 |
commit | a67636db9e1175c83cb861d3fdcfdcb1783935af (patch) | |
tree | 9d7f297b87a00c6c57583d3e6e2607a67145eb9a /ui/views | |
parent | e6f679c22fd36ec8d5b0b9cb18e31cd544232864 (diff) | |
download | chromium_src-a67636db9e1175c83cb861d3fdcfdcb1783935af.zip chromium_src-a67636db9e1175c83cb861d3fdcfdcb1783935af.tar.gz chromium_src-a67636db9e1175c83cb861d3fdcfdcb1783935af.tar.bz2 |
[Refactor]: Move drag_widget_ out of X11WholeScreenMoveLoop
BUG=None
Test=None
Review URL: https://codereview.chromium.org/452413002
Cr-Commit-Position: refs/heads/master@{#289026}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@289026 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/views')
6 files changed, 92 insertions, 99 deletions
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc index cdaecb7..b64de59 100644 --- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc +++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc @@ -9,6 +9,7 @@ #include "base/event_types.h" #include "base/lazy_instance.h" #include "base/message_loop/message_loop.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" #include "ui/base/clipboard/clipboard.h" @@ -20,9 +21,13 @@ #include "ui/base/x/x11_util.h" #include "ui/events/event.h" #include "ui/events/platform/platform_event_source.h" +#include "ui/gfx/image/image_skia.h" +#include "ui/gfx/screen.h" +#include "ui/views/controls/image_view.h" #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h" #include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h" #include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h" +#include "ui/views/widget/widget.h" #include "ui/wm/public/drag_drop_client.h" #include "ui/wm/public/drag_drop_delegate.h" @@ -78,6 +83,13 @@ const int kEndMoveLoopTimeoutMs = 1000; // stacking order has changed and |source_current_window_| needs to be updated. const int kRepeatMouseMoveTimeoutMs = 350; +// The minimum alpha before we declare a pixel transparent when searching in +// our source image. +const uint32 kMinAlpha = 32; + +// |drag_widget_|'s opacity. +const unsigned char kDragWidgetOpacity = 0xc0; + static base::LazyInstance< std::map< ::Window, views::DesktopDragDropClientAuraX11*> >::Leaky g_live_client_map = LAZY_INSTANCE_INITIALIZER; @@ -622,6 +634,12 @@ int DesktopDragDropClientAuraX11::StartDragAndDrop( } ui::SetAtomArrayProperty(xwindow_, "XdndActionList", "ATOM", actions); + gfx::ImageSkia drag_image = source_provider_->GetDragImage(); + if (IsValidDragImage(drag_image)) { + CreateDragWidget(drag_image); + drag_widget_offset_ = source_provider_->GetDragImageOffset(); + } + // It is possible for the DesktopWindowTreeHostX11 to be destroyed during the // move loop, which would also destroy this drag-client. So keep track of // whether it is alive after the drag ends. @@ -631,12 +649,10 @@ int DesktopDragDropClientAuraX11::StartDragAndDrop( // Windows has a specific method, DoDragDrop(), which performs the entire // drag. We have to emulate this, so we spin off a nested runloop which will // track all cursor movement and reroute events to a specific handler. - move_loop_->SetDragImage(source_provider_->GetDragImage(), - source_provider_->GetDragImageOffset()); move_loop_->RunMoveLoop(source_window, grab_cursor_); if (alive) { - move_loop_->SetDragImage(gfx::ImageSkia(), gfx::Vector2dF()); + drag_widget_.reset(); source_provider_ = NULL; g_current_drag_drop_client = NULL; @@ -673,8 +689,16 @@ void DesktopDragDropClientAuraX11::OnWindowDestroyed(aura::Window* window) { } void DesktopDragDropClientAuraX11::OnMouseMovement(XMotionEvent* event) { + gfx::Point screen_point(event->x_root, event->y_root); + if (drag_widget_.get()) { + drag_widget_->SetBounds( + gfx::Rect(screen_point - drag_widget_offset_, + drag_widget_->GetWindowBoundsInScreen().size())); + drag_widget_->StackAtTop(); + } + repeat_mouse_move_timer_.Stop(); - ProcessMouseMove(gfx::Point(event->x_root, event->y_root), event->time); + ProcessMouseMove(screen_point, event->time); } void DesktopDragDropClientAuraX11::OnMouseReleased() { @@ -1054,4 +1078,53 @@ void DesktopDragDropClientAuraX11::SendXdndDrop(::Window dest_window) { SendXClientEvent(dest_window, &xev); } +void DesktopDragDropClientAuraX11::CreateDragWidget( + const gfx::ImageSkia& image) { + Widget* widget = new Widget; + Widget::InitParams params(Widget::InitParams::TYPE_DRAG); + params.opacity = Widget::InitParams::OPAQUE_WINDOW; + params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + params.accept_events = false; + + gfx::Point location = gfx::Screen::GetNativeScreen()->GetCursorScreenPoint() - + drag_widget_offset_; + params.bounds = gfx::Rect(location, image.size()); + widget->set_focus_on_creation(false); + widget->set_frame_type(Widget::FRAME_TYPE_FORCE_NATIVE); + widget->Init(params); + widget->SetOpacity(kDragWidgetOpacity); + widget->GetNativeWindow()->SetName("DragWindow"); + + ImageView* image_view = new ImageView(); + image_view->SetImage(image); + image_view->SetBounds(0, 0, image.width(), image.height()); + widget->SetContentsView(image_view); + widget->Show(); + widget->GetNativeWindow()->layer()->SetFillsBoundsOpaquely(false); + + drag_widget_.reset(widget); +} + +bool DesktopDragDropClientAuraX11::IsValidDragImage( + const gfx::ImageSkia& image) { + if (image.isNull()) + return false; + + // Because we need a GL context per window, we do a quick check so that we + // don't make another context if the window would just be displaying a mostly + // transparent image. + const SkBitmap* in_bitmap = image.bitmap(); + SkAutoLockPixels in_lock(*in_bitmap); + for (int y = 0; y < in_bitmap->height(); ++y) { + uint32* in_row = in_bitmap->getAddr32(0, y); + + for (int x = 0; x < in_bitmap->width(); ++x) { + if (SkColorGetA(in_row[x]) > kMinAlpha) + return true; + } + } + + return false; +} + } // namespace views diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h index 3a77f80..8d30153 100644 --- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h +++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h @@ -29,6 +29,7 @@ class DragDropDelegate; } namespace gfx { +class ImageSkia; class Point; } @@ -42,6 +43,7 @@ class SelectionFormatMap; namespace views { class DesktopNativeCursorManager; +class Widget; class X11MoveLoop; // Implements drag and drop on X11 for aura. On one side, this class takes raw @@ -184,6 +186,13 @@ class VIEWS_EXPORT DesktopDragDropClientAuraX11 unsigned long event_time); void SendXdndDrop(::Window dest_window); + // Creates a widget for the user to drag around. + void CreateDragWidget(const gfx::ImageSkia& image); + + // Returns true if |image| has any visible regions (defined as having a pixel + // with alpha > 32). + bool IsValidDragImage(const gfx::ImageSkia& image); + // A nested message loop that notifies this object of events through the // X11MoveLoopDelegate interface. scoped_ptr<X11MoveLoop> move_loop_; @@ -254,6 +263,12 @@ class VIEWS_EXPORT DesktopDragDropClientAuraX11 // released. base::OneShotTimer<DesktopDragDropClientAuraX11> end_move_loop_timer_; + // Widget that the user drags around. May be NULL. + scoped_ptr<Widget> drag_widget_; + + // The offset of |drag_widget_| relative to the mouse position. + gfx::Vector2d drag_widget_offset_; + // We use these cursors while dragging. gfx::NativeCursor grab_cursor_; gfx::NativeCursor copy_grab_cursor_; diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc index b911bc4..1008289 100644 --- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc +++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc @@ -90,8 +90,6 @@ class TestMoveLoop : public X11MoveLoop { gfx::NativeCursor cursor) OVERRIDE; virtual void UpdateCursor(gfx::NativeCursor cursor) OVERRIDE; virtual void EndMoveLoop() OVERRIDE; - virtual void SetDragImage(const gfx::ImageSkia& image, - const gfx::Vector2dF& offset) OVERRIDE; private: // Not owned. @@ -240,10 +238,6 @@ void TestMoveLoop::EndMoveLoop() { } } -void TestMoveLoop::SetDragImage(const gfx::ImageSkia& image, - const gfx::Vector2dF& offset) { -} - /////////////////////////////////////////////////////////////////////////////// // TestDragDropClient diff --git a/ui/views/widget/desktop_aura/x11_move_loop.h b/ui/views/widget/desktop_aura/x11_move_loop.h index b8f3d97..102c866 100644 --- a/ui/views/widget/desktop_aura/x11_move_loop.h +++ b/ui/views/widget/desktop_aura/x11_move_loop.h @@ -27,10 +27,6 @@ class X11MoveLoop { // Ends the move loop that's currently in progress. virtual void EndMoveLoop() = 0; - - // Sets an image to be used during the drag. - virtual void SetDragImage(const gfx::ImageSkia& image, - const gfx::Vector2dF& offset) = 0; }; } // namespace views diff --git a/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc b/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc index 6c20841..76a5618 100644 --- a/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc +++ b/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc @@ -5,13 +5,10 @@ #include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h" #include <X11/Xlib.h> -// Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class. -#undef RootWindow #include "base/bind.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" -#include "third_party/skia/include/core/SkBitmap.h" #include "ui/aura/env.h" #include "ui/aura/window.h" #include "ui/aura/window_event_dispatcher.h" @@ -23,19 +20,11 @@ #include "ui/events/platform/scoped_event_dispatcher.h" #include "ui/events/platform/x11/x11_event_source.h" #include "ui/gfx/point_conversions.h" -#include "ui/gfx/screen.h" -#include "ui/views/controls/image_view.h" -#include "ui/views/widget/widget.h" namespace views { namespace { -// The minimum alpha before we declare a pixel transparent when searching in -// our source image. -const uint32 kMinAlpha = 32; -const unsigned char kDragWidgetOpacity = 0xc0; - class ScopedCapturer { public: explicit ScopedCapturer(aura::WindowTreeHost* host) @@ -100,13 +89,6 @@ uint32_t X11WholeScreenMoveLoop::DispatchEvent(const ui::PlatformEvent& event) { // keyboard focus even though we took pointer grab. switch (xev->type) { case MotionNotify: { - if (drag_widget_.get()) { - gfx::Screen* screen = gfx::Screen::GetNativeScreen(); - gfx::Point location = gfx::ToFlooredPoint( - screen->GetCursorScreenPoint() - drag_offset_); - drag_widget_->SetBounds(gfx::Rect(location, drag_image_.size())); - drag_widget_->StackAtTop(); - } last_xmotion_ = xev->xmotion; if (!weak_factory_.HasWeakPtrs()) { // Post a task to dispatch mouse movement event when control returns to @@ -206,8 +188,6 @@ bool X11WholeScreenMoveLoop::RunMoveLoop(aura::Window* source, nested_dispatcher_.Pass(); nested_dispatcher_ = ui::PlatformEventSource::GetInstance()->OverrideDispatcher(this); - if (!drag_image_.isNull() && CheckIfIconValid()) - CreateDragImageWindow(); // We are handling a mouse drag outside of the aura::RootWindow system. We // must manually make aura think that the mouse button is pressed so that we @@ -266,7 +246,6 @@ void X11WholeScreenMoveLoop::EndMoveLoop() { // Restore the previous dispatcher. nested_dispatcher_.reset(); - drag_widget_.reset(); delegate_->OnMoveLoopEnded(); XDestroyWindow(display, grab_input_window_); grab_input_window_ = None; @@ -275,12 +254,6 @@ void X11WholeScreenMoveLoop::EndMoveLoop() { quit_closure_.Run(); } -void X11WholeScreenMoveLoop::SetDragImage(const gfx::ImageSkia& image, - const gfx::Vector2dF& offset) { - drag_image_ = image; - drag_offset_ = offset; -} - bool X11WholeScreenMoveLoop::GrabPointerAndKeyboard(gfx::NativeCursor cursor) { XDisplay* display = gfx::GetXDisplay(); XGrabServer(display); @@ -342,48 +315,4 @@ Window X11WholeScreenMoveLoop::CreateDragInputWindow(XDisplay* display) { return window; } -void X11WholeScreenMoveLoop::CreateDragImageWindow() { - Widget* widget = new Widget; - Widget::InitParams params(Widget::InitParams::TYPE_DRAG); - params.opacity = Widget::InitParams::OPAQUE_WINDOW; - params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.accept_events = false; - - gfx::Point location = gfx::ToFlooredPoint( - gfx::Screen::GetNativeScreen()->GetCursorScreenPoint() - drag_offset_); - params.bounds = gfx::Rect(location, drag_image_.size()); - widget->set_focus_on_creation(false); - widget->set_frame_type(Widget::FRAME_TYPE_FORCE_NATIVE); - widget->Init(params); - widget->SetOpacity(kDragWidgetOpacity); - widget->GetNativeWindow()->SetName("DragWindow"); - - ImageView* image = new ImageView(); - image->SetImage(drag_image_); - image->SetBounds(0, 0, drag_image_.width(), drag_image_.height()); - widget->SetContentsView(image); - widget->Show(); - widget->GetNativeWindow()->layer()->SetFillsBoundsOpaquely(false); - - drag_widget_.reset(widget); -} - -bool X11WholeScreenMoveLoop::CheckIfIconValid() { - // Because we need a GL context per window, we do a quick check so that we - // don't make another context if the window would just be displaying a mostly - // transparent image. - const SkBitmap* in_bitmap = drag_image_.bitmap(); - SkAutoLockPixels in_lock(*in_bitmap); - for (int y = 0; y < in_bitmap->height(); ++y) { - uint32* in_row = in_bitmap->getAddr32(0, y); - - for (int x = 0; x < in_bitmap->width(); ++x) { - if (SkColorGetA(in_row[x]) > kMinAlpha) - return true; - } - } - - return false; -} - } // namespace views diff --git a/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h b/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h index e4a8adad..b82cb58 100644 --- a/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h +++ b/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h @@ -46,8 +46,6 @@ class X11WholeScreenMoveLoop : public X11MoveLoop, gfx::NativeCursor cursor) OVERRIDE; virtual void UpdateCursor(gfx::NativeCursor cursor) OVERRIDE; virtual void EndMoveLoop() OVERRIDE; - virtual void SetDragImage(const gfx::ImageSkia& image, - const gfx::Vector2dF& offset) OVERRIDE; private: // Grabs the pointer and keyboard, setting the mouse cursor to |cursor|. @@ -57,13 +55,6 @@ class X11WholeScreenMoveLoop : public X11MoveLoop, // Creates an input-only window to be used during the drag. Window CreateDragInputWindow(XDisplay* display); - // Creates a window to show the drag image during the drag. - void CreateDragImageWindow(); - - // Checks to see if |in_image| is an image that has any visible regions - // (defined as having a pixel with alpha > 32). If so, return true. - bool CheckIfIconValid(); - // Dispatch mouse movement event to |delegate_| in a posted task. void DispatchMouseMovement(); @@ -89,11 +80,6 @@ class X11WholeScreenMoveLoop : public X11MoveLoop, // Keeps track of whether we still have a pointer grab at the end of the loop. bool has_grab_; - // A Widget is created during the drag if there is an image available to be - // used during the drag. - scoped_ptr<Widget> drag_widget_; - gfx::ImageSkia drag_image_; - gfx::Vector2dF drag_offset_; XMotionEvent last_xmotion_; base::WeakPtrFactory<X11WholeScreenMoveLoop> weak_factory_; |