OLD | NEW |
| (Empty) |
1 // Copyright 2013 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/download/download_item_drag.h" | |
6 | |
7 #include "base/files/file_path.h" | |
8 #include "base/strings/utf_string_conversions.h" | |
9 #include "chrome/browser/download/drag_download_item.h" | |
10 #include "content/public/browser/download_item.h" | |
11 #include "net/base/filename_util.h" | |
12 #include "ui/base/dragdrop/gtk_dnd_util.h" | |
13 #include "ui/gfx/image/image.h" | |
14 #include "url/gurl.h" | |
15 | |
16 using content::DownloadItem; | |
17 | |
18 namespace { | |
19 | |
20 const int kDownloadItemCodeMask = ui::TEXT_URI_LIST | ui::CHROME_NAMED_URL; | |
21 const GdkDragAction kDownloadItemDragAction = GDK_ACTION_COPY; | |
22 | |
23 } // namespace | |
24 | |
25 // Stores metadata for a drag & drop operation. | |
26 class DownloadItemDrag::DragData { | |
27 public: | |
28 // Constructs a DragData object based on the current state of |item|. | |
29 explicit DragData(const DownloadItem* item); | |
30 | |
31 // Sets up a drag source and connects |drag_data| to 'drag-data-get' on | |
32 // |widget|. If |icon| is non-NULL it will be used as the drag icon. The | |
33 // object pointed to by |drag_data| will be deleted when the signal is | |
34 // disconnected. | |
35 static void AttachToWidget(scoped_ptr<DragData> drag_data, | |
36 GtkWidget* widget, | |
37 gfx::Image* icon); | |
38 | |
39 // 'drag-data-get' signal handler. | |
40 CHROMEGTK_CALLBACK_4(DragData, void, OnDragDataGet, GdkDragContext*, | |
41 GtkSelectionData*, guint, guint); | |
42 | |
43 private: | |
44 // GClosureNotify handler for destroying a DragData object. |data| is assumed | |
45 // to be a DragData*. | |
46 static void OnDestroy(gpointer data, GClosure* closure); | |
47 | |
48 GURL url_; | |
49 base::string16 display_name_; | |
50 }; | |
51 | |
52 DownloadItemDrag::DragData::DragData(const DownloadItem* item) | |
53 : url_(net::FilePathToFileURL(item->GetTargetFilePath())), | |
54 display_name_(item->GetFileNameToReportUser().LossyDisplayName()) { | |
55 DCHECK_EQ(DownloadItem::COMPLETE, item->GetState()); | |
56 } | |
57 | |
58 // static | |
59 void DownloadItemDrag::DragData::AttachToWidget(scoped_ptr<DragData> drag_data, | |
60 GtkWidget* widget, | |
61 gfx::Image* icon) { | |
62 gtk_drag_source_set( | |
63 widget, GDK_BUTTON1_MASK, NULL, 0, kDownloadItemDragAction); | |
64 ui::SetSourceTargetListFromCodeMask(widget, kDownloadItemCodeMask); | |
65 | |
66 // Disconnect previous signal handlers, if any. | |
67 g_signal_handlers_disconnect_matched( | |
68 widget, | |
69 G_SIGNAL_MATCH_FUNC, | |
70 0, | |
71 0, | |
72 NULL, | |
73 reinterpret_cast<gpointer>(&OnDragDataGetThunk), | |
74 NULL); | |
75 | |
76 // Connect new signal handlers. | |
77 g_signal_connect_data(widget, | |
78 "drag-data-get", | |
79 G_CALLBACK(&OnDragDataGetThunk), | |
80 reinterpret_cast<gpointer>(drag_data.release()), | |
81 &OnDestroy, | |
82 static_cast<GConnectFlags>(0)); | |
83 | |
84 if (icon) | |
85 gtk_drag_source_set_icon_pixbuf(widget, icon->ToGdkPixbuf()); | |
86 } | |
87 | |
88 void DownloadItemDrag::DragData::OnDragDataGet(GtkWidget* widget, | |
89 GdkDragContext* context, | |
90 GtkSelectionData* selection_data, | |
91 guint target_type, | |
92 guint time) { | |
93 ui::WriteURLWithName(selection_data, url_, display_name_, target_type); | |
94 } | |
95 | |
96 // static | |
97 void DownloadItemDrag::DragData::OnDestroy(gpointer data, GClosure* closure) { | |
98 DragData* drag_data = reinterpret_cast<DragData*>(data); | |
99 delete drag_data; | |
100 } | |
101 | |
102 // DownloadItemDrag ------------------------------------------------------------ | |
103 | |
104 // static | |
105 void DownloadItemDrag::SetSource(GtkWidget* widget, | |
106 const DownloadItem* item, | |
107 gfx::Image* icon) { | |
108 scoped_ptr<DragData> drag_data(new DragData(item)); | |
109 DragData::AttachToWidget(drag_data.Pass(), widget, icon); | |
110 } | |
111 | |
112 DownloadItemDrag::DownloadItemDrag(const DownloadItem* item, gfx::Image* icon) | |
113 : CustomDrag(icon, kDownloadItemCodeMask, kDownloadItemDragAction), | |
114 drag_data_(new DragData(item)) {} | |
115 | |
116 DownloadItemDrag::~DownloadItemDrag() {} | |
117 | |
118 void DownloadItemDrag::OnDragDataGet(GtkWidget* widget, | |
119 GdkDragContext* context, | |
120 GtkSelectionData* selection_data, | |
121 guint target_type, | |
122 guint time) { | |
123 drag_data_->OnDragDataGet(widget, context, selection_data, target_type, time); | |
124 } | |
125 | |
126 void DragDownloadItem(const content::DownloadItem* download, | |
127 gfx::Image* icon, | |
128 gfx::NativeView view) { | |
129 // This starts the drag process, the lifetime of this object is tied to the | |
130 // system drag. | |
131 new DownloadItemDrag(download, icon); | |
132 } | |
OLD | NEW |