From 4e14f278ea242dae6b7f4a3e0ebc1a98f79a1c55 Mon Sep 17 00:00:00 2001 From: Nick Schermer Date: Sat, 28 May 2011 13:02:20 +0000 Subject: Sleep on startup until a window manager is detected. --- diff --git a/panel/main.c b/panel/main.c index 76c851a..15600c8 100644 --- a/panel/main.c +++ b/panel/main.c @@ -58,6 +58,7 @@ static gchar *opt_add = NULL; static gboolean opt_restart = FALSE; static gboolean opt_quit = FALSE; static gboolean opt_version = FALSE; +static gboolean opt_disable_wm_check = FALSE; static gchar *opt_plugin_event = NULL; static gchar **opt_arguments = NULL; static gboolean sm_client_saved_state = FALSE; @@ -81,6 +82,7 @@ static GOptionEntry option_entries[] = { "add", '\0', 0, G_OPTION_ARG_STRING, &opt_add, N_("Add a new plugin to the panel"), N_("PLUGIN-NAME") }, { "restart", 'r', 0, G_OPTION_ARG_NONE, &opt_restart, N_("Restart the running panel instance"), NULL }, { "quit", 'q', 0, G_OPTION_ARG_NONE, &opt_quit, N_("Quit the running panel instance"), NULL }, + { "disable-wm-check", 'd', 0, G_OPTION_ARG_NONE, &opt_disable_wm_check, N_("Do not wait for a window manager on startup"), NULL }, { "version", 'V', 0, G_OPTION_ARG_NONE, &opt_version, N_("Print version information and exit"), NULL }, { "plugin-event", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &opt_plugin_event, NULL, NULL }, { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &opt_arguments, NULL, NULL }, @@ -345,6 +347,7 @@ main (gint argc, gchar **argv) signal (signums[i], panel_signal_handler); application = panel_application_get (); + panel_application_load (application, opt_disable_wm_check); /* save the state before the quit signal if we can, this is a bit safer */ g_signal_connect (G_OBJECT (sm_client), "save-state", diff --git a/panel/panel-application.c b/panel/panel-application.c index 2e78eb9..2a7ddd2 100644 --- a/panel/panel-application.c +++ b/panel/panel-application.c @@ -30,6 +30,11 @@ #include #include +#ifdef GDK_WINDOWING_X11 +#include +#include +#endif + #include #include #include @@ -55,7 +60,6 @@ static void panel_application_finalize (GObject *object); -static void panel_application_load (PanelApplication *application); static void panel_application_plugin_move (GtkWidget *item, PanelApplication *application); static gboolean panel_application_plugin_insert (PanelApplication *application, @@ -126,6 +130,10 @@ struct _PanelApplication /* autosave timeout */ guint autosave_timeout_id; +#ifdef GDK_WINDOWING_X11 + guint wait_for_wm_timeout_id; +#endif + /* drag and drop data */ guint drop_data_ready : 1; guint drop_occurred : 1; @@ -133,6 +141,19 @@ struct _PanelApplication guint drop_index; }; +#ifdef GDK_WINDOWING_X11 +typedef struct +{ + PanelApplication *application; + + Display *dpy; + Atom wm_cm_atom; + guint have_wm : 1; + guint counter; +} +WaitForWM; +#endif + enum { TARGET_PLUGIN_NAME, @@ -204,18 +225,11 @@ panel_application_init (PanelApplication *application) /* get a factory reference so it never unloads */ application->factory = panel_module_factory_get (); - /* load setup */ - panel_application_load (application); - /* start the autosave timeout */ application->autosave_timeout_id = g_timeout_add_seconds (AUTOSAVE_INTERVAL, panel_application_save_timeout, application); - - /* create empty window if everything else failed */ - if (G_UNLIKELY (application->windows == NULL)) - panel_application_new_window (application, NULL, TRUE); } @@ -231,6 +245,12 @@ panel_application_finalize (GObject *object) /* stop the autosave timeout */ g_source_remove (application->autosave_timeout_id); +#ifdef GDK_WINDOWING_X11 + /* stop autostart timeout */ + if (application->wait_for_wm_timeout_id != 0) + g_source_remove (application->wait_for_wm_timeout_id); +#endif + /* free all windows */ for (li = application->windows; li != NULL; li = li->next) { @@ -298,7 +318,7 @@ panel_application_xfconf_window_bindings (PanelApplication *application, static void -panel_application_load (PanelApplication *application) +panel_application_load_real (PanelApplication *application) { PanelWindow *window; guint i, j, n_panels; @@ -375,11 +395,62 @@ panel_application_load (PanelApplication *application) xfconf_array_free (array); } + + /* create empty window if everything else failed */ + if (G_UNLIKELY (application->windows == NULL)) + panel_application_new_window (application, NULL, TRUE); +} + + + +#ifdef GDK_WINDOWING_X11 +static gboolean +panel_application_wait_for_window_manager (gpointer data) +{ + WaitForWM *wfwm = data; + + if (XGetSelectionOwner (wfwm->dpy, wfwm->wm_cm_atom) != None) + wfwm->have_wm = TRUE; + + /* abort if a window manager is found or 5 seconds expired */ + return wfwm->counter++ < 20 * 5 && !wfwm->have_wm; } static void +panel_application_wait_for_window_manager_destroyed (gpointer data) +{ + WaitForWM *wfwm = data; + PanelApplication *application = wfwm->application; + + application->wait_for_wm_timeout_id = 0; + + if (!wfwm->have_wm) + { + g_printerr (G_LOG_DOMAIN ": No window manager registered on screen 0. " + "To start the panel without this check, run with --disable-wm-check.\n"); + } + else + { + panel_debug (PANEL_DEBUG_APPLICATION, "found window manager after %d tries", + wfwm->counter); + } + + XCloseDisplay (wfwm->dpy); + g_slice_free (WaitForWM, wfwm); + + /* start loading the panels, hopefully a window manager is found, but it + * probably also works fine without... */ + GDK_THREADS_ENTER (); + panel_application_load_real (application); + GDK_THREADS_LEAVE (); +} +#endif + + + +static void panel_application_plugin_move_drag_data_get (GtkWidget *item, GdkDragContext *drag_context, GtkSelectionData *selection_data, @@ -1102,6 +1173,41 @@ panel_application_get (void) void +panel_application_load (PanelApplication *application, + gboolean disable_wm_check) +{ +#ifdef GDK_WINDOWING_X11 + WaitForWM *wfwm; + + if (!disable_wm_check) + { + /* setup data for wm checking */ + wfwm = g_slice_new0 (WaitForWM); + wfwm->application = application; + wfwm->dpy = XOpenDisplay (NULL); + wfwm->wm_cm_atom = XInternAtom (wfwm->dpy, "_NET_WM_CM_S0", False); + wfwm->have_wm = FALSE; + wfwm->counter = 0; + + /* setup timeout to check for a window manager */ + application->wait_for_wm_timeout_id = + g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE, 50, panel_application_wait_for_window_manager, + wfwm, panel_application_wait_for_window_manager_destroyed); + } + else + { + /* directly launch */ + panel_application_load_real (application); + } +#else + /* directly launch */ + panel_application_load_real (application); +#endif +} + + + +void panel_application_save (PanelApplication *application, gboolean save_plugin_providers) { diff --git a/panel/panel-application.h b/panel/panel-application.h index 17238b1..5073821 100644 --- a/panel/panel-application.h +++ b/panel/panel-application.h @@ -38,6 +38,9 @@ GType panel_application_get_type (void) G_GNUC_CONST; PanelApplication *panel_application_get (void); +void panel_application_load (PanelApplication *application, + gboolean disable_wm_check); + void panel_application_save (PanelApplication *application, gboolean save_plugin_providers); -- cgit