/*- * Copyright (c) 2001 Jordan DeLong * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "wm.h" /* general globals */ Display *display; /* our display connection */ Cursor cursor_default; /* default cursor (for root window) */ Cursor cursor_move; /* cursor used when moving windows */ Cursor cursor_place; /* cursor for interactive placement */ XContext client_context; /* window context with client_t * */ XContext root_context; /* context for root windows storing screen_t * */ XContext decor_context; /* context with a decor_t * for decor windows */ XContext plugin_context; /* used for override_redirect windows created by plugins */ int shape_base; /* event base for shape extension (0 == no shape ext) */ char *binary_name; /* the bin golem was launched as (for restarts, etc) */ char *homedir_path; /* path to the user's home directory */ volatile int restart_flag = 0; /* flag when set means golem needs to restart */ volatile char *restart_bin = NULL; /* what to restart when golem_restart = 1, or null */ /* X atoms and their names */ Atom atoms[NUM_ATOMS]; char *atom_names[NUM_ATOMS] = { "WM_PROTOCOLS", "WM_DELETE_WINDOW", "WM_CHANGE_STATE", "WM_STATE" }; /* * crash recovery; for segmentation violations we dump a * core and restart. */ static RETSIGTYPE handle_sigsegv(int no) { warnx("segmentation fault; dumping a corefile and restarting"); if (!fork()) abort(); execlp(binary_name, binary_name, NULL); exit(EXIT_FAILURE); } /* handle exiting children */ static RETSIGTYPE handle_sigchld(int no) { pid_t pid; int status; /* wait on all the pids that need to exit */ while (((pid = waitpid(-1, &status, WNOHANG)) > 0) || (pid < 0 && errno == EINTR)); } /* allow SIGUSR1 to restart the windowmanager */ static RETSIGTYPE handle_sigusr1(int no) { restart_flag = 1; restart_bin = binary_name; } /* setup signals, open display, parse the rcfile, and then go to our loop */ int main(int argc, char **argv) { /* if -v we just print version and exit */ if (argc > 1 && strcmp(argv[1], "-v") == 0) { printf("golem-" VERSION "\n" BUILD_INFO "\n" "Copyright (c) 2001 Jordan DeLong\n"); exit(0); } #ifdef I18N setlocale(LC_CTYPE,""); #endif binary_name = argv[0]; homedir_path = getenv("HOME"); signal(SIGCHLD, handle_sigchld); signal(SIGUSR1, handle_sigusr1); /* try to get a connection to the X server */ display = XOpenDisplay(NULL); if (display == NULL) errx(1, "unable to open display"); /* call startup routines */ warnx("initializing"); options_init(); plugin_init(); rcfile_parse(); screen_init(); image_init(); xinerama_init(); plugin_start(); screen_manage_existing(); options_clean(); /* * don't reg this 'till now, so we won't get in an infinite loop * during startup. */ signal(SIGSEGV, handle_sigsegv); /* * call the main event loop; the loop runs processing on incoming * X events until something sets restart_flag. whatever set * restart_flag may also set restart_bin, which we handle after * calling shutdown routines. */ event_loop(); /* call shutdown routines */ warnx("shutting down"); desktop_shutdown(); plugin_shutdown(); client_shutdown(); keys_shutdown(); decor_shutdown(); dgroup_shutdown(); pixmap_shutdown(); screen_shutdown(); xinerama_shutdown(); warnx("finished"); /* * if restart_bin isn't set, we simply exit. otherwise we need to * execve the appropriate binary in our place. */ if (restart_bin == binary_name) execlp(binary_name, binary_name, NULL); else if (restart_bin != NULL) execl(_PATH_BSHELL, "sh", "-c", restart_bin, NULL); return 0; }