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 Foundation,
18  *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 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 #include <gio/gio.h>
67 
68 #ifdef ENABLE_DESKTOP_ICONS
69 #include "xfdesktop-icon-view.h"
70 #include "xfdesktop-window-icon-manager.h"
71 # ifdef ENABLE_FILE_ICONS
72 # include "xfdesktop-file-icon-manager.h"
73 # include "xfdesktop-special-file-icon.h"
74 # endif
75 #endif
76 
77 #include <libxfce4util/libxfce4util.h>
78 #include <libxfce4ui/libxfce4ui.h>
79 
80 #include <xfconf/xfconf.h>
81 #include <libwnck/libwnck.h>
82 
83 #include "xfdesktop-common.h"
84 #include "xfce-desktop.h"
85 #include "xfce-desktop-enum-types.h"
86 #include "xfce-workspace.h"
87 
88 /* disable setting the x background for bug 7442 */
89 //#define DISABLE_FOR_BUG7442
90 
91 struct _XfceDesktopPrivate
92 {
93     GdkScreen *gscreen;
94     WnckScreen *wnck_screen;
95     gboolean updates_frozen;
96 
97     XfconfChannel *channel;
98     gchar *property_prefix;
99 
100     cairo_surface_t *bg_surface;
101 
102     gint nworkspaces;
103     XfceWorkspace **workspaces;
104     gint current_workspace;
105     gboolean current_workspace_initialized;
106 
107     gboolean single_workspace_mode;
108     gint single_workspace_num;
109 
110     SessionLogoutFunc session_logout_func;
111 
112     guint32 grab_time;
113 
114 #ifdef ENABLE_DESKTOP_ICONS
115     XfceDesktopIconStyle icons_style;
116     gboolean icons_font_size_set;
117     guint icons_font_size;
118     guint icons_size;
119     gboolean primary;
120     gboolean icons_center_text;
121     gint  style_refresh_timer;
122     GtkWidget *icon_view;
123     gdouble system_font_size;
124 #endif
125 
126     gchar *last_filename;
127 };
128 
129 enum
130 {
131     SIG_POPULATE_ROOT_MENU = 0,
132     SIG_POPULATE_SECONDARY_ROOT_MENU,
133     N_SIGNALS
134 };
135 
136 enum
137 {
138     PROP_0 = 0,
139 #ifdef ENABLE_DESKTOP_ICONS
140     PROP_ICON_STYLE,
141     PROP_ICON_SIZE,
142     PROP_ICON_ON_PRIMARY,
143     PROP_ICON_FONT_SIZE,
144     PROP_ICON_FONT_SIZE_SET,
145     PROP_ICON_CENTER_TEXT,
146 #endif
147     PROP_SINGLE_WORKSPACE_MODE,
148     PROP_SINGLE_WORKSPACE_NUMBER,
149 };
150 
151 
152 static void xfce_desktop_finalize(GObject *object);
153 static void xfce_desktop_set_property(GObject *object,
154                                       guint property_id,
155                                       const GValue *value,
156                                       GParamSpec *pspec);
157 static void xfce_desktop_get_property(GObject *object,
158                                       guint property_id,
159                                       GValue *value,
160                                       GParamSpec *pspec);
161 
162 static void xfce_desktop_realize(GtkWidget *widget);
163 static void xfce_desktop_unrealize(GtkWidget *widget);
164 static gboolean xfce_desktop_button_press_event(GtkWidget *widget,
165                                                 GdkEventButton *evt);
166 static gboolean xfce_desktop_button_release_event(GtkWidget *widget,
167                                                   GdkEventButton *evt);
168 static gboolean xfce_desktop_popup_menu(GtkWidget *widget);
169 
170 static gboolean xfce_desktop_draw(GtkWidget *w,
171                                   cairo_t *cr);
172 static gboolean xfce_desktop_delete_event(GtkWidget *w,
173                                           GdkEventAny *evt);
174 static void xfce_desktop_style_updated(GtkWidget *w);
175 
176 static void xfce_desktop_set_single_workspace_mode(XfceDesktop *desktop,
177                                                    gboolean single_workspace);
178 static void xfce_desktop_set_single_workspace_number(XfceDesktop *desktop,
179                                                      gint workspace_num);
180 
181 static gboolean xfce_desktop_get_single_workspace_mode(XfceDesktop *desktop);
182 static gint xfce_desktop_get_current_workspace(XfceDesktop *desktop);
183 
184 #ifdef ENABLE_DESKTOP_ICONS
185 static void hidden_state_changed_cb(GObject *object, XfceDesktop *desktop);
186 #endif
187 
188 
189 static guint signals[N_SIGNALS] = { 0, };
190 
191 /* private functions */
192 
193 #ifdef ENABLE_DESKTOP_ICONS
194 static gdouble
xfce_desktop_ensure_system_font_size(XfceDesktop * desktop)195 xfce_desktop_ensure_system_font_size(XfceDesktop *desktop)
196 {
197     GdkScreen *gscreen;
198     GtkSettings *settings;
199     gchar *font_name = NULL;
200     PangoFontDescription *pfd;
201 
202     gscreen = gtk_widget_get_screen(GTK_WIDGET(desktop));
203 
204     settings = gtk_settings_get_for_screen(gscreen);
205     g_object_get(G_OBJECT(settings), "gtk-font-name", &font_name, NULL);
206 
207     pfd = pango_font_description_from_string(font_name);
208     desktop->priv->system_font_size = pango_font_description_get_size(pfd);
209     /* FIXME: this seems backwards from the documentation */
210     if(!pango_font_description_get_size_is_absolute(pfd)) {
211         XF_DEBUG("dividing by PANGO_SCALE");
212         desktop->priv->system_font_size /= PANGO_SCALE;
213     }
214     XF_DEBUG("system font size is %.05f", desktop->priv->system_font_size);
215 
216     g_free(font_name);
217     pango_font_description_free(pfd);
218 
219     return desktop->priv->system_font_size;
220 }
221 
222 static void
xfce_desktop_setup_icon_view(XfceDesktop * desktop)223 xfce_desktop_setup_icon_view(XfceDesktop *desktop)
224 {
225     XfdesktopIconViewManager *manager = NULL;
226 
227     switch(desktop->priv->icons_style) {
228         case XFCE_DESKTOP_ICON_STYLE_NONE:
229             /* nada */
230             break;
231 
232         case XFCE_DESKTOP_ICON_STYLE_WINDOWS:
233             manager = xfdesktop_window_icon_manager_new(desktop->priv->gscreen);
234             break;
235 
236 #ifdef ENABLE_FILE_ICONS
237         case XFCE_DESKTOP_ICON_STYLE_FILES:
238             {
239                 GFile *file;
240                 const gchar *desktop_path;
241 
242                 desktop_path = g_get_user_special_dir(G_USER_DIRECTORY_DESKTOP);
243                 file = g_file_new_for_path(desktop_path);
244                 manager = xfdesktop_file_icon_manager_new(file, desktop->priv->channel);
245                 g_object_unref(file);
246             }
247             break;
248 #endif
249 
250         default:
251             g_critical("Unusable XfceDesktopIconStyle: %d.  Unable to " \
252                        "display desktop icons.",
253                        desktop->priv->icons_style);
254             break;
255     }
256 
257     if(manager) {
258         xfce_desktop_ensure_system_font_size(desktop);
259 
260         desktop->priv->icon_view = xfdesktop_icon_view_new(manager);
261         /* If the user set a custom font size, use it. Otherwise use the system
262          * font size */
263         xfdesktop_icon_view_set_font_size(XFDESKTOP_ICON_VIEW(desktop->priv->icon_view),
264                                           (!desktop->priv->icons_font_size_set)
265                                           ? desktop->priv->system_font_size
266                                           : desktop->priv->icons_font_size);
267         if(desktop->priv->icons_size > 0) {
268             xfdesktop_icon_view_set_icon_size(XFDESKTOP_ICON_VIEW(desktop->priv->icon_view),
269                                               desktop->priv->icons_size);
270         }
271         xfdesktop_icon_view_set_center_text (XFDESKTOP_ICON_VIEW(desktop->priv->icon_view),
272                                              desktop->priv->icons_center_text);
273 
274         gtk_widget_show(desktop->priv->icon_view);
275         gtk_container_add(GTK_CONTAINER(desktop), desktop->priv->icon_view);
276 
277         xfdesktop_icon_view_set_primary(XFDESKTOP_ICON_VIEW(desktop->priv->icon_view),
278                                         desktop->priv->primary);
279 
280         if(desktop->priv->icons_style == XFCE_DESKTOP_ICON_STYLE_FILES)
281             g_signal_connect(G_OBJECT(manager), "hidden-state-changed",
282                              G_CALLBACK(hidden_state_changed_cb), desktop);
283     }
284 
285     gtk_widget_queue_draw(GTK_WIDGET(desktop));
286 }
287 #endif
288 
289 static void
set_imgfile_root_property(XfceDesktop * desktop,const gchar * filename,gint monitor)290 set_imgfile_root_property(XfceDesktop *desktop, const gchar *filename,
291                           gint monitor)
292 {
293     GdkDisplay *display;
294     gchar property_name[128];
295 
296     display = gdk_screen_get_display(desktop->priv->gscreen);
297     gdk_x11_display_error_trap_push(display);
298 
299     g_snprintf(property_name, 128, XFDESKTOP_IMAGE_FILE_FMT, monitor);
300     if(filename) {
301         gdk_property_change(gdk_screen_get_root_window(desktop->priv->gscreen),
302                             gdk_atom_intern(property_name, FALSE),
303                             gdk_x11_xatom_to_atom(XA_STRING), 8,
304                             GDK_PROP_MODE_REPLACE,
305                             (guchar *)filename, strlen(filename)+1);
306     } else {
307         gdk_property_delete(gdk_screen_get_root_window(desktop->priv->gscreen),
308                             gdk_atom_intern(property_name, FALSE));
309     }
310 
311     gdk_x11_display_error_trap_pop_ignored(display);
312 }
313 
314 static void
set_real_root_window_surface(GdkScreen * gscreen,cairo_surface_t * surface)315 set_real_root_window_surface(GdkScreen *gscreen,
316                              cairo_surface_t *surface)
317 {
318 #ifndef DISABLE_FOR_BUG7442
319     Window xid;
320     GdkDisplay *display;
321     GdkWindow *groot;
322     cairo_pattern_t *pattern;
323 
324     groot = gdk_screen_get_root_window(gscreen);
325     xid = GDK_WINDOW_XID(groot);
326 
327     display = gdk_screen_get_display(gscreen);
328     gdk_x11_display_error_trap_push(display);
329 
330     /* set root property for transparent Eterms */
331     gdk_property_change(groot,
332             gdk_atom_intern("_XROOTPMAP_ID", FALSE),
333             gdk_atom_intern("PIXMAP", FALSE), 32,
334             GDK_PROP_MODE_REPLACE, (guchar *)&xid, 1);
335     /* and set the root window's BG surface, because aterm is somewhat lame. */
336     pattern = cairo_pattern_create_for_surface(surface);
337 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
338     gdk_window_set_background_pattern(groot, pattern);
339 G_GNUC_END_IGNORE_DEPRECATIONS
340     cairo_pattern_destroy(pattern);
341     /* there really should be a standard for this crap... */
342 
343     gdk_x11_display_error_trap_pop_ignored(display);
344 #endif
345 }
346 
347 static cairo_surface_t *
create_bg_surface(GdkScreen * gscreen,gpointer user_data)348 create_bg_surface(GdkScreen *gscreen, gpointer user_data)
349 {
350     XfceDesktop *desktop = user_data;
351     cairo_pattern_t *pattern;
352     gint w, h;
353 
354     TRACE("entering");
355 
356     g_return_val_if_fail(XFCE_IS_DESKTOP(desktop), NULL);
357 
358     /* If the workspaces haven't been created yet there's no need to do the
359      * background surface */
360     if(desktop->priv->workspaces == NULL) {
361         XF_DEBUG("exiting, desktop->priv->workspaces == NULL");
362         return NULL;
363     }
364 
365     TRACE("really entering");
366 
367     xfdesktop_get_screen_dimensions (gscreen, &w, &h);
368     gtk_widget_set_size_request(GTK_WIDGET(desktop), w, h);
369     gtk_window_resize(GTK_WINDOW(desktop), w, h);
370 
371     if(desktop->priv->bg_surface)
372         cairo_surface_destroy(desktop->priv->bg_surface);
373     desktop->priv->bg_surface = gdk_window_create_similar_surface(
374                                     gtk_widget_get_window(GTK_WIDGET(desktop)),
375                                                           CAIRO_CONTENT_COLOR_ALPHA, w, h);
376 
377     pattern = cairo_pattern_create_for_surface(desktop->priv->bg_surface);
378 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
379     gdk_window_set_background_pattern(gtk_widget_get_window(GTK_WIDGET(desktop)), pattern);
380 G_GNUC_END_IGNORE_DEPRECATIONS
381     cairo_pattern_destroy(pattern);
382 
383     return desktop->priv->bg_surface;
384 }
385 
386 static void
set_accountsservice_user_bg(const gchar * background)387 set_accountsservice_user_bg(const gchar *background)
388 {
389     GDBusConnection *bus;
390     GVariant *variant;
391     GError *error = NULL;
392     gchar *object_path = NULL;
393 
394     bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
395     if (bus == NULL) {
396         g_warning ("Failed to get system bus: %s", error->message);
397         g_error_free (error);
398         return;
399     }
400 
401     variant = g_dbus_connection_call_sync (bus,
402                                            "org.freedesktop.Accounts",
403                                            "/org/freedesktop/Accounts",
404                                            "org.freedesktop.Accounts",
405                                            "FindUserByName",
406                                            g_variant_new ("(s)", g_get_user_name ()),
407                                            G_VARIANT_TYPE ("(o)"),
408                                            G_DBUS_CALL_FLAGS_NONE,
409                                            -1,
410                                            NULL,
411                                            &error);
412 
413     if (variant == NULL) {
414         DBG("Could not contact accounts service to look up '%s': %s",
415             g_get_user_name (), error->message);
416         g_error_free(error);
417         g_object_unref (bus);
418         return;
419     }
420 
421     g_variant_get(variant, "(o)", &object_path);
422     g_variant_unref(variant);
423 
424     variant = g_dbus_connection_call_sync (bus,
425                                            "org.freedesktop.Accounts",
426                                            object_path,
427                                            "org.freedesktop.DBus.Properties",
428                                            "Set",
429                                            g_variant_new ("(ssv)",
430                                                           "org.freedesktop.DisplayManager.AccountsService",
431                                                           "BackgroundFile",
432                                                           g_variant_new_string (background ? background : "")),
433                                            G_VARIANT_TYPE ("()"),
434                                            G_DBUS_CALL_FLAGS_NONE,
435                                            -1,
436                                            NULL,
437                                            &error);
438     if (variant != NULL) {
439         g_variant_unref (variant);
440     } else {
441         g_warning ("Failed to set the background '%s': %s", background, error->message);
442         g_clear_error (&error);
443     }
444 
445     g_object_unref (bus);
446 }
447 
448 static void
backdrop_changed_cb(XfceBackdrop * backdrop,gpointer user_data)449 backdrop_changed_cb(XfceBackdrop *backdrop, gpointer user_data)
450 {
451     XfceDesktop *desktop = XFCE_DESKTOP(user_data);
452     cairo_surface_t *surface = desktop->priv->bg_surface;
453     GdkScreen *gscreen = desktop->priv->gscreen;
454     GdkDisplay *display;
455     gchar *new_filename = NULL;
456     GdkRectangle rect;
457     cairo_region_t *clip_region = NULL;
458     gint i, monitor = -1, current_workspace;
459 #ifdef G_ENABLE_DEBUG
460     gchar *monitor_name = NULL;
461 #endif
462 
463     TRACE("entering");
464 
465     g_return_if_fail(XFCE_IS_DESKTOP(desktop));
466 
467     if(!XFCE_IS_BACKDROP(backdrop))
468         return;
469 
470     if(desktop->priv->updates_frozen || !gtk_widget_get_realized(GTK_WIDGET(desktop)))
471         return;
472 
473     TRACE("really entering");
474 
475     display = gdk_display_get_default();
476     current_workspace = xfce_desktop_get_current_workspace(desktop);
477 
478     /* Find out which monitor the backdrop is on */
479     for(i = 0; i < xfce_desktop_get_n_monitors(desktop); i++) {
480         if(backdrop == xfce_workspace_get_backdrop(desktop->priv->workspaces[current_workspace], i)) {
481             monitor = i;
482             break;
483         }
484     }
485     if(monitor == -1)
486         return;
487     /* notify Accountsservice of the new bg (only for monitor0) */
488     if(monitor == 0)
489     {
490         if (xfce_desktop_get_current_workspace(desktop) == 0)
491         {
492             new_filename = g_strdup(xfce_backdrop_get_image_filename(backdrop));
493             if (g_strcmp0(desktop->priv->last_filename, new_filename) != 0)
494             {
495                 desktop->priv->last_filename = g_strdup(new_filename);
496                 set_accountsservice_user_bg(xfce_backdrop_get_image_filename(backdrop));
497             }
498             g_free(new_filename);
499         }
500     }
501 
502 #ifdef G_ENABLE_DEBUG
503     monitor_name = gdk_screen_get_monitor_plug_name(gscreen, monitor);
504 
505     XF_DEBUG("backdrop changed for workspace %d, monitor %d (%s)", current_workspace, monitor, monitor_name);
506 
507     g_free(monitor_name);
508 #endif
509 
510     if(xfce_desktop_get_n_monitors(desktop) > 1
511        && xfce_workspace_get_xinerama_stretch(desktop->priv->workspaces[current_workspace])) {
512         /* Spanning screens */
513         GdkRectangle monitor_rect;
514 
515         gdk_monitor_get_geometry(gdk_display_get_monitor(display, 0),
516                                  &rect);
517         /* Get the lowest x and y value for all the monitors in
518          * case none of them start at 0,0 for whatever reason.
519          */
520         for(i = 1; i < xfce_desktop_get_n_monitors(desktop); i++) {
521             gdk_monitor_get_geometry(gdk_display_get_monitor(display, i),
522                                      &monitor_rect);
523 
524             if(monitor_rect.x < rect.x)
525                 rect.x = monitor_rect.x;
526             if(monitor_rect.y < rect.y)
527                 rect.y = monitor_rect.y;
528         }
529 
530         xfdesktop_get_screen_dimensions (gscreen, &rect.width, &rect.height);
531         XF_DEBUG("xinerama_stretch x %d, y %d, width %d, height %d",
532                  rect.x, rect.y, rect.width, rect.height);
533     } else {
534         gdk_monitor_get_geometry(gdk_display_get_monitor(display, monitor),
535                                  &rect);
536         XF_DEBUG("monitor x %d, y %d, width %d, height %d",
537                  rect.x, rect.y, rect.width, rect.height);
538     }
539 
540     xfce_backdrop_set_size(backdrop, rect.width, rect.height);
541 
542     if(monitor > 0
543        && !xfce_workspace_get_xinerama_stretch(desktop->priv->workspaces[current_workspace])) {
544         clip_region = cairo_region_create_rectangle(&rect);
545 
546         XF_DEBUG("clip_region: x: %d, y: %d, w: %d, h: %d",
547                  rect.x, rect.y, rect.width, rect.height);
548 
549         /* If we are not monitor 0 on a multi-monitor setup we need to subtract
550          * all the previous monitor regions so we don't draw over them. This
551          * should prevent the overlap and double backdrop drawing bugs.
552          */
553         for(i = 0; i < monitor; i++) {
554             GdkRectangle previous_monitor;
555             cairo_region_t *previous_region;
556 
557             gdk_monitor_get_geometry(gdk_display_get_monitor(display, i),
558                                      &previous_monitor);
559 
560             XF_DEBUG("previous_monitor: x: %d, y: %d, w: %d, h: %d",
561                      previous_monitor.x, previous_monitor.y,
562                      previous_monitor.width, previous_monitor.height);
563 
564             previous_region = cairo_region_create_rectangle(&previous_monitor);
565 
566             cairo_region_subtract(clip_region, previous_region);
567 
568             cairo_region_destroy(previous_region);
569         }
570     }
571 
572     if(clip_region != NULL) {
573         /* Update the area to redraw to limit the icons/area painted */
574         cairo_region_get_extents(clip_region, &rect);
575         XF_DEBUG("area to update: x: %d, y: %d, w: %d, h: %d",
576                  rect.x, rect.y, rect.width, rect.height);
577     }
578 
579     if(rect.width != 0 && rect.height != 0) {
580         /* get the composited backdrop pixbuf */
581         GdkPixbuf *pix = xfce_backdrop_get_pixbuf(backdrop);
582         cairo_t *cr;
583 
584         /* create the backdrop if needed */
585         if(!pix) {
586             xfce_backdrop_generate_async(backdrop);
587 
588             if(clip_region != NULL)
589                 cairo_region_destroy(clip_region);
590 
591             return;
592         }
593 
594         /* Create the background surface if it isn't already */
595         if(!desktop->priv->bg_surface) {
596             surface = create_bg_surface(gscreen, desktop);
597 
598             if(!surface) {
599                 g_object_unref(pix);
600 
601                 if(clip_region != NULL)
602                     cairo_region_destroy(clip_region);
603 
604                 return;
605             }
606         }
607 
608         cr = cairo_create(surface);
609         gdk_cairo_set_source_pixbuf(cr, pix, rect.x, rect.y);
610 
611         /* clip the area so we don't draw over a previous wallpaper */
612         if(clip_region != NULL) {
613             gdk_cairo_region(cr, clip_region);
614             cairo_clip(cr);
615         }
616 
617         cairo_paint(cr);
618 
619         /* tell gtk to redraw the repainted area */
620         gtk_widget_queue_draw_area(GTK_WIDGET(desktop), rect.x, rect.y,
621                                    rect.width, rect.height);
622 
623         set_imgfile_root_property(desktop,
624                                   xfce_backdrop_get_image_filename(backdrop),
625                                   monitor);
626 
627         /* do this again so apps watching the root win notice the update */
628         set_real_root_window_surface(gscreen, surface);
629 
630         g_object_unref(G_OBJECT(pix));
631         cairo_destroy(cr);
632         gtk_widget_show(GTK_WIDGET(desktop));
633     }
634 
635     if(clip_region != NULL)
636         cairo_region_destroy(clip_region);
637 }
638 
639 static void
screen_size_changed_cb(GdkScreen * gscreen,gpointer user_data)640 screen_size_changed_cb(GdkScreen *gscreen, gpointer user_data)
641 {
642     XfceDesktop *desktop = user_data;
643     gint current_workspace;
644 
645     TRACE("entering");
646 
647     current_workspace = xfce_desktop_get_current_workspace(desktop);
648 
649     if(desktop->priv->nworkspaces <= current_workspace)
650         return;
651 
652     if(current_workspace < 0)
653         return;
654 
655     /* release the bg_surface since the dimensions may have changed */
656     if(desktop->priv->bg_surface) {
657         cairo_surface_destroy(desktop->priv->bg_surface);
658         desktop->priv->bg_surface = NULL;
659     }
660 
661     /* special case for 1 backdrop to handle xinerama stretching */
662     if(xfce_workspace_get_xinerama_stretch(desktop->priv->workspaces[current_workspace])) {
663        backdrop_changed_cb(xfce_workspace_get_backdrop(desktop->priv->workspaces[current_workspace], 0), desktop);
664     } else {
665         gint i;
666 
667         for(i = 0; i < xfce_desktop_get_n_monitors(desktop); i++) {
668             XfceBackdrop *current_backdrop;
669             current_backdrop = xfce_workspace_get_backdrop(desktop->priv->workspaces[current_workspace], i);
670             backdrop_changed_cb(current_backdrop, desktop);
671         }
672     }
673 }
674 
675 static void
screen_composited_changed_cb(GdkScreen * gscreen,gpointer user_data)676 screen_composited_changed_cb(GdkScreen *gscreen,
677                              gpointer user_data)
678 {
679     TRACE("entering");
680     /* fake a screen size changed, so the background is properly set */
681     screen_size_changed_cb(gscreen, user_data);
682 }
683 
684 static void
xfce_desktop_monitors_changed(GdkScreen * gscreen,gpointer user_data)685 xfce_desktop_monitors_changed(GdkScreen *gscreen,
686                               gpointer user_data)
687 {
688     XfceDesktop *desktop = XFCE_DESKTOP(user_data);
689     gint i;
690 
691     TRACE("entering");
692 
693     /* Update the workspaces */
694     for(i = 0; i < desktop->priv->nworkspaces; i++) {
695         xfce_workspace_monitors_changed(desktop->priv->workspaces[i],
696                                         gscreen);
697     }
698 
699     /* fake a screen size changed, so the background is properly set */
700     screen_size_changed_cb(gscreen, user_data);
701 }
702 
703 static void
workspace_backdrop_changed_cb(XfceWorkspace * workspace,XfceBackdrop * backdrop,gpointer user_data)704 workspace_backdrop_changed_cb(XfceWorkspace *workspace,
705                               XfceBackdrop  *backdrop,
706                               gpointer user_data)
707 {
708     XfceDesktop *desktop = XFCE_DESKTOP(user_data);
709     gint current_workspace = 0, monitor = 0, i;
710 
711     TRACE("entering");
712 
713     g_return_if_fail(XFCE_IS_WORKSPACE(workspace) && XFCE_IS_BACKDROP(backdrop));
714 
715     current_workspace = xfce_desktop_get_current_workspace(desktop);
716 
717     /* Find out which monitor the backdrop is on */
718     for(i = 0; i < xfce_desktop_get_n_monitors(desktop); i++) {
719         if(backdrop == xfce_workspace_get_backdrop(desktop->priv->workspaces[current_workspace], i)) {
720             monitor = i;
721             break;
722         }
723     }
724 
725     if(xfce_desktop_get_current_workspace(desktop) == xfce_workspace_get_workspace_num(workspace)) {
726         /* Update the backdrop!
727          * In spanning mode, ignore updates to monitors other than the primary
728          */
729         if(!xfce_workspace_get_xinerama_stretch(workspace) || monitor == 0) {
730             backdrop_changed_cb(backdrop, user_data);
731         }
732     }
733 }
734 
735 static void
workspace_changed_cb(WnckScreen * wnck_screen,WnckWorkspace * previously_active_space,gpointer user_data)736 workspace_changed_cb(WnckScreen *wnck_screen,
737                      WnckWorkspace *previously_active_space,
738                      gpointer user_data)
739 {
740     XfceDesktop *desktop = XFCE_DESKTOP(user_data);
741     gint current_workspace, new_workspace, i;
742     XfceBackdrop *backdrop;
743 
744     TRACE("entering");
745 
746     current_workspace = desktop->priv->current_workspace;
747     new_workspace = xfce_desktop_get_current_workspace(desktop);
748 
749     if(desktop->priv->current_workspace_initialized && new_workspace == current_workspace)
750         return;
751     if(new_workspace < 0 || new_workspace >= desktop->priv->nworkspaces)
752         return;
753 
754     desktop->priv->current_workspace = new_workspace;
755     desktop->priv->current_workspace_initialized = TRUE;
756 
757     XF_DEBUG("current_workspace %d, new_workspace %d",
758              current_workspace, new_workspace);
759 
760     for(i = 0; i < xfce_desktop_get_n_monitors(desktop); i++) {
761         backdrop = xfce_workspace_get_backdrop(desktop->priv->workspaces[new_workspace], i);
762         /* update it */
763         backdrop_changed_cb(backdrop, user_data);
764 
765         /* When we're spanning screens we only care about the first monitor */
766         if(xfce_workspace_get_xinerama_stretch(desktop->priv->workspaces[new_workspace]))
767             break;
768     }
769 }
770 
771 static void
workspace_created_cb(WnckScreen * wnck_screen,WnckWorkspace * new_workspace,gpointer user_data)772 workspace_created_cb(WnckScreen *wnck_screen,
773                      WnckWorkspace *new_workspace,
774                      gpointer user_data)
775 {
776     XfceDesktop *desktop = XFCE_DESKTOP(user_data);
777     gint nlast_workspace;
778     TRACE("entering");
779 
780     nlast_workspace = desktop->priv->nworkspaces;
781 
782     /* add one more workspace */
783     desktop->priv->nworkspaces = nlast_workspace + 1;
784 
785     /* allocate size for it */
786     desktop->priv->workspaces = g_realloc(desktop->priv->workspaces,
787                                           desktop->priv->nworkspaces * sizeof(XfceWorkspace *));
788 
789     /* create the new workspace and set it up */
790     desktop->priv->workspaces[nlast_workspace] = xfce_workspace_new(desktop->priv->gscreen,
791                                                                     desktop->priv->channel,
792                                                                     desktop->priv->property_prefix,
793                                                                     nlast_workspace);
794 
795     xfce_workspace_monitors_changed(desktop->priv->workspaces[nlast_workspace],
796                                     desktop->priv->gscreen);
797 
798     g_signal_connect(desktop->priv->workspaces[nlast_workspace],
799                      "workspace-backdrop-changed",
800                      G_CALLBACK(workspace_backdrop_changed_cb), desktop);
801 }
802 
803 static void
workspace_destroyed_cb(WnckScreen * wnck_screen,WnckWorkspace * old_workspace,gpointer user_data)804 workspace_destroyed_cb(WnckScreen *wnck_screen,
805                      WnckWorkspace *old_workspace,
806                      gpointer user_data)
807 {
808     XfceDesktop *desktop = XFCE_DESKTOP(user_data);
809     gint nlast_workspace;
810     TRACE("entering");
811 
812     g_return_if_fail(XFCE_IS_DESKTOP(desktop));
813     g_return_if_fail(desktop->priv->nworkspaces - 1 >= 0);
814     g_return_if_fail(XFCE_IS_WORKSPACE(desktop->priv->workspaces[desktop->priv->nworkspaces-1]));
815 
816     nlast_workspace = desktop->priv->nworkspaces - 1;
817 
818     g_signal_handlers_disconnect_by_func(desktop->priv->workspaces[nlast_workspace],
819                                          G_CALLBACK(workspace_backdrop_changed_cb),
820                                          desktop);
821 
822     g_object_unref(desktop->priv->workspaces[nlast_workspace]);
823 
824     /* Remove one workspace */
825     desktop->priv->nworkspaces = nlast_workspace;
826 
827     /* deallocate it */
828     desktop->priv->workspaces = g_realloc(desktop->priv->workspaces,
829                                           desktop->priv->nworkspaces * sizeof(XfceWorkspace *));
830 
831     /* Make sure we stay within bounds now that we removed a workspace */
832     if(desktop->priv->current_workspace > desktop->priv->nworkspaces)
833         desktop->priv->current_workspace = desktop->priv->nworkspaces;
834 }
835 
836 static void
screen_set_selection(XfceDesktop * desktop)837 screen_set_selection(XfceDesktop *desktop)
838 {
839     Window xwin;
840     gint xscreen;
841     gchar selection_name[100], common_selection_name[32];
842     Atom selection_atom, common_selection_atom, manager_atom;
843 
844     xwin = GDK_WINDOW_XID(gtk_widget_get_window(GTK_WIDGET(desktop)));
845     xscreen = gdk_x11_screen_get_screen_number(desktop->priv->gscreen);
846 
847     g_snprintf(selection_name, 100, XFDESKTOP_SELECTION_FMT, xscreen);
848     selection_atom = XInternAtom(gdk_x11_get_default_xdisplay(), selection_name, False);
849     manager_atom = XInternAtom(gdk_x11_get_default_xdisplay(), "MANAGER", False);
850 
851     g_snprintf(common_selection_name, 32, "_NET_DESKTOP_MANAGER_S%d", xscreen);
852     common_selection_atom = XInternAtom(gdk_x11_get_default_xdisplay(), common_selection_name, False);
853 
854     /* the previous check in src/main.c occurs too early, so workaround by
855      * adding this one. */
856    if(XGetSelectionOwner(gdk_x11_get_default_xdisplay(), selection_atom) != None) {
857        g_critical("%s: already running, quitting.", PACKAGE);
858        exit(0);
859    }
860 
861     /* Check that _NET_DESKTOP_MANAGER_S%d isn't set, as it means another
862      * desktop manager is running, e.g. nautilus */
863     if(XGetSelectionOwner (gdk_x11_get_default_xdisplay(), common_selection_atom) != None) {
864         g_critical("%s: another desktop manager is running.", PACKAGE);
865         exit(1);
866     }
867 
868     XSelectInput(gdk_x11_get_default_xdisplay(), xwin, PropertyChangeMask | ButtonPressMask);
869     XSetSelectionOwner(gdk_x11_get_default_xdisplay(), selection_atom, xwin, GDK_CURRENT_TIME);
870     XSetSelectionOwner(gdk_x11_get_default_xdisplay(), common_selection_atom, xwin, GDK_CURRENT_TIME);
871 
872     /* Check to see if we managed to claim the selection. If not,
873      * we treat it as if we got it then immediately lost it */
874     if(XGetSelectionOwner(gdk_x11_get_default_xdisplay(), selection_atom) == xwin) {
875         XClientMessageEvent xev;
876         Window xroot = GDK_WINDOW_XID(gdk_screen_get_root_window(desktop->priv->gscreen));
877 
878         xev.type = ClientMessage;
879         xev.window = xroot;
880         xev.message_type = manager_atom;
881         xev.format = 32;
882         xev.data.l[0] = GDK_CURRENT_TIME;
883         xev.data.l[1] = selection_atom;
884         xev.data.l[2] = xwin;
885         xev.data.l[3] = 0;    /* manager specific data */
886         xev.data.l[4] = 0;    /* manager specific data */
887 
888         XSendEvent(gdk_x11_get_default_xdisplay(), xroot, False, StructureNotifyMask, (XEvent *)&xev);
889     } else {
890         g_error("%s: could not set selection ownership", PACKAGE);
891         exit(1);
892     }
893 }
894 
895 
896 
897 /* gobject-related functions */
898 
899 
G_DEFINE_TYPE_WITH_PRIVATE(XfceDesktop,xfce_desktop,GTK_TYPE_WINDOW)900 G_DEFINE_TYPE_WITH_PRIVATE(XfceDesktop, xfce_desktop, GTK_TYPE_WINDOW)
901 
902 
903 static void
904 xfce_desktop_class_init(XfceDesktopClass *klass)
905 {
906     GObjectClass *gobject_class = (GObjectClass *)klass;
907     GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
908 
909     gobject_class->finalize = xfce_desktop_finalize;
910     gobject_class->set_property = xfce_desktop_set_property;
911     gobject_class->get_property = xfce_desktop_get_property;
912 
913     widget_class->realize = xfce_desktop_realize;
914     widget_class->unrealize = xfce_desktop_unrealize;
915     widget_class->button_press_event = xfce_desktop_button_press_event;
916     widget_class->button_release_event = xfce_desktop_button_release_event;
917     widget_class->draw = xfce_desktop_draw;
918     widget_class->delete_event = xfce_desktop_delete_event;
919     widget_class->popup_menu = xfce_desktop_popup_menu;
920     widget_class->style_updated = xfce_desktop_style_updated;
921 
922     signals[SIG_POPULATE_ROOT_MENU] = g_signal_new("populate-root-menu",
923                                                    XFCE_TYPE_DESKTOP,
924                                                    G_SIGNAL_RUN_LAST,
925                                                    G_STRUCT_OFFSET(XfceDesktopClass,
926                                                                    populate_root_menu),
927                                                    NULL, NULL,
928                                                    g_cclosure_marshal_VOID__OBJECT,
929                                                    G_TYPE_NONE, 1,
930                                                    GTK_TYPE_MENU_SHELL);
931 
932     signals[SIG_POPULATE_SECONDARY_ROOT_MENU] = g_signal_new("populate-secondary-root-menu",
933                                                              XFCE_TYPE_DESKTOP,
934                                                              G_SIGNAL_RUN_LAST,
935                                                              G_STRUCT_OFFSET(XfceDesktopClass,
936                                                                              populate_secondary_root_menu),
937                                                              NULL, NULL,
938                                                              g_cclosure_marshal_VOID__OBJECT,
939                                                              G_TYPE_NONE, 1,
940                                                              GTK_TYPE_MENU_SHELL);
941 
942 #define XFDESKTOP_PARAM_FLAGS  (G_PARAM_READWRITE \
943                                 | G_PARAM_CONSTRUCT \
944                                 | G_PARAM_STATIC_NAME \
945                                 | G_PARAM_STATIC_NICK \
946                                 | G_PARAM_STATIC_BLURB)
947 
948 #ifdef ENABLE_DESKTOP_ICONS
949     g_object_class_install_property(gobject_class, PROP_ICON_STYLE,
950                                     g_param_spec_enum("icon-style",
951                                                       "icon style",
952                                                       "icon style",
953                                                       XFCE_TYPE_DESKTOP_ICON_STYLE,
954 #ifdef ENABLE_FILE_ICONS
955                                                       XFCE_DESKTOP_ICON_STYLE_FILES,
956 #else
957                                                       XFCE_DESKTOP_ICON_STYLE_WINDOWS,
958 #endif /* ENABLE_FILE_ICONS */
959                                                       XFDESKTOP_PARAM_FLAGS));
960 
961     g_object_class_install_property(gobject_class, PROP_ICON_SIZE,
962                                     g_param_spec_uint("icon-size",
963                                                       "icon size",
964                                                       "icon size",
965                                                       8, 192, DEFAULT_ICON_SIZE,
966                                                       XFDESKTOP_PARAM_FLAGS));
967 
968     g_object_class_install_property(gobject_class, PROP_ICON_ON_PRIMARY,
969                                     g_param_spec_boolean("primary",
970                                                          "primary",
971                                                          "primary",
972                                                          FALSE,
973                                                          XFDESKTOP_PARAM_FLAGS));
974 
975     g_object_class_install_property(gobject_class, PROP_ICON_FONT_SIZE,
976                                     g_param_spec_uint("icon-font-size",
977                                                       "icon font size",
978                                                       "icon font size",
979                                                       0, 144, 12,
980                                                       XFDESKTOP_PARAM_FLAGS));
981 
982     g_object_class_install_property(gobject_class, PROP_ICON_FONT_SIZE_SET,
983                                     g_param_spec_boolean("icon-font-size-set",
984                                                          "icon font size set",
985                                                          "icon font size set",
986                                                          FALSE,
987                                                          XFDESKTOP_PARAM_FLAGS));
988 
989     g_object_class_install_property(gobject_class, PROP_ICON_CENTER_TEXT,
990                                     g_param_spec_boolean("icon-center-text",
991                                                          "icon center text",
992                                                          "icon center text",
993                                                          TRUE,
994                                                          XFDESKTOP_PARAM_FLAGS));
995 
996 #endif /* ENABLE_DESKTOP_ICONS */
997 
998     g_object_class_install_property(gobject_class, PROP_SINGLE_WORKSPACE_MODE,
999                                     g_param_spec_boolean("single-workspace-mode",
1000                                                          "single-workspace-mode",
1001                                                          "single-workspace-mode",
1002                                                          TRUE,
1003                                                          XFDESKTOP_PARAM_FLAGS));
1004 
1005     g_object_class_install_property(gobject_class, PROP_SINGLE_WORKSPACE_NUMBER,
1006                                     g_param_spec_int("single-workspace-number",
1007                                                      "single-workspace-number",
1008                                                      "single-workspace-number",
1009                                                      0, G_MAXINT16, 0,
1010                                                      XFDESKTOP_PARAM_FLAGS));
1011 
1012 #undef XFDESKTOP_PARAM_FLAGS
1013 }
1014 
1015 static void
xfce_desktop_init(XfceDesktop * desktop)1016 xfce_desktop_init(XfceDesktop *desktop)
1017 {
1018     desktop->priv = xfce_desktop_get_instance_private(desktop);
1019 
1020     gtk_window_set_type_hint(GTK_WINDOW(desktop), GDK_WINDOW_TYPE_HINT_DESKTOP);
1021     /* Accept focus is needed for the menu pop up either by the menu key on
1022      * the keyboard or Shift+F10. */
1023     gtk_window_set_accept_focus(GTK_WINDOW(desktop), TRUE);
1024     /* Can focus is needed for the gtk_grab_add/remove commands */
1025     gtk_widget_set_can_focus(GTK_WIDGET(desktop), TRUE);
1026     gtk_window_set_resizable(GTK_WINDOW(desktop), FALSE);
1027 }
1028 
1029 static void
xfce_desktop_finalize(GObject * object)1030 xfce_desktop_finalize(GObject *object)
1031 {
1032     XfceDesktop *desktop = XFCE_DESKTOP(object);
1033 
1034     g_object_unref(G_OBJECT(desktop->priv->channel));
1035     g_free(desktop->priv->property_prefix);
1036 
1037 #ifdef ENABLE_DESKTOP_ICONS
1038     if(desktop->priv->style_refresh_timer != 0)
1039         g_source_remove(desktop->priv->style_refresh_timer);
1040 #endif
1041 
1042     G_OBJECT_CLASS(xfce_desktop_parent_class)->finalize(object);
1043 }
1044 
1045 static void
xfce_desktop_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)1046 xfce_desktop_set_property(GObject *object,
1047                           guint property_id,
1048                           const GValue *value,
1049                           GParamSpec *pspec)
1050 {
1051     XfceDesktop *desktop = XFCE_DESKTOP(object);
1052 
1053     switch(property_id) {
1054 #ifdef ENABLE_DESKTOP_ICONS
1055         case PROP_ICON_STYLE:
1056             xfce_desktop_set_icon_style(desktop,
1057                                         g_value_get_enum(value));
1058             break;
1059 
1060         case PROP_ICON_SIZE:
1061             xfce_desktop_set_icon_size(desktop,
1062                                        g_value_get_uint(value));
1063             break;
1064 
1065         case PROP_ICON_ON_PRIMARY:
1066             xfce_desktop_set_primary(desktop,
1067                                        g_value_get_boolean(value));
1068             break;
1069 
1070         case PROP_ICON_FONT_SIZE:
1071             xfce_desktop_set_icon_font_size(desktop,
1072                                             g_value_get_uint(value));
1073             break;
1074 
1075         case PROP_ICON_FONT_SIZE_SET:
1076             xfce_desktop_set_use_icon_font_size(desktop,
1077                                                 g_value_get_boolean(value));
1078             break;
1079 
1080         case PROP_ICON_CENTER_TEXT:
1081             xfce_desktop_set_center_text(desktop,
1082                                          g_value_get_boolean(value));
1083             break;
1084 
1085 #endif
1086         case PROP_SINGLE_WORKSPACE_MODE:
1087             xfce_desktop_set_single_workspace_mode(desktop,
1088                                                    g_value_get_boolean(value));
1089             break;
1090 
1091         case PROP_SINGLE_WORKSPACE_NUMBER:
1092             xfce_desktop_set_single_workspace_number(desktop,
1093                                                      g_value_get_int(value));
1094             break;
1095 
1096         default:
1097             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
1098             break;
1099     }
1100 }
1101 
1102 static void
xfce_desktop_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)1103 xfce_desktop_get_property(GObject *object,
1104                           guint property_id,
1105                           GValue *value,
1106                           GParamSpec *pspec)
1107 {
1108     XfceDesktop *desktop = XFCE_DESKTOP(object);
1109 
1110     switch(property_id) {
1111 #ifdef ENABLE_DESKTOP_ICONS
1112         case PROP_ICON_STYLE:
1113             g_value_set_enum(value, desktop->priv->icons_style);
1114             break;
1115 
1116         case PROP_ICON_SIZE:
1117             g_value_set_uint(value, desktop->priv->icons_size);
1118             break;
1119 
1120         case PROP_ICON_ON_PRIMARY:
1121             g_value_set_boolean(value, desktop->priv->primary);
1122             break;
1123 
1124         case PROP_ICON_FONT_SIZE:
1125             g_value_set_uint(value, desktop->priv->icons_font_size);
1126             break;
1127 
1128         case PROP_ICON_FONT_SIZE_SET:
1129             g_value_set_boolean(value, desktop->priv->icons_font_size_set);
1130             break;
1131 
1132         case PROP_ICON_CENTER_TEXT:
1133             g_value_set_boolean(value, desktop->priv->icons_center_text);
1134             break;
1135 
1136 #endif
1137         case PROP_SINGLE_WORKSPACE_MODE:
1138             g_value_set_boolean(value, desktop->priv->single_workspace_mode);
1139             break;
1140 
1141         case PROP_SINGLE_WORKSPACE_NUMBER:
1142             g_value_set_int(value, desktop->priv->single_workspace_num);
1143             break;
1144 
1145         default:
1146             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
1147             break;
1148     }
1149 }
1150 
1151 static void
xfce_desktop_realize(GtkWidget * widget)1152 xfce_desktop_realize(GtkWidget *widget)
1153 {
1154     XfceDesktop *desktop = XFCE_DESKTOP(widget);
1155     GdkAtom atom;
1156     gint sw, sh;
1157     Window xid;
1158     GdkWindow *groot;
1159     WnckScreen *wnck_screen;
1160 
1161     TRACE("entering");
1162 
1163     gtk_window_set_screen(GTK_WINDOW(desktop), desktop->priv->gscreen);
1164     xfdesktop_get_screen_dimensions (desktop->priv->gscreen, &sw, &sh);
1165 
1166     g_signal_connect(G_OBJECT(desktop->priv->gscreen),
1167                      "monitors-changed",
1168                      G_CALLBACK(xfce_desktop_monitors_changed),
1169                      desktop);
1170 
1171     /* chain up */
1172     GTK_WIDGET_CLASS(xfce_desktop_parent_class)->realize(widget);
1173 
1174     gtk_window_set_title(GTK_WINDOW(desktop), _("Desktop"));
1175     gtk_window_set_decorated(GTK_WINDOW(desktop), FALSE);
1176     gtk_widget_set_size_request(GTK_WIDGET(desktop), sw, sh);
1177     gtk_window_move(GTK_WINDOW(desktop), 0, 0);
1178 
1179     atom = gdk_atom_intern("_NET_WM_WINDOW_TYPE_DESKTOP", FALSE);
1180     gdk_property_change(gtk_widget_get_window(GTK_WIDGET(desktop)),
1181             gdk_atom_intern("_NET_WM_WINDOW_TYPE", FALSE),
1182             gdk_atom_intern("ATOM", FALSE), 32,
1183             GDK_PROP_MODE_REPLACE, (guchar *)&atom, 1);
1184 
1185     xid = GDK_WINDOW_XID(gtk_widget_get_window(GTK_WIDGET(desktop)));
1186     groot = gdk_screen_get_root_window(desktop->priv->gscreen);
1187 
1188     gdk_property_change(groot,
1189             gdk_atom_intern("XFCE_DESKTOP_WINDOW", FALSE),
1190             gdk_atom_intern("WINDOW", FALSE), 32,
1191             GDK_PROP_MODE_REPLACE, (guchar *)&xid, 1);
1192 
1193     gdk_property_change(groot,
1194             gdk_atom_intern("NAUTILUS_DESKTOP_WINDOW_ID", FALSE),
1195             gdk_atom_intern("WINDOW", FALSE), 32,
1196             GDK_PROP_MODE_REPLACE, (guchar *)&xid, 1);
1197 
1198     screen_set_selection(desktop);
1199 
1200     wnck_screen = wnck_screen_get(gdk_x11_screen_get_screen_number(desktop->priv->gscreen));
1201     desktop->priv->wnck_screen = wnck_screen;
1202 
1203     /* Watch for single workspace setting changes */
1204     xfconf_g_property_bind(desktop->priv->channel,
1205                            SINGLE_WORKSPACE_MODE, G_TYPE_BOOLEAN,
1206                            G_OBJECT(desktop), "single-workspace-mode");
1207     xfconf_g_property_bind(desktop->priv->channel,
1208                            SINGLE_WORKSPACE_NUMBER, G_TYPE_INT,
1209                            G_OBJECT(desktop), "single-workspace-number");
1210 
1211     /* watch for workspace changes */
1212     g_signal_connect(desktop->priv->wnck_screen, "active-workspace-changed",
1213                      G_CALLBACK(workspace_changed_cb), desktop);
1214     g_signal_connect(desktop->priv->wnck_screen, "workspace-created",
1215                      G_CALLBACK(workspace_created_cb), desktop);
1216     g_signal_connect(desktop->priv->wnck_screen, "workspace-destroyed",
1217                      G_CALLBACK(workspace_destroyed_cb), desktop);
1218 
1219     /* watch for screen changes */
1220     g_signal_connect(G_OBJECT(desktop->priv->gscreen), "size-changed",
1221             G_CALLBACK(screen_size_changed_cb), desktop);
1222     g_signal_connect(G_OBJECT(desktop->priv->gscreen), "composited-changed",
1223             G_CALLBACK(screen_composited_changed_cb), desktop);
1224 
1225     gtk_widget_add_events(GTK_WIDGET(desktop), GDK_EXPOSURE_MASK);
1226 
1227 #ifdef ENABLE_DESKTOP_ICONS
1228     xfce_desktop_setup_icon_view(desktop);
1229 #endif
1230 
1231     TRACE("exiting");
1232 }
1233 
1234 static void
xfce_desktop_unrealize(GtkWidget * widget)1235 xfce_desktop_unrealize(GtkWidget *widget)
1236 {
1237     XfceDesktop *desktop = XFCE_DESKTOP(widget);
1238     GdkDisplay  *display;
1239     gint i;
1240     GdkWindow *groot;
1241     gchar property_name[128];
1242 
1243     g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1244 
1245     /* disconnect all the xfconf settings to this desktop */
1246     xfconf_g_property_unbind_all(G_OBJECT(desktop));
1247 
1248     g_signal_handlers_disconnect_by_func(G_OBJECT(desktop->priv->gscreen),
1249                                          G_CALLBACK(xfce_desktop_monitors_changed),
1250                                          desktop);
1251 
1252     if(gtk_widget_get_mapped(widget))
1253         gtk_widget_unmap(widget);
1254     gtk_widget_set_mapped(widget, FALSE);
1255 
1256     gtk_container_forall(GTK_CONTAINER(widget),
1257                          (GtkCallback)gtk_widget_unrealize,
1258                          NULL);
1259 
1260     g_signal_handlers_disconnect_by_func(G_OBJECT(desktop->priv->gscreen),
1261             G_CALLBACK(screen_size_changed_cb), desktop);
1262     g_signal_handlers_disconnect_by_func(G_OBJECT(desktop->priv->gscreen),
1263             G_CALLBACK(screen_composited_changed_cb), desktop);
1264 
1265     display = gdk_screen_get_display(desktop->priv->gscreen);
1266     gdk_x11_display_error_trap_push(display);
1267 
1268     groot = gdk_screen_get_root_window(desktop->priv->gscreen);
1269     gdk_property_delete(groot, gdk_atom_intern("XFCE_DESKTOP_WINDOW", FALSE));
1270     gdk_property_delete(groot, gdk_atom_intern("NAUTILUS_DESKTOP_WINDOW_ID", FALSE));
1271 
1272 #ifndef DISABLE_FOR_BUG7442
1273     gdk_property_delete(groot, gdk_atom_intern("_XROOTPMAP_ID", FALSE));
1274     gdk_property_delete(groot, gdk_atom_intern("ESETROOT_PMAP_ID", FALSE));
1275 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1276     gdk_window_set_background_pattern(groot, NULL);
1277 G_GNUC_END_IGNORE_DEPRECATIONS
1278 #endif
1279 
1280     if(desktop->priv->workspaces) {
1281         for(i = 0; i < desktop->priv->nworkspaces; i++) {
1282             g_snprintf(property_name, 128, XFDESKTOP_IMAGE_FILE_FMT, i);
1283             gdk_property_delete(groot, gdk_atom_intern(property_name, FALSE));
1284             g_object_unref(G_OBJECT(desktop->priv->workspaces[i]));
1285         }
1286         g_free(desktop->priv->workspaces);
1287         desktop->priv->workspaces = NULL;
1288     }
1289 
1290     gdk_display_flush(display);
1291     gdk_x11_display_error_trap_pop_ignored(display);
1292 
1293     if(desktop->priv->bg_surface) {
1294         cairo_surface_destroy(desktop->priv->bg_surface);
1295         desktop->priv->bg_surface = NULL;
1296     }
1297 
1298     gtk_window_set_icon(GTK_WINDOW(widget), NULL);
1299 
1300     g_object_unref(G_OBJECT(gtk_widget_get_window(widget)));
1301     gtk_widget_set_window(widget, NULL);
1302 
1303     gtk_selection_remove_all(widget);
1304 
1305     gtk_widget_set_realized(widget, FALSE);
1306 }
1307 
1308 static gboolean
xfce_desktop_button_press_event(GtkWidget * w,GdkEventButton * evt)1309 xfce_desktop_button_press_event(GtkWidget *w,
1310                                 GdkEventButton *evt)
1311 {
1312     guint button = evt->button;
1313     guint state = evt->state;
1314     XfceDesktop *desktop = XFCE_DESKTOP(w);
1315 
1316     DBG("entering");
1317 
1318     g_return_val_if_fail(XFCE_IS_DESKTOP(w), FALSE);
1319 
1320     if(evt->type == GDK_BUTTON_PRESS) {
1321         if(button == 3 || (button == 1 && (state & GDK_SHIFT_MASK))) {
1322 #ifdef ENABLE_DESKTOP_ICONS
1323             /* Let the icon view handle these menu pop ups */
1324             if(desktop->priv->icons_style != XFCE_DESKTOP_ICON_STYLE_NONE)
1325                 return FALSE;
1326 #endif
1327             /* no icons on the desktop, grab the focus and pop up the menu */
1328             if(!gtk_widget_has_grab(w))
1329                 gtk_grab_add(w);
1330 
1331             xfce_desktop_popup_root_menu(desktop, button, evt->time);
1332             return TRUE;
1333         } else if(button == 2 || (button == 1 && (state & GDK_SHIFT_MASK)
1334                                   && (state & GDK_CONTROL_MASK)))
1335         {
1336             /* always grab the focus and pop up the menu */
1337             if(!gtk_widget_has_grab(w))
1338                 gtk_grab_add(w);
1339 
1340             xfce_desktop_popup_secondary_root_menu(desktop, button, evt->time);
1341             return TRUE;
1342         }
1343     }
1344 
1345     return FALSE;
1346 }
1347 
1348 static gboolean
xfce_desktop_button_release_event(GtkWidget * w,GdkEventButton * evt)1349 xfce_desktop_button_release_event(GtkWidget *w,
1350                                   GdkEventButton *evt)
1351 {
1352     DBG("entering");
1353 
1354     gtk_grab_remove(w);
1355 
1356     return FALSE;
1357 }
1358 
1359 /* This function gets called when the user presses the menu key on the keyboard.
1360  * Or Shift+F10 or whatever key binding the user has chosen. */
1361 static gboolean
xfce_desktop_popup_menu(GtkWidget * w)1362 xfce_desktop_popup_menu(GtkWidget *w)
1363 {
1364     GdkEventButton *evt;
1365     guint button, etime;
1366 
1367     DBG("entering");
1368 
1369     evt = (GdkEventButton *)gtk_get_current_event();
1370     if(evt && GDK_BUTTON_PRESS == evt->type) {
1371         button = evt->button;
1372         etime = evt->time;
1373     } else {
1374         button = 0;
1375         etime = gtk_get_current_event_time();
1376     }
1377 
1378     xfce_desktop_popup_root_menu(XFCE_DESKTOP(w), button, etime);
1379 
1380     gdk_event_free((GdkEvent*)evt);
1381     return TRUE;
1382 }
1383 
1384 static gboolean
xfce_desktop_draw(GtkWidget * w,cairo_t * cr)1385 xfce_desktop_draw(GtkWidget *w,
1386                   cairo_t *cr)
1387 {
1388     GList *children, *l;
1389 
1390     /*TRACE("entering");*/
1391 
1392     children = gtk_container_get_children(GTK_CONTAINER(w));
1393     for(l = children; l; l = l->next) {
1394         gtk_container_propagate_draw(GTK_CONTAINER(w),
1395                                      GTK_WIDGET(l->data),
1396                                      cr);
1397     }
1398     g_list_free(children);
1399 
1400     return FALSE;
1401 }
1402 
1403 static gboolean
xfce_desktop_delete_event(GtkWidget * w,GdkEventAny * evt)1404 xfce_desktop_delete_event(GtkWidget *w,
1405                           GdkEventAny *evt)
1406 {
1407     if(XFCE_DESKTOP(w)->priv->session_logout_func)
1408         XFCE_DESKTOP(w)->priv->session_logout_func();
1409 
1410     return TRUE;
1411 }
1412 
1413 #ifdef ENABLE_DESKTOP_ICONS
1414 static gboolean
style_refresh_cb(gpointer user_data)1415 style_refresh_cb(gpointer user_data)
1416 {
1417     XfceDesktop *desktop = user_data;
1418     cairo_pattern_t *pattern;
1419     gdouble old_font_size;
1420 
1421     TRACE("entering");
1422 
1423     desktop->priv->style_refresh_timer = 0;
1424 
1425     g_return_val_if_fail(XFCE_IS_DESKTOP(desktop), FALSE);
1426 
1427     if(!gtk_widget_get_realized(GTK_WIDGET(desktop)))
1428         return FALSE;
1429 
1430     if(desktop->priv->workspaces == NULL)
1431         return FALSE;
1432 
1433     if(desktop->priv->bg_surface) {
1434         pattern = cairo_pattern_create_for_surface(desktop->priv->bg_surface);
1435 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1436         gdk_window_set_background_pattern(gtk_widget_get_window(GTK_WIDGET(desktop)),
1437                                           pattern);
1438 G_GNUC_END_IGNORE_DEPRECATIONS
1439         cairo_pattern_destroy(pattern);
1440     }
1441 
1442     gtk_widget_queue_draw(GTK_WIDGET(desktop));
1443 
1444     if(!desktop->priv->icon_view || !XFDESKTOP_IS_ICON_VIEW(desktop->priv->icon_view))
1445         return FALSE;
1446 
1447     /* reset the icon view style */
1448     gtk_widget_reset_style(desktop->priv->icon_view);
1449 
1450     old_font_size = desktop->priv->system_font_size;
1451     if(xfce_desktop_ensure_system_font_size(desktop) != old_font_size
1452        && desktop->priv->icon_view && !desktop->priv->icons_font_size_set)
1453     {
1454         xfdesktop_icon_view_set_font_size(XFDESKTOP_ICON_VIEW(desktop->priv->icon_view),
1455                                           desktop->priv->system_font_size);
1456     }
1457 
1458     return FALSE;
1459 }
1460 #endif
1461 
1462 static void
xfce_desktop_style_updated(GtkWidget * w)1463 xfce_desktop_style_updated(GtkWidget *w)
1464 {
1465 #ifdef ENABLE_DESKTOP_ICONS
1466     XfceDesktop *desktop = XFCE_DESKTOP(w);
1467 
1468     TRACE("entering");
1469 
1470     if(desktop->priv->style_refresh_timer != 0)
1471         g_source_remove(desktop->priv->style_refresh_timer);
1472 
1473     desktop->priv->style_refresh_timer = g_idle_add_full(G_PRIORITY_LOW,
1474                                                          style_refresh_cb,
1475                                                          desktop,
1476                                                          NULL);
1477 #endif
1478 }
1479 
1480 static void
xfce_desktop_connect_settings(XfceDesktop * desktop)1481 xfce_desktop_connect_settings(XfceDesktop *desktop)
1482 {
1483 #ifdef ENABLE_DESKTOP_ICONS
1484 #define ICONS_PREFIX "/desktop-icons/"
1485     XfconfChannel *channel = desktop->priv->channel;
1486 
1487     xfce_desktop_freeze_updates(desktop);
1488 
1489     xfconf_g_property_bind(channel, ICONS_PREFIX "style",
1490                            XFCE_TYPE_DESKTOP_ICON_STYLE,
1491                            G_OBJECT(desktop), "icon-style");
1492     xfconf_g_property_bind(channel, ICONS_PREFIX "icon-size", G_TYPE_UINT,
1493                            G_OBJECT(desktop), "icon-size");
1494     xfconf_g_property_bind(channel, ICONS_PREFIX "primary", G_TYPE_BOOLEAN,
1495                            G_OBJECT(desktop), "primary");
1496     xfconf_g_property_bind(channel, ICONS_PREFIX "font-size", G_TYPE_UINT,
1497                            G_OBJECT(desktop), "icon-font-size");
1498     xfconf_g_property_bind(channel, ICONS_PREFIX "use-custom-font-size",
1499                            G_TYPE_BOOLEAN,
1500                            G_OBJECT(desktop), "icon-font-size-set");
1501     xfconf_g_property_bind(channel, ICONS_PREFIX "center-text",
1502                            G_TYPE_BOOLEAN,
1503                            G_OBJECT(desktop), "icon-center-text");
1504 
1505     xfce_desktop_thaw_updates(desktop);
1506 #undef ICONS_PREFIX
1507 #endif
1508 }
1509 
1510 static gboolean
xfce_desktop_get_single_workspace_mode(XfceDesktop * desktop)1511 xfce_desktop_get_single_workspace_mode(XfceDesktop *desktop)
1512 {
1513     g_return_val_if_fail(XFCE_IS_DESKTOP(desktop), TRUE);
1514 
1515     return desktop->priv->single_workspace_mode;
1516 }
1517 
1518 static gint
xfce_desktop_get_current_workspace(XfceDesktop * desktop)1519 xfce_desktop_get_current_workspace(XfceDesktop *desktop)
1520 {
1521     WnckWorkspace *wnck_workspace;
1522     gint workspace_num, current_workspace;
1523 
1524     g_return_val_if_fail(XFCE_IS_DESKTOP(desktop), -1);
1525 
1526     wnck_workspace = wnck_screen_get_active_workspace(desktop->priv->wnck_screen);
1527 
1528     if(wnck_workspace != NULL) {
1529         workspace_num = wnck_workspace_get_number(wnck_workspace);
1530     } else {
1531         workspace_num = desktop->priv->nworkspaces;
1532     }
1533 
1534     /* If we're in single_workspace mode we need to return the workspace that
1535      * it was set to, if possible, otherwise return the current workspace */
1536     if(xfce_desktop_get_single_workspace_mode(desktop) &&
1537        desktop->priv->single_workspace_num < desktop->priv->nworkspaces) {
1538         current_workspace = desktop->priv->single_workspace_num;
1539     } else {
1540         current_workspace = workspace_num;
1541     }
1542 
1543     XF_DEBUG("workspace_num %d, single_workspace_num %d, current_workspace %d, max workspaces %d",
1544              workspace_num, desktop->priv->single_workspace_num, current_workspace,
1545              desktop->priv->nworkspaces);
1546 
1547     return current_workspace;
1548 }
1549 
1550 /* public api */
1551 
1552 /**
1553  * xfce_desktop_new:
1554  * @gscreen: The current #GdkScreen.
1555  * @channel: An #XfconfChannel to use for settings.
1556  * @property_prefix: String prefix for per-screen properties.
1557  *
1558  * Creates a new #XfceDesktop for the specified #GdkScreen.  If @gscreen is
1559  * %NULL, the default screen will be used.
1560  *
1561  * Return value: A new #XfceDesktop.
1562  **/
1563 GtkWidget *
xfce_desktop_new(GdkScreen * gscreen,XfconfChannel * channel,const gchar * property_prefix)1564 xfce_desktop_new(GdkScreen *gscreen,
1565                  XfconfChannel *channel,
1566                  const gchar *property_prefix)
1567 {
1568     XfceDesktop *desktop;
1569 
1570     g_return_val_if_fail(channel && property_prefix, NULL);
1571 
1572     desktop = g_object_new(XFCE_TYPE_DESKTOP, NULL);
1573 
1574     if(!gscreen)
1575         gscreen = gdk_display_get_default_screen(gdk_display_get_default());
1576     gtk_window_set_screen(GTK_WINDOW(desktop), gscreen);
1577     desktop->priv->gscreen = gscreen;
1578 
1579     desktop->priv->channel = XFCONF_CHANNEL(g_object_ref(G_OBJECT(channel)));
1580     desktop->priv->property_prefix = g_strdup(property_prefix);
1581 
1582     xfce_desktop_connect_settings(desktop);
1583 
1584     desktop->priv->last_filename = g_strdup("");
1585 
1586     return GTK_WIDGET(desktop);
1587 }
1588 
1589 gint
xfce_desktop_get_n_monitors(XfceDesktop * desktop)1590 xfce_desktop_get_n_monitors(XfceDesktop *desktop)
1591 {
1592     g_return_val_if_fail(XFCE_IS_DESKTOP(desktop), 0);
1593 
1594     return gdk_display_get_n_monitors(gdk_screen_get_display(desktop->priv->gscreen));
1595 }
1596 
1597 void
xfce_desktop_set_icon_style(XfceDesktop * desktop,XfceDesktopIconStyle style)1598 xfce_desktop_set_icon_style(XfceDesktop *desktop,
1599                             XfceDesktopIconStyle style)
1600 {
1601     g_return_if_fail(XFCE_IS_DESKTOP(desktop)
1602                      && style <= XFCE_DESKTOP_ICON_STYLE_FILES);
1603 
1604 #ifdef ENABLE_DESKTOP_ICONS
1605     if(style == desktop->priv->icons_style)
1606         return;
1607 
1608     if(desktop->priv->icon_view) {
1609         gtk_widget_destroy(desktop->priv->icon_view);
1610         desktop->priv->icon_view = NULL;
1611     }
1612 
1613     desktop->priv->icons_style = style;
1614     if(gtk_widget_get_realized(GTK_WIDGET(desktop)))
1615         xfce_desktop_setup_icon_view(desktop);
1616 #endif
1617 }
1618 
1619 #ifdef ENABLE_DESKTOP_ICONS
1620 static gboolean
hidden_idle_cb(gpointer user_data)1621 hidden_idle_cb(gpointer user_data)
1622 {
1623     XfceDesktop *desktop;
1624 
1625     g_return_val_if_fail(XFCE_IS_DESKTOP(user_data), FALSE);
1626 
1627     desktop = XFCE_DESKTOP(user_data);
1628 
1629     /* destroy and load the icon view so that it adds or removes
1630      * the hidden icons from the desktop */
1631     if(desktop->priv->icon_view) {
1632         gtk_widget_destroy(desktop->priv->icon_view);
1633         desktop->priv->icon_view = NULL;
1634     }
1635 
1636     if(gtk_widget_get_realized(GTK_WIDGET(desktop)))
1637         xfce_desktop_setup_icon_view(desktop);
1638 
1639     return FALSE;
1640 }
1641 
1642 static void
hidden_state_changed_cb(GObject * object,XfceDesktop * desktop)1643 hidden_state_changed_cb(GObject *object,
1644                         XfceDesktop *desktop)
1645 {
1646     g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1647 
1648     if(desktop->priv->icon_view) {
1649         g_signal_handlers_disconnect_by_func(object,
1650                                              G_CALLBACK(hidden_state_changed_cb),
1651                                              desktop);
1652     }
1653 
1654     /* We have to do this in an idle callback */
1655     g_idle_add(hidden_idle_cb, desktop);
1656 }
1657 #endif /* ENABLE_DESKTOP_ICONS */
1658 
1659 XfceDesktopIconStyle
xfce_desktop_get_icon_style(XfceDesktop * desktop)1660 xfce_desktop_get_icon_style(XfceDesktop *desktop)
1661 {
1662     g_return_val_if_fail(XFCE_IS_DESKTOP(desktop), XFCE_DESKTOP_ICON_STYLE_NONE);
1663 
1664 #ifdef ENABLE_DESKTOP_ICONS
1665     return desktop->priv->icons_style;
1666 #else
1667     return XFCE_DESKTOP_ICON_STYLE_NONE;
1668 #endif
1669 }
1670 
1671 void
xfce_desktop_set_icon_size(XfceDesktop * desktop,guint icon_size)1672 xfce_desktop_set_icon_size(XfceDesktop *desktop,
1673                            guint icon_size)
1674 {
1675     g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1676 
1677 #ifdef ENABLE_DESKTOP_ICONS
1678     if(icon_size == desktop->priv->icons_size)
1679         return;
1680 
1681     desktop->priv->icons_size = icon_size;
1682 
1683     if(desktop->priv->icon_view) {
1684         xfdesktop_icon_view_set_icon_size(XFDESKTOP_ICON_VIEW(desktop->priv->icon_view),
1685                                           icon_size);
1686     }
1687 #endif
1688 }
1689 
1690 void
xfce_desktop_set_primary(XfceDesktop * desktop,gboolean primary)1691 xfce_desktop_set_primary(XfceDesktop *desktop,
1692                            gboolean primary)
1693 {
1694     g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1695 
1696     if(primary == desktop->priv->primary)
1697         return;
1698 
1699     desktop->priv->primary = primary;
1700 
1701     if(desktop->priv->icon_view) {
1702         xfdesktop_icon_view_set_primary(XFDESKTOP_ICON_VIEW(desktop->priv->icon_view),
1703                                         primary);
1704     }
1705 }
1706 
1707 void
xfce_desktop_set_icon_font_size(XfceDesktop * desktop,guint font_size_points)1708 xfce_desktop_set_icon_font_size(XfceDesktop *desktop,
1709                                 guint font_size_points)
1710 {
1711     g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1712 
1713 #ifdef ENABLE_DESKTOP_ICONS
1714     if(font_size_points == desktop->priv->icons_font_size)
1715         return;
1716 
1717     desktop->priv->icons_font_size = font_size_points;
1718 
1719     if(desktop->priv->icons_font_size_set && desktop->priv->icon_view) {
1720         xfdesktop_icon_view_set_font_size(XFDESKTOP_ICON_VIEW(desktop->priv->icon_view),
1721                                           font_size_points);
1722     }
1723 #endif
1724 }
1725 
1726 void
xfce_desktop_set_use_icon_font_size(XfceDesktop * desktop,gboolean use_icon_font_size)1727 xfce_desktop_set_use_icon_font_size(XfceDesktop *desktop,
1728                                     gboolean use_icon_font_size)
1729 {
1730     g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1731 
1732 #ifdef ENABLE_DESKTOP_ICONS
1733     if(use_icon_font_size == desktop->priv->icons_font_size_set)
1734         return;
1735 
1736     desktop->priv->icons_font_size_set = use_icon_font_size;
1737 
1738     if(desktop->priv->icon_view) {
1739         if(!use_icon_font_size) {
1740             xfce_desktop_ensure_system_font_size(desktop);
1741             xfdesktop_icon_view_set_font_size(XFDESKTOP_ICON_VIEW(desktop->priv->icon_view),
1742                                               desktop->priv->system_font_size);
1743         } else {
1744             xfdesktop_icon_view_set_font_size(XFDESKTOP_ICON_VIEW(desktop->priv->icon_view),
1745                                               desktop->priv->icons_font_size);
1746         }
1747     }
1748 #endif
1749 }
1750 
1751 void
xfce_desktop_set_center_text(XfceDesktop * desktop,gboolean center_text)1752 xfce_desktop_set_center_text (XfceDesktop *desktop,
1753                               gboolean center_text)
1754 {
1755     g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1756 
1757 #ifdef ENABLE_DESKTOP_ICONS
1758     if(center_text == desktop->priv->icons_center_text)
1759         return;
1760 
1761     desktop->priv->icons_center_text = center_text;
1762     if(desktop->priv->icon_view) {
1763         xfdesktop_icon_view_set_center_text (XFDESKTOP_ICON_VIEW(desktop->priv->icon_view), center_text);
1764     }
1765 #endif
1766 }
1767 
1768 static void
xfce_desktop_set_single_workspace_mode(XfceDesktop * desktop,gboolean single_workspace)1769 xfce_desktop_set_single_workspace_mode(XfceDesktop *desktop,
1770                                        gboolean single_workspace)
1771 {
1772     g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1773 
1774     if(single_workspace == desktop->priv->single_workspace_mode)
1775         return;
1776 
1777     desktop->priv->single_workspace_mode = single_workspace;
1778 
1779     XF_DEBUG("single_workspace_mode now %s", single_workspace ? "TRUE" : "FALSE");
1780 
1781 
1782     /* If the desktop has been realized then fake a screen size change to
1783      * update the backdrop. There's no reason to if there's no desktop yet */
1784     if(gtk_widget_get_realized(GTK_WIDGET(desktop)))
1785         screen_size_changed_cb(desktop->priv->gscreen, desktop);
1786 }
1787 
1788 static void
xfce_desktop_set_single_workspace_number(XfceDesktop * desktop,gint workspace_num)1789 xfce_desktop_set_single_workspace_number(XfceDesktop *desktop,
1790                                          gint workspace_num)
1791 {
1792     g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1793 
1794     if(workspace_num == desktop->priv->single_workspace_num)
1795         return;
1796 
1797     XF_DEBUG("single_workspace_num now %d", workspace_num);
1798 
1799     desktop->priv->single_workspace_num = workspace_num;
1800 
1801     if(xfce_desktop_get_single_workspace_mode(desktop)) {
1802         /* Fake a screen size changed to update the backdrop */
1803         screen_size_changed_cb(desktop->priv->gscreen, desktop);
1804     }
1805 }
1806 
1807 void
xfce_desktop_set_session_logout_func(XfceDesktop * desktop,SessionLogoutFunc logout_func)1808 xfce_desktop_set_session_logout_func(XfceDesktop *desktop,
1809                                      SessionLogoutFunc logout_func)
1810 {
1811     g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1812     desktop->priv->session_logout_func = logout_func;
1813 }
1814 
1815 void
xfce_desktop_freeze_updates(XfceDesktop * desktop)1816 xfce_desktop_freeze_updates(XfceDesktop *desktop)
1817 {
1818     g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1819     desktop->priv->updates_frozen = TRUE;
1820 }
1821 
1822 void
xfce_desktop_thaw_updates(XfceDesktop * desktop)1823 xfce_desktop_thaw_updates(XfceDesktop *desktop)
1824 {
1825     g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1826 
1827     desktop->priv->updates_frozen = FALSE;
1828     if(gtk_widget_get_realized(GTK_WIDGET(desktop)))
1829         xfce_desktop_monitors_changed(desktop->priv->gscreen, desktop);
1830 }
1831 
1832 static gboolean
xfce_desktop_menu_destroy_idled(gpointer data)1833 xfce_desktop_menu_destroy_idled(gpointer data)
1834 {
1835     gtk_widget_destroy(GTK_WIDGET(data));
1836     return FALSE;
1837 }
1838 
1839 static void
xfce_desktop_do_menu_popup(XfceDesktop * desktop,guint button,guint activate_time,guint populate_signal)1840 xfce_desktop_do_menu_popup(XfceDesktop *desktop,
1841                            guint button,
1842                            guint activate_time,
1843                            guint populate_signal)
1844 {
1845     GdkScreen *screen;
1846     GtkWidget *menu;
1847     GList *menu_children;
1848 
1849     DBG("entering");
1850 
1851     if(gtk_widget_has_screen(GTK_WIDGET(desktop)))
1852         screen = gtk_widget_get_screen(GTK_WIDGET(desktop));
1853     else
1854         screen = gdk_display_get_default_screen(gdk_display_get_default());
1855 
1856     menu = gtk_menu_new();
1857     gtk_menu_set_screen(GTK_MENU(menu), screen);
1858     gtk_menu_set_reserve_toggle_size (GTK_MENU (menu), FALSE);
1859     g_signal_connect_swapped(G_OBJECT(menu), "deactivate",
1860                              G_CALLBACK(g_idle_add),
1861                              (gpointer)xfce_desktop_menu_destroy_idled);
1862 
1863     g_signal_emit(G_OBJECT(desktop), populate_signal, 0, menu);
1864 
1865     /* if nobody populated the menu, don't do anything */
1866     menu_children = gtk_container_get_children(GTK_CONTAINER(menu));
1867     if(!menu_children) {
1868         gtk_widget_destroy(menu);
1869         return;
1870     }
1871 
1872     g_list_free(menu_children);
1873 
1874     gtk_menu_attach_to_widget(GTK_MENU(menu), GTK_WIDGET(desktop), NULL);
1875 
1876     /* Per gtk_menu_popup's documentation "for conflict-resolve initiation of
1877      * concurrent requests for mouse/keyboard grab requests." */
1878     if(activate_time == 0)
1879         activate_time = gtk_get_current_event_time();
1880 
1881     xfce_gtk_menu_popup_until_mapped(GTK_MENU(menu), NULL, NULL, NULL, NULL, button, activate_time);
1882 }
1883 
1884 
1885 void
xfce_desktop_popup_root_menu(XfceDesktop * desktop,guint button,guint activate_time)1886 xfce_desktop_popup_root_menu(XfceDesktop *desktop,
1887                              guint button,
1888                              guint activate_time)
1889 {
1890     DBG("entering");
1891 
1892     xfce_desktop_do_menu_popup(desktop, button, activate_time,
1893                                signals[SIG_POPULATE_ROOT_MENU]);
1894 
1895 }
1896 
1897 void
xfce_desktop_popup_secondary_root_menu(XfceDesktop * desktop,guint button,guint activate_time)1898 xfce_desktop_popup_secondary_root_menu(XfceDesktop *desktop,
1899                                        guint button,
1900                                        guint activate_time)
1901 {
1902     DBG("entering");
1903 
1904     xfce_desktop_do_menu_popup(desktop, button, activate_time,
1905                                signals[SIG_POPULATE_SECONDARY_ROOT_MENU]);
1906 }
1907 
1908 void
xfce_desktop_refresh(XfceDesktop * desktop,gboolean advance_wallpaper)1909 xfce_desktop_refresh(XfceDesktop *desktop, gboolean advance_wallpaper)
1910 {
1911     gint i, current_workspace;
1912 
1913     TRACE("entering");
1914 
1915     g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1916 
1917     if(!gtk_widget_get_realized(GTK_WIDGET(desktop)))
1918         return;
1919 
1920     if(desktop->priv->workspaces == NULL) {
1921         return;
1922     }
1923 
1924     current_workspace = xfce_desktop_get_current_workspace(desktop);
1925 
1926     /* reload backgrounds */
1927     for(i = 0; i < xfce_desktop_get_n_monitors(desktop); i++) {
1928         XfceBackdrop *backdrop;
1929 
1930         backdrop = xfce_workspace_get_backdrop(desktop->priv->workspaces[current_workspace], i);
1931 
1932         if(advance_wallpaper) {
1933             /* We need to trigger a new wallpaper event */
1934             xfce_backdrop_force_cycle(backdrop);
1935         } else {
1936             /* Reinitialize wallpaper */
1937             xfce_backdrop_clear_cached_image(backdrop);
1938             /* Fake a changed event so we redraw the wallpaper */
1939             backdrop_changed_cb(backdrop, desktop);
1940         }
1941     }
1942 }
1943 
1944 void
xfce_desktop_arrange_icons(XfceDesktop * desktop)1945 xfce_desktop_arrange_icons(XfceDesktop *desktop)
1946 {
1947     g_return_if_fail(XFCE_IS_DESKTOP(desktop));
1948 
1949 #ifdef ENABLE_DESKTOP_ICONS
1950     g_return_if_fail(XFDESKTOP_IS_ICON_VIEW(desktop->priv->icon_view));
1951 
1952     xfdesktop_icon_view_sort_icons(XFDESKTOP_ICON_VIEW(desktop->priv->icon_view));
1953 #endif
1954 }
1955 
1956 gboolean
xfce_desktop_get_cycle_backdrop(XfceDesktop * desktop)1957 xfce_desktop_get_cycle_backdrop(XfceDesktop *desktop)
1958 {
1959     gint monitor;
1960     XfceWorkspace *workspace;
1961     XfceBackdrop  *backdrop;
1962 
1963     g_return_val_if_fail(XFCE_IS_DESKTOP(desktop), FALSE);
1964 
1965     xfce_gdk_screen_get_active(&monitor);
1966     if(&monitor == NULL)
1967         return FALSE;
1968 
1969     workspace = desktop->priv->workspaces[desktop->priv->current_workspace];
1970     backdrop = xfce_workspace_get_backdrop(workspace, monitor);
1971 
1972     return xfce_backdrop_get_cycle_backdrop(backdrop);
1973 }
1974