diff options
Diffstat (limited to 'chromium/content/browser/web_contents/web_drag_source_gtk.cc')
-rw-r--r-- | chromium/content/browser/web_contents/web_drag_source_gtk.cc | 403 |
1 files changed, 0 insertions, 403 deletions
diff --git a/chromium/content/browser/web_contents/web_drag_source_gtk.cc b/chromium/content/browser/web_contents/web_drag_source_gtk.cc deleted file mode 100644 index 2f9e58707f9..00000000000 --- a/chromium/content/browser/web_contents/web_drag_source_gtk.cc +++ /dev/null @@ -1,403 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/web_contents/web_drag_source_gtk.h" - -#include <string> - -#include "base/nix/mime_util_xdg.h" -#include "base/strings/utf_string_conversions.h" -#include "base/threading/thread_restrictions.h" -#include "content/browser/download/drag_download_file.h" -#include "content/browser/download/drag_download_util.h" -#include "content/browser/renderer_host/render_view_host_delegate.h" -#include "content/browser/renderer_host/render_view_host_impl.h" -#include "content/browser/web_contents/drag_utils_gtk.h" -#include "content/browser/web_contents/web_contents_impl.h" -#include "content/public/browser/content_browser_client.h" -#include "content/public/browser/web_contents_view.h" -#include "content/public/common/content_client.h" -#include "content/public/common/drop_data.h" -#include "net/base/file_stream.h" -#include "net/base/net_util.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "ui/base/clipboard/custom_data_helper.h" -#include "ui/base/dragdrop/gtk_dnd_util.h" -#include "ui/base/gtk/gtk_screen_util.h" -#include "ui/gfx/gtk_compat.h" -#include "ui/gfx/gtk_util.h" - -using blink::WebDragOperation; -using blink::WebDragOperationsMask; -using blink::WebDragOperationNone; - -namespace content { - -WebDragSourceGtk::WebDragSourceGtk(WebContents* web_contents) - : web_contents_(static_cast<WebContentsImpl*>(web_contents)), - drag_pixbuf_(NULL), - drag_failed_(false), - drag_widget_(gtk_invisible_new()), - drag_context_(NULL), - drag_icon_(gtk_window_new(GTK_WINDOW_POPUP)) { - signals_.Connect(drag_widget_, "drag-failed", - G_CALLBACK(OnDragFailedThunk), this); - signals_.Connect(drag_widget_, "drag-begin", - G_CALLBACK(OnDragBeginThunk), - this); - signals_.Connect(drag_widget_, "drag-end", - G_CALLBACK(OnDragEndThunk), this); - signals_.Connect(drag_widget_, "drag-data-get", - G_CALLBACK(OnDragDataGetThunk), this); - - signals_.Connect(drag_icon_, "expose-event", - G_CALLBACK(OnDragIconExposeThunk), this); -} - -WebDragSourceGtk::~WebDragSourceGtk() { - // Break the current drag, if any. - if (drop_data_) { - gtk_grab_add(drag_widget_); - gtk_grab_remove(drag_widget_); - base::MessageLoopForUI::current()->RemoveObserver(this); - drop_data_.reset(); - } - - gtk_widget_destroy(drag_widget_); - gtk_widget_destroy(drag_icon_); -} - -bool WebDragSourceGtk::StartDragging(const DropData& drop_data, - WebDragOperationsMask allowed_ops, - GdkEventButton* last_mouse_down, - const SkBitmap& image, - const gfx::Vector2d& image_offset) { - // Guard against re-starting before previous drag completed. - if (drag_context_) { - NOTREACHED(); - return false; - } - - int targets_mask = 0; - - if (!drop_data.text.string().empty()) - targets_mask |= ui::TEXT_PLAIN; - if (drop_data.url.is_valid()) { - targets_mask |= ui::TEXT_URI_LIST; - targets_mask |= ui::CHROME_NAMED_URL; - targets_mask |= ui::NETSCAPE_URL; - } - if (!drop_data.html.string().empty()) - targets_mask |= ui::TEXT_HTML; - if (!drop_data.file_contents.empty()) - targets_mask |= ui::CHROME_WEBDROP_FILE_CONTENTS; - if (!drop_data.download_metadata.empty() && - ParseDownloadMetadata(drop_data.download_metadata, - &wide_download_mime_type_, - &download_file_name_, - &download_url_)) { - targets_mask |= ui::DIRECT_SAVE_FILE; - } - if (!drop_data.custom_data.empty()) - targets_mask |= ui::CUSTOM_DATA; - - // NOTE: Begin a drag even if no targets present. Otherwise, things like - // draggable list elements will not work. - - drop_data_.reset(new DropData(drop_data)); - - // The image we get from WebKit makes heavy use of alpha-shading. This looks - // bad on non-compositing WMs. Fall back to the default drag icon. - if (!image.isNull() && ui::IsScreenComposited()) - drag_pixbuf_ = gfx::GdkPixbufFromSkBitmap(image); - image_offset_ = image_offset; - - GtkTargetList* list = ui::GetTargetListFromCodeMask(targets_mask); - if (targets_mask & ui::CHROME_WEBDROP_FILE_CONTENTS) { - // Looking up the mime type can hit the disk. http://crbug.com/84896 - base::ThreadRestrictions::ScopedAllowIO allow_io; - drag_file_mime_type_ = gdk_atom_intern( - base::nix::GetDataMimeType(drop_data.file_contents).c_str(), FALSE); - gtk_target_list_add(list, drag_file_mime_type_, - 0, ui::CHROME_WEBDROP_FILE_CONTENTS); - } - - drag_failed_ = false; - // If we don't pass an event, GDK won't know what event time to start grabbing - // mouse events. Technically it's the mouse motion event and not the mouse - // down event that causes the drag, but there's no reliable way to know - // *which* motion event initiated the drag, so this will have to do. - // TODO(estade): This can sometimes be very far off, e.g. if the user clicks - // and holds and doesn't start dragging for a long time. I doubt it matters - // much, but we should probably look into the possibility of getting the - // initiating event from webkit. - drag_context_ = gtk_drag_begin(drag_widget_, list, - WebDragOpToGdkDragAction(allowed_ops), - 1, // Drags are always initiated by the left button. - reinterpret_cast<GdkEvent*>(last_mouse_down)); - // The drag adds a ref; let it own the list. - gtk_target_list_unref(list); - - // Sometimes the drag fails to start; |context| will be NULL and we won't - // get a drag-end signal. - if (!drag_context_) { - drag_failed_ = true; - drop_data_.reset(); - return false; - } - - base::MessageLoopForUI::current()->AddObserver(this); - return true; -} - -void WebDragSourceGtk::WillProcessEvent(GdkEvent* event) { - // No-op. -} - -void WebDragSourceGtk::DidProcessEvent(GdkEvent* event) { - if (event->type != GDK_MOTION_NOTIFY) - return; - - GdkEventMotion* event_motion = reinterpret_cast<GdkEventMotion*>(event); - gfx::Point client = ui::ClientPoint(GetContentNativeView()); - - if (web_contents_) { - web_contents_->DragSourceMovedTo( - client.x(), client.y(), - static_cast<int>(event_motion->x_root), - static_cast<int>(event_motion->y_root)); - } -} - -void WebDragSourceGtk::OnDragDataGet(GtkWidget* sender, - GdkDragContext* context, - GtkSelectionData* selection_data, - guint target_type, - guint time) { - const int kBitsPerByte = 8; - - switch (target_type) { - case ui::TEXT_PLAIN: { - std::string utf8_text = UTF16ToUTF8(drop_data_->text.string()); - gtk_selection_data_set_text(selection_data, utf8_text.c_str(), - utf8_text.length()); - break; - } - - case ui::TEXT_HTML: { - // TODO(estade): change relative links to be absolute using - // |html_base_url|. - std::string utf8_text = UTF16ToUTF8(drop_data_->html.string()); - gtk_selection_data_set(selection_data, - ui::GetAtomForTarget(ui::TEXT_HTML), - kBitsPerByte, - reinterpret_cast<const guchar*>(utf8_text.c_str()), - utf8_text.length()); - break; - } - - case ui::TEXT_URI_LIST: - case ui::CHROME_NAMED_URL: - case ui::NETSCAPE_URL: { - ui::WriteURLWithName(selection_data, drop_data_->url, - drop_data_->url_title, target_type); - break; - } - - case ui::CHROME_WEBDROP_FILE_CONTENTS: { - gtk_selection_data_set( - selection_data, - drag_file_mime_type_, kBitsPerByte, - reinterpret_cast<const guchar*>(drop_data_->file_contents.data()), - drop_data_->file_contents.length()); - break; - } - - case ui::DIRECT_SAVE_FILE: { - char status_code = 'E'; - - // Retrieves the full file path (in file URL format) provided by the - // drop target by reading from the source window's XdndDirectSave0 - // property. - gint file_url_len = 0; - guchar* file_url_value = NULL; - if (gdk_property_get(context->source_window, - ui::GetAtomForTarget(ui::DIRECT_SAVE_FILE), - ui::GetAtomForTarget(ui::TEXT_PLAIN_NO_CHARSET), - 0, - 1024, - FALSE, - NULL, - NULL, - &file_url_len, - &file_url_value) && - file_url_value) { - // Convert from the file url to the file path. - GURL file_url(std::string(reinterpret_cast<char*>(file_url_value), - file_url_len)); - g_free(file_url_value); - base::FilePath file_path; - if (net::FileURLToFilePath(file_url, &file_path)) { - // Open the file as a stream. - scoped_ptr<net::FileStream> file_stream( - CreateFileStreamForDrop( - &file_path, - GetContentClient()->browser()->GetNetLog())); - if (file_stream) { - // Start downloading the file to the stream. - scoped_refptr<DragDownloadFile> drag_file_downloader = - new DragDownloadFile( - file_path, - file_stream.Pass(), - download_url_, - Referrer(web_contents_->GetURL(), - drop_data_->referrer_policy), - web_contents_->GetEncoding(), - web_contents_); - drag_file_downloader->Start( - new PromiseFileFinalizer(drag_file_downloader.get())); - - // Set the status code to success. - status_code = 'S'; - } - } - - // Return the status code to the file manager. - gtk_selection_data_set(selection_data, - gtk_selection_data_get_target(selection_data), - kBitsPerByte, - reinterpret_cast<guchar*>(&status_code), - 1); - } - break; - } - - case ui::CUSTOM_DATA: { - Pickle custom_data; - ui::WriteCustomDataToPickle(drop_data_->custom_data, &custom_data); - gtk_selection_data_set( - selection_data, - ui::GetAtomForTarget(ui::CUSTOM_DATA), - kBitsPerByte, - reinterpret_cast<const guchar*>(custom_data.data()), - custom_data.size()); - break; - } - - default: - NOTREACHED(); - } -} - -gboolean WebDragSourceGtk::OnDragFailed(GtkWidget* sender, - GdkDragContext* context, - GtkDragResult result) { - drag_failed_ = true; - - gfx::Point root = ui::ScreenPoint(GetContentNativeView()); - gfx::Point client = ui::ClientPoint(GetContentNativeView()); - - if (web_contents_) { - web_contents_->DragSourceEndedAt( - client.x(), client.y(), root.x(), root.y(), - WebDragOperationNone); - } - - // Let the native failure animation run. - return FALSE; -} - -void WebDragSourceGtk::OnDragBegin(GtkWidget* sender, - GdkDragContext* drag_context) { - if (!download_url_.is_empty()) { - // Generate the file name based on both mime type and proposed file name. - std::string default_name = - GetContentClient()->browser()->GetDefaultDownloadName(); - base::FilePath generated_download_file_name = - net::GenerateFileName(download_url_, - std::string(), - std::string(), - download_file_name_.value(), - UTF16ToUTF8(wide_download_mime_type_), - default_name); - - // Pass the file name to the drop target by setting the source window's - // XdndDirectSave0 property. - gdk_property_change(drag_context->source_window, - ui::GetAtomForTarget(ui::DIRECT_SAVE_FILE), - ui::GetAtomForTarget(ui::TEXT_PLAIN_NO_CHARSET), - 8, - GDK_PROP_MODE_REPLACE, - reinterpret_cast<const guchar*>( - generated_download_file_name.value().c_str()), - generated_download_file_name.value().length()); - } - - if (drag_pixbuf_) { - gtk_widget_set_size_request(drag_icon_, - gdk_pixbuf_get_width(drag_pixbuf_), - gdk_pixbuf_get_height(drag_pixbuf_)); - - // We only need to do this once. - if (!gtk_widget_get_realized(drag_icon_)) { - GdkScreen* screen = gtk_widget_get_screen(drag_icon_); - GdkColormap* rgba = gdk_screen_get_rgba_colormap(screen); - if (rgba) - gtk_widget_set_colormap(drag_icon_, rgba); - } - - gtk_drag_set_icon_widget(drag_context, drag_icon_, - image_offset_.x(), image_offset_.y()); - } -} - -void WebDragSourceGtk::OnDragEnd(GtkWidget* sender, - GdkDragContext* drag_context) { - if (drag_pixbuf_) { - g_object_unref(drag_pixbuf_); - drag_pixbuf_ = NULL; - } - - base::MessageLoopForUI::current()->RemoveObserver(this); - - if (!download_url_.is_empty()) { - gdk_property_delete(drag_context->source_window, - ui::GetAtomForTarget(ui::DIRECT_SAVE_FILE)); - } - - if (!drag_failed_) { - gfx::Point root = ui::ScreenPoint(GetContentNativeView()); - gfx::Point client = ui::ClientPoint(GetContentNativeView()); - - if (web_contents_) { - web_contents_->DragSourceEndedAt( - client.x(), client.y(), root.x(), root.y(), - GdkDragActionToWebDragOp(drag_context->action)); - } - } - - web_contents_->SystemDragEnded(); - - drop_data_.reset(); - drag_context_ = NULL; -} - -gfx::NativeView WebDragSourceGtk::GetContentNativeView() const { - return web_contents_->GetView()->GetContentNativeView(); -} - -gboolean WebDragSourceGtk::OnDragIconExpose(GtkWidget* sender, - GdkEventExpose* event) { - cairo_t* cr = gdk_cairo_create(event->window); - gdk_cairo_rectangle(cr, &event->area); - cairo_clip(cr); - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - gdk_cairo_set_source_pixbuf(cr, drag_pixbuf_, 0, 0); - cairo_paint(cr); - cairo_destroy(cr); - - return TRUE; -} - -} // namespace content |