No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | nautilus-clipboard-monitor.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
2
3 nautilus-clipboard-monitor.c: catch clipboard changes.
4
5 Copyright (C) 2004 Red Hat, Inc.
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public
18 License along with this program; if not, write to the
19 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
21
22 Author: Alexander Larsson <alexl@redhat.com>
23 */
24
25 #include <config.h>
26 #include "nautilus-clipboard-monitor.h"
27 #include "nautilus-file.h"
28
29 #include <eel/eel-debug.h>
30 #include <gtk/gtk.h>
31
32 /* X11 has a weakness when it comes to clipboard handling,
33 * there is no way to get told when the owner of the clipboard
34 * changes. This is often needed, for instance to set the
35 * sensitivity of the paste menu item. We work around this
36 * internally in an app by telling the clipboard monitor when
37 * we changed the clipboard. Unfortunately this doesn't give
38 * us perfect results, we still don't catch changes made by
39 * other clients
40 *
41 * This is fixed with the XFIXES extensions, which recent versions
42 * of Gtk+ supports as the owner_change signal on GtkClipboard. We
43 * use this now, but keep the old code since not all X servers support
44 * XFIXES.
45 */
46
47 enum {
48 CLIPBOARD_CHANGED,
49 CLIPBOARD_INFO,
50 LAST_SIGNAL
51 };
52
53 struct NautilusClipboardMonitorDetails {
54 NautilusClipboardInfo *info;
55 };
56
57 static guint signals[LAST_SIGNAL];
58 static GdkAtom copied_files_atom;
59
60 G_DEFINE_TYPE (NautilusClipboardMonitor, nautilus_clipboard_monitor, G_TYPE_OBJECT);
61
62 static NautilusClipboardMonitor *clipboard_monitor = NULL;
63
64 static void
65 destroy_clipboard_monitor (void)
66 {
67 if (clipboard_monitor != NULL) {
68 g_object_unref (clipboard_monitor);
69 }
70 }
71
72 NautilusClipboardMonitor *
73 nautilus_clipboard_monitor_get (void)
74 {
75 GtkClipboard *clipboard;
76
77 if (clipboard_monitor == NULL) {
78 clipboard_monitor = NAUTILUS_CLIPBOARD_MONITOR (g_object_new (NAUTILUS_TYPE_CLIPBOARD_MONITOR, NULL));
79 eel_debug_call_at_shutdown (destroy_clipboard_monitor);
80
81 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
82 g_signal_connect (clipboard, "owner_change",
83 G_CALLBACK (nautilus_clipboard_monitor_emit_changed), NULL);
84 }
85 return clipboard_monitor;
86 }
87
88 void
89 nautilus_clipboard_monitor_emit_changed (void)
90 {
91 NautilusClipboardMonitor *monitor;
92
93 monitor = nautilus_clipboard_monitor_get ();
94
95 g_signal_emit (monitor, signals[CLIPBOARD_CHANGED], 0);
96 }
97
98 static NautilusClipboardInfo *
99 nautilus_clipboard_info_new (GList *files,
100 gboolean cut)
101 {
102 NautilusClipboardInfo *info;
103
104 info = g_slice_new0 (NautilusClipboardInfo);
105 info->files = nautilus_file_list_copy (files);
106 info->cut = cut;
107
108 return info;
109 }
110
111 static NautilusClipboardInfo *
112 nautilus_clipboard_info_copy (NautilusClipboardInfo *info)
113 {
114 NautilusClipboardInfo *new_info;
115
116 new_info = NULL;
117
118 if (info != NULL) {
119 new_info = nautilus_clipboard_info_new (info->files,
120 info->cut);
121 }
122
123 return new_info;
124 }
125
126 static void
127 nautilus_clipboard_info_free (NautilusClipboardInfo *info)
128 {
129 nautilus_file_list_free (info->files);
130
131 g_slice_free (NautilusClipboardInfo, info);
132 }
133
134 static void
135 nautilus_clipboard_monitor_init (NautilusClipboardMonitor *monitor)
136 {
137 monitor->details =
138 G_TYPE_INSTANCE_GET_PRIVATE (monitor, NAUTILUS_TYPE_CLIPBOARD_MONITOR,
139 NautilusClipboardMonitorDetails);
140 }
141
142 static void
143 clipboard_monitor_finalize (GObject *object)
144 {
145 NautilusClipboardMonitor *monitor;
146
147 monitor = NAUTILUS_CLIPBOARD_MONITOR (object);
148
149 if (monitor->details->info != NULL) {
150 nautilus_clipboard_info_free (monitor->details->info);
151 monitor->details->info = NULL;
152 }
153
154 G_OBJECT_CLASS (nautilus_clipboard_monitor_parent_class)->finalize (object);
155 }
156
157 static void
158 nautilus_clipboard_monitor_class_init (NautilusClipboardMonitorClass *klass)
159 {
160 GObjectClass *object_class;
161
162 object_class = G_OBJECT_CLASS (klass);
163 object_class->finalize = clipboard_monitor_finalize;
164
165 copied_files_atom = gdk_atom_intern ("x-special/gnome-copied-files", FALSE);
166
167 signals[CLIPBOARD_CHANGED] =
168 g_signal_new ("clipboard_changed",
169 G_TYPE_FROM_CLASS (klass),
170 G_SIGNAL_RUN_LAST,
171 G_STRUCT_OFFSET (NautilusClipboardMonitorClass, clipboard_changed),
172 NULL, NULL,
173 g_cclosure_marshal_VOID__VOID,
174 G_TYPE_NONE, 0);
175 signals[CLIPBOARD_INFO] =
176 g_signal_new ("clipboard_info",
177 G_TYPE_FROM_CLASS (klass),
178 G_SIGNAL_RUN_LAST,
179 G_STRUCT_OFFSET (NautilusClipboardMonitorClass, clipboard_info),
180 NULL, NULL,
181 g_cclosure_marshal_VOID__POINTER,
182 G_TYPE_NONE,
183 1, G_TYPE_POINTER);
184
185 g_type_class_add_private (klass, sizeof (NautilusClipboardMonitorDetails));
186 }
187
188 void
189 nautilus_clipboard_monitor_set_clipboard_info (NautilusClipboardMonitor *monitor,
190 NautilusClipboardInfo *info)
191 {
192 if (monitor->details->info != NULL) {
193 nautilus_clipboard_info_free (monitor->details->info);
194 monitor->details->info = NULL;
195 }
196
197 monitor->details->info = nautilus_clipboard_info_copy (info);
198
199 g_signal_emit (monitor, signals[CLIPBOARD_INFO], 0, monitor->details->info);
200
201 nautilus_clipboard_monitor_emit_changed ();
202 }
203
204 NautilusClipboardInfo *
205 nautilus_clipboard_monitor_get_clipboard_info (NautilusClipboardMonitor *monitor)
206 {
207 return monitor->details->info;
208 }
209
210 void
211 nautilus_clear_clipboard_callback (GtkClipboard *clipboard,
212 gpointer user_data)
213 {
214 nautilus_clipboard_monitor_set_clipboard_info
215 (nautilus_clipboard_monitor_get (), NULL);
216 }
217
218 static char *
219 convert_file_list_to_string (NautilusClipboardInfo *info,
220 gboolean format_for_text,
221 gsize *len)
222 {
223 GString *uris;
224 char *uri, *tmp;
225 GFile *f;
226 guint i;
227 GList *l;
228
229 if (format_for_text) {
230 uris = g_string_new (NULL);
231 } else {
232 uris = g_string_new (info->cut ? "cut" : "copy");
233 }
234
235 for (i = 0, l = info->files; l != NULL; l = l->next, i++) {
236 uri = nautilus_file_get_uri (l->data);
237
238 if (format_for_text) {
239 f = g_file_new_for_uri (uri);
240 tmp = g_file_get_parse_name (f);
241 g_object_unref (f);
242
243 if (tmp != NULL) {
244 g_string_append (uris, tmp);
245 g_free (tmp);
246 } else {
247 g_string_append (uris, uri);
248 }
249
250 /* skip newline for last element */
251 if (i + 1 < g_list_length (info->files)) {
252 g_string_append_c (uris, '\n');
253 }
254 } else {
255 g_string_append_c (uris, '\n');
256 g_string_append (uris, uri);
257 }
258
259 g_free (uri);
260 }
261
262 *len = uris->len;
263 return g_string_free (uris, FALSE);
264 }
265
266 void
267 nautilus_get_clipboard_callback (GtkClipboard *clipboard,
268 GtkSelectionData *selection_data,
269 guint info,
270 gpointer user_data)
271 {
272 char **uris;
273 GList *l;
274 int i;
275 NautilusClipboardInfo *clipboard_info;
276 GdkAtom target;
277
278 clipboard_info =
279 nautilus_clipboard_monitor_get_clipboard_info (nautilus_clipboard_monitor_get ());
280
281 target = gtk_selection_data_get_target (selection_data);
282
283 if (gtk_targets_include_uri (&target, 1)) {
284 uris = g_malloc ((g_list_length (clipboard_info->files) + 1) * sizeof (char *));
285 i = 0;
286
287 for (l = clipboard_info->files; l != NULL; l = l->next) {
288 uris[i] = nautilus_file_get_uri (l->data);
289 i++;
290 }
291
292 uris[i] = NULL;
293
294 gtk_selection_data_set_uris (selection_data, uris);
295
296 g_strfreev (uris);
297 } else if (gtk_targets_include_text (&target, 1)) {
298 char *str;
299 gsize len;
300
301 str = convert_file_list_to_string (clipboard_info, TRUE, &len);
302 gtk_selection_data_set_text (selection_data, str, len);
303 g_free (str);
304 } else if (target == copied_files_atom) {
305 char *str;
306 gsize len;
307
308 str = convert_file_list_to_string (clipboard_info, FALSE, &len);
309 gtk_selection_data_set (selection_data, copied_files_atom, 8, (guchar *) str, len);
310 g_free (str);
311 }
312 }