1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/gtk/custom_drag.h" 6 7 #include "base/utf_string_conversions.h" 8 #include "chrome/browser/download/download_item.h" 9 #include "chrome/browser/ui/gtk/bookmarks/bookmark_utils_gtk.h" 10 #include "googleurl/src/gurl.h" 11 #include "net/base/net_util.h" 12 #include "third_party/skia/include/core/SkBitmap.h" 13 #include "ui/base/dragdrop/gtk_dnd_util.h" 14 #include "ui/gfx/gtk_util.h" 15 #include "ui/gfx/image.h" 16 17 namespace { 18 19 const int kDownloadItemCodeMask = ui::TEXT_URI_LIST | ui::CHROME_NAMED_URL; 20 const GdkDragAction kDownloadItemDragAction = GDK_ACTION_COPY; 21 const GdkDragAction kBookmarkDragAction = 22 static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE); 23 24 void OnDragDataGetForDownloadItem(GtkSelectionData* selection_data, 25 guint target_type, 26 const DownloadItem* download_item) { 27 GURL url = net::FilePathToFileURL(download_item->full_path()); 28 ui::WriteURLWithName(selection_data, url, 29 UTF8ToUTF16(download_item->GetFileNameToReportUser().value()), 30 target_type); 31 } 32 33 void OnDragDataGetStandalone(GtkWidget* widget, GdkDragContext* context, 34 GtkSelectionData* selection_data, 35 guint target_type, guint time, 36 const DownloadItem* item) { 37 OnDragDataGetForDownloadItem(selection_data, target_type, item); 38 } 39 40 } // namespace 41 42 // CustomDrag ------------------------------------------------------------------ 43 44 CustomDrag::CustomDrag(gfx::Image* icon, int code_mask, GdkDragAction action) 45 : drag_widget_(gtk_invisible_new()), 46 image_(icon) { 47 g_signal_connect(drag_widget_, "drag-data-get", 48 G_CALLBACK(OnDragDataGetThunk), this); 49 g_signal_connect(drag_widget_, "drag-begin", 50 G_CALLBACK(OnDragBeginThunk), this); 51 g_signal_connect(drag_widget_, "drag-end", 52 G_CALLBACK(OnDragEndThunk), this); 53 54 GtkTargetList* list = ui::GetTargetListFromCodeMask(code_mask); 55 GdkEvent* event = gtk_get_current_event(); 56 gtk_drag_begin(drag_widget_, list, action, 1, event); 57 if (event) 58 gdk_event_free(event); 59 gtk_target_list_unref(list); 60 } 61 62 CustomDrag::~CustomDrag() { 63 gtk_widget_destroy(drag_widget_); 64 } 65 66 void CustomDrag::OnDragBegin(GtkWidget* widget, GdkDragContext* drag_context) { 67 if (image_) 68 gtk_drag_set_icon_pixbuf(drag_context, *image_, 0, 0); 69 } 70 71 void CustomDrag::OnDragEnd(GtkWidget* widget, GdkDragContext* drag_context) { 72 delete this; 73 } 74 75 // DownloadItemDrag ------------------------------------------------------------ 76 77 DownloadItemDrag::DownloadItemDrag(const DownloadItem* item, 78 gfx::Image* icon) 79 : CustomDrag(icon, kDownloadItemCodeMask, kDownloadItemDragAction), 80 download_item_(item) { 81 } 82 83 DownloadItemDrag::~DownloadItemDrag() { 84 } 85 86 void DownloadItemDrag::OnDragDataGet( 87 GtkWidget* widget, GdkDragContext* context, 88 GtkSelectionData* selection_data, 89 guint target_type, guint time) { 90 OnDragDataGetForDownloadItem(selection_data, target_type, download_item_); 91 } 92 93 // static 94 void DownloadItemDrag::SetSource(GtkWidget* widget, 95 DownloadItem* item, 96 gfx::Image* icon) { 97 gtk_drag_source_set(widget, GDK_BUTTON1_MASK, NULL, 0, 98 kDownloadItemDragAction); 99 ui::SetSourceTargetListFromCodeMask(widget, kDownloadItemCodeMask); 100 101 // Disconnect previous signal handlers, if any. 102 g_signal_handlers_disconnect_by_func( 103 widget, 104 reinterpret_cast<gpointer>(OnDragDataGetStandalone), 105 item); 106 // Connect new signal handlers. 107 g_signal_connect(widget, "drag-data-get", 108 G_CALLBACK(OnDragDataGetStandalone), item); 109 110 if (icon) 111 gtk_drag_source_set_icon_pixbuf(widget, *icon); 112 } 113 114 // static 115 void DownloadItemDrag::BeginDrag(const DownloadItem* item, gfx::Image* icon) { 116 new DownloadItemDrag(item, icon); 117 } 118 119 // BookmarkDrag ---------------------------------------------------------------- 120 121 BookmarkDrag::BookmarkDrag(Profile* profile, 122 const std::vector<const BookmarkNode*>& nodes) 123 : CustomDrag(NULL, 124 bookmark_utils::GetCodeMask(false), 125 kBookmarkDragAction), 126 profile_(profile), 127 nodes_(nodes) { 128 } 129 130 BookmarkDrag::~BookmarkDrag() { 131 } 132 133 void BookmarkDrag::OnDragDataGet(GtkWidget* widget, GdkDragContext* context, 134 GtkSelectionData* selection_data, 135 guint target_type, guint time) { 136 bookmark_utils::WriteBookmarksToSelection(nodes_, selection_data, 137 target_type, profile_); 138 } 139 140 // static 141 void BookmarkDrag::BeginDrag(Profile* profile, 142 const std::vector<const BookmarkNode*>& nodes) { 143 new BookmarkDrag(profile, nodes); 144 } 145