cwm-patched/calmwm.c

248 lines
5.6 KiB
C
Raw Normal View History

2007-04-27 12:58:48 -05:00
/*
* calmwm - the calm window manager
*
* Copyright (c) 2004 Marius Aamodt Eriksen <marius@monkey.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2007-04-27 12:58:48 -05:00
*
2011-05-11 08:53:51 -05:00
* $OpenBSD$
2007-04-27 12:58:48 -05:00
*/
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/wait.h>
#include <err.h>
#include <errno.h>
#include <getopt.h>
#include <limits.h>
#include <locale.h>
#include <poll.h>
#include <pwd.h>
#include <signal.h>
2012-11-08 21:52:02 -06:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
2007-04-27 12:58:48 -05:00
#include "calmwm.h"
Display *X_Dpy;
Time Last_Event_Time = CurrentTime;
Atom cwmh[CWMH_NITEMS];
Atom ewmh[EWMH_NITEMS];
struct screen_q Screenq = TAILQ_HEAD_INITIALIZER(Screenq);
struct conf Conf;
volatile sig_atomic_t cwm_status;
2007-04-27 12:58:48 -05:00
2014-09-06 11:24:32 -05:00
static void sighdlr(int);
static int x_errorhandler(Display *, XErrorEvent *);
static int x_init(const char *);
static void x_teardown(void);
static int x_wmerrorhandler(Display *, XErrorEvent *);
2007-04-27 12:58:48 -05:00
int
main(int argc, char **argv)
{
const char *conf_file = NULL;
char *conf_path, *display_name = NULL;
char *fallback;
int ch, xfd;
struct pollfd pfd[1];
struct passwd *pw;
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
warnx("no locale support");
mbtowc(NULL, NULL, MB_CUR_MAX);
fallback = u_argv(argv);
Conf.wm_argv = u_argv(argv);
while ((ch = getopt(argc, argv, "c:d:")) != -1) {
2007-04-27 12:58:48 -05:00
switch (ch) {
case 'c':
2008-05-19 13:53:09 -05:00
conf_file = optarg;
break;
case 'd':
display_name = optarg;
break;
2007-04-27 12:58:48 -05:00
default:
usage();
2007-04-27 12:58:48 -05:00
}
}
argc -= optind;
2007-05-21 02:53:11 -05:00
argv += optind;
2007-04-27 12:58:48 -05:00
2014-09-06 11:24:32 -05:00
if (signal(SIGCHLD, sighdlr) == SIG_ERR)
2008-04-15 15:24:41 -05:00
err(1, "signal");
if (signal(SIGHUP, sighdlr) == SIG_ERR)
err(1, "signal");
2007-04-27 12:58:48 -05:00
Conf.homedir = getenv("HOME");
if ((Conf.homedir == NULL) || (Conf.homedir[0] == '\0')) {
pw = getpwuid(getuid());
if (pw != NULL && pw->pw_dir != NULL && *pw->pw_dir != '\0')
Conf.homedir = pw->pw_dir;
else
Conf.homedir = "/";
}
if (conf_file == NULL)
xasprintf(&conf_path, "%s/%s", Conf.homedir, CONFFILE);
else
conf_path = xstrdup(conf_file);
if (access(conf_path, R_OK) != 0) {
if (conf_file != NULL)
warn("%s", conf_file);
free(conf_path);
conf_path = NULL;
}
conf_init(&Conf);
if (conf_path && (parse_config(conf_path, &Conf) == -1))
warnx("config file %s has errors", conf_path);
free(conf_path);
xfd = x_init(display_name);
cwm_status = CWM_RUNNING;
if (pledge("stdio rpath proc exec", NULL) == -1)
err(1, "pledge");
memset(&pfd, 0, sizeof(pfd));
pfd[0].fd = xfd;
pfd[0].events = POLLIN;
while (cwm_status == CWM_RUNNING) {
xev_process();
if (poll(pfd, 1, INFTIM) == -1) {
if (errno != EINTR)
warn("poll");
}
}
x_teardown();
if (cwm_status == CWM_EXEC_WM) {
u_exec(Conf.wm_argv);
warnx("'%s' failed to start, restarting fallback", Conf.wm_argv);
u_exec(fallback);
}
2007-04-27 12:58:48 -05:00
2014-09-07 14:27:30 -05:00
return(0);
2007-04-27 12:58:48 -05:00
}
static int
x_init(const char *dpyname)
2007-04-27 12:58:48 -05:00
{
int i;
2007-04-27 12:58:48 -05:00
if ((X_Dpy = XOpenDisplay(dpyname)) == NULL)
errx(1, "unable to open display \"%s\"", XDisplayName(dpyname));
2007-04-27 12:58:48 -05:00
XSetErrorHandler(x_wmerrorhandler);
XSelectInput(X_Dpy, DefaultRootWindow(X_Dpy), SubstructureRedirectMask);
XSync(X_Dpy, False);
2007-04-27 12:58:48 -05:00
XSetErrorHandler(x_errorhandler);
Conf.xrandr = XRRQueryExtension(X_Dpy, &Conf.xrandr_event_base, &i);
conf_atoms();
2013-06-17 12:11:10 -05:00
conf_cursor(&Conf);
2013-04-12 09:46:30 -05:00
for (i = 0; i < ScreenCount(X_Dpy); i++)
screen_init(i);
2017-12-22 15:30:01 -06:00
return ConnectionNumber(X_Dpy);
2007-04-27 12:58:48 -05:00
}
static void
x_teardown(void)
{
struct screen_ctx *sc;
unsigned int i;
conf_clear(&Conf);
TAILQ_FOREACH(sc, &Screenq, entry) {
for (i = 0; i < CWM_COLOR_NITEMS; i++)
XftColorFree(X_Dpy, DefaultVisual(X_Dpy, sc->which),
DefaultColormap(X_Dpy, sc->which),
&sc->xftcolor[i]);
XftFontClose(X_Dpy, sc->xftfont);
2016-09-28 19:30:40 -05:00
XftDrawDestroy(sc->menu.xftdraw);
XDestroyWindow(X_Dpy, sc->menu.win);
XUngrabKey(X_Dpy, AnyKey, AnyModifier, sc->rootwin);
}
XUngrabPointer(X_Dpy, CurrentTime);
XUngrabKeyboard(X_Dpy, CurrentTime);
for (i = 0; i < CF_NITEMS; i++)
XFreeCursor(X_Dpy, Conf.cursor[i]);
XSync(X_Dpy, False);
XSetInputFocus(X_Dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
XCloseDisplay(X_Dpy);
}
static int
x_wmerrorhandler(Display *dpy, XErrorEvent *e)
{
errx(1, "root window unavailable - perhaps another wm is running?");
2014-09-07 14:27:30 -05:00
return(0);
}
static int
2007-04-27 12:58:48 -05:00
x_errorhandler(Display *dpy, XErrorEvent *e)
{
2013-05-14 08:39:53 -05:00
#ifdef DEBUG
char msg[80], number[80], req[80];
2007-04-27 12:58:48 -05:00
XGetErrorText(X_Dpy, e->error_code, msg, sizeof(msg));
(void)snprintf(number, sizeof(number), "%d", e->request_code);
XGetErrorDatabaseText(X_Dpy, "XRequest", number,
"<unknown>", req, sizeof(req));
2007-04-27 12:58:48 -05:00
2014-01-03 09:29:06 -06:00
warnx("%s(0x%x): %s", req, (unsigned int)e->resourceid, msg);
2007-04-27 12:58:48 -05:00
#endif
2014-09-07 14:27:30 -05:00
return(0);
2007-04-27 12:58:48 -05:00
}
static void
2014-09-06 11:24:32 -05:00
sighdlr(int sig)
2007-04-27 12:58:48 -05:00
{
pid_t pid;
2014-09-06 11:24:32 -05:00
int save_errno = errno, status;
switch (sig) {
case SIGCHLD:
/* Collect dead children. */
while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) > 0 ||
(pid < 0 && errno == EINTR))
;
break;
case SIGHUP:
cwm_status = CWM_EXEC_WM;
break;
2014-09-06 11:24:32 -05:00
}
errno = save_errno;
2007-04-27 12:58:48 -05:00
}
__dead void
usage(void)
{
extern char *__progname;
(void)fprintf(stderr, "usage: %s [-c file] [-d display]\n",
__progname);
exit(1);
}