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