1
2 /*
3 * This file is a part of the Cairo-Dock project
4 *
5 * Copyright : (C) see the 'copyright' file.
6 * E-mail : see the 'copyright' file.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 3
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20 /*****************************************************************************************************
21 **
22 ** Program:
23 ** cairo-dock
24 **
25 ** License :
26 ** This program is released under the terms of the GNU General Public License, version 3 or above.
27 ** If you don't know what that means take a look at:
28 ** http://www.gnu.org/licenses/licenses.html#GPL
29 **
30 *********************** VERSION 0 (2006) *********************
31 **
32 ** Original idea :
33 ** Mirco "MacSlow" Mueller <macslow@bangang.de>, June 2006.
34 ** With the help of:
35 ** Behdad Esfahbod <behdad@behdad.org>
36 ** David Reveman <davidr@novell.com>
37 ** Karl Lattimer <karl@qdh.org.uk>
38 ** Originally conceived as a stress-test for cairo, librsvg, and glitz.
39 **
40 *********************** VERSION 0.1 and above (2007-2014) *********************
41 **
42 ** author(s) :
43 ** Fabrice Rey <fabounet@glx-dock.org>
44 ** With the help of:
45 ** A lot of people !!! (see the About menu and the 'copyright' file)
46 **
47 *******************************************************************************/
48
49 #include <unistd.h> // sleep, execl
50 #include <signal.h>
51
52 #define __USE_POSIX
53 #include <time.h>
54
55 #include <glib/gstdio.h>
56 #include <dbus/dbus-glib.h> // dbus_g_thread_init
57
58 #include "config.h"
59 #include "cairo-dock-icon-facility.h" // cairo_dock_get_first_icon
60 #include "cairo-dock-module-manager.h" // gldi_modules_new_from_directory
61 #include "cairo-dock-module-instance-manager.h" // GldiModuleInstance
62 #include "cairo-dock-dock-manager.h"
63 #include "cairo-dock-desklet-manager.h"
64 #include "cairo-dock-themes-manager.h"
65 #include "cairo-dock-dialog-factory.h"
66 #include "cairo-dock-keyfile-utilities.h"
67 #include "cairo-dock-config.h"
68 #include "cairo-dock-file-manager.h"
69 #include "cairo-dock-log.h"
70 #include "cairo-dock-keybinder.h"
71 #include "cairo-dock-opengl.h"
72 #include "cairo-dock-packages.h"
73 #include "cairo-dock-utils.h" // cairo_dock_launch_command
74 #include "cairo-dock-core.h"
75
76 #include "cairo-dock-gui-manager.h"
77 #include "cairo-dock-gui-backend.h"
78 #include "cairo-dock-user-interaction.h"
79 #include "cairo-dock-user-menu.h"
80
81 //#define CAIRO_DOCK_THEME_SERVER "http://themes.glx-dock.org"
82 #define CAIRO_DOCK_THEME_SERVER "http://download.tuxfamily.org/glxdock/themes"
83 #define CAIRO_DOCK_BACKUP_THEME_SERVER "http://fabounet03.free.fr"
84 // Nom du repertoire racine du theme courant.
85 #define CAIRO_DOCK_CURRENT_THEME_NAME "current_theme"
86 // Nom du repertoire des themes extras.
87 #define CAIRO_DOCK_EXTRAS_DIR "extras"
88
89 extern gchar *g_cCairoDockDataDir;
90 extern gchar *g_cCurrentThemePath;
91
92 extern gchar *g_cConfFile;
93 extern int g_iMajorVersion, g_iMinorVersion, g_iMicroVersion;
94
95 extern CairoDock *g_pMainDock;
96 extern CairoDockGLConfig g_openglConfig;
97
98 extern gboolean g_bUseOpenGL;
99 extern gboolean g_bEasterEggs;
100
101 extern GldiModuleInstance *g_pCurrentModule;
102 extern GtkWidget *cairo_dock_build_simple_gui_window (void);
103
104 gboolean g_bForceCairo = FALSE;
105 gboolean g_bLocked;
106
107 static gboolean s_bSucessfulLaunch = FALSE;
108 static GString *s_pLaunchCommand = NULL;
109 static gchar *s_cLastVersion = NULL;
110 static gchar *s_cDefaulBackend = NULL;
111 static gint s_iGuiMode = 0; // 0 = simple mode, 1 = advanced mode
112 static gint s_iLastYear = 0;
113 static gint s_iNbCrashes = 0;
114 static gboolean s_bPingServer = TRUE;
115 static gboolean s_bCDSessionLaunched = FALSE; // session CD already launched?
116
117
_on_got_server_answer(const gchar * data,G_GNUC_UNUSED gpointer user_data)118 static void _on_got_server_answer (const gchar *data, G_GNUC_UNUSED gpointer user_data)
119 {
120 if (data != NULL)
121 {
122 s_bPingServer = TRUE; // after we got the answer, we can write in the global file to not try any more.
123 gchar *cConfFilePath = g_strdup_printf ("%s/.cairo-dock", g_cCairoDockDataDir);
124 cairo_dock_update_conf_file (cConfFilePath,
125 G_TYPE_BOOLEAN, "Launch", "ping server", s_bPingServer,
126 G_TYPE_INVALID);
127 g_free (cConfFilePath);
128 }
129 }
_cairo_dock_successful_launch(gpointer data)130 static gboolean _cairo_dock_successful_launch (gpointer data)
131 {
132 s_bSucessfulLaunch = TRUE;
133 // new year greetings.
134 time_t t = time (NULL);
135 struct tm st;
136 localtime_r (&t, &st);
137
138 if (!data && st.tm_mday <= 15 && st.tm_mon == 0 && s_iLastYear < st.tm_year + 1900) // first 2 weeks of january + not first launch
139 {
140 s_iLastYear = st.tm_year + 1900;
141 gchar *cConfFilePath = g_strdup_printf ("%s/.cairo-dock", g_cCairoDockDataDir);
142 cairo_dock_update_conf_file (cConfFilePath,
143 G_TYPE_INT, "Launch", "last year", s_iLastYear,
144 G_TYPE_INVALID);
145 g_free (cConfFilePath);
146
147 Icon *pIcon = gldi_icons_get_any_without_dialog ();
148 gchar *cMessage = g_strdup_printf (_("Happy new year %d !!!"), s_iLastYear);
149 gchar *cMessageFull = g_strdup_printf ("\n%s :-)\n", cMessage);
150 gldi_dialog_show_temporary_with_icon (cMessageFull, pIcon, CAIRO_CONTAINER (g_pMainDock), 15000., CAIRO_DOCK_SHARE_DATA_DIR"/icons/balloons.png");
151 g_free (cMessageFull);
152 g_free (cMessage);
153 }
154
155 if (! s_bPingServer && g_str_has_suffix (g_cCairoDockDataDir, CAIRO_DOCK_DATA_DIR)) // the server (which hosts themes, third-party applets and packages) has never been accessed yet, ping it once
156 {
157 s_bPingServer = TRUE;
158 cairo_dock_get_url_data_async (CAIRO_DOCK_THEME_SERVER"/ping.txt", (GFunc)_on_got_server_answer, NULL);
159 }
160
161 return FALSE;
162 }
_cairo_dock_first_launch_setup(G_GNUC_UNUSED gpointer data)163 static gboolean _cairo_dock_first_launch_setup (G_GNUC_UNUSED gpointer data)
164 {
165 cairo_dock_launch_command (CAIRO_DOCK_SHARE_DATA_DIR"/scripts/initial-setup.sh");
166 return FALSE;
167 }
_cairo_dock_quit(G_GNUC_UNUSED int signal)168 static void _cairo_dock_quit (G_GNUC_UNUSED int signal)
169 {
170 gtk_main_quit ();
171 }
172 /* Crash at startup:
173 * - First 2 crashes: retry with a delay of 2 sec (maybe due to a problem at startup)
174 * - 3th crash: remove the applet and restart the dock
175 * - 4th crash: show the maintenance mode
176 * - 5th crash: quit
177 */
_cairo_dock_intercept_signal(int signal)178 static void _cairo_dock_intercept_signal (int signal)
179 {
180 cd_warning ("Cairo-Dock has crashed (sig %d).\nIt will be restarted now.\nFeel free to report this bug on glx-dock.org to help improving the dock!", signal);
181 g_print ("info on the system :\n");
182 int r = system ("uname -a");
183 if (r < 0)
184 cd_warning ("Not able to launch this command: uname");
185
186 // if a module is responsible, expose it to public shame.
187 if (g_pCurrentModule != NULL)
188 {
189 g_print ("The applet '%s' may be the culprit", g_pCurrentModule->pModule->pVisitCard->cModuleName);
190 if (! s_bSucessfulLaunch) // else, be quiet.
191 g_string_append_printf (s_pLaunchCommand, " -x \"%s\"", g_pCurrentModule->pModule->pVisitCard->cModuleName);
192 }
193 else
194 {
195 g_print ("Couldn't guess if it was an applet's fault or not. It may have crashed inside the core or inside a thread\n");
196 }
197
198 // if the crash occurs on startup, take additionnal measures; else just respawn quietly.
199 if (! s_bSucessfulLaunch) // a crash on startup,
200 {
201 if (s_iNbCrashes < 2) // the first 2 crashes, restart with a delay (in case we were launched too early on startup).
202 g_string_append (s_pLaunchCommand, " -w 2"); // 2s delay.
203 else if (g_pCurrentModule == NULL || s_iNbCrashes == 3) // crash and no culprit or 4th crash => start in maintenance mode.
204 g_string_append (s_pLaunchCommand, " -m");
205 g_string_append_printf (s_pLaunchCommand, " -q %d", s_iNbCrashes + 1); // increment the first-crash counter.
206 } // else a random crash, respawn quietly.
207
208 g_print ("restarting with '%s'...\n", s_pLaunchCommand->str);
209 execl ("/bin/sh", "/bin/sh", "-c", s_pLaunchCommand->str, (char *)NULL); // on ne revient pas de cette fonction.
210 //execlp ("cairo-dock", "cairo-dock", s_pLaunchCommand->str, (char *)0);
211 cd_warning ("Sorry, couldn't restart the dock");
212 }
_cairo_dock_set_signal_interception(void)213 static void _cairo_dock_set_signal_interception (void)
214 {
215 signal (SIGSEGV, _cairo_dock_intercept_signal); // Segmentation violation
216 signal (SIGFPE, _cairo_dock_intercept_signal); // Floating-point exception
217 signal (SIGILL, _cairo_dock_intercept_signal); // Illegal instruction
218 signal (SIGABRT, _cairo_dock_intercept_signal); // Abort // kill -6
219 }
220
on_delete_maintenance_gui(G_GNUC_UNUSED GtkWidget * pWidget,GMainLoop * pBlockingLoop)221 static gboolean on_delete_maintenance_gui (G_GNUC_UNUSED GtkWidget *pWidget, GMainLoop *pBlockingLoop)
222 {
223 cd_debug ("%s ()", __func__);
224 if (pBlockingLoop != NULL && g_main_loop_is_running (pBlockingLoop))
225 {
226 g_main_loop_quit (pBlockingLoop);
227 }
228 return FALSE; // TRUE <=> ne pas detruire la fenetre.
229 }
230
PrintMuteFunc(G_GNUC_UNUSED const gchar * string)231 static void PrintMuteFunc (G_GNUC_UNUSED const gchar *string) {}
232
_cairo_dock_get_global_config(const gchar * cCairoDockDataDir)233 static void _cairo_dock_get_global_config (const gchar *cCairoDockDataDir)
234 {
235 gchar *cConfFilePath = g_strdup_printf ("%s/.cairo-dock", cCairoDockDataDir);
236 GKeyFile *pKeyFile = g_key_file_new ();
237 if (g_file_test (cConfFilePath, G_FILE_TEST_EXISTS))
238 {
239 g_key_file_load_from_file (pKeyFile, cConfFilePath, 0, NULL);
240 s_cLastVersion = g_key_file_get_string (pKeyFile, "Launch", "last version", NULL);
241 s_cDefaulBackend = g_key_file_get_string (pKeyFile, "Launch", "default backend", NULL);
242 if (s_cDefaulBackend && *s_cDefaulBackend == '\0')
243 {
244 g_free (s_cDefaulBackend);
245 s_cDefaulBackend = NULL;
246 }
247 s_iGuiMode = g_key_file_get_integer (pKeyFile, "Gui", "mode", NULL); // 0 by default
248 s_iLastYear = g_key_file_get_integer (pKeyFile, "Launch", "last year", NULL); // 0 by default
249 s_bPingServer = g_key_file_get_boolean (pKeyFile, "Launch", "ping server", NULL); // FALSE by default
250 s_bCDSessionLaunched = g_key_file_get_boolean (pKeyFile, "Launch", "cd session", NULL); // FALSE by default
251 }
252 else // first launch or old version, the file doesn't exist yet.
253 {
254 gchar *cLastVersionFilePath = g_strdup_printf ("%s/.cairo-dock-last-version", cCairoDockDataDir);
255 if (g_file_test (cLastVersionFilePath, G_FILE_TEST_EXISTS))
256 {
257 gsize length = 0;
258 g_file_get_contents (cLastVersionFilePath,
259 &s_cLastVersion,
260 &length,
261 NULL);
262 }
263 g_remove (cLastVersionFilePath);
264 g_free (cLastVersionFilePath);
265 g_key_file_set_string (pKeyFile, "Launch", "last version", s_cLastVersion?s_cLastVersion:"");
266
267 g_key_file_set_string (pKeyFile, "Launch", "default backend", "");
268
269 g_key_file_set_integer (pKeyFile, "Gui", "mode", s_iGuiMode);
270
271 g_key_file_set_integer (pKeyFile, "Launch", "last year", s_iLastYear);
272
273 cairo_dock_write_keys_to_file (pKeyFile, cConfFilePath);
274 }
275 g_key_file_free (pKeyFile);
276 g_free (cConfFilePath);
277 }
278
279
main(int argc,char ** argv)280 int main (int argc, char** argv)
281 {
282 //\___________________ build the command line used to respawn, and check if we have been launched from another life.
283 s_pLaunchCommand = g_string_new (argv[0]);
284 int i;
285 for (i = 1; i < argc; i ++)
286 {
287 //g_print ("'%s'\n", argv[i]);
288 if (strcmp (argv[i], "-q") == 0) // this option is only set by the dock itself, at the end of the command line.
289 {
290 s_iNbCrashes = atoi (argv[i+1]);
291 argc = i; // remove this option, as it doesn't belong to the options table.
292 argv[i] = NULL;
293 break;
294 }
295 else if (strcmp (argv[i], "-w") == 0 || strcmp (argv[i], "-x") == 0) // skip this option and its argument.
296 {
297 i ++;
298 }
299 else if (strcmp (argv[i], "-m") == 0) // skip this option
300 {
301 // nothing else to do.
302 }
303 else // keep this option in the command line.
304 {
305 g_string_append_printf (s_pLaunchCommand, " %s", argv[i]);
306 }
307 }
308 /* Crash: 5th crash: an applet has already been removed and the maintenance
309 * mode has already been displayed => stop
310 */
311 if (s_iNbCrashes > 4)
312 {
313 g_print ("Sorry, Cairo-Dock has encoutered some problems, and will quit.\n");
314 return 1;
315 }
316
317 // mute all output messages if CD is not launched from a terminal
318 if (getenv("TERM") == NULL) /// why not isatty(stdout) ?...
319 g_set_print_handler(PrintMuteFunc);
320
321
322 // init lib
323 #if !defined (GLIB_VERSION_2_36) // no longer needed now... (>= 2.35)
324 g_type_init (); // should initialise threads too on new versions of GLIB (>= 2.24)
325 #endif
326 #if (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 24)
327 if (!g_thread_supported ())
328 g_thread_init (NULL);
329 #endif
330
331 dbus_g_thread_init (); // it's a wrapper: it will use dbus_threads_init_default ();
332
333 gtk_init (&argc, &argv);
334
335 GError *erreur = NULL;
336
337 //\___________________ internationalize the app.
338 bindtextdomain (CAIRO_DOCK_GETTEXT_PACKAGE, CAIRO_DOCK_LOCALE_DIR);
339 bind_textdomain_codeset (CAIRO_DOCK_GETTEXT_PACKAGE, "UTF-8");
340 textdomain (CAIRO_DOCK_GETTEXT_PACKAGE);
341
342 //\___________________ get app's options.
343 gboolean bSafeMode = FALSE, bMaintenance = FALSE, bNoSticky = FALSE, bCappuccino = FALSE, bPrintVersion = FALSE, bTesting = FALSE, bForceOpenGL = FALSE, bToggleIndirectRendering = FALSE, bKeepAbove = FALSE, bForceColors = FALSE, bAskBackend = FALSE, bMetacityWorkaround = FALSE;
344 gchar *cEnvironment = NULL, *cUserDefinedDataDir = NULL, *cVerbosity = 0, *cUserDefinedModuleDir = NULL, *cExcludeModule = NULL, *cThemeServerAdress = NULL;
345 int iDelay = 0;
346 GOptionEntry pOptionsTable[] =
347 {
348 // GLDI options: cairo, opengl, indirect-opengl, env, keep-above, no-sticky
349 {"cairo", 'c', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
350 &g_bForceCairo,
351 _("Use Cairo backend."), NULL},
352 {"opengl", 'o', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
353 &bForceOpenGL,
354 _("Use OpenGL backend."), NULL},
355 {"indirect-opengl", 'O', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
356 &bToggleIndirectRendering,
357 _("Use OpenGL backend with indirect rendering. There are very few case where this option should be used."), NULL},
358 {"ask-backend", 'A', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
359 &bAskBackend,
360 _("Ask again on startup which backend to use."), NULL},
361 {"env", 'e', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING,
362 &cEnvironment,
363 _("Force the dock to consider this environnement - use it with care."), NULL},
364 {"dir", 'd', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING,
365 &cUserDefinedDataDir,
366 _("Force the dock to load from this directory, instead of ~/.config/cairo-dock."), NULL},
367 {"server", 'S', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING,
368 &cThemeServerAdress,
369 _("Address of a server containing additional themes. This will overwrite the default server address."), NULL},
370 {"wait", 'w', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_INT,
371 &iDelay,
372 _("Wait for N seconds before starting; this is useful if you notice some problems when the dock starts with the session."), NULL},
373 {"maintenance", 'm', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
374 &bMaintenance,
375 _("Allow to edit the config before the dock is started and show the config panel on start."), NULL},
376 {"exclude", 'x', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING,
377 &cExcludeModule,
378 _("Exclude a given plug-in from activating (it is still loaded though)."), NULL},
379 {"safe-mode", 'f', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
380 &bSafeMode,
381 _("Don't load any plug-ins."), NULL},
382 {"metacity-workaround", 'W', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
383 &bMetacityWorkaround,
384 _("Work around some bugs in Metacity Window-Manager (invisible dialogs or sub-docks)"), NULL},
385 {"log", 'l', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING,
386 &cVerbosity,
387 _("Log verbosity (debug,message,warning,critical,error); default is warning."), NULL},
388 {"colors", 'F', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
389 &bForceColors,
390 _("Force to display some output messages with colors."), NULL},
391 {"version", 'v', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
392 &bPrintVersion,
393 _("Print version and quit."), NULL},
394 {"locked", 'k', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
395 &g_bLocked,
396 _("Lock the dock so that any modification is impossible for users."), NULL},
397 // below options are probably useless for most of people.
398 {"keep-above", 'a', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
399 &bKeepAbove,
400 _("Keep the dock above other windows."), NULL},
401 {"no-sticky", 's', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
402 &bNoSticky,
403 _("Don't make the dock appear on all desktops."), NULL},
404 {"capuccino", 'C', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
405 &bCappuccino,
406 _("Cairo-Dock makes anything, including coffee !"), NULL},
407 {"modules-dir", 'M', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING,
408 &cUserDefinedModuleDir,
409 _("Ask the dock to load additionnal modules contained in this directory (though it is unsafe for your dock to load unnofficial modules)."), NULL},
410 {"testing", 'T', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
411 &bTesting,
412 _("For debugging purpose only. The crash manager will not be started to hunt down the bugs."), NULL},
413 {"easter-eggs", 'E', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
414 &g_bEasterEggs,
415 _("For debugging purpose only. Some hidden and still unstable options will be activated."), NULL},
416 {NULL, 0, 0, 0,
417 NULL,
418 NULL, NULL}
419 };
420
421 GOptionContext *context = g_option_context_new ("Cairo-Dock");
422 g_option_context_add_main_entries (context, pOptionsTable, NULL);
423 g_option_context_parse (context, &argc, &argv, &erreur);
424 if (erreur != NULL)
425 {
426 cd_error ("ERROR in options: %s", erreur->message);
427 return 1;
428 }
429
430 if (bPrintVersion)
431 {
432 g_print ("%s\n", CAIRO_DOCK_VERSION);
433 return 0;
434 }
435
436 if (g_bLocked)
437 cd_warning ("Cairo-Dock will be locked.");
438
439 if (cVerbosity != NULL)
440 {
441 cd_log_set_level_from_name (cVerbosity);
442 g_free (cVerbosity);
443 }
444
445 if (bForceColors)
446 cd_log_force_use_color ();
447
448 CairoDockDesktopEnv iDesktopEnv = CAIRO_DOCK_UNKNOWN_ENV;
449 if (cEnvironment != NULL)
450 {
451 if (strcmp (cEnvironment, "gnome") == 0)
452 iDesktopEnv = CAIRO_DOCK_GNOME;
453 else if (strcmp (cEnvironment, "kde") == 0)
454 iDesktopEnv = CAIRO_DOCK_KDE;
455 else if (strcmp (cEnvironment, "xfce") == 0)
456 iDesktopEnv = CAIRO_DOCK_XFCE;
457 else if (strcmp (cEnvironment, "none") == 0)
458 iDesktopEnv = CAIRO_DOCK_UNKNOWN_ENV;
459 else
460 cd_warning ("Unknown environment '%s'", cEnvironment);
461 g_free (cEnvironment);
462 }
463
464 if (bCappuccino)
465 {
466 const gchar *cCappuccino = _("Cairo-Dock makes anything, including coffee !");
467 g_print ("%s\n", cCappuccino);
468 return 0;
469 }
470
471 //\___________________ get global config.
472 gboolean bFirstLaunch = FALSE;
473 gchar *cRootDataDirPath;
474 // if the user has specified the '-d' parameter.
475 if (cUserDefinedDataDir != NULL)
476 {
477 // if 'cRootDataDirPath' is not a full path, we will have a few problems with image in the config panel without a full path (e.g. 'bg.svg' in the default theme)
478 if (*cUserDefinedDataDir == '/')
479 cRootDataDirPath = cUserDefinedDataDir;
480 else if (*cUserDefinedDataDir == '~')
481 cRootDataDirPath = g_strdup_printf ("%s%s", getenv("HOME"), cUserDefinedDataDir + 1);
482 else
483 cRootDataDirPath = g_strdup_printf ("%s/%s", g_get_current_dir(), cUserDefinedDataDir);
484 cUserDefinedDataDir = NULL;
485 }
486 else
487 {
488 cRootDataDirPath = g_strdup_printf ("%s/.config/%s", getenv("HOME"), CAIRO_DOCK_DATA_DIR);
489 }
490 bFirstLaunch = ! g_file_test (cRootDataDirPath, G_FILE_TEST_IS_DIR);
491 _cairo_dock_get_global_config (cRootDataDirPath);
492 if (bAskBackend)
493 {
494 g_free (s_cDefaulBackend);
495 s_cDefaulBackend = NULL;
496 }
497
498 //\___________________ delay the startup if specified.
499 if (iDelay > 0)
500 {
501 sleep (iDelay);
502 }
503
504 //\___________________ initialize libgldi.
505 GldiRenderingMethod iRendering = (bForceOpenGL ? GLDI_OPENGL : g_bForceCairo ? GLDI_CAIRO : GLDI_DEFAULT);
506 gldi_init (iRendering);
507
508 //\___________________ set custom user options.
509 if (bKeepAbove)
510 cairo_dock_force_docks_above ();
511
512 if (bNoSticky)
513 cairo_dock_set_containers_non_sticky ();
514
515 if (bMetacityWorkaround)
516 cairo_dock_disable_containers_opacity ();
517
518 if (iDesktopEnv != CAIRO_DOCK_UNKNOWN_ENV)
519 cairo_dock_fm_force_desktop_env (iDesktopEnv);
520
521 if (bToggleIndirectRendering)
522 gldi_gl_backend_force_indirect_rendering ();
523
524 gchar *cExtraDirPath = g_strconcat (cRootDataDirPath, "/"CAIRO_DOCK_EXTRAS_DIR, NULL);
525 gchar *cThemesDirPath = g_strconcat (cRootDataDirPath, "/"CAIRO_DOCK_THEMES_DIR, NULL);
526 gchar *cCurrentThemeDirPath = g_strconcat (cRootDataDirPath, "/"CAIRO_DOCK_CURRENT_THEME_NAME, NULL);
527
528 cairo_dock_set_paths (cRootDataDirPath, cExtraDirPath, cThemesDirPath, cCurrentThemeDirPath, (gchar*)CAIRO_DOCK_SHARE_THEMES_DIR, (gchar*)CAIRO_DOCK_DISTANT_THEMES_DIR, cThemeServerAdress ? cThemeServerAdress : g_strdup (CAIRO_DOCK_THEME_SERVER));
529
530 //\___________________ Check that OpenGL is safely usable, if not ask the user what to do.
531 if (bAskBackend || (g_bUseOpenGL && ! bForceOpenGL && ! bToggleIndirectRendering && ! gldi_gl_backend_is_safe ())) // opengl disponible sans l'avoir force mais pas safe => on demande confirmation.
532 {
533 if (s_cDefaulBackend == NULL) // pas de backend par defaut defini.
534 {
535 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Use OpenGL in Cairo-Dock"),
536 NULL,
537 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
538 _("Yes"),
539 GTK_RESPONSE_YES,
540 _("No"),
541 GTK_RESPONSE_NO,
542 NULL);
543 GtkWidget *label = gtk_label_new (_("OpenGL allows you to use the hardware acceleration, reducing the CPU load to the minimum.\nIt also allows some pretty visual effects similar to Compiz.\nHowever, some cards and/or their drivers don't fully support it, which may prevent the dock from running correctly.\nDo you want to activate OpenGL ?\n (To not show this dialog, launch the dock from the Application menu,\n or with the -o option to force OpenGL and -c to force cairo.)"));
544 GtkWidget *pContentBox = gtk_dialog_get_content_area (GTK_DIALOG(dialog));
545
546 gtk_box_pack_start (GTK_BOX (pContentBox), label, FALSE, FALSE, 0);
547
548 GtkWidget *pAskBox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
549 gtk_box_pack_start (GTK_BOX (pContentBox), pAskBox, FALSE, FALSE, 0);
550 label = gtk_label_new (_("Remember this choice"));
551 GtkWidget *pCheckBox = gtk_check_button_new ();
552 gtk_box_pack_end (GTK_BOX (pAskBox), pCheckBox, FALSE, FALSE, 0);
553 gtk_box_pack_end (GTK_BOX (pAskBox), label, FALSE, FALSE, 0);
554
555 gtk_widget_show_all (dialog);
556
557 gint iAnswer = gtk_dialog_run (GTK_DIALOG (dialog)); // lance sa propre main loop, c'est pourquoi on peut le faire avant le gtk_main().
558 gboolean bRememberChoice = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pCheckBox));
559 gtk_widget_destroy (dialog);
560 if (iAnswer == GTK_RESPONSE_NO)
561 {
562 gldi_gl_backend_deactivate ();
563 }
564
565 if (bRememberChoice) // l'utilisateur a defini le choix par defaut.
566 {
567 s_cDefaulBackend = g_strdup (iAnswer == GTK_RESPONSE_NO ? "cairo" : "opengl");
568 gchar *cConfFilePath = g_strdup_printf ("%s/.cairo-dock", g_cCairoDockDataDir);
569 cairo_dock_update_conf_file (cConfFilePath,
570 G_TYPE_STRING, "Launch", "default backend", s_cDefaulBackend,
571 G_TYPE_INVALID);
572 g_free (cConfFilePath);
573 }
574 }
575 else if (strcmp (s_cDefaulBackend, "opengl") != 0) // un backend par defaut qui n'est pas OpenGL.
576 {
577 gldi_gl_backend_deactivate ();
578 }
579 }
580 g_print ("\n"
581 " ============================================================================\n"
582 "\tCairo-Dock version : %s\n"
583 "\tCompiled date : %s %s\n"
584 "\tBuilt with GTK : %d.%d\n"
585 "\tRunning with OpenGL: %d\n"
586 " ============================================================================\n\n",
587 CAIRO_DOCK_VERSION,
588 __DATE__, __TIME__,
589 GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
590 g_bUseOpenGL);
591
592 //\___________________ load plug-ins (must be done after everything is initialized).
593 if (! bSafeMode)
594 {
595 gldi_modules_new_from_directory (NULL, &erreur); // load gldi-based plug-ins
596 if (erreur != NULL)
597 {
598 cd_warning ("%s\n no module will be available", erreur->message);
599 g_error_free (erreur);
600 erreur = NULL;
601 }
602
603 if (cUserDefinedModuleDir != NULL)
604 {
605 gldi_modules_new_from_directory (cUserDefinedModuleDir, &erreur); // load user plug-ins
606 if (erreur != NULL)
607 {
608 cd_warning ("%s\n no additionnal module will be available", erreur->message);
609 g_error_free (erreur);
610 erreur = NULL;
611 }
612 g_free (cUserDefinedModuleDir);
613 cUserDefinedModuleDir = NULL;
614 }
615 }
616
617 //\___________________ define GUI backend.
618 cairo_dock_load_user_gui_backend (s_iGuiMode);
619
620 //\___________________ register to the useful notifications.
621 gldi_object_register_notification (&myContainerObjectMgr,
622 NOTIFICATION_DROP_DATA,
623 (GldiNotificationFunc) cairo_dock_notification_drop_data,
624 GLDI_RUN_AFTER, NULL);
625 gldi_object_register_notification (&myContainerObjectMgr,
626 NOTIFICATION_CLICK_ICON,
627 (GldiNotificationFunc) cairo_dock_notification_click_icon,
628 GLDI_RUN_AFTER, NULL);
629 gldi_object_register_notification (&myContainerObjectMgr,
630 NOTIFICATION_MIDDLE_CLICK_ICON,
631 (GldiNotificationFunc) cairo_dock_notification_middle_click_icon,
632 GLDI_RUN_AFTER, NULL);
633 gldi_object_register_notification (&myContainerObjectMgr,
634 NOTIFICATION_SCROLL_ICON,
635 (GldiNotificationFunc) cairo_dock_notification_scroll_icon,
636 GLDI_RUN_AFTER, NULL);
637 gldi_object_register_notification (&myContainerObjectMgr,
638 NOTIFICATION_BUILD_CONTAINER_MENU,
639 (GldiNotificationFunc) cairo_dock_notification_build_container_menu,
640 GLDI_RUN_FIRST, NULL);
641 gldi_object_register_notification (&myContainerObjectMgr,
642 NOTIFICATION_BUILD_ICON_MENU,
643 (GldiNotificationFunc) cairo_dock_notification_build_icon_menu,
644 GLDI_RUN_AFTER, NULL);
645
646 gldi_object_register_notification (&myDeskletObjectMgr,
647 NOTIFICATION_CONFIGURE_DESKLET,
648 (GldiNotificationFunc) cairo_dock_notification_configure_desklet,
649 GLDI_RUN_AFTER, NULL);
650 gldi_object_register_notification (&myDockObjectMgr,
651 NOTIFICATION_ICON_MOVED,
652 (GldiNotificationFunc) cairo_dock_notification_icon_moved,
653 GLDI_RUN_AFTER, NULL);
654 gldi_object_register_notification (&myDockObjectMgr,
655 NOTIFICATION_DESTROY,
656 (GldiNotificationFunc) cairo_dock_notification_dock_destroyed,
657 GLDI_RUN_AFTER, NULL);
658 gldi_object_register_notification (&myModuleObjectMgr,
659 NOTIFICATION_MODULE_ACTIVATED,
660 (GldiNotificationFunc) cairo_dock_notification_module_activated,
661 GLDI_RUN_AFTER, NULL);
662 gldi_object_register_notification (&myModuleObjectMgr,
663 NOTIFICATION_MODULE_REGISTERED,
664 (GldiNotificationFunc) cairo_dock_notification_module_registered,
665 GLDI_RUN_AFTER, NULL);
666 gldi_object_register_notification (&myModuleInstanceObjectMgr,
667 NOTIFICATION_MODULE_INSTANCE_DETACHED,
668 (GldiNotificationFunc) cairo_dock_notification_module_detached,
669 GLDI_RUN_AFTER, NULL);
670 gldi_object_register_notification (&myDockObjectMgr,
671 NOTIFICATION_INSERT_ICON,
672 (GldiNotificationFunc) cairo_dock_notification_icon_inserted,
673 GLDI_RUN_AFTER, NULL);
674 gldi_object_register_notification (&myDockObjectMgr,
675 NOTIFICATION_REMOVE_ICON,
676 (GldiNotificationFunc) cairo_dock_notification_icon_removed,
677 GLDI_RUN_AFTER, NULL);
678 gldi_object_register_notification (&myDeskletObjectMgr,
679 NOTIFICATION_DESTROY,
680 (GldiNotificationFunc) cairo_dock_notification_desklet_added_removed,
681 GLDI_RUN_AFTER, NULL);
682 gldi_object_register_notification (&myDeskletObjectMgr,
683 NOTIFICATION_NEW,
684 (GldiNotificationFunc) cairo_dock_notification_desklet_added_removed,
685 GLDI_RUN_AFTER, NULL);
686 gldi_object_register_notification (&myShortkeyObjectMgr,
687 NOTIFICATION_NEW,
688 (GldiNotificationFunc) cairo_dock_notification_shortkey_added_removed_changed,
689 GLDI_RUN_AFTER, NULL);
690 gldi_object_register_notification (&myShortkeyObjectMgr,
691 NOTIFICATION_DESTROY,
692 (GldiNotificationFunc) cairo_dock_notification_shortkey_added_removed_changed,
693 GLDI_RUN_AFTER, NULL);
694 gldi_object_register_notification (&myShortkeyObjectMgr,
695 NOTIFICATION_SHORTKEY_CHANGED,
696 (GldiNotificationFunc) cairo_dock_notification_shortkey_added_removed_changed,
697 GLDI_RUN_AFTER, NULL);
698
699 //\___________________ handle crashes.
700 if (! bTesting)
701 _cairo_dock_set_signal_interception ();
702
703 //\___________________ handle terminate signals to quit properly (especially when the system shuts down).
704 signal (SIGTERM, _cairo_dock_quit); // Term // kill -15 (system)
705 signal (SIGHUP, _cairo_dock_quit); // sent to a process when its controlling terminal is closed
706
707 //\___________________ Disable modules that have crashed
708 if (cExcludeModule != NULL && (s_iNbCrashes > 2 || bMaintenance)) // 3th crash or 4th (with -m)
709 {
710 gchar *cCommand = g_strdup_printf ("sed -i \"/modules/ s/%s//g\" \"%s\"",
711 cExcludeModule, g_cConfFile);
712 int r = system (cCommand);
713 if (r < 0)
714 cd_warning ("Not able to launch this command: %s", cCommand);
715 else
716 cd_warning (_("The module '%s' has been deactivated because it may "
717 "have caused some problems.\nYou can reactivate it, if it happens "
718 "again thanks to report it at http://glx-dock.org"), cExcludeModule);
719 g_free (cCommand);
720 }
721
722 //\___________________ maintenance mode -> show the main config panel.
723 if (bMaintenance)
724 {
725 cairo_dock_load_user_gui_backend (1); // force the advanced GUI, it can display the config before the theme is loaded.
726
727 GtkWidget *pWindow = cairo_dock_show_main_gui ();
728 gtk_window_set_title (GTK_WINDOW (pWindow), _("< Maintenance mode >"));
729 if (cExcludeModule != NULL)
730 cairo_dock_set_status_message_printf (pWindow, "%s '%s'...", _("Something went wrong with this applet:"), cExcludeModule);
731 gtk_window_set_modal (GTK_WINDOW (pWindow), TRUE);
732 GMainLoop *pBlockingLoop = g_main_loop_new (NULL, FALSE);
733 g_signal_connect (G_OBJECT (pWindow),
734 "destroy",
735 G_CALLBACK (on_delete_maintenance_gui),
736 pBlockingLoop);
737
738 cd_warning ("showing the maintenance mode ...");
739 g_main_loop_run (pBlockingLoop); // pas besoin de GDK_THREADS_LEAVE/ENTER vu qu'on est pas encore dans la main loop de GTK. En fait cette boucle va jouer le role de la main loop GTK.
740 cd_warning ("end of the maintenance mode.");
741
742 g_main_loop_unref (pBlockingLoop);
743 cairo_dock_load_user_gui_backend (s_iGuiMode); // go back to the user GUI.
744 }
745
746 //\___________________ load the current theme.
747 cd_message ("loading theme ...");
748 const gchar *cDesktopSessionEnv = g_getenv ("DESKTOP_SESSION");
749 if (! g_file_test (g_cConfFile, G_FILE_TEST_EXISTS)) // no theme yet, copy the default theme first.
750 {
751 const gchar *cThemeName;
752 if (g_strcmp0 (cDesktopSessionEnv, "cairo-dock") == 0)
753 {
754 cThemeName = "Default-Panel";
755 // We're using the CD session for the first time
756 s_bCDSessionLaunched = TRUE;
757 gchar *cConfFilePath = g_strdup_printf ("%s/.cairo-dock", g_cCairoDockDataDir);
758 cairo_dock_update_conf_file (cConfFilePath,
759 G_TYPE_BOOLEAN, "Launch", "cd session", s_bCDSessionLaunched,
760 G_TYPE_INVALID);
761 g_free (cConfFilePath);
762 }
763 else
764 cThemeName = "Default-Single";
765 gchar *cCommand = g_strdup_printf ("cp -r \"%s/%s\"/* \"%s\"", CAIRO_DOCK_SHARE_DATA_DIR"/themes", cThemeName, g_cCurrentThemePath);
766 cd_message (cCommand);
767 int r = system (cCommand);
768 if (r < 0)
769 cd_warning ("Not able to launch this command: %s", cCommand);
770 g_free (cCommand);
771 }
772 /* The first time the Cairo-Dock session is used but not the first time the
773 * dock is launched: propose to use the Default-Panel theme if a second
774 * dock is not used (case: the user has already launched the dock and he
775 * wants to test the Cairo-Dock session: propose a theme with two docks)
776 */
777 else if (! s_bCDSessionLaunched && g_strcmp0 (cDesktopSessionEnv, "cairo-dock") == 0)
778 {
779 gchar *cSecondDock = g_strdup_printf ("%s/"CAIRO_DOCK_MAIN_DOCK_NAME"-2.conf", g_cCurrentThemePath);
780 if (! g_file_test (cSecondDock, G_FILE_TEST_EXISTS))
781 {
782 GtkWidget *pDialog = gtk_dialog_new_with_buttons (_("You're using our Cairo-Dock session"),
783 NULL,
784 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
785 _("Yes"), GTK_RESPONSE_YES,
786 _("No"), GTK_RESPONSE_NO,
787 NULL);
788 GtkWidget *pLabel = gtk_label_new (_("It can be interesting to use an adapted theme for this session.\n\nDo you want to load our \"Default-Panel\" theme?\n\nNote: your current theme will be saved and can be reimported later from the Themes manager"));
789
790 GtkWidget *pContentBox = gtk_dialog_get_content_area (GTK_DIALOG (pDialog));
791 gtk_box_pack_start (GTK_BOX (pContentBox), pLabel, FALSE, FALSE, 0);
792 gtk_widget_show_all (pDialog);
793
794 gint iAnswer = gtk_dialog_run (GTK_DIALOG (pDialog)); // will block the main loop
795 gtk_widget_destroy (pDialog);
796 if (iAnswer == GTK_RESPONSE_YES)
797 {
798 time_t epoch = (time_t) time (NULL);
799 struct tm currentTime;
800 localtime_r (&epoch, ¤tTime);
801 char cDateBuffer[22+1];
802 strftime (cDateBuffer, 22, "Theme_%Y%m%d_%H%M%S", ¤tTime);
803
804 cairo_dock_export_current_theme (cDateBuffer, TRUE, TRUE);
805 cairo_dock_import_theme ("Default-Panel", TRUE, TRUE);
806 }
807
808 // Force init script
809 g_timeout_add_seconds (4, _cairo_dock_first_launch_setup, NULL);
810 }
811 g_free (cSecondDock);
812
813 // Update 'cd session' key: we already check that the user is using an adapted theme for this session
814 s_bCDSessionLaunched = TRUE;
815 gchar *cConfFilePath = g_strdup_printf ("%s/.cairo-dock", g_cCairoDockDataDir);
816 cairo_dock_update_conf_file (cConfFilePath,
817 G_TYPE_BOOLEAN, "Launch", "cd session", s_bCDSessionLaunched,
818 G_TYPE_INVALID);
819 g_free (cConfFilePath);
820 }
821 cairo_dock_load_current_theme ();
822
823 //\___________________ lock mode.
824 if (g_bLocked) // comme on ne pourra pas ouvrir le panneau de conf, ces 2 variables resteront tel quel.
825 {
826 myDocksParam.bLockIcons = TRUE;
827 myDocksParam.bLockAll = TRUE;
828 }
829
830 if (!bSafeMode && gldi_module_get_nb () <= 1) // 1 en comptant l'aide
831 {
832 Icon *pIcon = gldi_icons_get_any_without_dialog ();
833 gldi_dialog_show_temporary_with_icon (_("No plug-in were found.\nPlug-ins provide most of the functionalities (animations, applets, views, etc).\nSee http://glx-dock.org for more information.\nThere is almost no meaning in running the dock without them and it's probably due to a problem with the installation of these plug-ins.\nBut if you really want to use the dock without these plug-ins, you can launch the dock with the '-f' option to no longer have this message.\n"), pIcon, CAIRO_CONTAINER (g_pMainDock), 0., CAIRO_DOCK_SHARE_DATA_DIR"/"CAIRO_DOCK_ICON);
834 }
835
836 //\___________________ display the changelog in case of a new version.
837 gboolean bNewVersion = (s_cLastVersion == NULL || strcmp (s_cLastVersion, CAIRO_DOCK_VERSION) != 0);
838 if (bNewVersion)
839 {
840 gchar *cConfFilePath = g_strdup_printf ("%s/.cairo-dock", g_cCairoDockDataDir);
841 cairo_dock_update_conf_file (cConfFilePath,
842 G_TYPE_STRING, "Launch", "last version", CAIRO_DOCK_VERSION,
843 G_TYPE_INVALID);
844 g_free (cConfFilePath);
845
846 /// If any operation must be done on the user theme (like activating a module by default, or disabling an option), it should be done here once (when CAIRO_DOCK_VERSION matches the new version).
847 }
848
849 //g_print ("bFirstLaunch: %d; bNewVersion: %d\n", bFirstLaunch, bNewVersion);
850 if (bFirstLaunch) // first launch => set up config
851 {
852 g_timeout_add_seconds (4, _cairo_dock_first_launch_setup, NULL);
853 }
854 else if (bNewVersion) // new version -> changelog (if it's the first launch, useless to display what's new, we already have the Welcome message).
855 {
856 gchar *cChangeLogFilePath = g_strdup_printf ("%s/ChangeLog.txt", CAIRO_DOCK_SHARE_DATA_DIR);
857 GKeyFile *pKeyFile = cairo_dock_open_key_file (cChangeLogFilePath);
858 if (pKeyFile != NULL)
859 {
860 gchar *cKeyName = g_strdup_printf ("%d.%d.%d", g_iMajorVersion, g_iMinorVersion, g_iMicroVersion); // version without "alpha", "beta", "rc", etc.
861 gchar *cChangeLogMessage = g_key_file_get_string (pKeyFile, "ChangeLog", cKeyName, NULL);
862 g_free (cKeyName);
863 if (cChangeLogMessage != NULL)
864 {
865 GString *sChangeLogMessage = g_string_new (gettext (cChangeLogMessage));
866 g_free (cChangeLogMessage);
867
868 // changelog message is now split (by line): to not re-translate all the message when there is a modification
869 int i = 0;
870 while (TRUE)
871 {
872 cKeyName = g_strdup_printf ("%d.%d.%d.%d", g_iMajorVersion, g_iMinorVersion, g_iMicroVersion, i);
873 cChangeLogMessage = g_key_file_get_string (pKeyFile, "ChangeLog", cKeyName, NULL);
874 g_free (cKeyName);
875
876 if (cChangeLogMessage == NULL) // no more message
877 break;
878
879 g_string_append_printf (sChangeLogMessage, "\n %s", gettext (cChangeLogMessage));
880
881 g_free (cChangeLogMessage);
882 i++;
883 }
884
885 Icon *pFirstIcon = cairo_dock_get_first_icon (g_pMainDock->icons);
886
887 CairoDialogAttr attr;
888 memset (&attr, 0, sizeof (CairoDialogAttr));
889 attr.cText = sChangeLogMessage->str;
890 attr.cImageFilePath = CAIRO_DOCK_SHARE_DATA_DIR"/"CAIRO_DOCK_ICON;
891 attr.bUseMarkup = TRUE;
892 attr.pIcon = pFirstIcon;
893 attr.pContainer = CAIRO_CONTAINER (g_pMainDock);
894 gldi_dialog_new (&attr);
895 g_string_free (sChangeLogMessage, TRUE);
896 }
897 g_key_file_free (pKeyFile);
898 }
899 // In case something has changed in Compiz/Gtk/others, we also run the script on a new version of the dock.
900 g_timeout_add_seconds (4, _cairo_dock_first_launch_setup, NULL);
901 }
902 else if (cExcludeModule != NULL && ! bMaintenance && s_iNbCrashes > 1)
903 {
904 gchar *cMessage;
905 if (s_iNbCrashes == 2) // <=> second crash: display a dialogue
906 cMessage = g_strdup_printf (_("The module '%s' may have encountered a problem.\nIt has been restored successfully, but if it happens again, please report it at http://glx-dock.org"), cExcludeModule);
907 else // since the 3th crash: the applet has been disabled
908 cMessage = g_strdup_printf (_("The module '%s' has been deactivated because it may have caused some problems.\nYou can reactivate it, if it happens again thanks to report it at http://glx-dock.org"), cExcludeModule);
909
910 GldiModule *pModule = gldi_module_get (cExcludeModule);
911 Icon *icon = gldi_icons_get_any_without_dialog ();
912 gldi_dialog_show_temporary_with_icon (cMessage, icon, CAIRO_CONTAINER (g_pMainDock), 15000., (pModule ? pModule->pVisitCard->cIconFilePath : NULL));
913 g_free (cMessage);
914 }
915
916 if (! bTesting)
917 g_timeout_add_seconds (5, _cairo_dock_successful_launch, GINT_TO_POINTER (bFirstLaunch));
918
919 // Start Mainloop
920 gtk_main ();
921
922 signal (SIGSEGV, NULL); // Segmentation violation
923 signal (SIGFPE, NULL); // Floating-point exception
924 signal (SIGILL, NULL); // Illegal instruction
925 signal (SIGABRT, NULL);
926 signal (SIGTERM, NULL);
927 signal (SIGHUP, NULL);
928
929 gldi_free_all ();
930
931 #if (LIBRSVG_MAJOR_VERSION == 2 && LIBRSVG_MINOR_VERSION < 36)
932 rsvg_term ();
933 #endif
934 xmlCleanupParser ();
935 g_string_free (s_pLaunchCommand, TRUE);
936
937 cd_message ("Bye bye !");
938 g_print ("\033[0m\n");
939
940 return 0;
941 }
942