[Xfce4-commits] <xfdesktop:master> Merge branch 'eric/Port-to-GApplication'

Eric Koegel noreply at xfce.org
Thu Nov 14 00:38:06 CET 2013


Updating branch refs/heads/master
         to 46c09c3a910df3e71bf9b15f5488c8265816256c (commit)
       from 2e4d8d39015c87b4c91c6a0e9192dba123a0c681 (commit)

commit 46c09c3a910df3e71bf9b15f5488c8265816256c
Merge: 2e4d8d3 14fa81a
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Thu Nov 14 02:37:07 2013 +0300

    Merge branch 'eric/Port-to-GApplication'
    
    Conflicts:
    	common/xfdesktop-common.c
    	common/xfdesktop-common.h
    	src/main.c

commit 14fa81af7edeb570e6f3251ed9b3dc795560a328
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Wed Nov 13 09:09:22 2013 +0300

    xfdesktop-application code cleanup
    
    This patch also works around g_application_quit being too new.
    The startup operation can be canceled now, additional comments
    added and some sanity checks were added.

commit 0efc8138db0b63262f1b674b49d2b23d92e4b37c
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Mon Sep 23 14:10:27 2013 +0300

    Tell session manage not to restart when quitting

commit f8204f77cf48452b7021ee707369f6b69f322928
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sat Sep 21 11:34:48 2013 +0300

    Wait for the window manager (Bug 7769)
    
    When xfdesktop starts before the window manager the wallpaper images
    and icons won't appear on all the screens. This patch waits for the
    window manager to start up or 5 seconds before loading the desktops.
    Most of the actual checking if the wm is ready is based on a patch
    in xfce4-panel, commit-id cabbdfd1c04caf20a71e0af773accf809135a03d

commit 1d9dca11efbc9ac7f416d9c9dccb2049be2b5997
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sat Sep 21 10:50:39 2013 +0300

    Workaround g_action_map being too new
    
    This adds in code for g_simple_action_group stuff so that it will
    work with glib versions earlier than 2.32.

commit f4fa63b92f0ee07268f0af8b0bccb39a03c0e0e5
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sat Sep 21 09:57:11 2013 +0300

    Use the GApplication API
    
    Uses the GApplication API to handle process uniqueness, message
    passing, and lifecycle management. This eliminates the need to
    check if xfdesktop is already running and using X to forward events
    to the running instance of xfdesktop making it eaiser to port to
    GTK3 in the future (as well as GTKApplication).

 common/xfdesktop-common.c   |   47 ---
 common/xfdesktop-common.h   |    3 -
 src/Makefile.am             |    4 +-
 src/main.c                  |  356 +----------------
 src/xfce-desktop.c          |   10 +-
 src/xfdesktop-application.c |  883 +++++++++++++++++++++++++++++++++++++++++++
 src/xfdesktop-application.h |   47 +++
 7 files changed, 951 insertions(+), 399 deletions(-)

diff --git a/common/xfdesktop-common.c b/common/xfdesktop-common.c
index ca6b89c..f36c500 100644
--- a/common/xfdesktop-common.c
+++ b/common/xfdesktop-common.c
@@ -120,53 +120,6 @@ xfdesktop_image_file_is_valid(const gchar *filename)
     return image_valid;
 }
 
-gboolean
-xfdesktop_check_is_running(Window *xid)
-{
-    const gchar *display = g_getenv("DISPLAY");
-    gchar *p;
-    gint xscreen = -1;
-    gchar selection_name[100];
-    Atom selection_atom;
-
-    if(display) {
-        if((p=g_strrstr(display, ".")))
-            xscreen = atoi(p);
-    }
-    if(xscreen == -1)
-        xscreen = 0;
-
-    g_snprintf(selection_name, 100, XFDESKTOP_SELECTION_FMT, xscreen);
-    selection_atom = XInternAtom(gdk_x11_get_default_xdisplay(), selection_name, False);
-
-    if((*xid = XGetSelectionOwner(gdk_x11_get_default_xdisplay(), selection_atom)))
-        return TRUE;
-
-    return FALSE;
-}
-
-void
-xfdesktop_send_client_message(Window xid, const gchar *msg)
-{
-    GdkEventClient gev;
-    GtkWidget *win;
-
-    win = gtk_invisible_new();
-    gtk_widget_realize(win);
-
-    gev.type = GDK_CLIENT_EVENT;
-    gev.window = gtk_widget_get_window(win);
-    gev.send_event = TRUE;
-    gev.message_type = gdk_atom_intern("STRING", FALSE);
-    gev.data_format = 8;
-    strcpy(gev.data.b, msg);
-
-    gdk_event_send_client_message((GdkEvent *)&gev, (GdkNativeWindow)xid);
-    gdk_flush();
-
-    gtk_widget_destroy(win);
-}
-
 /* The image styles changed from versions prior to 4.11.
  * Auto isn't an option anymore, additionally we should handle invalid
  * values. Set them to the default of stretched. */
diff --git a/common/xfdesktop-common.h b/common/xfdesktop-common.h
index e1b3878..78f543b 100644
--- a/common/xfdesktop-common.h
+++ b/common/xfdesktop-common.h
@@ -90,9 +90,6 @@ gboolean xfdesktop_image_file_is_valid(const gchar *filename);
 
 gchar *xfdesktop_get_file_mimetype(const gchar *file);
 
-gboolean xfdesktop_check_is_running(Window *xid);
-void xfdesktop_send_client_message(Window xid, const gchar *msg);
-
 gint xfce_translate_image_styles(gint input);
 
 guint32 xfdesktop_popup_keyboard_grab_available(GdkWindow *win);
diff --git a/src/Makefile.am b/src/Makefile.am
index 4d73dad..42667a0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -25,7 +25,9 @@ xfdesktop_SOURCES = \
 	xfce-workspace.c \
 	xfce-workspace.h \
 	xfce-desktop.c \
-	xfce-desktop.h
+	xfce-desktop.h \
+	xfdesktop-application.c \
+	xfdesktop-application.h
 
 desktop_icon_sources = \
 	xfdesktop-icon.c \
diff --git a/src/main.c b/src/main.c
index 7669b4f..a2b552b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -48,206 +48,25 @@
 #include <unistd.h>
 #endif
 
-#include <X11/Xlib.h>
-
-#include <gdk/gdkx.h>
-#include <gtk/gtk.h>
-
-#include <xfconf/xfconf.h>
-#include <libxfce4ui/libxfce4ui.h>
-
 #ifdef ENABLE_FILE_ICONS
 #include <dbus/dbus-glib.h>
 #endif
 
