You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

420 lines
13 KiB

  1. /*
  2. * Copyright (C) 2008-2010 Nick Schermer <nick@xfce.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. */
  18. #ifdef HAVE_CONFIG_H
  19. #include <config.h>
  20. #endif
  21. #ifdef HAVE_STDIO_H
  22. #include <stdio.h>
  23. #endif
  24. #ifdef HAVE_STDLIB_H
  25. #include <stdlib.h>
  26. #endif
  27. #ifdef HAVE_UNISTD_H
  28. #include <unistd.h>
  29. #endif
  30. #ifdef HAVE_STRING_H
  31. #include <string.h>
  32. #endif
  33. #ifdef HAVE_SIGNAL_H
  34. #include <signal.h>
  35. #endif
  36. #include <glib.h>
  37. #include <dbus/dbus-glib.h>
  38. #include <libxfce4util/libxfce4util.h>
  39. #include <libxfce4ui/libxfce4ui.h>
  40. #include <common/panel-private.h>
  41. #include <common/panel-debug.h>
  42. #include <libxfce4panel/libxfce4panel.h>
  43. #include <panel/panel-application.h>
  44. #include <panel/panel-dbus-service.h>
  45. #include <panel/panel-dbus-client.h>
  46. #include <panel/panel-preferences-dialog.h>
  47. static gint opt_preferences = -1;
  48. static gint opt_add_items = -1;
  49. static gboolean opt_save = FALSE;
  50. static gchar *opt_add = NULL;
  51. static gboolean opt_restart = FALSE;
  52. static gboolean opt_quit = FALSE;
  53. static gboolean opt_version = FALSE;
  54. static gboolean opt_disable_wm_check = FALSE;
  55. static gchar *opt_plugin_event = NULL;
  56. static gchar **opt_arguments = NULL;
  57. static gchar *opt_socket_id = NULL;
  58. static gboolean panel_callback_handler (const gchar *name,
  59. const gchar *value,
  60. gpointer user_data,
  61. GError **error);
  62. /* command line options */
  63. #define PANEL_CALLBACK_OPTION G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, panel_callback_handler
  64. static GOptionEntry option_entries[] =
  65. {
  66. { "preferences", 'p', PANEL_CALLBACK_OPTION, N_("Show the 'Panel Preferences' dialog"), N_("PANEL-NUMBER") },
  67. { "add-items", 'a', PANEL_CALLBACK_OPTION, N_("Show the 'Add New Items' dialog"), N_("PANEL-NUMBER") },
  68. { "save", 's', 0, G_OPTION_ARG_NONE, &opt_save, N_("Save the panel configuration"), NULL },
  69. { "add", '\0', 0, G_OPTION_ARG_STRING, &opt_add, N_("Add a new plugin to the panel"), N_("PLUGIN-NAME") },
  70. { "restart", 'r', 0, G_OPTION_ARG_NONE, &opt_restart, N_("Restart the running panel instance"), NULL },
  71. { "quit", 'q', 0, G_OPTION_ARG_NONE, &opt_quit, N_("Quit the running panel instance"), NULL },
  72. { "disable-wm-check", 'd', 0, G_OPTION_ARG_NONE, &opt_disable_wm_check, N_("Do not wait for a window manager on startup"), NULL },
  73. { "version", 'V', 0, G_OPTION_ARG_NONE, &opt_version, N_("Print version information and exit"), NULL },
  74. { "plugin-event", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &opt_plugin_event, NULL, NULL },
  75. { "socket-id", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &opt_socket_id, NULL, NULL },
  76. { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &opt_arguments, NULL, NULL },
  77. { NULL }
  78. };
  79. static gboolean
  80. panel_callback_handler (const gchar *name,
  81. const gchar *value,
  82. gpointer user_data,
  83. GError **error)
  84. {
  85. panel_return_val_if_fail (name != NULL, FALSE);
  86. if (strcmp (name, "--preferences") == 0
  87. || strcmp (name, "-p") == 0)
  88. {
  89. opt_preferences = value != NULL ? MAX (0, atoi (value)) : 0;
  90. }
  91. else if (strcmp (name, "--add-items") == 0
  92. || strcmp (name, "-a") == 0)
  93. {
  94. opt_add_items = value != NULL ? MAX (0, atoi (value)) : 0;
  95. }
  96. else
  97. {
  98. panel_assert_not_reached ();
  99. return FALSE;
  100. }
  101. return TRUE;
  102. }
  103. static void
  104. panel_signal_handler (gint signum)
  105. {
  106. static gboolean was_triggered = FALSE;
  107. /* avoid recursing this handler if we receive a
  108. * signal before the mainloop is started */
  109. if (was_triggered)
  110. return;
  111. was_triggered = TRUE;
  112. panel_debug (PANEL_DEBUG_MAIN,
  113. "received signal %s <%d>, %s panel",
  114. g_strsignal (signum), signum,
  115. signum == SIGUSR1 ? "restarting" : "quiting");
  116. panel_dbus_service_exit_panel (signum == SIGUSR1);
  117. }
  118. static void
  119. panel_sm_client_quit (XfceSMClient *sm_client)
  120. {
  121. panel_return_if_fail (XFCE_IS_SM_CLIENT (sm_client));
  122. panel_return_if_fail (!panel_dbus_service_get_restart ());
  123. panel_debug (PANEL_DEBUG_MAIN,
  124. "terminate panel for session manager");
  125. gtk_main_quit ();
  126. }
  127. static void
  128. panel_debug_notify_proxy (void)
  129. {
  130. gchar *path;
  131. const gchar *proxy_cmd;
  132. if (G_UNLIKELY (panel_debug_has_domain (PANEL_DEBUG_GDB)))
  133. proxy_cmd = "gdb";
  134. else if (G_UNLIKELY (panel_debug_has_domain (PANEL_DEBUG_VALGRIND)))
  135. proxy_cmd = "valgrind";
  136. else
  137. return;
  138. path = g_find_program_in_path (proxy_cmd);
  139. if (G_LIKELY (path != NULL))
  140. {
  141. panel_debug (PANEL_DEBUG_MAIN,
  142. "running external plugins with %s, logs stored in %s",
  143. path, g_get_tmp_dir ());
  144. g_free (path);
  145. if (panel_debug_has_domain (PANEL_DEBUG_GDB))
  146. {
  147. /* performs sanity checks on the released memory slices */
  148. g_setenv ("G_SLICE", "debug-blocks", TRUE);
  149. }
  150. else if (panel_debug_has_domain (PANEL_DEBUG_VALGRIND))
  151. {
  152. /* use g_malloc() and g_free() instead of slices */
  153. g_setenv ("G_SLICE", "always-malloc", TRUE);
  154. g_setenv ("G_DEBUG", "gc-friendly", TRUE);
  155. }
  156. }
  157. else
  158. {
  159. panel_debug (PANEL_DEBUG_MAIN, "%s not found in PATH", proxy_cmd);
  160. }
  161. }
  162. gint
  163. main (gint argc, gchar **argv)
  164. {
  165. GOptionContext *context;
  166. PanelApplication *application;
  167. GError *error = NULL;
  168. PanelDBusService *dbus_service;
  169. gboolean succeed = FALSE;
  170. guint i;
  171. const gint signums[] = { SIGINT, SIGQUIT, SIGTERM, SIGABRT, SIGUSR1 };
  172. const gchar *error_msg;
  173. XfceSMClient *sm_client;
  174. panel_debug (PANEL_DEBUG_MAIN,
  175. "version %s on gtk+ %d.%d.%d (%d.%d.%d), glib %d.%d.%d (%d.%d.%d)",
  176. LIBXFCE4PANEL_VERSION,
  177. gtk_major_version, gtk_minor_version, gtk_micro_version,
  178. GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION,
  179. glib_major_version, glib_minor_version, glib_micro_version,
  180. GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
  181. /* inform the user about usage of gdb/valgrind */
  182. panel_debug_notify_proxy ();
  183. /* set translation domain */
  184. xfce_textdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8");
  185. #ifdef G_ENABLE_DEBUG
  186. /* do NOT remove this line for now, If something doesn't work,
  187. * fix your code instead! */
  188. g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
  189. #endif
  190. /* parse context options */
  191. context = g_option_context_new (_("[ARGUMENTS...]"));
  192. g_option_context_add_main_entries (context, option_entries, GETTEXT_PACKAGE);
  193. g_option_context_add_group (context, gtk_get_option_group (TRUE));
  194. g_option_context_add_group (context, xfce_sm_client_get_option_group (argc, argv));
  195. if (!g_option_context_parse (context, &argc, &argv, &error))
  196. {
  197. g_print ("%s: %s.\n", PACKAGE_NAME, error->message);
  198. g_print (_("Type \"%s --help\" for usage."), G_LOG_DOMAIN);
  199. g_print ("\n");
  200. g_error_free (error);
  201. return EXIT_FAILURE;
  202. }
  203. g_option_context_free (context);
  204. gtk_init (&argc, &argv);
  205. if (opt_version)
  206. {
  207. /* print version information */
  208. if (opt_arguments != NULL && *opt_arguments != NULL)
  209. g_print ("%s (%s)", *opt_arguments, PACKAGE_NAME);
  210. else
  211. g_print ("%s", PACKAGE_NAME);
  212. g_print (" %s (Xfce %s)\n\n", PACKAGE_VERSION, xfce_version_string ());
  213. g_print ("%s\n", "Copyright (c) 2004-2011");
  214. g_print ("\t%s\n\n", _("The Xfce development team. All rights reserved."));
  215. g_print (_("Please report bugs to <%s>."), PACKAGE_BUGREPORT);
  216. g_print ("\n");
  217. return EXIT_SUCCESS;
  218. }
  219. else if (opt_preferences >= 0)
  220. {
  221. /* send a signal to the running instance to show the preferences dialog */
  222. succeed = panel_dbus_client_display_preferences_dialog (opt_preferences, opt_socket_id, &error);
  223. goto dbus_return;
  224. }
  225. else if (opt_add_items >= 0)
  226. {
  227. /* send a signal to the running instance to show the add items dialog */
  228. succeed = panel_dbus_client_display_items_dialog (opt_add_items, &error);
  229. goto dbus_return;
  230. }
  231. else if (opt_save)
  232. {
  233. /* send a save signal to the running instance */
  234. succeed = panel_dbus_client_save (&error);
  235. goto dbus_return;
  236. }
  237. else if (opt_add != NULL)
  238. {
  239. /* send a add-new-item signal to the running instance */
  240. succeed = panel_dbus_client_add_new_item (opt_add, opt_arguments, &error);
  241. goto dbus_return;
  242. }
  243. else if (opt_restart || opt_quit)
  244. {
  245. /* send a terminate signal to the running instance */
  246. succeed = panel_dbus_client_terminate (opt_restart, &error);
  247. goto dbus_return;
  248. }
  249. else if (opt_plugin_event != NULL)
  250. {
  251. /* send the plugin event to the running instance */
  252. succeed = panel_dbus_client_plugin_event (opt_plugin_event, &error);
  253. goto dbus_return;
  254. }
  255. launch_panel:
  256. /* start dbus service */
  257. dbus_service = panel_dbus_service_get ();
  258. if (!panel_dbus_service_is_owner (dbus_service))
  259. {
  260. /* quit without error if an instance is running */
  261. succeed = TRUE;
  262. g_print ("%s: %s\n\n", G_LOG_DOMAIN, _("There is already a running instance"));
  263. goto dbus_return;
  264. }
  265. /* start session management */
  266. sm_client = xfce_sm_client_get ();
  267. xfce_sm_client_set_restart_style (sm_client, XFCE_SM_CLIENT_RESTART_IMMEDIATELY);
  268. xfce_sm_client_set_priority (sm_client, XFCE_SM_CLIENT_PRIORITY_CORE);
  269. g_signal_connect (G_OBJECT (sm_client), "quit",
  270. G_CALLBACK (panel_sm_client_quit), NULL);
  271. if (!xfce_sm_client_connect (sm_client, &error))
  272. {
  273. g_printerr ("%s: Failed to connect to session manager: %s\n",
  274. G_LOG_DOMAIN, error->message);
  275. g_clear_error (&error);
  276. }
  277. /* setup signal handlers to properly quit the main loop */
  278. for (i = 0; i < G_N_ELEMENTS (signums); i++)
  279. signal (signums[i], panel_signal_handler);
  280. application = panel_application_get ();
  281. panel_application_load (application, opt_disable_wm_check);
  282. /* open dialog if we started from launch_panel */
  283. if (opt_preferences >= 0)
  284. panel_preferences_dialog_show_from_id (opt_preferences, opt_socket_id);
  285. gtk_main ();
  286. /* make sure there are no incomming events when we close */
  287. g_object_unref (G_OBJECT (dbus_service));
  288. /* destroy all the opened dialogs */
  289. panel_application_destroy_dialogs (application);
  290. g_object_unref (G_OBJECT (application));
  291. g_object_unref (G_OBJECT (sm_client));
  292. if (panel_dbus_service_get_restart ())
  293. {
  294. /* spawn ourselfs again */
  295. g_print ("%s: %s\n\n", G_LOG_DOMAIN, _("Restarting..."));
  296. g_spawn_command_line_async (argv[0], NULL);
  297. }
  298. return EXIT_SUCCESS;
  299. dbus_return:
  300. /* stop any running startup notification */
  301. gdk_notify_startup_complete ();
  302. if (G_UNLIKELY (error != NULL))
  303. {
  304. /* get suitable error message */
  305. if (opt_preferences >= 0)
  306. error_msg = _("Failed to show the preferences dialog");
  307. else if (opt_add_items >= 0)
  308. error_msg = _("Failed to show the add new items dialog");
  309. else if (opt_save)
  310. error_msg = _("Failed to save the panel configuration");
  311. else if (opt_add)
  312. error_msg = _("Failed to add a plugin to the panel");
  313. else if (opt_restart)
  314. error_msg = _("Failed to restart the panel");
  315. else if (opt_quit)
  316. error_msg = _("Failed to quit the panel");
  317. else
  318. error_msg = _("Failed to send D-Bus message");
  319. /* show understandable message for this common error */
  320. if (error->code == DBUS_GERROR_NAME_HAS_NO_OWNER)
  321. {
  322. /* normally start the panel */
  323. if (opt_preferences >= 0 || opt_restart)
  324. {
  325. g_clear_error (&error);
  326. if (xfce_dialog_confirm (NULL, GTK_STOCK_EXECUTE, NULL,
  327. _("Do you want to start the panel? If you do, make sure "
  328. "you save the session on logout, so the panel is "
  329. "automatically started the next time you login."),
  330. _("No running instance of %s was found"), G_LOG_DOMAIN))
  331. {
  332. panel_debug (PANEL_DEBUG_MAIN, "user confirmed to start the panel");
  333. goto launch_panel;
  334. }
  335. else
  336. {
  337. return EXIT_FAILURE;
  338. }
  339. }
  340. else
  341. {
  342. /* I18N: %s is replaced with xfce4-panel */
  343. g_clear_error (&error);
  344. g_set_error (&error, 0, 0, _("No running instance of %s was found"), G_LOG_DOMAIN);
  345. }
  346. }
  347. /* show error dialog */
  348. xfce_dialog_show_error (NULL, error, "%s", error_msg);
  349. g_error_free (error);
  350. }
  351. return succeed ? EXIT_SUCCESS : EXIT_FAILURE;
  352. }