4
* Copyright 2009 PCMan <pcman.tw@gmail.com>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22
#include "fm-dnd-src.h"
24
GtkTargetEntry fm_default_dnd_src_targets[] =
26
{"application/x-fmlist-ptr", GTK_TARGET_SAME_APP, FM_DND_SRC_TARGET_FM_LIST},
27
{"text/uri-list", 0, FM_DND_SRC_TARGET_URI_LIST}
36
static void fm_dnd_src_finalize (GObject *object);
39
on_drag_data_get ( GtkWidget *src_widget,
40
GdkDragContext *drag_context,
41
GtkSelectionData *sel_data,
47
on_drag_begin ( GtkWidget *src_widget,
48
GdkDragContext *drag_context,
52
on_drag_end ( GtkWidget *src_widget,
53
GdkDragContext *drag_context,
56
static guint signals[N_SIGNALS];
59
G_DEFINE_TYPE(FmDndSrc, fm_dnd_src, G_TYPE_OBJECT);
62
static void fm_dnd_src_class_init(FmDndSrcClass *klass)
64
GObjectClass *g_object_class;
65
FmDndSrcClass *dnd_src_class;
67
g_object_class = G_OBJECT_CLASS(klass);
68
g_object_class->finalize = fm_dnd_src_finalize;
70
dnd_src_class = FM_DND_SRC_CLASS(klass);
72
/* emitted when information of source files is needed.
73
* call fm_dnd_source_set_files() in its callback to
74
* provide info of dragged source files. */
76
g_signal_new ( "data-get",
77
G_TYPE_FROM_CLASS( klass ),
79
G_STRUCT_OFFSET ( FmDndSrcClass, data_get ),
81
g_cclosure_marshal_VOID__VOID,
86
static void fm_dnd_src_finalize(GObject *object)
90
g_return_if_fail(object != NULL);
91
g_return_if_fail(FM_IS_DND_SRC(object));
93
ds = FM_DND_SRC(object);
96
fm_list_unref(ds->files);
98
fm_dnd_src_set_widget(ds, NULL);
100
G_OBJECT_CLASS(fm_dnd_src_parent_class)->finalize(object);
104
static void fm_dnd_src_init(FmDndSrc *self)
110
FmDndSrc *fm_dnd_src_new(GtkWidget* w)
112
FmDndSrc* ds = (FmDndSrc*)g_object_new(FM_TYPE_DND_SRC, NULL);
113
fm_dnd_src_set_widget(ds, w);
117
void fm_dnd_src_set_widget(FmDndSrc* ds, GtkWidget* w)
121
if(ds->widget) /* there is an old widget connected */
123
g_signal_handlers_disconnect_by_func(ds->widget, on_drag_data_get, ds);
124
g_signal_handlers_disconnect_by_func(ds->widget, on_drag_begin, ds);
125
g_signal_handlers_disconnect_by_func(ds->widget, on_drag_end, ds);
130
g_object_add_weak_pointer(G_OBJECT(w), &ds->widget);
131
g_signal_connect(w, "drag-data-get", G_CALLBACK(on_drag_data_get), ds);
132
g_signal_connect_after(w, "drag-begin", G_CALLBACK(on_drag_begin), ds);
133
g_signal_connect_after(w, "drag-end", G_CALLBACK(on_drag_end), ds);
137
void fm_dnd_src_set_files(FmDndSrc* ds, FmFileInfoList* files)
139
ds->files = fm_list_ref(files);
142
void fm_dnd_src_set_file(FmDndSrc* ds, FmFileInfo* file)
144
FmFileInfoList* files = fm_file_info_list_new();
145
fm_list_push_tail(files, file);
150
on_drag_data_get ( GtkWidget *src_widget,
151
GdkDragContext *drag_context,
152
GtkSelectionData *sel_data,
159
/* Don't call the default handler */
160
g_signal_stop_emission_by_name( src_widget, "drag-data-get" );
161
drag_context->actions = GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK;
163
type = gdk_atom_intern_static_string(fm_default_dnd_src_targets[info].target);
166
case FM_DND_SRC_TARGET_FM_LIST:
167
/* just store the pointer in GtkSelection since this is used
168
* within the same app. */
169
gtk_selection_data_set(sel_data, type, 8,
170
&ds->files, sizeof(gpointer));
172
case FM_DND_SRC_TARGET_URI_LIST:
175
GString* uri_list = g_string_sized_new( 8192 );
180
for( l = fm_list_peek_head_link(ds->files); l; l=l->next )
182
file = (FmFileInfo*)l->data;
183
uri = fm_path_to_uri(file->path);
184
g_string_append( uri_list, uri );
186
g_string_append( uri_list, "\r\n" );
188
gtk_selection_data_set ( sel_data, type, 8,
189
( guchar* ) uri_list->str, uri_list->len + 1 );
190
g_string_free( uri_list, TRUE );
197
on_drag_begin ( GtkWidget *src_widget,
198
GdkDragContext *drag_context,
201
/* block default handler */
203
gtk_drag_set_icon_default( drag_context );
205
/* FIXME: set the icon to file icon later */
206
// gtk_drag_set_icon_pixbuf();
208
/* ask drag source to provide list of source files. */
209
g_signal_emit(ds, signals[DATA_GET], 0);
213
on_drag_end ( GtkWidget *src_widget,
214
GdkDragContext *drag_context,