-#include "xfdesktop-common.h"
-#include "xfce-backdrop.h"
-#include "xfce-desktop.h"
-#include "menu.h"
-#include "windowlist.h"
-
-#ifdef HAVE_LIBNOTIFY
-#include "xfdesktop-notify.h"
-#endif
-
-static XfceSMClient *sm_client = NULL;
-
-static void
-session_logout(void)
-{
-    xfce_sm_client_request_shutdown(sm_client, XFCE_SM_CLIENT_SHUTDOWN_HINT_ASK);
-}
-
-static void
-session_die(gpointer user_data)
-{
-    gtk_main_quit();
-}
-
-static void
-event_forward_to_rootwin(GdkScreen *gscreen, GdkEvent *event)
-{
-    XButtonEvent xev, xev2;
-    Display *dpy = GDK_DISPLAY_XDISPLAY(gdk_screen_get_display(gscreen));
-    
-    if(event->type == GDK_BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE) {
-        if(event->type == GDK_BUTTON_PRESS) {
-            xev.type = ButtonPress;
-            /*
-             * rox has an option to disable the next
-             * instruction. it is called "blackbox_hack". Does
-             * anyone know why exactly it is needed?
-             */
-            XUngrabPointer(dpy, event->button.time);
-        } else
-            xev.type = ButtonRelease;
-        
-        xev.button = event->button.button;
-        xev.x = event->button.x;    /* Needed for icewm */
-        xev.y = event->button.y;
-        xev.x_root = event->button.x_root;
-        xev.y_root = event->button.y_root;
-        xev.state = event->button.state;
-
-        xev2.type = 0;
-    } else if(event->type == GDK_SCROLL) {
-        xev.type = ButtonPress;
-        xev.button = event->scroll.direction + 4;
-        xev.x = event->scroll.x;    /* Needed for icewm */
-        xev.y = event->scroll.y;
-        xev.x_root = event->scroll.x_root;
-        xev.y_root = event->scroll.y_root;
-        xev.state = event->scroll.state;
-        
-        xev2.type = ButtonRelease;
-        xev2.button = xev.button;
-    } else
-        return;
-    xev.window = GDK_WINDOW_XWINDOW(gdk_screen_get_root_window(gscreen));
-    xev.root =  xev.window;
-    xev.subwindow = None;
-    xev.time = event->button.time;
-    xev.same_screen = True;
-
-    XSendEvent(dpy, xev.window, False, ButtonPressMask | ButtonReleaseMask,
-            (XEvent *)&xev);
-    if(xev2.type == 0)
-        return;
-
-    /* send button release for scroll event */
-    xev2.window = xev.window;
-    xev2.root = xev.root;
-    xev2.subwindow = xev.subwindow;
-    xev2.time = xev.time;
-    xev2.x = xev.x;
-    xev2.y = xev.y;
-    xev2.x_root = xev.x_root;
-    xev2.y_root = xev.y_root;
-    xev2.state = xev.state;
-    xev2.same_screen = xev.same_screen;
-
-    XSendEvent(dpy, xev2.window, False, ButtonPressMask | ButtonReleaseMask,
-            (XEvent *)&xev2);
-}
-
-static gboolean
-scroll_cb(GtkWidget *w, GdkEventScroll *evt, gpointer user_data)
-{
-    event_forward_to_rootwin(gtk_widget_get_screen(w), (GdkEvent*)evt);
-    return TRUE;
-}
-
-static gboolean 
-reload_idle_cb(gpointer data)
-{
-    XfceDesktop **desktops = data;
-    gint i, nscreens;
-
-    nscreens = gdk_display_get_n_screens(gdk_display_get_default());
-    for(i = 0; i < nscreens; ++i) {
-        if(desktops[i])
-            xfce_desktop_refresh(desktops[i]);
-    }
-
-    menu_reload();
-
-    return FALSE;
-}
-
-static gboolean
-client_message_received(GtkWidget *w, GdkEventClient *evt, gpointer user_data)
-{
-    if(evt->data_format == 8) {
-        if(!strcmp(RELOAD_MESSAGE, evt->data.b)) {
-            g_idle_add((GSourceFunc)reload_idle_cb, user_data);
-            return TRUE;
-        } else if(!strcmp(MENU_MESSAGE, evt->data.b)) {
-            xfce_desktop_popup_root_menu(XFCE_DESKTOP(w), 0, 0);
-            return TRUE;
-        } else if(!strcmp(WINDOWLIST_MESSAGE, evt->data.b)) {
-            xfce_desktop_popup_secondary_root_menu(XFCE_DESKTOP(w), 0, 0);
-            return TRUE;
-#ifdef ENABLE_FILE_ICONS
-        } else if(!strcmp(ARRANGE_MESSAGE, evt->data.b)) {
-            xfce_desktop_arrange_icons(XFCE_DESKTOP(w));
-            return TRUE;
-#endif
-        } else if(!strcmp(QUIT_MESSAGE, evt->data.b)) {
-            xfce_sm_client_set_restart_style(sm_client,
-                                             XFCE_SM_CLIENT_RESTART_NORMAL);
-            gtk_main_quit();
-            return TRUE;
-        }
-    }
+#include <gtk/gtk.h>
 
-    return FALSE;
-}
+#include <libxfce4util/libxfce4util.h>
 
