/*-
* 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;
}
syntax highlighted by Code2HTML, v. 0.9.1