summaryrefslogtreecommitdiffstats
path: root/chrome/browser/gtk/bookmark_menu_controller_gtk.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/gtk/bookmark_menu_controller_gtk.cc')
-rw-r--r--chrome/browser/gtk/bookmark_menu_controller_gtk.cc72
1 files changed, 67 insertions, 5 deletions
diff --git a/chrome/browser/gtk/bookmark_menu_controller_gtk.cc b/chrome/browser/gtk/bookmark_menu_controller_gtk.cc
index a0d905b..af9e97f 100644
--- a/chrome/browser/gtk/bookmark_menu_controller_gtk.cc
+++ b/chrome/browser/gtk/bookmark_menu_controller_gtk.cc
@@ -11,6 +11,8 @@
#include "base/gfx/gtk_util.h"
#include "base/string_util.h"
#include "chrome/browser/gtk/bookmark_context_menu.h"
+#include "chrome/browser/gtk/bookmark_utils_gtk.h"
+#include "chrome/browser/gtk/dnd_registry.h"
#include "chrome/browser/gtk/menu_gtk.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/page_navigator.h"
@@ -51,7 +53,8 @@ BookmarkMenuController::BookmarkMenuController(Browser* browser,
profile_(profile),
page_navigator_(navigator),
parent_window_(window),
- node_(node) {
+ node_(node),
+ ignore_button_release_(false) {
menu_.Own(gtk_menu_new());
BuildMenu(node, start_child_index, menu_.get());
gtk_widget_show_all(menu_.get());
@@ -103,6 +106,7 @@ void BookmarkMenuController::BuildMenu(const BookmarkNode* parent,
GtkWidget* menu_item = gtk_image_menu_item_new_with_label(
WideToUTF8(node->GetTitle()).c_str());
+ g_object_set_data(G_OBJECT(menu_item), "bookmark-node", AsVoid(node));
if (node->is_url()) {
SkBitmap icon = profile_->GetBookmarkModel()->GetFavIcon(node);
@@ -111,7 +115,6 @@ void BookmarkMenuController::BuildMenu(const BookmarkNode* parent,
GetBitmapNamed(IDR_DEFAULT_FAVICON);
}
SetImageMenuItem(menu_item, icon);
- g_object_set_data(G_OBJECT(menu_item), "bookmark-node", AsVoid(node));
g_signal_connect(G_OBJECT(menu_item), "activate",
G_CALLBACK(OnMenuItemActivated), this);
g_signal_connect(G_OBJECT(menu_item), "button-press-event",
@@ -130,6 +133,17 @@ void BookmarkMenuController::BuildMenu(const BookmarkNode* parent,
NOTREACHED();
}
+ gtk_drag_source_set(menu_item, GDK_BUTTON1_MASK,
+ NULL, 0, GDK_ACTION_MOVE);
+ dnd::SetSourceTargetListFromCodeMask(menu_item,
+ dnd::X_CHROME_BOOKMARK_ITEM);
+ g_signal_connect(G_OBJECT(menu_item), "drag-begin",
+ G_CALLBACK(&OnMenuItemDragBegin), this);
+ g_signal_connect(G_OBJECT(menu_item), "drag-end",
+ G_CALLBACK(&OnMenuItemDragEnd), this);
+ g_signal_connect(G_OBJECT(menu_item), "drag-data-get",
+ G_CALLBACK(&OnMenuItemDragGet), this);
+
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
node_to_menu_widget_map_[node] = menu_item;
}
@@ -146,6 +160,8 @@ gboolean BookmarkMenuController::OnButtonPressed(
GtkWidget* sender,
GdkEventButton* event,
BookmarkMenuController* controller) {
+ controller->ignore_button_release_ = false;
+
if (event->button == 3) {
// Show the right click menu and stop processing this button event.
const BookmarkNode* node = GetNodeFromMenuItem(sender);
@@ -168,9 +184,11 @@ gboolean BookmarkMenuController::OnButtonReleased(
GtkWidget* sender,
GdkEventButton* event,
BookmarkMenuController* controller) {
- // TODO(erg): The OnButtonPressed and OnButtonReleased handlers should have
- // the same guard code that prevents them from interfering with DnD as
- // BookmarkBarGtk's versions.
+ if (controller->ignore_button_release_) {
+ // Don't handle this message; it was a drag.
+ controller->ignore_button_release_ = false;
+ return FALSE;
+ }
// Releasing either button 1 or 2 should trigger the bookmark menu.
if (event->button == 1 || event->button == 2) {
@@ -191,3 +209,47 @@ void BookmarkMenuController::OnMenuItemActivated(
GtkMenuItem* menu_item, BookmarkMenuController* controller) {
controller->NavigateToMenuItem(GTK_WIDGET(menu_item), CURRENT_TAB);
}
+
+// static
+void BookmarkMenuController::OnMenuItemDragBegin(
+ GtkWidget* menu_item,
+ GdkDragContext* drag_context,
+ BookmarkMenuController* controller) {
+ // The parent menu item might be removed during the drag. Ref it so |button|
+ // won't get destroyed.
+ g_object_ref(menu_item->parent);
+
+ // Signal to any future OnButtonReleased calls that we're dragging instead of
+ // pressing.
+ controller->ignore_button_release_ = true;
+
+ const BookmarkNode* node = bookmark_utils::BookmarkNodeForWidget(menu_item);
+ GtkWidget* window = bookmark_utils::GetDragRepresentation(node,
+ controller->model_);
+ gint x, y;
+ gtk_widget_get_pointer(menu_item, &x, &y);
+ gtk_drag_set_icon_widget(drag_context, window, x, y);
+
+ // Hide our node.
+ gtk_widget_hide(menu_item);
+}
+
+// static
+void BookmarkMenuController::OnMenuItemDragEnd(
+ GtkWidget* menu_item,
+ GdkDragContext* drag_context,
+ BookmarkMenuController* controller) {
+ gtk_widget_show(menu_item);
+ g_object_unref(menu_item->parent);
+}
+
+// static
+void BookmarkMenuController::OnMenuItemDragGet(
+ GtkWidget* widget, GdkDragContext* context,
+ GtkSelectionData* selection_data,
+ guint target_type, guint time,
+ BookmarkMenuController* controller) {
+ const BookmarkNode* node = bookmark_utils::BookmarkNodeForWidget(widget);
+ bookmark_utils::WriteBookmarkToSelection(node, selection_data, target_type,
+ controller->profile_);
+}