summaryrefslogtreecommitdiffstats
path: root/ash/drag_drop
diff options
context:
space:
mode:
authormazda@chromium.org <mazda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-26 11:59:04 +0000
committermazda@chromium.org <mazda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-26 11:59:04 +0000
commit0518d0dde990e5382c94bde61e10cd3f3bbf7c27 (patch)
tree7bbe180593b3f2456ae4c4c842a1575a3e3b7cf1 /ash/drag_drop
parent7f219e315a3b6e6b262f75313f52b555632d9317 (diff)
downloadchromium_src-0518d0dde990e5382c94bde61e10cd3f3bbf7c27.zip
chromium_src-0518d0dde990e5382c94bde61e10cd3f3bbf7c27.tar.gz
chromium_src-0518d0dde990e5382c94bde61e10cd3f3bbf7c27.tar.bz2
Support Drag and Drop across displays.
This CL introduces DragDropTracker, which - Makes a dummy window capture events while dragging an item, and - Dispatches mouse events to the window at the pointer location in DragDropController::PreHandleMouseEvent. BUG=136817 Review URL: https://chromiumcodereview.appspot.com/10855159 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@153401 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash/drag_drop')
-rw-r--r--ash/drag_drop/drag_drop_controller.cc43
-rw-r--r--ash/drag_drop/drag_drop_controller.h7
-rw-r--r--ash/drag_drop/drag_drop_controller_unittest.cc4
-rw-r--r--ash/drag_drop/drag_drop_tracker.cc68
-rw-r--r--ash/drag_drop/drag_drop_tracker.h51
-rw-r--r--ash/drag_drop/drag_drop_tracker_unittest.cc212
-rw-r--r--ash/drag_drop/drag_image_view.cc2
7 files changed, 366 insertions, 21 deletions
diff --git a/ash/drag_drop/drag_drop_controller.cc b/ash/drag_drop/drag_drop_controller.cc
index c273bf0..5d44085 100644
--- a/ash/drag_drop/drag_drop_controller.cc
+++ b/ash/drag_drop/drag_drop_controller.cc
@@ -4,6 +4,7 @@
#include "ash/drag_drop/drag_drop_controller.h"
+#include "ash/drag_drop/drag_drop_tracker.h"
#include "ash/drag_drop/drag_image_view.h"
#include "ash/shell.h"
#include "ash/wm/coordinate_conversion.h"
@@ -44,7 +45,6 @@ DragDropController::DragDropController()
drag_data_(NULL),
drag_operation_(0),
drag_window_(NULL),
- drag_drop_in_progress_(false),
should_block_during_drag_drop_(true) {
Shell::GetInstance()->AddEnvEventFilter(this);
}
@@ -57,16 +57,13 @@ DragDropController::~DragDropController() {
}
int DragDropController::StartDragAndDrop(const ui::OSExchangeData& data,
+ aura::RootWindow* root_window,
const gfx::Point& root_location,
int operation) {
- DCHECK(!drag_drop_in_progress_);
- // TODO(oshima): Add CaptureClient client API.
- aura::Window* capture_window =
- aura::client::GetCaptureWindow(Shell::GetPrimaryRootWindow());
- if (capture_window)
- capture_window->ReleaseCapture();
- drag_drop_in_progress_ = true;
+ DCHECK(!IsDragDropInProgress());
+
drag_cursor_ = ui::kCursorPointer;
+ drag_drop_tracker_.reset(new DragDropTracker(root_window));
drag_data_ = &data;
drag_operation_ = operation;
@@ -197,7 +194,7 @@ void DragDropController::DragCancel() {
}
bool DragDropController::IsDragDropInProgress() {
- return drag_drop_in_progress_;
+ return !!drag_drop_tracker_.get();
}
gfx::NativeCursor DragDropController::GetDragCursor() {
@@ -206,7 +203,7 @@ gfx::NativeCursor DragDropController::GetDragCursor() {
bool DragDropController::PreHandleKeyEvent(aura::Window* target,
ui::KeyEvent* event) {
- if (drag_drop_in_progress_ && event->key_code() == ui::VKEY_ESCAPE) {
+ if (IsDragDropInProgress() && event->key_code() == ui::VKEY_ESCAPE) {
DragCancel();
return true;
}
@@ -215,17 +212,23 @@ bool DragDropController::PreHandleKeyEvent(aura::Window* target,
bool DragDropController::PreHandleMouseEvent(aura::Window* target,
ui::MouseEvent* event) {
- if (!drag_drop_in_progress_)
+ if (!IsDragDropInProgress())
return false;
- switch (event->type()) {
+ aura::Window* translated_target = drag_drop_tracker_->GetTarget(*event);
+ if (!translated_target) {
+ DragCancel();
+ return true;
+ }
+ scoped_ptr<ui::MouseEvent> translated_event(
+ drag_drop_tracker_->ConvertMouseEvent(translated_target, *event));
+ switch (translated_event->type()) {
case ui::ET_MOUSE_DRAGGED:
- DragUpdate(target, *event);
+ DragUpdate(translated_target, *translated_event.get());
break;
case ui::ET_MOUSE_RELEASED:
- Drop(target, *event);
+ Drop(translated_target, *translated_event.get());
break;
default:
- // We could reach here if the user drops outside the root window.
// We could also reach here because RootWindow may sometimes generate a
// bunch of fake mouse events
// (aura::RootWindow::PostMouseMoveEventAfterWindowChange).
@@ -238,7 +241,9 @@ ui::TouchStatus DragDropController::PreHandleTouchEvent(
aura::Window* target,
ui::TouchEvent* event) {
// TODO(sad): Also check for the touch-id.
- if (!drag_drop_in_progress_)
+ // TODO(varunjain): Add code for supporting drag-and-drop across displays
+ // (http://crbug.com/114755).
+ if (!IsDragDropInProgress())
return ui::TOUCH_STATUS_UNKNOWN;
switch (event->type()) {
case ui::ET_TOUCH_MOVED:
@@ -277,7 +282,7 @@ void DragDropController::OnImplicitAnimationsCompleted() {
// By the time we finish animation, another drag/drop session may have
// started. We do not want to destroy the drag image in that case.
- if (!drag_drop_in_progress_)
+ if (!IsDragDropInProgress())
drag_image_.reset();
}
@@ -301,7 +306,9 @@ void DragDropController::Cleanup() {
drag_window_->RemoveObserver(this);
drag_window_ = NULL;
drag_data_ = NULL;
- drag_drop_in_progress_ = false;
+ // Cleanup can be called again while deleting DragDropTracker, so use Pass
+ // instead of reset to avoid double free.
+ drag_drop_tracker_.Pass();
}
} // namespace internal
diff --git a/ash/drag_drop/drag_drop_controller.h b/ash/drag_drop/drag_drop_controller.h
index 468ba58..dabcbc1 100644
--- a/ash/drag_drop/drag_drop_controller.h
+++ b/ash/drag_drop/drag_drop_controller.h
@@ -16,6 +16,7 @@
#include "ui/gfx/point.h"
namespace aura {
+class RootWindow;
class Window;
}
@@ -31,6 +32,7 @@ class DragDropControllerTest;
namespace internal {
+class DragDropTracker;
class DragImageView;
class ASH_EXPORT DragDropController
@@ -48,6 +50,7 @@ class ASH_EXPORT DragDropController
// Overridden from aura::client::DragDropClient:
virtual int StartDragAndDrop(const ui::OSExchangeData& data,
+ aura::RootWindow* root_window,
const gfx::Point& root_location,
int operation) OVERRIDE;
virtual void DragUpdate(aura::Window* target,
@@ -95,8 +98,6 @@ class ASH_EXPORT DragDropController
aura::Window* drag_window_;
gfx::Point drag_start_location_;
- bool drag_drop_in_progress_;
-
// Indicates whether the caller should be blocked on a drag/drop session.
// Only be used for tests.
bool should_block_during_drag_drop_;
@@ -104,6 +105,8 @@ class ASH_EXPORT DragDropController
// Closure for quitting nested message loop.
base::Closure quit_closure_;
+ scoped_ptr<ash::internal::DragDropTracker> drag_drop_tracker_;
+
DISALLOW_COPY_AND_ASSIGN(DragDropController);
};
diff --git a/ash/drag_drop/drag_drop_controller_unittest.cc b/ash/drag_drop/drag_drop_controller_unittest.cc
index ca6e368..7740186 100644
--- a/ash/drag_drop/drag_drop_controller_unittest.cc
+++ b/ash/drag_drop/drag_drop_controller_unittest.cc
@@ -127,11 +127,13 @@ class TestDragDropController : public internal::DragDropController {
private:
int StartDragAndDrop(const ui::OSExchangeData& data,
+ aura::RootWindow* root_window,
const gfx::Point& location,
int operation) OVERRIDE {
drag_start_received_ = true;
data.GetString(&drag_string_);
- return DragDropController::StartDragAndDrop(data, location, operation);
+ return DragDropController::StartDragAndDrop(
+ data, root_window, location, operation);
}
void DragUpdate(aura::Window* target,
diff --git a/ash/drag_drop/drag_drop_tracker.cc b/ash/drag_drop/drag_drop_tracker.cc
new file mode 100644
index 0000000..0a04d105
--- /dev/null
+++ b/ash/drag_drop/drag_drop_tracker.cc
@@ -0,0 +1,68 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/drag_drop/drag_drop_tracker.h"
+
+#include "ash/shell.h"
+#include "ash/shell_window_ids.h"
+#include "ash/wm/coordinate_conversion.h"
+#include "ui/aura/root_window.h"
+#include "ui/base/event.h"
+#include "ui/gfx/screen.h"
+
+namespace {
+
+// Creates a window for capturing drag events.
+aura::Window* CreateCaptureWindow(aura::RootWindow* root_window) {
+ aura::Window* window = new aura::Window(NULL);
+ window->SetType(aura::client::WINDOW_TYPE_NORMAL);
+ window->Init(ui::LAYER_NOT_DRAWN);
+ window->SetParent(NULL);
+ window->SetBoundsInScreen(root_window->GetBoundsInScreen(),
+ gfx::Screen::GetDisplayNearestWindow(root_window));
+ window->Show();
+ return window;
+}
+
+} // namespace
+
+namespace ash {
+namespace internal {
+
+DragDropTracker::DragDropTracker(aura::RootWindow* root_window)
+ : capture_window_(CreateCaptureWindow(root_window)) {
+ capture_window_->SetCapture();
+}
+
+DragDropTracker::~DragDropTracker() {
+ capture_window_->ReleaseCapture();
+}
+
+aura::Window* DragDropTracker::GetTarget(const ui::LocatedEvent& event) {
+ std::pair<aura::RootWindow*, gfx::Point> pair =
+ ash::wm::GetRootWindowRelativeToWindow(capture_window_.get(),
+ event.location());
+ return pair.first->GetEventHandlerForPoint(pair.second);
+}
+
+ui::MouseEvent* DragDropTracker::ConvertMouseEvent(
+ aura::Window* target,
+ const ui::MouseEvent& event) {
+ DCHECK(capture_window_.get());
+ std::pair<aura::RootWindow*, gfx::Point> location_pair =
+ ash::wm::GetRootWindowRelativeToWindow(capture_window_.get(),
+ event.location());
+ aura::Window::ConvertPointToTarget(location_pair.first, target,
+ &location_pair.second);
+ std::pair<aura::RootWindow*, gfx::Point> root_location_pair =
+ ash::wm::GetRootWindowRelativeToWindow(capture_window_->GetRootWindow(),
+ event.root_location());
+ return new ui::MouseEvent(event.type(),
+ location_pair.second,
+ root_location_pair.second,
+ event.flags());
+}
+
+} // namespace internal
+} // namespace ash
diff --git a/ash/drag_drop/drag_drop_tracker.h b/ash/drag_drop/drag_drop_tracker.h
new file mode 100644
index 0000000..fa56ed6
--- /dev/null
+++ b/ash/drag_drop/drag_drop_tracker.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_DRAG_DROP_DRAG_DROP_TRACKER_H_
+#define ASH_DRAG_DROP_DRAG_DROP_TRACKER_H_
+
+#include "ash/ash_export.h"
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/base/event.h"
+
+namespace aura {
+class RootWindow;
+class Window;
+}
+
+namespace ash {
+namespace internal {
+
+// Provides functions for handling drag events inside and outside the root
+// window where drag is started. This internally sets up a capture window for
+// tracking drag events outside the root window where drag is initiated.
+// ash/wm/coordinate_conversion.h is used internally and only X11 environment
+// is supported for now.
+class ASH_EXPORT DragDropTracker {
+ public:
+ explicit DragDropTracker(aura::RootWindow* root_window);
+ ~DragDropTracker();
+
+ // Gets the target located at |event| in the coordinates of the root window
+ // given to the constructor.
+ aura::Window* GetTarget(const ui::LocatedEvent& event);
+
+ // Converts the locations of |event| in the coordinates of the root window
+ // given to the constructor to the ones in |target|'s coordinates.
+ // Caller takes ownership of the returned object.
+ ui::MouseEvent* ConvertMouseEvent(aura::Window* target,
+ const ui::MouseEvent& event);
+
+ private:
+ // A window for capturing drag events while dragging.
+ scoped_ptr<aura::Window> capture_window_;
+
+ DISALLOW_COPY_AND_ASSIGN(DragDropTracker);
+};
+
+} // namespace internal
+} // namespace ash
+
+#endif // ASH_DRAG_DROP_DRAG_DROP_TRACKER_H_
diff --git a/ash/drag_drop/drag_drop_tracker_unittest.cc b/ash/drag_drop/drag_drop_tracker_unittest.cc
new file mode 100644
index 0000000..ddc75ba
--- /dev/null
+++ b/ash/drag_drop/drag_drop_tracker_unittest.cc
@@ -0,0 +1,212 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/drag_drop/drag_drop_tracker.h"
+
+#include "ash/shell.h"
+#include "ash/shell_window_ids.h"
+#include "ash/test/ash_test_base.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/aura/root_window.h"
+#include "ui/aura/test/test_windows.h"
+#include "ui/aura/window.h"
+
+namespace ash {
+namespace test {
+
+class DragDropTrackerTest : public test::AshTestBase {
+ public:
+ virtual void SetUp() OVERRIDE {
+ AshTestBase::SetUp();
+ UpdateDisplay("0+0-200x200,0+201-200x200");
+ }
+
+ static aura::Window* CreateTestWindow(const gfx::Rect& bounds,
+ aura::Window* parent) {
+ static int window_id = 0;
+ return aura::test::CreateTestWindowWithDelegate(
+ new aura::test::TestWindowDelegate,
+ window_id++,
+ bounds,
+ parent);
+ }
+
+ static aura::Window* GetTarget(aura::RootWindow* root_window,
+ const gfx::Point& location) {
+ scoped_ptr<internal::DragDropTracker> tracker(
+ new internal::DragDropTracker(root_window));
+ ui::MouseEvent e(ui::ET_MOUSE_DRAGGED,
+ location,
+ location,
+ ui::EF_NONE);
+ aura::Window* target = tracker->GetTarget(e);
+ return target;
+ }
+
+ static ui::MouseEvent* ConvertMouseEvent(aura::RootWindow* root_window,
+ aura::Window* target,
+ const ui::MouseEvent& event) {
+ scoped_ptr<internal::DragDropTracker> tracker(
+ new internal::DragDropTracker(root_window));
+ ui::MouseEvent* converted = tracker->ConvertMouseEvent(target, event);
+ return converted;
+ }
+};
+
+// TODO(mazda): Remove this once ash/wm/coordinate_conversion.h supports
+// non-X11 platforms.
+#if defined(USE_X11)
+#define MAYBE_GetTarget GetTarget
+#else
+#define MAYBE_GetTarget DISABLED_GetTarget
+#endif
+
+TEST_F(DragDropTrackerTest, MAYBE_GetTarget) {
+ Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
+ EXPECT_EQ(2U, root_windows.size());
+
+ aura::Window* default_container0 =
+ ash::Shell::GetContainer(root_windows[0],
+ ash::internal::kShellWindowId_DefaultContainer);
+ EXPECT_TRUE(NULL != default_container0);
+
+ scoped_ptr<aura::Window> window0(
+ CreateTestWindow(gfx::Rect(0, 0, 100, 100), default_container0));
+ window0->Show();
+
+ aura::Window* default_container1 =
+ ash::Shell::GetContainer(root_windows[1],
+ ash::internal::kShellWindowId_DefaultContainer);
+ EXPECT_TRUE(NULL != default_container1);
+
+ scoped_ptr<aura::Window> window1(
+ CreateTestWindow(gfx::Rect(100, 100, 100, 100), default_container1));
+ window1->Show();
+
+ // Start tracking from the RootWindow0 and check the point on RootWindow0 that
+ // |window0| covers.
+ EXPECT_EQ(window0.get(), GetTarget(root_windows[0], gfx::Point(50, 50)));
+
+ // Start tracking from the RootWindow0 and check the point on RootWindow0 that
+ // neither |window0| nor |window1| covers.
+ EXPECT_NE(window0.get(), GetTarget(root_windows[0], gfx::Point(150, 150)));
+ EXPECT_NE(window1.get(), GetTarget(root_windows[0], gfx::Point(150, 150)));
+
+ // Start tracking from the RootWindow0 and check the point on RootWindow1 that
+ // |window1| covers.
+ EXPECT_EQ(window1.get(), GetTarget(root_windows[0], gfx::Point(150, 350)));
+
+ // Start tracking from the RootWindow0 and check the point on RootWindow1 that
+ // neither |window0| nor |window1| covers.
+ EXPECT_NE(window0.get(), GetTarget(root_windows[0], gfx::Point(50, 250)));
+ EXPECT_NE(window1.get(), GetTarget(root_windows[0], gfx::Point(50, 250)));
+
+ // Start tracking from the RootWindow1 and check the point on RootWindow0 that
+ // |window0| covers.
+ EXPECT_EQ(window0.get(), GetTarget(root_windows[1], gfx::Point(50, -150)));
+
+ // Start tracking from the RootWindow1 and check the point on RootWindow0 that
+ // neither |window0| nor |window1| covers.
+ EXPECT_NE(window0.get(), GetTarget(root_windows[1], gfx::Point(150, -50)));
+ EXPECT_NE(window1.get(), GetTarget(root_windows[1], gfx::Point(150, -50)));
+
+ // Start tracking from the RootWindow1 and check the point on RootWindow1 that
+ // |window1| covers.
+ EXPECT_EQ(window1.get(), GetTarget(root_windows[1], gfx::Point(150, 150)));
+
+ // Start tracking from the RootWindow1 and check the point on RootWindow1 that
+ // neither |window0| nor |window1| covers.
+ EXPECT_NE(window0.get(), GetTarget(root_windows[1], gfx::Point(50, 50)));
+ EXPECT_NE(window1.get(), GetTarget(root_windows[1], gfx::Point(50, 50)));
+}
+
+// TODO(mazda): Remove this once ash/wm/coordinate_conversion.h supports
+// non-X11 platforms.
+#if defined(USE_X11)
+#define MAYBE_ConvertMouseEvent ConvertMouseEvent
+#else
+#define MAYBE_ConvertMouseEvent DISABLED_ConvertMouseEvent
+#endif
+
+TEST_F(DragDropTrackerTest, MAYBE_ConvertMouseEvent) {
+ Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
+ EXPECT_EQ(2U, root_windows.size());
+
+ aura::Window* default_container0 =
+ ash::Shell::GetContainer(root_windows[0],
+ ash::internal::kShellWindowId_DefaultContainer);
+ EXPECT_TRUE(NULL != default_container0);
+
+ scoped_ptr<aura::Window> window0(
+ CreateTestWindow(gfx::Rect(0, 0, 100, 100), default_container0));
+ window0->Show();
+
+ aura::Window* default_container1 =
+ ash::Shell::GetContainer(root_windows[1],
+ ash::internal::kShellWindowId_DefaultContainer);
+ EXPECT_TRUE(NULL != default_container1);
+
+ scoped_ptr<aura::Window> window1(
+ CreateTestWindow(gfx::Rect(100, 100, 100, 100), default_container1));
+ window1->Show();
+
+ // Start tracking from the RootWindow0 and converts the mouse event into
+ // |window0|'s coodinates.
+ ui::MouseEvent original00(ui::ET_MOUSE_DRAGGED,
+ gfx::Point(50, 50),
+ gfx::Point(50, 50),
+ ui::EF_NONE);
+ scoped_ptr<ui::MouseEvent> converted00(ConvertMouseEvent(root_windows[0],
+ window0.get(),
+ original00));
+ EXPECT_EQ(original00.type(), converted00->type());
+ EXPECT_EQ(gfx::Point(50, 50), converted00->location());
+ EXPECT_EQ(gfx::Point(50, 50), converted00->root_location());
+ EXPECT_EQ(original00.flags(), converted00->flags());
+
+ // Start tracking from the RootWindow0 and converts the mouse event into
+ // |window1|'s coodinates.
+ ui::MouseEvent original01(ui::ET_MOUSE_DRAGGED,
+ gfx::Point(150, 350),
+ gfx::Point(150, 350),
+ ui::EF_NONE);
+ scoped_ptr<ui::MouseEvent> converted01(ConvertMouseEvent(root_windows[0],
+ window1.get(),
+ original01));
+ EXPECT_EQ(original01.type(), converted01->type());
+ EXPECT_EQ(gfx::Point(50, 50), converted01->location());
+ EXPECT_EQ(gfx::Point(150, 150), converted01->root_location());
+ EXPECT_EQ(original01.flags(), converted01->flags());
+
+ // Start tracking from the RootWindow1 and converts the mouse event into
+ // |window0|'s coodinates.
+ ui::MouseEvent original10(ui::ET_MOUSE_DRAGGED,
+ gfx::Point(50, -150),
+ gfx::Point(50, -150),
+ ui::EF_NONE);
+ scoped_ptr<ui::MouseEvent> converted10(ConvertMouseEvent(root_windows[1],
+ window0.get(),
+ original10));
+ EXPECT_EQ(original10.type(), converted10->type());
+ EXPECT_EQ(gfx::Point(50, 50), converted10->location());
+ EXPECT_EQ(gfx::Point(50, 50), converted10->root_location());
+ EXPECT_EQ(original10.flags(), converted10->flags());
+
+ // Start tracking from the RootWindow1 and converts the mouse event into
+ // |window1|'s coodinates.
+ ui::MouseEvent original11(ui::ET_MOUSE_DRAGGED,
+ gfx::Point(150, 150),
+ gfx::Point(150, 150),
+ ui::EF_NONE);
+ scoped_ptr<ui::MouseEvent> converted11(ConvertMouseEvent(root_windows[1],
+ window1.get(),
+ original11));
+ EXPECT_EQ(original11.type(), converted11->type());
+ EXPECT_EQ(gfx::Point(50, 50), converted11->location());
+ EXPECT_EQ(gfx::Point(150, 150), converted11->root_location());
+ EXPECT_EQ(original11.flags(), converted11->flags());
+}
+
+} // namespace test
+} // namespace aura
diff --git a/ash/drag_drop/drag_image_view.cc b/ash/drag_drop/drag_image_view.cc
index 7a138f3..b6a32f8 100644
--- a/ash/drag_drop/drag_image_view.cc
+++ b/ash/drag_drop/drag_image_view.cc
@@ -5,6 +5,7 @@
#include "ash/drag_drop/drag_image_view.h"
#include "ash/wm/shadow_types.h"
+#include "ui/aura/window.h"
#include "ui/views/widget/widget.h"
namespace ash {
@@ -23,6 +24,7 @@ Widget* CreateDragWidget() {
params.transparent = true;
drag_widget->Init(params);
drag_widget->SetOpacity(0xFF);
+ drag_widget->GetNativeWindow()->set_owned_by_parent(false);
SetShadowType(drag_widget->GetNativeView(), SHADOW_TYPE_NONE);
return drag_widget;
}