diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-18 17:10:18 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-18 17:10:18 +0000 |
commit | 2ca8a064a206fba910dc0f50f8a2f2509828d8f1 (patch) | |
tree | 9e128f90d2392b901aca101baabe12dd36621943 /chrome/browser | |
parent | 911f815112d8d11778c771467fbef2c2b1f8e160 (diff) | |
download | chromium_src-2ca8a064a206fba910dc0f50f8a2f2509828d8f1.zip chromium_src-2ca8a064a206fba910dc0f50f8a2f2509828d8f1.tar.gz chromium_src-2ca8a064a206fba910dc0f50f8a2f2509828d8f1.tar.bz2 |
GTK: implement extension bookmark manager drag api.
Also, cross-platform: eschew RenderViewHostDelegate:BookmarkDrag::DragData type in favor of BookmarkDragData.
BUG=37702
TEST=manual
Review URL: http://codereview.chromium.org/1029004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41959 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
20 files changed, 376 insertions, 217 deletions
diff --git a/chrome/browser/bookmarks/bookmark_drag_data.cc b/chrome/browser/bookmarks/bookmark_drag_data.cc index 3491d06..d722659 100644 --- a/chrome/browser/bookmarks/bookmark_drag_data.cc +++ b/chrome/browser/bookmarks/bookmark_drag_data.cc @@ -89,8 +89,20 @@ BookmarkDragData::BookmarkDragData(const BookmarkNode* node) { BookmarkDragData::BookmarkDragData( const std::vector<const BookmarkNode*>& nodes) { + ReadFromVector(nodes); +} + +bool BookmarkDragData::ReadFromVector( + const std::vector<const BookmarkNode*>& nodes) { + Clear(); + + if (nodes.empty()) + return false; + for (size_t i = 0; i < nodes.size(); ++i) elements.push_back(Element(nodes[i])); + + return true; } #if !defined(OS_MACOSX) @@ -272,12 +284,14 @@ void BookmarkDragData::Clear() { elements.clear(); } +void BookmarkDragData::SetOriginatingProfile(Profile* profile) { + DCHECK(profile_path_.empty()); + + if (profile) + profile_path_ = profile->GetPath().value(); +} + bool BookmarkDragData::IsFromProfile(Profile* profile) const { // An empty path means the data is not associated with any profile. - return (!profile_path_.empty() && -#if defined(WCHAR_T_IS_UTF16) - profile->GetPath().ToWStringHack() == profile_path_); -#elif defined(WCHAR_T_IS_UTF32) - profile->GetPath().value() == profile_path_); -#endif + return !profile_path_.empty() && profile_path_ == profile->GetPath().value(); } diff --git a/chrome/browser/bookmarks/bookmark_drag_data.h b/chrome/browser/bookmarks/bookmark_drag_data.h index e26c362..7f007a2 100644 --- a/chrome/browser/bookmarks/bookmark_drag_data.h +++ b/chrome/browser/bookmarks/bookmark_drag_data.h @@ -86,6 +86,9 @@ struct BookmarkDragData { explicit BookmarkDragData(const BookmarkNode* node); explicit BookmarkDragData(const std::vector<const BookmarkNode*>& nodes); + // Reads bookmarks from the given vector. + bool ReadFromVector(const std::vector<const BookmarkNode*>& nodes); + // Writes elements to the clipboard. void WriteToClipboard(Profile* profile) const; @@ -138,6 +141,11 @@ struct BookmarkDragData { // Clears the data. void Clear(); + // Sets |profile_path_| to that of |profile|. This is useful for the + // constructors/readers that don't set it. This should only be called if the + // profile path is not already set. + void SetOriginatingProfile(Profile* profile); + // Returns true if this data is from the specified profile. bool IsFromProfile(Profile* profile) const; diff --git a/chrome/browser/bookmarks/bookmark_utils.cc b/chrome/browser/bookmarks/bookmark_utils.cc index c31b821..cda4ef0 100644 --- a/chrome/browser/bookmarks/bookmark_utils.cc +++ b/chrome/browser/bookmarks/bookmark_utils.cc @@ -40,6 +40,8 @@ #include "views/drag_utils.h" #include "views/widget/root_view.h" #include "views/widget/widget.h" +#elif defined(TOOLKIT_GTK) +#include "chrome/browser/gtk/custom_drag.h" #endif using base::Time; @@ -352,9 +354,8 @@ void DragBookmarks(Profile* profile, MessageLoop::current()->SetNestableTasksAllowed(true); bookmark_pasteboard_helper_mac::StartDrag(profile, nodes, view); MessageLoop::current()->SetNestableTasksAllowed(was_nested); -#else - // TODO(arv): Implement for GTK. - NOTIMPLEMENTED(); +#elif defined(TOOLKIT_GTK) + BookmarkDrag::BeginDrag(profile, nodes); #endif } diff --git a/chrome/browser/cocoa/web_drop_target.mm b/chrome/browser/cocoa/web_drop_target.mm index 06e0a98..b051772 100644 --- a/chrome/browser/cocoa/web_drop_target.mm +++ b/chrome/browser/cocoa/web_drop_target.mm @@ -5,6 +5,7 @@ #import "chrome/browser/cocoa/web_drop_target.h" #include "base/sys_string_conversions.h" +#include "chrome/browser/bookmarks/bookmark_drag_data.h" #include "chrome/browser/bookmarks/bookmark_pasteboard_helper_mac.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/tab_contents.h" @@ -82,8 +83,9 @@ using WebKit::WebDragOperationsMask; // If the tab is showing the boomark manager, send BookmarkDrag events RenderViewHostDelegate::BookmarkDrag* dragDelegate = tabContents_->GetBookmarkDragDelegate(); - if(dragDelegate) - dragDelegate->OnDragEnter(NULL); + BookmarkDragData dragData; + if(dragDelegate && dragData.ReadFromDragClipboard()) + dragDelegate->OnDragEnter(dragData); // Fill out a WebDropData from pasteboard. WebDropData data; @@ -142,8 +144,9 @@ using WebKit::WebDragOperationsMask; // If the tab is showing the boomark manager, send BookmarkDrag events RenderViewHostDelegate::BookmarkDrag* dragDelegate = tabContents_->GetBookmarkDragDelegate(); - if(dragDelegate) - dragDelegate->OnDragOver(NULL); + BookmarkDragData dragData; + if(dragDelegate && dragData.ReadFromDragClipboard()) + dragDelegate->OnDragOver(dragData); return current_operation_; } @@ -168,8 +171,9 @@ using WebKit::WebDragOperationsMask; // If the tab is showing the boomark manager, send BookmarkDrag events RenderViewHostDelegate::BookmarkDrag* dragDelegate = tabContents_->GetBookmarkDragDelegate(); - if(dragDelegate) - dragDelegate->OnDrop(NULL); + BookmarkDragData dragData; + if(dragDelegate && dragData.ReadFromDragClipboard()) + dragDelegate->OnDrop(dragData); currentRVH_ = NULL; diff --git a/chrome/browser/download/download_util.cc b/chrome/browser/download/download_util.cc index 6aa33e1..6d83c8f 100644 --- a/chrome/browser/download/download_util.cc +++ b/chrome/browser/download/download_util.cc @@ -43,7 +43,7 @@ #include "app/drag_drop_types.h" #include "views/widget/widget_gtk.h" #elif defined(TOOLKIT_GTK) -#include "chrome/browser/gtk/download_item_drag.h" +#include "chrome/browser/gtk/custom_drag.h" #endif // defined(TOOLKIT_GTK) #endif // defined(OS_LINUX) diff --git a/chrome/browser/extensions/extension_bookmark_manager_api.cc b/chrome/browser/extensions/extension_bookmark_manager_api.cc index f12e62f..5c589ba 100644 --- a/chrome/browser/extensions/extension_bookmark_manager_api.cc +++ b/chrome/browser/extensions/extension_bookmark_manager_api.cc @@ -27,8 +27,6 @@ namespace keys = extension_bookmarks_module_constants; namespace { -typedef RenderViewHostDelegate::BookmarkDrag::DragData DragData; - // Returns a single bookmark node from the argument ID. // This returns NULL in case of failure. const BookmarkNode* GetNodeFromArguments(BookmarkModel* model, @@ -136,21 +134,6 @@ void BookmarkDragDataToJSON(Profile* profile, const BookmarkDragData& data, args->Append(value); } -// This is the platform specific function that takes the drag data and creates -// the BookmarkDragData as needed. -bool GetBookmarkDragData(const DragData* data, - BookmarkDragData* bookmark_drag_data) { -#if defined(TOOLKIT_VIEWS) - // On TOOLKIT_VIEWS DragData is OSExchangeData. - return bookmark_drag_data->Read(*data); -#elif defined(OS_MACOSX) - return bookmark_drag_data->ReadFromDragClipboard(); -#else - NOTIMPLEMENTED(); - return false; -#endif -} - } // namespace ExtensionBookmarkManagerEventRouter::ExtensionBookmarkManagerEventRouter( @@ -177,34 +160,38 @@ void ExtensionBookmarkManagerEventRouter::DispatchEvent(const char* event_name, } void ExtensionBookmarkManagerEventRouter::DispatchDragEvent( - const DragData* data, const char* event_name) { - BookmarkDragData bookmark_drag_data; - if (::GetBookmarkDragData(data, &bookmark_drag_data)) { - ListValue args; - BookmarkDragDataToJSON(profile_, bookmark_drag_data, &args); - DispatchEvent(event_name, &args); - } + const BookmarkDragData& data, const char* event_name) { + if (data.size() == 0) + return; + + ListValue args; + BookmarkDragDataToJSON(profile_, data, &args); + DispatchEvent(event_name, &args); } -void ExtensionBookmarkManagerEventRouter::OnDragEnter(const DragData* data) { +void ExtensionBookmarkManagerEventRouter::OnDragEnter( + const BookmarkDragData& data) { DispatchDragEvent(data, keys::kOnBookmarkDragEnter); } -void ExtensionBookmarkManagerEventRouter::OnDragOver(const DragData* data) { +void ExtensionBookmarkManagerEventRouter::OnDragOver( + const BookmarkDragData& data) { // Intentionally empty since these events happens too often and floods the // message queue. We do not need this event for the bookmark manager anyway. } -void ExtensionBookmarkManagerEventRouter::OnDragLeave(const DragData* data) { +void ExtensionBookmarkManagerEventRouter::OnDragLeave( + const BookmarkDragData& data) { DispatchDragEvent(data, keys::kOnBookmarkDragLeave); } -void ExtensionBookmarkManagerEventRouter::OnDrop(const DragData* data) { +void ExtensionBookmarkManagerEventRouter::OnDrop( + const BookmarkDragData& data) { DispatchDragEvent(data, keys::kOnBookmarkDrop); // Make a copy that is owned by this instance. ClearBookmarkDragData(); - ::GetBookmarkDragData(data, &bookmark_drag_data_); + bookmark_drag_data_ = data; } const BookmarkDragData* diff --git a/chrome/browser/extensions/extension_bookmark_manager_api.h b/chrome/browser/extensions/extension_bookmark_manager_api.h index 3ab9964..b15e07c 100644 --- a/chrome/browser/extensions/extension_bookmark_manager_api.h +++ b/chrome/browser/extensions/extension_bookmark_manager_api.h @@ -11,6 +11,7 @@ #include "chrome/browser/renderer_host/render_view_host_delegate.h" #include "chrome/browser/shell_dialogs.h" +struct BookmarkDragData; class BookmarkNode; class ListValue; class Profile; @@ -25,10 +26,10 @@ class ExtensionBookmarkManagerEventRouter virtual ~ExtensionBookmarkManagerEventRouter(); // RenderViewHostDelegate::BookmarkDrag interface - virtual void OnDragEnter(const DragData* data); - virtual void OnDragOver(const DragData* data); - virtual void OnDragLeave(const DragData* data); - virtual void OnDrop(const DragData* data); + virtual void OnDragEnter(const BookmarkDragData& data); + virtual void OnDragOver(const BookmarkDragData& data); + virtual void OnDragLeave(const BookmarkDragData& data); + virtual void OnDrop(const BookmarkDragData& data); // The bookmark drag and drop data. This gets set after a drop was done on // the page. This returns NULL if no data is available. @@ -41,7 +42,7 @@ class ExtensionBookmarkManagerEventRouter // Helper to actually dispatch an event to extension listeners. void DispatchEvent(const char* event_name, const ListValue* args); - void DispatchDragEvent(const DragData* data, const char* event_name); + void DispatchDragEvent(const BookmarkDragData& data, const char* event_name); Profile* profile_; TabContents* tab_contents_; diff --git a/chrome/browser/gtk/bookmark_bar_gtk.cc b/chrome/browser/gtk/bookmark_bar_gtk.cc index 2ae1421..c1054ab 100644 --- a/chrome/browser/gtk/bookmark_bar_gtk.cc +++ b/chrome/browser/gtk/bookmark_bar_gtk.cc @@ -837,12 +837,7 @@ GtkWidget* BookmarkBarGtk::CreateBookmarkButton(const BookmarkNode* node) { // The tool item is also a source for dragging gtk_drag_source_set(button, GDK_BUTTON1_MASK, NULL, 0, static_cast<GdkDragAction>(GDK_ACTION_MOVE | GDK_ACTION_COPY)); - int target_mask = gtk_dnd_util::CHROME_BOOKMARK_ITEM; - if (node->is_url()) { - target_mask |= gtk_dnd_util::TEXT_URI_LIST | - gtk_dnd_util::TEXT_PLAIN | - gtk_dnd_util::NETSCAPE_URL; - } + int target_mask = bookmark_utils::GetCodeMask(node->is_folder()); gtk_dnd_util::SetSourceTargetListFromCodeMask(button, target_mask); g_signal_connect(button, "drag-begin", G_CALLBACK(&OnButtonDragBeginThunk), this); diff --git a/chrome/browser/gtk/bookmark_manager_gtk.cc b/chrome/browser/gtk/bookmark_manager_gtk.cc index b023a44c..848b306 100644 --- a/chrome/browser/gtk/bookmark_manager_gtk.cc +++ b/chrome/browser/gtk/bookmark_manager_gtk.cc @@ -60,12 +60,6 @@ const int kDefaultColumnWidth = 200; // The destination targets that the right tree view accepts for dragging. const int kDestTargetList[] = { gtk_dnd_util::CHROME_BOOKMARK_ITEM, -1 }; -// The source targets that the right tree view supports for dragging. -const int kSourceTargetMask = gtk_dnd_util::CHROME_BOOKMARK_ITEM | - gtk_dnd_util::TEXT_URI_LIST | - gtk_dnd_util::TEXT_PLAIN | - gtk_dnd_util::NETSCAPE_URL; - // We only have one manager open at a time. BookmarkManagerGtk* manager = NULL; @@ -559,7 +553,7 @@ GtkWidget* BookmarkManagerGtk::MakeRightPane() { static_cast<GdkDragAction>(GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK)); gtk_dnd_util::SetSourceTargetListFromCodeMask( - right_tree_view_, kSourceTargetMask); + right_tree_view_, bookmark_utils::GetCodeMask(false)); // We connect to drag dest signals, but we don't actually enable the widget // as a drag destination unless it corresponds to the contents of a folder. @@ -1301,7 +1295,7 @@ gboolean BookmarkManagerGtk::OnRightTreeViewMotion( static_cast<gint>(event->y))) { bm->delaying_mousedown_ = false; GtkTargetList* targets = gtk_dnd_util::GetTargetListFromCodeMask( - kSourceTargetMask); + bookmark_utils::GetCodeMask(false)); gtk_drag_begin(tree_view, targets, GDK_ACTION_MOVE, 1, reinterpret_cast<GdkEvent*>(event)); // The drag adds a ref; let it own the list. diff --git a/chrome/browser/gtk/bookmark_utils_gtk.cc b/chrome/browser/gtk/bookmark_utils_gtk.cc index 73b3feda..c15c9fb 100644 --- a/chrome/browser/gtk/bookmark_utils_gtk.cc +++ b/chrome/browser/gtk/bookmark_utils_gtk.cc @@ -198,6 +198,16 @@ void SetButtonTextColors(GtkWidget* label, GtkThemeProvider* provider) { // DnD-related ----------------------------------------------------------------- +int GetCodeMask(bool folder) { + int rv = gtk_dnd_util::CHROME_BOOKMARK_ITEM; + if (!folder) { + rv |= gtk_dnd_util::TEXT_URI_LIST | + gtk_dnd_util::TEXT_PLAIN | + gtk_dnd_util::NETSCAPE_URL; + } + return rv; +} + void WriteBookmarkToSelection(const BookmarkNode* node, GtkSelectionData* selection_data, guint target_type, @@ -272,17 +282,19 @@ std::vector<const BookmarkNode*> GetNodesFromSelection( Profile* profile, gboolean* delete_selection_data, gboolean* dnd_success) { - *delete_selection_data = FALSE; - *dnd_success = FALSE; + if (delete_selection_data) + *delete_selection_data = FALSE; + if (dnd_success) + *dnd_success = FALSE; if ((selection_data != NULL) && (selection_data->length >= 0)) { - if (context->action == GDK_ACTION_MOVE) { + if (context && delete_selection_data && context->action == GDK_ACTION_MOVE) *delete_selection_data = TRUE; - } switch (target_type) { case gtk_dnd_util::CHROME_BOOKMARK_ITEM: { - *dnd_success = TRUE; + if (dnd_success) + *dnd_success = TRUE; Pickle pickle(reinterpret_cast<char*>(selection_data->data), selection_data->length); BookmarkDragData drag_data; diff --git a/chrome/browser/gtk/bookmark_utils_gtk.h b/chrome/browser/gtk/bookmark_utils_gtk.h index de56039..012ce96 100644 --- a/chrome/browser/gtk/bookmark_utils_gtk.h +++ b/chrome/browser/gtk/bookmark_utils_gtk.h @@ -48,6 +48,10 @@ void SetButtonTextColors(GtkWidget* label, GtkThemeProvider* provider); // Drag and drop. -------------------------------------------------------------- +// Get the DnD target mask for a bookmark drag. This will vary based on whether +// the node in question is a folder. +int GetCodeMask(bool folder); + // Pickle a node into a GtkSelection. void WriteBookmarkToSelection(const BookmarkNode* node, GtkSelectionData* selection_data, diff --git a/chrome/browser/gtk/custom_drag.cc b/chrome/browser/gtk/custom_drag.cc new file mode 100644 index 0000000..7cff653 --- /dev/null +++ b/chrome/browser/gtk/custom_drag.cc @@ -0,0 +1,134 @@ +// Copyright (c) 2010 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 "chrome/browser/gtk/custom_drag.h" + +#include "app/gtk_dnd_util.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/download/download_manager.h" +#include "chrome/browser/gtk/bookmark_utils_gtk.h" +#include "gfx/gtk_util.h" +#include "googleurl/src/gurl.h" +#include "net/base/net_util.h" +#include "third_party/skia/include/core/SkBitmap.h" + +namespace { + +const int kDownloadItemCodeMask = gtk_dnd_util::TEXT_URI_LIST | + gtk_dnd_util::CHROME_NAMED_URL; +const GdkDragAction kDownloadItemDragAction = GDK_ACTION_COPY; +const GdkDragAction kBookmarkDragAction = GDK_ACTION_COPY; + +void OnDragDataGetForDownloadItem(GtkSelectionData* selection_data, + guint target_type, + const DownloadItem* download_item) { + GURL url = net::FilePathToFileURL(download_item->full_path()); + gtk_dnd_util::WriteURLWithName(selection_data, url, + UTF8ToUTF16(download_item->GetFileName().value()), target_type); +} + +void OnDragDataGetStandalone(GtkWidget* widget, GdkDragContext* context, + GtkSelectionData* selection_data, + guint target_type, guint time, + const DownloadItem* item) { + OnDragDataGetForDownloadItem(selection_data, target_type, item); +} + +} // namespace + +// CustomDrag ------------------------------------------------------------------ + +CustomDrag::CustomDrag(SkBitmap* icon, int code_mask, GdkDragAction action) + : drag_widget_(gtk_invisible_new()), + pixbuf_(icon ? gfx::GdkPixbufFromSkBitmap(icon) : NULL) { + g_object_ref_sink(drag_widget_); + g_signal_connect(drag_widget_, "drag-data-get", + G_CALLBACK(OnDragDataGetThunk), this); + g_signal_connect(drag_widget_, "drag-begin", + G_CALLBACK(OnDragBeginThunk), this); + g_signal_connect(drag_widget_, "drag-end", + G_CALLBACK(OnDragEndThunk), this); + + GtkTargetList* list = gtk_dnd_util::GetTargetListFromCodeMask(code_mask); + GdkEvent* event = gtk_get_current_event(); + gtk_drag_begin(drag_widget_, list, action, 1, event); + if (event) + gdk_event_free(event); + gtk_target_list_unref(list); +} + +CustomDrag::~CustomDrag() { + if (pixbuf_) + g_object_unref(pixbuf_); + g_object_unref(drag_widget_); +} + +void CustomDrag::OnDragBegin(GtkWidget* widget, GdkDragContext* drag_context) { + if (pixbuf_) + gtk_drag_set_icon_pixbuf(drag_context, pixbuf_, 0, 0); +} + +void CustomDrag::OnDragEnd(GtkWidget* widget, GdkDragContext* drag_context) { + delete this; +} + +// DownloadItemDrag ------------------------------------------------------------ + +DownloadItemDrag::DownloadItemDrag(const DownloadItem* item, + SkBitmap* icon) + : CustomDrag(icon, kDownloadItemCodeMask, kDownloadItemDragAction), + download_item_(item) { +} + +DownloadItemDrag::~DownloadItemDrag() { +} + +void DownloadItemDrag::OnDragDataGet( + GtkWidget* widget, GdkDragContext* context, + GtkSelectionData* selection_data, + guint target_type, guint time) { + OnDragDataGetForDownloadItem(selection_data, target_type, download_item_); +} + +// static +void DownloadItemDrag::SetSource(GtkWidget* widget, DownloadItem* item) { + gtk_drag_source_set(widget, GDK_BUTTON1_MASK, NULL, 0, + kDownloadItemDragAction); + gtk_dnd_util::SetSourceTargetListFromCodeMask(widget, kDownloadItemCodeMask); + g_signal_connect(widget, "drag-data-get", + G_CALLBACK(OnDragDataGetStandalone), item); +} + +// static +void DownloadItemDrag::BeginDrag(const DownloadItem* item, SkBitmap* icon) { + new DownloadItemDrag(item, icon); +} + +// BookmarkDrag ---------------------------------------------------------------- + +BookmarkDrag::BookmarkDrag(Profile* profile, + const std::vector<const BookmarkNode*>& nodes) + : CustomDrag(NULL, + bookmark_utils::GetCodeMask(false), + kBookmarkDragAction), + profile_(profile), + nodes_(nodes) { +} + +BookmarkDrag::~BookmarkDrag() { +} + +void BookmarkDrag::OnDragDataGet(GtkWidget* widget, GdkDragContext* context, + GtkSelectionData* selection_data, + guint target_type, guint time) { + bookmark_utils::WriteBookmarksToSelection(nodes_, selection_data, + target_type, profile_); +} + +// static +void BookmarkDrag::BeginDrag(Profile* profile, + const std::vector<const BookmarkNode*>& nodes) { + new BookmarkDrag(profile, nodes); +} + diff --git a/chrome/browser/gtk/custom_drag.h b/chrome/browser/gtk/custom_drag.h new file mode 100644 index 0000000..a43b0da --- /dev/null +++ b/chrome/browser/gtk/custom_drag.h @@ -0,0 +1,95 @@ +// Copyright (c) 2010 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 CHROME_BROWSER_GTK_CUSTOM_DRAG_H_ +#define CHROME_BROWSER_GTK_CUSTOM_DRAG_H_ + +#include <gtk/gtk.h> +#include <vector> + +#include "app/gtk_signal.h" +#include "base/basictypes.h" + +class BookmarkNode; +class DownloadItem; +class Profile; +class SkBitmap; + +// Base class for programatically generated drags. +class CustomDrag { + protected: + explicit CustomDrag(SkBitmap* icon, int code_mask, GdkDragAction action); + virtual ~CustomDrag(); + + virtual void OnDragDataGet(GtkWidget* widget, GdkDragContext* context, + GtkSelectionData* selection_data, + guint target_type, guint time) = 0; + + private: + CHROMEGTK_CALLBACK_1(CustomDrag, void, OnDragBegin, GdkDragContext*); + CHROMEGTK_CALLBACK_1(CustomDrag, void, OnDragEnd, GdkDragContext*); + + // Since this uses a virtual function, we can't use a macro. + static void OnDragDataGetThunk(GtkWidget* widget, GdkDragContext* context, + GtkSelectionData* selection_data, + guint target_type, guint time, + CustomDrag* custom_drag) { + return custom_drag->OnDragDataGet(widget, context, selection_data, + target_type, time); + } + + GtkWidget* drag_widget_; + GdkPixbuf* pixbuf_; + + DISALLOW_COPY_AND_ASSIGN(CustomDrag); +}; + +// Encapsulates functionality for drags of download items. +class DownloadItemDrag : public CustomDrag { + public: + // Sets |widget| as a source for drags pertaining to |item|. No + // DownloadItemDrag object is created. + static void SetSource(GtkWidget* widget, DownloadItem* item); + + // Creates a new DownloadItemDrag, the lifetime of which is tied to the + // system drag. + static void BeginDrag(const DownloadItem* item, SkBitmap* icon); + + private: + DownloadItemDrag(const DownloadItem* item, SkBitmap* icon); + virtual ~DownloadItemDrag(); + + virtual void OnDragDataGet(GtkWidget* widget, GdkDragContext* context, + GtkSelectionData* selection_data, + guint target_type, guint time); + + const DownloadItem* download_item_; + + DISALLOW_COPY_AND_ASSIGN(DownloadItemDrag); +}; + +// Encapsulates functionality for drags of one or more bookmarks. +class BookmarkDrag : public CustomDrag { + public: + // Creates a new BookmarkDrag, the lifetime of which is tied to the + // system drag. + static void BeginDrag(Profile* profile, + const std::vector<const BookmarkNode*>& nodes); + + private: + BookmarkDrag(Profile* profile, + const std::vector<const BookmarkNode*>& nodes); + virtual ~BookmarkDrag(); + + virtual void OnDragDataGet(GtkWidget* widget, GdkDragContext* context, + GtkSelectionData* selection_data, + guint target_type, guint time); + + Profile* profile_; + std::vector<const BookmarkNode*> nodes_; + + DISALLOW_COPY_AND_ASSIGN(BookmarkDrag); +}; + +#endif // CHROME_BROWSER_GTK_CUSTOM_DRAG_H_ diff --git a/chrome/browser/gtk/download_item_drag.cc b/chrome/browser/gtk/download_item_drag.cc deleted file mode 100644 index 24c312e..0000000 --- a/chrome/browser/gtk/download_item_drag.cc +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) 2010 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 "chrome/browser/gtk/download_item_drag.h" - -#include "app/gtk_dnd_util.h" -#include "base/utf_string_conversions.h" -#include "chrome/browser/download/download_manager.h" -#include "gfx/gtk_util.h" -#include "googleurl/src/gurl.h" -#include "net/base/net_util.h" -#include "third_party/skia/include/core/SkBitmap.h" - -namespace { - -const int kCodeMask = gtk_dnd_util::TEXT_URI_LIST | - gtk_dnd_util::CHROME_NAMED_URL; -const GdkDragAction kDragAction = GDK_ACTION_COPY; - -void OnDragDataGet(GtkWidget* widget, GdkDragContext* context, - GtkSelectionData* selection_data, - guint target_type, guint time, - DownloadItem* download_item) { - GURL url = net::FilePathToFileURL(download_item->full_path()); - gtk_dnd_util::WriteURLWithName(selection_data, url, - UTF8ToUTF16(download_item->GetFileName().value()), target_type); -} - -} // namespace - -// static -void DownloadItemDrag::SetSource(GtkWidget* widget, DownloadItem* item) { - gtk_drag_source_set(widget, GDK_BUTTON1_MASK, NULL, 0, - kDragAction); - gtk_dnd_util::SetSourceTargetListFromCodeMask(widget, kCodeMask); - g_signal_connect(widget, "drag-data-get", - G_CALLBACK(OnDragDataGet), item); -} - -// static -void DownloadItemDrag::BeginDrag(const DownloadItem* item, SkBitmap* icon) { - new DownloadItemDrag(item, icon); -} - -DownloadItemDrag::DownloadItemDrag(const DownloadItem* item, - SkBitmap* icon) - : drag_widget_(gtk_invisible_new()), - pixbuf_(gfx::GdkPixbufFromSkBitmap(icon)) { - g_object_ref_sink(drag_widget_); - g_signal_connect(drag_widget_, "drag-data-get", - G_CALLBACK(OnDragDataGet), const_cast<DownloadItem*>(item)); - g_signal_connect(drag_widget_, "drag-begin", - G_CALLBACK(OnDragBegin), this); - g_signal_connect(drag_widget_, "drag-end", - G_CALLBACK(OnDragEnd), this); - - GtkTargetList* list = gtk_dnd_util::GetTargetListFromCodeMask(kCodeMask); - GdkEvent* event = gtk_get_current_event(); - gtk_drag_begin(drag_widget_, list, kDragAction, 1, event); - if (event) - gdk_event_free(event); - gtk_target_list_unref(list); -} - -DownloadItemDrag::~DownloadItemDrag() { - g_object_unref(pixbuf_); - g_object_unref(drag_widget_); -} - -// static -void DownloadItemDrag::OnDragBegin(GtkWidget* widget, - GdkDragContext* drag_context, - DownloadItemDrag* drag) { - gtk_drag_set_icon_pixbuf(drag_context, drag->pixbuf_, 0, 0); -} - -// static -void DownloadItemDrag::OnDragEnd(GtkWidget* widget, - GdkDragContext* drag_context, - DownloadItemDrag* drag) { - delete drag; -} diff --git a/chrome/browser/gtk/download_item_drag.h b/chrome/browser/gtk/download_item_drag.h deleted file mode 100644 index 1f8df44..0000000 --- a/chrome/browser/gtk/download_item_drag.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2010 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 CHROME_BROWSER_GTK_DOWNLOAD_ITEM_DRAG_H_ -#define CHROME_BROWSER_GTK_DOWNLOAD_ITEM_DRAG_H_ - -#include <gtk/gtk.h> - -#include "base/basictypes.h" - -class DownloadItem; -class SkBitmap; - -class DownloadItemDrag { - public: - // Sets |widget| as a source for drags pertaining to |item|. No - // DownloadItemDrag object is created. - static void SetSource(GtkWidget* widget, DownloadItem* item); - - // Creates a new DownloadItemDrag, the lifetime of which is tied to the - // system drag. - static void BeginDrag(const DownloadItem* item, SkBitmap* icon); - - private: - explicit DownloadItemDrag(const DownloadItem* item, SkBitmap* icon); - ~DownloadItemDrag(); - - static void OnDragBegin(GtkWidget* widget, - GdkDragContext* drag_context, - DownloadItemDrag* drag); - - static void OnDragEnd(GtkWidget* widget, - GdkDragContext* drag_context, - DownloadItemDrag* drag); - - GtkWidget* drag_widget_; - GdkPixbuf* pixbuf_; - - DISALLOW_COPY_AND_ASSIGN(DownloadItemDrag); -}; - -#endif // CHROME_BROWSER_GTK_DOWNLOAD_ITEM_DRAG_H_ diff --git a/chrome/browser/gtk/download_item_gtk.cc b/chrome/browser/gtk/download_item_gtk.cc index 264b003..d996bc5 100644 --- a/chrome/browser/gtk/download_item_gtk.cc +++ b/chrome/browser/gtk/download_item_gtk.cc @@ -24,7 +24,7 @@ #include "chrome/browser/download/download_manager.h" #include "chrome/browser/download/download_shelf.h" #include "chrome/browser/download/download_util.h" -#include "chrome/browser/gtk/download_item_drag.h" +#include "chrome/browser/gtk/custom_drag.h" #include "chrome/browser/gtk/download_shelf_gtk.h" #include "chrome/browser/gtk/gtk_theme_provider.h" #include "chrome/browser/gtk/gtk_util.h" diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h index ff10230..b1a1148 100644 --- a/chrome/browser/renderer_host/render_view_host_delegate.h +++ b/chrome/browser/renderer_host/render_view_host_delegate.h @@ -17,6 +17,7 @@ #include "webkit/glue/window_open_disposition.h" struct BookmarkDragData; +class BookmarkNode; struct ContextMenuParams; class FilePath; class GURL; @@ -424,21 +425,10 @@ class RenderViewHostDelegate { class BookmarkDrag { public: - -#if defined(TOOLKIT_VIEWS) - typedef OSExchangeData DragData; -#elif defined(OS_LINUX) - // TODO(arv): GtkSelectionData? - class DragData {}; -#else - // TODO(arv): NSDraggingInfo? - class DragData {}; -#endif - - virtual void OnDragEnter(const DragData* data) = 0; - virtual void OnDragOver(const DragData* data) = 0; - virtual void OnDragLeave(const DragData* data) = 0; - virtual void OnDrop(const DragData* data) = 0; + virtual void OnDragEnter(const BookmarkDragData& data) = 0; + virtual void OnDragOver(const BookmarkDragData& data) = 0; + virtual void OnDragLeave(const BookmarkDragData& data) = 0; + virtual void OnDrop(const BookmarkDragData& data) = 0; }; // --------------------------------------------------------------------------- diff --git a/chrome/browser/tab_contents/web_drag_dest_gtk.cc b/chrome/browser/tab_contents/web_drag_dest_gtk.cc index 2bb5fa3..d96f6cf 100644 --- a/chrome/browser/tab_contents/web_drag_dest_gtk.cc +++ b/chrome/browser/tab_contents/web_drag_dest_gtk.cc @@ -9,6 +9,7 @@ #include "app/gtk_dnd_util.h" #include "base/file_path.h" #include "base/utf_string_conversions.h" +#include "chrome/browser/gtk/bookmark_utils_gtk.h" #include "chrome/browser/gtk/gtk_util.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/tab_contents.h" @@ -60,6 +61,10 @@ void WebDragDestGtk::UpdateDragStatus(WebDragOperation operation) { void WebDragDestGtk::DragLeave() { tab_contents_->render_view_host()->DragTargetDragLeave(); + + if (tab_contents_->GetBookmarkDragDelegate()) { + tab_contents_->GetBookmarkDragDelegate()->OnDragLeave(bookmark_drag_data_); + } } gboolean WebDragDestGtk::OnDragMotion(GtkWidget* sender, @@ -77,6 +82,7 @@ gboolean WebDragDestGtk::OnDragMotion(GtkWidget* sender, gtk_dnd_util::TEXT_HTML, gtk_dnd_util::NETSCAPE_URL, gtk_dnd_util::CHROME_NAMED_URL, + gtk_dnd_util::CHROME_BOOKMARK_ITEM, // TODO(estade): support image drags? }; @@ -87,12 +93,14 @@ gboolean WebDragDestGtk::OnDragMotion(GtkWidget* sender, time); } } else if (data_requests_ == 0) { + // TODO(snej): Pass appropriate DragOperation instead of hardcoding tab_contents_->render_view_host()-> DragTargetDragOver(gtk_util::ClientPoint(widget_), gtk_util::ScreenPoint(widget_), static_cast<WebDragOperation>( WebDragOperationCopy | WebDragOperationMove)); - // TODO(snej): Pass appropriate DragOperation instead of hardcoding + if (tab_contents_->GetBookmarkDragDelegate()) + tab_contents_->GetBookmarkDragDelegate()->OnDragOver(bookmark_drag_data_); drag_over_time_ = time; } @@ -160,19 +168,36 @@ void WebDragDestGtk::OnDragDataReceived( gtk_dnd_util::GetAtomForTarget(gtk_dnd_util::CHROME_NAMED_URL)) { gtk_dnd_util::ExtractNamedURL(data, &drop_data_->url, &drop_data_->url_title); + } else if (data->target == + gtk_dnd_util::GetAtomForTarget( + gtk_dnd_util::CHROME_BOOKMARK_ITEM)) { + bookmark_drag_data_.ReadFromVector( + bookmark_utils::GetNodesFromSelection( + NULL, data, + gtk_dnd_util::CHROME_BOOKMARK_ITEM, + tab_contents_->profile(), NULL, NULL)); + bookmark_drag_data_.SetOriginatingProfile(tab_contents_->profile()); } } if (data_requests_ == 0) { // Tell the renderer about the drag. // |x| and |y| are seemingly arbitrary at this point. + // TODO(snej): Pass appropriate DragOperation instead of hardcoding. tab_contents_->render_view_host()-> DragTargetDragEnter(*drop_data_.get(), gtk_util::ClientPoint(widget_), gtk_util::ScreenPoint(widget_), static_cast<WebDragOperation>( WebDragOperationCopy | WebDragOperationMove)); - // TODO(snej): Pass appropriate DragOperation instead of hardcoding + + // This is non-null if tab_contents_ is showing an ExtensionDOMUI with + // support for (at the moment experimental) drag and drop extensions. + if (tab_contents_->GetBookmarkDragDelegate()) { + tab_contents_->GetBookmarkDragDelegate()->OnDragEnter( + bookmark_drag_data_); + } + drag_over_time_ = time; } } @@ -202,6 +227,11 @@ gboolean WebDragDestGtk::OnDragDrop(GtkWidget* sender, GdkDragContext* context, DragTargetDrop(gtk_util::ClientPoint(widget_), gtk_util::ScreenPoint(widget_)); + // This is non-null if tab_contents_ is showing an ExtensionDOMUI with + // support for (at the moment experimental) drag and drop extensions. + if (tab_contents_->GetBookmarkDragDelegate()) + tab_contents_->GetBookmarkDragDelegate()->OnDrop(bookmark_drag_data_); + // The second parameter is just an educated guess, but at least we will // get the drag-end animation right sometimes. gtk_drag_finish(context, is_drop_target_, FALSE, time); diff --git a/chrome/browser/tab_contents/web_drag_dest_gtk.h b/chrome/browser/tab_contents/web_drag_dest_gtk.h index e8b0c3a..49607b2 100644 --- a/chrome/browser/tab_contents/web_drag_dest_gtk.h +++ b/chrome/browser/tab_contents/web_drag_dest_gtk.h @@ -6,13 +6,16 @@ #define CHROME_BROWSER_TAB_CONTENTS_WEB_DRAG_DEST_GTK_H_ #include <gtk/gtk.h> +#include <vector> #include "app/gtk_signal.h" #include "base/scoped_ptr.h" #include "base/task.h" +#include "chrome/browser/bookmarks/bookmark_drag_data.h" #include "third_party/WebKit/WebKit/chromium/public/WebDragOperation.h" #include "webkit/glue/webdropdata.h" +class BookmarkNode; class TabContents; // A helper class that handles DnD for drops in the renderer. In GTK parlance, @@ -80,6 +83,10 @@ class WebDragDestGtk { // |widget_| is. int destroy_handler_; + // The bookmark data for the current tab. This will be empty if there is not + // a native bookmark drag (or we haven't gotten the data from the source yet). + BookmarkDragData bookmark_drag_data_; + ScopedRunnableMethodFactory<WebDragDestGtk> method_factory_; DISALLOW_COPY_AND_ASSIGN(WebDragDestGtk); diff --git a/chrome/browser/tab_contents/web_drop_target_win.cc b/chrome/browser/tab_contents/web_drop_target_win.cc index f84a4b0..72d4e23 100644 --- a/chrome/browser/tab_contents/web_drop_target_win.cc +++ b/chrome/browser/tab_contents/web_drop_target_win.cc @@ -10,6 +10,7 @@ #include "app/clipboard/clipboard_util_win.h" #include "app/os_exchange_data.h" #include "app/os_exchange_data_provider_win.h" +#include "chrome/browser/bookmarks/bookmark_drag_data.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "gfx/point.h" @@ -122,7 +123,9 @@ DWORD WebDropTarget::OnDragEnter(IDataObject* data_object, // support for (at the moment experimental) drag and drop extensions. if (tab_contents_->GetBookmarkDragDelegate()) { OSExchangeData os_exchange_data(new OSExchangeDataProviderWin(data_object)); - tab_contents_->GetBookmarkDragDelegate()->OnDragEnter(&os_exchange_data); + BookmarkDragData bookmark_drag_data; + if (bookmark_drag_data.Read(os_exchange_data)) + tab_contents_->GetBookmarkDragDelegate()->OnDragEnter(bookmark_drag_data); } // We lie here and always return a DROPEFFECT because we don't want to @@ -150,7 +153,9 @@ DWORD WebDropTarget::OnDragOver(IDataObject* data_object, if (tab_contents_->GetBookmarkDragDelegate()) { OSExchangeData os_exchange_data(new OSExchangeDataProviderWin(data_object)); - tab_contents_->GetBookmarkDragDelegate()->OnDragOver(&os_exchange_data); + BookmarkDragData bookmark_drag_data; + if (bookmark_drag_data.Read(os_exchange_data)) + tab_contents_->GetBookmarkDragDelegate()->OnDragOver(bookmark_drag_data); } if (!is_drop_target_) @@ -172,7 +177,9 @@ void WebDropTarget::OnDragLeave(IDataObject* data_object) { if (tab_contents_->GetBookmarkDragDelegate()) { OSExchangeData os_exchange_data(new OSExchangeDataProviderWin(data_object)); - tab_contents_->GetBookmarkDragDelegate()->OnDragLeave(&os_exchange_data); + BookmarkDragData bookmark_drag_data; + if (bookmark_drag_data.Read(os_exchange_data)) + tab_contents_->GetBookmarkDragDelegate()->OnDragLeave(bookmark_drag_data); } } @@ -198,7 +205,9 @@ DWORD WebDropTarget::OnDrop(IDataObject* data_object, if (tab_contents_->GetBookmarkDragDelegate()) { OSExchangeData os_exchange_data(new OSExchangeDataProviderWin(data_object)); - tab_contents_->GetBookmarkDragDelegate()->OnDrop(&os_exchange_data); + BookmarkDragData bookmark_drag_data; + if (bookmark_drag_data.Read(os_exchange_data)) + tab_contents_->GetBookmarkDragDelegate()->OnDrop(bookmark_drag_data); } current_rvh_ = NULL; |