00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00044 #define _GNU_SOURCE
00045 #define _SVID_SOURCE
00046
00047 #include <config.h>
00048 #include "main.h"
00049 #include "util.h"
00050 #include "display-private.h"
00051 #include "errors.h"
00052 #include "ui.h"
00053 #include "session.h"
00054 #include "prefs.h"
00055
00056 #include <glib-object.h>
00057
00058 #include <stdlib.h>
00059 #include <sys/types.h>
00060 #include <stdio.h>
00061 #include <string.h>
00062 #include <signal.h>
00063 #include <unistd.h>
00064 #include <errno.h>
00065 #include <fcntl.h>
00066 #include <locale.h>
00067 #include <time.h>
00068
00072 static MetaExitCode meta_exit_code = META_EXIT_SUCCESS;
00073
00078 static GMainLoop *meta_main_loop = NULL;
00079
00084 static gboolean meta_restart_after_quit = FALSE;
00085
00086 static void prefs_changed_callback (MetaPreference pref,
00087 gpointer data);
00088
00099 static void
00100 log_handler (const gchar *log_domain,
00101 GLogLevelFlags log_level,
00102 const gchar *message,
00103 gpointer user_data)
00104 {
00105 meta_warning ("Log level %d: %s\n", log_level, message);
00106 meta_print_backtrace ();
00107 }
00108
00113 static void
00114 version (void)
00115 {
00116 g_print (_("metacity %s\n"
00117 "Copyright (C) 2001-2008 Havoc Pennington, Red Hat, Inc., and others\n"
00118 "This is free software; see the source for copying conditions.\n"
00119 "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"),
00120 VERSION);
00121 exit (0);
00122 }
00123
00130 static void
00131 meta_print_compilation_info (void)
00132 {
00133 #ifdef HAVE_SHAPE
00134 meta_verbose ("Compiled with shape extension\n");
00135 #else
00136 meta_verbose ("Compiled without shape extension\n");
00137 #endif
00138 #ifdef HAVE_XINERAMA
00139 meta_topic (META_DEBUG_XINERAMA, "Compiled with Xinerama extension\n");
00140 #else
00141 meta_topic (META_DEBUG_XINERAMA, "Compiled without Xinerama extension\n");
00142 #endif
00143 #ifdef HAVE_XFREE_XINERAMA
00144 meta_topic (META_DEBUG_XINERAMA, " (using XFree86 Xinerama)\n");
00145 #else
00146 meta_topic (META_DEBUG_XINERAMA, " (not using XFree86 Xinerama)\n");
00147 #endif
00148 #ifdef HAVE_SOLARIS_XINERAMA
00149 meta_topic (META_DEBUG_XINERAMA, " (using Solaris Xinerama)\n");
00150 #else
00151 meta_topic (META_DEBUG_XINERAMA, " (not using Solaris Xinerama)\n");
00152 #endif
00153 #ifdef HAVE_XSYNC
00154 meta_verbose ("Compiled with sync extension\n");
00155 #else
00156 meta_verbose ("Compiled without sync extension\n");
00157 #endif
00158 #ifdef HAVE_RANDR
00159 meta_verbose ("Compiled with randr extension\n");
00160 #else
00161 meta_verbose ("Compiled without randr extension\n");
00162 #endif
00163 #ifdef HAVE_STARTUP_NOTIFICATION
00164 meta_verbose ("Compiled with startup notification\n");
00165 #else
00166 meta_verbose ("Compiled without startup notification\n");
00167 #endif
00168 #ifdef HAVE_COMPOSITE_EXTENSIONS
00169 meta_verbose ("Compiled with composite extensions\n");
00170 #else
00171 meta_verbose ("Compiled without composite extensions\n");
00172 #endif
00173 }
00174
00183 static void
00184 meta_print_self_identity (void)
00185 {
00186 char buf[256];
00187 GDate d;
00188 const char *charset;
00189
00190
00191 g_date_clear (&d, 1);
00192 g_date_set_time_t (&d, time (NULL));
00193 g_date_strftime (buf, sizeof (buf), "%x", &d);
00194 meta_verbose ("Metacity version %s running on %s\n",
00195 VERSION, buf);
00196
00197
00198 g_get_charset (&charset);
00199 meta_verbose ("Running in locale \"%s\" with encoding \"%s\"\n",
00200 setlocale (LC_ALL, NULL), charset);
00201
00202
00203 meta_print_compilation_info ();
00204 }
00205
00211 typedef struct
00212 {
00213 gchar *save_file;
00214 gchar *display_name;
00215 gchar *client_id;
00216 gboolean replace_wm;
00217 gboolean disable_sm;
00218 gboolean print_version;
00219 gboolean sync;
00220 } MetaArguments;
00221
00234 static void
00235 meta_parse_options (int *argc, char ***argv,
00236 MetaArguments *meta_args)
00237 {
00238 MetaArguments my_args = {NULL, NULL, NULL, FALSE, FALSE, FALSE};
00239 GOptionEntry options[] = {
00240 {
00241 "sm-disable", 0, 0, G_OPTION_ARG_NONE,
00242 &my_args.disable_sm,
00243 N_("Disable connection to session manager"),
00244 NULL
00245 },
00246 {
00247 "replace", 0, 0, G_OPTION_ARG_NONE,
00248 &my_args.replace_wm,
00249 N_("Replace the running window manager with Metacity"),
00250 NULL
00251 },
00252 {
00253 "sm-client-id", 0, 0, G_OPTION_ARG_STRING,
00254 &my_args.client_id,
00255 N_("Specify session management ID"),
00256 "ID"
00257 },
00258 {
00259 "display", 0, 0, G_OPTION_ARG_STRING,
00260 &my_args.display_name, N_("X Display to use"),
00261 "DISPLAY"
00262 },
00263 {
00264 "sm-save-file", 0, 0, G_OPTION_ARG_FILENAME,
00265 &my_args.save_file,
00266 N_("Initialize session from savefile"),
00267 "FILE"
00268 },
00269 {
00270 "version", 0, 0, G_OPTION_ARG_NONE,
00271 &my_args.print_version,
00272 N_("Print version"),
00273 NULL
00274 },
00275 {
00276 "sync", 0, 0, G_OPTION_ARG_NONE,
00277 &my_args.sync,
00278 N_("Make X calls synchronous"),
00279 NULL
00280 },
00281 {NULL}
00282 };
00283 GOptionContext *ctx;
00284 GError *error = NULL;
00285
00286 ctx = g_option_context_new (NULL);
00287 g_option_context_add_main_entries (ctx, options, "metacity");
00288 if (!g_option_context_parse (ctx, argc, argv, &error))
00289 {
00290 g_print ("metacity: %s\n", error->message);
00291 exit(1);
00292 }
00293 g_option_context_free (ctx);
00294
00295 *meta_args = my_args;
00296 }
00297
00304 static
00305 void meta_select_display (gchar *display_name)
00306 {
00307 gchar *envVar = "";
00308 if (display_name)
00309 envVar = g_strconcat ("DISPLAY=", display_name, NULL);
00310 else if (g_getenv ("METACITY_DISPLAY"))
00311 envVar = g_strconcat ("DISPLAY=",
00312 g_getenv ("METACITY_DISPLAY"), NULL);
00313
00314 putenv (envVar);
00315 }
00316
00328 int
00329 main (int argc, char **argv)
00330 {
00331 struct sigaction act;
00332 sigset_t empty_mask;
00333 MetaArguments meta_args;
00334 const gchar *log_domains[] = {
00335 NULL, G_LOG_DOMAIN, "Gtk", "Gdk", "GLib",
00336 "Pango", "GLib-GObject", "GThread"
00337 };
00338 guint i;
00339
00340 if (setlocale (LC_ALL, "") == NULL)
00341 meta_warning ("Locale not understood by C library, internationalization will not work\n");
00342
00343 sigemptyset (&empty_mask);
00344 act.sa_handler = SIG_IGN;
00345 act.sa_mask = empty_mask;
00346 act.sa_flags = 0;
00347 if (sigaction (SIGPIPE, &act, NULL) < 0)
00348 g_printerr ("Failed to register SIGPIPE handler: %s\n",
00349 g_strerror (errno));
00350 #ifdef SIGXFSZ
00351 if (sigaction (SIGXFSZ, &act, NULL) < 0)
00352 g_printerr ("Failed to register SIGXFSZ handler: %s\n",
00353 g_strerror (errno));
00354 #endif
00355
00356 if (g_getenv ("METACITY_VERBOSE"))
00357 meta_set_verbose (TRUE);
00358 if (g_getenv ("METACITY_DEBUG"))
00359 meta_set_debugging (TRUE);
00360
00361 if (g_get_home_dir ())
00362 chdir (g_get_home_dir ());
00363
00364 meta_print_self_identity ();
00365
00366 bindtextdomain (GETTEXT_PACKAGE, METACITY_LOCALEDIR);
00367 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
00368 textdomain (GETTEXT_PACKAGE);
00369
00370
00371 meta_parse_options (&argc, &argv, &meta_args);
00372
00373 meta_set_syncing (meta_args.sync || (g_getenv ("METACITY_SYNC") != NULL));
00374
00375 if (meta_args.print_version)
00376 version ();
00377
00378 meta_select_display (meta_args.display_name);
00379
00380 if (meta_args.replace_wm)
00381 meta_set_replace_current_wm (TRUE);
00382
00383 if (meta_args.save_file && meta_args.client_id)
00384 meta_fatal ("Can't specify both SM save file and SM client id\n");
00385
00386 meta_main_loop = g_main_loop_new (NULL, FALSE);
00387
00388 g_type_init ();
00389
00390 meta_ui_init (&argc, &argv);
00391
00392
00393 meta_errors_init ();
00394
00395
00396 meta_prefs_init ();
00397 meta_prefs_add_listener (prefs_changed_callback, NULL);
00398
00399
00400 #if 1
00401
00402 for (i=0; i<G_N_ELEMENTS(log_domains); i++)
00403 g_log_set_handler (log_domains[i],
00404 G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
00405 log_handler, NULL);
00406
00407 #endif
00408
00409 if (g_getenv ("METACITY_G_FATAL_WARNINGS") != NULL)
00410 g_log_set_always_fatal (G_LOG_LEVEL_MASK);
00411
00412 meta_ui_set_current_theme (meta_prefs_get_theme (), FALSE);
00413
00414
00415
00416
00417
00418 if (!meta_ui_have_a_theme ())
00419 meta_ui_set_current_theme ("Simple", FALSE);
00420
00421 if (!meta_ui_have_a_theme ())
00422 {
00423 const char *dir_entry = NULL;
00424 GError *err = NULL;
00425 GDir *themes_dir = NULL;
00426
00427 if (!(themes_dir = g_dir_open (METACITY_DATADIR"/themes", 0, &err)))
00428 {
00429 meta_fatal (_("Failed to scan themes directory: %s\n"), err->message);
00430 g_error_free (err);
00431 }
00432 else
00433 {
00434 while (((dir_entry = g_dir_read_name (themes_dir)) != NULL) &&
00435 (!meta_ui_have_a_theme ()))
00436 {
00437 meta_ui_set_current_theme (dir_entry, FALSE);
00438 }
00439
00440 g_dir_close (themes_dir);
00441 }
00442 }
00443
00444 if (!meta_ui_have_a_theme ())
00445 meta_fatal (_("Could not find a theme! Be sure %s exists and contains the usual themes.\n"),
00446 METACITY_DATADIR"/themes");
00447
00448
00449
00450
00451
00452 if (!meta_args.disable_sm)
00453 {
00454 if (meta_args.client_id == NULL)
00455 {
00456 const gchar *desktop_autostart_id;
00457
00458 desktop_autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID");
00459
00460 if (desktop_autostart_id != NULL)
00461 meta_args.client_id = g_strdup (desktop_autostart_id);
00462 }
00463
00464
00465
00466 g_unsetenv ("DESKTOP_AUTOSTART_ID");
00467
00468 meta_session_init (meta_args.client_id, meta_args.save_file);
00469 }
00470
00471
00472
00473 g_free (meta_args.save_file);
00474 g_free (meta_args.display_name);
00475 g_free (meta_args.client_id);
00476
00477 if (!meta_display_open ())
00478 meta_exit (META_EXIT_ERROR);
00479
00480 g_main_loop_run (meta_main_loop);
00481
00482 meta_display_close (meta_get_display (),
00483 CurrentTime);
00484
00485 meta_session_shutdown ();
00486
00487 if (meta_restart_after_quit)
00488 {
00489 GError *err;
00490
00491 err = NULL;
00492 if (!g_spawn_async (NULL,
00493 argv,
00494 NULL,
00495 G_SPAWN_SEARCH_PATH,
00496 NULL,
00497 NULL,
00498 NULL,
00499 &err))
00500 {
00501 meta_fatal (_("Failed to restart: %s\n"),
00502 err->message);
00503 g_error_free (err);
00504 meta_exit_code = META_EXIT_ERROR;
00505 }
00506 }
00507
00508 return meta_exit_code;
00509 }
00510
00520 void
00521 meta_quit (MetaExitCode code)
00522 {
00523 meta_exit_code = code;
00524
00525 if (g_main_loop_is_running (meta_main_loop))
00526 g_main_loop_quit (meta_main_loop);
00527 }
00528
00535 void
00536 meta_restart (void)
00537 {
00538 meta_restart_after_quit = TRUE;
00539 meta_quit (META_EXIT_SUCCESS);
00540 }
00541
00551 static void
00552 prefs_changed_callback (MetaPreference pref,
00553 gpointer data)
00554 {
00555 switch (pref)
00556 {
00557 case META_PREF_THEME:
00558 meta_ui_set_current_theme (meta_prefs_get_theme (), FALSE);
00559 meta_display_retheme_all ();
00560 break;
00561
00562 case META_PREF_CURSOR_THEME:
00563 case META_PREF_CURSOR_SIZE:
00564 meta_display_set_cursor_theme (meta_prefs_get_cursor_theme (),
00565 meta_prefs_get_cursor_size ());
00566 break;
00567 default:
00568
00569 break;
00570 }
00571 }