summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-28 00:45:35 +0000
committerestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-28 00:45:35 +0000
commit903e7a8a5f8948b96c46f16c4920648c29a5af12 (patch)
treed34d420a39ce4e3e8048ec5503d9c255617ca357 /chrome/browser
parentf05798163ceb52a2694e59c1a7f40ace72fb2024 (diff)
downloadchromium_src-903e7a8a5f8948b96c46f16c4920648c29a5af12.zip
chromium_src-903e7a8a5f8948b96c46f16c4920648c29a5af12.tar.gz
chromium_src-903e7a8a5f8948b96c46f16c4920648c29a5af12.tar.bz2
Gtk: DnD extravaganza
- Correctly update drag status for drags over renderer. This makes things look quite a bit better. - Rework the dnd utils so that we specify the drag targets in the order we prefer them (for destinations) - Refactor code in bookmark bar so folder and toolbar drags share more code - Allow bookmark bar to accept URI lists and plain text drags (for plain text we require the text to be a valid url) BUG=17431 Review URL: http://codereview.chromium.org/159419 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@21767 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/bookmarks/bookmark_utils.cc10
-rw-r--r--chrome/browser/bookmarks/bookmark_utils.h5
-rw-r--r--chrome/browser/gtk/bookmark_bar_gtk.cc132
-rw-r--r--chrome/browser/gtk/bookmark_bar_gtk.h26
-rw-r--r--chrome/browser/gtk/bookmark_manager_gtk.cc12
-rw-r--r--chrome/browser/gtk/bookmark_utils_gtk.cc29
-rw-r--r--chrome/browser/gtk/bookmark_utils_gtk.h8
-rw-r--r--chrome/browser/gtk/browser_toolbar_gtk.cc6
-rw-r--r--chrome/browser/gtk/gtk_dnd_util.cc73
-rw-r--r--chrome/browser/gtk/gtk_dnd_util.h11
-rw-r--r--chrome/browser/gtk/tabs/tab_strip_gtk.cc4
-rw-r--r--chrome/browser/tab_contents/tab_contents_view_gtk.cc23
12 files changed, 196 insertions, 143 deletions
diff --git a/chrome/browser/bookmarks/bookmark_utils.cc b/chrome/browser/bookmarks/bookmark_utils.cc
index f08560a..83d0bb3 100644
--- a/chrome/browser/bookmarks/bookmark_utils.cc
+++ b/chrome/browser/bookmarks/bookmark_utils.cc
@@ -28,6 +28,7 @@
#include "chrome/common/notification_service.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
+#include "grit/app_strings.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "net/base/net_util.h"
@@ -417,6 +418,15 @@ bool CanPasteFromClipboard(const BookmarkNode* node) {
#endif
}
+std::string GetNameForURL(const GURL& url) {
+ if (url.is_valid()) {
+ return WideToUTF8(net::GetSuggestedFilename(
+ url, std::string(), std::string(), std::wstring()));
+ } else {
+ return l10n_util::GetStringUTF8(IDS_APP_UNTITLED_SHORTCUT_FILE_NAME);
+ }
+}
+
std::vector<const BookmarkNode*> GetMostRecentlyModifiedGroups(
BookmarkModel* model,
size_t max_count) {
diff --git a/chrome/browser/bookmarks/bookmark_utils.h b/chrome/browser/bookmarks/bookmark_utils.h
index 97eec88..0c4ecab 100644
--- a/chrome/browser/bookmarks/bookmark_utils.h
+++ b/chrome/browser/bookmarks/bookmark_utils.h
@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_BOOKMARKS_BOOKMARK_UTILS_H_
#define CHROME_BROWSER_BOOKMARKS_BOOKMARK_UTILS_H_
+#include <string>
#include <vector>
#include "base/gfx/native_widget_types.h"
@@ -103,6 +104,10 @@ void PasteFromClipboard(BookmarkModel* model,
// Returns true if the user can copy from the pasteboard.
bool CanPasteFromClipboard(const BookmarkNode* node);
+// Returns a name for the given URL. Used for drags into bookmark areas when
+// the source doesn't specify a title.
+std::string GetNameForURL(const GURL& url);
+
// Returns a vector containing up to |max_count| of the most recently modified
// groups. This never returns an empty vector.
std::vector<const BookmarkNode*> GetMostRecentlyModifiedGroups(
diff --git a/chrome/browser/gtk/bookmark_bar_gtk.cc b/chrome/browser/gtk/bookmark_bar_gtk.cc
index 877d2af..5e2c736 100644
--- a/chrome/browser/gtk/bookmark_bar_gtk.cc
+++ b/chrome/browser/gtk/bookmark_bar_gtk.cc
@@ -48,6 +48,12 @@ const int kInstructionsPadding = 6;
// Color of the instructional text.
const GdkColor kInstructionsColor = GDK_COLOR_RGB(128, 128, 142);
+// The targets accepted by the toolbar and folder buttons for DnD.
+const int kDestTargetList[] = { GtkDndUtil::CHROME_BOOKMARK_ITEM,
+ GtkDndUtil::CHROME_NAMED_URL,
+ GtkDndUtil::TEXT_URI_LIST,
+ GtkDndUtil::TEXT_PLAIN, -1 };
+
void SetToolBarStyle() {
static bool style_was_set = false;
@@ -159,15 +165,13 @@ void BookmarkBarGtk::Init(Profile* profile) {
gtk_drag_dest_set(bookmark_toolbar_.get(), GTK_DEST_DEFAULT_DROP,
NULL, 0, GDK_ACTION_MOVE);
- GtkDndUtil::SetDestTargetListFromCodeMask(bookmark_toolbar_.get(),
- GtkDndUtil::CHROME_BOOKMARK_ITEM |
- GtkDndUtil::CHROME_NAMED_URL);
+ GtkDndUtil::SetDestTargetList(bookmark_toolbar_.get(), kDestTargetList);
g_signal_connect(bookmark_toolbar_.get(), "drag-motion",
G_CALLBACK(&OnToolbarDragMotion), this);
g_signal_connect(bookmark_toolbar_.get(), "drag-leave",
G_CALLBACK(&OnToolbarDragLeave), this);
g_signal_connect(bookmark_toolbar_.get(), "drag-data-received",
- G_CALLBACK(&OnToolbarDragReceived), this);
+ G_CALLBACK(&OnDragReceived), this);
g_signal_connect(bookmark_toolbar_.get(), "button-press-event",
G_CALLBACK(&OnButtonPressed), this);
@@ -449,11 +453,9 @@ GtkToolItem* BookmarkBarGtk::CreateBookmarkToolItem(const BookmarkNode* node) {
void BookmarkBarGtk::ConnectFolderButtonEvents(GtkWidget* widget) {
gtk_drag_dest_set(widget, GTK_DEST_DEFAULT_ALL, NULL, 0, GDK_ACTION_MOVE);
- GtkDndUtil::SetDestTargetListFromCodeMask(widget,
- GtkDndUtil::CHROME_BOOKMARK_ITEM |
- GtkDndUtil::CHROME_NAMED_URL);
+ GtkDndUtil::SetDestTargetList(widget, kDestTargetList);
g_signal_connect(widget, "drag-data-received",
- G_CALLBACK(&OnFolderDragReceived), this);
+ G_CALLBACK(&OnDragReceived), this);
// Connect to 'button-release-event' instead of 'clicked' because we need
// access to the modifier keys and we do different things on each
@@ -666,40 +668,6 @@ gboolean BookmarkBarGtk::OnFolderButtonReleased(GtkWidget* sender,
}
// static
-void BookmarkBarGtk::OnFolderDragReceived(GtkWidget* widget,
- GdkDragContext* context, gint x, gint y, GtkSelectionData* selection_data,
- guint target_type, guint time, BookmarkBarGtk* bar) {
- gboolean dnd_success = FALSE;
- gboolean delete_selection_data = FALSE;
-
- const BookmarkNode* dest_node = bar->GetNodeForToolButton(widget);
- DCHECK(dest_node->is_folder());
-
- if (target_type == GtkDndUtil::CHROME_BOOKMARK_ITEM) {
- std::vector<const BookmarkNode*> nodes =
- bookmark_utils::GetNodesFromSelection(context, selection_data,
- target_type,
- bar->profile_,
- &delete_selection_data,
- &dnd_success);
- DCHECK(!nodes.empty());
- DCHECK(dnd_success);
-
- for (std::vector<const BookmarkNode*>::iterator it = nodes.begin();
- it != nodes.end(); ++it) {
- bar->model_->Move(*it, dest_node, dest_node->GetChildCount());
- }
- } else if (target_type == GtkDndUtil::CHROME_NAMED_URL) {
- dnd_success = bookmark_utils::CreateNewBookmarkFromNamedUrl(
- selection_data, bar->model_, dest_node, dest_node->GetChildCount());
- } else {
- NOTREACHED();
- }
-
- gtk_drag_finish(context, dnd_success, delete_selection_data, time);
-}
-
-// static
gboolean BookmarkBarGtk::OnToolbarExpose(GtkWidget* widget,
GdkEventExpose* event,
BookmarkBarGtk* bar) {
@@ -771,36 +739,68 @@ void BookmarkBarGtk::OnToolbarDragLeave(GtkToolbar* toolbar,
}
// static
-void BookmarkBarGtk::OnToolbarDragReceived(GtkWidget* widget,
- GdkDragContext* context,
- gint x, gint y,
- GtkSelectionData* selection_data,
- guint target_type, guint time,
- BookmarkBarGtk* bar) {
+void BookmarkBarGtk::OnDragReceived(GtkWidget* widget,
+ GdkDragContext* context,
+ gint x, gint y,
+ GtkSelectionData* selection_data,
+ guint target_type, guint time,
+ BookmarkBarGtk* bar) {
gboolean dnd_success = FALSE;
gboolean delete_selection_data = FALSE;
- gint index = gtk_toolbar_get_drop_index(
+ const BookmarkNode* dest_node;
+ gint index;
+ if (widget == bar->bookmark_toolbar_.get()) {
+ dest_node = bar->model_->GetBookmarkBarNode();
+ index = gtk_toolbar_get_drop_index(
GTK_TOOLBAR(bar->bookmark_toolbar_.get()), x, y);
+ } else {
+ dest_node = bar->GetNodeForToolButton(widget);
+ index = dest_node->GetChildCount();
+ }
- if (target_type == GtkDndUtil::CHROME_BOOKMARK_ITEM) {
- std::vector<const BookmarkNode*> nodes =
- bookmark_utils::GetNodesFromSelection(context, selection_data,
- target_type,
- bar->profile_,
- &delete_selection_data,
- &dnd_success);
- DCHECK(!nodes.empty());
- for (std::vector<const BookmarkNode*>::iterator it = nodes.begin();
- it != nodes.end(); ++it) {
- bar->model_->Move(*it, bar->model_->GetBookmarkBarNode(), index);
- index = bar->model_->GetBookmarkBarNode()->IndexOfChild(*it) + 1;
+ switch (target_type) {
+ case GtkDndUtil::CHROME_BOOKMARK_ITEM: {
+ std::vector<const BookmarkNode*> nodes =
+ bookmark_utils::GetNodesFromSelection(context, selection_data,
+ target_type,
+ bar->profile_,
+ &delete_selection_data,
+ &dnd_success);
+ DCHECK(!nodes.empty());
+ for (std::vector<const BookmarkNode*>::iterator it = nodes.begin();
+ it != nodes.end(); ++it) {
+ bar->model_->Move(*it, dest_node, index);
+ index = dest_node->IndexOfChild(*it) + 1;
+ }
+ break;
+ }
+
+ case GtkDndUtil::CHROME_NAMED_URL: {
+ dnd_success = bookmark_utils::CreateNewBookmarkFromNamedUrl(
+ selection_data, bar->model_, dest_node, index);
+ break;
+ }
+
+ case GtkDndUtil::TEXT_URI_LIST: {
+ dnd_success = bookmark_utils::CreateNewBookmarksFromURIList(
+ selection_data, bar->model_, dest_node, index);
+ break;
+ }
+
+ case GtkDndUtil::TEXT_PLAIN: {
+ guchar* text = gtk_selection_data_get_text(selection_data);
+ GURL url(reinterpret_cast<char*>(text));
+ g_free(text);
+ // TODO(estade): It would be nice to head this case off at drag motion,
+ // so that it doesn't look like we can drag onto the bookmark bar.
+ if (!url.is_valid())
+ break;
+ std::string title = bookmark_utils::GetNameForURL(url);
+ bar->model_->AddURL(dest_node, index, UTF8ToWide(title), url);
+ dnd_success = TRUE;
+ break;
}
- } else if (target_type == GtkDndUtil::CHROME_NAMED_URL) {
- dnd_success = bookmark_utils::CreateNewBookmarkFromNamedUrl(
- selection_data, bar->model_, bar->model_->GetBookmarkBarNode(), index);
- } else {
- NOTREACHED();
}
gtk_drag_finish(context, dnd_success, delete_selection_data, time);
diff --git a/chrome/browser/gtk/bookmark_bar_gtk.h b/chrome/browser/gtk/bookmark_bar_gtk.h
index faac53a..5220b95 100644
--- a/chrome/browser/gtk/bookmark_bar_gtk.h
+++ b/chrome/browser/gtk/bookmark_bar_gtk.h
@@ -142,7 +142,7 @@ class BookmarkBarGtk : public AnimationDelegate,
void PopupMenuForNode(GtkWidget* sender, const BookmarkNode* node,
GdkEventButton* event);
- // GtkButton callbacks
+ // GtkButton callbacks.
static gboolean OnButtonPressed(GtkWidget* sender,
GdkEventButton* event,
BookmarkBarGtk* bar);
@@ -160,18 +160,12 @@ class BookmarkBarGtk : public AnimationDelegate,
guint target_type, guint time,
BookmarkBarGtk* bar);
- // GtkButton callbacks for folder buttons
+ // GtkButton callbacks for folder buttons.
static gboolean OnFolderButtonReleased(GtkWidget* sender,
GdkEventButton* event,
BookmarkBarGtk* bar);
- static void OnFolderDragReceived(GtkWidget* widget,
- GdkDragContext* context,
- gint x, gint y,
- GtkSelectionData* selection_data,
- guint target_type, guint time,
- BookmarkBarGtk* bar);
- // GtkToolbar callbacks
+ // GtkToolbar callbacks.
static gboolean OnToolbarExpose(GtkWidget* widget, GdkEventExpose* event,
BookmarkBarGtk* window);
static gboolean OnToolbarDragMotion(GtkToolbar* toolbar,
@@ -184,12 +178,14 @@ class BookmarkBarGtk : public AnimationDelegate,
GdkDragContext* context,
guint time,
BookmarkBarGtk* bar);
- static void OnToolbarDragReceived(GtkWidget* widget,
- GdkDragContext* context,
- gint x, gint y,
- GtkSelectionData* selection_data,
- guint target_type, guint time,
- BookmarkBarGtk* bar);
+
+ // Used for both folder buttons and the toolbar.
+ static void OnDragReceived(GtkWidget* widget,
+ GdkDragContext* context,
+ gint x, gint y,
+ GtkSelectionData* selection_data,
+ guint target_type, guint time,
+ BookmarkBarGtk* bar);
// GtkHBox callbacks.
static gboolean OnHBoxExpose(GtkWidget* widget, GdkEventExpose* event,
diff --git a/chrome/browser/gtk/bookmark_manager_gtk.cc b/chrome/browser/gtk/bookmark_manager_gtk.cc
index 25ae32f..ef58e88 100644
--- a/chrome/browser/gtk/bookmark_manager_gtk.cc
+++ b/chrome/browser/gtk/bookmark_manager_gtk.cc
@@ -54,6 +54,9 @@ const int kSearchDelayMS = 200;
// resizes the column.
const int kDefaultColumnWidth = 200;
+// The targets that the right tree view accepts for dragging.
+const int kDestTargetList[] = { GtkDndUtil::CHROME_BOOKMARK_ITEM, -1 };
+
// We only have one manager open at a time.
BookmarkManagerGtk* manager = NULL;
@@ -449,8 +452,7 @@ GtkWidget* BookmarkManagerGtk::MakeLeftPane() {
// The left side is only a drag destination (not a source).
gtk_drag_dest_set(left_tree_view_, GTK_DEST_DEFAULT_DROP,
NULL, 0, GDK_ACTION_MOVE);
- GtkDndUtil::SetDestTargetListFromCodeMask(left_tree_view_,
- GtkDndUtil::CHROME_BOOKMARK_ITEM);
+ GtkDndUtil::SetDestTargetList(left_tree_view_, kDestTargetList);
g_signal_connect(left_tree_view_, "drag-data-received",
G_CALLBACK(&OnLeftTreeViewDragReceived), this);
@@ -525,8 +527,7 @@ GtkWidget* BookmarkManagerGtk::MakeRightPane() {
GDK_BUTTON1_MASK,
NULL, 0, GDK_ACTION_MOVE);
GtkDndUtil::SetSourceTargetListFromCodeMask(
- right_tree_view_, GtkDndUtil::CHROME_BOOKMARK_ITEM |
- GtkDndUtil::TEXT_URI_LIST);
+ right_tree_view_, GtkDndUtil::CHROME_BOOKMARK_ITEM);
// 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.
@@ -618,8 +619,7 @@ void BookmarkManagerGtk::BuildRightStore() {
gtk_drag_dest_set(right_tree_view_, GTK_DEST_DEFAULT_ALL, NULL, 0,
GDK_ACTION_MOVE);
- GtkDndUtil::SetDestTargetListFromCodeMask(right_tree_view_,
- GtkDndUtil::CHROME_BOOKMARK_ITEM);
+ GtkDndUtil::SetDestTargetList(right_tree_view_, kDestTargetList);
} else {
SaveColumnConfiguration();
gtk_tree_view_column_set_visible(path_column_, TRUE);
diff --git a/chrome/browser/gtk/bookmark_utils_gtk.cc b/chrome/browser/gtk/bookmark_utils_gtk.cc
index fa2a56e..07e87ec 100644
--- a/chrome/browser/gtk/bookmark_utils_gtk.cc
+++ b/chrome/browser/gtk/bookmark_utils_gtk.cc
@@ -10,6 +10,7 @@
#include "base/string_util.h"
#include "chrome/browser/bookmarks/bookmark_drag_data.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/gtk/gtk_chrome_button.h"
#include "chrome/browser/gtk/gtk_dnd_util.h"
#include "chrome/browser/gtk/gtk_theme_provider.h"
@@ -209,7 +210,7 @@ void WriteBookmarksToSelection(const std::vector<const BookmarkNode*>& nodes,
for (size_t i = 0; i < nodes.size(); ++i) {
// If the node is a folder, this will be empty. TODO(estade): figure out
// if there are any ramifications to passing an empty URI. After a
- // lttle testing, it seems fine.
+ // little testing, it seems fine.
const GURL& url = nodes[i]->GetURL();
// This const cast should be safe as gtk_selection_data_set_uris()
// makes copies.
@@ -268,9 +269,31 @@ bool CreateNewBookmarkFromNamedUrl(GtkSelectionData* selection_data,
std::string title_utf8, url_utf8;
bool rv = data.ReadString(&iter, &title_utf8);
rv = rv && data.ReadString(&iter, &url_utf8);
- if (rv)
- model->AddURL(parent, idx, UTF8ToWide(title_utf8), GURL(url_utf8));
+ if (rv) {
+ GURL url(url_utf8);
+ if (title_utf8.empty())
+ title_utf8 = GetNameForURL(url);
+ model->AddURL(parent, idx, UTF8ToWide(title_utf8), url);
+ }
return rv;
}
+bool CreateNewBookmarksFromURIList(GtkSelectionData* selection_data,
+ BookmarkModel* model, const BookmarkNode* parent, int idx) {
+ gchar** uris = gtk_selection_data_get_uris(selection_data);
+ if (!uris) {
+ NOTREACHED();
+ return false;
+ }
+
+ for (size_t i = 0; uris[i] != NULL; ++i) {
+ GURL url(uris[i]);
+ std::string title = GetNameForURL(url);
+ model->AddURL(parent, idx++, UTF8ToWide(title), url);
+ }
+
+ g_strfreev(uris);
+ return true;
+}
+
} // namespace bookmark_utils
diff --git a/chrome/browser/gtk/bookmark_utils_gtk.h b/chrome/browser/gtk/bookmark_utils_gtk.h
index d2d0143..865a79e 100644
--- a/chrome/browser/gtk/bookmark_utils_gtk.h
+++ b/chrome/browser/gtk/bookmark_utils_gtk.h
@@ -83,6 +83,14 @@ bool CreateNewBookmarkFromNamedUrl(
const BookmarkNode* parent,
int idx);
+// Add the URIs in |selection_data| into the model at the given position. They
+// will be added whether or not the URL is valid.
+bool CreateNewBookmarksFromURIList(
+ GtkSelectionData* selection_data,
+ BookmarkModel* model,
+ const BookmarkNode* parent,
+ int idx);
+
} // namespace bookmark_utils
#endif // CHROME_BROWSER_GTK_BOOKMARK_UTILS_GTK_H_
diff --git a/chrome/browser/gtk/browser_toolbar_gtk.cc b/chrome/browser/gtk/browser_toolbar_gtk.cc
index 06200a6..dfaad68 100644
--- a/chrome/browser/gtk/browser_toolbar_gtk.cc
+++ b/chrome/browser/gtk/browser_toolbar_gtk.cc
@@ -452,9 +452,9 @@ void BrowserToolbarGtk::SetUpDragForHomeButton() {
// prefer URIs over plain text when both are available.
gtk_drag_dest_set(home_->widget(), GTK_DEST_DEFAULT_ALL,
NULL, 0, GDK_ACTION_COPY);
- GtkDndUtil::SetDestTargetListFromCodeMask(home_->widget(),
- GtkDndUtil::TEXT_PLAIN |
- GtkDndUtil::TEXT_URI_LIST);
+ static const int targets[] = { GtkDndUtil::TEXT_PLAIN,
+ GtkDndUtil::TEXT_URI_LIST, -1 };
+ GtkDndUtil::SetDestTargetList(home_->widget(), targets);
g_signal_connect(home_->widget(), "drag-data-received",
G_CALLBACK(OnDragDataReceived), this);
diff --git a/chrome/browser/gtk/gtk_dnd_util.cc b/chrome/browser/gtk/gtk_dnd_util.cc
index ebc2412..92a5602 100644
--- a/chrome/browser/gtk/gtk_dnd_util.cc
+++ b/chrome/browser/gtk/gtk_dnd_util.cc
@@ -6,17 +6,6 @@
#include "base/logging.h"
-namespace {
-
-void AddApplicationTarget(GtkTargetList* targets, int code_mask, int target) {
- if (code_mask & target) {
- gtk_target_list_add(targets, GtkDndUtil::GetAtomForTarget(target),
- GTK_TARGET_SAME_APP, target);
- }
-}
-
-} // namespace
-
// static
GdkAtom GtkDndUtil::GetAtomForTarget(int target) {
switch (target) {
@@ -61,34 +50,60 @@ GdkAtom GtkDndUtil::GetAtomForTarget(int target) {
GtkTargetList* GtkDndUtil::GetTargetListFromCodeMask(int code_mask) {
GtkTargetList* targets = gtk_target_list_new(NULL, 0);
- if (code_mask & TEXT_PLAIN)
- gtk_target_list_add_text_targets(targets, TEXT_PLAIN);
+ for (size_t i = 1; i < INVALID_TARGET; i = i << 1) {
+ if (i == CHROME_WEBDROP_FILE_CONTENTS)
+ continue;
- if (code_mask & TEXT_URI_LIST)
- gtk_target_list_add_uri_targets(targets, TEXT_URI_LIST);
-
- if (code_mask & TEXT_HTML)
- gtk_target_list_add(targets, GetAtomForTarget(TEXT_PLAIN), 0, TEXT_HTML);
-
- AddApplicationTarget(targets, code_mask, CHROME_TAB);
- AddApplicationTarget(targets, code_mask, CHROME_BOOKMARK_ITEM);
- AddApplicationTarget(targets, code_mask, CHROME_NAMED_URL);
+ if (i & code_mask)
+ AddTargetToList(targets, i);
+ }
return targets;
}
// static
-void GtkDndUtil::SetDestTargetListFromCodeMask(GtkWidget* dest,
- int code_mask) {
+void GtkDndUtil::SetSourceTargetListFromCodeMask(GtkWidget* source,
+ int code_mask) {
GtkTargetList* targets = GetTargetListFromCodeMask(code_mask);
- gtk_drag_dest_set_target_list(dest, targets);
+ gtk_drag_source_set_target_list(source, targets);
gtk_target_list_unref(targets);
}
// static
-void GtkDndUtil::SetSourceTargetListFromCodeMask(GtkWidget* source,
- int code_mask) {
- GtkTargetList* targets = GetTargetListFromCodeMask(code_mask);
- gtk_drag_source_set_target_list(source, targets);
+void GtkDndUtil::SetDestTargetList(GtkWidget* dest, const int* target_codes) {
+ GtkTargetList* targets = gtk_target_list_new(NULL, 0);
+
+ for (size_t i = 0; target_codes[i] != -1; ++i) {
+ AddTargetToList(targets, target_codes[i]);
+ }
+
+ gtk_drag_dest_set_target_list(dest, targets);
gtk_target_list_unref(targets);
}
+
+// static
+void GtkDndUtil::AddTargetToList(GtkTargetList* targets, int target_code) {
+ switch (target_code) {
+ case TEXT_PLAIN:
+ gtk_target_list_add_text_targets(targets, TEXT_PLAIN);
+ break;
+
+ case TEXT_URI_LIST:
+ gtk_target_list_add_uri_targets(targets, TEXT_URI_LIST);
+ break;
+
+ case TEXT_HTML:
+ gtk_target_list_add(targets, GetAtomForTarget(TEXT_PLAIN), 0, TEXT_HTML);
+ break;
+
+ case CHROME_TAB:
+ case CHROME_BOOKMARK_ITEM:
+ case CHROME_NAMED_URL:
+ gtk_target_list_add(targets, GtkDndUtil::GetAtomForTarget(target_code),
+ GTK_TARGET_SAME_APP, target_code);
+ break;
+
+ default:
+ NOTREACHED() << " Unexpected target code: " << target_code;
+ }
+}
diff --git a/chrome/browser/gtk/gtk_dnd_util.h b/chrome/browser/gtk/gtk_dnd_util.h
index 42432c7..2ac5433 100644
--- a/chrome/browser/gtk/gtk_dnd_util.h
+++ b/chrome/browser/gtk/gtk_dnd_util.h
@@ -21,6 +21,8 @@ class GtkDndUtil {
TEXT_PLAIN = 1 << 4,
TEXT_URI_LIST = 1 << 5,
TEXT_HTML = 1 << 6,
+
+ INVALID_TARGET = 1 << 7,
};
// Get the atom for a given target (of the above enum type). Will return NULL
@@ -35,13 +37,18 @@ class GtkDndUtil {
// of the client code to do the right thing.
static GtkTargetList* GetTargetListFromCodeMask(int code_mask);
- // Set the drag target list for |dest| or |source| with the target list that
+ // Set the drag target list for |source| with the target list that
// corresponds to |code_mask|.
- static void SetDestTargetListFromCodeMask(GtkWidget* dest, int code_mask);
static void SetSourceTargetListFromCodeMask(GtkWidget* source, int code_mask);
+ // Set the accepted targets list for |dest|. The |target_codes| array should
+ // be sorted in preference order and should be terminated with -1.
+ static void SetDestTargetList(GtkWidget* dest, const int* target_codes);
+
private:
GtkDndUtil();
+
+ static void AddTargetToList(GtkTargetList* targets, int target_code);
};
#endif // CHROME_BROWSER_GTK_GTK_DND_UTIL_H_
diff --git a/chrome/browser/gtk/tabs/tab_strip_gtk.cc b/chrome/browser/gtk/tabs/tab_strip_gtk.cc
index 27a1d02..3af798a 100644
--- a/chrome/browser/gtk/tabs/tab_strip_gtk.cc
+++ b/chrome/browser/gtk/tabs/tab_strip_gtk.cc
@@ -701,8 +701,8 @@ void TabStripGtk::Init() {
NULL, 0,
static_cast<GdkDragAction>(
GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK));
- GtkDndUtil::SetDestTargetListFromCodeMask(tabstrip_.get(),
- GtkDndUtil::TEXT_URI_LIST);
+ static const int targets[] = { GtkDndUtil::TEXT_URI_LIST, -1 };
+ GtkDndUtil::SetDestTargetList(tabstrip_.get(), targets);
g_signal_connect(G_OBJECT(tabstrip_.get()), "expose-event",
G_CALLBACK(OnExpose), this);
diff --git a/chrome/browser/tab_contents/tab_contents_view_gtk.cc b/chrome/browser/tab_contents/tab_contents_view_gtk.cc
index 5368233..7adc0a2 100644
--- a/chrome/browser/tab_contents/tab_contents_view_gtk.cc
+++ b/chrome/browser/tab_contents/tab_contents_view_gtk.cc
@@ -8,11 +8,11 @@
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
-#include "app/l10n_util.h"
#include "base/mime_util.h"
#include "base/gfx/point.h"
#include "base/gfx/rect.h"
#include "base/gfx/size.h"
+#include "base/pickle.h"
#include "base/string_util.h"
#include "build/build_config.h"
#include "chrome/browser/download/download_shelf.h"
@@ -34,8 +34,6 @@
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_source.h"
#include "chrome/common/notification_type.h"
-#include "grit/app_strings.h"
-#include "net/base/net_util.h"
#include "webkit/glue/webdropdata.h"
namespace {
@@ -231,7 +229,9 @@ class WebDragDest {
// TODO(estade): we might want to support other actions besides copy,
// but that would increase the cost of getting our drag success guess
// wrong.
- gdk_drag_status(context_, GDK_ACTION_COPY, drag_over_time_);
+ gdk_drag_status(context_, is_drop_target ? GDK_ACTION_COPY :
+ static_cast<GdkDragAction>(0),
+ drag_over_time_);
is_drop_target_ = false;
}
}
@@ -820,20 +820,9 @@ void TabContentsViewGtk::OnDragDataGet(
}
case GtkDndUtil::CHROME_NAMED_URL: {
- std::string name;
- const GURL& url = view->drop_data_->url;
- if (!view->drop_data_->url_title.empty()) {
- name = UTF16ToUTF8(view->drop_data_->url_title);
- } else if (url.is_valid()) {
- name = WideToUTF8(net::GetSuggestedFilename(
- url, std::string(), std::string(), std::wstring()));
- } else {
- // Nothing else can be done, just use a default.
- name = l10n_util::GetStringUTF8(IDS_APP_UNTITLED_SHORTCUT_FILE_NAME);
- }
Pickle pickle;
- pickle.WriteString(name);
- pickle.WriteString(url.spec());
+ pickle.WriteString(UTF16ToUTF8(view->drop_data_->url_title));
+ pickle.WriteString(view->drop_data_->url.spec());
gtk_selection_data_set(selection_data,
GtkDndUtil::GetAtomForTarget(GtkDndUtil::CHROME_NAMED_URL),
bits_per_byte,