| File: | core/main.c |
| Warning: | line 429, column 18 Using a fixed address is not portable because that address will probably not be valid in all environments or platforms |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | |||
| 2 | ||||
| 3 | /* Croma main() */ | |||
| 4 | ||||
| 5 | /* | |||
| 6 | * Copyright (C) 2001 Havoc Pennington | |||
| 7 | * Copyright (C) 2006 Elijah Newren | |||
| 8 | * | |||
| 9 | * This program is free software; you can redistribute it and/or | |||
| 10 | * modify it under the terms of the GNU General Public License as | |||
| 11 | * published by the Free Software Foundation; either version 2 of the | |||
| 12 | * License, or (at your option) any later version. | |||
| 13 | * | |||
| 14 | * This program is distributed in the hope that it will be useful, but | |||
| 15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| 17 | * General Public License for more details. | |||
| 18 | * | |||
| 19 | * You should have received a copy of the GNU General Public License | |||
| 20 | * along with this program; if not, write to the Free Software | |||
| 21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | |||
| 22 | * 02110-1301, USA. | |||
| 23 | */ | |||
| 24 | ||||
| 25 | /** | |||
| 26 | * \file | |||
| 27 | * Program startup. | |||
| 28 | * Functions which parse the command-line arguments, create the display, | |||
| 29 | * kick everything off and then close down Croma when it's time to go. | |||
| 30 | */ | |||
| 31 | ||||
| 32 | /** | |||
| 33 | * \mainpage | |||
| 34 | * Croma - a boring window manager for the adult in you | |||
| 35 | * | |||
| 36 | * Many window managers are like Marshmallow Froot Loops; Croma | |||
| 37 | * is like Cheerios. | |||
| 38 | * | |||
| 39 | * The best way to get a handle on how the whole system fits together | |||
| 40 | * is discussed in doc/code-overview.txt; if you're looking for functions | |||
| 41 | * to investigate, read main(), meta_display_open(), and event_callback(). | |||
| 42 | */ | |||
| 43 | ||||
| 44 | #define _GNU_SOURCE | |||
| 45 | #define _XOPEN_SOURCE700 /* for putenv() and some signal-related functions */ | |||
| 46 | ||||
| 47 | #include <config.h> | |||
| 48 | #include "main.h" | |||
| 49 | #include "util.h" | |||
| 50 | #include "display-private.h" | |||
| 51 | #include "errors.h" | |||
| 52 | #include "ui.h" | |||
| 53 | #include "session.h" | |||
| 54 | #include "prefs.h" | |||
| 55 | #include "core.h" | |||
| 56 | ||||
| 57 | #include <glib-object.h> | |||
| 58 | #include <glib/gprintf.h> | |||
| 59 | ||||
| 60 | #include <stdlib.h> | |||
| 61 | #include <sys/types.h> | |||
| 62 | #include <sys/wait.h> | |||
| 63 | #include <stdio.h> | |||
| 64 | #include <string.h> | |||
| 65 | #include <signal.h> | |||
| 66 | #include <unistd.h> | |||
| 67 | #include <errno(*__errno_location ()).h> | |||
| 68 | #include <fcntl.h> | |||
| 69 | #include <locale.h> | |||
| 70 | #include <time.h> | |||
| 71 | #include <unistd.h> | |||
| 72 | ||||
| 73 | /** | |||
| 74 | * The exit code we'll return to our parent process when we eventually die. | |||
| 75 | */ | |||
| 76 | static MetaExitCode meta_exit_code = META_EXIT_SUCCESS; | |||
| 77 | ||||
| 78 | /** | |||
| 79 | * Handle on the main loop, so that we have an easy way of shutting Croma | |||
| 80 | * down. | |||
| 81 | */ | |||
| 82 | static GMainLoop *meta_main_loop = NULL((void*)0); | |||
| 83 | ||||
| 84 | /** | |||
| 85 | * If set, Croma will spawn an identical copy of itself immediately | |||
| 86 | * before quitting. | |||
| 87 | */ | |||
| 88 | static gboolean meta_restart_after_quit = FALSE(0); | |||
| 89 | ||||
| 90 | static void prefs_changed_callback (MetaPreference pref, | |||
| 91 | gpointer data); | |||
| 92 | ||||
| 93 | /** | |||
| 94 | * Prints log messages. If Croma was compiled with backtrace support, | |||
| 95 | * also prints a backtrace (see meta_print_backtrace()). | |||
| 96 | * | |||
| 97 | * \param log_domain the domain the error occurred in (we ignore this) | |||
| 98 | * \param log_level the log level so that we can filter out less | |||
| 99 | * important messages | |||
| 100 | * \param message the message to log | |||
| 101 | * \param user_data arbitrary data (we ignore this) | |||
| 102 | */ | |||
| 103 | static void | |||
| 104 | log_handler (const gchar *log_domain, | |||
| 105 | GLogLevelFlags log_level, | |||
| 106 | const gchar *message, | |||
| 107 | gpointer user_data) | |||
| 108 | { | |||
| 109 | meta_warning ("Log level %d: %s\n", log_level, message); | |||
| 110 | meta_print_backtrace (); | |||
| 111 | } | |||
| 112 | ||||
| 113 | /** | |||
| 114 | * Prints the version notice. This is shown when Croma is called | |||
| 115 | * with the --version switch. | |||
| 116 | */ | |||
| 117 | static void | |||
| 118 | version (void) | |||
| 119 | { | |||
| 120 | const int latest_year = 2009; | |||
| 121 | char yearbuffer[256]; | |||
| 122 | GDate date; | |||
| 123 | ||||
| 124 | /* this is all so the string to translate stays constant. | |||
| 125 | * see how much we love the translators. | |||
| 126 | */ | |||
| 127 | g_date_set_dmy (&date, 1, G_DATE_JANUARY, latest_year); | |||
| 128 | if (g_date_strftime (yearbuffer, sizeof (yearbuffer), "%Y", &date)==0) | |||
| 129 | /* didn't work? fall back to decimal representation */ | |||
| 130 | g_sprintf (yearbuffer, "%d", latest_year); | |||
| 131 | ||||
| 132 | g_print (_("croma %s\n"dgettext ("croma", "croma %s\n" "Copyright (C) 2001-%s Havoc Pennington, Red Hat, Inc., and others\n" "This is free software; see the source for copying conditions.\n" "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" ) | |||
| 133 | "Copyright (C) 2001-%s Havoc Pennington, Red Hat, Inc., and others\n"dgettext ("croma", "croma %s\n" "Copyright (C) 2001-%s Havoc Pennington, Red Hat, Inc., and others\n" "This is free software; see the source for copying conditions.\n" "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" ) | |||
| 134 | "This is free software; see the source for copying conditions.\n"dgettext ("croma", "croma %s\n" "Copyright (C) 2001-%s Havoc Pennington, Red Hat, Inc., and others\n" "This is free software; see the source for copying conditions.\n" "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" ) | |||
| 135 | "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n")dgettext ("croma", "croma %s\n" "Copyright (C) 2001-%s Havoc Pennington, Red Hat, Inc., and others\n" "This is free software; see the source for copying conditions.\n" "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" ), | |||
| 136 | VERSION"1.25.1", yearbuffer); | |||
| 137 | exit (0); | |||
| 138 | } | |||
| 139 | ||||
| 140 | /** | |||
| 141 | * Prints a list of which configure script options were used to | |||
| 142 | * build this copy of Croma. This is actually always called | |||
| 143 | * on startup, but it's all no-op unless we're in verbose mode | |||
| 144 | * (see meta_set_verbose). | |||
| 145 | */ | |||
| 146 | static void | |||
| 147 | meta_print_compilation_info (void) | |||
| 148 | { | |||
| 149 | #ifdef HAVE_SHAPE | |||
| 150 | meta_verbosemeta_verbose_real ("Compiled with shape extension\n"); | |||
| 151 | #else | |||
| 152 | meta_verbosemeta_verbose_real ("Compiled without shape extension\n"); | |||
| 153 | #endif | |||
| 154 | #ifdef HAVE_XINERAMA | |||
| 155 | meta_topicmeta_topic_real (META_DEBUG_XINERAMA, "Compiled with Xinerama extension\n"); | |||
| 156 | #else | |||
| 157 | meta_topicmeta_topic_real (META_DEBUG_XINERAMA, "Compiled without Xinerama extension\n"); | |||
| 158 | #endif | |||
| 159 | #ifdef HAVE_XFREE_XINERAMA | |||
| 160 | meta_topicmeta_topic_real (META_DEBUG_XINERAMA, " (using XFree86 Xinerama)\n"); | |||
| 161 | #else | |||
| 162 | meta_topicmeta_topic_real (META_DEBUG_XINERAMA, " (not using XFree86 Xinerama)\n"); | |||
| 163 | #endif | |||
| 164 | #ifdef HAVE_SOLARIS_XINERAMA | |||
| 165 | meta_topicmeta_topic_real (META_DEBUG_XINERAMA, " (using Solaris Xinerama)\n"); | |||
| 166 | #else | |||
| 167 | meta_topicmeta_topic_real (META_DEBUG_XINERAMA, " (not using Solaris Xinerama)\n"); | |||
| 168 | #endif | |||
| 169 | #ifdef HAVE_XSYNC | |||
| 170 | meta_verbosemeta_verbose_real ("Compiled with sync extension\n"); | |||
| 171 | #else | |||
| 172 | meta_verbosemeta_verbose_real ("Compiled without sync extension\n"); | |||
| 173 | #endif | |||
| 174 | #ifdef HAVE_RANDR | |||
| 175 | meta_verbosemeta_verbose_real ("Compiled with randr extension\n"); | |||
| 176 | #else | |||
| 177 | meta_verbosemeta_verbose_real ("Compiled without randr extension\n"); | |||
| 178 | #endif | |||
| 179 | #ifdef HAVE_STARTUP_NOTIFICATION | |||
| 180 | meta_verbosemeta_verbose_real ("Compiled with startup notification\n"); | |||
| 181 | #else | |||
| 182 | meta_verbosemeta_verbose_real ("Compiled without startup notification\n"); | |||
| 183 | #endif | |||
| 184 | #ifdef HAVE_COMPOSITE_EXTENSIONS1 | |||
| 185 | meta_verbosemeta_verbose_real ("Compiled with composite extensions\n"); | |||
| 186 | #else | |||
| 187 | meta_verbosemeta_verbose_real ("Compiled without composite extensions\n"); | |||
| 188 | #endif | |||
| 189 | } | |||
| 190 | ||||
| 191 | /** | |||
| 192 | * Prints the version number, the current timestamp (not the | |||
| 193 | * build date), the locale, the character encoding, and a list | |||
| 194 | * of configure script options that were used to build this | |||
| 195 | * copy of Croma. This is actually always called | |||
| 196 | * on startup, but it's all no-op unless we're in verbose mode | |||
| 197 | * (see meta_set_verbose). | |||
| 198 | */ | |||
| 199 | static void | |||
| 200 | meta_print_self_identity (void) | |||
| 201 | { | |||
| 202 | char buf[256]; | |||
| 203 | GDate d; | |||
| 204 | const char *charset; | |||
| 205 | ||||
| 206 | /* Version and current date. */ | |||
| 207 | g_date_clear (&d, 1); | |||
| 208 | g_date_set_time_t (&d, time (NULL((void*)0))); | |||
| 209 | g_date_strftime (buf, sizeof (buf), "%x", &d); | |||
| 210 | meta_verbosemeta_verbose_real ("Croma version %s running on %s\n", | |||
| 211 | VERSION"1.25.1", buf); | |||
| 212 | ||||
| 213 | /* Locale and encoding. */ | |||
| 214 | g_get_charset (&charset); | |||
| 215 | meta_verbosemeta_verbose_real ("Running in locale \"%s\" with encoding \"%s\"\n", | |||
| 216 | setlocale (LC_ALL6, NULL((void*)0)), charset); | |||
| 217 | ||||
| 218 | /* Compilation settings. */ | |||
| 219 | meta_print_compilation_info (); | |||
| 220 | } | |||
| 221 | ||||
| 222 | /** | |||
| 223 | * The set of possible options that can be set on Croma's | |||
| 224 | * command line. This type exists so that meta_parse_options() can | |||
| 225 | * write to an instance of it. | |||
| 226 | */ | |||
| 227 | typedef struct | |||
| 228 | { | |||
| 229 | gchar *save_file; | |||
| 230 | gchar *display_name; | |||
| 231 | gchar *client_id; | |||
| 232 | gboolean replace_wm; | |||
| 233 | gboolean disable_sm; | |||
| 234 | gboolean print_version; | |||
| 235 | gboolean sync; | |||
| 236 | gboolean composite; | |||
| 237 | gboolean no_composite; | |||
| 238 | gboolean no_force_fullscreen; | |||
| 239 | } MetaArguments; | |||
| 240 | ||||
| 241 | #ifdef HAVE_COMPOSITE_EXTENSIONS1 | |||
| 242 | #define COMPOSITE_OPTS_FLAGS0 0 | |||
| 243 | #else /* HAVE_COMPOSITE_EXTENSIONS */ | |||
| 244 | /* No compositor, so don't show the arguments in --help */ | |||
| 245 | #define COMPOSITE_OPTS_FLAGS0 G_OPTION_FLAG_HIDDEN | |||
| 246 | #endif /* HAVE_COMPOSITE_EXTENSIONS */ | |||
| 247 | ||||
| 248 | /** | |||
| 249 | * Parses argc and argv and returns the | |||
| 250 | * arguments that Croma understands in meta_args. | |||
| 251 | * | |||
| 252 | * The strange call signature has to be written like it is so | |||
| 253 | * that g_option_context_parse() gets a chance to modify argc and | |||
| 254 | * argv. | |||
| 255 | * | |||
| 256 | * \param argc Pointer to the number of arguments Croma was given | |||
| 257 | * \param argv Pointer to the array of arguments Croma was given | |||
| 258 | * \param meta_args The result of parsing the arguments. | |||
| 259 | **/ | |||
| 260 | static void | |||
| 261 | meta_parse_options (int *argc, char ***argv, | |||
| 262 | MetaArguments *meta_args) | |||
| 263 | { | |||
| 264 | MetaArguments my_args = { .replace_wm = FALSE(0), | |||
| 265 | .disable_sm = FALSE(0), | |||
| 266 | .print_version = FALSE(0), | |||
| 267 | .sync = FALSE(0), | |||
| 268 | .composite = FALSE(0) }; | |||
| 269 | ||||
| 270 | GOptionEntry options[] = { | |||
| 271 | { | |||
| 272 | "sm-disable", 0, 0, G_OPTION_ARG_NONE, | |||
| 273 | &my_args.disable_sm, | |||
| 274 | N_("Disable connection to session manager")"Disable connection to session manager", | |||
| 275 | NULL((void*)0) | |||
| 276 | }, | |||
| 277 | { | |||
| 278 | "replace", 0, 0, G_OPTION_ARG_NONE, | |||
| 279 | &my_args.replace_wm, | |||
| 280 | N_("Replace the running window manager with Croma")"Replace the running window manager with Croma", | |||
| 281 | NULL((void*)0) | |||
| 282 | }, | |||
| 283 | { | |||
| 284 | "sm-client-id", 0, 0, G_OPTION_ARG_STRING, | |||
| 285 | &my_args.client_id, | |||
| 286 | N_("Specify session management ID")"Specify session management ID", | |||
| 287 | "ID" | |||
| 288 | }, | |||
| 289 | { | |||
| 290 | "display", 'd', 0, G_OPTION_ARG_STRING, | |||
| 291 | &my_args.display_name, N_("X Display to use")"X Display to use", | |||
| 292 | "DISPLAY" | |||
| 293 | }, | |||
| 294 | { | |||
| 295 | "sm-save-file", 0, 0, G_OPTION_ARG_FILENAME, | |||
| 296 | &my_args.save_file, | |||
| 297 | N_("Initialize session from savefile")"Initialize session from savefile", | |||
| 298 | "FILE" | |||
| 299 | }, | |||
| 300 | { | |||
| 301 | "version", 0, 0, G_OPTION_ARG_NONE, | |||
| 302 | &my_args.print_version, | |||
| 303 | N_("Print version")"Print version", | |||
| 304 | NULL((void*)0) | |||
| 305 | }, | |||
| 306 | { | |||
| 307 | "sync", 0, 0, G_OPTION_ARG_NONE, | |||
| 308 | &my_args.sync, | |||
| 309 | N_("Make X calls synchronous")"Make X calls synchronous", | |||
| 310 | NULL((void*)0) | |||
| 311 | }, | |||
| 312 | { | |||
| 313 | "composite", 'c', COMPOSITE_OPTS_FLAGS0, G_OPTION_ARG_NONE, | |||
| 314 | &my_args.composite, | |||
| 315 | N_("Turn compositing on")"Turn compositing on", | |||
| 316 | NULL((void*)0) | |||
| 317 | }, | |||
| 318 | { | |||
| 319 | "no-composite", 0, COMPOSITE_OPTS_FLAGS0, G_OPTION_ARG_NONE, | |||
| 320 | &my_args.no_composite, | |||
| 321 | N_("Turn compositing off")"Turn compositing off", | |||
| 322 | NULL((void*)0) | |||
| 323 | }, | |||
| 324 | { | |||
| 325 | "no-force-fullscreen", 0, COMPOSITE_OPTS_FLAGS0, G_OPTION_ARG_NONE, | |||
| 326 | &my_args.no_force_fullscreen, | |||
| 327 | N_("Don't make fullscreen windows that are maximized and have no decorations")"Don't make fullscreen windows that are maximized and have no decorations", | |||
| 328 | NULL((void*)0) | |||
| 329 | }, | |||
| 330 | {NULL((void*)0)} | |||
| 331 | }; | |||
| 332 | GOptionContext *ctx; | |||
| 333 | GError *error = NULL((void*)0); | |||
| 334 | ||||
| 335 | ctx = g_option_context_new (NULL((void*)0)); | |||
| 336 | g_option_context_add_main_entries (ctx, options, "croma"); | |||
| 337 | if (!g_option_context_parse (ctx, argc, argv, &error)) | |||
| 338 | { | |||
| 339 | g_print ("croma: %s\n", error->message); | |||
| 340 | exit(1); | |||
| 341 | } | |||
| 342 | g_option_context_free (ctx); | |||
| 343 | /* Return the parsed options through the meta_args param. */ | |||
| 344 | *meta_args = my_args; | |||
| 345 | } | |||
| 346 | ||||
| 347 | /** | |||
| 348 | * Selects which display Croma should use. It first tries to use | |||
| 349 | * display_name as the display. If display_name is NULL then | |||
| 350 | * try to use the environment variable CROMA_DISPLAY. If that | |||
| 351 | * also is NULL, use the default - :0.0 | |||
| 352 | */ | |||
| 353 | static void | |||
| 354 | meta_select_display (gchar *display_name) | |||
| 355 | { | |||
| 356 | gchar *envVar = ""; | |||
| 357 | if (display_name) | |||
| 358 | envVar = g_strconcat ("DISPLAY=", display_name, NULL((void*)0)); | |||
| 359 | else if (g_getenv ("CROMA_DISPLAY")) | |||
| 360 | envVar = g_strconcat ("DISPLAY=", | |||
| 361 | g_getenv ("CROMA_DISPLAY"), NULL((void*)0)); | |||
| 362 | /* DO NOT FREE envVar, putenv() sucks */ | |||
| 363 | putenv (envVar); | |||
| 364 | } | |||
| 365 | ||||
| 366 | static void | |||
| 367 | meta_finalize (void) | |||
| 368 | { | |||
| 369 | MetaDisplay *display = meta_get_display(); | |||
| 370 | if (display) | |||
| 371 | meta_display_close (display, | |||
| 372 | CurrentTime0L); /* I doubt correct timestamps matter here */ | |||
| 373 | ||||
| 374 | meta_session_shutdown (); | |||
| 375 | } | |||
| 376 | ||||
| 377 | static int sigterm_pipe_fds[2] = { -1, -1 }; | |||
| 378 | ||||
| 379 | static void | |||
| 380 | sigterm_handler (int signum) | |||
| 381 | { | |||
| 382 | if (sigterm_pipe_fds[1] >= 0) | |||
| 383 | { | |||
| 384 | G_GNUC_UNUSED__attribute__ ((__unused__)) int dummy; | |||
| 385 | ||||
| 386 | dummy = write (sigterm_pipe_fds[1], "", 1); | |||
| 387 | close (sigterm_pipe_fds[1]); | |||
| 388 | sigterm_pipe_fds[1] = -1; | |||
| 389 | } | |||
| 390 | } | |||
| 391 | ||||
| 392 | static gboolean | |||
| 393 | on_sigterm (GIOChannel *source, | |||
| 394 | GIOCondition condition, | |||
| 395 | gpointer user_data) | |||
| 396 | { | |||
| 397 | meta_quit (META_EXIT_SUCCESS); | |||
| 398 | return FALSE(0); | |||
| 399 | } | |||
| 400 | ||||
| 401 | /** | |||
| 402 | * This is where the story begins. It parses commandline options and | |||
| 403 | * environment variables, sets up the screen, hands control off to | |||
| 404 | * CTK, and cleans up afterwards. | |||
| 405 | * | |||
| 406 | * \param argc Number of arguments (as usual) | |||
| 407 | * \param argv Array of arguments (as usual) | |||
| 408 | * | |||
| 409 | * \bug It's a bit long. It would be good to split it out into separate | |||
| 410 | * functions. | |||
| 411 | */ | |||
| 412 | int | |||
| 413 | main (int argc, char **argv) | |||
| 414 | { | |||
| 415 | struct sigaction act; | |||
| 416 | sigset_t empty_mask; | |||
| 417 | MetaArguments meta_args; | |||
| 418 | const gchar *log_domains[] = { | |||
| 419 | NULL((void*)0), G_LOG_DOMAIN"croma", "Ctk", "Cdk", "GLib", | |||
| 420 | "Pango", "GLib-GObject", "GThread" | |||
| 421 | }; | |||
| 422 | guint i; | |||
| 423 | GIOChannel *channel; | |||
| 424 | ||||
| 425 | if (setlocale (LC_ALL6, "") == NULL((void*)0)) | |||
| ||||
| 426 | meta_warning ("Locale not understood by C library, internationalization will not work\n"); | |||
| 427 | ||||
| 428 | sigemptyset (&empty_mask); | |||
| 429 | act.sa_handler__sigaction_handler.sa_handler = SIG_IGN((__sighandler_t) 1); | |||
| ||||
| 430 | act.sa_mask = empty_mask; | |||
| 431 | act.sa_flags = 0; | |||
| 432 | if (sigaction (SIGPIPE13, &act, NULL((void*)0)) < 0) | |||
| 433 | g_printerr ("Failed to register SIGPIPE handler: %s\n", | |||
| 434 | g_strerror (errno(*__errno_location ()))); | |||
| 435 | #ifdef SIGXFSZ25 | |||
| 436 | if (sigaction (SIGXFSZ25, &act, NULL((void*)0)) < 0) | |||
| 437 | g_printerr ("Failed to register SIGXFSZ handler: %s\n", | |||
| 438 | g_strerror (errno(*__errno_location ()))); | |||
| 439 | #endif | |||
| 440 | ||||
| 441 | if (pipe (sigterm_pipe_fds) != 0) | |||
| 442 | g_printerr ("Failed to create SIGTERM pipe: %s\n", | |||
| 443 | g_strerror (errno(*__errno_location ()))); | |||
| 444 | ||||
| 445 | channel = g_io_channel_unix_new (sigterm_pipe_fds[0]); | |||
| 446 | g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL((void*)0)); | |||
| 447 | g_io_add_watch (channel, G_IO_IN, on_sigterm, NULL((void*)0)); | |||
| 448 | g_io_channel_set_close_on_unref (channel, TRUE(!(0))); | |||
| 449 | g_io_channel_unref (channel); | |||
| 450 | ||||
| 451 | act.sa_handler__sigaction_handler.sa_handler = &sigterm_handler; | |||
| 452 | if (sigaction (SIGTERM15, &act, NULL((void*)0)) < 0) | |||
| 453 | g_printerr ("Failed to register SIGTERM handler: %s\n", | |||
| 454 | g_strerror (errno(*__errno_location ()))); | |||
| 455 | ||||
| 456 | if (g_getenv ("CROMA_VERBOSE")) | |||
| 457 | meta_set_verbose (TRUE(!(0))); | |||
| 458 | if (g_getenv ("CROMA_DEBUG")) | |||
| 459 | meta_set_debugging (TRUE(!(0))); | |||
| 460 | ||||
| 461 | if (g_get_home_dir ()) | |||
| 462 | if (chdir (g_get_home_dir ()) < 0) | |||
| 463 | meta_warning ("Could not change to home directory %s.\n", | |||
| 464 | g_get_home_dir ()); | |||
| 465 | ||||
| 466 | meta_print_self_identity (); | |||
| 467 | ||||
| 468 | bindtextdomain (GETTEXT_PACKAGE"croma", CROMA_LOCALEDIR"/usr/share/locale"); | |||
| 469 | bind_textdomain_codeset (GETTEXT_PACKAGE"croma", "UTF-8"); | |||
| 470 | textdomain (GETTEXT_PACKAGE"croma"); | |||
| 471 | ||||
| 472 | /* Parse command line arguments.*/ | |||
| 473 | meta_parse_options (&argc, &argv, &meta_args); | |||
| 474 | ||||
| 475 | meta_set_syncing (meta_args.sync || (g_getenv ("CROMA_SYNC") != NULL((void*)0))); | |||
| 476 | ||||
| 477 | if (meta_args.print_version) | |||
| 478 | version (); | |||
| 479 | ||||
| 480 | meta_select_display (meta_args.display_name); | |||
| 481 | ||||
| 482 | if (meta_args.replace_wm) | |||
| 483 | meta_set_replace_current_wm (TRUE(!(0))); | |||
| 484 | ||||
| 485 | if (meta_args.save_file && meta_args.client_id) | |||
| 486 | meta_fatal ("Can't specify both SM save file and SM client id\n"); | |||
| 487 | ||||
| 488 | meta_main_loop = g_main_loop_new (NULL((void*)0), FALSE(0)); | |||
| 489 | ||||
| 490 | meta_ui_init (&argc, &argv); | |||
| 491 | ||||
| 492 | /* Load prefs */ | |||
| 493 | meta_prefs_init (); | |||
| 494 | meta_prefs_add_listener (prefs_changed_callback, NULL((void*)0)); | |||
| 495 | ||||
| 496 | ||||
| 497 | #if 1 | |||
| 498 | ||||
| 499 | for (i=0; i<G_N_ELEMENTS(log_domains)(sizeof (log_domains) / sizeof ((log_domains)[0])); i++) | |||
| 500 | g_log_set_handler (log_domains[i], | |||
| 501 | G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, | |||
| 502 | log_handler, NULL((void*)0)); | |||
| 503 | ||||
| 504 | #endif | |||
| 505 | ||||
| 506 | if (g_getenv ("CROMA_G_FATAL_WARNINGS") != NULL((void*)0)) | |||
| 507 | g_log_set_always_fatal (G_LOG_LEVEL_MASK); | |||
| 508 | ||||
| 509 | meta_ui_set_current_theme (meta_prefs_get_theme (), FALSE(0)); | |||
| 510 | ||||
| 511 | /* Try to find some theme that'll work if the theme preference | |||
| 512 | * doesn't exist. First try Simple (the default theme) then just | |||
| 513 | * try anything in the themes directory. | |||
| 514 | */ | |||
| 515 | if (!meta_ui_have_a_theme ()) | |||
| 516 | meta_ui_set_current_theme ("Simple", FALSE(0)); | |||
| 517 | ||||
| 518 | if (!meta_ui_have_a_theme ()) | |||
| 519 | { | |||
| 520 | const char *dir_entry = NULL((void*)0); | |||
| 521 | GError *err = NULL((void*)0); | |||
| 522 | GDir *themes_dir = NULL((void*)0); | |||
| 523 | ||||
| 524 | if (!(themes_dir = g_dir_open (CROMA_DATADIR"/usr/share""/themes", 0, &err))) | |||
| 525 | { | |||
| 526 | meta_fatal (_("Failed to scan themes directory: %s\n")dgettext ("croma", "Failed to scan themes directory: %s\n"), err->message); | |||
| 527 | g_error_free (err); | |||
| 528 | } | |||
| 529 | else | |||
| 530 | { | |||
| 531 | while (((dir_entry = g_dir_read_name (themes_dir)) != NULL((void*)0)) && | |||
| 532 | (!meta_ui_have_a_theme ())) | |||
| 533 | { | |||
| 534 | meta_ui_set_current_theme (dir_entry, FALSE(0)); | |||
| 535 | } | |||
| 536 | ||||
| 537 | g_dir_close (themes_dir); | |||
| 538 | } | |||
| 539 | } | |||
| 540 | ||||
| 541 | if (!meta_ui_have_a_theme ()) | |||
| 542 | meta_fatal (_("Could not find a theme! Be sure %s exists and contains the usual themes.\n")dgettext ("croma", "Could not find a theme! Be sure %s exists and contains the usual themes.\n" ), | |||
| 543 | CROMA_DATADIR"/usr/share""/themes"); | |||
| 544 | ||||
| 545 | /* Connect to SM as late as possible - but before managing display, | |||
| 546 | * or we might try to manage a window before we have the session | |||
| 547 | * info | |||
| 548 | */ | |||
| 549 | if (!meta_args.disable_sm) | |||
| 550 | { | |||
| 551 | if (meta_args.client_id == NULL((void*)0)) | |||
| 552 | { | |||
| 553 | const gchar *desktop_autostart_id; | |||
| 554 | ||||
| 555 | desktop_autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID"); | |||
| 556 | ||||
| 557 | if (desktop_autostart_id != NULL((void*)0)) | |||
| 558 | meta_args.client_id = g_strdup (desktop_autostart_id)g_strdup_inline (desktop_autostart_id); | |||
| 559 | } | |||
| 560 | ||||
| 561 | /* Unset DESKTOP_AUTOSTART_ID in order to avoid child processes to | |||
| 562 | * use the same client id. */ | |||
| 563 | g_unsetenv ("DESKTOP_AUTOSTART_ID"); | |||
| 564 | ||||
| 565 | meta_session_init (meta_args.client_id, meta_args.save_file); | |||
| 566 | } | |||
| 567 | /* Free memory possibly allocated by the argument parsing which are | |||
| 568 | * no longer needed. | |||
| 569 | */ | |||
| 570 | g_free (meta_args.save_file); | |||
| 571 | g_free (meta_args.display_name); | |||
| 572 | g_free (meta_args.client_id); | |||
| 573 | ||||
| 574 | if (meta_args.composite || meta_args.no_composite) | |||
| 575 | meta_prefs_set_force_compositing_manager (meta_args.composite); | |||
| 576 | ||||
| 577 | if (meta_args.no_force_fullscreen) | |||
| 578 | meta_prefs_set_force_fullscreen (FALSE(0)); | |||
| 579 | ||||
| 580 | if (!meta_display_open ()) | |||
| 581 | meta_exit (META_EXIT_ERROR); | |||
| 582 | ||||
| 583 | g_main_loop_run (meta_main_loop); | |||
| 584 | ||||
| 585 | meta_finalize (); | |||
| 586 | ||||
| 587 | if (meta_restart_after_quit) | |||
| 588 | { | |||
| 589 | GError *err; | |||
| 590 | ||||
| 591 | err = NULL((void*)0); | |||
| 592 | if (!g_spawn_async (NULL((void*)0), | |||
| 593 | argv, | |||
| 594 | NULL((void*)0), | |||
| 595 | G_SPAWN_SEARCH_PATH, | |||
| 596 | NULL((void*)0), | |||
| 597 | NULL((void*)0), | |||
| 598 | NULL((void*)0), | |||
| 599 | &err)) | |||
| 600 | { | |||
| 601 | meta_fatal (_("Failed to restart: %s\n")dgettext ("croma", "Failed to restart: %s\n"), | |||
| 602 | err->message); | |||
| 603 | g_error_free (err); /* not reached anyhow */ | |||
| 604 | meta_exit_code = META_EXIT_ERROR; | |||
| 605 | } | |||
| 606 | } | |||
| 607 | ||||
| 608 | return meta_exit_code; | |||
| 609 | } | |||
| 610 | ||||
| 611 | /** | |||
| 612 | * Stops Croma. This tells the event loop to stop processing; it is rather | |||
| 613 | * dangerous to use this rather than meta_restart() because this will leave | |||
| 614 | * the user with no window manager. We generally do this only if, for example, | |||
| 615 | * the session manager asks us to; we assume the session manager knows what | |||
| 616 | * it's talking about. | |||
| 617 | * | |||
| 618 | * \param code The success or failure code to return to the calling process. | |||
| 619 | */ | |||
| 620 | void | |||
| 621 | meta_quit (MetaExitCode code) | |||
| 622 | { | |||
| 623 | meta_exit_code = code; | |||
| 624 | ||||
| 625 | if (g_main_loop_is_running (meta_main_loop)) | |||
| 626 | g_main_loop_quit (meta_main_loop); | |||
| 627 | } | |||
| 628 | ||||
| 629 | /** | |||
| 630 | * Restarts Croma. In practice, this tells the event loop to stop | |||
| 631 | * processing, having first set the meta_restart_after_quit flag which | |||
| 632 | * tells Croma to spawn an identical copy of itself before quitting. | |||
| 633 | * This happens on receipt of a _CROMA_RESTART_MESSAGE client event. | |||
| 634 | */ | |||
| 635 | void | |||
| 636 | meta_restart (void) | |||
| 637 | { | |||
| 638 | meta_restart_after_quit = TRUE(!(0)); | |||
| 639 | meta_quit (META_EXIT_SUCCESS); | |||
| 640 | } | |||
| 641 | ||||
| 642 | /** | |||
| 643 | * Called on pref changes. (One of several functions of its kind and purpose.) | |||
| 644 | * | |||
| 645 | * \bug Why are these particular prefs handled in main.c and not others? | |||
| 646 | * Should they be? | |||
| 647 | * | |||
| 648 | * \param pref Which preference has changed | |||
| 649 | * \param data Arbitrary data (which we ignore) | |||
| 650 | */ | |||
| 651 | static void | |||
| 652 | prefs_changed_callback (MetaPreference pref, | |||
| 653 | gpointer data) | |||
| 654 | { | |||
| 655 | switch (pref) | |||
| 656 | { | |||
| 657 | case META_PREF_THEME: | |||
| 658 | meta_ui_set_current_theme (meta_prefs_get_theme (), FALSE(0)); | |||
| 659 | meta_display_retheme_all (); | |||
| 660 | break; | |||
| 661 | ||||
| 662 | case META_PREF_CURSOR_THEME: | |||
| 663 | case META_PREF_CURSOR_SIZE: | |||
| 664 | meta_display_set_cursor_theme (meta_prefs_get_cursor_theme (), | |||
| 665 | meta_prefs_get_cursor_size ()); | |||
| 666 | break; | |||
| 667 | case META_PREF_ICON_SIZE: | |||
| 668 | meta_invalidate_all_icons(); | |||
| 669 | break; | |||
| 670 | default: | |||
| 671 | /* handled elsewhere or otherwise */ | |||
| 672 | break; | |||
| 673 | } | |||
| 674 | } |