1 /*
2 * eog-clipboard-handler.c
3 * This file is part of eog
4 *
5 * Author: Felix Riemann <friemann@gnome.org>
6 *
7 * Copyright (C) 2010 GNOME Foundation
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <glib.h>
29 #include <gdk-pixbuf/gdk-pixbuf.h>
30 #include <gtk/gtk.h>
31 #include "eog-clipboard-handler.h"
32
33 enum {
34 PROP_0,
35 PROP_PIXBUF,
36 PROP_URI
37 };
38
39 enum {
40 TARGET_PIXBUF,
41 TARGET_TEXT,
42 TARGET_URI
43 };
44
45 struct _EogClipboardHandlerPrivate {
46 GdkPixbuf *pixbuf;
47 gchar *uri;
48 };
49
G_DEFINE_TYPE_WITH_PRIVATE(EogClipboardHandler,eog_clipboard_handler,G_TYPE_INITIALLY_UNOWNED)50 G_DEFINE_TYPE_WITH_PRIVATE(EogClipboardHandler, eog_clipboard_handler, G_TYPE_INITIALLY_UNOWNED)
51
52 static GdkPixbuf*
53 eog_clipboard_handler_get_pixbuf (EogClipboardHandler *handler)
54 {
55 g_return_val_if_fail (EOG_IS_CLIPBOARD_HANDLER (handler), NULL);
56
57 return handler->priv->pixbuf;
58 }
59
60 static const gchar *
eog_clipboard_handler_get_uri(EogClipboardHandler * handler)61 eog_clipboard_handler_get_uri (EogClipboardHandler *handler)
62 {
63 g_return_val_if_fail (EOG_IS_CLIPBOARD_HANDLER (handler), NULL);
64
65 return handler->priv->uri;
66 }
67
68 static void
eog_clipboard_handler_set_pixbuf(EogClipboardHandler * handler,GdkPixbuf * pixbuf)69 eog_clipboard_handler_set_pixbuf (EogClipboardHandler *handler, GdkPixbuf *pixbuf)
70 {
71 g_return_if_fail (EOG_IS_CLIPBOARD_HANDLER (handler));
72 g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
73
74 if (handler->priv->pixbuf == pixbuf)
75 return;
76
77 if (handler->priv->pixbuf)
78 g_object_unref (handler->priv->pixbuf);
79
80 handler->priv->pixbuf = g_object_ref (pixbuf);
81
82 g_object_notify (G_OBJECT (handler), "pixbuf");
83 }
84
85 static void
eog_clipboard_handler_set_uri(EogClipboardHandler * handler,const gchar * uri)86 eog_clipboard_handler_set_uri (EogClipboardHandler *handler, const gchar *uri)
87 {
88 g_return_if_fail (EOG_IS_CLIPBOARD_HANDLER (handler));
89
90 if (handler->priv->uri != NULL)
91 g_free (handler->priv->uri);
92
93 handler->priv->uri = g_strdup (uri);
94 g_object_notify (G_OBJECT (handler), "uri");
95 }
96
97 static void
eog_clipboard_handler_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)98 eog_clipboard_handler_get_property (GObject *object, guint property_id,
99 GValue *value, GParamSpec *pspec)
100 {
101 EogClipboardHandler *handler;
102
103 g_return_if_fail (EOG_IS_CLIPBOARD_HANDLER (object));
104
105 handler = EOG_CLIPBOARD_HANDLER (object);
106
107 switch (property_id) {
108 case PROP_PIXBUF:
109 g_value_set_object (value,
110 eog_clipboard_handler_get_pixbuf (handler));
111 break;
112 case PROP_URI:
113 g_value_set_string (value,
114 eog_clipboard_handler_get_uri (handler));
115 break;
116 default:
117 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
118 }
119 }
120
121 static void
eog_clipboard_handler_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)122 eog_clipboard_handler_set_property (GObject *object, guint property_id,
123 const GValue *value, GParamSpec *pspec)
124 {
125 EogClipboardHandler *handler;
126
127 g_return_if_fail (EOG_IS_CLIPBOARD_HANDLER (object));
128
129 handler = EOG_CLIPBOARD_HANDLER (object);
130
131 switch (property_id) {
132 case PROP_PIXBUF:
133 {
134 GdkPixbuf *pixbuf;
135
136 pixbuf = g_value_get_object (value);
137 eog_clipboard_handler_set_pixbuf (handler, pixbuf);
138 break;
139 }
140 case PROP_URI:
141 {
142 const gchar *uri;
143
144 uri = g_value_get_string (value);
145 eog_clipboard_handler_set_uri (handler, uri);
146 break;
147 }
148 default:
149 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
150 }
151
152 }
153
154 static void
eog_clipboard_handler_dispose(GObject * obj)155 eog_clipboard_handler_dispose (GObject *obj)
156 {
157 EogClipboardHandlerPrivate *priv;
158
159 g_return_if_fail (EOG_IS_CLIPBOARD_HANDLER (obj));
160
161 priv = EOG_CLIPBOARD_HANDLER (obj)->priv;
162
163 if (priv->pixbuf != NULL) {
164 g_object_unref (priv->pixbuf);
165 priv->pixbuf = NULL;
166 }
167 if (priv->uri) {
168 g_free (priv->uri);
169 priv->uri = NULL;
170 }
171
172 G_OBJECT_CLASS (eog_clipboard_handler_parent_class)->dispose (obj);
173 }
174
175 static void
eog_clipboard_handler_init(EogClipboardHandler * handler)176 eog_clipboard_handler_init (EogClipboardHandler *handler)
177 {
178 handler->priv = eog_clipboard_handler_get_instance_private (handler);
179 }
180
181 static void
eog_clipboard_handler_class_init(EogClipboardHandlerClass * klass)182 eog_clipboard_handler_class_init (EogClipboardHandlerClass *klass)
183 {
184 GObjectClass *g_obj_class = G_OBJECT_CLASS (klass);
185
186 g_obj_class->get_property = eog_clipboard_handler_get_property;
187 g_obj_class->set_property = eog_clipboard_handler_set_property;
188 g_obj_class->dispose = eog_clipboard_handler_dispose;
189
190 g_object_class_install_property (
191 g_obj_class, PROP_PIXBUF,
192 g_param_spec_object ("pixbuf", NULL, NULL, GDK_TYPE_PIXBUF,
193 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
194 G_PARAM_STATIC_STRINGS));
195
196 g_object_class_install_property (
197 g_obj_class, PROP_URI,
198 g_param_spec_string ("uri", NULL, NULL, NULL,
199 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
200 G_PARAM_STATIC_STRINGS));
201 }
202
203 EogClipboardHandler*
eog_clipboard_handler_new(EogImage * img)204 eog_clipboard_handler_new (EogImage *img)
205 {
206 GObject *obj;
207 GFile *file;
208 GdkPixbuf *pbuf;
209 gchar *uri;
210
211 g_object_ref (img);
212 pbuf = eog_image_get_pixbuf (img);
213 file = eog_image_get_file (img);
214 uri = g_file_get_uri (file);
215 obj = g_object_new (EOG_TYPE_CLIPBOARD_HANDLER,
216 "pixbuf", pbuf,
217 "uri", uri,
218 NULL);
219 g_free (uri);
220 g_object_unref (file);
221 g_object_unref (pbuf);
222 g_object_unref (img);
223
224 return EOG_CLIPBOARD_HANDLER (obj);
225
226 }
227
228 static void
eog_clipboard_handler_get_func(GtkClipboard * clipboard,GtkSelectionData * selection,guint info,gpointer owner)229 eog_clipboard_handler_get_func (GtkClipboard *clipboard,
230 GtkSelectionData *selection,
231 guint info, gpointer owner)
232 {
233 EogClipboardHandler *handler;
234
235 g_return_if_fail (EOG_IS_CLIPBOARD_HANDLER (owner));
236
237 handler = EOG_CLIPBOARD_HANDLER (owner);
238
239 switch (info) {
240 case TARGET_PIXBUF:
241 {
242 GdkPixbuf *pixbuf = eog_clipboard_handler_get_pixbuf (handler);
243 g_object_ref (pixbuf);
244 gtk_selection_data_set_pixbuf (selection, pixbuf);
245 g_object_unref (pixbuf);
246 break;
247 }
248 case TARGET_TEXT:
249 {
250 gtk_selection_data_set_text (selection,
251 eog_clipboard_handler_get_uri (handler),
252 -1);
253 break;
254 }
255 case TARGET_URI:
256 {
257 gchar *uris[2];
258 uris[0] = g_strdup (eog_clipboard_handler_get_uri (handler));
259 uris[1] = NULL;
260
261 gtk_selection_data_set_uris (selection, uris);
262 g_free (uris[0]);
263 break;
264 }
265 default:
266 g_return_if_reached ();
267 }
268
269 }
270
271 static void
eog_clipboard_handler_clear_func(GtkClipboard * clipboard,gpointer owner)272 eog_clipboard_handler_clear_func (GtkClipboard *clipboard, gpointer owner)
273 {
274 g_return_if_fail (EOG_IS_CLIPBOARD_HANDLER (owner));
275
276 g_object_unref (G_OBJECT (owner));
277 }
278
279 void
eog_clipboard_handler_copy_to_clipboard(EogClipboardHandler * handler,GtkClipboard * clipboard)280 eog_clipboard_handler_copy_to_clipboard (EogClipboardHandler *handler,
281 GtkClipboard *clipboard)
282 {
283 GtkTargetList *tlist;
284 GtkTargetEntry *targets;
285 gint n_targets = 0;
286 gboolean set = FALSE;
287
288 tlist = gtk_target_list_new (NULL, 0);
289
290 if (handler->priv->pixbuf != NULL)
291 gtk_target_list_add_image_targets (tlist, TARGET_PIXBUF, TRUE);
292
293 if (handler->priv->uri != NULL) {
294 gtk_target_list_add_text_targets (tlist, TARGET_TEXT);
295 gtk_target_list_add_uri_targets (tlist, TARGET_URI);
296 }
297
298 targets = gtk_target_table_new_from_list (tlist, &n_targets);
299
300 // We need to take ownership here if nobody else did
301 g_object_ref_sink (handler);
302
303 if (n_targets > 0) {
304 set = gtk_clipboard_set_with_owner (clipboard,
305 targets, n_targets,
306 eog_clipboard_handler_get_func,
307 eog_clipboard_handler_clear_func,
308 G_OBJECT (handler));
309
310 }
311
312 if (!set) {
313 gtk_clipboard_clear (clipboard);
314 g_object_unref (handler);
315 }
316
317 gtk_target_table_free (targets, n_targets);
318 gtk_target_list_unref (tlist);
319 }
320
321