-static void
-xfdesktop_handle_SIGUSR1(gint sig,
-                         gpointer user_data)
-{
-    //settings_reload_all();  /* FIXME */
-    menu_reload();
-}
-
-static void
-xfdesktop_handle_quit_signals(gint sig,
-                              gpointer user_data)
-{
-    gint main_level;
-    
-    for(main_level = gtk_main_level(); main_level > 0; --main_level)
-        gtk_main_quit();
-}
+#include "xfdesktop-application.h"
 
 int
 main(int argc, char **argv)
 {
-    GOptionContext *octx;
-    GdkDisplay *gdpy;
-    GtkWidget **desktops;
-    gint i, nscreens;
-    Window xid;
-    XfconfChannel *channel = NULL;
-    const gchar *message = NULL;
-    gboolean already_running;
-    gchar buf[1024];
-    GError *error = NULL;
-    gboolean opt_version = FALSE, opt_reload = FALSE;
-    gboolean opt_menu = FALSE, opt_windowlist = FALSE;
-    gboolean opt_arrange = FALSE, opt_quit = FALSE;
-    const GOptionEntry main_entries[] = {
-        { "version", 'V', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &opt_version, N_("Display version information"), NULL },
-        { "reload", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &opt_reload, N_("Reload all settings, refresh image list"), NULL },
-        { "menu", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &opt_menu, N_("Pop up the menu (at the current mouse position)"), NULL },
-        { "windowlist", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &opt_windowlist, N_("Pop up the window list (at the current mouse position)"), NULL },
-#ifdef ENABLE_FILE_ICONS
-        { "arrange", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &opt_arrange, N_("Automatically arrange all the icons on the desktop"), NULL },
+    XfdesktopApplication *app;
+    int ret = 0;
+
+#if !GLIB_CHECK_VERSION (2, 36, 0)
+    g_type_init();
 #endif
-        { "quit", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &opt_quit, N_("Cause xfdesktop to quit"), NULL },
-        { NULL, 0, 0, 0, NULL, NULL, NULL }
-    };
 
 #ifdef G_ENABLE_DEBUG
     /* do NOT remove this line. If something doesn't work,
@@ -262,162 +81,11 @@ main(int argc, char **argv)
     dbus_g_thread_init();
 #endif
 
-    octx = g_option_context_new("");
-    g_option_context_add_main_entries(octx, main_entries, NULL);
-    g_option_context_add_group(octx, gtk_get_option_group(TRUE));
-    g_option_context_add_group(octx, xfce_sm_client_get_option_group(argc, argv));
+    app = xfdesktop_application_get();
 
-    if(!g_option_context_parse(octx, &argc, &argv, &error)) {
-        g_printerr(_("Failed to parse arguments: %s\n"), error->message);
-        g_error_free(error);
-        return 1;
-    }
+    ret = xfdesktop_application_run(app, argc, argv);
 
-    g_option_context_free(octx);
+    g_object_unref(app);
 
-    if(opt_version) {
-        g_print(_("This is %s version %s, running on Xfce %s.\n"), PACKAGE,
-                VERSION, xfce_version_string());
-        g_print(_("Built with GTK+ %d.%d.%d, linked with GTK+ %d.%d.%d."),
-                GTK_MAJOR_VERSION,GTK_MINOR_VERSION, GTK_MICRO_VERSION,
-                gtk_major_version, gtk_minor_version, gtk_micro_version);
-        g_print("\n");
-        g_print(_("Build options:\n"));
-        g_print(_("    Desktop Menu:        %s\n"),
-#ifdef USE_DESKTOP_MENU
-                _("enabled")
-#else
-                _("disabled")
-#endif
-                );
-        g_print(_("    Desktop Icons:       %s\n"),
-#ifdef ENABLE_DESKTOP_ICONS
-                _("enabled")
-#else
-                _("disabled")
-#endif
-                );
-        g_print(_("    Desktop File Icons:  %s\n"),
-#ifdef ENABLE_FILE_ICONS
-                _("enabled")
-#else
-                _("disabled")
-#endif
-                );
-        
-        return 0;
-    } else if(opt_reload)
-        message = RELOAD_MESSAGE;
-    else if(opt_menu)
-        message = MENU_MESSAGE;
-    else if(opt_windowlist)
-        message = WINDOWLIST_MESSAGE;
-    else if(opt_arrange)
-        message = ARRANGE_MESSAGE;
-    else if(opt_quit)
-        message = QUIT_MESSAGE;
-    
-    signal(SIGPIPE, SIG_IGN);
-
-    already_running = xfdesktop_check_is_running(&xid);
-    if(already_running) {
-        if(!message) {
-            g_printerr("%s[%d] is already running; assuming --reload\n",
-                       PACKAGE, (int)getpid());
-            message = RELOAD_MESSAGE;
-        }
-    }
-
-    if(message) {
-        if(!already_running)
-            g_printerr(_("%s is not running.\n"), PACKAGE);
-        else
-            xfdesktop_send_client_message(xid, message);
-
-        return (already_running ? 0 : 1);
-    }
-
-    DBG ("starting up");
-
-    sm_client = xfce_sm_client_get();
-    xfce_sm_client_set_restart_style(sm_client, XFCE_SM_CLIENT_RESTART_IMMEDIATELY);
-    xfce_sm_client_set_priority(sm_client, XFCE_SM_CLIENT_PRIORITY_DESKTOP);
-    g_signal_connect(sm_client, "quit",
-                     G_CALLBACK(session_die), NULL);
-
-    if(!xfce_sm_client_connect(sm_client, &error) && error) {
-        g_printerr("Failed to connect to session manager: %s\n", error->message);
-        g_clear_error(&error);
-    }
-
-    gdpy = gdk_display_get_default();
-
-    if(!xfconf_init(&error)) {
-        g_warning("%s: unable to connect to settings daemon: %s.  Defaults will be used",
-                  PACKAGE, error->message);
-        g_error_free(error);
-        error = NULL;
-    } else
-        channel = xfconf_channel_get(XFDESKTOP_CHANNEL);
-
-    nscreens = gdk_display_get_n_screens(gdpy);
-    desktops = g_new0(GtkWidget *, nscreens);
-    for(i = 0; i < nscreens; i++) {
-        g_snprintf(buf, sizeof(buf), "/backdrop/screen%d/", i);
-        desktops[i] = xfce_desktop_new(gdk_display_get_screen(gdpy, i),
-                                       channel, buf);
-        gtk_widget_add_events(desktops[i], GDK_BUTTON_PRESS_MASK
-                              | GDK_BUTTON_RELEASE_MASK | GDK_SCROLL_MASK);
-        g_signal_connect(G_OBJECT(desktops[i]), "scroll-event",
-                         G_CALLBACK(scroll_cb), NULL);
-        g_signal_connect(G_OBJECT(desktops[i]), "client-event",
-                         G_CALLBACK(client_message_received), desktops);
-        menu_attach(XFCE_DESKTOP(desktops[i]));
-        windowlist_attach(XFCE_DESKTOP(desktops[i]));
-        gtk_widget_show(desktops[i]);
-        gdk_window_lower(gtk_widget_get_window(desktops[i]));
-    }
-    
-    for(i = 0; i < nscreens; ++i) {
-        xfce_desktop_set_session_logout_func(XFCE_DESKTOP(desktops[i]),
-                                             session_logout);
-    }
-
-    menu_init(channel);
-    windowlist_init(channel);
-    
-    if(xfce_posix_signal_handler_init(&error)) {
-        xfce_posix_signal_handler_set_handler(SIGHUP,
-                                              xfdesktop_handle_quit_signals,
-                                              desktops, NULL);
-        xfce_posix_signal_handler_set_handler(SIGINT,
-                                              xfdesktop_handle_quit_signals,
-                                              desktops, NULL);
-        xfce_posix_signal_handler_set_handler(SIGTERM,
-                                              xfdesktop_handle_quit_signals,
-                                              desktops, NULL);
-        xfce_posix_signal_handler_set_handler(SIGUSR1,
-                                              xfdesktop_handle_SIGUSR1,
-                                              desktops, NULL);
-    } else {
-        g_warning("Unable to set up POSIX signal handlers: %s", error->message);
-        g_error_free(error);
-    }
-
-    gtk_main();
-    
-    menu_cleanup();
-    windowlist_cleanup();
-    
-    for(i = 0; i < nscreens; i++)
-        gtk_widget_destroy(desktops[i]);
-    g_free(desktops);
-    
-    xfconf_shutdown();
-
-#ifdef HAVE_LIBNOTIFY
-    xfdesktop_notify_uninit();
-#endif
-    
-    return 0;
+    return ret;
 }
diff --git a/src/xfce-desktop.c b/src/xfce-desktop.c
index e874a20..d93535c 100644
--- a/src/xfce-desktop.c
+++ b/src/xfce-desktop.c
@@ -1128,15 +1128,17 @@ xfce_desktop_unrealize(GtkWidget *widget)
     gdk_flush();
     gdk_error_trap_pop();
 
-    g_object_unref(G_OBJECT(desktop->priv->bg_pixmap));
-    desktop->priv->bg_pixmap = NULL;
+    if(desktop->priv->bg_pixmap) {
+        g_object_unref(G_OBJECT(desktop->priv->bg_pixmap));
+        desktop->priv->bg_pixmap = NULL;
+    }
     
     gtk_window_set_icon(GTK_WINDOW(widget), NULL);
-    
+
     gtk_style_detach(gtk_widget_get_style(widget));
     g_object_unref(G_OBJECT(gtk_widget_get_window(widget)));
     gtk_widget_set_window(widget, NULL);
-    
+
     gtk_selection_remove_all(widget);
     
     gtk_widget_set_realized(widget, FALSE);
diff --git a/src/xfdesktop-application.c b/src/xfdesktop-application.c
new file mode 100644
index 0000000..bc95841
--- /dev/null
+++ b/src/xfdesktop-application.c
@@ -0,0 +1,883 @@
+/*
+ *  xfdesktop - xfce4's desktop manager
+ *
+ *  Copyright (c) 2006      Brian Tarricone, <bjt23 at cornell.edu>
+ *  Copyright (c) 2010-2011 Jannis Pohlmann, <jannis at xfce.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software Foundation,
+ *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+/* Random portions taken from or inspired by the original xfdesktop for xfce4:
+ *     Copyright (C) 2002-2003 Jasper Huijsmans (huysmans at users.sourceforge.net)
+ *     Copyright (C) 2003 Benedikt Meurer <benedikt.meurer at unix-ag.uni-siegen.de>
+ *  X event forwarding code:
+ *     Copyright (c) 2004 Nils Rennebarth
+ * Additional portions taken from https://bugzilla.xfce.org/attachment.cgi?id=3751
+ * which is in xfce4-panel git commit id 2a8de2b1b019eaef543e34764c999a409fe2bef9
+ * and adapted for xfdesktop.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+
+#include <xfconf/xfconf.h>
+#include <libxfce4ui/libxfce4ui.h>
+#include <libxfce4util/libxfce4util.h>
+
+#include "xfdesktop-common.h"
+#include "xfce-backdrop.h"
+#include "xfce-desktop.h"
+#include "menu.h"
+#include "windowlist.h"
+
+#ifdef HAVE_LIBNOTIFY
+#include "xfdesktop-notify.h"
+#endif
+
+#include "xfdesktop-application.h"
+
+static void xfdesktop_application_finalize(GObject *object);
+
+static void session_logout(void);
+static void session_die(gpointer user_data);
+
+static void event_forward_to_rootwin(GdkScreen *gscreen, GdkEvent *event);
+
+static gboolean scroll_cb(GtkWidget *w, GdkEventScroll *evt, gpointer user_data);
+
+static gboolean reload_idle_cb(gpointer data);
+static void cb_xfdesktop_application_reload(GAction  *action,
+                                            GVariant *parameter,
+                                            gpointer  data);
+
+static void xfdesktop_handle_quit_signals(gint sig, gpointer user_data);
+static void cb_xfdesktop_application_quit(GAction  *action,
+                                          GVariant *parameter,
+                                          gpointer  data);
+
+static gint xfdesktop_application_get_current_screen_number(XfdesktopApplication *app);
+
+static void cb_xfdesktop_application_menu(GAction  *action,
+                                          GVariant *parameter,
+                                          gpointer  data);
+
+static void cb_xfdesktop_application_arrange(GAction  *action,
+                                             GVariant *parameter,
+                                             gpointer  data);
+
+static gboolean cb_wait_for_window_manager(gpointer data);
+static void     cb_wait_for_window_manager_destroyed(gpointer data);
+
+static void xfdesktop_application_startup(GApplication *g_application);
+static void xfdesktop_application_start(XfdesktopApplication *app);
+static void xfdesktop_application_shutdown(GApplication *g_application);
+
+static gboolean xfdesktop_application_local_command_line(GApplication *g_application,
+                                                         gchar ***arguments,
+                                                         int *exit_status);
+static gint xfdesktop_application_command_line(GApplication *g_application,
+                                               GApplicationCommandLine *command_line);
+
+typedef struct
+{
+    XfdesktopApplication *app;
+
+    Display *dpy;
+    Atom *atoms;
+    guint atom_count;
+    guint have_wm : 1;
+    guint counter;
+    guint wait_for_wm_timeout_id;
+} WaitForWM;
+
+struct _XfdesktopApplication
+{
+    GApplication parent;
+
+#if !GLIB_CHECK_VERSION (2, 32, 0)
+    GSimpleActionGroup *actions;
+#endif
+
+    GtkWidget **desktops;
+    XfconfChannel *channel;
+    gint nscreens;
+    guint wait_for_wm_timeout_id;
+    XfceSMClient *sm_client;
+    GCancellable *cancel;
+
+    gboolean opt_disable_wm_check;
+};
+
+struct _XfdesktopApplicationClass
+{
+    GApplicationClass parent;
+};
+
+
+
+G_DEFINE_TYPE(XfdesktopApplication, xfdesktop_application, G_TYPE_APPLICATION)
+
+
+static void
+xfdesktop_application_class_init(XfdesktopApplicationClass *klass)
+{
+    GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+    GApplicationClass *gapplication_class = G_APPLICATION_CLASS(klass);
+
+    gobject_class->finalize = xfdesktop_application_finalize;
+
+    gapplication_class->startup = xfdesktop_application_startup;
+    gapplication_class->shutdown = xfdesktop_application_shutdown;
+    gapplication_class->local_command_line = xfdesktop_application_local_command_line;
+    gapplication_class->command_line = xfdesktop_application_command_line;
+}
+
+static void
+xfdesktop_application_add_action(XfdesktopApplication *app, GAction *action)
+{
+#if GLIB_CHECK_VERSION (2, 32, 0)
+    g_action_map_add_action(G_ACTION_MAP(app), action);
+#else
+    g_simple_action_group_insert(app->actions, action);
+#endif
+}
+
+static void
+xfdesktop_application_init(XfdesktopApplication *app)
+{
+    GSimpleAction *action;
+
+    app->cancel = g_cancellable_new();
+
+#if !GLIB_CHECK_VERSION (2, 32, 0)
+    app->actions = g_simple_action_group_new();
+#endif
+
+    /* reload action */
+    action = g_simple_action_new("reload", NULL);
+    g_signal_connect(action, "activate", G_CALLBACK(cb_xfdesktop_application_reload), app);
+    xfdesktop_application_add_action(app, G_ACTION(action));
+    g_object_unref(action);
+
+    /* quit action */
+    action = g_simple_action_new("quit", NULL);
+    g_signal_connect(action, "activate", G_CALLBACK(cb_xfdesktop_application_quit), app);
+    xfdesktop_application_add_action(app, G_ACTION(action));
+    g_object_unref(action);
+
+    /* menu action, parameter pops up primary (TRUE) or windowlist menu */
+    action = g_simple_action_new("menu", G_VARIANT_TYPE_BOOLEAN);
+    g_signal_connect(action, "activate", G_CALLBACK(cb_xfdesktop_application_menu), app);
+    xfdesktop_application_add_action(app, G_ACTION(action));
+    g_object_unref(action);
+
+    /* arrange action */
+    action = g_simple_action_new("arrange", NULL);
+    g_signal_connect(action, "activate", G_CALLBACK(cb_xfdesktop_application_arrange), app);
+    xfdesktop_application_add_action(app, G_ACTION(action));
+    g_object_unref(action);
+
+#if !GLIB_CHECK_VERSION (2, 32, 0)
+    g_application_set_action_group(G_APPLICATION(app), (GActionGroup*)app->actions);
+#endif
+}
+
+static void
+xfdesktop_application_finalize(GObject *object)
+{
+    G_OBJECT_CLASS(xfdesktop_application_parent_class)->finalize(object);
+}
+
+/**
+ * xfdesktop_application_get:
+ *
+ * Singleton. Additional calls increase the reference count.
+ *
+ * Return value: #XfdesktopApplication, free with g_object_unref.
+ **/
+XfdesktopApplication *
+xfdesktop_application_get(void)
+{
+    static XfdesktopApplication *app = NULL;
+
+    if(app == NULL) {
+       app = g_object_new(XFDESKTOP_TYPE_APPLICATION,
+                          "application-id", "org.xfce.xfdesktop",
+                          "flags", G_APPLICATION_HANDLES_COMMAND_LINE,
+                          NULL);
+    } else {
+        g_object_ref(app);
+    }
+
+    return app;
+}
+
+static void
+session_logout(void)
+{
+    XfceSMClient *sm_client;
+
+    sm_client = xfce_sm_client_get();
+    xfce_sm_client_request_shutdown(sm_client, XFCE_SM_CLIENT_SHUTDOWN_HINT_ASK);
+}
+
+static void
+session_die(gpointer user_data)
+{
+    gint main_level;
+    XfdesktopApplication *app;
+
+    TRACE("entering");
+
+    /* If we somehow got here after the app has been released we don't need
+     * to do anything */
+    if(user_data == NULL || !XFDESKTOP_IS_APPLICATION(user_data))
+        return;
+
+    app = XFDESKTOP_APPLICATION(user_data);
+
+    /* Cancel the wait for wm check if it's still running */
+    g_cancellable_cancel(app->cancel);
+
+    /* unhook our session quit function */
+    g_signal_handlers_disconnect_by_func(app->sm_client, session_die, app);
+
+    for(main_level = gtk_main_level(); main_level > 0; --main_level)
+        gtk_main_quit();
+
+#if GLIB_CHECK_VERSION(2, 32, 0)
+    g_application_quit(G_APPLICATION(app));
+#else
+    xfdesktop_application_shutdown(G_APPLICATION(app));
+#endif
+}
+
+static void
+event_forward_to_rootwin(GdkScreen *gscreen, GdkEvent *event)
+{
+    XButtonEvent xev, xev2;
+    Display *dpy = GDK_DISPLAY_XDISPLAY(gdk_screen_get_display(gscreen));
+
+    if(event->type == GDK_BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE) {
+        if(event->type == GDK_BUTTON_PRESS) {
+            xev.type = ButtonPress;
+            /*
+             * rox has an option to disable the next
+             * instruction. it is called "blackbox_hack". Does
+             * anyone know why exactly it is needed?
+             */
+            XUngrabPointer(dpy, event->button.time);
+        } else
+            xev.type = ButtonRelease;
+
+        xev.button = event->button.button;
+        xev.x = event->button.x;    /* Needed for icewm */
+        xev.y = event->button.y;
+        xev.x_root = event->button.x_root;
+        xev.y_root = event->button.y_root;
+        xev.state = event->button.state;
+
+        xev2.type = 0;
+    } else if(event->type == GDK_SCROLL) {
+        xev.type = ButtonPress;
+        xev.button = event->scroll.direction + 4;
+        xev.x = event->scroll.x;    /* Needed for icewm */
+        xev.y = event->scroll.y;
+        xev.x_root = event->scroll.x_root;
+        xev.y_root = event->scroll.y_root;
+        xev.state = event->scroll.state;
+
+        xev2.type = ButtonRelease;
+        xev2.button = xev.button;
+    } else
+        return;
+    xev.window = GDK_WINDOW_XWINDOW(gdk_screen_get_root_window(gscreen));
+    xev.root =  xev.window;
+    xev.subwindow = None;
+    xev.time = event->button.time;
+    xev.same_screen = True;
+
+    XSendEvent(dpy, xev.window, False, ButtonPressMask | ButtonReleaseMask,
+            (XEvent *)&xev);
+    if(xev2.type == 0)
+        return;
+
+    /* send button release for scroll event */
+    xev2.window = xev.window;
+    xev2.root = xev.root;
+    xev2.subwindow = xev.subwindow;
+    xev2.time = xev.time;
+    xev2.x = xev.x;
+    xev2.y = xev.y;
+    xev2.x_root = xev.x_root;
+    xev2.y_root = xev.y_root;
+    xev2.state = xev.state;
+    xev2.same_screen = xev.same_screen;
+
+    XSendEvent(dpy, xev2.window, False, ButtonPressMask | ButtonReleaseMask,
+            (XEvent *)&xev2);
+}
+
+static gboolean
+scroll_cb(GtkWidget *w, GdkEventScroll *evt, gpointer user_data)
+{
+    event_forward_to_rootwin(gtk_widget_get_screen(w), (GdkEvent*)evt);
+    return TRUE;
+}
+
+static gboolean
+reload_idle_cb(gpointer data)
+{
+    XfdesktopApplication *app = XFDESKTOP_APPLICATION(data);
+    gint i;
+
+    TRACE("entering");
+
+    g_return_if_fail(app->desktops);
+
+    /* reload all the desktops */
+    for(i = 0; i < app->nscreens; ++i) {
+        if(app->desktops[i])
+            xfce_desktop_refresh(XFCE_DESKTOP(app->desktops[i]));
+    }
+
+    menu_reload();
+
+    g_application_release(G_APPLICATION(app));
+
+    return FALSE;
+}
+
+static void
+cb_xfdesktop_application_reload(GAction  *action,
+                                GVariant *parameter,
+                                gpointer  data)
+{
+    GApplication *g_application;
+
+    if(!data || !G_IS_APPLICATION(data))
+        return;
+
+    g_application = G_APPLICATION(data);
+
+    /* hold the app so it doesn't quit while a queue up a refresh */
+    g_application_hold(g_application);
+    g_idle_add((GSourceFunc)reload_idle_cb, g_application);
+}
+
+static void
+xfdesktop_handle_quit_signals(gint sig,
+                              gpointer user_data)
+{
+    TRACE("entering");
+
+    g_return_if_fail(XFDESKTOP_IS_APPLICATION(user_data));
+
+    session_die(user_data);
+}
+
+static void
+cb_xfdesktop_application_quit(GAction  *action,
+                              GVariant *parameter,
+                              gpointer  data)
+{
+    XfdesktopApplication *app;
+
+    TRACE("entering");
+
+    g_return_if_fail(XFDESKTOP_IS_APPLICATION(data));
+
+    app = XFDESKTOP_APPLICATION(data);
+
+    /* If the user told xfdesktop to quit, set the restart style to something
+     * where it won't restart itself */
+    if(app->sm_client && XFCE_IS_SM_CLIENT(app->sm_client)) {
+        xfce_sm_client_set_restart_style(app->sm_client,
+                                         XFCE_SM_CLIENT_RESTART_NORMAL);
+    }
+
+    session_die(app);
+}
+
+static gint
+xfdesktop_application_get_current_screen_number(XfdesktopApplication *app)
+{
+    GdkDisplay *display = gdk_display_get_default();
+    GdkScreen *screen;
+    gint screen_num;
+
+    gdk_display_get_pointer(display, &screen, NULL, NULL, NULL);
+
+    screen_num = gdk_screen_get_number(screen);
+
+    if(screen_num >= app->nscreens) {
+        g_printerr("screen_num >= app->nscreens");
+        return -1;
+    }
+
+    return screen_num;
+}
+
+/* parameter is a boolean that determines whether to popup the primay or
+ * windowlist menu */
+static void
+cb_xfdesktop_application_menu(GAction  *action,
+                              GVariant *parameter,
+                              gpointer  data)
+{
+    XfdesktopApplication *app;
+    gboolean popup_root_menu;
+    gint screen_num;
+
+    TRACE("entering");
+
+    /* sanity checks */
+    if(!data || !XFDESKTOP_IS_APPLICATION(data))
+        return;
+
+    if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_BOOLEAN))
+        return;
+
+    popup_root_menu = g_variant_get_boolean(parameter);
+    app = XFDESKTOP_APPLICATION(data);
+
+    screen_num = xfdesktop_application_get_current_screen_number(app);
+    /* not initialized */
+    if(screen_num < 0)
+        return;
+
+    if(popup_root_menu) {
+        xfce_desktop_popup_root_menu(XFCE_DESKTOP(app->desktops[screen_num]),
+                                     0, GDK_CURRENT_TIME);
+    } else {
+        xfce_desktop_popup_secondary_root_menu(XFCE_DESKTOP(app->desktops[screen_num]),
+                                               0, GDK_CURRENT_TIME);
+    }
+}
+
+static void
+cb_xfdesktop_application_arrange(GAction  *action,
+                                 GVariant *parameter,
+                                 gpointer  data)
+{
+    XfdesktopApplication *app;
+    gint screen_num;
+
+    TRACE("entering");
+
+    /* sanity check */
+    if(!data || !XFDESKTOP_IS_APPLICATION(data))
+        return;
+
+    app = XFDESKTOP_APPLICATION(data);
+
+    screen_num = xfdesktop_application_get_current_screen_number(app);
+    /* not initialized */
+    if(screen_num < 0)
+        return;
+
+    xfce_desktop_arrange_icons(XFCE_DESKTOP(app->desktops[screen_num]));
+}
+
+/* Cleans up the associated wait for wm resources */
+static void
+wait_for_window_manager_cleanup(WaitForWM *wfwm)
+{
+    g_free(wfwm->atoms);
+    XCloseDisplay(wfwm->dpy);
+    g_slice_free(WaitForWM, wfwm);
+}
+
+static gboolean
+cb_wait_for_window_manager(gpointer data)
+{
+    WaitForWM *wfwm = data;
+    guint i;
+    gboolean have_wm = TRUE;
+
+    /* Check if it was canceled. This way xfdesktop doesn't start up if
+     * we're quitting */
+    if(g_cancellable_is_cancelled(wfwm->app->cancel)) {
+        g_application_release(G_APPLICATION(wfwm->app));
+        wait_for_window_manager_cleanup(wfwm);
+        return FALSE;
+    }
+
+    for(i = 0; i < wfwm->atom_count; i++) {
+        if(XGetSelectionOwner(wfwm->dpy, wfwm->atoms[i]) == None) {
+            DBG("window manager not ready on screen %d", i);
+            have_wm = FALSE;
+            break;
+        }
+    }
+
+    wfwm->have_wm = have_wm;
+
+    /* abort if a window manager is found or 5 seconds expired */
+    return wfwm->counter++ < 20 * 5 && !wfwm->have_wm;
+}
+
+static void
+cb_wait_for_window_manager_destroyed(gpointer data)
+{
+    WaitForWM *wfwm = data;
+
+    g_return_if_fail(wfwm->app != NULL);
+
+    /* Check if it was canceled. This way xfdesktop doesn't start up if
+     * we're quitting */
+    if(g_cancellable_is_cancelled(wfwm->app->cancel)) {
+        g_application_release(G_APPLICATION(wfwm->app));
+        wait_for_window_manager_cleanup(wfwm);
+        return;
+    }
+
+
+    wfwm->app->wait_for_wm_timeout_id = 0;
+
+    if(!wfwm->have_wm) {
+        g_printerr("No window manager registered on screen 0. "
+                   "To start the xfdesktop without this check, run with --disable-wm-check.\n");
+    } else {
+        DBG("found window manager after %d tries", wfwm->counter);
+    }
+
+    /* start loading the desktop, hopefully a window manager is found, but it
+     * also works without it */
+    xfdesktop_application_start(wfwm->app);
+
+    wait_for_window_manager_cleanup(wfwm);
+}
+
+static void
+xfdesktop_application_startup(GApplication *g_application)
+{
+    XfdesktopApplication *app = XFDESKTOP_APPLICATION(g_application);
+    WaitForWM *wfwm;
+    guint i;
+    gchar **atom_names;
+
+    TRACE("entering");
+
+    /* hold so it does not exit on us before the main loop gets going */
+    g_application_hold(g_application);
+
+    if(!app->opt_disable_wm_check) {
+        /* setup data for wm checking */
+        wfwm = g_slice_new0(WaitForWM);
+        wfwm->dpy = XOpenDisplay(NULL);
+        wfwm->have_wm = FALSE;
+        wfwm->counter = 0;
+        wfwm->app = app;
+
+        /* preload wm atoms for all screens */
+        wfwm->atom_count = XScreenCount(wfwm->dpy);
+        wfwm->atoms = g_new(Atom, wfwm->atom_count);
+        atom_names = g_new0(gchar *, wfwm->atom_count + 1);
+
+        for(i = 0; i < wfwm->atom_count; i++)
+            atom_names[i] = g_strdup_printf ("WM_S%d", i);
+
+        if(!XInternAtoms(wfwm->dpy, atom_names, wfwm->atom_count, False, wfwm->atoms))
+            wfwm->atom_count = 0;
+
+        g_strfreev(atom_names);
+
+        /* setup timeout to check for a window manager */
+        app->wait_for_wm_timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE,
+                                                         50,
+                                                         cb_wait_for_window_manager,
+                                                         wfwm,
+                                                         cb_wait_for_window_manager_destroyed);
+    } else {
+        /* directly launch */
+        xfdesktop_application_start(app);
+    }
+
+    /* let the parent class do it's startup as well */
+    G_APPLICATION_CLASS(xfdesktop_application_parent_class)->startup(g_application);
+}
+
+static void
+xfdesktop_application_start(XfdesktopApplication *app)
+{
+    GdkDisplay *gdpy;
+    GError *error = NULL;
+    gint i;
+    gchar buf[1024];
+
+    TRACE("entering");
+
+    g_return_if_fail(app != NULL);
+
+    /* stop autostart timeout */
+    if(app->wait_for_wm_timeout_id != 0)
+        g_source_remove(app->wait_for_wm_timeout_id);
+
+    gdpy = gdk_display_get_default();
+
+    /* setup the session management options */
+    app->sm_client = xfce_sm_client_get();
+    xfce_sm_client_set_restart_style(app->sm_client, XFCE_SM_CLIENT_RESTART_IMMEDIATELY);
+    xfce_sm_client_set_priority(app->sm_client, XFCE_SM_CLIENT_PRIORITY_DESKTOP);
+    g_signal_connect(app->sm_client, "quit", G_CALLBACK(session_die), app);
+
+    if(!xfce_sm_client_connect(app->sm_client, &error) && error) {
+        g_printerr("Failed to connect to session manager: %s\n", error->message);
+        g_clear_error(&error);
+    }
+
+
+    if(!xfconf_init(&error)) {
+        g_warning("%s: unable to connect to settings daemon: %s.  Defaults will be used",
+                  PACKAGE, error->message);
+        g_error_free(error);
+        error = NULL;
+    } else
+        app->channel = xfconf_channel_get(XFDESKTOP_CHANNEL);
+
+    /* create an XfceDesktop for every screen */
+    app->nscreens = gdk_display_get_n_screens(gdpy);
+    app->desktops = g_new0(GtkWidget *, app->nscreens);
+
+    for(i = 0; i < app->nscreens; i++) {
+        g_snprintf(buf, sizeof(buf), "/backdrop/screen%d/", i);
+        app->desktops[i] = xfce_desktop_new(gdk_display_get_screen(gdpy, i),
+                                            app->channel, buf);
+
+        /* hook into the scroll event so we can forward it to the window
+         * manager */
+        gtk_widget_add_events(app->desktops[i], GDK_BUTTON_PRESS_MASK
+                              | GDK_BUTTON_RELEASE_MASK | GDK_SCROLL_MASK);
+        g_signal_connect(G_OBJECT(app->desktops[i]), "scroll-event",
+                         G_CALLBACK(scroll_cb), app);
+
+        menu_attach(XFCE_DESKTOP(app->desktops[i]));
+        windowlist_attach(XFCE_DESKTOP(app->desktops[i]));
+
+        /* display the desktop and try to put it at the bottom */
+        gtk_widget_show(app->desktops[i]);
+        gdk_window_lower(gtk_widget_get_window(app->desktops[i]));
+
+        xfce_desktop_set_session_logout_func(XFCE_DESKTOP(app->desktops[i]),
+                                             session_logout);
+    }
+
+    menu_init(app->channel);
+    windowlist_init(app->channel);
+
+    /* hook up to the different quit signals */
+    if(xfce_posix_signal_handler_init(&error)) {
+        xfce_posix_signal_handler_set_handler(SIGHUP,
+                                              xfdesktop_handle_quit_signals,
+                                              app, NULL);
+        xfce_posix_signal_handler_set_handler(SIGINT,
+                                              xfdesktop_handle_quit_signals,
+                                              app, NULL);
+        xfce_posix_signal_handler_set_handler(SIGTERM,
+                                              xfdesktop_handle_quit_signals,
+                                              app, NULL);
+    } else {
+        g_warning("Unable to set up POSIX signal handlers: %s", error->message);
+        g_error_free(error);
+    }
+
+    gtk_main();
+
+    /* now that main has started we can release our hold */
+    g_application_release(G_APPLICATION(app));
+}
+
+gint
+xfdesktop_application_run(XfdesktopApplication *app, int argc, char **argv)
+{
+    return g_application_run(G_APPLICATION(app), argc, argv);
+}
+
+static void
+xfdesktop_application_shutdown(GApplication *g_application)
+{
+    XfdesktopApplication *app = XFDESKTOP_APPLICATION(g_application);
+    gint i;
+
+    TRACE("entering");
+
+    if(app->wait_for_wm_timeout_id != 0) {
+        g_source_remove(app->wait_for_wm_timeout_id);
+        app->wait_for_wm_timeout_id = 0;
+    }
+
+    menu_cleanup();
+    windowlist_cleanup();
+
+    if(app->desktops) {
+        for(i = 0; i < app->nscreens; i++) {
+            /* ensure the desktops get freed if they haven't been */
+            if(app->desktops[i] && GTK_IS_WIDGET(app->desktops[i]))
+                gtk_widget_destroy(app->desktops[i]);
+        }
+
+        g_free(app->desktops);
+        app->desktops = NULL;
+    }
+
+    xfconf_shutdown();
+
+#ifdef HAVE_LIBNOTIFY
+    xfdesktop_notify_uninit();
+#endif
+
+    G_APPLICATION_CLASS(xfdesktop_application_parent_class)->shutdown(g_application);
+}
+
+static gboolean
+xfdesktop_application_local_command_line(GApplication *g_application,
+                                         gchar ***arguments,
+                                         int *exit_status)
+{
+    XfdesktopApplication *app = XFDESKTOP_APPLICATION(g_application);
+    GOptionContext *octx;
+    gint argc;
+    GError *error = NULL;
+    gboolean opt_version = FALSE;
+    gboolean opt_reload = FALSE;
+    gboolean opt_menu = FALSE;
+    gboolean opt_windowlist = FALSE;
+    gboolean opt_arrange = FALSE;
+    gboolean opt_quit = FALSE;
+    gboolean option_set = FALSE;
+    const GOptionEntry main_entries[] = {
+        { "version", 'V', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &opt_version, N_("Display version information"), NULL },
+        { "reload", 'R', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &opt_reload, N_("Reload all settings"), NULL },
+        { "menu", 'M', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &opt_menu, N_("Pop up the menu (at the current mouse position)"), NULL },
+        { "windowlist", 'W', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &opt_windowlist, N_("Pop up the window list (at the current mouse position)"), NULL },
+#ifdef ENABLE_FILE_ICONS
+        { "arrange", 'A', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &opt_arrange, N_("Automatically arrange all the icons on the desktop"), NULL },
+#endif
+        { "disable-wm-check", 'D', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &app->opt_disable_wm_check, N_("Do not wait for a window manager on startup"), NULL },
+        { "quit", 'Q', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &opt_quit, N_("Cause xfdesktop to quit"), NULL },
+        { NULL, 0, 0, 0, NULL, NULL, NULL }
+    };
+
+    TRACE("entering");
+
+    argc = g_strv_length(*arguments);
+
+    octx = g_option_context_new("");
+    g_option_context_set_ignore_unknown_options(octx, TRUE);
+    g_option_context_add_main_entries(octx, main_entries, NULL);
+    g_option_context_add_group(octx, gtk_get_option_group(TRUE));
+    g_option_context_add_group(octx, xfce_sm_client_get_option_group(argc, *arguments));
+
+    if(!g_option_context_parse(octx, &argc, arguments, &error)) {
+        g_printerr(_("Failed to parse arguments: %s\n"), error->message);
+        g_option_context_free(octx);
+        g_error_free(error);
+        *exit_status = 1;
+        return TRUE;
+    }
+
+    g_option_context_free(octx);
+
+    /* Print the version info and exit */
+    if(opt_version) {
+        g_print(_("This is %s version %s, running on Xfce %s.\n"), PACKAGE,
+                VERSION, xfce_version_string());
+        g_print(_("Built with GTK+ %d.%d.%d, linked with GTK+ %d.%d.%d."),
+                GTK_MAJOR_VERSION,GTK_MINOR_VERSION, GTK_MICRO_VERSION,
+                gtk_major_version, gtk_minor_version, gtk_micro_version);
+        g_print("\n");
+        g_print(_("Build options:\n"));
+        g_print(_("    Desktop Menu:        %s\n"),
+#ifdef USE_DESKTOP_MENU
+                _("enabled")
+#else
+                _("disabled")
+#endif
+                );
+        g_print(_("    Desktop Icons:       %s\n"),
+#ifdef ENABLE_DESKTOP_ICONS
+                _("enabled")
+#else
+                _("disabled")
+#endif
+                );
+        g_print(_("    Desktop File Icons:  %s\n"),
+#ifdef ENABLE_FILE_ICONS
+                _("enabled")
+#else
+                _("disabled")
+#endif
+                );
+
+        /* free our memory and exit */
+        g_object_unref(g_application);
+        *exit_status = 0;
+        return TRUE;
+    }
+
+    /* This will call xfdesktop_application_startup if it needs to */
+    g_application_register(g_application, NULL, NULL);
+
+    /* handle our defined options */
+    if(opt_quit) {
+        g_action_group_activate_action(G_ACTION_GROUP(g_application), "quit", NULL);
+        option_set = TRUE;
+    } else if(opt_reload) {
+        g_action_group_activate_action(G_ACTION_GROUP(g_application), "reload", NULL);
+        option_set = TRUE;
+    } else if(opt_menu) {
+        g_action_group_activate_action(G_ACTION_GROUP(g_application), "menu",
+                                       g_variant_new_boolean(TRUE));
+        option_set = TRUE;
+    } else if(opt_windowlist) {
+        g_action_group_activate_action(G_ACTION_GROUP(g_application), "menu",
+                                       g_variant_new_boolean(FALSE));
+        option_set = TRUE;
+    } else if(opt_arrange) {
+        g_action_group_activate_action(G_ACTION_GROUP(g_application), "arrange", NULL);
+        option_set = TRUE;
+    }
+
+    /* We handled the command line option */
+    if(option_set) {
+        *exit_status = 0;
+        return TRUE;
+    }
+
+    /* propagate it up */
+    return G_APPLICATION_CLASS(xfdesktop_application_parent_class)->local_command_line(g_application, arguments, exit_status);
+}
+
+static gint
+xfdesktop_application_command_line(GApplication *g_application,
+                                   GApplicationCommandLine *command_line)
+{
+    /* If we don't process everything in the local command line then the options
+     * won't show up during xfdesktop --help */
+
+    return 0;
+}
diff --git a/src/xfdesktop-application.h b/src/xfdesktop-application.h
new file mode 100644
index 0000000..e575a4c
--- /dev/null
+++ b/src/xfdesktop-application.h
@@ -0,0 +1,47 @@
+/*
+ *  xfdesktop - xfce4's desktop manager
+ *
+ *  Copyright (c) 2006      Brian Tarricone, <bjt23 at cornell.edu>
+ *  Copyright (c) 2010-2011 Jannis Pohlmann, <jannis at xfce.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software Foundation,
+ *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#ifndef __XFDESKTOP_APPLICATION_H__
+#define __XFDESKTOP_APPLICATION_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define XFDESKTOP_TYPE_APPLICATION            (xfdesktop_application_get_type())
+#define XFDESKTOP_APPLICATION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), XFDESKTOP_TYPE_APPLICATION, XfdesktopApplication))
+#define XFDESKTOP_APPLICATION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), XFDESKTOP_TYPE_APPLICATION, XfdesktopApplicationClass))
+#define XFDESKTOP_IS_APPLICATION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), XFDESKTOP_TYPE_APPLICATION))
+#define XFDESKTOP_APPLICATION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), XFDESKTOP_TYPE_APPLICATION, XfdesktopApplicationClass))
+
+typedef struct _XfdesktopApplication        XfdesktopApplication;
+typedef struct _XfdesktopApplicationClass   XfdesktopApplicationClass;
+
+
+GType xfdesktop_application_get_type(void) G_GNUC_CONST;
+
+XfdesktopApplication *xfdesktop_application_get(void);
+
+gint xfdesktop_application_run(XfdesktopApplication *app, int argc, char **argv);
+
+G_END_DECLS
+
+#endif  /* __XFDESKTOP_ICON_H__ */


More information about the Xfce4-commits mailing list