Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(273)

Side by Side Diff: ui/views/widget/drop_target_gtk.cc

Issue 9728002: Removing deprecated GTK-Views code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/views/widget/drop_target_gtk.h ('k') | ui/views/widget/gtk_views_fixed.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 "ui/views/widget/drop_target_gtk.h"
6
7 #include <algorithm>
8 #include <iterator>
9 #include <string>
10 #include <vector>
11
12 #include "base/file_path.h"
13 #include "base/utf_string_conversions.h"
14 #include "net/base/net_util.h"
15 #include "ui/base/dragdrop/drag_drop_types.h"
16 #include "ui/base/dragdrop/gtk_dnd_util.h"
17 #include "ui/base/dragdrop/os_exchange_data_provider_gtk.h"
18 #include "ui/gfx/point.h"
19 #include "ui/views/widget/native_widget_gtk.h"
20 #include "ui/views/widget/root_view.h"
21
22 using ui::OSExchangeData;
23
24 namespace {
25
26 std::string GdkAtomToString(GdkAtom atom) {
27 gchar* c_name = gdk_atom_name(atom);
28 std::string name(c_name);
29 g_free(c_name);
30 return name;
31 }
32
33 // Returns true if |name| is a known name of plain text.
34 bool IsTextType(const std::string& name) {
35 return name == "text/plain" || name == "TEXT" ||
36 name == "STRING" || name == "UTF8_STRING" ||
37 name == "text/plain;charset=utf-8";
38 }
39
40 // Returns the OSExchangeData::Formats in |targets| and all the
41 // OSExchangeData::CustomFormats in |type_set|.
42 int CalculateTypes(GList* targets, std::set<GdkAtom>* type_set) {
43 int types = 0;
44 for (GList* element = targets; element;
45 element = g_list_next(element)) {
46 GdkAtom atom = static_cast<GdkAtom>(element->data);
47 type_set->insert(atom);
48 if (atom == GDK_TARGET_STRING) {
49 types |= OSExchangeData::STRING;
50 } else if (atom == ui::GetAtomForTarget(ui::CHROME_NAMED_URL)) {
51 types |= OSExchangeData::URL;
52 } else if (atom == ui::GetAtomForTarget(ui::TEXT_URI_LIST)) {
53 // TEXT_URI_LIST is used for files as well as urls.
54 types |= OSExchangeData::URL | OSExchangeData::FILE_NAME;
55 } else {
56 std::string target_name = GdkAtomToString(atom);
57 if (IsTextType(target_name)) {
58 types |= OSExchangeData::STRING;
59 } else {
60 // Assume any unknown data is pickled.
61 types |= OSExchangeData::PICKLED_DATA;
62 }
63 }
64 }
65 return types;
66 }
67
68 } // namespace
69
70 namespace views {
71
72 DropTargetGtk::DropTargetGtk(internal::RootView* root_view,
73 GdkDragContext* context)
74 : helper_(root_view),
75 requested_formats_(0),
76 waiting_for_data_(false),
77 received_drop_(false),
78 pending_view_(NULL) {
79 std::set<GdkAtom> all_formats;
80 int source_formats = CalculateTypes(context->targets, &all_formats);
81 data_.reset(new OSExchangeData(new OSExchangeDataProviderGtk(
82 source_formats, all_formats)));
83 }
84
85 DropTargetGtk::~DropTargetGtk() {
86 }
87
88 void DropTargetGtk::ResetTargetViewIfEquals(View* view) {
89 helper_.ResetTargetViewIfEquals(view);
90 }
91
92 void DropTargetGtk::OnDragDataReceived(GdkDragContext* context,
93 gint x,
94 gint y,
95 GtkSelectionData* data,
96 guint info,
97 guint time) {
98 std::string target_name = GdkAtomToString(data->type);
99 if (data->type == GDK_TARGET_STRING || IsTextType(target_name)) {
100 guchar* text_data = gtk_selection_data_get_text(data);
101 string16 result;
102 if (text_data) {
103 char* as_char = reinterpret_cast<char*>(text_data);
104 UTF8ToUTF16(as_char, strlen(as_char), &result);
105 g_free(text_data);
106 }
107 data_provider().SetString(result);
108 } else if (requested_custom_formats_.find(data->type) !=
109 requested_custom_formats_.end()) {
110 Pickle result;
111 if (data->length > 0)
112 result = Pickle(reinterpret_cast<char*>(data->data), data->length);
113 data_provider().SetPickledData(data->type, result);
114 } else if (data->type == ui::GetAtomForTarget(ui::CHROME_NAMED_URL)) {
115 GURL url;
116 string16 title;
117 ui::ExtractNamedURL(data, &url, &title);
118 data_provider().SetURL(url, title);
119 } else if (data->type == ui::GetAtomForTarget(ui::TEXT_URI_LIST)) {
120 std::vector<GURL> urls;
121 ui::ExtractURIList(data, &urls);
122 if (urls.size() == 1 && urls[0].is_valid()) {
123 data_provider().SetURL(urls[0], string16());
124
125 // TEXT_URI_LIST is used for files as well as urls.
126 if (urls[0].SchemeIsFile()) {
127 FilePath file_path;
128 if (net::FileURLToFilePath(urls[0], &file_path))
129 data_provider().SetFilename(file_path);
130 }
131 } else {
132 // Consumers of OSExchangeData will see this as an invalid URL. That is,
133 // when GetURL is invoked on the OSExchangeData this triggers false to
134 // be returned.
135 data_provider().SetURL(GURL(), string16());
136 }
137 }
138
139 if (!data_->HasAllFormats(requested_formats_, requested_custom_formats_))
140 return; // Waiting on more data.
141
142 int drag_operation = ui::DragDropTypes::GdkDragActionToDragOperation(
143 context->actions);
144 gfx::Point root_view_location(x, y);
145 drag_operation = helper_.OnDragOver(*data_, root_view_location,
146 drag_operation);
147 GdkDragAction gdk_action = static_cast<GdkDragAction>(
148 ui::DragDropTypes::DragOperationToGdkDragAction(drag_operation));
149 if (!received_drop_)
150 gdk_drag_status(context, gdk_action, time);
151
152 waiting_for_data_ = false;
153
154 if (pending_view_ && received_drop_) {
155 FinishDrop(context, x, y, time);
156 // WARNING: we've been deleted.
157 return;
158 }
159 }
160
161 gboolean DropTargetGtk::OnDragDrop(GdkDragContext* context,
162 gint x,
163 gint y,
164 guint time) {
165 received_drop_ = true;
166 OnDragMotion(context, x, y, time);
167 if (!pending_view_) {
168 // User isn't over a view, no drop can occur.
169 static_cast<NativeWidgetGtk*>(
170 helper_.root_view()->GetWidget()->native_widget())->ResetDropTarget();
171 // WARNING: we've been deleted.
172 return FALSE;
173 }
174
175 if (!waiting_for_data_) {
176 // We've got all the data now.
177 FinishDrop(context, x, y, time);
178 // WARNING: we've been deleted.
179 return TRUE;
180 }
181 // We're waiting on data.
182 return TRUE;
183 }
184
185 void DropTargetGtk::OnDragLeave(GdkDragContext* context, guint time) {
186 helper_.OnDragExit();
187 }
188
189 gboolean DropTargetGtk::OnDragMotion(GdkDragContext* context,
190 gint x,
191 gint y,
192 guint time) {
193 waiting_for_data_ = false;
194 gfx::Point root_view_location(x, y);
195 pending_view_ =
196 helper_.CalculateTargetView(root_view_location, *data_, false);
197 if (pending_view_ &&
198 (received_drop_ || (pending_view_ != helper_.target_view() &&
199 pending_view_->AreDropTypesRequired()))) {
200 // The target requires drop types before it can answer CanDrop,
201 // ask for the data now.
202 int formats = 0;
203 std::set<GdkAtom> custom_formats;
204 pending_view_->GetDropFormats(&formats, &custom_formats);
205 IntersectFormats(data_provider().known_formats(),
206 data_provider().known_custom_formats(),
207 &formats, &custom_formats);
208 if (!data_provider().HasDataForAllFormats(formats, custom_formats)) {
209 if (!received_drop_)
210 helper_.OnDragExit();
211
212 // The target needs data for all the types before it can test if the
213 // drop is valid, but we don't have all the data. Request the data
214 // now. When we get back the data we'll update the target.
215 RequestFormats(context, formats, custom_formats, time);
216
217 waiting_for_data_ = true;
218
219 return TRUE;
220 }
221 }
222
223 int drag_operation = ui::DragDropTypes::GdkDragActionToDragOperation(
224 context->actions);
225 drag_operation = helper_.OnDragOver(*data_, root_view_location,
226 drag_operation);
227 if (!received_drop_) {
228 GdkDragAction gdk_action =
229 static_cast<GdkDragAction>(
230 ui::DragDropTypes::DragOperationToGdkDragAction(drag_operation));
231 gdk_drag_status(context, gdk_action, time);
232 }
233 return TRUE;
234 }
235
236 void DropTargetGtk::FinishDrop(GdkDragContext* context,
237 gint x, gint y, guint time) {
238 gfx::Point root_view_location(x, y);
239 int drag_operation = ui::DragDropTypes::GdkDragActionToDragOperation(
240 context->actions);
241 drag_operation = helper_.OnDrop(*data_, root_view_location,
242 drag_operation);
243 GdkDragAction gdk_action =
244 static_cast<GdkDragAction>(
245 ui::DragDropTypes::DragOperationToGdkDragAction(drag_operation));
246 gtk_drag_finish(context, gdk_action != 0, (gdk_action & GDK_ACTION_MOVE),
247 time);
248
249 static_cast<NativeWidgetGtk*>(helper_.root_view()->GetWidget()->
250 native_widget())->ResetDropTarget();
251 // WARNING: we've been deleted.
252 }
253
254 void DropTargetGtk::IntersectFormats(int f1, const std::set<GdkAtom>& cf1,
255 int* f2, std::set<GdkAtom>* cf2) {
256 *f2 = (*f2 & f1);
257 std::set<GdkAtom> cf;
258 std::set_intersection(
259 cf1.begin(), cf1.end(), cf2->begin(), cf2->end(),
260 std::insert_iterator<std::set<GdkAtom> >(cf, cf.begin()));
261 cf.swap(*cf2);
262 }
263
264 void DropTargetGtk::RequestFormats(GdkDragContext* context,
265 int formats,
266 const std::set<GdkAtom>& custom_formats,
267 guint time) {
268 GtkWidget* widget = static_cast<NativeWidgetGtk*>(helper_.root_view()->
269 GetWidget()->native_widget())->window_contents();
270
271 const std::set<GdkAtom>& known_formats =
272 data_provider().known_custom_formats();
273 if ((formats & OSExchangeData::STRING) != 0 &&
274 (requested_formats_ & OSExchangeData::STRING) == 0) {
275 requested_formats_ |= OSExchangeData::STRING;
276 if (known_formats.count(gdk_atom_intern("UTF8_STRING", false))) {
277 gtk_drag_get_data(widget, context,
278 gdk_atom_intern("UTF8_STRING", false), time);
279 } else if (known_formats.count(gdk_atom_intern("text/plain;charset=utf-8",
280 false))) {
281 gtk_drag_get_data(widget, context,
282 gdk_atom_intern("text/plain;charset=utf-8", false),
283 time);
284 } else if (known_formats.count(GDK_TARGET_STRING)) {
285 gtk_drag_get_data(widget, context, GDK_TARGET_STRING, time);
286 } else if (known_formats.count(gdk_atom_intern("text/plain", false))) {
287 gtk_drag_get_data(widget, context, gdk_atom_intern("text/plain", false),
288 time);
289 } else if (known_formats.count(gdk_atom_intern("TEXT", false))) {
290 gtk_drag_get_data(widget, context, gdk_atom_intern("TEXT", false),
291 time);
292 } else if (known_formats.count(gdk_atom_intern("STRING", false))) {
293 gtk_drag_get_data(widget, context, gdk_atom_intern("STRING", false),
294 time);
295 }
296 }
297 if ((formats & OSExchangeData::URL) != 0 &&
298 (requested_formats_ & OSExchangeData::URL) == 0) {
299 requested_formats_ |= OSExchangeData::URL;
300 if (known_formats.count(ui::GetAtomForTarget(ui::CHROME_NAMED_URL))) {
301 gtk_drag_get_data(widget, context,
302 ui::GetAtomForTarget(ui::CHROME_NAMED_URL), time);
303 } else if (known_formats.count(
304 ui::GetAtomForTarget(ui::TEXT_URI_LIST))) {
305 gtk_drag_get_data(widget, context,
306 ui::GetAtomForTarget(ui::TEXT_URI_LIST), time);
307 }
308 }
309 if (((formats & OSExchangeData::FILE_NAME) != 0) &&
310 (requested_formats_ & OSExchangeData::FILE_NAME) == 0) {
311 requested_formats_ |= OSExchangeData::FILE_NAME;
312 gtk_drag_get_data(widget, context,
313 ui::GetAtomForTarget(ui::TEXT_URI_LIST), time);
314 }
315 for (std::set<GdkAtom>::const_iterator i = custom_formats.begin();
316 i != custom_formats.end(); ++i) {
317 if (requested_custom_formats_.find(*i) ==
318 requested_custom_formats_.end()) {
319 requested_custom_formats_.insert(*i);
320 gtk_drag_get_data(widget, context, *i, time);
321 }
322 }
323 }
324
325 OSExchangeDataProviderGtk& DropTargetGtk::data_provider() const {
326 return static_cast<OSExchangeDataProviderGtk&>(data_->provider());
327 }
328
329 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/widget/drop_target_gtk.h ('k') | ui/views/widget/gtk_views_fixed.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698