Home | History | Annotate | Download | only in gtk
      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 "chrome/browser/ui/gtk/custom_drag.h"
      6 
      7 #include "base/utf_string_conversions.h"
      8 #include "chrome/browser/download/download_item.h"
      9 #include "chrome/browser/ui/gtk/bookmarks/bookmark_utils_gtk.h"
     10 #include "googleurl/src/gurl.h"
     11 #include "net/base/net_util.h"
     12 #include "third_party/skia/include/core/SkBitmap.h"
     13 #include "ui/base/dragdrop/gtk_dnd_util.h"
     14 #include "ui/gfx/gtk_util.h"
     15 #include "ui/gfx/image.h"
     16 
     17 namespace {
     18 
     19 const int kDownloadItemCodeMask = ui::TEXT_URI_LIST | ui::CHROME_NAMED_URL;
     20 const GdkDragAction kDownloadItemDragAction = GDK_ACTION_COPY;
     21 const GdkDragAction kBookmarkDragAction =
     22     static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE);
     23 
     24 void OnDragDataGetForDownloadItem(GtkSelectionData* selection_data,
     25                                   guint target_type,
     26                                   const DownloadItem* download_item) {
     27   GURL url = net::FilePathToFileURL(download_item->full_path());
     28   ui::WriteURLWithName(selection_data, url,
     29       UTF8ToUTF16(download_item->GetFileNameToReportUser().value()),
     30       target_type);
     31 }
     32 
     33 void OnDragDataGetStandalone(GtkWidget* widget, GdkDragContext* context,
     34                              GtkSelectionData* selection_data,
     35                              guint target_type, guint time,
     36                              const DownloadItem* item) {
     37   OnDragDataGetForDownloadItem(selection_data, target_type, item);
     38 }
     39 
     40 }  // namespace
     41 
     42 // CustomDrag ------------------------------------------------------------------
     43 
     44 CustomDrag::CustomDrag(gfx::Image* icon, int code_mask, GdkDragAction action)
     45     : drag_widget_(gtk_invisible_new()),
     46       image_(icon) {
     47   g_signal_connect(drag_widget_, "drag-data-get",
     48                    G_CALLBACK(OnDragDataGetThunk), this);
     49   g_signal_connect(drag_widget_, "drag-begin",
     50                    G_CALLBACK(OnDragBeginThunk), this);
     51   g_signal_connect(drag_widget_, "drag-end",
     52                    G_CALLBACK(OnDragEndThunk), this);
     53 
     54   GtkTargetList* list = ui::GetTargetListFromCodeMask(code_mask);
     55   GdkEvent* event = gtk_get_current_event();
     56   gtk_drag_begin(drag_widget_, list, action, 1, event);
     57   if (event)
     58     gdk_event_free(event);
     59   gtk_target_list_unref(list);
     60 }
     61 
     62 CustomDrag::~CustomDrag() {
     63   gtk_widget_destroy(drag_widget_);
     64 }
     65 
     66 void CustomDrag::OnDragBegin(GtkWidget* widget, GdkDragContext* drag_context) {
     67   if (image_)
     68     gtk_drag_set_icon_pixbuf(drag_context, *image_, 0, 0);
     69 }
     70 
     71 void CustomDrag::OnDragEnd(GtkWidget* widget, GdkDragContext* drag_context) {
     72   delete this;
     73 }
     74 
     75 // DownloadItemDrag ------------------------------------------------------------
     76 
     77 DownloadItemDrag::DownloadItemDrag(const DownloadItem* item,
     78                                    gfx::Image* icon)
     79     : CustomDrag(icon, kDownloadItemCodeMask, kDownloadItemDragAction),
     80       download_item_(item) {
     81 }
     82 
     83 DownloadItemDrag::~DownloadItemDrag() {
     84 }
     85 
     86 void DownloadItemDrag::OnDragDataGet(
     87     GtkWidget* widget, GdkDragContext* context,
     88     GtkSelectionData* selection_data,
     89     guint target_type, guint time) {
     90   OnDragDataGetForDownloadItem(selection_data, target_type, download_item_);
     91 }
     92 
     93 // static
     94 void DownloadItemDrag::SetSource(GtkWidget* widget,
     95                                  DownloadItem* item,
     96                                  gfx::Image* icon) {
     97   gtk_drag_source_set(widget, GDK_BUTTON1_MASK, NULL, 0,
     98                       kDownloadItemDragAction);
     99   ui::SetSourceTargetListFromCodeMask(widget, kDownloadItemCodeMask);
    100 
    101   // Disconnect previous signal handlers, if any.
    102   g_signal_handlers_disconnect_by_func(
    103       widget,
    104       reinterpret_cast<gpointer>(OnDragDataGetStandalone),
    105       item);
    106   // Connect new signal handlers.
    107   g_signal_connect(widget, "drag-data-get",
    108                    G_CALLBACK(OnDragDataGetStandalone), item);
    109 
    110   if (icon)
    111     gtk_drag_source_set_icon_pixbuf(widget, *icon);
    112 }
    113 
    114 // static
    115 void DownloadItemDrag::BeginDrag(const DownloadItem* item, gfx::Image* icon) {
    116   new DownloadItemDrag(item, icon);
    117 }
    118 
    119 // BookmarkDrag ----------------------------------------------------------------
    120 
    121 BookmarkDrag::BookmarkDrag(Profile* profile,
    122                            const std::vector<const BookmarkNode*>& nodes)
    123     : CustomDrag(NULL,
    124                  bookmark_utils::GetCodeMask(false),
    125                  kBookmarkDragAction),
    126       profile_(profile),
    127       nodes_(nodes) {
    128 }
    129 
    130 BookmarkDrag::~BookmarkDrag() {
    131 }
    132 
    133 void BookmarkDrag::OnDragDataGet(GtkWidget* widget, GdkDragContext* context,
    134                                  GtkSelectionData* selection_data,
    135                                  guint target_type, guint time) {
    136   bookmark_utils::WriteBookmarksToSelection(nodes_, selection_data,
    137                                             target_type, profile_);
    138 }
    139 
    140 // static
    141 void BookmarkDrag::BeginDrag(Profile* profile,
    142                              const std::vector<const BookmarkNode*>& nodes) {
    143   new BookmarkDrag(profile, nodes);
    144 }
    145