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