Merge lp:~noskcaj/ubuntu/trusty/xfdesktop4/4.11 into lp:ubuntu/trusty/xfdesktop4

Proposed by Jackson Doak
Status: Merged
Merge reported by: Martin Pitt
Merged at revision: not available
Proposed branch: lp:~noskcaj/ubuntu/trusty/xfdesktop4/4.11
Merge into: lp:ubuntu/trusty/xfdesktop4
Diff against target: 149575 lines (+44679/-77106)
158 files modified
.pc/applied-patches (+0/-3)
.pc/xubuntu_fix-duplicate-volumes.patch/src/xfdesktop-file-icon-manager.c (+0/-3422)
.pc/xubuntu_improve-nautilus-interactions.patch/src/xfce-desktop.c (+0/-1518)
.pc/xubuntu_set-accountsservice-user-bg.patch/src/xfce-desktop.c (+0/-1529)
ChangeLog (+4252/-215)
INSTALL (+4/-4)
Makefile.am (+0/-4)
Makefile.in (+178/-161)
NEWS (+150/-0)
README (+6/-6)
aclocal.m4 (+318/-302)
backgrounds/Makefile.in (+72/-37)
common/Makefile.am (+4/-13)
common/Makefile.in (+148/-91)
common/xfdesktop-common.c (+91/-314)
common/xfdesktop-common.h (+26/-20)
common/xfdesktop-thumbnailer.c (+60/-43)
common/xfdesktop-thumbnailer.h (+5/-2)
compile (+7/-3)
config.guess (+106/-78)
config.sub (+57/-48)
configure (+346/-157)
configure.ac (+21/-22)
debian/changelog (+34/-0)
debian/control (+4/-4)
debian/copyright (+62/-34)
debian/patches/series (+0/-1)
debian/patches/xubuntu_fix-duplicate-volumes.patch (+0/-23)
debian/patches/xubuntu_improve-nautilus-interactions.patch (+15/-13)
debian/patches/xubuntu_set-accountsservice-user-bg.patch (+19/-22)
debian/rules (+3/-2)
debian/xfdesktop-settings.1 (+25/-5)
depcomp (+269/-186)
doc/Makefile.in (+71/-36)
doc/README.kiosk (+6/-52)
doc/README.xfconf (+26/-15)
install-sh (+7/-7)
ltmain.sh (+2/-2)
missing (+159/-275)
mkinstalldirs (+0/-162)
pixmaps/Makefile.in (+73/-38)
po/POTFILES.in (+1/-0)
po/ar.po (+534/-1382)
po/az.po (+0/-1651)
po/bg.po (+552/-961)
po/bn_IN.po (+0/-1655)
po/ca.po (+503/-1487)
po/cs.po (+520/-1581)
po/da.po (+498/-1345)
po/de.po (+518/-1084)
po/dz.po (+0/-1822)
po/el.po (+507/-576)
po/en_AU.po (+1007/-0)
po/en_GB.po (+511/-1522)
po/es.po (+523/-1571)
po/es_MX.po (+0/-1650)
po/et.po (+535/-1289)
po/eu.po (+508/-1359)
po/fa.po (+0/-1638)
po/fa_IR.po (+1011/-0)
po/fi.po (+0/-1034)
po/fr.po (+526/-1354)
po/gl.po (+502/-1061)
po/gu.po (+0/-1719)
po/he.po (+566/-1360)
po/hi.po (+0/-1180)
po/hr.po (+515/-715)
po/hu.po (+498/-530)
po/hy.po (+0/-1636)
po/id.po (+522/-1451)
po/is.po (+620/-673)
po/it.po (+515/-750)
po/ja.po (+465/-586)
po/ka.po (+0/-956)
po/kk.po (+506/-1063)
po/ko.po (+535/-558)
po/lt.po (+507/-535)
po/mk.po (+0/-1813)
po/mr.po (+0/-1649)
po/ms.po (+619/-799)
po/nb.po (+540/-477)
po/nl.po (+507/-1447)
po/nn.po (+498/-525)
po/oc.po (+1007/-0)
po/pl.po (+521/-1552)
po/pt.po (+542/-572)
po/pt_BR.po (+520/-1503)
po/ro.po (+506/-542)
po/ru.po (+535/-560)
po/sk.po (+509/-1402)
po/sl.po (+1007/-0)
po/sr.po (+552/-1583)
po/sv.po (+534/-1382)
po/ta.po (+0/-1194)
po/th.po (+1014/-0)
po/tr.po (+515/-1341)
po/ug.po (+501/-503)
po/uk.po (+499/-1345)
po/uz.po (+1008/-0)
po/zh_CN.po (+511/-517)
po/zh_HK.po (+1016/-0)
po/zh_TW.po (+523/-1297)
settings/Makefile.am (+5/-1)
settings/Makefile.in (+136/-74)
settings/main.c (+1449/-1141)
settings/xfce-backdrop-settings.desktop.in (+1/-1)
settings/xfdesktop-settings-appearance-frame-ui.glade (+308/-540)
settings/xfdesktop-settings-appearance-frame-ui.h (+284/-532)
settings/xfdesktop-settings-ui.glade (+61/-105)
settings/xfdesktop-settings-ui.h (+819/-825)
src/Makefile.am (+5/-1)
src/Makefile.in (+175/-82)
src/main.c (+29/-360)
src/menu.c (+2/-2)
src/menu.h (+2/-2)
src/windowlist.c (+118/-111)
src/windowlist.h (+2/-2)
src/xfce-backdrop.c (+1071/-311)
src/xfce-backdrop.h (+37/-20)
src/xfce-desktop-enum-types.c (+24/-1)
src/xfce-desktop-enum-types.h (+2/-0)
src/xfce-desktop-menu.c (+2/-2)
src/xfce-desktop-menu.h (+2/-2)
src/xfce-desktop.c (+647/-569)
src/xfce-desktop.h (+3/-9)
src/xfce-workspace.c (+744/-0)
src/xfce-workspace.h (+82/-0)
src/xfdesktop-app-menu-item.c (+10/-22)
src/xfdesktop-app-menu-item.h (+3/-4)
src/xfdesktop-application.c (+880/-0)
src/xfdesktop-application.h (+47/-0)
src/xfdesktop-clipboard-manager.c (+24/-12)
src/xfdesktop-clipboard-manager.h (+3/-3)
src/xfdesktop-file-icon-manager.c (+1039/-605)
src/xfdesktop-file-icon-manager.h (+3/-15)
src/xfdesktop-file-icon.c (+138/-3)
src/xfdesktop-file-icon.h (+12/-2)
src/xfdesktop-file-utils.c (+296/-320)
src/xfdesktop-file-utils.h (+10/-9)
src/xfdesktop-icon-view-manager.c (+21/-2)
src/xfdesktop-icon-view-manager.h (+14/-2)
src/xfdesktop-icon-view.c (+635/-334)
src/xfdesktop-icon-view.h (+2/-2)
src/xfdesktop-icon.c (+108/-10)
src/xfdesktop-icon.h (+22/-7)
src/xfdesktop-notify.c (+129/-8)
src/xfdesktop-notify.h (+5/-6)
src/xfdesktop-regular-file-icon.c (+201/-153)
src/xfdesktop-regular-file-icon.h (+2/-2)
src/xfdesktop-special-file-icon.c (+112/-75)
src/xfdesktop-special-file-icon.h (+2/-2)
src/xfdesktop-volume-icon.c (+262/-157)
src/xfdesktop-volume-icon.h (+2/-2)
src/xfdesktop-window-icon-manager.c (+2/-2)
src/xfdesktop-window-icon-manager.h (+2/-2)
src/xfdesktop-window-icon.c (+24/-37)
src/xfdesktop-window-icon.h (+2/-2)
xfdesktop.1 (+42/-7)
To merge this branch: bzr merge lp:~noskcaj/ubuntu/trusty/xfdesktop4/4.11
Reviewer Review Type Date Requested Status
Martin Pitt Approve
Review via email: mp+201528@code.launchpad.net

Description of the change

Merge from debian packaging svn. needed for xubuntu

To post a comment you must log in.
Revision history for this message
Martin Pitt (pitti) wrote :

