diff options
21 files changed, 529 insertions, 54 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp index 69a4917..d949329 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -603,8 +603,10 @@ ], }], ['OS=="win"', { - # TODO(zork): fix this test to build on Windows. See: crosbug.com/26906 'sources/': [ + # TODO(win_ash): implement DragDropController::StartDragAndDrop + ['exclude', 'drag_drop/drag_drop_controller_unittest.cc'], + # TODO(zork): fix this test to build on Windows. See: crosbug.com/26906 ['exclude', 'focus_cycler_unittest.cc'], ], }], diff --git a/ash/drag_drop/drag_drop_controller.cc b/ash/drag_drop/drag_drop_controller.cc index cf6135e..4248099 100644 --- a/ash/drag_drop/drag_drop_controller.cc +++ b/ash/drag_drop/drag_drop_controller.cc @@ -106,6 +106,17 @@ int DragDropController::StartDragAndDrop( if (IsDragDropInProgress()) return 0; +#if defined(OS_WIN) + // TODO(win_ash): need to figure out how this will work in Metro, since + // OSExchangeDataProviderAura isn't used in Windows builds. Two alternatives: + // 1) Use OSExchangeDataProviderAura in Ash and OSExchangeDataProviderWin + // elsewhere. This will complicate creating an ui::OSExchangeData to pass + // in more context. + // 2) Add methods to get the image and offset in the base interface of these + // implementations to get to this data here. + NOTIMPLEMENTED(); + return 0; +#else const ui::OSExchangeDataProviderAura& provider = static_cast<const ui::OSExchangeDataProviderAura&>(data.provider()); // We do not support touch drag/drop without a drag image. @@ -180,6 +191,7 @@ int DragDropController::StartDragAndDrop( drag_source_window_->RemoveObserver(this); drag_source_window_ = NULL; } +#endif return drag_operation_; } diff --git a/ash/drag_drop/drag_drop_controller_unittest.cc b/ash/drag_drop/drag_drop_controller_unittest.cc index 14a25c6..06969eb 100644 --- a/ash/drag_drop/drag_drop_controller_unittest.cc +++ b/ash/drag_drop/drag_drop_controller_unittest.cc @@ -16,8 +16,8 @@ #include "ui/base/clipboard/clipboard.h" #include "ui/base/clipboard/scoped_clipboard_writer.h" #include "ui/base/dragdrop/drag_drop_types.h" +#include "ui/base/dragdrop/drag_utils.h" #include "ui/base/dragdrop/os_exchange_data.h" -#include "ui/base/dragdrop/os_exchange_data_provider_aura.h" #include "ui/base/events/event.h" #include "ui/base/gestures/gesture_types.h" #include "ui/base/ui_base_switches.h" @@ -73,12 +73,13 @@ class DragTestView : public views::View { void WriteDragData(const gfx::Point& p, OSExchangeData* data) OVERRIDE { data->SetString(UTF8ToUTF16("I am being dragged")); - ui::OSExchangeDataProviderAura& provider = - static_cast<ui::OSExchangeDataProviderAura&>(data->provider()); gfx::ImageSkiaRep* image = new gfx::ImageSkiaRep( gfx::Size(10, 20), ui::SCALE_FACTOR_100P); gfx::ImageSkia* image_skia = new gfx::ImageSkia(*image); - provider.set_drag_image(*image_skia); + + drag_utils::SetDragImageOnDataObject( + *image_skia, gfx::Size(image_skia->width(), image_skia->height()), + gfx::Vector2d(), data); } bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE { diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc index 6947e84..a88f550 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc @@ -546,7 +546,7 @@ class BookmarkBarViewTest5 : public BookmarkBarViewEventTestBase { // Drop the item so that it's now the second item. views::MenuItemView* target_menu = bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(1); - gfx::Point loc(1, target_menu->height() - 1); + gfx::Point loc(1, target_menu->height() - 2); views::View::ConvertPointToScreen(target_menu, &loc); ui_controls::SendMouseMove(loc.x(), loc.y()); diff --git a/chrome/test/base/view_event_test_base.cc b/chrome/test/base/view_event_test_base.cc index f3948d1..28a951e 100644 --- a/chrome/test/base/view_event_test_base.cc +++ b/chrome/test/base/view_event_test_base.cc @@ -8,12 +8,14 @@ #include "base/bind_helpers.h" #include "base/message_loop.h" #include "base/string_number_conversions.h" +#include "chrome/browser/ui/views/chrome_views_delegate.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/browser_thread.h" #include "ui/base/ime/text_input_test_support.h" #include "ui/compositor/test/compositor_test_support.h" #include "ui/ui_controls/ui_controls.h" #include "ui/views/view.h" +#include "ui/views/widget/desktop_aura/desktop_screen.h" #include "ui/views/widget/widget.h" #if defined(USE_ASH) @@ -88,8 +90,17 @@ void ViewEventTestBase::SetUp() { ui::TextInputTestSupport::Initialize(); ui::CompositorTestSupport::Initialize(); #if defined(USE_ASH) +#if defined(OS_WIN) + // http://crbug.com/154081 use ash::Shell code path below on win_ash bots when + // interactive_ui_tests is brought up on that platform. + views::ViewsDelegate::views_delegate = new ChromeViewsDelegate; + + gfx::Screen::SetScreenInstance( + gfx::SCREEN_TYPE_NATIVE, views::CreateDesktopScreen()); +#else ash::Shell::CreateInstance(new ash::test::TestShellDelegate()); #endif +#endif window_ = views::Widget::CreateWindow(this); } @@ -104,8 +115,13 @@ void ViewEventTestBase::TearDown() { window_ = NULL; } #if defined(USE_ASH) +#if defined(OS_WIN) + delete views::ViewsDelegate::views_delegate; + views::ViewsDelegate::views_delegate = NULL; +#else ash::Shell::DeleteInstance(); #endif +#endif #if defined(USE_AURA) aura::Env::DeleteInstance(); #endif @@ -144,8 +160,14 @@ void ViewEventTestBase::StartMessageLoopAndRunTest() { window_->Show(); // Make sure the window is the foreground window, otherwise none of the // mouse events are going to be targeted correctly. -#if defined(OS_WIN) && !defined(USE_AURA) - SetForegroundWindow(window_->GetNativeWindow()); +#if defined(OS_WIN) +#if defined(USE_AURA) + HWND window = + window_->GetNativeWindow()->GetRootWindow()->GetAcceleratedWidget(); +#else + HWND window = window_->GetNativeWindow(); +#endif + SetForegroundWindow(window); #endif // Flush any pending events to make sure we start with a clean slate. diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc index bf881e3..dde8d86 100644 --- a/content/browser/web_contents/web_contents_view_aura.cc +++ b/content/browser/web_contents/web_contents_view_aura.cc @@ -33,16 +33,21 @@ #include "ui/aura/window_observer.h" #include "ui/base/clipboard/custom_data_helper.h" #include "ui/base/dragdrop/drag_drop_types.h" +#include "ui/base/dragdrop/drag_utils.h" #include "ui/base/dragdrop/os_exchange_data.h" -#include "ui/base/dragdrop/os_exchange_data_provider_aura.h" #include "ui/base/events/event.h" #include "ui/base/events/event_utils.h" #include "ui/base/hit_test.h" #include "ui/compositor/layer.h" #include "ui/compositor/scoped_layer_animation_settings.h" +#include "ui/gfx/image/image_skia.h" #include "ui/gfx/screen.h" #include "webkit/glue/webdropdata.h" +#if defined(OS_WIN) +#include "ui/base/clipboard/clipboard_util_win.h" +#endif + namespace content { WebContentsView* CreateWebContentsView( WebContentsImpl* web_contents, @@ -128,9 +133,9 @@ class WebDragSourceAura : public MessageLoopForUI::Observer, DISALLOW_COPY_AND_ASSIGN(WebDragSourceAura); }; -// Utility to fill a ui::OSExchangeDataProviderAura object from WebDropData. +// Utility to fill a ui::OSExchangeDataProvider object from WebDropData. void PrepareDragData(const WebDropData& drop_data, - ui::OSExchangeDataProviderAura* provider) { + ui::OSExchangeData::Provider* provider) { if (!drop_data.text.string().empty()) provider->SetString(drop_data.text.string()); if (drop_data.url.is_valid()) @@ -152,8 +157,13 @@ void PrepareDragData(const WebDropData& drop_data, if (!drop_data.custom_data.empty()) { Pickle pickle; ui::WriteCustomDataToPickle(drop_data.custom_data, &pickle); +#if defined(OS_WIN) + provider->SetPickledData( + ui::ClipboardUtil::GetWebCustomDataFormat()->cfFormat, pickle); +#else provider->SetPickledData(ui::Clipboard::GetWebCustomDataFormatType(), pickle); +#endif } } @@ -193,8 +203,13 @@ void PrepareWebDropData(WebDropData* drop_data, } Pickle pickle; +#if defined(OS_WIN) + if (data.GetPickledData(ui::ClipboardUtil::GetWebCustomDataFormat()->cfFormat, + &pickle)) +#else if (data.GetPickledData(ui::Clipboard::GetWebCustomDataFormatType(), &pickle)) +#endif ui::ReadCustomDataIntoMap(pickle.data(), pickle.size(), &drop_data->custom_data); } @@ -672,13 +687,15 @@ void WebContentsViewAura::StartDragging( if (!aura::client::GetDragDropClient(root_window)) return; - ui::OSExchangeDataProviderAura* provider = new ui::OSExchangeDataProviderAura; + ui::OSExchangeData::Provider* provider = ui::OSExchangeData::CreateProvider(); PrepareDragData(drop_data, provider); + + ui::OSExchangeData data(provider); // takes ownership of |provider|. + if (!image.isNull()) { - provider->set_drag_image(image); - provider->set_drag_image_offset(image_offset); + drag_utils::SetDragImageOnDataObject(image, + gfx::Size(image.width(), image.height()), image_offset, &data); } - ui::OSExchangeData data(provider); // takes ownership of |provider|. scoped_ptr<WebDragSourceAura> drag_source( new WebDragSourceAura(GetNativeView(), web_contents_)); diff --git a/ui/aura/ui_controls_win.cc b/ui/aura/ui_controls_win.cc index a28d553..49e5fe8 100644 --- a/ui/aura/ui_controls_win.cc +++ b/ui/aura/ui_controls_win.cc @@ -14,8 +14,7 @@ namespace aura { namespace { class UIControlsWin : public ui_controls::UIControlsAura { public: - UIControlsWin(RootWindow* root_window) : root_window_(root_window) { - } + UIControlsWin() {} // UIControlsAura overrides: virtual bool SendKeyPress(gfx::NativeWindow native_window, @@ -43,7 +42,6 @@ class UIControlsWin : public ui_controls::UIControlsAura { } virtual bool SendMouseMove(long x, long y) { gfx::Point point(x, y); - root_window_->ConvertPointToNativeScreen(&point); return ui_controls::internal::SendMouseMoveImpl( point.x(), point.y(), base::Closure()); } @@ -51,7 +49,6 @@ class UIControlsWin : public ui_controls::UIControlsAura { long y, const base::Closure& task) { gfx::Point point(x, y); - root_window_->ConvertPointToNativeScreen(&point); return ui_controls::internal::SendMouseMoveImpl(point.x(), point.y(), task); } virtual bool SendMouseEvents(ui_controls::MouseButton type, int state) { @@ -72,14 +69,13 @@ class UIControlsWin : public ui_controls::UIControlsAura { } private: - RootWindow* root_window_; DISALLOW_COPY_AND_ASSIGN(UIControlsWin); }; } // namespace ui_controls::UIControlsAura* CreateUIControlsAura(RootWindow* root_window) { - return new UIControlsWin(root_window); + return new UIControlsWin(); } } // namespace aura diff --git a/ui/base/dragdrop/os_exchange_data.h b/ui/base/dragdrop/os_exchange_data.h index 92b6798..c99cf3a 100644 --- a/ui/base/dragdrop/os_exchange_data.h +++ b/ui/base/dragdrop/os_exchange_data.h @@ -49,12 +49,12 @@ class UI_EXPORT OSExchangeData { public: // CustomFormats are used for non-standard data types. For example, bookmark // nodes are written using a CustomFormat. -#if defined(USE_AURA) +#if defined(OS_WIN) + typedef CLIPFORMAT CustomFormat; +#elif defined(USE_AURA) // Use the same type as the clipboard (why do we want two different // definitions of this on other platforms?). typedef Clipboard::FormatType CustomFormat; -#elif defined(OS_WIN) - typedef CLIPFORMAT CustomFormat; #elif defined(TOOLKIT_GTK) typedef GdkAtom CustomFormat; #else @@ -139,6 +139,9 @@ class UI_EXPORT OSExchangeData { #endif }; + // Creates the platform specific Provider. + static Provider* CreateProvider(); + OSExchangeData(); // Creates an OSExchangeData with the specified provider. OSExchangeData // takes ownership of the supplied provider. @@ -222,9 +225,6 @@ class UI_EXPORT OSExchangeData { #endif private: - // Creates the platform specific Provider. - static Provider* CreateProvider(); - // Provides the actual data. scoped_ptr<Provider> provider_; diff --git a/ui/base/dragdrop/os_exchange_data_provider_win.cc b/ui/base/dragdrop/os_exchange_data_provider_win.cc index fc4fc85..65922f8 100644 --- a/ui/base/dragdrop/os_exchange_data_provider_win.cc +++ b/ui/base/dragdrop/os_exchange_data_provider_win.cc @@ -327,6 +327,16 @@ void OSExchangeDataProviderWin::SetFilename(const FilePath& path) { data_->contents_.push_back(info); } +void OSExchangeDataProviderWin::SetFilenames( + const std::vector<OSExchangeData::FileInfo>& filenames) { + for (size_t i = 0; i < filenames.size(); ++i) { + STGMEDIUM* storage = GetStorageForFileName(filenames[i].path); + DataObjectImpl::StoredDataInfo* info = + new DataObjectImpl::StoredDataInfo(CF_HDROP, storage); + data_->contents_.push_back(info); + } +} + void OSExchangeDataProviderWin::SetPickledData(CLIPFORMAT format, const Pickle& data) { STGMEDIUM* storage = GetStorageForBytes(static_cast<const char*>(data.data()), @@ -395,6 +405,18 @@ bool OSExchangeDataProviderWin::GetFilename(FilePath* path) const { return success; } +bool OSExchangeDataProviderWin::GetFilenames( + std::vector<OSExchangeData::FileInfo>* filenames) const { + std::vector<string16> filenames_local; + bool success = ClipboardUtil::GetFilenames(source_object_, &filenames_local); + if (success) { + for (size_t i = 0; i < filenames_local.size(); ++i) + filenames->push_back( + OSExchangeData::FileInfo(FilePath(filenames_local[i]), FilePath())); + } + return success; +} + bool OSExchangeDataProviderWin::GetPickledData(CLIPFORMAT format, Pickle* data) const { DCHECK(data); diff --git a/ui/base/dragdrop/os_exchange_data_provider_win.h b/ui/base/dragdrop/os_exchange_data_provider_win.h index 576445f..9705d34 100644 --- a/ui/base/dragdrop/os_exchange_data_provider_win.h +++ b/ui/base/dragdrop/os_exchange_data_provider_win.h @@ -161,9 +161,7 @@ class UI_EXPORT OSExchangeDataProviderWin : public OSExchangeData::Provider { virtual void SetURL(const GURL& url, const string16& title); virtual void SetFilename(const FilePath& path); virtual void SetFilenames( - const std::vector<OSExchangeData::FileInfo>& filenames) { - NOTREACHED(); - } + const std::vector<OSExchangeData::FileInfo>& filenames); virtual void SetPickledData(OSExchangeData::CustomFormat format, const Pickle& data); virtual void SetFileContents(const FilePath& filename, @@ -174,10 +172,7 @@ class UI_EXPORT OSExchangeDataProviderWin : public OSExchangeData::Provider { virtual bool GetURLAndTitle(GURL* url, string16* title) const; virtual bool GetFilename(FilePath* path) const; virtual bool GetFilenames( - std::vector<OSExchangeData::FileInfo>* filenames) const { - NOTREACHED(); - return false; - } + std::vector<OSExchangeData::FileInfo>* filenames) const; virtual bool GetPickledData(OSExchangeData::CustomFormat format, Pickle* data) const; virtual bool GetFileContents(FilePath* filename, @@ -593,7 +593,6 @@ ['exclude', 'gfx/screen_gtk.cc'], ['exclude', 'base/dialogs/select_file_dialog_mac.mm'], ['exclude', 'base/dialogs/select_file_dialog_win.cc'], - ['exclude', 'base/dragdrop/drag_utils_win.cc'], ['exclude', 'base/work_area_watcher_observer.h'], ['exclude', 'base/x/active_window_watcher_x.cc'], ['exclude', 'base/x/active_window_watcher_x.h'], @@ -616,8 +615,8 @@ }], ['use_aura==1 and OS=="win"', { 'sources/': [ - ['exclude', 'base/dragdrop/os_exchange_data_provider_win.cc'], - ['exclude', 'base/dragdrop/os_exchange_data_provider_win.h'], + ['exclude', 'base/dragdrop/os_exchange_data_provider_aura.cc'], + ['exclude', 'base/dragdrop/drag_utils_aura.cc'], ], }], ['use_aura==0 and toolkit_views==0', { diff --git a/ui/views/controls/textfield/native_textfield_views_unittest.cc b/ui/views/controls/textfield/native_textfield_views_unittest.cc index e599e7c..91ee81f 100644 --- a/ui/views/controls/textfield/native_textfield_views_unittest.cc +++ b/ui/views/controls/textfield/native_textfield_views_unittest.cc @@ -873,11 +873,7 @@ TEST_F(NativeTextfieldViewsTest, DragAndDrop_AcceptDrop) { ui::OSExchangeData bad_data; bad_data.SetFilename(FilePath(FILE_PATH_LITERAL("x"))); #if defined(OS_WIN) -#if defined(USE_AURA) - ui::OSExchangeData::CustomFormat fmt = ui::Clipboard::GetBitmapFormatType(); -#else ui::OSExchangeData::CustomFormat fmt = CF_BITMAP; -#endif bad_data.SetPickledData(fmt, Pickle()); bad_data.SetFileContents(FilePath(L"x"), "x"); bad_data.SetHtml(string16(ASCIIToUTF16("x")), GURL("x.org")); diff --git a/ui/views/views.gyp b/ui/views/views.gyp index edc77d6..6bfd9f5 100644 --- a/ui/views/views.gyp +++ b/ui/views/views.gyp @@ -358,6 +358,10 @@ 'widget/desktop_aura/desktop_cursor_client.h', 'widget/desktop_aura/desktop_dispatcher_client.cc', 'widget/desktop_aura/desktop_dispatcher_client.h', + 'widget/desktop_aura/desktop_drag_drop_client_win.cc', + 'widget/desktop_aura/desktop_drag_drop_client_win.h', + 'widget/desktop_aura/desktop_drop_target_win.cc', + 'widget/desktop_aura/desktop_drop_target_win.h', 'widget/desktop_aura/desktop_layout_manager.cc', 'widget/desktop_aura/desktop_layout_manager.h', 'widget/desktop_aura/desktop_native_widget_aura.cc', @@ -474,9 +478,9 @@ ['OS=="win"', { 'sources/': [ ['include', 'widget/desktop_aura/desktop_screen_win.cc'], - ['include', 'widget/desktop_aura/desktop_screen_win.h'], + ['include', 'widget/desktop_aura/desktop_drag_drop_client_win.cc'], + ['include', 'widget/desktop_aura/desktop_drop_target_win.cc'], ['include', 'widget/desktop_aura/desktop_root_window_host_win.cc'], - ['include', 'widget/desktop_aura/desktop_root_window_host_win.h'], ], }], ], diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc new file mode 100644 index 0000000..08de103 --- /dev/null +++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc @@ -0,0 +1,73 @@ +// 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 "ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h" + +#include "ui/base/dragdrop/drag_drop_types.h" +#include "ui/base/dragdrop/drag_source.h" +#include "ui/base/dragdrop/os_exchange_data_provider_win.h" +#include "ui/views/widget/desktop_aura/desktop_drop_target_win.h" +#include "ui/views/widget/desktop_aura/desktop_root_window_host_win.h" +#include "ui/views/widget/drop_target_win.h" + +namespace views { + +DesktopDragDropClientWin::DesktopDragDropClientWin( + aura::RootWindow* root_window, + HWND window) + : drag_drop_in_progress_(false), + drag_operation_(0) { + drop_target_ = new DesktopDropTargetWin(root_window, window); +} + +DesktopDragDropClientWin::~DesktopDragDropClientWin() { +} + +int DesktopDragDropClientWin::StartDragAndDrop( + const ui::OSExchangeData& data, + aura::RootWindow* root_window, + aura::Window* source_window, + const gfx::Point& root_location, + int operation, + ui::DragDropTypes::DragEventSource source) { + drag_drop_in_progress_ = true; + drag_operation_ = operation; + + drag_source_ = new ui::DragSource; + DWORD effects; + DoDragDrop(ui::OSExchangeDataProviderWin::GetIDataObject(data), + drag_source_, + ui::DragDropTypes::DragOperationToDropEffect(operation), + &effects); + + drag_drop_in_progress_ = false; + + return drag_operation_; +} + +void DesktopDragDropClientWin::DragUpdate(aura::Window* target, + const ui::LocatedEvent& event) { +} + +void DesktopDragDropClientWin::Drop(aura::Window* target, + const ui::LocatedEvent& event) { +} + +void DesktopDragDropClientWin::DragCancel() { + drag_source_->CancelDrag(); + drag_operation_ = 0; +} + +bool DesktopDragDropClientWin::IsDragDropInProgress() { + return drag_drop_in_progress_; +} + +void DesktopDragDropClientWin::OnNativeWidgetDestroying(HWND window) { + if (drop_target_.get()) { + RevokeDragDrop(window); + drop_target_ = NULL; + } +} + +} // namespace views diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h b/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h new file mode 100644 index 0000000..852e7ab --- /dev/null +++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h @@ -0,0 +1,59 @@ +// 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 UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_DRAG_DROP_CLIENT_WIN_H_ +#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_DRAG_DROP_CLIENT_WIN_H_ + +#include "base/compiler_specific.h" +#include "base/memory/ref_counted.h" +#include "ui/aura/client/drag_drop_client.h" +#include "ui/views/views_export.h" + +namespace ui { +class DragSource; +class RootWindow; +} + +namespace views { +class DesktopDragDragSourceWin; +class DesktopDropTargetWin; + +class VIEWS_EXPORT DesktopDragDropClientWin + : public aura::client::DragDropClient { + public: + DesktopDragDropClientWin(aura::RootWindow* root_window, HWND window); + virtual ~DesktopDragDropClientWin(); + + // Overridden from aura::client::DragDropClient: + virtual int StartDragAndDrop( + const ui::OSExchangeData& data, + aura::RootWindow* root_window, + aura::Window* source_window, + const gfx::Point& root_location, + int operation, + ui::DragDropTypes::DragEventSource source) OVERRIDE; + virtual void DragUpdate(aura::Window* target, + const ui::LocatedEvent& event) OVERRIDE; + virtual void Drop(aura::Window* target, + const ui::LocatedEvent& event) OVERRIDE; + virtual void DragCancel() OVERRIDE; + virtual bool IsDragDropInProgress() OVERRIDE; + + void OnNativeWidgetDestroying(HWND window); + + private: + bool drag_drop_in_progress_; + + int drag_operation_; + + scoped_refptr<ui::DragSource> drag_source_; + + scoped_refptr<DesktopDropTargetWin> drop_target_; + + DISALLOW_COPY_AND_ASSIGN(DesktopDragDropClientWin); +}; + +} // namespace views + +#endif // UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_DRAG_DROP_CLIENT_WIN_H_ diff --git a/ui/views/widget/desktop_aura/desktop_drop_target_win.cc b/ui/views/widget/desktop_aura/desktop_drop_target_win.cc new file mode 100644 index 0000000..4d0a8ea --- /dev/null +++ b/ui/views/widget/desktop_aura/desktop_drop_target_win.cc @@ -0,0 +1,139 @@ +// Copyright (c) 2011 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 "ui/views/widget/desktop_aura/desktop_drop_target_win.h" + +#include "ui/aura/client/drag_drop_client.h" +#include "ui/aura/client/drag_drop_delegate.h" +#include "ui/aura/window.h" +#include "ui/aura/root_window.h" +#include "ui/base/dragdrop/drag_drop_types.h" +#include "ui/base/dragdrop/os_exchange_data_provider_win.h" +#include "ui/base/events/event.h" + +using aura::client::DragDropDelegate; +using ui::OSExchangeData; +using ui::OSExchangeDataProviderWin; + +namespace views { + +DesktopDropTargetWin::DesktopDropTargetWin(aura::RootWindow* root_window, + HWND window) + : ui::DropTarget(window), + root_window_(root_window), + target_window_(NULL) { +} + +DesktopDropTargetWin::~DesktopDropTargetWin() { + if (target_window_) + target_window_->RemoveObserver(this); +} + +DWORD DesktopDropTargetWin::OnDragEnter(IDataObject* data_object, + DWORD key_state, + POINT position, + DWORD effect) { + scoped_ptr<OSExchangeData> data; + scoped_ptr<ui::DropTargetEvent> event; + DragDropDelegate* delegate; + // Translate will call OnDragEntered. + Translate(data_object, key_state, position, effect, &data, &event, &delegate); + return ui::DragDropTypes::DragOperationToDropEffect( + ui::DragDropTypes::DRAG_NONE); +} + +DWORD DesktopDropTargetWin::OnDragOver(IDataObject* data_object, + DWORD key_state, + POINT position, + DWORD effect) { + int drag_operation = ui::DragDropTypes::DRAG_NONE; + scoped_ptr<OSExchangeData> data; + scoped_ptr<ui::DropTargetEvent> event; + DragDropDelegate* delegate; + Translate(data_object, key_state, position, effect, &data, &event, &delegate); + if (delegate) + drag_operation = delegate->OnDragUpdated(*event); + return ui::DragDropTypes::DragOperationToDropEffect(drag_operation); +} + +void DesktopDropTargetWin::OnDragLeave(IDataObject* data_object) { + NotifyDragLeave(); +} + +DWORD DesktopDropTargetWin::OnDrop(IDataObject* data_object, + DWORD key_state, + POINT position, + DWORD effect) { + int drag_operation = ui::DragDropTypes::DRAG_NONE; + scoped_ptr<OSExchangeData> data; + scoped_ptr<ui::DropTargetEvent> event; + DragDropDelegate* delegate; + Translate(data_object, key_state, position, effect, &data, &event, &delegate); + if (delegate) + drag_operation = delegate->OnPerformDrop(*event); + if (target_window_) { + target_window_->RemoveObserver(this); + target_window_ = NULL; + } + return ui::DragDropTypes::DragOperationToDropEffect(drag_operation); +} + +void DesktopDropTargetWin::OnWindowDestroyed(aura::Window* window) { + DCHECK(window == target_window_); + target_window_ = NULL; +} + +void DesktopDropTargetWin::Translate( + IDataObject* data_object, + DWORD key_state, + POINT position, + DWORD effect, + scoped_ptr<OSExchangeData>* data, + scoped_ptr<ui::DropTargetEvent>* event, + DragDropDelegate** delegate) { + gfx::Point location(position.x, position.y); + gfx::Point root_location = location; + root_window_->ConvertPointFromNativeScreen(&root_location); + aura::Window* target_window = + root_window_->GetEventHandlerForPoint(root_location); + bool target_window_changed = false; + if (target_window != target_window_) { + if (target_window_) + NotifyDragLeave(); + target_window_ = target_window; + if (target_window_) + target_window_->AddObserver(this); + target_window_changed = true; + } + *delegate = NULL; + if (!target_window_) + return; + *delegate = aura::client::GetDragDropDelegate(target_window_); + if (!*delegate) + return; + + data->reset(new OSExchangeData(new OSExchangeDataProviderWin(data_object))); + location = root_location; + aura::Window::ConvertPointToTarget(root_window_, target_window_, &location); + event->reset(new ui::DropTargetEvent( + *(data->get()), + location, + root_location, + ui::DragDropTypes::DropEffectToDragOperation(effect))); + if (target_window_changed) + (*delegate)->OnDragEntered(*event->get()); +} + +void DesktopDropTargetWin::NotifyDragLeave() { + if (!target_window_) + return; + DragDropDelegate* delegate = + aura::client::GetDragDropDelegate(target_window_); + if (delegate) + delegate->OnDragExited(); + target_window_->RemoveObserver(this); + target_window_ = NULL; +} + +} // namespace views diff --git a/ui/views/widget/desktop_aura/desktop_drop_target_win.h b/ui/views/widget/desktop_aura/desktop_drop_target_win.h new file mode 100644 index 0000000..bdb22bb8 --- /dev/null +++ b/ui/views/widget/desktop_aura/desktop_drop_target_win.h @@ -0,0 +1,81 @@ +// 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 UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTIOP_DROP_TARGET_WIN_H_ +#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTIOP_DROP_TARGET_WIN_H_ + +#include "base/memory/scoped_ptr.h" +#include "ui/base/dragdrop/drop_target.h" +#include "ui/aura/window_observer.h" + +namespace aura { +class RootWindow; +namespace client { +class DragDropDelegate; +} +} + +namespace ui { +class DropTargetEvent; +class OSExchangeData; +} + +namespace views { + +// DesktopDropTargetWin takes care of managing drag and drop for +// DesktopRootWindowHostWin. It converts Windows OLE drop messages into +// aura::client::DragDropDelegate calls. +class DesktopDropTargetWin : public ui::DropTarget, + public aura::WindowObserver { + public: + DesktopDropTargetWin(aura::RootWindow* root_window, HWND window); + virtual ~DesktopDropTargetWin(); + + private: + // ui::DropTarget implementation: + virtual DWORD OnDragEnter(IDataObject* data_object, + DWORD key_state, + POINT position, + DWORD effect) OVERRIDE; + virtual DWORD OnDragOver(IDataObject* data_object, + DWORD key_state, + POINT position, + DWORD effect) OVERRIDE; + virtual void OnDragLeave(IDataObject* data_object) OVERRIDE; + virtual DWORD OnDrop(IDataObject* data_object, + DWORD key_state, + POINT position, + DWORD effect) OVERRIDE; + + // aura::WindowObserver implementation: + virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE; + + // Common functionality for the ui::DropTarget methods to translate from COM + // data types to Aura ones. + void Translate(IDataObject* data_object, + DWORD key_state, + POINT cursor_position, + DWORD effect, + scoped_ptr<ui::OSExchangeData>* data, + scoped_ptr<ui::DropTargetEvent>* event, + aura::client::DragDropDelegate** delegate); + + void NotifyDragLeave(); + + // The root window associated with this drop target. + aura::RootWindow* root_window_; + + // The Aura window that is currently under the cursor. We need to manually + // keep track of this because Windows will only call our drag enter method + // once when the user enters the associated HWND. But inside that HWND there + // could be multiple aura windows, so we need to generate drag enter events + // for them. + aura::Window* target_window_; + + DISALLOW_COPY_AND_ASSIGN(DesktopDropTargetWin); +}; + +} // namespace views + +#endif // UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTIOP_DROP_TARGET_WIN_H_ diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc index 0a11531..0ac38a7 100644 --- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc +++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc @@ -17,10 +17,13 @@ #include "ui/native_theme/native_theme.h" #include "ui/views/corewm/compound_event_filter.h" #include "ui/views/corewm/input_method_event_filter.h" +#include "ui/views/drag_utils.h" #include "ui/views/ime/input_method.h" #include "ui/views/ime/input_method_bridge.h" #include "ui/views/widget/desktop_aura/desktop_root_window_host.h" +#include "ui/views/widget/drop_helper.h" #include "ui/views/widget/native_widget_aura_window_observer.h" +#include "ui/views/widget/root_view.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_aura_utils.h" @@ -133,6 +136,9 @@ void DesktopNativeWidgetAura::InitNativeWidget( desktop_root_window_host_->Init(window_, params)); stacking_client_.reset( new DesktopNativeWidgetAuraStackingClient(root_window_.get())); + drop_helper_.reset(new DropHelper( + static_cast<internal::RootView*>(GetWidget()->GetRootView()))); + aura::client::SetDragDropDelegate(window_, this); aura::client::SetActivationDelegate(window_, this); } @@ -394,11 +400,13 @@ bool DesktopNativeWidgetAura::IsAccessibleWidget() const { return false; } -void DesktopNativeWidgetAura::RunShellDrag(View* view, - const ui::OSExchangeData& data, - const gfx::Point& location, - int operation, - ui::DragDropTypes::DragEventSource source) { +void DesktopNativeWidgetAura::RunShellDrag( + View* view, + const ui::OSExchangeData& data, + const gfx::Point& location, + int operation, + ui::DragDropTypes::DragEventSource source) { + views::RunShellDrag(window_, data, location, operation, source); } void DesktopNativeWidgetAura::SchedulePaintInRect(const gfx::Rect& rect) { @@ -522,7 +530,7 @@ void DesktopNativeWidgetAura::OnWindowDestroyed() { window_ = NULL; native_widget_delegate_->OnNativeWidgetDestroyed(); if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) - delete this; + delete this; } void DesktopNativeWidgetAura::OnWindowTargetVisibilityChanged(bool visible) { @@ -633,4 +641,31 @@ void DesktopNativeWidgetAura::DispatchKeyEventPostIME(const ui::KeyEvent& key) { focus_manager->OnKeyEvent(key); } +//////////////////////////////////////////////////////////////////////////////// +// DesktopNativeWidgetAura, aura::WindowDragDropDelegate implementation: + +void DesktopNativeWidgetAura::OnDragEntered(const ui::DropTargetEvent& event) { + DCHECK(drop_helper_.get() != NULL); + last_drop_operation_ = drop_helper_->OnDragOver(event.data(), + event.location(), event.source_operations()); +} + +int DesktopNativeWidgetAura::OnDragUpdated(const ui::DropTargetEvent& event) { + DCHECK(drop_helper_.get() != NULL); + last_drop_operation_ = drop_helper_->OnDragOver(event.data(), + event.location(), event.source_operations()); + return last_drop_operation_; +} + +void DesktopNativeWidgetAura::OnDragExited() { + DCHECK(drop_helper_.get() != NULL); + drop_helper_->OnDragExit(); +} + +int DesktopNativeWidgetAura::OnPerformDrop(const ui::DropTargetEvent& event) { + DCHECK(drop_helper_.get() != NULL); + return drop_helper_->OnDrop(event.data(), event.location(), + last_drop_operation_); +} + } // namespace views diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h index 63977a5..cbf8f56 100644 --- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h +++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h @@ -7,6 +7,7 @@ #include "base/memory/weak_ptr.h" #include "ui/aura/client/activation_delegate.h" +#include "ui/aura/client/drag_drop_delegate.h" #include "ui/aura/window_delegate.h" #include "ui/views/ime/input_method_delegate.h" #include "ui/views/widget/native_widget_private.h" @@ -26,6 +27,7 @@ class InputMethodEventFilter; } class DesktopRootWindowHost; +class DropHelper; class NativeWidgetAuraWindowObserver; // TODO(erg): May also need to be a DragDropDelegate @@ -33,7 +35,8 @@ class VIEWS_EXPORT DesktopNativeWidgetAura : public internal::NativeWidgetPrivate, public aura::WindowDelegate, public aura::client::ActivationDelegate, - public views::internal::InputMethodDelegate { + public views::internal::InputMethodDelegate, + public aura::client::DragDropDelegate { public: explicit DesktopNativeWidgetAura(internal::NativeWidgetDelegate* delegate); virtual ~DesktopNativeWidgetAura(); @@ -180,6 +183,12 @@ class VIEWS_EXPORT DesktopNativeWidgetAura // Overridden from views::internal::InputMethodDelegate: virtual void DispatchKeyEventPostIME(const ui::KeyEvent& key) OVERRIDE; + // Overridden from aura::client::DragDropDelegate: + virtual void OnDragEntered(const ui::DropTargetEvent& event) OVERRIDE; + virtual int OnDragUpdated(const ui::DropTargetEvent& event) OVERRIDE; + virtual void OnDragExited() OVERRIDE; + virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE; + private: // See class documentation for Widget in widget.h for a note about ownership. Widget::InitParams::Ownership ownership_; @@ -209,6 +218,9 @@ class VIEWS_EXPORT DesktopNativeWidgetAura scoped_ptr<corewm::InputMethodEventFilter> input_method_event_filter_; + scoped_ptr<DropHelper> drop_helper_; + int last_drop_operation_; + DISALLOW_COPY_AND_ASSIGN(DesktopNativeWidgetAura); }; diff --git a/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc b/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc index a5b785c..ca19df0 100644 --- a/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc +++ b/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc @@ -26,8 +26,10 @@ #include "ui/views/widget/desktop_aura/desktop_activation_client.h" #include "ui/views/widget/desktop_aura/desktop_cursor_client.h" #include "ui/views/widget/desktop_aura/desktop_dispatcher_client.h" +#include "ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h" #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" #include "ui/views/widget/desktop_aura/desktop_screen_position_client.h" +#include "ui/views/widget/root_view.h" #include "ui/views/widget/widget_delegate.h" #include "ui/views/widget/widget_hwnd_utils.h" #include "ui/views/win/fullscreen_handler.h" @@ -130,13 +132,16 @@ aura::RootWindow* DesktopRootWindowHostWin::Init( cursor_client_.reset(new DesktopCursorClient(root_window_)); aura::client::SetCursorClient(root_window_, cursor_client_.get()); - position_client_.reset(new DesktopScreenPositionClient()); aura::client::SetScreenPositionClient(root_window_, position_client_.get()); desktop_native_widget_aura_->InstallInputMethodEventFilter(root_window_); + drag_drop_client_.reset(new DesktopDragDropClientWin(root_window_, + GetHWND())); + aura::client::SetDragDropClient(root_window_, drag_drop_client_.get()); + focus_client_->FocusWindow(content_window_, NULL); root_window_->SetProperty(kContentWindowForRootWindow, content_window_); @@ -373,7 +378,9 @@ void DesktopRootWindowHostWin::SetBounds(const gfx::Rect& bounds) { } gfx::Point DesktopRootWindowHostWin::GetLocationOnNativeScreen() const { - return gfx::Point(1, 1); + RECT r; + GetWindowRect(GetHWND(), &r); + return gfx::Point(r.left, r.top); } void DesktopRootWindowHostWin::SetCapture() { @@ -588,11 +595,11 @@ void DesktopRootWindowHostWin::HandleCreate() { // 1. Window property association // 2. MouseWheel. - // 3. Drop target. - // 4. Tooltip Manager. + // 3. Tooltip Manager. } void DesktopRootWindowHostWin::HandleDestroying() { + drag_drop_client_->OnNativeWidgetDestroying(GetHWND()); native_widget_delegate_->OnNativeWidgetDestroying(); } diff --git a/ui/views/widget/desktop_aura/desktop_root_window_host_win.h b/ui/views/widget/desktop_aura/desktop_root_window_host_win.h index 8ff793c..8dd59ae 100644 --- a/ui/views/widget/desktop_aura/desktop_root_window_host_win.h +++ b/ui/views/widget/desktop_aura/desktop_root_window_host_win.h @@ -22,6 +22,7 @@ namespace views { class DesktopActivationClient; class DesktopCursorClient; class DesktopDispatcherClient; +class DesktopDragDropClientWin; class HWNDMessageHandler; class VIEWS_EXPORT DesktopRootWindowHostWin @@ -224,6 +225,8 @@ class VIEWS_EXPORT DesktopRootWindowHostWin // A simple cursor client which just forwards events to the RootWindow. scoped_ptr<DesktopCursorClient> cursor_client_; + scoped_ptr<DesktopDragDropClientWin> drag_drop_client_; + DISALLOW_COPY_AND_ASSIGN(DesktopRootWindowHostWin); }; |