OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/gtk/custom_drag.h" | 5 #include "chrome/browser/ui/gtk/download/download_item_drag.h" |
6 | 6 |
7 #include "base/files/file_path.h" | 7 #include "base/files/file_path.h" |
8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
9 #include "chrome/browser/ui/gtk/bookmarks/bookmark_utils_gtk.h" | |
10 #include "content/public/browser/download_item.h" | 9 #include "content/public/browser/download_item.h" |
11 #include "net/base/net_util.h" | 10 #include "net/base/net_util.h" |
12 #include "third_party/skia/include/core/SkBitmap.h" | |
13 #include "ui/base/dragdrop/gtk_dnd_util.h" | 11 #include "ui/base/dragdrop/gtk_dnd_util.h" |
14 #include "ui/gfx/gtk_util.h" | |
15 #include "ui/gfx/image/image.h" | 12 #include "ui/gfx/image/image.h" |
16 #include "url/gurl.h" | 13 #include "url/gurl.h" |
17 | 14 |
18 using content::DownloadItem; | 15 using content::DownloadItem; |
19 | 16 |
20 namespace { | 17 namespace { |
21 | 18 |
22 const int kDownloadItemCodeMask = ui::TEXT_URI_LIST | ui::CHROME_NAMED_URL; | 19 const int kDownloadItemCodeMask = ui::TEXT_URI_LIST | ui::CHROME_NAMED_URL; |
23 const GdkDragAction kDownloadItemDragAction = GDK_ACTION_COPY; | 20 const GdkDragAction kDownloadItemDragAction = GDK_ACTION_COPY; |
24 const GdkDragAction kBookmarkDragAction = | |
25 static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE); | |
26 | 21 |
27 } // namespace | 22 } // namespace |
28 | 23 |
29 // CustomDrag ------------------------------------------------------------------ | |
30 | |
31 CustomDrag::CustomDrag(gfx::Image* icon, int code_mask, GdkDragAction action) | |
32 : drag_widget_(gtk_invisible_new()), | |
33 image_(icon) { | |
34 g_signal_connect(drag_widget_, "drag-data-get", | |
35 G_CALLBACK(OnDragDataGetThunk), this); | |
36 g_signal_connect(drag_widget_, "drag-begin", | |
37 G_CALLBACK(OnDragBeginThunk), this); | |
38 g_signal_connect(drag_widget_, "drag-end", | |
39 G_CALLBACK(OnDragEndThunk), this); | |
40 | |
41 GtkTargetList* list = ui::GetTargetListFromCodeMask(code_mask); | |
42 GdkEvent* event = gtk_get_current_event(); | |
43 gtk_drag_begin(drag_widget_, list, action, 1, event); | |
44 if (event) | |
45 gdk_event_free(event); | |
46 gtk_target_list_unref(list); | |
47 } | |
48 | |
49 CustomDrag::~CustomDrag() { | |
50 gtk_widget_destroy(drag_widget_); | |
51 } | |
52 | |
53 void CustomDrag::OnDragBegin(GtkWidget* widget, GdkDragContext* drag_context) { | |
54 if (image_) | |
55 gtk_drag_set_icon_pixbuf(drag_context, image_->ToGdkPixbuf(), 0, 0); | |
56 } | |
57 | |
58 void CustomDrag::OnDragEnd(GtkWidget* widget, GdkDragContext* drag_context) { | |
59 delete this; | |
60 } | |
61 | |
62 // DownloadItemDrag ------------------------------------------------------------ | |
63 | |
64 // Stores metadata for a drag & drop operation. | 24 // Stores metadata for a drag & drop operation. |
65 class DownloadItemDrag::DragData { | 25 class DownloadItemDrag::DragData { |
66 public: | 26 public: |
67 // Constructs a DragData object based on the current state of |item|. | 27 // Constructs a DragData object based on the current state of |item|. |
68 explicit DragData(const DownloadItem* item); | 28 explicit DragData(const DownloadItem* item); |
69 | 29 |
70 // 'drag-data-get' signal handler. | |
71 CHROMEGTK_CALLBACK_4(DragData, void, OnDragDataGet, GdkDragContext*, | |
72 GtkSelectionData*, guint, guint); | |
73 | |
74 // Sets up a drag source and connects |drag_data| to 'drag-data-get' on | 30 // Sets up a drag source and connects |drag_data| to 'drag-data-get' on |
75 // |widget|. If |icon| is non-NULL it will be used as the drag icon. The | 31 // |widget|. If |icon| is non-NULL it will be used as the drag icon. The |
76 // object pointed to by |drag_data| will be deleted when the signal is | 32 // object pointed to by |drag_data| will be deleted when the signal is |
77 // disconnected. | 33 // disconnected. |
78 static void AttachToWidget(scoped_ptr<DragData> drag_data, | 34 static void AttachToWidget(scoped_ptr<DragData> drag_data, |
79 GtkWidget* widget, | 35 GtkWidget* widget, |
80 gfx::Image* icon); | 36 gfx::Image* icon); |
81 | 37 |
| 38 // 'drag-data-get' signal handler. |
| 39 CHROMEGTK_CALLBACK_4(DragData, void, OnDragDataGet, GdkDragContext*, |
| 40 GtkSelectionData*, guint, guint); |
| 41 |
82 private: | 42 private: |
83 // GClosureNotify handler for destroying a DragData object. |data| is assumed | 43 // GClosureNotify handler for destroying a DragData object. |data| is assumed |
84 // to be a DragData*. | 44 // to be a DragData*. |
85 static void OnDestroy(gpointer data, GClosure* closure); | 45 static void OnDestroy(gpointer data, GClosure* closure); |
86 | 46 |
87 GURL url_; | 47 GURL url_; |
88 string16 display_name_; | 48 base::string16 display_name_; |
89 }; | 49 }; |
90 | 50 |
91 DownloadItemDrag::DragData::DragData(const DownloadItem* item) | 51 DownloadItemDrag::DragData::DragData(const DownloadItem* item) |
92 : url_(net::FilePathToFileURL(item->GetTargetFilePath())), | 52 : url_(net::FilePathToFileURL(item->GetTargetFilePath())), |
93 display_name_(item->GetFileNameToReportUser().LossyDisplayName()) { | 53 display_name_(item->GetFileNameToReportUser().LossyDisplayName()) { |
94 DCHECK_EQ(DownloadItem::COMPLETE, item->GetState()); | 54 DCHECK_EQ(DownloadItem::COMPLETE, item->GetState()); |
95 } | 55 } |
96 | 56 |
| 57 // static |
| 58 void DownloadItemDrag::DragData::AttachToWidget(scoped_ptr<DragData> drag_data, |
| 59 GtkWidget* widget, |
| 60 gfx::Image* icon) { |
| 61 gtk_drag_source_set( |
| 62 widget, GDK_BUTTON1_MASK, NULL, 0, kDownloadItemDragAction); |
| 63 ui::SetSourceTargetListFromCodeMask(widget, kDownloadItemCodeMask); |
| 64 |
| 65 // Disconnect previous signal handlers, if any. |
| 66 g_signal_handlers_disconnect_matched( |
| 67 widget, |
| 68 G_SIGNAL_MATCH_FUNC, |
| 69 0, |
| 70 0, |
| 71 NULL, |
| 72 reinterpret_cast<gpointer>(&OnDragDataGetThunk), |
| 73 NULL); |
| 74 |
| 75 // Connect new signal handlers. |
| 76 g_signal_connect_data(widget, |
| 77 "drag-data-get", |
| 78 G_CALLBACK(&OnDragDataGetThunk), |
| 79 reinterpret_cast<gpointer>(drag_data.release()), |
| 80 &OnDestroy, |
| 81 static_cast<GConnectFlags>(0)); |
| 82 |
| 83 if (icon) |
| 84 gtk_drag_source_set_icon_pixbuf(widget, icon->ToGdkPixbuf()); |
| 85 } |
| 86 |
97 void DownloadItemDrag::DragData::OnDragDataGet(GtkWidget* widget, | 87 void DownloadItemDrag::DragData::OnDragDataGet(GtkWidget* widget, |
98 GdkDragContext* context, | 88 GdkDragContext* context, |
99 GtkSelectionData* selection_data, | 89 GtkSelectionData* selection_data, |
100 guint target_type, | 90 guint target_type, |
101 guint time) { | 91 guint time) { |
102 ui::WriteURLWithName(selection_data, url_, display_name_, target_type); | 92 ui::WriteURLWithName(selection_data, url_, display_name_, target_type); |
103 } | 93 } |
104 | 94 |
105 // static | 95 // static |
106 void DownloadItemDrag::DragData::AttachToWidget(scoped_ptr<DragData> drag_data, | |
107 GtkWidget* widget, | |
108 gfx::Image* icon) { | |
109 gtk_drag_source_set(widget, GDK_BUTTON1_MASK, NULL, 0, | |
110 kDownloadItemDragAction); | |
111 ui::SetSourceTargetListFromCodeMask(widget, kDownloadItemCodeMask); | |
112 | |
113 // Disconnect previous signal handlers, if any. | |
114 g_signal_handlers_disconnect_matched( | |
115 widget, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, | |
116 reinterpret_cast<gpointer>(&OnDragDataGetThunk), | |
117 NULL); | |
118 | |
119 // Connect new signal handlers. | |
120 g_signal_connect_data( | |
121 widget, "drag-data-get", | |
122 G_CALLBACK(&OnDragDataGetThunk), | |
123 reinterpret_cast<gpointer>(drag_data.release()), | |
124 &OnDestroy, | |
125 static_cast<GConnectFlags>(0)); | |
126 | |
127 if (icon) | |
128 gtk_drag_source_set_icon_pixbuf(widget, icon->ToGdkPixbuf()); | |
129 } | |
130 | |
131 // static | |
132 void DownloadItemDrag::DragData::OnDestroy(gpointer data, GClosure* closure) { | 96 void DownloadItemDrag::DragData::OnDestroy(gpointer data, GClosure* closure) { |
133 DragData* drag_data = reinterpret_cast<DragData*>(data); | 97 DragData* drag_data = reinterpret_cast<DragData*>(data); |
134 delete drag_data; | 98 delete drag_data; |
135 } | 99 } |
136 | 100 |
137 DownloadItemDrag::DownloadItemDrag(const DownloadItem* item, | 101 // DownloadItemDrag ------------------------------------------------------------ |
138 gfx::Image* icon) | |
139 : CustomDrag(icon, kDownloadItemCodeMask, kDownloadItemDragAction), | |
140 drag_data_(new DragData(item)) { | |
141 } | |
142 | |
143 DownloadItemDrag::~DownloadItemDrag() { | |
144 } | |
145 | |
146 void DownloadItemDrag::OnDragDataGet( | |
147 GtkWidget* widget, GdkDragContext* context, | |
148 GtkSelectionData* selection_data, | |
149 guint target_type, guint time) { | |
150 drag_data_->OnDragDataGet(widget, context, selection_data, target_type, time); | |
151 } | |
152 | 102 |
153 // static | 103 // static |
154 void DownloadItemDrag::SetSource(GtkWidget* widget, | 104 void DownloadItemDrag::SetSource(GtkWidget* widget, |
155 const DownloadItem* item, | 105 const DownloadItem* item, |
156 gfx::Image* icon) { | 106 gfx::Image* icon) { |
157 scoped_ptr<DragData> drag_data(new DragData(item)); | 107 scoped_ptr<DragData> drag_data(new DragData(item)); |
158 DragData::AttachToWidget(drag_data.Pass(), widget, icon); | 108 DragData::AttachToWidget(drag_data.Pass(), widget, icon); |
159 } | 109 } |
160 | 110 |
161 // static | 111 // static |
162 void DownloadItemDrag::BeginDrag(const DownloadItem* item, gfx::Image* icon) { | 112 void DownloadItemDrag::BeginDrag(const DownloadItem* item, gfx::Image* icon) { |
163 new DownloadItemDrag(item, icon); | 113 new DownloadItemDrag(item, icon); |
164 } | 114 } |
165 | 115 |
166 // BookmarkDrag ---------------------------------------------------------------- | 116 DownloadItemDrag::DownloadItemDrag(const DownloadItem* item, gfx::Image* icon) |
| 117 : CustomDrag(icon, kDownloadItemCodeMask, kDownloadItemDragAction), |
| 118 drag_data_(new DragData(item)) {} |
167 | 119 |
168 BookmarkDrag::BookmarkDrag(Profile* profile, | 120 DownloadItemDrag::~DownloadItemDrag() {} |
169 const std::vector<const BookmarkNode*>& nodes) | |
170 : CustomDrag(NULL, GetCodeMask(false), kBookmarkDragAction), | |
171 profile_(profile), | |
172 nodes_(nodes) {} | |
173 | 121 |
174 BookmarkDrag::~BookmarkDrag() { | 122 void DownloadItemDrag::OnDragDataGet(GtkWidget* widget, |
| 123 GdkDragContext* context, |
| 124 GtkSelectionData* selection_data, |
| 125 guint target_type, |
| 126 guint time) { |
| 127 drag_data_->OnDragDataGet(widget, context, selection_data, target_type, time); |
175 } | 128 } |
176 | |
177 void BookmarkDrag::OnDragDataGet(GtkWidget* widget, | |
178 GdkDragContext* context, | |
179 GtkSelectionData* selection_data, | |
180 guint target_type, | |
181 guint time) { | |
182 WriteBookmarksToSelection(nodes_, selection_data, target_type, profile_); | |
183 } | |
184 | |
185 // static | |
186 void BookmarkDrag::BeginDrag(Profile* profile, | |
187 const std::vector<const BookmarkNode*>& nodes) { | |
188 new BookmarkDrag(profile, nodes); | |
189 } | |
OLD | NEW |