Looks good, thanks! Uploading with fixed version number 4.11.2-0ubuntu1; as -1 is not released in Debian yet, this shouldn't be -1ubuntu1.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== removed file '.pc/applied-patches'
--- .pc/applied-patches 2013-03-04 20:45:02 +0000
+++ .pc/applied-patches 1970-01-01 00:00:00 +0000
@@ -1,3 +0,0 @@
1xubuntu_improve-nautilus-interactions.patch
2xubuntu_fix-duplicate-volumes.patch
3xubuntu_set-accountsservice-user-bg.patch
40
=== removed directory '.pc/xubuntu_fix-duplicate-volumes.patch'
=== removed directory '.pc/xubuntu_fix-duplicate-volumes.patch/src'
=== removed file '.pc/xubuntu_fix-duplicate-volumes.patch/src/xfdesktop-file-icon-manager.c'
--- .pc/xubuntu_fix-duplicate-volumes.patch/src/xfdesktop-file-icon-manager.c 2012-10-29 12:00:16 +0000
+++ .pc/xubuntu_fix-duplicate-volumes.patch/src/xfdesktop-file-icon-manager.c 1970-01-01 00:00:00 +0000
@@ -1,3422 +0,0 @@
1/*
2 * xfdesktop - xfce4's desktop manager
3 *
4 * Copyright(c) 2006 Brian Tarricone, <bjt23@cornell.edu>
5 * Copyright(c) 2006 Benedikt Meurer, <benny@xfce.org>
6 * Copyright(c) 2010-2011 Jannis Pohlmann, <jannis@xfce.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26
27#ifdef HAVE_STRING_H
28#include <string.h>
29#endif
30
31#ifdef HAVE_TIME_H
32#include <time.h>
33#endif
34
35#ifdef HAVE_UNISTD_H
36#include <unistd.h>
37#endif
38
39#ifdef HAVE_SYS_STAT_H
40#include <sys/stat.h>
41#endif
42
43#ifdef HAVE_SYS_TYPES_H
44#include <sys/types.h>
45#endif
46
47#ifdef HAVE_ERRNO_H
48#include <errno.h>
49#endif
50
51#ifndef PATH_MAX
52#define PATH_MAX 4096
53#endif
54
55#include <gio/gio.h>
56#include <gdk/gdkkeysyms.h>
57
58#ifdef HAVE_THUNARX
59#include <thunarx/thunarx.h>
60#endif
61
62#include "xfce-desktop.h"
63#include "xfdesktop-clipboard-manager.h"
64#include "xfdesktop-common.h"
65#include "xfdesktop-file-icon.h"
66#include "xfdesktop-file-icon-manager.h"
67#include "xfdesktop-file-utils.h"
68#include "xfdesktop-file-manager-proxy.h"
69#include "xfdesktop-icon-view.h"
70#include "xfdesktop-regular-file-icon.h"
71#include "xfdesktop-special-file-icon.h"
72#include "xfdesktop-trash-proxy.h"
73#include "xfdesktop-volume-icon.h"
74#include "xfdesktop-thumbnailer.h"
75
76#include <libxfce4util/libxfce4util.h>
77#include <libxfce4ui/libxfce4ui.h>
78
79#define SAVE_DELAY 7000
80#define BORDER 8
81
82#define SETTING_SHOW_FILESYSTEM "/desktop-icons/file-icons/show-filesystem"
83#define SETTING_SHOW_HOME "/desktop-icons/file-icons/show-home"
84#define SETTING_SHOW_TRASH "/desktop-icons/file-icons/show-trash"
85#define SETTING_SHOW_REMOVABLE "/desktop-icons/file-icons/show-removable"
86#define SETTING_SHOW_THUMBNAILS "/desktop-icons/show-thumbnails"
87
88enum
89{
90 PROP0 = 0,
91 PROP_FOLDER,
92 PROP_SHOW_FILESYSTEM,
93 PROP_SHOW_HOME,
94 PROP_SHOW_TRASH,
95 PROP_SHOW_REMOVABLE,
96 PROP_SHOW_THUMBNAILS
97};
98
99struct _XfdesktopFileIconManagerPrivate
100{
101 gboolean inited;
102
103 XfconfChannel *channel;
104
105 GtkWidget *desktop;
106 XfdesktopIconView *icon_view;
107
108 GdkScreen *gscreen;
109
110 GFile *folder;
111 XfdesktopFileIcon *desktop_icon;
112 GFileMonitor *monitor;
113 GFileEnumerator *enumerator;
114
115 GVolumeMonitor *volume_monitor;
116
117 GHashTable *icons;
118 GHashTable *removable_icons;
119 GHashTable *special_icons;
120
121 gboolean show_removable_media;
122 gboolean show_special[XFDESKTOP_SPECIAL_FILE_ICON_TRASH+1];
123 gboolean show_thumbnails;
124
125 guint save_icons_id;
126
127 GList *deferred_icons;
128
129 GtkTargetList *drag_targets;
130 GtkTargetList *drop_targets;
131
132#ifdef HAVE_THUNARX
133 GList *thunarx_menu_providers;
134 GList *thunarx_properties_providers;
135#endif
136
137 XfdesktopThumbnailer *thumbnailer;
138};
139
140static void xfdesktop_file_icon_manager_set_property(GObject *object,
141 guint property_id,
142 const GValue *value,
143 GParamSpec *pspec);
144static void xfdesktop_file_icon_manager_get_property(GObject *object,
145 guint property_id,
146 GValue *value,
147 GParamSpec *pspec);
148static void xfdesktop_file_icon_manager_finalize(GObject *obj);
149static void xfdesktop_file_icon_manager_icon_view_manager_init(XfdesktopIconViewManagerIface *iface);
150
151static gboolean xfdesktop_file_icon_manager_real_init(XfdesktopIconViewManager *manager,
152 XfdesktopIconView *icon_view);
153static void xfdesktop_file_icon_manager_fini(XfdesktopIconViewManager *manager);
154
155static gboolean xfdesktop_file_icon_manager_drag_drop(XfdesktopIconViewManager *manager,
156 XfdesktopIcon *drop_icon,
157 GdkDragContext *context,
158 guint16 row,
159 guint16 col,
160 guint time_);
161static void xfdesktop_file_icon_manager_drag_data_received(XfdesktopIconViewManager *manager,
162 XfdesktopIcon *drop_icon,
163 GdkDragContext *context,
164 guint16 row,
165 guint16 col,
166 GtkSelectionData *data,
167 guint info,
168 guint time_);
169static void xfdesktop_file_icon_manager_drag_data_get(XfdesktopIconViewManager *manager,
170 GList *drag_icons,
171 GdkDragContext *context,
172 GtkSelectionData *data,
173 guint info,
174 guint time_);
175
176static gboolean xfdesktop_file_icon_manager_check_create_desktop_folder(GFile *file);
177static void xfdesktop_file_icon_manager_load_desktop_folder(XfdesktopFileIconManager *fmanager);
178static void xfdesktop_file_icon_manager_load_removable_media(XfdesktopFileIconManager *fmanager);
179static void xfdesktop_file_icon_manager_remove_removable_media(XfdesktopFileIconManager *fmanager);
180
181static void xfdesktop_file_icon_position_changed(XfdesktopFileIcon *icon,
182 gpointer user_data);
183
184static void xfdesktop_file_icon_manager_update_image(GtkWidget *widget,
185 gchar *srcfile,
186 gchar *thumbfile,
187 XfdesktopFileIconManager *fmanager);
188
189G_DEFINE_TYPE_EXTENDED(XfdesktopFileIconManager,
190 xfdesktop_file_icon_manager,
191 G_TYPE_OBJECT, 0,
192 G_IMPLEMENT_INTERFACE(XFDESKTOP_TYPE_ICON_VIEW_MANAGER,
193 xfdesktop_file_icon_manager_icon_view_manager_init))
194
195
196typedef struct
197{
198 XfdesktopFileIconManager *fmanager;
199 DBusGProxy *proxy;
200 DBusGProxyCall *call;
201 GList *files;
202} XfdesktopTrashFilesData;
203
204enum
205{
206 TARGET_TEXT_URI_LIST = 0,
207 TARGET_XDND_DIRECT_SAVE0,
208 TARGET_NETSCAPE_URL,
209};
210
211static const GtkTargetEntry drag_targets[] = {
212 { "text/uri-list", 0, TARGET_TEXT_URI_LIST, },
213};
214static const gint n_drag_targets = (sizeof(drag_targets)/sizeof(drag_targets[0]));
215static const GtkTargetEntry drop_targets[] = {
216 { "text/uri-list", 0, TARGET_TEXT_URI_LIST, },
217 { "XdndDirectSave0", 0, TARGET_XDND_DIRECT_SAVE0, },
218 { "_NETSCAPE_URL", 0, TARGET_NETSCAPE_URL },
219};
220static const gint n_drop_targets = (sizeof(drop_targets)/sizeof(drop_targets[0]));
221
222static XfdesktopClipboardManager *clipboard_manager = NULL;
223
224static GQuark xfdesktop_app_info_quark = 0;
225
226
227static void
228xfdesktop_file_icon_manager_class_init(XfdesktopFileIconManagerClass *klass)
229{
230 GObjectClass *gobject_class = (GObjectClass *)klass;
231
232 g_type_class_add_private(klass, sizeof(XfdesktopFileIconManagerPrivate));
233
234 gobject_class->set_property = xfdesktop_file_icon_manager_set_property;
235 gobject_class->get_property = xfdesktop_file_icon_manager_get_property;
236 gobject_class->finalize = xfdesktop_file_icon_manager_finalize;
237
238 g_object_class_install_property(gobject_class, PROP_FOLDER,
239 g_param_spec_object("folder", "Desktop Folder",
240 "Folder this icon manager manages",
241 G_TYPE_FILE,
242 G_PARAM_READWRITE
243 | G_PARAM_CONSTRUCT_ONLY
244 | G_PARAM_STATIC_NAME
245 | G_PARAM_STATIC_NICK
246 | G_PARAM_STATIC_BLURB));
247
248#define XFDESKTOP_PARAM_FLAGS (G_PARAM_READWRITE \
249 | G_PARAM_CONSTRUCT \
250 | G_PARAM_STATIC_NAME \
251 | G_PARAM_STATIC_NICK \
252 | G_PARAM_STATIC_BLURB)
253 g_object_class_install_property(gobject_class, PROP_SHOW_FILESYSTEM,
254 g_param_spec_boolean("show-filesystem",
255 "show filesystem",
256 "show filesystem",
257 TRUE,
258 XFDESKTOP_PARAM_FLAGS));
259 g_object_class_install_property(gobject_class, PROP_SHOW_HOME,
260 g_param_spec_boolean("show-home",
261 "show home",
262 "show home",
263 TRUE,
264 XFDESKTOP_PARAM_FLAGS));
265 g_object_class_install_property(gobject_class, PROP_SHOW_TRASH,
266 g_param_spec_boolean("show-trash",
267 "show trash",
268 "show trash",
269 TRUE,
270 XFDESKTOP_PARAM_FLAGS));
271 g_object_class_install_property(gobject_class, PROP_SHOW_REMOVABLE,
272 g_param_spec_boolean("show-removable",
273 "show removable",
274 "show removable",
275 TRUE,
276 XFDESKTOP_PARAM_FLAGS));
277 g_object_class_install_property(gobject_class, PROP_SHOW_THUMBNAILS,
278 g_param_spec_boolean("show-thumbnails",
279 "show-thumbnails",
280 "show-thumbnails",
281 TRUE,
282 XFDESKTOP_PARAM_FLAGS));
283#undef XFDESKTOP_PARAM_FLAGS
284
285 xfdesktop_app_info_quark = g_quark_from_static_string("xfdesktop-app-info-quark");
286}
287
288static void
289xfdesktop_file_icon_manager_init(XfdesktopFileIconManager *fmanager)
290{
291 fmanager->priv = G_TYPE_INSTANCE_GET_PRIVATE(fmanager,
292 XFDESKTOP_TYPE_FILE_ICON_MANAGER,
293 XfdesktopFileIconManagerPrivate);
294
295 /* be safe */
296 fmanager->priv->gscreen = gdk_screen_get_default();
297 fmanager->priv->drag_targets = gtk_target_list_new(drag_targets,
298 n_drag_targets);
299 fmanager->priv->drop_targets = gtk_target_list_new(drop_targets,
300 n_drop_targets);
301
302 fmanager->priv->thumbnailer = xfdesktop_thumbnailer_new();
303
304 g_signal_connect(G_OBJECT(fmanager->priv->thumbnailer), "thumbnail-ready", G_CALLBACK(xfdesktop_file_icon_manager_update_image), fmanager);
305}
306
307static void
308xfdesktop_file_icon_manager_set_property(GObject *object,
309 guint property_id,
310 const GValue *value,
311 GParamSpec *pspec)
312{
313 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(object);
314
315 switch(property_id) {
316 case PROP_FOLDER:
317 fmanager->priv->folder = g_value_dup_object(value);
318 xfdesktop_file_icon_manager_check_create_desktop_folder(fmanager->priv->folder);
319 break;
320
321 case PROP_SHOW_FILESYSTEM:
322 xfdesktop_file_icon_manager_set_show_special_file(fmanager,
323 XFDESKTOP_SPECIAL_FILE_ICON_FILESYSTEM,
324 g_value_get_boolean(value));
325 break;
326
327 case PROP_SHOW_HOME:
328 xfdesktop_file_icon_manager_set_show_special_file(fmanager,
329 XFDESKTOP_SPECIAL_FILE_ICON_HOME,
330 g_value_get_boolean(value));
331 break;
332
333 case PROP_SHOW_TRASH:
334 xfdesktop_file_icon_manager_set_show_special_file(fmanager,
335 XFDESKTOP_SPECIAL_FILE_ICON_TRASH,
336 g_value_get_boolean(value));
337 break;
338
339 case PROP_SHOW_REMOVABLE:
340 xfdesktop_file_icon_manager_set_show_removable_media(fmanager,
341 g_value_get_boolean(value));
342 break;
343
344 case PROP_SHOW_THUMBNAILS:
345 xfdesktop_file_icon_manager_set_show_thumbnails(fmanager,
346 g_value_get_boolean(value));
347 break;
348
349 default:
350 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
351 }
352}
353
354static void
355xfdesktop_file_icon_manager_get_property(GObject *object,
356 guint property_id,
357 GValue *value,
358 GParamSpec *pspec)
359{
360 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(object);
361
362 switch(property_id) {
363 case PROP_FOLDER:
364 g_value_set_object(value, fmanager->priv->folder);
365 break;
366
367 case PROP_SHOW_FILESYSTEM:
368 g_value_set_boolean(value,
369 fmanager->priv->show_special[XFDESKTOP_SPECIAL_FILE_ICON_FILESYSTEM]);
370 break;
371
372 case PROP_SHOW_HOME:
373 g_value_set_boolean(value,
374 fmanager->priv->show_special[XFDESKTOP_SPECIAL_FILE_ICON_HOME]);
375 break;
376
377 case PROP_SHOW_TRASH:
378 g_value_set_boolean(value,
379 fmanager->priv->show_special[XFDESKTOP_SPECIAL_FILE_ICON_TRASH]);
380 break;
381
382 case PROP_SHOW_REMOVABLE:
383 g_value_set_boolean(value, fmanager->priv->show_removable_media);
384 break;
385
386 case PROP_SHOW_THUMBNAILS:
387 g_value_set_boolean(value, fmanager->priv->show_thumbnails);
388 break;
389
390 default:
391 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
392 }
393}
394
395static void
396xfdesktop_file_icon_manager_finalize(GObject *obj)
397{
398 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(obj);
399
400 if(fmanager->priv->inited)
401 xfdesktop_file_icon_manager_fini(XFDESKTOP_ICON_VIEW_MANAGER(fmanager));
402
403 g_object_unref(G_OBJECT(fmanager->priv->channel));
404
405 gtk_target_list_unref(fmanager->priv->drag_targets);
406 gtk_target_list_unref(fmanager->priv->drop_targets);
407
408 g_object_unref(fmanager->priv->folder);
409 g_object_unref(fmanager->priv->thumbnailer);
410
411 G_OBJECT_CLASS(xfdesktop_file_icon_manager_parent_class)->finalize(obj);
412}
413
414static void
415xfdesktop_file_icon_manager_icon_view_manager_init(XfdesktopIconViewManagerIface *iface)
416{
417 iface->manager_init = xfdesktop_file_icon_manager_real_init;
418 iface->manager_fini = xfdesktop_file_icon_manager_fini;
419 iface->drag_drop = xfdesktop_file_icon_manager_drag_drop;
420 iface->drag_data_received = xfdesktop_file_icon_manager_drag_data_received;
421 iface->drag_data_get = xfdesktop_file_icon_manager_drag_data_get;
422}
423
424
425
426/* FIXME: remove this before 4.4.0; leave it for now to migrate older beta
427* installs from the old location */
428static void
429__migrate_old_icon_positions(XfdesktopFileIconManager *fmanager)
430{
431 gchar relpath[PATH_MAX], *old_file;
432
433 g_snprintf(relpath, PATH_MAX, "xfce4/desktop/icons.screen%d-%dx%d.rc",
434 gdk_screen_get_number(fmanager->priv->gscreen),
435 gdk_screen_get_width(fmanager->priv->gscreen),
436 gdk_screen_get_height(fmanager->priv->gscreen));
437
438 old_file = xfce_resource_save_location(XFCE_RESOURCE_CACHE, relpath, FALSE);
439
440 if(G_UNLIKELY(old_file) && g_file_test(old_file, G_FILE_TEST_EXISTS)) {
441 gchar *new_file = xfce_resource_save_location(XFCE_RESOURCE_CONFIG,
442 relpath, FALSE);
443 if(G_LIKELY(new_file)) {
444 if(rename(old_file, new_file)) {
445 /* grumble, have to do this the hard way */
446 gchar *contents = NULL;
447 gsize length = 0;
448 GError *error = NULL;
449
450 if(g_file_get_contents(old_file, &contents, &length, &error)) {
451 if(!g_file_set_contents(new_file, contents, length,
452 &error))
453 {
454 g_critical("Unable to write to %s: %s", new_file,
455 error->message);
456 g_error_free(error);
457 }
458
459 g_free(contents);
460 } else {
461 g_critical("Unable to read from %s: %s", old_file,
462 error->message);
463 g_error_free(error);
464 }
465 }
466 } else
467 g_critical("Unable to migrate icon position file to new location.");
468
469 /* i debate removing the old file even if the migration failed,
470 * but i think this is the best way to avoid bug reports that
471 * aren't my problem. */
472 unlink(old_file);
473
474 g_free(new_file);
475 }
476
477 g_free(old_file);
478}
479
480static gboolean
481xfdesktop_file_icon_manager_check_create_desktop_folder(GFile *folder)
482{
483 GFileInfo *info;
484 GError *error = NULL;
485 gboolean result = TRUE;
486 gchar *primary;
487
488 g_return_val_if_fail(G_IS_FILE(folder), FALSE);
489
490 info = g_file_query_info(folder, XFDESKTOP_FILE_INFO_NAMESPACE,
491 G_FILE_QUERY_INFO_NONE, NULL, NULL);
492
493 if(info == NULL) {
494 if(!g_file_make_directory_with_parents(folder, NULL, &error)) {
495 gchar *uri = g_file_get_uri(folder);
496 gchar *display_name = g_filename_display_basename(uri);
497 primary = g_markup_printf_escaped(_("Could not create the desktop folder \"%s\""),
498 display_name);
499 g_free(display_name);
500 g_free(uri);
501
502 xfce_message_dialog(NULL, _("Desktop Folder Error"),
503 GTK_STOCK_DIALOG_WARNING, primary,
504 error->message, GTK_STOCK_CLOSE,
505 GTK_RESPONSE_ACCEPT, NULL);
506 g_free(primary);
507
508 result = FALSE;
509 }
510 } else {
511 if(g_file_info_get_file_type(info) != G_FILE_TYPE_DIRECTORY) {
512 gchar *uri = g_file_get_uri(folder);
513 gchar *display_name = g_filename_display_basename(uri);
514 primary = g_markup_printf_escaped(_("Could not create the desktop folder \"%s\""),
515 display_name);
516 g_free(display_name);
517 g_free(uri);
518
519 xfce_message_dialog(NULL, _("Desktop Folder Error"),
520 GTK_STOCK_DIALOG_WARNING, primary,
521 _("A normal file with the same name already exists. "
522 "Please delete or rename it."), GTK_STOCK_CLOSE,
523 GTK_RESPONSE_ACCEPT, NULL);
524 g_free(primary);
525
526 result = FALSE;
527 }
528 }
529
530 return result;
531}
532
533
534/* icon signal handlers */
535
536static void
537xfdesktop_file_icon_menu_executed(GtkWidget *widget,
538 gpointer user_data)
539{
540 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
541 XfdesktopIcon *icon;
542 GList *selected;
543
544 selected = xfdesktop_icon_view_get_selected_items(fmanager->priv->icon_view);
545 g_return_if_fail(g_list_length(selected) == 1);
546 icon = XFDESKTOP_ICON(selected->data);
547 g_list_free(selected);
548
549 xfdesktop_icon_activated(icon);
550}
551
552static void
553xfdesktop_file_icon_menu_open_all(GtkWidget *widget,
554 gpointer user_data)
555{
556 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
557 GList *selected;
558
559 selected = xfdesktop_icon_view_get_selected_items(fmanager->priv->icon_view);
560 g_return_if_fail(selected);
561
562 g_list_foreach(selected, (GFunc)xfdesktop_icon_activated, NULL);
563 g_list_free(selected);
564}
565
566static void
567xfdesktop_file_icon_menu_rename(GtkWidget *widget,
568 gpointer user_data)
569{
570 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
571 XfdesktopFileIcon *icon;
572 GList *selected;
573 GFile *file;
574 GtkWidget *toplevel;
575
576 selected = xfdesktop_icon_view_get_selected_items(fmanager->priv->icon_view);
577 g_return_if_fail(g_list_length(selected) == 1);
578 icon = XFDESKTOP_FILE_ICON(selected->data);
579 g_list_free(selected);
580
581 file = xfdesktop_file_icon_peek_file(icon);
582 toplevel = gtk_widget_get_toplevel(GTK_WIDGET(fmanager->priv->icon_view));
583
584 xfdesktop_file_utils_rename_file(file, fmanager->priv->gscreen,
585 GTK_WINDOW(toplevel));
586}
587
588enum
589{
590 COL_PIX = 0,
591 COL_NAME,
592 N_COLS
593};
594
595static void
596xfdesktop_file_icon_manager_delete_files(XfdesktopFileIconManager *fmanager,
597 GList *files)
598{
599 GtkWidget *toplevel = gtk_widget_get_toplevel(GTK_WIDGET(fmanager->priv->icon_view));
600 GList *gfiles = NULL, *lp;
601
602 for(lp = g_list_last(files); lp != NULL; lp = lp->prev)
603 gfiles = g_list_prepend(gfiles, xfdesktop_file_icon_peek_file(lp->data));
604
605 xfdesktop_file_utils_unlink_files(gfiles, fmanager->priv->gscreen,
606 GTK_WINDOW(toplevel));
607
608 g_list_free(gfiles);
609}
610
611static void
612xfdesktop_file_icon_manager_trash_files_cb(DBusGProxy *proxy,
613 GError *error,
614 gpointer user_data)
615{
616 XfdesktopFileIconManager *fmanager = user_data;
617
618 g_return_if_fail(fmanager);
619
620 if(error) {
621 GtkWidget *parent = gtk_widget_get_toplevel(GTK_WIDGET(fmanager->priv->icon_view));
622
623 xfce_message_dialog(GTK_WINDOW(parent),
624 _("Trash Error"), GTK_STOCK_DIALOG_ERROR,
625 _("The selected files could not be trashed"),
626 _("This feature requires a file manager service to "
627 "be present (such as the one supplied by Thunar)."),
628 GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT, NULL);
629 }
630}
631
632static gboolean
633xfdesktop_file_icon_manager_trash_files(XfdesktopFileIconManager *fmanager,
634 GList *files)
635{
636 DBusGProxy *trash_proxy = xfdesktop_file_utils_peek_trash_proxy();
637 gboolean result = TRUE;
638 gchar **uris, *display_name, *startup_id;
639 GList *l;
640 gint i, nfiles;
641 GFile *file;
642
643 g_return_val_if_fail(files, TRUE);
644
645 if(!trash_proxy)
646 return FALSE;
647
648 nfiles = g_list_length(files);
649 uris = g_new(gchar *, nfiles + 1);
650
651 for(l = files, i = 0; l; l = l->next, ++i) {
652 file = xfdesktop_file_icon_peek_file(XFDESKTOP_FILE_ICON(l->data));
653 uris[i] = g_file_get_uri(file);
654 }
655 uris[nfiles] = NULL;
656
657 display_name = gdk_screen_make_display_name(fmanager->priv->gscreen);
658 startup_id = g_strdup_printf("_TIME%d", gtk_get_current_event_time());
659
660 if (!xfdesktop_trash_proxy_move_to_trash_async(trash_proxy, (const char **)uris,
661 display_name, startup_id,
662 xfdesktop_file_icon_manager_trash_files_cb,
663 fmanager))
664 {
665 GtkWidget *parent = gtk_widget_get_toplevel(GTK_WIDGET(fmanager->priv->icon_view));
666
667 xfce_message_dialog(GTK_WINDOW(parent),
668 _("Trash Error"), GTK_STOCK_DIALOG_ERROR,
669 _("The selected files could not be trashed"),
670 _("This feature requires a file manager service to "
671 "be present (such as the one supplied by Thunar)."),
672 GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT, NULL);
673
674 result = FALSE;
675 }
676
677 g_free(startup_id);
678 g_strfreev(uris);
679 g_free(display_name);
680
681 return result;
682}
683
684static void
685xfdesktop_file_icon_manager_delete_selected(XfdesktopFileIconManager *fmanager,
686 gboolean force_delete)
687{
688 GList *selected, *l;
689
690 selected = xfdesktop_icon_view_get_selected_items(fmanager->priv->icon_view);
691 if(!selected)
692 return;
693
694 /* remove anybody that's not deletable */
695 for(l = selected; l; ) {
696 if(!xfdesktop_file_icon_can_delete_file(XFDESKTOP_FILE_ICON(l->data))) {
697 GList *next = l->next;
698
699 if(l->prev)
700 l->prev->next = l->next;
701 else /* this is the first item; reset |selected| */
702 selected = l->next;
703
704 if(l->next)
705 l->next->prev = l->prev;
706
707 l->next = l->prev = NULL;
708 g_list_free_1(l);
709
710 l = next;
711 } else
712 l = l->next;
713 }
714
715 if(G_UNLIKELY(!selected))
716 return;
717
718 /* make sure the icons don't get destroyed while we're working */
719 g_list_foreach(selected, (GFunc)g_object_ref, NULL);
720
721 if (!force_delete) {
722 xfdesktop_file_icon_manager_trash_files(fmanager, selected);
723 } else {
724 xfdesktop_file_icon_manager_delete_files(fmanager, selected);
725 }
726
727 g_list_foreach(selected, (GFunc)g_object_unref, NULL);
728 g_list_free(selected);
729
730 xfdesktop_file_icon_position_changed(NULL, fmanager);
731}
732
733static void
734xfdesktop_file_icon_menu_app_info_executed(GtkWidget *widget,
735 gpointer user_data)
736{
737 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
738 XfdesktopFileIcon *icon;
739 GdkAppLaunchContext *context;
740 GAppInfo *app_info;
741 GFile *file;
742 GList files, *selected;
743 GtkWidget *toplevel;
744 GError *error = NULL;
745
746 selected = xfdesktop_icon_view_get_selected_items(fmanager->priv->icon_view);
747 g_return_if_fail(g_list_length(selected) == 1);
748 icon = XFDESKTOP_FILE_ICON(selected->data);
749 g_list_free(selected);
750
751 /* get the app info related to this menu item */
752 app_info = g_object_get_qdata(G_OBJECT(widget), xfdesktop_app_info_quark);
753 if(!app_info)
754 return;
755
756 /* build a fake file list */
757 file = xfdesktop_file_icon_peek_file(icon);
758 files.prev = files.next = NULL;
759 files.data = file;
760
761 /* prepare the launch context and configure its screen */
762 context = gdk_app_launch_context_new();
763 toplevel = gtk_widget_get_toplevel(GTK_WIDGET(fmanager->priv->icon_view));
764 gdk_app_launch_context_set_screen(context, gtk_widget_get_screen(toplevel));
765
766 /* try to launch the application */
767 if(!xfdesktop_file_utils_app_info_launch(app_info, fmanager->priv->folder, &files,
768 G_APP_LAUNCH_CONTEXT(context), &error))
769 {
770 gchar *primary = g_markup_printf_escaped(_("Unable to launch \"%s\":"),
771 g_app_info_get_name(app_info));
772 xfce_message_dialog(GTK_WINDOW(toplevel), _("Launch Error"),
773 GTK_STOCK_DIALOG_ERROR, primary, error->message,
774 GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT, NULL);
775 g_free(primary);
776 g_error_free(error);
777 }
778}
779
780static void
781xfdesktop_file_icon_menu_open_folder(GtkWidget *widget,
782 gpointer user_data)
783{
784 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
785 XfdesktopFileIcon *icon;
786 GList *selected;
787 GFile *file;
788 GtkWidget *toplevel;
789
790 selected = xfdesktop_icon_view_get_selected_items(fmanager->priv->icon_view);
791 g_return_if_fail(g_list_length(selected) == 1);
792 icon = XFDESKTOP_FILE_ICON(selected->data);
793 g_list_free(selected);
794
795 file = xfdesktop_file_icon_peek_file(icon);
796
797 toplevel = gtk_widget_get_toplevel(GTK_WIDGET(fmanager->priv->icon_view));
798
799 xfdesktop_file_utils_open_folder(file, fmanager->priv->gscreen,
800 GTK_WINDOW(toplevel));
801}
802
803static void
804xfdesktop_file_icon_menu_open_desktop(GtkWidget *widget,
805 gpointer user_data)
806{
807 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
808 XfdesktopFileIcon *icon = fmanager->priv->desktop_icon;
809 GFile *file;
810 GtkWidget *toplevel;
811
812 file = xfdesktop_file_icon_peek_file(icon);
813 if(!file)
814 return;
815
816 toplevel = gtk_widget_get_toplevel(GTK_WIDGET(fmanager->priv->icon_view));
817
818 xfdesktop_file_utils_open_folder(file, fmanager->priv->gscreen,
819 GTK_WINDOW(toplevel));
820}
821
822static void
823xfdesktop_file_icon_menu_other_app(GtkWidget *widget,
824 gpointer user_data)
825{
826 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
827 XfdesktopFileIcon *icon;
828 GtkWidget *toplevel;
829 GList *selected;
830 GFile *file;
831
832 selected = xfdesktop_icon_view_get_selected_items(fmanager->priv->icon_view);
833 g_return_if_fail(g_list_length(selected) == 1);
834 icon = XFDESKTOP_FILE_ICON(selected->data);
835 g_list_free(selected);
836
837 toplevel = gtk_widget_get_toplevel(GTK_WIDGET(fmanager->priv->icon_view));
838
839 file = xfdesktop_file_icon_peek_file(icon);
840
841 xfdesktop_file_utils_display_chooser_dialog(file, TRUE,
842 fmanager->priv->gscreen,
843 GTK_WINDOW(toplevel));
844}
845
846static void
847xfdesktop_file_icon_menu_cut(GtkWidget *widget,
848 gpointer user_data)
849{
850 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
851 GList *files;
852
853 files = xfdesktop_icon_view_get_selected_items(fmanager->priv->icon_view);
854 if(!files)
855 return;
856
857 xfdesktop_clipboard_manager_cut_files(clipboard_manager, files);
858
859 g_list_free(files);
860}
861
862static void
863xfdesktop_file_icon_menu_copy(GtkWidget *widget,
864 gpointer user_data)
865{
866 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
867 GList *files;
868
869 files = xfdesktop_icon_view_get_selected_items(fmanager->priv->icon_view);
870 if(!files)
871 return;
872
873 xfdesktop_clipboard_manager_copy_files(clipboard_manager, files);
874
875 g_list_free(files);
876}
877
878static void
879xfdesktop_file_icon_menu_delete(GtkWidget *widget,
880 gpointer user_data)
881{
882 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
883 GdkModifierType state;
884 gboolean force_delete = FALSE;
885
886 if(gtk_get_current_event_state(&state) && state & GDK_SHIFT_MASK)
887 force_delete = TRUE;
888
889 xfdesktop_file_icon_manager_delete_selected(fmanager, force_delete);
890}
891
892static void
893xfdesktop_file_icon_menu_paste(GtkWidget *widget,
894 gpointer user_data)
895{
896 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
897 if(widget && fmanager)
898 xfdesktop_clipboard_manager_paste_files(clipboard_manager, fmanager->priv->folder, widget, NULL);
899}
900
901static void
902xfdesktop_file_icon_menu_arrange_icons(GtkWidget *widget,
903 gpointer user_data)
904{
905 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
906 xfdesktop_icon_view_sort_icons(fmanager->priv->icon_view);
907}
908
909static void
910xfdesktop_file_icon_menu_properties(GtkWidget *widget,
911 gpointer user_data)
912{
913 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
914 GList *selected;
915 XfdesktopFileIcon *icon;
916 GtkWidget *toplevel;
917 GFile *file;
918
919 selected = xfdesktop_icon_view_get_selected_items(fmanager->priv->icon_view);
920 g_return_if_fail(g_list_length(selected) == 1);
921 icon = XFDESKTOP_FILE_ICON(selected->data);
922 g_list_free(selected);
923
924 file = xfdesktop_file_icon_peek_file(icon);
925 toplevel = gtk_widget_get_toplevel(GTK_WIDGET(fmanager->priv->icon_view));
926
927 xfdesktop_file_utils_show_properties_dialog(file, fmanager->priv->gscreen,
928 GTK_WINDOW(toplevel));
929}
930
931static void
932xfdesktop_file_icon_manager_desktop_properties(GtkWidget *widget,
933 gpointer user_data)
934{
935 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
936 GtkWidget *parent = gtk_widget_get_toplevel(GTK_WIDGET(fmanager->priv->icon_view));
937 GFile *file = xfdesktop_file_icon_peek_file (fmanager->priv->desktop_icon);
938
939 xfdesktop_file_utils_show_properties_dialog(file, fmanager->priv->gscreen,
940 GTK_WINDOW(parent));
941}
942
943static GtkWidget *
944xfdesktop_menu_item_from_app_info(XfdesktopFileIconManager *fmanager,
945 XfdesktopFileIcon *icon,
946 GAppInfo *app_info,
947 gboolean with_mnemonic,
948 gboolean with_title_prefix)
949{
950 GtkWidget *mi, *img;
951 gchar *title;
952 GIcon *gicon;
953
954 if(!with_title_prefix)
955 title = g_strdup(g_app_info_get_name(app_info));
956 else if(with_mnemonic) {
957 title = g_strdup_printf(_("_Open With \"%s\""),
958 g_app_info_get_name(app_info));
959 } else {
960 title = g_strdup_printf(_("Open With \"%s\""),
961 g_app_info_get_name(app_info));
962 }
963
964 if(with_mnemonic)
965 mi = gtk_image_menu_item_new_with_mnemonic(title);
966 else
967 mi = gtk_image_menu_item_new_with_label(title);
968 g_free(title);
969
970 g_object_set_qdata_full(G_OBJECT(mi), xfdesktop_app_info_quark,
971 g_object_ref(app_info), g_object_unref);
972
973 gicon = g_app_info_get_icon(app_info);
974 img = gtk_image_new_from_gicon(gicon, GTK_ICON_SIZE_MENU);
975 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi),
976 img);
977 gtk_widget_show(img);
978 gtk_widget_show(mi);
979
980 g_signal_connect(G_OBJECT(mi), "activate",
981 G_CALLBACK(xfdesktop_file_icon_menu_app_info_executed),
982 fmanager);
983
984 return mi;
985}
986
987static gboolean
988xfdesktop_file_icon_menu_free_icon_list_idled(gpointer user_data)
989{
990 GList *icon_list = user_data;
991
992 g_list_foreach(icon_list, (GFunc)g_object_unref, NULL);
993 g_list_free(icon_list);
994
995 return FALSE;
996}
997
998static void
999xfdesktop_file_icon_menu_free_icon_list(GtkMenu *menu,
1000 gpointer user_data)
1001{
1002 g_idle_add(xfdesktop_file_icon_menu_free_icon_list_idled, user_data);
1003}
1004
1005static void
1006xfdesktop_file_icon_menu_create_launcher(GtkWidget *widget,
1007 gpointer user_data)
1008{
1009 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
1010 GFile *file;
1011 gchar *cmd = NULL, *uri = NULL, *display_name;
1012 GError *error = NULL;
1013
1014 display_name = gdk_screen_make_display_name(fmanager->priv->gscreen);
1015
1016 file = g_object_get_data(G_OBJECT(widget), "file");
1017
1018 if(file) {
1019 uri = g_file_get_uri(file);
1020 cmd = g_strdup_printf("exo-desktop-item-edit \"--display=%s\" \"%s\"",
1021 display_name, uri);
1022 } else {
1023 const gchar *type = g_object_get_data(G_OBJECT(widget), "xfdesktop-launcher-type");
1024 uri = g_file_get_uri(fmanager->priv->folder);
1025 if(G_UNLIKELY(!type))
1026 type = "Application";
1027 cmd = g_strdup_printf("exo-desktop-item-edit \"--display=%s\" --create-new --type %s \"%s\"",
1028 display_name, type, uri);
1029 }
1030
1031 if(!xfce_spawn_command_line_on_screen(NULL, cmd, FALSE, FALSE, &error)) {
1032 GtkWidget *toplevel = gtk_widget_get_toplevel(GTK_WIDGET(fmanager->priv->icon_view));
1033 xfce_message_dialog(GTK_WINDOW(toplevel), _("Launch Error"),
1034 GTK_STOCK_DIALOG_ERROR,
1035 _("Unable to launch \"exo-desktop-item-edit\", which is required to create and edit launchers and links on the desktop."),
1036 error->message, GTK_STOCK_CLOSE,
1037 GTK_RESPONSE_ACCEPT, NULL);
1038 g_error_free(error);
1039 }
1040
1041 g_free(display_name);
1042 g_free(uri);
1043 g_free(cmd);
1044}
1045
1046static void
1047xfdesktop_file_icon_menu_create_folder(GtkWidget *widget,
1048 gpointer user_data)
1049{
1050 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
1051 GtkWidget *toplevel;
1052
1053 toplevel = gtk_widget_get_toplevel(GTK_WIDGET(fmanager->priv->icon_view));
1054
1055 xfdesktop_file_utils_create_file(fmanager->priv->folder, "inode/directory",
1056 fmanager->priv->gscreen,
1057 GTK_WINDOW(toplevel));
1058}
1059
1060static void
1061xfdesktop_file_icon_template_item_activated(GtkWidget *mi,
1062 gpointer user_data)
1063{
1064 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
1065 GtkWidget *toplevel;
1066 GFile *file = g_object_get_data(G_OBJECT(mi), "file");
1067
1068 toplevel = gtk_widget_get_toplevel(GTK_WIDGET(fmanager->priv->icon_view));
1069
1070 if(file) {
1071 xfdesktop_file_utils_create_file_from_template(fmanager->priv->folder, file,
1072 fmanager->priv->gscreen,
1073 GTK_WINDOW(toplevel));
1074 } else {
1075 xfdesktop_file_utils_create_file(fmanager->priv->folder, "text/plain",
1076 fmanager->priv->gscreen,
1077 GTK_WINDOW(toplevel));
1078 }
1079}
1080
1081static gint
1082compare_template_files(gconstpointer a,
1083 gconstpointer b)
1084{
1085 GFileInfo *info_a = g_object_get_data(G_OBJECT(a), "info");
1086 GFileInfo *info_b = g_object_get_data(G_OBJECT(b), "info");
1087 GFileType type_a = g_file_info_get_file_type(info_a);
1088 GFileType type_b = g_file_info_get_file_type(info_b);
1089 const gchar* name_a = g_file_info_get_display_name(info_a);
1090 const gchar* name_b = g_file_info_get_display_name(info_b);
1091
1092 if(!info_a || !info_b)
1093 return 0;
1094
1095 if(type_a == type_b) {
1096 return g_strcmp0(name_a, name_b);
1097 } else {
1098 if(type_a == G_FILE_TYPE_DIRECTORY)
1099 return -1;
1100 else
1101 return 1;
1102 }
1103}
1104
1105static gboolean
1106xfdesktop_file_icon_menu_fill_template_menu(GtkWidget *menu,
1107 GFile *template_dir,
1108 XfdesktopFileIconManager *fmanager)
1109{
1110 GFileEnumerator *enumerator;
1111 GtkWidget *item, *image, *submenu;
1112 GFileInfo *info;
1113 GFile *file;
1114 GIcon *icon;
1115 GList *files = NULL, *lp;
1116 gchar *label, *dot;
1117 gboolean have_templates = FALSE;
1118
1119 g_return_val_if_fail(G_IS_FILE(template_dir), FALSE);
1120
1121 enumerator = g_file_enumerate_children(template_dir,
1122 XFDESKTOP_FILE_INFO_NAMESPACE,
1123 G_FILE_QUERY_INFO_NONE,
1124 NULL, NULL);
1125
1126 if(enumerator) {
1127 while((info = g_file_enumerator_next_file(enumerator, NULL, NULL))) {
1128 file = g_file_get_child(template_dir, g_file_info_get_name(info));
1129 g_object_set_data_full(G_OBJECT(file), "info", info, g_object_unref);
1130 files = g_list_prepend(files, file);
1131 }
1132
1133 g_object_unref(enumerator);
1134 }
1135
1136 files = g_list_sort(files, compare_template_files);
1137
1138 for(lp = files; lp != NULL; lp = lp->next) {
1139 file = lp->data;
1140 info = g_object_get_data(G_OBJECT(file), "info");
1141
1142 if(g_file_info_get_file_type(info) == G_FILE_TYPE_DIRECTORY) {
1143 /* allocate a new submenu for the directory */
1144 submenu = gtk_menu_new();
1145 g_object_ref_sink(submenu);
1146 gtk_menu_set_screen(GTK_MENU(submenu), gtk_widget_get_screen(menu));
1147
1148 /* fill the submenu from the folder contents */
1149 have_templates = xfdesktop_file_icon_menu_fill_template_menu(submenu, file, fmanager)
1150 || have_templates;
1151
1152 /* check if any items were added to the submenu */
1153 if (GTK_MENU_SHELL(submenu)->children)
1154 {
1155 /* create a new menu item for the submenu */
1156 item = gtk_image_menu_item_new_with_label (g_file_info_get_display_name(info));
1157 icon = g_file_info_get_icon(info);
1158 image = gtk_image_new_from_gicon(icon, GTK_ICON_SIZE_MENU);
1159 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
1160 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
1161 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1162 gtk_widget_show (item);
1163 }
1164
1165 /* cleanup */
1166 g_object_unref (submenu);
1167 } else {
1168 /* generate a label by stripping off the extension */
1169 label = g_strdup(g_file_info_get_display_name(info));
1170 dot = g_utf8_strrchr(label, -1, '.');
1171 if(dot)
1172 *dot = '\0';
1173
1174 /* allocate a new menu item */
1175 item = gtk_image_menu_item_new_with_label(label);
1176 icon = g_file_info_get_icon(info);
1177 image = gtk_image_new_from_gicon(icon, GTK_ICON_SIZE_MENU);
1178 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
1179 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1180 gtk_widget_show(item);
1181
1182 g_object_set_data_full(G_OBJECT(item), "file",
1183 g_object_ref(file), g_object_unref);
1184
1185 g_signal_connect (G_OBJECT(item), "activate",
1186 G_CALLBACK(xfdesktop_file_icon_template_item_activated),
1187 fmanager);
1188
1189 have_templates = TRUE;
1190 }
1191
1192 g_object_unref(file);
1193 }
1194
1195 g_list_free(files);
1196
1197 return have_templates;
1198#if 0
1199 dp = g_dir_open (absolute_path, 0, NULL);
1200 g_free (absolute_path);
1201
1202 /* read the directory contents (if opened successfully) */
1203 if (G_LIKELY (dp != NULL))
1204 {
1205 /* process all files within the directory */
1206 for (;;)
1207 {
1208 /* read the name of the next file */
1209 name = g_dir_read_name (dp);
1210 if (G_UNLIKELY (name == NULL))
1211 break;
1212 else if (name[0] == '.')
1213 continue;
1214
1215 /* determine the info for that file */
1216 path = thunar_vfs_path_relative (templates_path, name);
1217 info = thunar_vfs_info_new_for_path (path, NULL);
1218 thunar_vfs_path_unref (path);
1219
1220 /* add the info (if any) to our list */
1221 if (G_LIKELY (info != NULL))
1222 info_list = g_list_insert_sorted (info_list, info, info_compare);
1223 }
1224
1225 /* close the directory handle */
1226 g_dir_close (dp);
1227 }
1228
1229 /* check if we have any infos */
1230 if (G_UNLIKELY (info_list == NULL))
1231 return FALSE;
1232
1233 /* determine the icon theme for the menu */
1234 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (menu));
1235
1236 /* add menu items for all infos */
1237 for (lp = info_list; lp != NULL; lp = lp->next)
1238 {
1239 /* determine the info */
1240 info = lp->data;
1241
1242 /* check if we have a regular file or a directory here */
1243 if (G_LIKELY (info->type == THUNAR_VFS_FILE_TYPE_REGULAR))
1244 {
1245 /* generate a label by stripping off the extension */
1246 label = g_strdup (info->display_name);
1247 dot = g_utf8_strrchr (label, -1, '.');
1248 if (G_LIKELY (dot != NULL))
1249 *dot = '\0';
1250
1251 /* allocate a new menu item */
1252 item = gtk_image_menu_item_new_with_label (label);
1253 g_object_set_data_full (G_OBJECT (item), I_("thunar-vfs-info"), thunar_vfs_info_ref (info), (GDestroyNotify) thunar_vfs_info_unref);
1254 g_signal_connect (G_OBJECT (item), "activate",
1255 G_CALLBACK (xfdesktop_file_icon_template_item_activated),
1256 fmanager);
1257 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1258 gtk_widget_show (item);
1259
1260 /* lookup the icon for the mime type of that file */
1261 icon_name = thunar_vfs_mime_info_lookup_icon_name (info->mime_info, icon_theme);
1262
1263 /* generate an image based on the named icon */
1264 image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
1265 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
1266 gtk_widget_show (image);
1267
1268 /* cleanup */
1269 g_free (label);
1270
1271 have_templates = TRUE;
1272 }
1273 else if (info->type == THUNAR_VFS_FILE_TYPE_DIRECTORY)
1274 {
1275 /* allocate a new submenu for the directory */
1276 submenu = gtk_menu_new ();
1277 g_object_ref_sink (G_OBJECT (submenu));
1278 gtk_menu_set_screen (GTK_MENU (submenu), gtk_widget_get_screen (menu));
1279
1280 /* fill the submenu from the folder contents */
1281 have_templates = xfdesktop_file_icon_menu_fill_template_menu(submenu,
1282 info->path,
1283 fmanager)
1284 || have_templates;
1285
1286 /* check if any items were added to the submenu */
1287 if (G_LIKELY (GTK_MENU_SHELL (submenu)->children != NULL))
1288 {
1289 /* hook up the submenu */
1290 item = gtk_image_menu_item_new_with_label (info->display_name);
1291 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
1292 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1293 gtk_widget_show (item);
1294
1295 /* lookup the icon for the mime type of that file */
1296 icon_name = thunar_vfs_mime_info_lookup_icon_name (info->mime_info, icon_theme);
1297
1298 /* generate an image based on the named icon */
1299 image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
1300 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
1301 gtk_widget_show (image);
1302 }
1303
1304 /* cleanup */
1305 g_object_unref (G_OBJECT (submenu));
1306 }
1307 }
1308
1309 /* release the info list */
1310 thunar_vfs_info_list_free (info_list);
1311#endif
1312
1313 return have_templates;
1314}
1315
1316#ifdef HAVE_THUNARX
1317static inline void
1318xfdesktop_menu_shell_append_action_list(GtkMenuShell *menu_shell,
1319 GList *actions)
1320{
1321 GList *l;
1322 GtkAction *action;
1323 GtkWidget *mi;
1324
1325 for(l = actions; l; l = l->next) {
1326 action = GTK_ACTION(l->data);
1327 mi = gtk_action_create_menu_item(action);
1328 gtk_widget_show(mi);
1329 gtk_menu_shell_append(menu_shell, mi);
1330 }
1331}
1332#endif
1333
1334static void
1335xfdesktop_settings_launch(GtkWidget *w,
1336 gpointer user_data)
1337{
1338 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
1339 gchar *cmd;
1340 GError *error = NULL;
1341
1342 cmd = g_find_program_in_path("xfdesktop-settings");
1343 if(!cmd)
1344 cmd = g_strdup(BINDIR "/xfdesktop-settings");
1345
1346 if(!xfce_spawn_command_line_on_screen(fmanager->priv->gscreen, cmd, FALSE, TRUE, &error)) {
1347 GtkWidget *toplevel = gtk_widget_get_toplevel(GTK_WIDGET(fmanager->priv->icon_view));
1348 /* printf is to be translator-friendly */
1349 gchar *primary = g_strdup_printf(_("Unable to launch \"%s\":"), cmd);
1350 xfce_message_dialog(GTK_WINDOW(toplevel), _("Launch Error"),
1351 GTK_STOCK_DIALOG_ERROR, primary, error->message,
1352 GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT, NULL);
1353 g_free(primary);
1354 g_error_free(error);
1355 }
1356
1357 g_free(cmd);
1358}
1359
1360static void
1361xfdesktop_file_icon_manager_populate_context_menu(XfceDesktop *desktop,
1362 GtkMenuShell *menu,
1363 gpointer user_data)
1364{
1365 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
1366 XfdesktopFileIcon *file_icon = NULL;
1367 GFileInfo *info = NULL;
1368 GList *selected, *app_infos, *l;
1369 GtkWidget *mi, *img, *tmpl_menu;
1370 gboolean multi_sel, got_custom_menu = FALSE;
1371 GFile *templates_dir = NULL, *home_dir;
1372 const gchar *templates_dir_path = NULL;
1373#ifdef HAVE_THUNARX
1374 GtkWidget *toplevel = gtk_widget_get_toplevel(GTK_WIDGET(fmanager->priv->icon_view));
1375#endif
1376
1377 TRACE("ENTERING");
1378
1379 selected = xfdesktop_icon_view_get_selected_items(fmanager->priv->icon_view);
1380 if(selected)
1381 file_icon = selected->data;
1382 else {
1383 /* assume click on the desktop itself */
1384 selected = g_list_append(selected, fmanager->priv->desktop_icon);
1385 file_icon = fmanager->priv->desktop_icon;
1386 }
1387 info = xfdesktop_file_icon_peek_file_info(file_icon);
1388
1389 multi_sel = (g_list_length(selected) > 1);
1390
1391 if(!multi_sel) {
1392 got_custom_menu = xfdesktop_icon_populate_context_menu(XFDESKTOP_ICON(selected->data),
1393 GTK_WIDGET(menu));
1394 }
1395
1396 /* make sure icons don't get destroyed while menu is open */
1397 g_list_foreach(selected, (GFunc)g_object_ref, NULL);
1398 g_object_set_data(G_OBJECT(menu), "--xfdesktop-icon-list", selected);
1399 g_signal_connect(G_OBJECT(menu), "deactivate",
1400 G_CALLBACK(xfdesktop_file_icon_menu_free_icon_list),
1401 selected);
1402
1403 if(!got_custom_menu) {
1404 if(multi_sel) {
1405 img = gtk_image_new_from_stock(GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU);
1406 gtk_widget_show(img);
1407 mi = gtk_image_menu_item_new_with_mnemonic(_("_Open all"));
1408 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img);
1409 gtk_widget_show(mi);
1410 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1411 g_signal_connect(G_OBJECT(mi), "activate",
1412 G_CALLBACK(xfdesktop_file_icon_menu_open_all),
1413 fmanager);
1414
1415 mi = gtk_separator_menu_item_new();
1416 gtk_widget_show(mi);
1417 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1418 } else if(info) {
1419 if(g_file_info_get_file_type(info) == G_FILE_TYPE_DIRECTORY) {
1420 img = gtk_image_new_from_stock(GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU);
1421 gtk_widget_show(img);
1422 if(file_icon == fmanager->priv->desktop_icon)
1423 mi = gtk_image_menu_item_new_with_mnemonic(_("_Open in New Window"));
1424 else
1425 mi = gtk_image_menu_item_new_with_mnemonic(_("_Open"));
1426 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img);
1427 gtk_widget_show(mi);
1428 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1429 g_signal_connect(G_OBJECT(mi), "activate",
1430 file_icon == fmanager->priv->desktop_icon
1431 ? G_CALLBACK(xfdesktop_file_icon_menu_open_desktop)
1432 : G_CALLBACK(xfdesktop_file_icon_menu_open_folder),
1433 fmanager);
1434
1435 mi = gtk_separator_menu_item_new();
1436 gtk_widget_show(mi);
1437 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1438
1439 if(file_icon == fmanager->priv->desktop_icon) {
1440 GIcon *icon;
1441
1442 /* create launcher item */
1443
1444 mi = gtk_image_menu_item_new_with_mnemonic(_("Create _Launcher..."));
1445 g_object_set_data(G_OBJECT(mi), "xfdesktop-launcher-type", "Application");
1446 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1447 gtk_widget_show(mi);
1448
1449 g_signal_connect(G_OBJECT(mi), "activate",
1450 G_CALLBACK(xfdesktop_file_icon_menu_create_launcher),
1451 fmanager);
1452
1453 icon = g_content_type_get_icon("application/x-desktop");
1454 img = gtk_image_new_from_gicon(icon, GTK_ICON_SIZE_MENU);
1455 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img);
1456 gtk_widget_show(img);
1457
1458 /* create link item */
1459
1460 mi = gtk_image_menu_item_new_with_mnemonic(_("Create _URL Link..."));
1461 g_object_set_data(G_OBJECT(mi), "xfdesktop-launcher-type", "Link");
1462 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1463 gtk_widget_show(mi);
1464
1465 g_signal_connect(G_OBJECT(mi), "activate",
1466 G_CALLBACK(xfdesktop_file_icon_menu_create_launcher),
1467 fmanager);
1468
1469 icon = g_themed_icon_new("insert-link");
1470 img = gtk_image_new_from_gicon(icon, GTK_ICON_SIZE_MENU);
1471 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img);
1472 gtk_widget_show(img);
1473
1474 /* create folder item */
1475
1476 mi = gtk_image_menu_item_new_with_mnemonic(_("Create _Folder..."));
1477 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1478 gtk_widget_show(mi);
1479
1480 g_signal_connect(G_OBJECT(mi), "activate",
1481 G_CALLBACK(xfdesktop_file_icon_menu_create_folder),
1482 fmanager);
1483
1484 icon = g_content_type_get_icon("inode/directory");
1485 img = gtk_image_new_from_gicon(icon, GTK_ICON_SIZE_MENU);
1486 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img);
1487 gtk_widget_show(img);
1488
1489 /* create from template submenu */
1490
1491 mi = gtk_menu_item_new_with_mnemonic(_("Create From _Template"));
1492 gtk_widget_show(mi);
1493 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1494
1495 tmpl_menu = gtk_menu_new();
1496 gtk_menu_item_set_submenu(GTK_MENU_ITEM(mi), tmpl_menu);
1497
1498 home_dir = g_file_new_for_path(xfce_get_homedir());
1499 templates_dir_path = g_get_user_special_dir(G_USER_DIRECTORY_TEMPLATES);
1500 if(templates_dir_path) {
1501 templates_dir = g_file_new_for_path(templates_dir_path);
1502 }
1503
1504 if(templates_dir && !g_file_equal(home_dir, templates_dir))
1505 {
1506 xfdesktop_file_icon_menu_fill_template_menu(tmpl_menu,
1507 templates_dir,
1508 fmanager);
1509 }
1510
1511 if(templates_dir)
1512 g_object_unref(templates_dir);
1513 g_object_unref(home_dir);
1514
1515 img = gtk_image_new_from_stock(GTK_STOCK_NEW, GTK_ICON_SIZE_MENU);
1516 gtk_widget_show(img);
1517 mi = gtk_image_menu_item_new_with_mnemonic(_("_Empty File"));
1518 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img);
1519 gtk_widget_show(mi);
1520 gtk_menu_shell_append(GTK_MENU_SHELL(tmpl_menu), mi);
1521 g_signal_connect(G_OBJECT(mi), "activate",
1522 G_CALLBACK(xfdesktop_file_icon_template_item_activated),
1523 fmanager);
1524
1525 mi = gtk_separator_menu_item_new();
1526 gtk_widget_show(mi);
1527 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1528 }
1529 } else {
1530 if(xfdesktop_file_utils_file_is_executable(info)) {
1531 img = gtk_image_new_from_stock(GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU);
1532 gtk_widget_show(img);
1533 mi = gtk_image_menu_item_new_with_mnemonic(_("_Execute"));
1534 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img);
1535 gtk_widget_show(mi);
1536 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1537
1538 g_signal_connect(G_OBJECT(mi), "activate",
1539 G_CALLBACK(xfdesktop_file_icon_menu_executed),
1540 fmanager);
1541
1542 mi = gtk_separator_menu_item_new();
1543 gtk_widget_show(mi);
1544 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1545
1546 if(g_content_type_equals(g_file_info_get_content_type(info),
1547 "application/x-desktop"))
1548 {
1549 GFile *file = xfdesktop_file_icon_peek_file(file_icon);
1550
1551 img = gtk_image_new_from_stock(GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU);
1552 gtk_widget_show(img);
1553 mi = gtk_image_menu_item_new_with_mnemonic(_("_Edit Launcher"));
1554 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img);
1555 g_object_set_data_full(G_OBJECT(mi), "file",
1556 g_object_ref(file), g_object_unref);
1557 gtk_widget_show(mi);
1558 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1559 g_signal_connect(G_OBJECT(mi), "activate",
1560 G_CALLBACK(xfdesktop_file_icon_menu_create_launcher),
1561 fmanager);
1562 }
1563 }
1564
1565 app_infos = g_app_info_get_all_for_type(g_file_info_get_content_type(info));
1566 if(app_infos) {
1567 GAppInfo *app_info = G_APP_INFO(app_infos->data);
1568
1569 mi = xfdesktop_menu_item_from_app_info(fmanager, file_icon,
1570 app_info, TRUE, TRUE);
1571 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1572
1573 g_object_unref(app_info);
1574
1575 if(app_infos->next) {
1576 GtkWidget *app_infos_menu;
1577 gint list_len = g_list_length(app_infos->next);
1578
1579 if(!xfdesktop_file_utils_file_is_executable(info)
1580 && list_len <= 3)
1581 {
1582 mi = gtk_separator_menu_item_new();
1583 gtk_widget_show(mi);
1584 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1585 }
1586
1587 if(list_len > 3) {
1588 mi = gtk_menu_item_new_with_label(_("Open With"));
1589 gtk_widget_show(mi);
1590 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1591
1592 app_infos_menu = gtk_menu_new();
1593 gtk_menu_item_set_submenu(GTK_MENU_ITEM(mi),
1594 app_infos_menu);
1595 } else
1596 app_infos_menu = (GtkWidget *)menu;
1597
1598 for(l = app_infos->next; l; l = l->next) {
1599 app_info = G_APP_INFO(l->data);
1600 mi = xfdesktop_menu_item_from_app_info(fmanager,
1601 file_icon, app_info,
1602 FALSE, TRUE);
1603 gtk_menu_shell_append(GTK_MENU_SHELL(app_infos_menu), mi);
1604 g_object_unref(app_info);
1605 }
1606 }
1607
1608 /* free the app info list */
1609 g_list_free(app_infos);
1610 }
1611
1612 img = gtk_image_new_from_stock(GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU);
1613 gtk_widget_show(img);
1614 mi = gtk_image_menu_item_new_with_mnemonic(_("Open With Other _Application..."));
1615 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img);
1616 gtk_widget_show(mi);
1617 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1618 g_signal_connect(G_OBJECT(mi), "activate",
1619 G_CALLBACK(xfdesktop_file_icon_menu_other_app),
1620 fmanager);
1621
1622 mi = gtk_separator_menu_item_new();
1623 gtk_widget_show(mi);
1624 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1625 }
1626 }
1627
1628#ifdef HAVE_THUNARX
1629 if(!multi_sel && fmanager->priv->thunarx_menu_providers) {
1630 GList *menu_actions = NULL;
1631 ThunarxMenuProvider *provider;
1632
1633 if(g_file_info_get_file_type(info) == G_FILE_TYPE_DIRECTORY) {
1634 for(l = fmanager->priv->thunarx_menu_providers; l; l = l->next) {
1635 provider = THUNARX_MENU_PROVIDER(l->data);
1636 menu_actions = g_list_concat(menu_actions,
1637 thunarx_menu_provider_get_folder_actions(provider,
1638 toplevel,
1639 THUNARX_FILE_INFO(file_icon)));
1640 }
1641 } else {
1642 for(l = fmanager->priv->thunarx_menu_providers; l; l = l->next) {
1643 provider = THUNARX_MENU_PROVIDER(l->data);
1644 menu_actions = g_list_concat(menu_actions,
1645 thunarx_menu_provider_get_file_actions(provider,
1646 toplevel,
1647 selected));
1648 }
1649 }
1650
1651 if(menu_actions) {
1652 xfdesktop_menu_shell_append_action_list(GTK_MENU_SHELL(menu),
1653 menu_actions);
1654 g_list_foreach(menu_actions, (GFunc)g_object_unref, NULL);
1655 g_list_free(menu_actions);
1656
1657 mi = gtk_separator_menu_item_new();
1658 gtk_widget_show(mi);
1659 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1660 }
1661 }
1662#endif
1663
1664 if(file_icon == fmanager->priv->desktop_icon) {
1665 mi = gtk_image_menu_item_new_from_stock(GTK_STOCK_PASTE, NULL);
1666 gtk_widget_show(mi);
1667 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1668 if(xfdesktop_clipboard_manager_get_can_paste(clipboard_manager)) {
1669 g_signal_connect(G_OBJECT(mi), "activate",
1670 G_CALLBACK(xfdesktop_file_icon_menu_paste),
1671 fmanager);
1672 } else
1673 gtk_widget_set_sensitive(mi, FALSE);
1674 } else {
1675 mi = gtk_image_menu_item_new_from_stock(GTK_STOCK_COPY, NULL);
1676 gtk_widget_show(mi);
1677 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1678 g_signal_connect(G_OBJECT(mi), "activate",
1679 G_CALLBACK(xfdesktop_file_icon_menu_copy),
1680 fmanager);
1681
1682 mi = gtk_image_menu_item_new_from_stock(GTK_STOCK_CUT, NULL);
1683 gtk_widget_show(mi);
1684 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1685 if(multi_sel || xfdesktop_file_icon_can_delete_file(file_icon)) {
1686 g_signal_connect(G_OBJECT(mi), "activate",
1687 G_CALLBACK(xfdesktop_file_icon_menu_cut),
1688 fmanager);
1689 } else
1690 gtk_widget_set_sensitive(mi, FALSE);
1691
1692 mi = gtk_image_menu_item_new_from_stock(GTK_STOCK_DELETE, NULL);
1693 gtk_widget_show(mi);
1694 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1695 if(multi_sel || xfdesktop_file_icon_can_delete_file(file_icon)) {
1696 g_signal_connect(G_OBJECT(mi), "activate",
1697 G_CALLBACK(xfdesktop_file_icon_menu_delete),
1698 fmanager);
1699 } else
1700 gtk_widget_set_sensitive(mi, FALSE);
1701
1702 mi = gtk_separator_menu_item_new();
1703 gtk_widget_show(mi);
1704 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1705
1706 mi = gtk_image_menu_item_new_with_mnemonic(_("_Rename..."));
1707 gtk_widget_show(mi);
1708 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1709 if(!multi_sel && xfdesktop_file_icon_can_rename_file(file_icon)) {
1710 g_signal_connect(G_OBJECT(mi), "activate",
1711 G_CALLBACK(xfdesktop_file_icon_menu_rename),
1712 fmanager);
1713 } else
1714 gtk_widget_set_sensitive(mi, FALSE);
1715 }
1716
1717 mi = gtk_separator_menu_item_new();
1718 gtk_widget_show(mi);
1719 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1720
1721 if(file_icon == fmanager->priv->desktop_icon) {
1722 img = gtk_image_new_from_stock(GTK_STOCK_SORT_ASCENDING, GTK_ICON_SIZE_MENU);
1723 gtk_widget_show(img);
1724 mi = gtk_image_menu_item_new_with_mnemonic(_("Arrange Desktop _Icons"));
1725 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img);
1726 gtk_widget_show(mi);
1727 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1728 g_signal_connect(G_OBJECT(mi), "activate",
1729 G_CALLBACK(xfdesktop_file_icon_menu_arrange_icons),
1730 fmanager);
1731
1732 img = gtk_image_new_from_stock(GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU);
1733 gtk_widget_show(img);
1734 mi = gtk_image_menu_item_new_with_mnemonic(_("Desktop _Settings..."));
1735 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img);
1736 gtk_widget_show(mi);
1737 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1738 g_signal_connect(G_OBJECT(mi), "activate",
1739 G_CALLBACK(xfdesktop_settings_launch), fmanager);
1740 }
1741
1742 img = gtk_image_new_from_stock(GTK_STOCK_PROPERTIES, GTK_ICON_SIZE_MENU);
1743 gtk_widget_show(img);
1744 mi = gtk_image_menu_item_new_with_mnemonic(_("P_roperties..."));
1745 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img);
1746 gtk_widget_show(mi);
1747 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1748 if(multi_sel || !info)
1749 gtk_widget_set_sensitive(mi, FALSE);
1750 else {
1751 g_signal_connect(G_OBJECT(mi), "activate",
1752 file_icon == fmanager->priv->desktop_icon
1753 ? G_CALLBACK(xfdesktop_file_icon_manager_desktop_properties)
1754 : G_CALLBACK(xfdesktop_file_icon_menu_properties),
1755 fmanager);
1756 }
1757 }
1758
1759 /* don't free |selected|. the menu deactivated handler does that */
1760}
1761
1762static void
1763file_icon_hash_write_icons(gpointer key,
1764 gpointer value,
1765 gpointer data)
1766{
1767 XfceRc *rcfile = data;
1768 XfdesktopIcon *icon = value;
1769 guint16 row, col;
1770
1771 if(xfdesktop_icon_get_position(icon, &row, &col)) {
1772 xfce_rc_set_group(rcfile, xfdesktop_icon_peek_label(icon));
1773 xfce_rc_write_int_entry(rcfile, "row", row);
1774 xfce_rc_write_int_entry(rcfile, "col", col);
1775 }
1776}
1777
1778static gboolean
1779xfdesktop_file_icon_manager_save_icons(gpointer user_data)
1780{
1781 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
1782 gchar relpath[PATH_MAX], *tmppath, *path;
1783 XfceRc *rcfile;
1784 gint x = 0, y = 0, width = 0, height = 0;
1785
1786 fmanager->priv->save_icons_id = 0;
1787
1788 xfdesktop_get_workarea_single(fmanager->priv->icon_view,
1789 0,
1790 &x,
1791 &y,
1792 &width,
1793 &height);
1794
1795 g_snprintf(relpath, PATH_MAX, "xfce4/desktop/icons.screen%d-%dx%d.rc",
1796 gdk_screen_get_number(fmanager->priv->gscreen),
1797 width,
1798 height);
1799
1800 path = xfce_resource_save_location(XFCE_RESOURCE_CONFIG, relpath, TRUE);
1801 if(!path)
1802 return FALSE;
1803
1804 tmppath = g_strconcat(path, ".new", NULL);
1805
1806 rcfile = xfce_rc_simple_open(tmppath, FALSE);
1807 if(!rcfile) {
1808 g_warning("Unable to determine location of icon position cache file. " \
1809 "Icon positions will not be saved.");
1810 g_free(path);
1811 g_free(tmppath);
1812 return FALSE;
1813 }
1814
1815 g_hash_table_foreach(fmanager->priv->icons,
1816 file_icon_hash_write_icons, rcfile);
1817 if(fmanager->priv->show_removable_media) {
1818 g_hash_table_foreach(fmanager->priv->removable_icons,
1819 file_icon_hash_write_icons, rcfile);
1820 }
1821 g_hash_table_foreach(fmanager->priv->special_icons,
1822 file_icon_hash_write_icons, rcfile);
1823
1824 xfce_rc_flush(rcfile);
1825 xfce_rc_close(rcfile);
1826
1827 if(rename(tmppath, path)) {
1828 g_warning("Unable to rename temp file to %s: %s", path,
1829 strerror(errno));
1830 unlink(tmppath);
1831 }
1832
1833 g_free(path);
1834 g_free(tmppath);
1835
1836 return FALSE;
1837}
1838
1839static void
1840xfdesktop_file_icon_position_changed(XfdesktopFileIcon *icon,
1841 gpointer user_data)
1842{
1843 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
1844
1845 if(fmanager->priv->save_icons_id)
1846 g_source_remove(fmanager->priv->save_icons_id);
1847
1848 fmanager->priv->save_icons_id = g_timeout_add(SAVE_DELAY,
1849 xfdesktop_file_icon_manager_save_icons,
1850 fmanager);
1851}
1852
1853
1854/* ***** */
1855
1856gboolean
1857xfdesktop_file_icon_manager_get_cached_icon_position(XfdesktopFileIconManager *fmanager,
1858 const gchar *name,
1859 gint16 *row,
1860 gint16 *col)
1861{
1862 gchar relpath[PATH_MAX];
1863 gchar *filename = NULL;
1864 gboolean ret = FALSE;
1865 gint x = 0, y = 0, width = 0, height = 0;
1866
1867 xfdesktop_get_workarea_single(fmanager->priv->icon_view,
1868 0,
1869 &x,
1870 &y,
1871 &width,
1872 &height);
1873
1874 g_snprintf(relpath, PATH_MAX, "xfce4/desktop/icons.screen%d-%dx%d.rc",
1875 gdk_screen_get_number(fmanager->priv->gscreen),
1876 width,
1877 height);
1878
1879 filename = xfce_resource_lookup(XFCE_RESOURCE_CONFIG, relpath);
1880
1881 /* Check if we have to migrate from the old file format */
1882 if(filename == NULL) {
1883 g_snprintf(relpath, PATH_MAX, "xfce4/desktop/icons.screen%d.rc",
1884 gdk_screen_get_number(fmanager->priv->gscreen));
1885 filename = xfce_resource_lookup(XFCE_RESOURCE_CONFIG, relpath);
1886 }
1887
1888 if(filename != NULL) {
1889 XfceRc *rcfile;
1890 rcfile = xfce_rc_simple_open(filename, TRUE);
1891
1892 if(xfce_rc_has_group(rcfile, name)) {
1893 xfce_rc_set_group(rcfile, name);
1894 *row = xfce_rc_read_int_entry(rcfile, "row", -1);
1895 *col = xfce_rc_read_int_entry(rcfile, "col", -1);
1896 if(*row >= 0 && *col >= 0)
1897 ret = TRUE;
1898 }
1899 xfce_rc_close(rcfile);
1900 g_free(filename);
1901 }
1902
1903 return ret;
1904}
1905
1906
1907#if defined(DEBUG) && DEBUG > 0
1908static GList *_alive_icon_list = NULL;
1909
1910static void
1911_icon_notify_destroy(gpointer data,
1912 GObject *obj)
1913{
1914 g_assert(g_list_find(_alive_icon_list, obj));
1915 _alive_icon_list = g_list_remove(_alive_icon_list, obj);
1916
1917 DBG("icon finalized: '%s'", xfdesktop_icon_peek_label(XFDESKTOP_ICON(obj)));
1918}
1919#endif
1920
1921static gboolean
1922xfdesktop_file_icon_manager_add_icon(XfdesktopFileIconManager *fmanager,
1923 XfdesktopFileIcon *icon,
1924 gboolean defer_if_missing)
1925{
1926 gint16 row = -1, col = -1;
1927 gboolean do_add = FALSE;
1928 const gchar *name;
1929 GFile *file;
1930
1931 file = xfdesktop_file_icon_peek_file(icon);
1932
1933 if(fmanager->priv->show_thumbnails && g_file_get_path(file) != NULL) {
1934 xfdesktop_thumbnailer_queue_thumbnail(fmanager->priv->thumbnailer,
1935 g_file_get_path(file));
1936 }
1937
1938
1939 name = xfdesktop_icon_peek_label(XFDESKTOP_ICON(icon));
1940 if(xfdesktop_file_icon_manager_get_cached_icon_position(fmanager, name,
1941 &row, &col))
1942 {
1943 DBG("attempting to set icon '%s' to position (%d,%d)", name, row, col);
1944 xfdesktop_icon_set_position(XFDESKTOP_ICON(icon), row, col);
1945 do_add = TRUE;
1946 } else {
1947 if(defer_if_missing) {
1948 fmanager->priv->deferred_icons = g_list_prepend(fmanager->priv->deferred_icons,
1949 g_object_ref(file));
1950 } else
1951 do_add = TRUE;
1952 }
1953
1954 if(do_add) {
1955 g_signal_connect(G_OBJECT(icon), "position-changed",
1956 G_CALLBACK(xfdesktop_file_icon_position_changed),
1957 fmanager);
1958 xfdesktop_icon_view_add_item(fmanager->priv->icon_view,
1959 XFDESKTOP_ICON(icon));
1960 }
1961
1962#if defined(DEBUG) && DEBUG > 0
1963 if(do_add) {
1964 _alive_icon_list = g_list_prepend(_alive_icon_list, icon);
1965 g_object_weak_ref(G_OBJECT(icon), _icon_notify_destroy, NULL);
1966 }
1967#endif
1968
1969 return do_add;
1970}
1971
1972static XfdesktopFileIcon *
1973xfdesktop_file_icon_manager_add_regular_icon(XfdesktopFileIconManager *fmanager,
1974 GFile *file,
1975 GFileInfo *info,
1976 gboolean defer_if_missing)
1977{
1978 XfdesktopRegularFileIcon *icon = NULL;
1979 gboolean is_desktop_file = FALSE;
1980
1981 g_return_val_if_fail(fmanager && G_IS_FILE(file) && G_IS_FILE_INFO(info), NULL);
1982
1983 if(g_content_type_equals(g_file_info_get_content_type(info),
1984 "application/x-desktop"))
1985 {
1986 is_desktop_file = TRUE;
1987 }
1988 else
1989 {
1990 gchar *uri = g_file_get_uri(file);
1991 if(g_str_has_suffix(uri, ".desktop"))
1992 is_desktop_file = TRUE;
1993 g_free(uri);
1994 }
1995
1996 /* if it's a .desktop file, and it has Hidden=true, or an
1997 * OnlyShowIn Or NotShowIn that would hide it from Xfce, don't
1998 * show it on the desktop (bug #4022) */
1999 if(is_desktop_file)
2000 {
2001 gchar *path = g_file_get_path(file);
2002 XfceRc *rcfile = xfce_rc_simple_open(path, TRUE);
2003 g_free(path);
2004
2005 if(rcfile) {
2006 const gchar *value;
2007
2008 xfce_rc_set_group(rcfile, "Desktop Entry");
2009 if(xfce_rc_read_bool_entry(rcfile, "Hidden", FALSE)) {
2010 xfce_rc_close(rcfile);
2011 return NULL;
2012 }
2013
2014 value = xfce_rc_read_entry(rcfile, "OnlyShowIn", NULL);
2015 if(value && strncmp(value, "XFCE;", 5) && !strstr(value, ";XFCE;")) {
2016 xfce_rc_close(rcfile);
2017 return NULL;
2018 }
2019
2020 value = xfce_rc_read_entry(rcfile, "NotShowIn", NULL);
2021 if(value && (!strncmp(value, "XFCE;", 5) || strstr(value, ";XFCE;"))) {
2022 xfce_rc_close(rcfile);
2023 return NULL;
2024 }
2025
2026 xfce_rc_close(rcfile);
2027 }
2028 }
2029
2030 /* should never return NULL */
2031 icon = xfdesktop_regular_file_icon_new(file, info, fmanager->priv->gscreen);
2032
2033 if(xfdesktop_file_icon_manager_add_icon(fmanager,
2034 XFDESKTOP_FILE_ICON(icon),
2035 defer_if_missing))
2036 {
2037 g_hash_table_replace(fmanager->priv->icons, g_object_ref(file), icon);
2038 return XFDESKTOP_FILE_ICON(icon);
2039 } else {
2040 g_object_unref(G_OBJECT(icon));
2041 return NULL;
2042 }
2043}
2044
2045static XfdesktopFileIcon *
2046xfdesktop_file_icon_manager_add_volume_icon(XfdesktopFileIconManager *fmanager,
2047 GVolume *volume)
2048{
2049 XfdesktopVolumeIcon *icon;
2050
2051 g_return_val_if_fail(fmanager && G_IS_VOLUME(volume), NULL);
2052
2053 /* should never return NULL */
2054 icon = xfdesktop_volume_icon_new(volume, fmanager->priv->gscreen);
2055
2056 if(xfdesktop_file_icon_manager_add_icon(fmanager,
2057 XFDESKTOP_FILE_ICON(icon),
2058 FALSE))
2059 {
2060 g_hash_table_replace(fmanager->priv->removable_icons,
2061 g_object_ref(G_OBJECT(volume)), icon);
2062 return XFDESKTOP_FILE_ICON(icon);
2063 } else {
2064 g_object_unref(G_OBJECT(icon));
2065 return NULL;
2066 }
2067}
2068
2069static XfdesktopFileIcon *
2070xfdesktop_file_icon_manager_add_special_file_icon(XfdesktopFileIconManager *fmanager,
2071 XfdesktopSpecialFileIconType type)
2072{
2073 XfdesktopSpecialFileIcon *icon;
2074
2075 /* can return NULL if it's the trash icon and dbus isn't around */
2076 icon = xfdesktop_special_file_icon_new(type, fmanager->priv->gscreen);
2077 if(!icon)
2078 return NULL;
2079
2080 if(xfdesktop_file_icon_manager_add_icon(fmanager,
2081 XFDESKTOP_FILE_ICON(icon),
2082 FALSE))
2083 {
2084 g_hash_table_replace(fmanager->priv->special_icons,
2085 GINT_TO_POINTER(type), icon);
2086 return XFDESKTOP_FILE_ICON(icon);
2087 } else {
2088 g_object_unref(G_OBJECT(icon));
2089 return NULL;
2090 }
2091}
2092
2093static gboolean
2094xfdesktop_remove_icons_ht(gpointer key,
2095 gpointer value,
2096 gpointer user_data)
2097{
2098 xfdesktop_icon_view_remove_item(XFDESKTOP_ICON_VIEW(user_data),
2099 XFDESKTOP_ICON(value));
2100 return TRUE;
2101}
2102
2103static void
2104xfdesktop_file_icon_manager_refresh_icons(XfdesktopFileIconManager *fmanager)
2105{
2106 gint i;
2107
2108 /* if a save is pending, flush icon positions */
2109 if(fmanager->priv->save_icons_id) {
2110 g_source_remove(fmanager->priv->save_icons_id);
2111 fmanager->priv->save_icons_id = 0;
2112 xfdesktop_file_icon_manager_save_icons(fmanager);
2113 }
2114
2115 /* ditch removable media */
2116 if(fmanager->priv->show_removable_media)
2117 xfdesktop_file_icon_manager_remove_removable_media(fmanager);
2118
2119 /* ditch special icons */
2120 for(i = 0; i <= XFDESKTOP_SPECIAL_FILE_ICON_TRASH; ++i) {
2121 XfdesktopIcon *icon = g_hash_table_lookup(fmanager->priv->special_icons,
2122 GINT_TO_POINTER(i));
2123 if(icon) {
2124 xfdesktop_icon_view_remove_item(fmanager->priv->icon_view, icon);
2125 g_hash_table_remove(fmanager->priv->special_icons,
2126 GINT_TO_POINTER(i));
2127 }
2128 }
2129
2130 /* ditch normal icons */
2131 if(fmanager->priv->icons) {
2132 g_hash_table_foreach_remove(fmanager->priv->icons,
2133 (GHRFunc)xfdesktop_remove_icons_ht,
2134 fmanager->priv->icon_view);
2135 }
2136
2137#if defined(DEBUG) && DEBUG > 0
2138 g_assert(_xfdesktop_icon_view_n_items(fmanager->priv->icon_view) == 0);
2139 g_assert(g_list_length(_alive_icon_list) == 0);
2140#endif
2141
2142 /* clear out anything left in the icon view */
2143 xfdesktop_icon_view_remove_all(fmanager->priv->icon_view);
2144
2145 /* add back the special icons */
2146 for(i = 0; i <= XFDESKTOP_SPECIAL_FILE_ICON_TRASH; ++i) {
2147 if(fmanager->priv->show_special[i])
2148 xfdesktop_file_icon_manager_add_special_file_icon(fmanager, i);
2149 }
2150
2151 /* add back removable media */
2152 if(fmanager->priv->show_removable_media)
2153 xfdesktop_file_icon_manager_load_removable_media(fmanager);
2154
2155 /* reload and add ~/Desktop/ */
2156 xfdesktop_file_icon_manager_load_desktop_folder(fmanager);
2157}
2158
2159static gboolean
2160xfdesktop_file_icon_manager_key_press(GtkWidget *widget,
2161 GdkEventKey *evt,
2162 gpointer user_data)
2163{
2164 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
2165 GList *selected;
2166 gboolean force_delete = FALSE;
2167
2168 switch(evt->keyval) {
2169 case GDK_Delete:
2170 case GDK_KP_Delete:
2171 if(evt->state & GDK_SHIFT_MASK)
2172 force_delete = TRUE;
2173 xfdesktop_file_icon_manager_delete_selected(fmanager, force_delete);
2174 break;
2175
2176 case GDK_c:
2177 case GDK_C:
2178 if(!(evt->state & GDK_CONTROL_MASK)
2179 || (evt->state & (GDK_SHIFT_MASK|GDK_MOD1_MASK|GDK_MOD4_MASK)))
2180 {
2181 return FALSE;
2182 }
2183 selected = xfdesktop_icon_view_get_selected_items(fmanager->priv->icon_view);
2184 if(selected) {
2185 xfdesktop_clipboard_manager_copy_files(clipboard_manager,
2186 selected);
2187 g_list_free(selected);
2188 }
2189 break;
2190
2191 case GDK_x:
2192 case GDK_X:
2193 if(!(evt->state & GDK_CONTROL_MASK)
2194 || (evt->state & (GDK_SHIFT_MASK|GDK_MOD1_MASK|GDK_MOD4_MASK)))
2195 {
2196 return FALSE;
2197 }
2198 selected = xfdesktop_icon_view_get_selected_items(fmanager->priv->icon_view);
2199 if(selected) {
2200 xfdesktop_clipboard_manager_cut_files(clipboard_manager,
2201 selected);
2202 g_list_free(selected);
2203 }
2204 return TRUE;
2205
2206 case GDK_v:
2207 case GDK_V:
2208 if(!(evt->state & GDK_CONTROL_MASK)
2209 || (evt->state & (GDK_SHIFT_MASK|GDK_MOD1_MASK|GDK_MOD4_MASK)))
2210 {
2211 return FALSE;
2212 }
2213 if(xfdesktop_clipboard_manager_get_can_paste(clipboard_manager)) {
2214 xfdesktop_clipboard_manager_paste_files(clipboard_manager, fmanager->priv->folder, widget, NULL);
2215 }
2216 return TRUE;
2217
2218 case GDK_r:
2219 case GDK_R:
2220 if(!(evt->state & GDK_CONTROL_MASK)
2221 || (evt->state & (GDK_SHIFT_MASK|GDK_MOD1_MASK|GDK_MOD4_MASK)))
2222 {
2223 return FALSE;
2224 }
2225 /* fall through */
2226 case GDK_F5:
2227 xfdesktop_file_icon_manager_refresh_icons(fmanager);
2228 return TRUE;
2229
2230 case GDK_F2:
2231 selected = xfdesktop_icon_view_get_selected_items(fmanager->priv->icon_view);
2232 if(g_list_length(selected) == 1) {
2233 XfdesktopFileIcon *icon = XFDESKTOP_FILE_ICON(selected->data);
2234 if(xfdesktop_file_icon_can_rename_file(icon)) {
2235 xfdesktop_file_icon_menu_rename(NULL, fmanager);
2236 return TRUE;
2237 }
2238 }
2239 if(selected)
2240 g_list_free(selected);
2241 break;
2242 }
2243
2244 return FALSE;
2245}
2246
2247static void
2248xfdesktop_file_icon_manager_file_changed(GFileMonitor *monitor,
2249 GFile *file,
2250 GFile *other_file,
2251 GFileMonitorEvent event,
2252 gpointer user_data)
2253{
2254 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
2255 XfdesktopFileIcon *icon;
2256 GFileInfo *file_info;
2257
2258 switch(event) {
2259 case G_FILE_MONITOR_EVENT_CHANGED:
2260 DBG("got changed event: %s", g_file_get_path(file));
2261
2262 icon = g_hash_table_lookup(fmanager->priv->icons, file);
2263 if(icon) {
2264 file_info = g_file_query_info(file, XFDESKTOP_FILE_INFO_NAMESPACE,
2265 G_FILE_QUERY_INFO_NONE, NULL, NULL);
2266
2267 if(file_info) {
2268 /* update the icon if the file still exists */
2269 xfdesktop_file_icon_update_file_info(icon, file_info);
2270 g_object_unref(file_info);
2271 } else {
2272 /* remove the icon as the file no longer seems to be existing */
2273 xfdesktop_icon_view_remove_item(fmanager->priv->icon_view,
2274 XFDESKTOP_ICON(icon));
2275 g_hash_table_remove(fmanager->priv->icons, file);
2276 }
2277 }
2278 break;
2279 case G_FILE_MONITOR_EVENT_CREATED:
2280 DBG("got created event");
2281
2282 /* make sure it's not the desktop folder itself */
2283 if(g_file_equal(fmanager->priv->folder, file))
2284 return;
2285
2286 /* first make sure we don't already have an icon for this path.
2287 * this seems to be necessary to avoid inconsistencies */
2288 icon = g_hash_table_lookup(fmanager->priv->icons, file);
2289 if(icon) {
2290 xfdesktop_icon_view_remove_item(fmanager->priv->icon_view,
2291 XFDESKTOP_ICON(icon));
2292 g_hash_table_remove(fmanager->priv->icons, file);
2293 }
2294
2295 file_info = g_file_query_info(file, XFDESKTOP_FILE_INFO_NAMESPACE,
2296 G_FILE_QUERY_INFO_NONE, NULL, NULL);
2297 if(file_info) {
2298 gboolean is_hidden = g_file_info_get_attribute_boolean(file_info,
2299 G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN);
2300 if(!is_hidden) {
2301 xfdesktop_file_icon_manager_add_regular_icon(fmanager,
2302 file, file_info,
2303 FALSE);
2304 }
2305
2306 g_object_unref(file_info);
2307 }
2308
2309 break;
2310 case G_FILE_MONITOR_EVENT_DELETED:
2311 DBG("got deleted event");
2312
2313 icon = g_hash_table_lookup(fmanager->priv->icons, file);
2314 if(icon) {
2315 /* Always try to remove thumbnail so it doesn't take up
2316 * space on the user's disk.
2317 */
2318 xfdesktop_thumbnailer_delete_thumbnail(fmanager->priv->thumbnailer,
2319 g_file_get_path(file));
2320 xfdesktop_icon_delete_thumbnail(XFDESKTOP_ICON(icon));
2321
2322 xfdesktop_icon_view_remove_item(fmanager->priv->icon_view,
2323 XFDESKTOP_ICON(icon));
2324 g_hash_table_remove(fmanager->priv->icons, file);
2325 } else {
2326 if(g_file_equal(file, fmanager->priv->folder)) {
2327 DBG("~/Desktop disappeared!");
2328 /* yes, refresh before and after is correct */
2329 xfdesktop_file_icon_manager_refresh_icons(fmanager);
2330 xfdesktop_file_icon_manager_check_create_desktop_folder(fmanager->priv->folder);
2331 xfdesktop_file_icon_manager_refresh_icons(fmanager);
2332 }
2333 }
2334 break;
2335 default:
2336 break;
2337 }
2338}
2339
2340static void
2341xfdesktop_file_icon_manager_files_ready(GFileEnumerator *enumerator,
2342 GAsyncResult *result,
2343 gpointer user_data)
2344{
2345 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
2346 GError *error = NULL;
2347 GList *files, *l;
2348 gboolean is_hidden;
2349
2350 g_return_if_fail(enumerator == fmanager->priv->enumerator);
2351
2352 files = g_file_enumerator_next_files_finish(enumerator, result, &error);
2353
2354 if(!files) {
2355 if(error) {
2356 GtkWidget *toplevel = gtk_widget_get_toplevel(GTK_WIDGET(fmanager->priv->icon_view));
2357#if GTK_CHECK_VERSION (2, 18, 0)
2358 xfce_message_dialog(gtk_widget_is_toplevel(toplevel) ? GTK_WINDOW(toplevel) : NULL,
2359#else
2360 xfce_message_dialog(GTK_WIDGET_TOPLEVEL(toplevel) ? GTK_WINDOW(toplevel) : NULL,
2361#endif
2362 _("Load Error"),
2363 GTK_STOCK_DIALOG_WARNING,
2364 _("Failed to load the desktop folder"), error->message,
2365 GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT, NULL);
2366 }
2367
2368 g_object_unref(fmanager->priv->enumerator);
2369 fmanager->priv->enumerator = NULL;
2370
2371 if(fmanager->priv->deferred_icons) {
2372 for(l = fmanager->priv->deferred_icons; l; l = l->next) {
2373 GFile *file = G_FILE(l->data);
2374 GFileInfo *info = g_file_query_info(file,
2375 XFDESKTOP_FILE_INFO_NAMESPACE,
2376 G_FILE_QUERY_INFO_NONE,
2377 NULL, NULL);
2378
2379 xfdesktop_file_icon_manager_add_regular_icon(fmanager,
2380 file, info,
2381 FALSE);
2382 g_object_unref(info);
2383 g_object_unref(file);
2384 }
2385 g_list_free(fmanager->priv->deferred_icons);
2386 fmanager->priv->deferred_icons = NULL;
2387 }
2388
2389
2390 if(!fmanager->priv->monitor) {
2391 fmanager->priv->monitor = g_file_monitor(fmanager->priv->folder,
2392 G_FILE_MONITOR_NONE,
2393 NULL, NULL);
2394 g_signal_connect(fmanager->priv->monitor, "changed",
2395 G_CALLBACK(xfdesktop_file_icon_manager_file_changed),
2396 fmanager);
2397 }
2398 } else {
2399 for(l = files; l; l = l->next) {
2400 DBG("got a GFileInfo: %s", g_file_info_get_display_name(l->data));
2401
2402 is_hidden = g_file_info_get_attribute_boolean(l->data,
2403 G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN);
2404 if(!is_hidden) {
2405 const gchar *name = g_file_info_get_name(l->data);
2406 GFile *file = g_file_get_child(fmanager->priv->folder, name);
2407
2408 xfdesktop_file_icon_manager_add_regular_icon(fmanager,
2409 file, l->data,
2410 TRUE);
2411
2412 g_object_unref(file);
2413 }
2414
2415 g_object_unref(l->data);
2416 }
2417
2418 g_list_free(files);
2419
2420 g_file_enumerator_next_files_async(fmanager->priv->enumerator,
2421 10, G_PRIORITY_DEFAULT, NULL,
2422 (GAsyncReadyCallback) xfdesktop_file_icon_manager_files_ready,
2423 fmanager);
2424 }
2425}
2426
2427static void
2428xfdesktop_file_icon_manager_load_desktop_folder(XfdesktopFileIconManager *fmanager)
2429{
2430 if(fmanager->priv->deferred_icons) {
2431 g_list_foreach(fmanager->priv->deferred_icons, (GFunc)g_object_unref, NULL);
2432 g_list_free(fmanager->priv->deferred_icons);
2433 fmanager->priv->deferred_icons = NULL;
2434 }
2435
2436 if(fmanager->priv->enumerator) {
2437 g_object_unref(fmanager->priv->enumerator);
2438 fmanager->priv->enumerator = NULL;
2439 }
2440
2441 fmanager->priv->enumerator = g_file_enumerate_children(fmanager->priv->folder,
2442 XFDESKTOP_FILE_INFO_NAMESPACE,
2443 G_FILE_QUERY_INFO_NONE,
2444 NULL, NULL);
2445
2446 if(fmanager->priv->enumerator) {
2447 g_file_enumerator_next_files_async(fmanager->priv->enumerator,
2448 10, G_PRIORITY_DEFAULT, NULL,
2449 (GAsyncReadyCallback) xfdesktop_file_icon_manager_files_ready,
2450 fmanager);
2451
2452 }
2453}
2454
2455static void
2456xfdesktop_file_icon_manager_check_icons_opacity(gpointer key,
2457 gpointer value,
2458 gpointer data)
2459{
2460 XfdesktopRegularFileIcon *icon = XFDESKTOP_REGULAR_FILE_ICON(value);
2461 XfdesktopClipboardManager *cmanager = XFDESKTOP_CLIPBOARD_MANAGER(data);
2462
2463 if(G_UNLIKELY(xfdesktop_clipboard_manager_has_cutted_file(cmanager, XFDESKTOP_FILE_ICON(icon))))
2464 xfdesktop_regular_file_icon_set_pixbuf_opacity(icon, 50);
2465 else
2466 xfdesktop_regular_file_icon_set_pixbuf_opacity(icon, 100);
2467}
2468
2469static void
2470xfdesktop_file_icon_manager_clipboard_changed(XfdesktopClipboardManager *cmanager,
2471 gpointer user_data)
2472{
2473 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
2474
2475 TRACE("entering");
2476
2477 /* slooow? */
2478 g_hash_table_foreach(fmanager->priv->icons,
2479 xfdesktop_file_icon_manager_check_icons_opacity,
2480 cmanager);
2481}
2482
2483
2484static void
2485xfdesktop_file_icon_manager_volume_changed(GVolume *volume,
2486 gpointer user_data)
2487{
2488 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
2489 XfdesktopIcon *icon;
2490 gboolean is_present = xfdesktop_file_utils_volume_is_present(volume);
2491
2492 icon = g_hash_table_lookup(fmanager->priv->removable_icons, volume);
2493
2494 if(is_present && !icon)
2495 xfdesktop_file_icon_manager_add_volume_icon(fmanager, volume);
2496 else if(!is_present && icon) {
2497 xfdesktop_icon_view_remove_item(fmanager->priv->icon_view, icon);
2498 g_hash_table_remove(fmanager->priv->removable_icons, volume);
2499 }
2500}
2501
2502static void
2503xfdesktop_file_icon_manager_add_removable_volume(XfdesktopFileIconManager *fmanager,
2504 GVolume *volume)
2505{
2506 if(!xfdesktop_file_utils_volume_is_removable(volume))
2507 return;
2508
2509 if(xfdesktop_file_utils_volume_is_present(volume))
2510 xfdesktop_file_icon_manager_add_volume_icon(fmanager, volume);
2511
2512 g_signal_connect(G_OBJECT(volume), "changed",
2513 G_CALLBACK(xfdesktop_file_icon_manager_volume_changed),
2514 fmanager);
2515}
2516
2517static void
2518xfdesktop_file_icon_manager_volume_added(GVolumeMonitor *monitor,
2519 GVolume *volume,
2520 gpointer user_data)
2521{
2522 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
2523
2524 xfdesktop_file_icon_manager_add_removable_volume(fmanager, volume);
2525}
2526
2527static void
2528xfdesktop_file_icon_manager_volume_removed(GVolumeMonitor *monitor,
2529 GVolume *volume,
2530 gpointer user_data)
2531{
2532 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
2533 XfdesktopIcon *icon;
2534
2535 icon = g_hash_table_lookup(fmanager->priv->removable_icons, volume);
2536 if(icon) {
2537 xfdesktop_icon_view_remove_item(fmanager->priv->icon_view, icon);
2538 g_hash_table_remove(fmanager->priv->removable_icons, volume);
2539 }
2540}
2541
2542static void
2543xfdesktop_file_icon_manager_load_removable_media(XfdesktopFileIconManager *fmanager)
2544{
2545 GList *volumes, *l;
2546
2547 /* ensure we don't re-enter if we're already set up */
2548 if(fmanager->priv->removable_icons)
2549 return;
2550
2551 if(!fmanager->priv->volume_monitor) {
2552 fmanager->priv->volume_monitor = g_volume_monitor_get();
2553 g_object_add_weak_pointer(G_OBJECT(fmanager->priv->volume_monitor),
2554 (gpointer)&fmanager->priv->volume_monitor);
2555 } else
2556 g_object_ref(G_OBJECT(fmanager->priv->volume_monitor));
2557
2558 fmanager->priv->removable_icons = g_hash_table_new_full(g_direct_hash,
2559 g_direct_equal,
2560 (GDestroyNotify)g_object_unref,
2561 (GDestroyNotify)g_object_unref);
2562
2563 volumes = g_volume_monitor_get_volumes(fmanager->priv->volume_monitor);
2564 for(l = volumes; l; l = l->next) {
2565 xfdesktop_file_icon_manager_add_removable_volume(fmanager, l->data);
2566 g_object_unref(l->data);
2567 }
2568 g_list_free(volumes);
2569
2570 g_signal_connect(G_OBJECT(fmanager->priv->volume_monitor), "volume-added",
2571 G_CALLBACK(xfdesktop_file_icon_manager_volume_added),
2572 fmanager);
2573 g_signal_connect(G_OBJECT(fmanager->priv->volume_monitor), "volume-removed",
2574 G_CALLBACK(xfdesktop_file_icon_manager_volume_removed),
2575 fmanager);
2576}
2577
2578static void
2579xfdesktop_file_icon_manager_ht_remove_removable_media(gpointer key,
2580 gpointer value,
2581 gpointer user_data)
2582{
2583 XfdesktopIcon *icon = XFDESKTOP_ICON(value);
2584 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(user_data);
2585 GVolume *volume;
2586
2587 volume = xfdesktop_volume_icon_peek_volume(XFDESKTOP_VOLUME_ICON(icon));
2588 if(volume) {
2589 g_signal_handlers_disconnect_by_func(volume,
2590 G_CALLBACK(xfdesktop_file_icon_manager_volume_changed),
2591 fmanager);
2592 }
2593
2594 xfdesktop_icon_view_remove_item(fmanager->priv->icon_view, icon);
2595}
2596
2597static void
2598xfdesktop_file_icon_manager_remove_removable_media(XfdesktopFileIconManager *fmanager)
2599{
2600 if(fmanager->priv->removable_icons) {
2601 g_hash_table_foreach(fmanager->priv->removable_icons,
2602 xfdesktop_file_icon_manager_ht_remove_removable_media,
2603 fmanager);
2604 g_hash_table_destroy(fmanager->priv->removable_icons);
2605 fmanager->priv->removable_icons = NULL;
2606 }
2607
2608 if(fmanager->priv->volume_monitor) {
2609 g_signal_handlers_disconnect_by_func(G_OBJECT(fmanager->priv->volume_monitor),
2610 G_CALLBACK(xfdesktop_file_icon_manager_volume_added),
2611 fmanager);
2612 g_signal_handlers_disconnect_by_func(G_OBJECT(fmanager->priv->volume_monitor),
2613 G_CALLBACK(xfdesktop_file_icon_manager_volume_removed),
2614 fmanager);
2615
2616 g_object_unref(fmanager->priv->volume_monitor);
2617 }
2618}
2619
2620
2621/* virtual functions */
2622
2623static gboolean
2624xfdesktop_file_icon_manager_real_init(XfdesktopIconViewManager *manager,
2625 XfdesktopIconView *icon_view)
2626{
2627 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(manager);
2628 GFileInfo *desktop_info;
2629 gint i;
2630#ifdef HAVE_THUNARX
2631 ThunarxProviderFactory *thunarx_pfac;
2632#endif
2633
2634 if(fmanager->priv->inited) {
2635 g_warning("Initializing icon manager when already inited");
2636 return FALSE;
2637 }
2638
2639 fmanager->priv->icon_view = icon_view;
2640
2641 fmanager->priv->desktop = gtk_widget_get_toplevel(GTK_WIDGET(icon_view));
2642 g_signal_connect(G_OBJECT(fmanager->priv->desktop), "populate-root-menu",
2643 G_CALLBACK(xfdesktop_file_icon_manager_populate_context_menu),
2644 fmanager);
2645
2646 fmanager->priv->gscreen = gtk_widget_get_screen(GTK_WIDGET(icon_view));
2647
2648 /* FIXME: remove for 4.4.0 */
2649 __migrate_old_icon_positions(fmanager);
2650
2651 if(!clipboard_manager) {
2652 GdkDisplay *gdpy = gdk_screen_get_display(fmanager->priv->gscreen);
2653 clipboard_manager = xfdesktop_clipboard_manager_get_for_display(gdpy);
2654 g_object_add_weak_pointer(G_OBJECT(clipboard_manager),
2655 (gpointer)&clipboard_manager);
2656 } else
2657 g_object_ref(G_OBJECT(clipboard_manager));
2658
2659 g_signal_connect(G_OBJECT(clipboard_manager), "changed",
2660 G_CALLBACK(xfdesktop_file_icon_manager_clipboard_changed),
2661 fmanager);
2662
2663 xfdesktop_icon_view_set_selection_mode(icon_view, GTK_SELECTION_MULTIPLE);
2664 xfdesktop_icon_view_enable_drag_source(icon_view,
2665 GDK_SHIFT_MASK | GDK_CONTROL_MASK,
2666 drag_targets, n_drag_targets,
2667 GDK_ACTION_LINK | GDK_ACTION_COPY
2668 | GDK_ACTION_MOVE);
2669 xfdesktop_icon_view_enable_drag_dest(icon_view, drop_targets,
2670 n_drop_targets, GDK_ACTION_LINK
2671 | GDK_ACTION_COPY | GDK_ACTION_MOVE);
2672
2673 g_signal_connect(G_OBJECT(xfdesktop_icon_view_get_window_widget(icon_view)),
2674 "key-press-event",
2675 G_CALLBACK(xfdesktop_file_icon_manager_key_press),
2676 fmanager);
2677
2678 fmanager->priv->icons = g_hash_table_new_full((GHashFunc)g_file_hash,
2679 (GEqualFunc)g_file_equal,
2680 (GDestroyNotify)g_object_unref,
2681 (GDestroyNotify)g_object_unref);
2682
2683 fmanager->priv->special_icons = g_hash_table_new_full(g_direct_hash,
2684 g_direct_equal,
2685 NULL,
2686 (GDestroyNotify)g_object_unref);
2687
2688 if(!xfdesktop_file_utils_dbus_init())
2689 g_warning("Unable to initialise D-Bus. Some xfdesktop features may be unavailable.");
2690
2691 /* do this in the reverse order stuff should be displayed */
2692 xfdesktop_file_icon_manager_load_desktop_folder(fmanager);
2693 if(fmanager->priv->show_removable_media)
2694 xfdesktop_file_icon_manager_load_removable_media(fmanager);
2695 for(i = XFDESKTOP_SPECIAL_FILE_ICON_TRASH; i >= 0; --i) {
2696 if(fmanager->priv->show_special[i])
2697 xfdesktop_file_icon_manager_add_special_file_icon(fmanager, i);
2698 }
2699
2700#ifdef HAVE_THUNARX
2701 thunarx_pfac = thunarx_provider_factory_get_default();
2702
2703 fmanager->priv->thunarx_menu_providers =
2704 thunarx_provider_factory_list_providers(thunarx_pfac,
2705 THUNARX_TYPE_MENU_PROVIDER);
2706 fmanager->priv->thunarx_properties_providers =
2707 thunarx_provider_factory_list_providers(thunarx_pfac,
2708 THUNARX_TYPE_PROPERTY_PAGE_PROVIDER);
2709
2710 g_object_unref(G_OBJECT(thunarx_pfac));
2711#endif
2712
2713 desktop_info = g_file_query_info(fmanager->priv->folder,
2714 XFDESKTOP_FILE_INFO_NAMESPACE,
2715 G_FILE_QUERY_INFO_NONE,
2716 NULL, NULL);
2717
2718 fmanager->priv->desktop_icon = XFDESKTOP_FILE_ICON(xfdesktop_regular_file_icon_new(fmanager->priv->folder,
2719 desktop_info,
2720 fmanager->priv->gscreen));
2721
2722 g_object_unref(desktop_info);
2723
2724 fmanager->priv->inited = TRUE;
2725
2726 return TRUE;
2727}
2728
2729static void
2730xfdesktop_file_icon_manager_fini(XfdesktopIconViewManager *manager)
2731{
2732 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(manager);
2733 gint i;
2734
2735 if(!fmanager->priv->inited) {
2736 g_warning("Trying to de-init icon manager when it was never inited");
2737 return;
2738 }
2739
2740 fmanager->priv->inited = FALSE;
2741
2742 if(fmanager->priv->enumerator) {
2743 g_object_unref(fmanager->priv->enumerator);
2744 fmanager->priv->enumerator = NULL;
2745 }
2746
2747 g_signal_handlers_disconnect_by_func(G_OBJECT(fmanager->priv->desktop),
2748 G_CALLBACK(xfdesktop_file_icon_manager_populate_context_menu),
2749 fmanager);
2750
2751 if(fmanager->priv->save_icons_id) {
2752 g_source_remove(fmanager->priv->save_icons_id);
2753 fmanager->priv->save_icons_id = 0;
2754 xfdesktop_file_icon_manager_save_icons(fmanager);
2755 }
2756
2757 g_signal_handlers_disconnect_by_func(G_OBJECT(clipboard_manager),
2758 G_CALLBACK(xfdesktop_file_icon_manager_clipboard_changed),
2759 fmanager);
2760
2761 g_object_unref(G_OBJECT(clipboard_manager));
2762
2763 if(fmanager->priv->show_removable_media)
2764 xfdesktop_file_icon_manager_remove_removable_media(fmanager);
2765
2766 for(i = 0; i <= XFDESKTOP_SPECIAL_FILE_ICON_TRASH; ++i) {
2767 XfdesktopIcon *icon = g_hash_table_lookup(fmanager->priv->special_icons,
2768 GINT_TO_POINTER(i));
2769 if(icon) {
2770 xfdesktop_icon_view_remove_item(fmanager->priv->icon_view, icon);
2771 g_hash_table_remove(fmanager->priv->special_icons,
2772 GINT_TO_POINTER(i));
2773 }
2774 }
2775
2776 if(fmanager->priv->icons) {
2777 g_hash_table_foreach_remove(fmanager->priv->icons,
2778 (GHRFunc)xfdesktop_remove_icons_ht,
2779 fmanager->priv->icon_view);
2780 }
2781
2782 if(fmanager->priv->deferred_icons) {
2783 g_list_foreach(fmanager->priv->deferred_icons, (GFunc)g_object_unref, NULL);
2784 g_list_free(fmanager->priv->deferred_icons);
2785 fmanager->priv->deferred_icons = NULL;
2786 }
2787
2788 /* disconnect from the file monitor and release it */
2789 g_signal_handlers_disconnect_by_func(fmanager->priv->monitor,
2790 G_CALLBACK(xfdesktop_file_icon_manager_file_changed),
2791 fmanager);
2792 g_object_unref(fmanager->priv->monitor);
2793 fmanager->priv->monitor = NULL;
2794
2795 g_object_unref(G_OBJECT(fmanager->priv->desktop_icon));
2796 fmanager->priv->desktop_icon = NULL;
2797
2798#ifdef HAVE_THUNARX
2799 g_list_foreach(fmanager->priv->thunarx_menu_providers,
2800 (GFunc)g_object_unref, NULL);
2801 g_list_free(fmanager->priv->thunarx_menu_providers);
2802
2803 g_list_foreach(fmanager->priv->thunarx_properties_providers,
2804 (GFunc)g_object_unref, NULL);
2805 g_list_free(fmanager->priv->thunarx_properties_providers);
2806#endif
2807
2808 g_hash_table_destroy(fmanager->priv->special_icons);
2809 fmanager->priv->special_icons = NULL;
2810
2811 g_hash_table_destroy(fmanager->priv->icons);
2812 fmanager->priv->icons = NULL;
2813
2814 xfdesktop_file_utils_dbus_cleanup();
2815
2816 g_signal_handlers_disconnect_by_func(G_OBJECT(xfdesktop_icon_view_get_window_widget(fmanager->priv->icon_view)),
2817 G_CALLBACK(xfdesktop_file_icon_manager_key_press),
2818 fmanager);
2819
2820 xfdesktop_icon_view_unset_drag_source(fmanager->priv->icon_view);
2821 xfdesktop_icon_view_unset_drag_dest(fmanager->priv->icon_view);
2822}
2823
2824static gboolean
2825xfdesktop_file_icon_manager_drag_drop(XfdesktopIconViewManager *manager,
2826 XfdesktopIcon *drop_icon,
2827 GdkDragContext *context,
2828 guint16 row,
2829 guint16 col,
2830 guint time_)
2831{
2832 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(manager);
2833 GtkWidget *widget = GTK_WIDGET(fmanager->priv->icon_view);
2834 GdkAtom target;
2835
2836 TRACE("entering");
2837
2838 target = gtk_drag_dest_find_target(widget, context,
2839 fmanager->priv->drop_targets);
2840 if(target == GDK_NONE)
2841 return FALSE;
2842 else if(target == gdk_atom_intern("XdndDirectSave0", FALSE)) {
2843 /* X direct save protocol implementation copied more or less from
2844 * Thunar, Copyright (c) Benedikt Meurer */
2845 gint prop_len;
2846 guchar *prop_text = NULL;
2847 GFile *source_file, *file;
2848 gchar *uri = NULL;
2849
2850 if(drop_icon) {
2851 GFileInfo *info = xfdesktop_file_icon_peek_file_info(XFDESKTOP_FILE_ICON(drop_icon));
2852 if(!info)
2853 return FALSE;
2854
2855 if(g_file_info_get_file_type(info) != G_FILE_TYPE_DIRECTORY)
2856 return FALSE;
2857
2858 source_file = xfdesktop_file_icon_peek_file(XFDESKTOP_FILE_ICON(drop_icon));
2859
2860 } else
2861 source_file = fmanager->priv->folder;
2862
2863 if(gdk_property_get(context->source_window,
2864 gdk_atom_intern("XdndDirectSave0", FALSE),
2865 gdk_atom_intern("text/plain", FALSE),
2866 0, 1024, FALSE, NULL, NULL, &prop_len,
2867 &prop_text) && prop_text)
2868 {
2869 prop_text = g_realloc(prop_text, prop_len + 1);
2870 prop_text[prop_len] = 0;
2871
2872 file = g_file_resolve_relative_path(source_file, (const gchar *)prop_text);
2873 uri = g_file_get_uri(file);
2874 g_object_unref(file);
2875
2876 gdk_property_change(context->source_window,
2877 gdk_atom_intern("XdndDirectSave0", FALSE),
2878 gdk_atom_intern("text/plain", FALSE), 8,
2879 GDK_PROP_MODE_REPLACE, (const guchar *)uri,
2880 strlen(uri));
2881
2882 g_free(prop_text);
2883 g_free(uri);
2884 }
2885
2886 if(!uri)
2887 return FALSE;
2888 } else if(target == gdk_atom_intern("_NETSCAPE_URL", FALSE)) {
2889 if(drop_icon) {
2890 /* don't allow a drop on an icon that isn't a folder (i.e., not
2891 * on an icon that's an executable */
2892 GFileInfo *info = xfdesktop_file_icon_peek_file_info(XFDESKTOP_FILE_ICON(drop_icon));
2893 if(!info || g_file_info_get_file_type(info) != G_FILE_TYPE_DIRECTORY)
2894 return FALSE;
2895 }
2896 }
2897
2898 TRACE("target good");
2899
2900 gtk_drag_get_data(widget, context, target, time_);
2901
2902 return TRUE;
2903}
2904
2905static void xfdesktop_dnd_item(GtkWidget *item, GdkDragAction *action)
2906{
2907 *action = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(item), "action"));
2908}
2909
2910static void xfdesktop_dnd_item_cancel(GtkWidget *item, GdkDragAction *action)
2911{
2912 *action = 0;
2913}
2914
2915/**
2916 * xfdesktop_dnd_menu:
2917 * @manager : the #XfdesktopIconViewManager instance
2918 * @drop_icon : the #XfdesktopIcon to which is being dropped.
2919 * @context : the #GdkDragContext of the icons being dropped.
2920 * @row : the row on the desktop to drop to.
2921 * @col : the col on the desktop to drop to.
2922 * @ time_ : the starting time of the drag event.
2923 * Pops up a menu that asks the user to choose one of the
2924 * actions or to cancel the drop. Sets context->action to
2925 * the new action the user selected or 0 on cancel.
2926 * Portions of this code was copied from thunar-dnd.c
2927 * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org>
2928 * Copyright (c) 2009-2011 Jannis Pohlmann <jannis@xfce.org>
2929 **/
2930static void xfdesktop_dnd_menu (XfdesktopIconViewManager *manager,
2931 XfdesktopIcon *drop_icon,
2932 GdkDragContext *context,
2933 guint16 row,
2934 guint16 col,
2935 guint time_)
2936{
2937 static GdkDragAction actions[] = { GDK_ACTION_COPY, GDK_ACTION_MOVE, GDK_ACTION_LINK };
2938 static const gchar *action_names[] = { N_ ("Copy _Here") , N_ ("_Move Here") , N_ ("_Link Here") };
2939 static const gchar *action_icons[] = { "stock_folder-copy", "stock_folder-move", NULL };
2940 GtkWidget *menu;
2941 GtkWidget *item;
2942 GtkWidget *image;
2943 guint menu_item, signal_id;
2944 GMainLoop *loop;
2945 gint response;
2946 menu = gtk_menu_new();
2947
2948 /* This adds the Copy, Move, & Link options */
2949 for(menu_item = 0; menu_item < G_N_ELEMENTS(actions); menu_item++) {
2950 item = gtk_image_menu_item_new_with_mnemonic(_(action_names[menu_item]));
2951 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2952 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(xfdesktop_dnd_item), &response);
2953 g_object_set_data(G_OBJECT(item), "action", GUINT_TO_POINTER(actions[menu_item]));
2954 /* add image to the menu item */
2955 if(G_LIKELY(action_icons[menu_item] != NULL)) {
2956 image = gtk_image_new_from_icon_name(action_icons[menu_item], GTK_ICON_SIZE_MENU);
2957 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
2958 gtk_widget_show(image);
2959 }
2960
2961 gtk_widget_show(item);
2962 }
2963
2964 /* Add a seperator */
2965 item = gtk_separator_menu_item_new();
2966 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2967 gtk_widget_show(item);
2968
2969 /* Cancel option */
2970 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CANCEL, NULL);
2971 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2972 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(xfdesktop_dnd_item_cancel), &response);
2973 gtk_widget_show(item);
2974
2975 gtk_widget_show(menu);
2976 g_object_ref_sink(G_OBJECT(menu));
2977
2978 /* Loop until we get a user response */
2979 loop = g_main_loop_new(NULL, FALSE);
2980 signal_id = g_signal_connect_swapped(G_OBJECT(menu), "deactivate", G_CALLBACK(g_main_loop_quit), loop);
2981 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, time_);
2982 g_main_loop_run(loop);
2983 g_signal_handler_disconnect(G_OBJECT(menu), signal_id);
2984 g_main_loop_unref(loop);
2985
2986 context->action = response;
2987
2988 g_object_unref(G_OBJECT(menu));
2989}
2990
2991static void
2992xfdesktop_file_icon_manager_drag_data_received(XfdesktopIconViewManager *manager,
2993 XfdesktopIcon *drop_icon,
2994 GdkDragContext *context,
2995 guint16 row,
2996 guint16 col,
2997 GtkSelectionData *data,
2998 guint info,
2999 guint time_)
3000{
3001 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(manager);
3002 XfdesktopFileIcon *file_icon = NULL;
3003 GFileInfo *tinfo = NULL;
3004 GFile *tfile = NULL;
3005 gboolean copy_only = TRUE, drop_ok = FALSE;
3006 GList *file_list;
3007 gboolean user_selected_action = FALSE;
3008
3009 TRACE("entering");
3010
3011 if(context->action == GDK_ACTION_ASK) {
3012 xfdesktop_dnd_menu(manager, drop_icon, context, row, col, time_);
3013
3014 if(context->action == 0) {
3015 gtk_drag_finish(context, FALSE, FALSE, time_);
3016 return;
3017 }
3018 /* The user picked whether to move or copy the files */
3019 user_selected_action = TRUE;
3020 }
3021
3022 if(info == TARGET_XDND_DIRECT_SAVE0) {
3023 /* we don't suppose XdndDirectSave stage 3, result F, i.e., the app
3024 * has to save the data itself given the filename we provided in
3025 * stage 1 */
3026 if(8 == data->format && 1 == data->length && 'F' == data->data[0]) {
3027 gdk_property_change(context->source_window,
3028 gdk_atom_intern("XdndDirectSave0", FALSE),
3029 gdk_atom_intern("text/plain", FALSE), 8,
3030 GDK_PROP_MODE_REPLACE, (const guchar *)"", 0);
3031 } else if(8 == data->format && data->length == 1
3032 && 'S' == data->data[0])
3033 {
3034 /* FIXME: do we really need to do anything here? xfdesktop should
3035 * detect when something changes on its own */
3036 }
3037
3038 drop_ok = TRUE;
3039 } else if(info == TARGET_NETSCAPE_URL) {
3040 /* data is "URL\nTITLE" */
3041 GFile *source_file = NULL;
3042 gchar *exo_desktop_item_edit = g_find_program_in_path("exo-desktop-item-edit");
3043
3044 if(drop_icon) {
3045 GFileInfo *finfo = xfdesktop_file_icon_peek_file_info(XFDESKTOP_FILE_ICON(drop_icon));
3046 if(g_file_info_get_file_type(finfo) == G_FILE_TYPE_DIRECTORY)
3047 source_file = xfdesktop_file_icon_peek_file(XFDESKTOP_FILE_ICON(drop_icon));
3048 } else
3049 source_file = fmanager->priv->folder;
3050
3051 if(source_file && exo_desktop_item_edit) {
3052 gchar **parts = g_strsplit((const gchar *)data->data, "\n", -1);
3053
3054 if(2 == g_strv_length(parts)) {
3055 gchar *cwd = g_file_get_uri(source_file);
3056 gchar *myargv[16];
3057 gint i = 0;
3058
3059 /* use the argv form so we don't have to worry about quoting
3060 * the link title */
3061 myargv[i++] = exo_desktop_item_edit;
3062 myargv[i++] = "--type=Link";
3063 myargv[i++] = "--url";
3064 myargv[i++] = parts[0];
3065 myargv[i++] = "--name";
3066 myargv[i++] = parts[1];
3067 myargv[i++] = "--create-new";
3068 myargv[i++] = cwd;
3069 myargv[i++] = NULL;
3070
3071 if(xfce_spawn_on_screen(fmanager->priv->gscreen, NULL, myargv,
3072 NULL, G_SPAWN_SEARCH_PATH, TRUE,
3073 gtk_get_current_event_time(),
3074 NULL, NULL))
3075 {
3076 drop_ok = TRUE;
3077 }
3078
3079 g_free(cwd);
3080 }
3081
3082 g_strfreev(parts);
3083 }
3084
3085 g_free(exo_desktop_item_edit);
3086 } else if(info == TARGET_TEXT_URI_LIST) {
3087 if(drop_icon) {
3088 file_icon = XFDESKTOP_FILE_ICON(drop_icon);
3089 tfile = xfdesktop_file_icon_peek_file(file_icon);
3090 tinfo = xfdesktop_file_icon_peek_file_info(file_icon);
3091 }
3092
3093 copy_only = (context->action == GDK_ACTION_COPY);
3094
3095 if(tfile && g_file_has_uri_scheme(tfile, "trash") && copy_only) {
3096 gtk_drag_finish(context, FALSE, FALSE, time_);
3097 return;
3098 }
3099
3100 file_list = xfdesktop_file_utils_file_list_from_string((const gchar *)data->data);
3101 if(file_list) {
3102 GtkWidget *toplevel = gtk_widget_get_toplevel(GTK_WIDGET(fmanager->priv->icon_view));
3103
3104 if(tinfo && xfdesktop_file_utils_file_is_executable(tinfo)) {
3105 drop_ok = xfdesktop_file_utils_execute(fmanager->priv->folder,
3106 tfile, file_list,
3107 fmanager->priv->gscreen,
3108 GTK_WINDOW(toplevel));
3109 } else if(tfile && g_file_has_uri_scheme(tfile, "trash")) {
3110 /* move files to the trash */
3111 xfdesktop_file_utils_trash_files(file_list,
3112 fmanager->priv->gscreen,
3113 GTK_WINDOW(toplevel));
3114 } else {
3115 GFile *base_dest_file = NULL;
3116 GList *l, *dest_file_list = NULL;
3117 gboolean dest_is_volume = (drop_icon
3118 && XFDESKTOP_IS_VOLUME_ICON(drop_icon));
3119
3120 /* if it's a volume, but we don't have |tinfo|, this just isn't
3121 * going to work */
3122 if(!tinfo && dest_is_volume) {
3123 xfdesktop_file_utils_file_list_free(file_list);
3124 gtk_drag_finish(context, FALSE, FALSE, time_);
3125 return;
3126 }
3127
3128 if(tinfo && g_file_info_get_file_type(tinfo) == G_FILE_TYPE_DIRECTORY) {
3129 base_dest_file = g_object_ref(tfile);
3130 } else {
3131 base_dest_file = g_object_ref(fmanager->priv->folder);
3132 }
3133
3134 /* If the user didn't pick whether to copy or move via
3135 * a GDK_ACTION_ASK then determine if we should move/copy
3136 * by checking if the files are on the same filesystem
3137 * and are writable by the user.
3138 */
3139 if(user_selected_action == FALSE) {
3140 GFileInfo *src_info, *dest_info;
3141 const gchar *src_name, *dest_name;
3142
3143 dest_info = g_file_query_info(base_dest_file,
3144 XFDESKTOP_FILE_INFO_NAMESPACE,
3145 G_FILE_QUERY_INFO_NONE,
3146 NULL,
3147 NULL);
3148 src_info = g_file_query_info(file_list->data,
3149 XFDESKTOP_FILE_INFO_NAMESPACE,
3150 G_FILE_QUERY_INFO_NONE,
3151 NULL,
3152 NULL);
3153
3154 if(dest_info != NULL && src_info != NULL) {
3155 dest_name = g_file_info_get_attribute_string(dest_info,
3156 G_FILE_ATTRIBUTE_ID_FILESYSTEM);
3157 src_name = g_file_info_get_attribute_string(src_info,
3158 G_FILE_ATTRIBUTE_ID_FILESYSTEM);
3159
3160 if((g_strcmp0(src_name, dest_name) == 0)
3161 && g_file_info_get_attribute_boolean(src_info,
3162 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))
3163 {
3164 copy_only = FALSE;
3165 context->action = GDK_ACTION_MOVE;
3166 }
3167 }
3168
3169 if(dest_info != NULL)
3170 g_object_unref(dest_info);
3171 if(src_info != NULL)
3172 g_object_unref(src_info);
3173 }
3174
3175 for (l = file_list; l; l = l->next) {
3176 gchar *dest_basename = g_file_get_basename(l->data);
3177
3178 if(dest_basename && *dest_basename != '\0') {
3179 /* If we copy a file, we need to use the new absolute filename
3180 * as the destination. If we move or link, we need to use the destination
3181 * directory. */
3182 if(copy_only) {
3183 GFile *dest_file = g_file_get_child(base_dest_file, dest_basename);
3184 dest_file_list = g_list_prepend(dest_file_list, dest_file);
3185 } else {
3186 dest_file_list = g_list_prepend(dest_file_list, base_dest_file);
3187 }
3188 }
3189
3190 g_free(dest_basename);
3191 }
3192
3193 g_object_unref(base_dest_file);
3194
3195 if(dest_file_list) {
3196 dest_file_list = g_list_reverse(dest_file_list);
3197
3198 drop_ok = xfdesktop_file_utils_transfer_files(context->action,
3199 file_list,
3200 dest_file_list,
3201 fmanager->priv->gscreen);
3202 }
3203
3204 if(copy_only) {
3205 xfdesktop_file_utils_file_list_free(dest_file_list);
3206 } else {
3207 g_list_free(dest_file_list);
3208 }
3209 }
3210 }
3211 }
3212
3213 DBG("finishing drop on desktop from external source: drop_ok=%s, copy_only=%s",
3214 drop_ok?"TRUE":"FALSE", copy_only?"TRUE":"FALSE");
3215
3216 gtk_drag_finish(context, drop_ok, !copy_only, time_);
3217}
3218
3219static void
3220xfdesktop_file_icon_manager_drag_data_get(XfdesktopIconViewManager *manager,
3221 GList *drag_icons,
3222 GdkDragContext *context,
3223 GtkSelectionData *data,
3224 guint info,
3225 guint time_)
3226{
3227 GList *file_list;
3228 gchar *str;
3229
3230 TRACE("entering");
3231
3232 g_return_if_fail(drag_icons);
3233 g_return_if_fail(info == TARGET_TEXT_URI_LIST);
3234
3235 file_list = xfdesktop_file_utils_file_icon_list_to_file_list(drag_icons);
3236 str = xfdesktop_file_utils_file_list_to_string(file_list);
3237
3238 gtk_selection_data_set(data, data->target, 8, (guchar *)str, strlen(str));
3239
3240 g_free(str);
3241 xfdesktop_file_utils_file_list_free(file_list);
3242}
3243
3244
3245/* public api */
3246
3247XfdesktopIconViewManager *
3248xfdesktop_file_icon_manager_new(GFile *folder,
3249 XfconfChannel *channel)
3250{
3251 XfdesktopFileIconManager *fmanager;
3252
3253 g_return_val_if_fail(folder && channel, NULL);
3254
3255 fmanager = g_object_new(XFDESKTOP_TYPE_FILE_ICON_MANAGER,
3256 "folder", folder,
3257 NULL);
3258 fmanager->priv->channel = g_object_ref(G_OBJECT(channel));
3259
3260 xfconf_g_property_bind(channel, SETTING_SHOW_FILESYSTEM, G_TYPE_BOOLEAN,
3261 G_OBJECT(fmanager), "show-filesystem");
3262 xfconf_g_property_bind(channel, SETTING_SHOW_HOME, G_TYPE_BOOLEAN,
3263 G_OBJECT(fmanager), "show-home");
3264 xfconf_g_property_bind(channel, SETTING_SHOW_TRASH, G_TYPE_BOOLEAN,
3265 G_OBJECT(fmanager), "show-trash");
3266 xfconf_g_property_bind(channel, SETTING_SHOW_REMOVABLE, G_TYPE_BOOLEAN,
3267 G_OBJECT(fmanager), "show-removable");
3268 xfconf_g_property_bind(channel, SETTING_SHOW_THUMBNAILS, G_TYPE_BOOLEAN,
3269 G_OBJECT(fmanager), "show-thumbnails");
3270
3271 return XFDESKTOP_ICON_VIEW_MANAGER(fmanager);
3272}
3273
3274void
3275xfdesktop_file_icon_manager_set_show_removable_media(XfdesktopFileIconManager *manager,
3276 gboolean show_removable_media)
3277{
3278 g_return_if_fail(XFDESKTOP_IS_FILE_ICON_MANAGER(manager));
3279
3280 if(show_removable_media == manager->priv->show_removable_media)
3281 return;
3282
3283 manager->priv->show_removable_media = show_removable_media;
3284
3285 if(!manager->priv->inited)
3286 return;
3287
3288 if(show_removable_media)
3289 xfdesktop_file_icon_manager_load_removable_media(manager);
3290 else
3291 xfdesktop_file_icon_manager_remove_removable_media(manager);
3292}
3293
3294gboolean
3295xfdesktop_file_icon_manager_get_show_removable_media(XfdesktopFileIconManager *manager)
3296{
3297 g_return_val_if_fail(XFDESKTOP_IS_FILE_ICON_MANAGER(manager), FALSE);
3298 return manager->priv->show_removable_media;
3299}
3300
3301static void
3302xfdesktop_file_icon_manager_requeue_thumbnails(gpointer key,
3303 gpointer value,
3304 gpointer data)
3305{
3306 GFile *file = key;
3307 XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(data);
3308
3309 xfdesktop_thumbnailer_queue_thumbnail(fmanager->priv->thumbnailer,
3310 g_file_get_path(file));
3311}
3312
3313static void
3314xfdesktop_file_icon_manager_remove_thumbnails(gpointer key,
3315 gpointer value,
3316 gpointer data)
3317{
3318 XfdesktopRegularFileIcon *icon = XFDESKTOP_REGULAR_FILE_ICON(value);
3319
3320 xfdesktop_icon_delete_thumbnail(XFDESKTOP_ICON(icon));
3321}
3322
3323void
3324xfdesktop_file_icon_manager_set_show_thumbnails(XfdesktopFileIconManager *manager,
3325 gboolean show_thumbnails)
3326{
3327 g_return_if_fail(XFDESKTOP_IS_FILE_ICON_MANAGER(manager));
3328
3329 if(show_thumbnails == manager->priv->show_thumbnails)
3330 return;
3331
3332 manager->priv->show_thumbnails = show_thumbnails;
3333
3334 if(!manager->priv->inited)
3335 return;
3336
3337 if(show_thumbnails) {
3338 /* We have to request to create the thumbnails everytime. */
3339 g_hash_table_foreach(manager->priv->icons,
3340 xfdesktop_file_icon_manager_requeue_thumbnails,
3341 manager);
3342 } else {
3343 /* We have to remove the thumbnails because the regular file
3344 * icons can't easily check if thumbnails are allowed.
3345 */
3346 g_hash_table_foreach(manager->priv->icons,
3347 xfdesktop_file_icon_manager_remove_thumbnails,
3348 manager);
3349 }
3350}
3351
3352gboolean
3353xfdesktop_file_icon_manager_get_show_thumbnails(XfdesktopFileIconManager *manager)
3354{
3355 g_return_val_if_fail(XFDESKTOP_IS_FILE_ICON_MANAGER(manager), FALSE);
3356 return manager->priv->show_thumbnails;
3357}
3358
3359void
3360xfdesktop_file_icon_manager_set_show_special_file(XfdesktopFileIconManager *manager,
3361 XfdesktopSpecialFileIconType type,
3362 gboolean show_special_file)
3363{
3364 g_return_if_fail(XFDESKTOP_IS_FILE_ICON_MANAGER(manager));
3365 g_return_if_fail((int)type >= 0 && type <= XFDESKTOP_SPECIAL_FILE_ICON_TRASH);
3366
3367 if(manager->priv->show_special[type] == show_special_file)
3368 return;
3369
3370 manager->priv->show_special[type] = show_special_file;
3371
3372 if(!manager->priv->inited)
3373 return;
3374
3375 if(show_special_file) {
3376 g_return_if_fail(!g_hash_table_lookup(manager->priv->special_icons,
3377 GINT_TO_POINTER(type)));
3378 xfdesktop_file_icon_manager_add_special_file_icon(manager, type);
3379 } else {
3380 XfdesktopIcon *icon = g_hash_table_lookup(manager->priv->special_icons,
3381 GINT_TO_POINTER(type));
3382 if(icon) {
3383 xfdesktop_icon_view_remove_item(manager->priv->icon_view, icon);
3384 g_hash_table_remove(manager->priv->special_icons,
3385 GINT_TO_POINTER(type));
3386 }
3387 }
3388}
3389
3390gboolean
3391xfdesktop_file_icon_manager_get_show_special_file(XfdesktopFileIconManager *manager,
3392 XfdesktopSpecialFileIconType type)
3393{
3394 g_return_val_if_fail(XFDESKTOP_IS_FILE_ICON_MANAGER(manager), FALSE);
3395 g_return_val_if_fail((int)type >= 0 && type <= XFDESKTOP_SPECIAL_FILE_ICON_TRASH,
3396 FALSE);
3397
3398 return manager->priv->show_special[type];
3399}
3400
3401static void
3402xfdesktop_file_icon_manager_update_image(GtkWidget *widget,
3403 gchar *srcfile,
3404 gchar *thumbfile,
3405 XfdesktopFileIconManager *manager)
3406{
3407 GFile *file;
3408 XfdesktopIcon *icon;
3409
3410 g_return_if_fail(srcfile && thumbfile);
3411 g_return_if_fail(XFDESKTOP_FILE_ICON_MANAGER(manager));
3412
3413 file = g_file_new_for_path(srcfile);
3414
3415 icon = g_hash_table_lookup(manager->priv->icons, file);
3416 if(icon)
3417 {
3418 g_object_unref(file);
3419 file = g_file_new_for_path(thumbfile);
3420 xfdesktop_icon_set_thumbnail_file(icon, file);
3421 }
3422}
34230
=== removed directory '.pc/xubuntu_improve-nautilus-interactions.patch'
=== removed directory '.pc/xubuntu_improve-nautilus-interactions.patch/src'
=== removed file '.pc/xubuntu_improve-nautilus-interactions.patch/src/xfce-desktop.c'
--- .pc/xubuntu_improve-nautilus-interactions.patch/src/xfce-desktop.c 2013-03-03 11:58:50 +0000
+++ .pc/xubuntu_improve-nautilus-interactions.patch/src/xfce-desktop.c 1970-01-01 00:00:00 +0000
@@ -1,1518 +0,0 @@
1/*
2 * xfdesktop - xfce4's desktop manager
3 *
4 * Copyright (c) 2004-2007 Brian Tarricone, <bjt23@cornell.edu>
5 *
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.
10 *
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 Library General Public License for more details.
15 *
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 * Random portions taken from or inspired by the original xfdesktop for xfce4:
21 * Copyright (C) 2002-2003 Jasper Huijsmans (huysmans@users.sourceforge.net)
22 * Copyright (C) 2003 Benedikt Meurer <benedikt.meurer@unix-ag.uni-siegen.de>
23 */
24
25#ifdef HAVE_CONFIG_H
26#include <config.h>
27#endif
28
29#include <stdio.h>
30
31#ifdef HAVE_STDLIB_H
32#include <stdlib.h>
33#endif
34
35#ifdef HAVE_STRING_H
36#include <string.h>
37#endif
38
39#ifdef HAVE_SYS_TYPES_H
40#include <sys/types.h>
41#endif
42#ifdef HAVE_SYS_STAT_H
43#include <sys/stat.h>
44#endif
45#ifdef HAVE_UNISTD_H
46#include <unistd.h>
47#endif
48
49#ifdef HAVE_FCNTL_H
50#include <fcntl.h>
51#endif
52
53#include <ctype.h>
54#include <errno.h>
55
56#ifdef HAVE_TIME_H
57#include <time.h>
58#endif
59
60#include <X11/Xlib.h>
61#include <X11/Xatom.h>
62
63#include <glib.h>
64#include <gdk/gdkx.h>
65#include <gtk/gtk.h>
66
67#ifdef ENABLE_DESKTOP_ICONS
68#include "xfdesktop-icon-view.h"
69#include "xfdesktop-window-icon-manager.h"
70# ifdef ENABLE_FILE_ICONS
71# include "xfdesktop-file-icon-manager.h"
72# include "xfdesktop-special-file-icon.h"
73# endif
74#endif
75
76#include <libxfce4util/libxfce4util.h>
77#include <libxfce4ui/libxfce4ui.h>
78
79#include <xfconf/xfconf.h>
80
81#include "xfdesktop-common.h"
82#include "xfce-desktop.h"
83#include "xfce-desktop-enum-types.h"
84
85/* disable setting the x background for bug 7442 */
86//#define DISABLE_FOR_BUG7442
87
88struct _XfceDesktopPriv
89{
90 GdkScreen *gscreen;
91 gboolean updates_frozen;
92
93 XfconfChannel *channel;
94 gchar *property_prefix;
95
96 GdkPixmap *bg_pixmap;
97
98 guint nbackdrops;
99 XfceBackdrop **backdrops;
100
101 gboolean xinerama_stretch;
102
103 SessionLogoutFunc session_logout_func;
104
105#ifdef ENABLE_DESKTOP_ICONS
106 XfceDesktopIconStyle icons_style;
107 gboolean icons_font_size_set;
108 guint icons_font_size;
109 guint icons_size;
110 GtkWidget *icon_view;
111 gdouble system_font_size;
112#endif
113};
114
115enum
116{
117 SIG_POPULATE_ROOT_MENU = 0,
118 SIG_POPULATE_SECONDARY_ROOT_MENU,
119 N_SIGNALS
120};
121
122enum
123{
124 PROP_0 = 0,
125 PROP_XINERAMA_STRETCH,
126#ifdef ENABLE_DESKTOP_ICONS
127 PROP_ICON_STYLE,
128 PROP_ICON_SIZE,
129 PROP_ICON_FONT_SIZE,
130 PROP_ICON_FONT_SIZE_SET,
131#endif
132};
133
134
135static void xfce_desktop_finalize(GObject *object);
136static void xfce_desktop_set_property(GObject *object,
137 guint property_id,
138 const GValue *value,
139 GParamSpec *pspec);
140static void xfce_desktop_get_property(GObject *object,
141 guint property_id,
142 GValue *value,
143 GParamSpec *pspec);
144
145static void xfce_desktop_realize(GtkWidget *widget);
146static void xfce_desktop_unrealize(GtkWidget *widget);
147static gboolean xfce_desktop_button_press_event(GtkWidget *widget,
148 GdkEventButton *evt);
149static gboolean xfce_desktop_popup_menu(GtkWidget *widget);
150
151static gboolean xfce_desktop_expose(GtkWidget *w,
152 GdkEventExpose *evt);
153static gboolean xfce_desktop_delete_event(GtkWidget *w,
154 GdkEventAny *evt);
155static void xfce_desktop_style_set(GtkWidget *w,
156 GtkStyle *old_style);
157
158static void xfce_desktop_connect_backdrop_settings(XfceDesktop *desktop,
159 XfceBackdrop *backdrop,
160 guint monitor);
161
162static guint signals[N_SIGNALS] = { 0, };
163
164/* private functions */
165
166#ifdef ENABLE_DESKTOP_ICONS
167static gdouble
168xfce_desktop_ensure_system_font_size(XfceDesktop *desktop)
169{
170 GdkScreen *gscreen;
171 GtkSettings *settings;
172 gchar *font_name = NULL;
173 PangoFontDescription *pfd;
174
175 gscreen = gtk_widget_get_screen(GTK_WIDGET(desktop));
176 /* FIXME: needed? */
177 if(!gscreen)
178 gscreen = gdk_display_get_default_screen(gdk_display_get_default());
179
180 settings = gtk_settings_get_for_screen(gscreen);
181 g_object_get(G_OBJECT(settings), "gtk-font-name", &font_name, NULL);
182
183 pfd = pango_font_description_from_string(font_name);
184 desktop->priv->system_font_size = pango_font_description_get_size(pfd);
185 /* FIXME: this seems backwards from the documentation */
186 if(!pango_font_description_get_size_is_absolute(pfd)) {
187 DBG("dividing by PANGO_SCALE");
188 desktop->priv->system_font_size /= PANGO_SCALE;
189 }
190 DBG("system font size is %.05f", desktop->priv->system_font_size);
191
192 g_free(font_name);
193 pango_font_description_free(pfd);
194
195 return desktop->priv->system_font_size;
196}
197
198static void
199xfce_desktop_setup_icon_view(XfceDesktop *desktop)
200{
201 XfdesktopIconViewManager *manager = NULL;
202
203 switch(desktop->priv->icons_style) {
204 case XFCE_DESKTOP_ICON_STYLE_NONE:
205 /* nada */
206 break;
207
208 case XFCE_DESKTOP_ICON_STYLE_WINDOWS:
209 manager = xfdesktop_window_icon_manager_new(desktop->priv->gscreen);
210 break;
211
212#ifdef ENABLE_FILE_ICONS
213 case XFCE_DESKTOP_ICON_STYLE_FILES:
214 {
215 GFile *file;
216 const gchar *desktop_path;
217
218 desktop_path = g_get_user_special_dir(G_USER_DIRECTORY_DESKTOP);
219 file = g_file_new_for_path(desktop_path);
220 manager = xfdesktop_file_icon_manager_new(file, desktop->priv->channel);
221 g_object_unref(file);
222 }
223 break;
224#endif
225
226 default:
227 g_critical("Unusable XfceDesktopIconStyle: %d. Unable to " \
228 "display desktop icons.",
229 desktop->priv->icons_style);
230 break;
231 }
232
233 if(manager) {
234 xfce_desktop_ensure_system_font_size(desktop);
235
236 desktop->priv->icon_view = xfdesktop_icon_view_new(manager);
237 xfdesktop_icon_view_set_font_size(XFDESKTOP_ICON_VIEW(desktop->priv->icon_view),
238 (!desktop->priv->icons_font_size_set
239 || !desktop->priv->icons_font_size)
240 ? desktop->priv->system_font_size
241 : desktop->priv->icons_font_size);
242 if(desktop->priv->icons_size > 0) {
243 xfdesktop_icon_view_set_icon_size(XFDESKTOP_ICON_VIEW(desktop->priv->icon_view),
244 desktop->priv->icons_size);
245 }
246 gtk_widget_show(desktop->priv->icon_view);
247 gtk_container_add(GTK_CONTAINER(desktop), desktop->priv->icon_view);
248 }
249
250 gtk_widget_queue_draw(GTK_WIDGET(desktop));
251}
252#endif
253
254static void
255set_imgfile_root_property(XfceDesktop *desktop, const gchar *filename,
256 gint monitor)
257{
258 gchar property_name[128];
259
260 gdk_error_trap_push();
261
262 g_snprintf(property_name, 128, XFDESKTOP_IMAGE_FILE_FMT, monitor);
263 if(filename) {
264 gdk_property_change(gdk_screen_get_root_window(desktop->priv->gscreen),
265 gdk_atom_intern(property_name, FALSE),
266 gdk_x11_xatom_to_atom(XA_STRING), 8,
267 GDK_PROP_MODE_REPLACE,
268 (guchar *)filename, strlen(filename)+1);
269 } else {
270 gdk_property_delete(gdk_screen_get_root_window(desktop->priv->gscreen),
271 gdk_atom_intern(property_name, FALSE));
272 }
273
274 gdk_error_trap_pop();
275}
276
277static void
278set_real_root_window_pixmap(GdkScreen *gscreen,
279 GdkPixmap *pmap)
280{
281#ifndef DISABLE_FOR_BUG7442
282 Window xid;
283 GdkWindow *groot;
284
285 xid = GDK_DRAWABLE_XID(pmap);
286 groot = gdk_screen_get_root_window(gscreen);
287
288 gdk_error_trap_push();
289
290 /* set root property for transparent Eterms */
291 gdk_property_change(groot,
292 gdk_atom_intern("_XROOTPMAP_ID", FALSE),
293 gdk_atom_intern("PIXMAP", FALSE), 32,
294 GDK_PROP_MODE_REPLACE, (guchar *)&xid, 1);
295 /* set this other property because someone might need it sometime. */
296 gdk_property_change(groot,
297 gdk_atom_intern("ESETROOT_PMAP_ID", FALSE),
298 gdk_atom_intern("PIXMAP", FALSE), 32,
299 GDK_PROP_MODE_REPLACE, (guchar *)&xid, 1);
300 /* and set the root window's BG pixmap, because aterm is somewhat lame. */
301 gdk_window_set_back_pixmap(groot, pmap, FALSE);
302 /* there really should be a standard for this crap... */
303
304 gdk_error_trap_pop();
305#endif
306}
307
308static void
309backdrop_changed_cb(XfceBackdrop *backdrop, gpointer user_data)
310{
311 XfceDesktop *desktop = XFCE_DESKTOP(user_data);
312 GdkPixmap *pmap = desktop->priv->bg_pixmap;
313 GdkScreen *gscreen = desktop->priv->gscreen;
314 GdkPixbuf *pix;
315 GdkRectangle rect;
316 guint i;
317 gint monitor = -1;
318
319 TRACE("entering");
320
321 g_return_if_fail(XFCE_IS_DESKTOP(desktop));
322
323 if(desktop->priv->updates_frozen || !GTK_WIDGET_REALIZED(GTK_WIDGET(desktop)))
324 return;
325
326 TRACE("really entering");
327
328 for(i = 0; i < XFCE_DESKTOP(desktop)->priv->nbackdrops; i++) {
329 if(backdrop == XFCE_DESKTOP(desktop)->priv->backdrops[i]) {
330 monitor = i;
331 break;
332 }
333 }
334 if(monitor == -1)
335 return;
336
337 /* create/get the composited backdrop pixmap */
338 pix = xfce_backdrop_get_pixbuf(backdrop);
339 if(!pix)
340 return;
341
342 if(desktop->priv->xinerama_stretch) {
343 GdkRectangle monitor_rect;
344
345 gdk_screen_get_monitor_geometry(gscreen, 0, &rect);
346
347 /* Get the lowest x and y value for all the monitors in
348 * case none of them start at 0,0 for whatever reason.
349 */
350 for(i = 1; i < (guint)gdk_screen_get_n_monitors(gscreen); i++) {
351 gdk_screen_get_monitor_geometry(gscreen, i, &monitor_rect);
352
353 if(monitor_rect.x < rect.x)
354 rect.x = monitor_rect.x;
355 if(monitor_rect.y < rect.y)
356 rect.y = monitor_rect.y;
357 }
358
359 rect.width = gdk_screen_get_width(gscreen);
360 rect.height = gdk_screen_get_height(gscreen);
361 } else {
362 gdk_screen_get_monitor_geometry(gscreen, monitor, &rect);
363 }
364
365 gdk_draw_pixbuf(GDK_DRAWABLE(pmap), GTK_WIDGET(desktop)->style->black_gc,
366 pix, 0, 0, rect.x, rect.y,
367 gdk_pixbuf_get_width(pix), gdk_pixbuf_get_height(pix),
368 GDK_RGB_DITHER_MAX, 0, 0);
369 g_object_unref(G_OBJECT(pix));
370
371 /* tell gtk to redraw the repainted area */
372 gtk_widget_queue_draw_area(GTK_WIDGET(desktop), rect.x, rect.y,
373 rect.width, rect.height);
374
375 set_imgfile_root_property(desktop,
376 xfce_backdrop_get_image_filename(backdrop),
377 monitor);
378
379 /* do this again so apps watching the root win notice the update */
380 set_real_root_window_pixmap(gscreen, pmap);
381}
382
383static void
384backdrop_cycle_cb(XfceBackdrop *backdrop, gpointer user_data)
385{
386 const gchar* backdrop_list;
387
388 TRACE("entering");
389
390 g_return_if_fail(XFCE_IS_BACKDROP(backdrop));
391
392 backdrop_list = xfce_backdrop_get_list(backdrop);
393
394 if(xfdesktop_backdrop_list_is_valid(backdrop_list)) {
395 gchar *backdrop_file;
396 GError *error = NULL;
397
398 backdrop_file = xfdesktop_backdrop_list_choose_random(backdrop_list,
399 &error);
400
401 xfce_backdrop_set_image_filename(backdrop, backdrop_file);
402 g_free(backdrop_file);
403 backdrop_changed_cb(backdrop, user_data);
404 }
405}
406
407static void
408screen_size_changed_cb(GdkScreen *gscreen, gpointer user_data)
409{
410 XfceDesktop *desktop = user_data;
411 gint w, h;
412
413 g_return_if_fail(XFCE_IS_DESKTOP(desktop));
414
415 w = gdk_screen_get_width(gscreen);
416 h = gdk_screen_get_height(gscreen);
417 gtk_widget_set_size_request(GTK_WIDGET(desktop), w, h);
418 gtk_window_resize(GTK_WINDOW(desktop), w, h);
419
420 if(desktop->priv->bg_pixmap)
421 g_object_unref(G_OBJECT(desktop->priv->bg_pixmap));
422 desktop->priv->bg_pixmap = gdk_pixmap_new(GDK_DRAWABLE(GTK_WIDGET(desktop)->window),
423 w, h, -1);
424 set_real_root_window_pixmap(desktop->priv->gscreen,
425 desktop->priv->bg_pixmap);
426 gdk_window_set_back_pixmap(GTK_WIDGET(desktop)->window,
427 desktop->priv->bg_pixmap, FALSE);
428
429 /* special case for 1 backdrop to handle xinerama stretching */
430 if(desktop->priv->xinerama_stretch) {
431 xfce_backdrop_set_size(desktop->priv->backdrops[0], w, h);
432 backdrop_changed_cb(desktop->priv->backdrops[0], desktop);
433 } else {
434 GdkRectangle rect;
435 guint i;
436
437 for(i = 0; i < desktop->priv->nbackdrops; i++) {
438 gdk_screen_get_monitor_geometry(gscreen, i, &rect);
439 xfce_backdrop_set_size(desktop->priv->backdrops[i], rect.width,
440 rect.height);
441 backdrop_changed_cb(desktop->priv->backdrops[i], desktop);
442 }
443 }
444}
445
446static void
447screen_composited_changed_cb(GdkScreen *gscreen,
448 gpointer user_data)
449{
450 /* fake a screen size changed, so the background is properly set */
451 screen_size_changed_cb(gscreen, user_data);
452}
453
454static void
455xfce_desktop_monitors_changed(GdkScreen *gscreen,
456 gpointer user_data)
457{
458 XfceDesktop *desktop = XFCE_DESKTOP(user_data);
459 guint i;
460
461 if(desktop->priv->xinerama_stretch) {
462 if(desktop->priv->nbackdrops > 1) {
463 for(i = 1; i < desktop->priv->nbackdrops; ++i)
464 g_object_unref(G_OBJECT(desktop->priv->backdrops[i]));
465 }
466
467 if(desktop->priv->nbackdrops != 1) {
468 desktop->priv->backdrops = g_realloc(desktop->priv->backdrops,
469 sizeof(XfceBackdrop *));
470 if(!desktop->priv->nbackdrops) {
471 GdkVisual *vis = gtk_widget_get_visual(GTK_WIDGET(desktop));
472 desktop->priv->backdrops[0] = xfce_backdrop_new(vis);
473 xfce_desktop_connect_backdrop_settings(desktop,
474 desktop->priv->backdrops[0],
475 0);
476 g_signal_connect(G_OBJECT(desktop->priv->backdrops[0]),
477 "changed",
478 G_CALLBACK(backdrop_changed_cb), desktop);
479 g_signal_connect(G_OBJECT(desktop->priv->backdrops[0]),
480 "cycle",
481 G_CALLBACK(backdrop_cycle_cb), desktop);
482 }
483 desktop->priv->nbackdrops = 1;
484 }
485 } else {
486 guint n_monitors = gdk_screen_get_n_monitors(gscreen);
487
488 if(n_monitors < desktop->priv->nbackdrops) {
489 for(i = n_monitors; i < desktop->priv->nbackdrops; ++i)
490 g_object_unref(G_OBJECT(desktop->priv->backdrops[i]));
491 }
492
493 if(n_monitors != desktop->priv->nbackdrops) {
494 desktop->priv->backdrops = g_realloc(desktop->priv->backdrops,
495 sizeof(XfceBackdrop *) * n_monitors);
496 if(n_monitors > desktop->priv->nbackdrops) {
497 GdkVisual *vis = gtk_widget_get_visual(GTK_WIDGET(desktop));
498 for(i = desktop->priv->nbackdrops; i < n_monitors; ++i) {
499 desktop->priv->backdrops[i] = xfce_backdrop_new(vis);
500 xfce_desktop_connect_backdrop_settings(desktop,
501 desktop->priv->backdrops[i],
502 i);
503 g_signal_connect(G_OBJECT(desktop->priv->backdrops[i]),
504 "changed",
505 G_CALLBACK(backdrop_changed_cb),
506 desktop);
507 g_signal_connect(G_OBJECT(desktop->priv->backdrops[i]),
508 "cycle",
509 G_CALLBACK(backdrop_cycle_cb),
510 desktop);
511 }
512 }
513 desktop->priv->nbackdrops = n_monitors;
514 }
515 }
516
517 /* update the total size of the screen and the size of each backdrop */
518 screen_size_changed_cb(gscreen, desktop);
519}
520
521static void
522screen_set_selection(XfceDesktop *desktop)
523{
524 Window xwin;
525 gint xscreen;
526 gchar selection_name[100];
527 Atom selection_atom, manager_atom;
528
529 xwin = GDK_WINDOW_XID(GTK_WIDGET(desktop)->window);
530 xscreen = gdk_screen_get_number(desktop->priv->gscreen);
531
532 g_snprintf(selection_name, 100, XFDESKTOP_SELECTION_FMT, xscreen);
533 selection_atom = XInternAtom(GDK_DISPLAY(), selection_name, False);
534 manager_atom = XInternAtom(GDK_DISPLAY(), "MANAGER", False);
535
536 /* the previous check in src/main.c occurs too early, so workaround by
537 * adding this one. */
538 if(XGetSelectionOwner(GDK_DISPLAY(), selection_atom) != None) {
539 g_warning("%s: already running, quitting.", PACKAGE);
540 exit(0);
541 }
542
543 XSelectInput(GDK_DISPLAY(), xwin, PropertyChangeMask | ButtonPressMask);
544 XSetSelectionOwner(GDK_DISPLAY(), selection_atom, xwin, GDK_CURRENT_TIME);
545
546 /* Check to see if we managed to claim the selection. If not,
547 * we treat it as if we got it then immediately lost it */
548 if(XGetSelectionOwner(GDK_DISPLAY(), selection_atom) == xwin) {
549 XClientMessageEvent xev;
550 Window xroot = GDK_WINDOW_XID(gdk_screen_get_root_window(desktop->priv->gscreen));
551
552 xev.type = ClientMessage;
553 xev.window = xroot;
554 xev.message_type = manager_atom;
555 xev.format = 32;
556 xev.data.l[0] = GDK_CURRENT_TIME;
557 xev.data.l[1] = selection_atom;
558 xev.data.l[2] = xwin;
559 xev.data.l[3] = 0; /* manager specific data */
560 xev.data.l[4] = 0; /* manager specific data */
561
562 XSendEvent(GDK_DISPLAY(), xroot, False, StructureNotifyMask, (XEvent *)&xev);
563 } else {
564 g_error("%s: could not set selection ownership", PACKAGE);
565 exit(1);
566 }
567}
568
569
570
571/* gobject-related functions */
572
573
574G_DEFINE_TYPE(XfceDesktop, xfce_desktop, GTK_TYPE_WINDOW)
575
576
577static void
578xfce_desktop_class_init(XfceDesktopClass *klass)
579{
580 GObjectClass *gobject_class = (GObjectClass *)klass;
581 GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
582
583 g_type_class_add_private(klass, sizeof(XfceDesktopPriv));
584
585 gobject_class->finalize = xfce_desktop_finalize;
586 gobject_class->set_property = xfce_desktop_set_property;
587 gobject_class->get_property = xfce_desktop_get_property;
588
589 widget_class->realize = xfce_desktop_realize;
590 widget_class->unrealize = xfce_desktop_unrealize;
591 widget_class->button_press_event = xfce_desktop_button_press_event;
592 widget_class->expose_event = xfce_desktop_expose;
593 widget_class->delete_event = xfce_desktop_delete_event;
594 widget_class->popup_menu = xfce_desktop_popup_menu;
595 widget_class->style_set = xfce_desktop_style_set;
596
597 signals[SIG_POPULATE_ROOT_MENU] = g_signal_new("populate-root-menu",
598 XFCE_TYPE_DESKTOP,
599 G_SIGNAL_RUN_LAST,
600 G_STRUCT_OFFSET(XfceDesktopClass,
601 populate_root_menu),
602 NULL, NULL,
603 g_cclosure_marshal_VOID__OBJECT,
604 G_TYPE_NONE, 1,
605 GTK_TYPE_MENU_SHELL);
606
607 signals[SIG_POPULATE_SECONDARY_ROOT_MENU] = g_signal_new("populate-secondary-root-menu",
608 XFCE_TYPE_DESKTOP,
609 G_SIGNAL_RUN_LAST,
610 G_STRUCT_OFFSET(XfceDesktopClass,
611 populate_secondary_root_menu),
612 NULL, NULL,
613 g_cclosure_marshal_VOID__OBJECT,
614 G_TYPE_NONE, 1,
615 GTK_TYPE_MENU_SHELL);
616
617#define XFDESKTOP_PARAM_FLAGS (G_PARAM_READWRITE \
618 | G_PARAM_CONSTRUCT \
619 | G_PARAM_STATIC_NAME \
620 | G_PARAM_STATIC_NICK \
621 | G_PARAM_STATIC_BLURB)
622
623 g_object_class_install_property(gobject_class, PROP_XINERAMA_STRETCH,
624 g_param_spec_boolean("xinerama-stretch",
625 "xinerama stretch",
626 "xinerama stretch",
627 FALSE,
628 XFDESKTOP_PARAM_FLAGS));
629
630#ifdef ENABLE_DESKTOP_ICONS
631 g_object_class_install_property(gobject_class, PROP_ICON_STYLE,
632 g_param_spec_enum("icon-style",
633 "icon style",
634 "icon style",
635 XFCE_TYPE_DESKTOP_ICON_STYLE,
636#ifdef ENABLE_FILE_ICONS
637 XFCE_DESKTOP_ICON_STYLE_FILES,
638#else
639 XFCE_DESKTOP_ICON_STYLE_WINDOWS,
640#endif
641 XFDESKTOP_PARAM_FLAGS));
642
643 g_object_class_install_property(gobject_class, PROP_ICON_SIZE,
644 g_param_spec_uint("icon-size",
645 "icon size",
646 "icon size",
647 8, 192, 36,
648 XFDESKTOP_PARAM_FLAGS));
649
650 g_object_class_install_property(gobject_class, PROP_ICON_FONT_SIZE,
651 g_param_spec_uint("icon-font-size",
652 "icon font size",
653 "icon font size",
654 4, 144, 12,
655 XFDESKTOP_PARAM_FLAGS));
656
657 g_object_class_install_property(gobject_class, PROP_ICON_FONT_SIZE_SET,
658 g_param_spec_boolean("icon-font-size-set",
659 "icon font size set",
660 "icon font size set",
661 FALSE,
662 XFDESKTOP_PARAM_FLAGS));
663#endif
664#undef XFDESKTOP_PARAM_FLAGS
665}
666
667static void
668xfce_desktop_init(XfceDesktop *desktop)
669{
670 desktop->priv = G_TYPE_INSTANCE_GET_PRIVATE(desktop, XFCE_TYPE_DESKTOP,
671 XfceDesktopPriv);
672 GTK_WINDOW(desktop)->type = GTK_WINDOW_TOPLEVEL;
673
674 gtk_window_set_type_hint(GTK_WINDOW(desktop), GDK_WINDOW_TYPE_HINT_DESKTOP);
675 gtk_window_set_accept_focus(GTK_WINDOW(desktop), FALSE);
676 gtk_window_set_resizable(GTK_WINDOW(desktop), FALSE);
677}
678
679static void
680xfce_desktop_finalize(GObject *object)
681{
682 XfceDesktop *desktop = XFCE_DESKTOP(object);
683
684 g_object_unref(G_OBJECT(desktop->priv->channel));
685 g_free(desktop->priv->property_prefix);
686
687 G_OBJECT_CLASS(xfce_desktop_parent_class)->finalize(object);
688}
689
690static void
691xfce_desktop_set_property(GObject *object,
692 guint property_id,
693 const GValue *value,
694 GParamSpec *pspec)
695{
696 XfceDesktop *desktop = XFCE_DESKTOP(object);
697
698 switch(property_id) {
699 case PROP_XINERAMA_STRETCH:
700 xfce_desktop_set_xinerama_stretch(desktop,
701 g_value_get_boolean(value));
702 break;
703
704#ifdef ENABLE_DESKTOP_ICONS
705 case PROP_ICON_STYLE:
706 xfce_desktop_set_icon_style(desktop,
707 g_value_get_enum(value));
708 break;
709
710 case PROP_ICON_SIZE:
711 xfce_desktop_set_icon_size(desktop,
712 g_value_get_uint(value));
713 break;
714
715 case PROP_ICON_FONT_SIZE:
716 xfce_desktop_set_icon_font_size(desktop,
717 g_value_get_uint(value));
718 break;
719
720 case PROP_ICON_FONT_SIZE_SET:
721 xfce_desktop_set_use_icon_font_size(desktop,
722 g_value_get_boolean(value));
723 break;
724
725#endif
726 default:
727 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
728 break;
729 }
730}
731
732static void
733xfce_desktop_get_property(GObject *object,
734 guint property_id,
735 GValue *value,
736 GParamSpec *pspec)
737{
738 XfceDesktop *desktop = XFCE_DESKTOP(object);
739
740 switch(property_id) {
741 case PROP_XINERAMA_STRETCH:
742 g_value_set_boolean(value, desktop->priv->xinerama_stretch);
743 break;
744
745#ifdef ENABLE_DESKTOP_ICONS
746 case PROP_ICON_STYLE:
747 g_value_set_enum(value, desktop->priv->icons_style);
748 break;
749
750 case PROP_ICON_SIZE:
751 g_value_set_uint(value, desktop->priv->icons_size);
752 break;
753
754 case PROP_ICON_FONT_SIZE:
755 g_value_set_uint(value, desktop->priv->icons_font_size);
756 break;
757
758 case PROP_ICON_FONT_SIZE_SET:
759 g_value_set_boolean(value, desktop->priv->icons_font_size_set);
760 break;
761
762#endif
763 default:
764 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
765 break;
766 }
767}
768
769static void
770xfce_desktop_realize(GtkWidget *widget)
771{
772 XfceDesktop *desktop = XFCE_DESKTOP(widget);
773 GdkAtom atom;
774 gint sw, sh;
775 Window xid;
776 GdkWindow *groot;
777
778 TRACE("entering");
779
780 gtk_window_set_screen(GTK_WINDOW(desktop), desktop->priv->gscreen);
781 sw = gdk_screen_get_width(desktop->priv->gscreen);
782 sh = gdk_screen_get_height(desktop->priv->gscreen);
783 if(gtk_major_version > 2
784 || (gtk_major_version == 2 && gtk_minor_version >= 13))
785 {
786 g_signal_connect(G_OBJECT(desktop->priv->gscreen),
787 "monitors-changed",
788 G_CALLBACK(xfce_desktop_monitors_changed),
789 desktop);
790 }
791
792 /* chain up */
793 GTK_WIDGET_CLASS(xfce_desktop_parent_class)->realize(widget);
794
795 gtk_window_set_title(GTK_WINDOW(desktop), _("Desktop"));
796
797 gtk_widget_set_size_request(GTK_WIDGET(desktop), sw, sh);
798 gtk_window_move(GTK_WINDOW(desktop), 0, 0);
799
800 atom = gdk_atom_intern("_NET_WM_WINDOW_TYPE_DESKTOP", FALSE);
801 gdk_property_change(GTK_WIDGET(desktop)->window,
802 gdk_atom_intern("_NET_WM_WINDOW_TYPE", FALSE),
803 gdk_atom_intern("ATOM", FALSE), 32,
804 GDK_PROP_MODE_REPLACE, (guchar *)&atom, 1);
805
806 xid = GDK_WINDOW_XID(GTK_WIDGET(desktop)->window);
807 groot = gdk_screen_get_root_window(desktop->priv->gscreen);
808
809 gdk_property_change(groot,
810 gdk_atom_intern("XFCE_DESKTOP_WINDOW", FALSE),
811 gdk_atom_intern("WINDOW", FALSE), 32,
812 GDK_PROP_MODE_REPLACE, (guchar *)&xid, 1);
813
814 gdk_property_change(groot,
815 gdk_atom_intern("NAUTILUS_DESKTOP_WINDOW_ID", FALSE),
816 gdk_atom_intern("WINDOW", FALSE), 32,
817 GDK_PROP_MODE_REPLACE, (guchar *)&xid, 1);
818
819 screen_set_selection(desktop);
820
821 xfce_desktop_monitors_changed(desktop->priv->gscreen, desktop);
822
823 g_signal_connect(G_OBJECT(desktop->priv->gscreen), "size-changed",
824 G_CALLBACK(screen_size_changed_cb), desktop);
825 g_signal_connect(G_OBJECT(desktop->priv->gscreen), "composited-changed",
826 G_CALLBACK(screen_composited_changed_cb), desktop);
827
828 gtk_widget_add_events(GTK_WIDGET(desktop), GDK_EXPOSURE_MASK);
829
830#ifdef ENABLE_DESKTOP_ICONS
831 xfce_desktop_setup_icon_view(desktop);
832#endif
833
834 TRACE("exiting");
835}
836
837static void
838xfce_desktop_unrealize(GtkWidget *widget)
839{
840 XfceDesktop *desktop = XFCE_DESKTOP(widget);
841 guint i;
842 GdkWindow *groot;
843 gchar property_name[128];
844
845 g_return_if_fail(XFCE_IS_DESKTOP(desktop));
846
847 if(gtk_major_version > 2
848 || (gtk_major_version == 2 && gtk_minor_version >= 13))
849 {
850 g_signal_handlers_disconnect_by_func(G_OBJECT(desktop->priv->gscreen),
851 G_CALLBACK(xfce_desktop_monitors_changed),
852 desktop);
853 }
854
855 if(GTK_WIDGET_MAPPED(widget))
856 gtk_widget_unmap(widget);
857 GTK_WIDGET_UNSET_FLAGS(widget, GTK_MAPPED);
858
859 gtk_container_forall(GTK_CONTAINER(widget),
860 (GtkCallback)gtk_widget_unrealize,
861 NULL);
862
863 g_signal_handlers_disconnect_by_func(G_OBJECT(desktop->priv->gscreen),
864 G_CALLBACK(screen_size_changed_cb), desktop);
865 g_signal_handlers_disconnect_by_func(G_OBJECT(desktop->priv->gscreen),
866 G_CALLBACK(screen_composited_changed_cb), desktop);
867
868 gdk_error_trap_push();
869
870 groot = gdk_screen_get_root_window(desktop->priv->gscreen);
871 gdk_property_delete(groot, gdk_atom_intern("XFCE_DESKTOP_WINDOW", FALSE));
872 gdk_property_delete(groot, gdk_atom_intern("NAUTILUS_DESKTOP_WINDOW_ID", FALSE));
873
874#ifndef DISABLE_FOR_BUG7442
875 gdk_property_delete(groot, gdk_atom_intern("_XROOTPMAP_ID", FALSE));
876 gdk_property_delete(groot, gdk_atom_intern("ESETROOT_PMAP_ID", FALSE));
877 gdk_window_set_back_pixmap(groot, NULL, FALSE);
878#endif
879
880 if(desktop->priv->backdrops) {
881 for(i = 0; i < desktop->priv->nbackdrops; i++) {
882 g_snprintf(property_name, 128, XFDESKTOP_IMAGE_FILE_FMT, i);
883 gdk_property_delete(groot, gdk_atom_intern(property_name, FALSE));
884 g_object_unref(G_OBJECT(desktop->priv->backdrops[i]));
885 }
886 g_free(desktop->priv->backdrops);
887 desktop->priv->backdrops = NULL;
888 }
889
890 gdk_flush();
891 gdk_error_trap_pop();
892
893 g_object_unref(G_OBJECT(desktop->priv->bg_pixmap));
894 desktop->priv->bg_pixmap = NULL;
895
896 gtk_window_set_icon(GTK_WINDOW(widget), NULL);
897
898 gtk_style_detach(widget->style);
899 g_object_unref(G_OBJECT(widget->window));
900 widget->window = NULL;
901
902 gtk_selection_remove_all(widget);
903
904 GTK_WIDGET_UNSET_FLAGS(widget, GTK_REALIZED);
905}
906
907static gboolean
908xfce_desktop_button_press_event(GtkWidget *w,
909 GdkEventButton *evt)
910{
911 guint button = evt->button;
912 guint state = evt->state;
913 g_return_val_if_fail(XFCE_IS_DESKTOP(w), FALSE);
914
915 if(evt->type == GDK_BUTTON_PRESS) {
916 if(button == 3 || (button == 1 && (state & GDK_SHIFT_MASK))) {
917#ifdef ENABLE_DESKTOP_ICONS
918 if(XFCE_DESKTOP(w)->priv->icons_style != XFCE_DESKTOP_ICON_STYLE_NONE)
919 return FALSE;
920#endif
921 xfce_desktop_popup_root_menu(XFCE_DESKTOP(w),
922 button,
923 evt->time);
924 } else if(button == 2 || (button == 1 && (state & GDK_SHIFT_MASK)
925 && (state & GDK_CONTROL_MASK)))
926 {
927 xfce_desktop_popup_secondary_root_menu(XFCE_DESKTOP(w),
928 button, evt->time);
929 return TRUE;
930 }
931 }
932
933 return FALSE;
934}
935
936static gboolean
937xfce_desktop_popup_menu(GtkWidget *w)
938{
939 GdkEventButton *evt;
940 guint button, etime;
941
942 evt = (GdkEventButton *)gtk_get_current_event();
943 if(evt && GDK_BUTTON_PRESS == evt->type) {
944 button = evt->button;
945 etime = evt->time;
946 } else {
947 button = 0;
948 etime = gtk_get_current_event_time();
949 }
950
951 xfce_desktop_popup_root_menu(XFCE_DESKTOP(w), button, etime);
952
953 return TRUE;
954}
955
956static gboolean
957xfce_desktop_expose(GtkWidget *w,
958 GdkEventExpose *evt)
959{
960 GList *children, *l;
961
962 /*TRACE("entering");*/
963
964 if(evt->count != 0)
965 return FALSE;
966
967 gdk_window_clear_area(w->window, evt->area.x, evt->area.y,
968 evt->area.width, evt->area.height);
969
970 children = gtk_container_get_children(GTK_CONTAINER(w));
971 for(l = children; l; l = l->next) {
972 gtk_container_propagate_expose(GTK_CONTAINER(w),
973 GTK_WIDGET(l->data),
974 evt);
975 }
976 g_list_free(children);
977
978 return FALSE;
979}
980
981static gboolean
982xfce_desktop_delete_event(GtkWidget *w,
983 GdkEventAny *evt)
984{
985 if(XFCE_DESKTOP(w)->priv->session_logout_func)
986 XFCE_DESKTOP(w)->priv->session_logout_func();
987
988 return TRUE;
989}
990
991static void
992xfce_desktop_style_set(GtkWidget *w,
993 GtkStyle *old_style)
994{
995 XfceDesktop *desktop = XFCE_DESKTOP(w);
996#ifdef ENABLE_DESKTOP_ICONS
997 gdouble old_font_size;
998#endif
999
1000 if(GDK_IS_WINDOW(desktop->priv->bg_pixmap))
1001 gdk_window_set_back_pixmap(w->window, desktop->priv->bg_pixmap, FALSE);
1002 gtk_widget_queue_draw(w);
1003
1004#ifdef ENABLE_DESKTOP_ICONS
1005 old_font_size = desktop->priv->system_font_size;
1006 if(xfce_desktop_ensure_system_font_size(desktop) != old_font_size
1007 && desktop->priv->icon_view && !desktop->priv->icons_font_size_set)
1008 {
1009 xfdesktop_icon_view_set_font_size(XFDESKTOP_ICON_VIEW(desktop->priv->icon_view),
1010 desktop->priv->system_font_size);
1011 }
1012#endif
1013}
1014
1015static void
1016xfce_desktop_connect_settings(XfceDesktop *desktop)
1017{
1018 XfconfChannel *channel = desktop->priv->channel;
1019 gchar buf[1024];
1020
1021 xfce_desktop_freeze_updates(desktop);
1022
1023 g_strlcpy(buf, desktop->priv->property_prefix, sizeof(buf));
1024 g_strlcat(buf, "xinerama-stretch", sizeof(buf));
1025 xfconf_g_property_bind(channel, buf, G_TYPE_BOOLEAN,
1026 G_OBJECT(desktop), "xinerama-stretch");
1027
1028#ifdef ENABLE_DESKTOP_ICONS
1029#define ICONS_PREFIX "/desktop-icons/"
1030
1031 xfconf_g_property_bind(channel, ICONS_PREFIX "style",
1032 XFCE_TYPE_DESKTOP_ICON_STYLE,
1033 G_OBJECT(desktop), "icon-style");
1034 xfconf_g_property_bind(channel, ICONS_PREFIX "icon-size", G_TYPE_UINT,
1035 G_OBJECT(desktop), "icon-size");
1036 xfconf_g_property_bind(channel, ICONS_PREFIX "font-size", G_TYPE_UINT,
1037 G_OBJECT(desktop), "icon-font-size");
1038 xfconf_g_property_bind(channel, ICONS_PREFIX "use-custom-font-size",
1039 G_TYPE_BOOLEAN,
1040 G_OBJECT(desktop), "icon-font-size-set");
1041#undef ICONS_PREFIX
1042#endif
1043
1044 xfce_desktop_thaw_updates(desktop);
1045}
1046
1047static void
1048xfce_desktop_image_filename_changed(XfconfChannel *channel,
1049 const gchar *property,
1050 const GValue *value,
1051 gpointer user_data)
1052{
1053 XfceDesktop *desktop = user_data;
1054 gchar *p;
1055 const gchar *filename;
1056 gint monitor;
1057 XfceBackdrop *backdrop;
1058
1059 p = strstr(property, "/monitor");
1060 if(!p)
1061 return;
1062
1063 monitor = atoi(p + 8);
1064 if(monitor < 0 || monitor >= gdk_screen_get_n_monitors(desktop->priv->gscreen))
1065 return;
1066
1067 if(desktop->priv->xinerama_stretch && monitor != 0)
1068 return;
1069 backdrop = desktop->priv->backdrops[monitor];
1070
1071 if(!G_VALUE_HOLDS_STRING(value))
1072 filename = DEFAULT_BACKDROP;
1073 else
1074 filename = g_value_get_string(value);
1075 if(G_LIKELY(filename && *filename)) {
1076 if(xfdesktop_backdrop_list_is_valid(filename)) {
1077 gchar *backdrop_file;
1078 GError *error = NULL;
1079
1080 backdrop_file = xfdesktop_backdrop_list_choose_random(filename,
1081 &error);
1082#if 0
1083 if(!backdrop_file && !xfdesktop_backdrop_list_is_valid(filename)) {
1084 gchar *primary = g_strdup_printf(_("Unable to load image from backdrop list file \"%s\""),
1085 filename);
1086 xfce_message_dialog(GTK_WINDOW(desktop), _("Desktop Error"),
1087 GTK_STOCK_DIALOG_ERROR, primary,
1088 error->message,
1089 GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT,
1090 NULL);
1091 g_error_free(error);
1092 g_free(primary);
1093 }
1094#endif
1095
1096 xfce_backdrop_set_image_filename(backdrop, backdrop_file);
1097 g_free(backdrop_file);
1098
1099 xfce_backdrop_set_list(backdrop, g_strdup(filename));
1100 } else {
1101 xfce_backdrop_set_image_filename(backdrop, filename);
1102
1103 xfce_backdrop_set_list(backdrop, NULL);
1104 }
1105 }
1106}
1107
1108static void
1109xfce_desktop_connect_backdrop_settings(XfceDesktop *desktop,
1110 XfceBackdrop *backdrop,
1111 guint monitor)
1112{
1113 XfconfChannel *channel = desktop->priv->channel;
1114 char buf[1024], buf1[1024];
1115 gint pp_len;
1116 GValue value = { 0, };
1117
1118 g_snprintf(buf, sizeof(buf), "%smonitor%d/",
1119 desktop->priv->property_prefix, monitor);
1120 pp_len = strlen(buf);
1121
1122 g_strlcat(buf, "color-style", sizeof(buf));
1123 xfconf_g_property_bind(channel, buf, XFCE_TYPE_BACKDROP_COLOR_STYLE,
1124 G_OBJECT(backdrop), "color-style");
1125
1126 buf[pp_len] = 0;
1127 g_strlcat(buf, "color1", sizeof(buf));
1128 xfconf_g_property_bind_gdkcolor(channel, buf,
1129 G_OBJECT(backdrop), "first-color");
1130
1131 buf[pp_len] = 0;
1132 g_strlcat(buf, "color2", sizeof(buf));
1133 xfconf_g_property_bind_gdkcolor(channel, buf,
1134 G_OBJECT(backdrop), "second-color");
1135
1136 buf[pp_len] = 0;
1137 g_strlcat(buf, "image-show", sizeof(buf));
1138 xfconf_g_property_bind(channel, buf, G_TYPE_BOOLEAN,
1139 G_OBJECT(backdrop), "show-image");
1140
1141 buf[pp_len] = 0;
1142 g_strlcat(buf, "image-style", sizeof(buf));
1143 xfconf_g_property_bind(channel, buf, XFCE_TYPE_BACKDROP_IMAGE_STYLE,
1144 G_OBJECT(backdrop), "image-style");
1145
1146 buf[pp_len] = 0;
1147 g_strlcat(buf, "brightness", sizeof(buf));
1148 xfconf_g_property_bind(channel, buf, G_TYPE_INT,
1149 G_OBJECT(backdrop), "brightness");
1150
1151 buf[pp_len] = 0;
1152 g_strlcat(buf, "saturation", sizeof(buf));
1153 xfconf_g_property_bind(channel, buf, G_TYPE_DOUBLE,
1154 G_OBJECT(backdrop), "saturation");
1155
1156 buf[pp_len] = 0;
1157 g_strlcat(buf, "backdrop-cycle-enable", sizeof(buf));
1158 xfconf_g_property_bind(channel, buf, G_TYPE_BOOLEAN,
1159 G_OBJECT(backdrop), "backdrop-cycle-enable");
1160
1161 buf[pp_len] = 0;
1162 g_strlcat(buf, "backdrop-cycle-timer", sizeof(buf));
1163 xfconf_g_property_bind(channel, buf, G_TYPE_UINT,
1164 G_OBJECT(backdrop), "backdrop-cycle-timer");
1165
1166 /* the image filename could be an image or a backdrop list, so we
1167 * can't just bind the property directly */
1168 buf[pp_len] = 0;
1169 g_strlcat(buf, "image-path", sizeof(buf));
1170 g_strlcpy(buf1, "property-changed::", sizeof(buf1));
1171 g_strlcat(buf1, buf, sizeof(buf1));
1172 g_signal_connect(G_OBJECT(channel), buf1,
1173 G_CALLBACK(xfce_desktop_image_filename_changed), desktop);
1174 if(xfconf_channel_get_property(channel, buf, &value)) {
1175 xfce_desktop_image_filename_changed(channel, buf, &value, desktop);
1176 g_value_unset(&value);
1177 }
1178}
1179
1180
1181
1182/* public api */
1183
1184/**
1185 * xfce_desktop_new:
1186 * @gscreen: The current #GdkScreen.
1187 * @channel: An #XfconfChannel to use for settings.
1188 * @property_prefix: String prefix for per-screen properties.
1189 *
1190 * Creates a new #XfceDesktop for the specified #GdkScreen. If @gscreen is
1191 * %NULL, the default screen will be used.
1192 *
1193 * Return value: A new #XfceDesktop.
1194 **/
1195GtkWidget *
1196xfce_desktop_new(GdkScreen *gscreen,
1197 XfconfChannel *channel,
1198 const gchar *property_prefix)
1199{
1200 XfceDesktop *desktop;
1201
1202 g_return_val_if_fail(channel && property_prefix, NULL);
1203
1204 desktop = g_object_new(XFCE_TYPE_DESKTOP, NULL);
1205
1206 if(!gscreen)
1207 gscreen = gdk_display_get_default_screen(gdk_display_get_default());
1208 gtk_window_set_screen(GTK_WINDOW(desktop), gscreen);
1209 desktop->priv->gscreen = gscreen;
1210
1211 desktop->priv->channel = g_object_ref(G_OBJECT(channel));
1212 desktop->priv->property_prefix = g_strdup(property_prefix);
1213
1214 xfce_desktop_connect_settings(desktop);
1215
1216 return GTK_WIDGET(desktop);
1217}
1218
1219guint
1220xfce_desktop_get_n_monitors(XfceDesktop *desktop)
1221{
1222 g_return_val_if_fail(XFCE_IS_DESKTOP(desktop), 0);
1223
1224 return desktop->priv->nbackdrops;
1225}
1226
1227gint
1228xfce_desktop_get_width(XfceDesktop *desktop)
1229{
1230 g_return_val_if_fail(XFCE_IS_DESKTOP(desktop), -1);
1231
1232 return gdk_screen_get_width(desktop->priv->gscreen);
1233}
1234
1235gint
1236xfce_desktop_get_height(XfceDesktop *desktop)
1237{
1238 g_return_val_if_fail(XFCE_IS_DESKTOP(desktop), -1);
1239
1240 return gdk_screen_get_height(desktop->priv->gscreen);
1241}
1242
1243void
1244xfce_desktop_set_xinerama_stretch(XfceDesktop *desktop,
1245 gboolean stretch)
1246{
1247 g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1248
1249 if(stretch == desktop->priv->xinerama_stretch)
1250 return;
1251
1252 desktop->priv->xinerama_stretch = stretch;
1253
1254 if(!desktop->priv->updates_frozen)
1255 xfce_desktop_monitors_changed(desktop->priv->gscreen, desktop);
1256}
1257
1258gboolean
1259xfce_desktop_get_xinerama_stretch(XfceDesktop *desktop)
1260{
1261 g_return_val_if_fail(XFCE_IS_DESKTOP(desktop), FALSE);
1262 return desktop->priv->xinerama_stretch;
1263}
1264
1265void
1266xfce_desktop_set_icon_style(XfceDesktop *desktop,
1267 XfceDesktopIconStyle style)
1268{
1269 g_return_if_fail(XFCE_IS_DESKTOP(desktop)
1270 && style <= XFCE_DESKTOP_ICON_STYLE_FILES);
1271
1272#ifdef ENABLE_DESKTOP_ICONS
1273 if(style == desktop->priv->icons_style)
1274 return;
1275
1276 if(desktop->priv->icon_view) {
1277 gtk_widget_destroy(desktop->priv->icon_view);
1278 desktop->priv->icon_view = NULL;
1279 }
1280
1281 desktop->priv->icons_style = style;
1282 if(GTK_WIDGET_REALIZED(desktop))
1283 xfce_desktop_setup_icon_view(desktop);
1284#endif
1285}
1286
1287XfceDesktopIconStyle
1288xfce_desktop_get_icon_style(XfceDesktop *desktop)
1289{
1290 g_return_val_if_fail(XFCE_IS_DESKTOP(desktop), XFCE_DESKTOP_ICON_STYLE_NONE);
1291
1292#ifdef ENABLE_DESKTOP_ICONS
1293 return desktop->priv->icons_style;
1294#else
1295 return XFCE_DESKTOP_ICON_STYLE_NONE;
1296#endif
1297}
1298
1299void
1300xfce_desktop_set_icon_size(XfceDesktop *desktop,
1301 guint icon_size)
1302{
1303 g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1304
1305#ifdef ENABLE_DESKTOP_ICONS
1306 if(icon_size == desktop->priv->icons_size)
1307 return;
1308
1309 desktop->priv->icons_size = icon_size;
1310
1311 if(desktop->priv->icon_view) {
1312 xfdesktop_icon_view_set_icon_size(XFDESKTOP_ICON_VIEW(desktop->priv->icon_view),
1313 icon_size);
1314 }
1315#endif
1316}
1317
1318void
1319xfce_desktop_set_icon_font_size(XfceDesktop *desktop,
1320 guint font_size_points)
1321{
1322 g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1323
1324#ifdef ENABLE_DESKTOP_ICONS
1325 if(font_size_points == desktop->priv->icons_font_size)
1326 return;
1327
1328 desktop->priv->icons_font_size = font_size_points;
1329
1330 if(desktop->priv->icons_font_size_set && desktop->priv->icon_view) {
1331 xfdesktop_icon_view_set_font_size(XFDESKTOP_ICON_VIEW(desktop->priv->icon_view),
1332 font_size_points);
1333 }
1334#endif
1335}
1336
1337void
1338xfce_desktop_set_use_icon_font_size(XfceDesktop *desktop,
1339 gboolean use_icon_font_size)
1340{
1341 g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1342
1343#ifdef ENABLE_DESKTOP_ICONS
1344 if(use_icon_font_size == desktop->priv->icons_font_size_set)
1345 return;
1346
1347 desktop->priv->icons_font_size_set = use_icon_font_size;
1348
1349 if(desktop->priv->icon_view) {
1350 if(!use_icon_font_size) {
1351 xfce_desktop_ensure_system_font_size(desktop);
1352 xfdesktop_icon_view_set_font_size(XFDESKTOP_ICON_VIEW(desktop->priv->icon_view),
1353 desktop->priv->system_font_size);
1354 } else {
1355 xfdesktop_icon_view_set_font_size(XFDESKTOP_ICON_VIEW(desktop->priv->icon_view),
1356 desktop->priv->icons_font_size);
1357 }
1358 }
1359#endif
1360}
1361
1362void
1363xfce_desktop_set_session_logout_func(XfceDesktop *desktop,
1364 SessionLogoutFunc logout_func)
1365{
1366 g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1367 desktop->priv->session_logout_func = logout_func;
1368}
1369
1370void
1371xfce_desktop_freeze_updates(XfceDesktop *desktop)
1372{
1373 g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1374 desktop->priv->updates_frozen = TRUE;
1375}
1376
1377void
1378xfce_desktop_thaw_updates(XfceDesktop *desktop)
1379{
1380 g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1381
1382 desktop->priv->updates_frozen = FALSE;
1383 if(GTK_WIDGET_REALIZED(desktop))
1384 xfce_desktop_monitors_changed(desktop->priv->gscreen, desktop);
1385}
1386
1387XfceBackdrop *
1388xfce_desktop_peek_backdrop(XfceDesktop *desktop,
1389 guint monitor)
1390{
1391 g_return_val_if_fail(XFCE_IS_DESKTOP(desktop)
1392 && GTK_WIDGET_REALIZED(GTK_WIDGET(desktop))
1393 && monitor < desktop->priv->nbackdrops, NULL);
1394 return desktop->priv->backdrops[monitor];
1395}
1396
1397static gboolean
1398xfce_desktop_menu_destroy_idled(gpointer data)
1399{
1400 gtk_widget_destroy(GTK_WIDGET(data));
1401 return FALSE;
1402}
1403
1404static void
1405xfce_desktop_do_menu_popup(XfceDesktop *desktop,
1406 guint button,
1407 guint activate_time,
1408 guint populate_signal)
1409{
1410 GdkScreen *screen;
1411 GtkWidget *menu;
1412 GList *menu_children;
1413
1414 TRACE("entering");
1415
1416 if(gtk_widget_has_screen(GTK_WIDGET(desktop)))
1417 screen = gtk_widget_get_screen(GTK_WIDGET(desktop));
1418 else
1419 screen = gdk_display_get_default_screen(gdk_display_get_default());
1420
1421 if(xfdesktop_popup_grab_available(gdk_screen_get_root_window(screen),
1422 activate_time))
1423 {
1424 menu = gtk_menu_new();
1425 gtk_menu_set_screen(GTK_MENU(menu), screen);
1426 g_signal_connect_swapped(G_OBJECT(menu), "deactivate",
1427 G_CALLBACK(g_idle_add),
1428 (gpointer)xfce_desktop_menu_destroy_idled);
1429
1430 g_signal_emit(G_OBJECT(desktop), populate_signal, 0, menu);
1431
1432 /* if nobody populated the menu, don't do anything */
1433 menu_children = gtk_container_get_children(GTK_CONTAINER(menu));
1434 if(!menu_children) {
1435 gtk_widget_destroy(menu);
1436 return;
1437 }
1438
1439 g_list_free(menu_children);
1440
1441 gtk_menu_attach_to_widget(GTK_MENU(menu), GTK_WIDGET(desktop), NULL);
1442
1443 /* bug #3652: for some reason passing the correct button here breaks
1444 * on some systems but not others. always pass 0 for now. */
1445 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0,
1446 activate_time);
1447 } else
1448 g_critical("Unable to get keyboard/mouse grab. Unable to pop up menu");
1449}
1450
1451void
1452xfce_desktop_popup_root_menu(XfceDesktop *desktop,
1453 guint button,
1454 guint activate_time)
1455{
1456 xfce_desktop_do_menu_popup(desktop, button, activate_time,
1457 signals[SIG_POPULATE_ROOT_MENU]);
1458}
1459
1460void
1461xfce_desktop_popup_secondary_root_menu(XfceDesktop *desktop,
1462 guint button,
1463 guint activate_time)
1464{
1465 xfce_desktop_do_menu_popup(desktop, button, activate_time,
1466 signals[SIG_POPULATE_SECONDARY_ROOT_MENU]);
1467}
1468
1469void
1470xfce_desktop_refresh(XfceDesktop *desktop)
1471{
1472 gchar buf[256];
1473 guint i, max;
1474
1475 g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1476
1477 if(!GTK_WIDGET_REALIZED(desktop))
1478 return;
1479
1480 /* reload image */
1481 if(desktop->priv->xinerama_stretch)
1482 max = 1;
1483 else
1484 max = desktop->priv->nbackdrops;
1485 for(i = 0; i < max; ++i) {
1486 GValue val = { 0, };
1487
1488 g_snprintf(buf, sizeof(buf), "%smonitor%d/image-path",
1489 desktop->priv->property_prefix, i);
1490 xfconf_channel_get_property(desktop->priv->channel, buf, &val);
1491
1492 xfce_desktop_image_filename_changed(desktop->priv->channel, buf,
1493 &val, desktop);
1494
1495 if(G_VALUE_TYPE(&val))
1496 g_value_unset(&val);
1497 }
1498
1499#ifdef ENABLE_DESKTOP_ICONS
1500 /* reload icon view */
1501 if(desktop->priv->icon_view) {
1502 gtk_widget_destroy(desktop->priv->icon_view);
1503 desktop->priv->icon_view = NULL;
1504 }
1505 xfce_desktop_setup_icon_view(desktop);
1506#endif
1507}
1508
1509void xfce_desktop_arrange_icons(XfceDesktop *desktop)
1510{
1511 g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1512
1513#ifdef ENABLE_DESKTOP_ICONS
1514 g_return_if_fail(XFDESKTOP_IS_ICON_VIEW(desktop->priv->icon_view));
1515
1516 xfdesktop_icon_view_sort_icons(XFDESKTOP_ICON_VIEW(desktop->priv->icon_view));
1517#endif
1518}
15190
=== removed directory '.pc/xubuntu_set-accountsservice-user-bg.patch'
=== removed directory '.pc/xubuntu_set-accountsservice-user-bg.patch/src'
=== removed file '.pc/xubuntu_set-accountsservice-user-bg.patch/src/xfce-desktop.c'
--- .pc/xubuntu_set-accountsservice-user-bg.patch/src/xfce-desktop.c 2013-03-03 11:58:50 +0000
+++ .pc/xubuntu_set-accountsservice-user-bg.patch/src/xfce-desktop.c 1970-01-01 00:00:00 +0000
@@ -1,1529 +0,0 @@
1/*
2 * xfdesktop - xfce4's desktop manager
3 *
4 * Copyright (c) 2004-2007 Brian Tarricone, <bjt23@cornell.edu>
5 *
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.
10 *
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 Library General Public License for more details.
15 *
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 * Random portions taken from or inspired by the original xfdesktop for xfce4:
21 * Copyright (C) 2002-2003 Jasper Huijsmans (huysmans@users.sourceforge.net)
22 * Copyright (C) 2003 Benedikt Meurer <benedikt.meurer@unix-ag.uni-siegen.de>
23 */
24
25#ifdef HAVE_CONFIG_H
26#include <config.h>
27#endif
28
29#include <stdio.h>
30
31#ifdef HAVE_STDLIB_H
32#include <stdlib.h>
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: