OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/tab_contents/tab_contents_view_gtk.h" | 5 #include "chrome/browser/tab_contents/tab_contents_view_gtk.h" |
6 | 6 |
7 #include <gdk/gdk.h> | 7 #include <gdk/gdk.h> |
8 #include <gtk/gtk.h> | 8 #include <gtk/gtk.h> |
9 | 9 |
10 #include "base/mime_util.h" | 10 #include "base/mime_util.h" |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 dest->OnDragDataReceived(drag_context, x, y, data, info, time); | 172 dest->OnDragDataReceived(drag_context, x, y, data, info, time); |
173 } | 173 } |
174 | 174 |
175 // Called when a system drag crosses over the render view. As there is no drag | 175 // Called when a system drag crosses over the render view. As there is no drag |
176 // enter event, we treat it as an enter event (and not a regular motion event) | 176 // enter event, we treat it as an enter event (and not a regular motion event) |
177 // when |context_| is NULL. | 177 // when |context_| is NULL. |
178 gboolean OnDragMotion(GdkDragContext* context, gint x, gint y, guint time) { | 178 gboolean OnDragMotion(GdkDragContext* context, gint x, gint y, guint time) { |
179 if (context_ != context) { | 179 if (context_ != context) { |
180 context_ = context; | 180 context_ = context; |
181 drop_data_.reset(new WebDropData); | 181 drop_data_.reset(new WebDropData); |
182 data_requests_ = 0; | |
183 is_drop_target_ = false; | 182 is_drop_target_ = false; |
184 | 183 |
185 // TODO(estade): support other targets. When we start support URL drags, | 184 static int supported_targets[] = { |
186 // we'll have to worry about interstitial pages (see web_drop_target.cc). | 185 GtkDndUtil::X_CHROME_TEXT_PLAIN, |
187 data_requests_++; | 186 GtkDndUtil::X_CHROME_TEXT_URI_LIST, |
188 gtk_drag_get_data(widget_, context, | 187 GtkDndUtil::X_CHROME_TEXT_HTML, |
189 gdk_atom_intern("text/plain", FALSE), time); | 188 // TODO(estade): support image drags? |
| 189 }; |
| 190 |
| 191 data_requests_ = arraysize(supported_targets); |
| 192 for (size_t i = 0; i < arraysize(supported_targets); ++i) { |
| 193 gtk_drag_get_data(widget_, context, |
| 194 GtkDndUtil::GetAtomForTarget(supported_targets[i]), |
| 195 time); |
| 196 } |
190 } else if (data_requests_ == 0) { | 197 } else if (data_requests_ == 0) { |
191 tab_contents_->render_view_host()-> | 198 tab_contents_->render_view_host()-> |
192 DragTargetDragOver(ClientPoint(), ScreenPoint()); | 199 DragTargetDragOver(ClientPoint(), ScreenPoint()); |
193 drag_over_time_ = time; | 200 drag_over_time_ = time; |
194 } | 201 } |
195 | 202 |
196 // Pretend we are a drag destination because we don't want to wait for | 203 // Pretend we are a drag destination because we don't want to wait for |
197 // the renderer to tell us if we really are or not. | 204 // the renderer to tell us if we really are or not. |
198 return TRUE; | 205 return TRUE; |
199 } | 206 } |
200 | 207 |
201 // We make a series of requests for the drag data when the drag first enters | 208 // We make a series of requests for the drag data when the drag first enters |
202 // the render view. This is the callback that is used to give us the data | 209 // the render view. This is the callback that is used to give us the data |
203 // for each individual target. When |data_requests_| reaches 0, we know we | 210 // for each individual target. When |data_requests_| reaches 0, we know we |
204 // have attained all the data, and we can finally tell the renderer about the | 211 // have attained all the data, and we can finally tell the renderer about the |
205 // drag. | 212 // drag. |
206 void OnDragDataReceived(GdkDragContext* context, gint x, gint y, | 213 void OnDragDataReceived(GdkDragContext* context, gint x, gint y, |
207 GtkSelectionData* data, guint info, guint time) { | 214 GtkSelectionData* data, guint info, guint time) { |
208 // We might get the data from an old get_data() request that we no longer | 215 // We might get the data from an old get_data() request that we no longer |
209 // care about. | 216 // care about. |
210 if (context != context_) | 217 if (context != context_) |
211 return; | 218 return; |
212 | 219 |
213 data_requests_--; | 220 data_requests_--; |
214 | 221 |
215 // If the source can't provide us with valid data for a requested target, | 222 // Decode the data. |
216 // data->data will be NULL. | |
217 if (data->data) { | 223 if (data->data) { |
218 drop_data_->plain_text = UTF8ToUTF16(std::string( | 224 // If the source can't provide us with valid data for a requested target, |
219 reinterpret_cast<char*>(data->data), data->length)); | 225 // data->data will be NULL. |
| 226 if (data->target == |
| 227 GtkDndUtil::GetAtomForTarget(GtkDndUtil::X_CHROME_TEXT_PLAIN)) { |
| 228 guchar* text = gtk_selection_data_get_text(data); |
| 229 if (text) { |
| 230 drop_data_->plain_text = UTF8ToUTF16(std::string( |
| 231 reinterpret_cast<char*>(text), data->length)); |
| 232 g_free(text); |
| 233 } |
| 234 } else if (data->target == |
| 235 GtkDndUtil::GetAtomForTarget(GtkDndUtil::X_CHROME_TEXT_URI_LIST)) { |
| 236 gchar** uris = gtk_selection_data_get_uris(data); |
| 237 if (uris) { |
| 238 for (gchar** uri_iter = uris; *uri_iter; uri_iter++) { |
| 239 // TODO(estade): Can the filenames have a non-UTF8 encoding? |
| 240 drop_data_->filenames.push_back(UTF8ToUTF16(*uri_iter)); |
| 241 } |
| 242 // Also, write the first URI as the URL. |
| 243 if (uris[0]) |
| 244 drop_data_->url = GURL(uris[0]); |
| 245 g_strfreev(uris); |
| 246 } |
| 247 } else if (data->target == |
| 248 GtkDndUtil::GetAtomForTarget(GtkDndUtil::X_CHROME_TEXT_HTML)) { |
| 249 // TODO(estade): Can the html have a non-UTF8 encoding? |
| 250 drop_data_->text_html = UTF8ToUTF16(std::string( |
| 251 reinterpret_cast<char*>(data->data), data->length)); |
| 252 // We leave the base URL empty. |
| 253 } |
220 } | 254 } |
221 | 255 |
222 if (data_requests_ == 0) { | 256 if (data_requests_ == 0) { |
| 257 // Tell the renderer about the drag. |
223 // |x| and |y| are seemingly arbitrary at this point. | 258 // |x| and |y| are seemingly arbitrary at this point. |
224 tab_contents_->render_view_host()-> | 259 tab_contents_->render_view_host()-> |
225 DragTargetDragEnter(*drop_data_.get(), ClientPoint(), ScreenPoint()); | 260 DragTargetDragEnter(*drop_data_.get(), ClientPoint(), ScreenPoint()); |
226 drag_over_time_ = time; | 261 drag_over_time_ = time; |
227 } | 262 } |
228 } | 263 } |
229 | 264 |
230 // The drag has left our widget; forward this information to the renderer. | 265 // The drag has left our widget; forward this information to the renderer. |
231 void OnDragLeave(GdkDragContext* context, guint time) { | 266 void OnDragLeave(GdkDragContext* context, guint time) { |
232 // Set |context_| to NULL to make sure we will recognize the next DragMotion | 267 // Set |context_| to NULL to make sure we will recognize the next DragMotion |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
430 // animation. | 465 // animation. |
431 int x = 0; | 466 int x = 0; |
432 int y = 0; | 467 int y = 0; |
433 if (fixed_->window) | 468 if (fixed_->window) |
434 gdk_window_get_origin(fixed_->window, &x, &y); | 469 gdk_window_get_origin(fixed_->window, &x, &y); |
435 out->SetRect(x + fixed_->allocation.x, y + fixed_->allocation.y, | 470 out->SetRect(x + fixed_->allocation.x, y + fixed_->allocation.y, |
436 fixed_->allocation.width, fixed_->allocation.height); | 471 fixed_->allocation.width, fixed_->allocation.height); |
437 } | 472 } |
438 | 473 |
439 void TabContentsViewGtk::OnContentsDestroy() { | 474 void TabContentsViewGtk::OnContentsDestroy() { |
440 // TODO(estade): Windows uses this function cancel pending drag-n-drop drags. | 475 // TODO(estade): Windows uses this for some sort of plugin-related stuff. |
441 // We don't have drags yet, so do nothing for now. | |
442 } | 476 } |
443 | 477 |
444 void TabContentsViewGtk::SetPageTitle(const std::wstring& title) { | 478 void TabContentsViewGtk::SetPageTitle(const std::wstring& title) { |
445 // Set the window name to include the page title so it's easier to spot | 479 // Set the window name to include the page title so it's easier to spot |
446 // when debugging (e.g. via xwininfo -tree). | 480 // when debugging (e.g. via xwininfo -tree). |
447 gfx::NativeView content_view = GetContentNativeView(); | 481 gfx::NativeView content_view = GetContentNativeView(); |
448 if (content_view && content_view->window) | 482 if (content_view && content_view->window) |
449 gdk_window_set_title(content_view->window, WideToUTF8(title).c_str()); | 483 gdk_window_set_title(content_view->window, WideToUTF8(title).c_str()); |
450 } | 484 } |
451 | 485 |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
734 gtk_container_child_set_property(GTK_CONTAINER(floating_container), | 768 gtk_container_child_set_property(GTK_CONTAINER(floating_container), |
735 widget, "x", &value); | 769 widget, "x", &value); |
736 | 770 |
737 int child_y = std::max(half_view_height - (requisition.height / 2), 0); | 771 int child_y = std::max(half_view_height - (requisition.height / 2), 0); |
738 g_value_set_int(&value, child_y); | 772 g_value_set_int(&value, child_y); |
739 gtk_container_child_set_property(GTK_CONTAINER(floating_container), | 773 gtk_container_child_set_property(GTK_CONTAINER(floating_container), |
740 widget, "y", &value); | 774 widget, "y", &value); |
741 g_value_unset(&value); | 775 g_value_unset(&value); |
742 } | 776 } |
743 } | 777 } |
OLD | NEW |