2007-04-27 11:58:48 -06:00
|
|
|
/*
|
|
|
|
* calmwm - the calm window manager
|
|
|
|
*
|
|
|
|
* Copyright (c) 2004 Marius Aamodt Eriksen <marius@monkey.org>
|
|
|
|
*
|
2008-01-11 09:06:44 -07:00
|
|
|
* 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.
|
|
|
|
*
|
2018-02-09 12:54:54 -07:00
|
|
|
* $OpenBSD: calmwm.c,v 1.109 2018/02/09 19:54:54 okan Exp $
|
2007-04-27 11:58:48 -06:00
|
|
|
*/
|
|
|
|
|
2015-01-19 07:54:16 -07:00
|
|
|
#include <sys/types.h>
|
2009-12-14 21:10:42 -07:00
|
|
|
#include <sys/queue.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
|
|
|
|
#include <err.h>
|
|
|
|
#include <errno.h>
|
2009-12-14 20:34:34 -07:00
|
|
|
#include <getopt.h>
|
2015-01-19 07:54:16 -07:00
|
|
|
#include <limits.h>
|
2012-08-07 08:05:49 -06:00
|
|
|
#include <locale.h>
|
2017-12-27 10:04:35 -07:00
|
|
|
#include <poll.h>
|
2009-12-14 20:34:34 -07:00
|
|
|
#include <signal.h>
|
2012-11-08 20:52:02 -07:00
|
|
|
#include <stdio.h>
|
2009-12-14 21:10:42 -07:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
2009-12-14 20:34:34 -07:00
|
|
|
|
2007-04-27 11:58:48 -06:00
|
|
|
#include "calmwm.h"
|
|
|
|
|
2016-10-18 11:03:30 -06:00
|
|
|
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 11:58:48 -06:00
|
|
|
|
2014-09-06 10:24:32 -06:00
|
|
|
static void sighdlr(int);
|
2009-06-26 06:21:58 -06:00
|
|
|
static int x_errorhandler(Display *, XErrorEvent *);
|
2017-12-22 14:27:45 -07:00
|
|
|
static int x_init(const char *);
|
2009-04-15 08:01:45 -06:00
|
|
|
static void x_teardown(void);
|
2013-06-17 08:08:51 -06:00
|
|
|
static int x_wmerrorhandler(Display *, XErrorEvent *);
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
int
|
|
|
|
main(int argc, char **argv)
|
|
|
|
{
|
2018-02-09 12:54:54 -07:00
|
|
|
char *display_name = NULL;
|
2017-12-29 13:09:19 -07:00
|
|
|
char *fallback;
|
2017-12-22 14:27:45 -07:00
|
|
|
int ch, xfd;
|
2017-12-27 10:04:35 -07:00
|
|
|
struct pollfd pfd[1];
|
2007-05-10 11:23:49 -06:00
|
|
|
|
2012-08-07 08:05:49 -06:00
|
|
|
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
|
|
|
|
warnx("no locale support");
|
|
|
|
mbtowc(NULL, NULL, MB_CUR_MAX);
|
|
|
|
|
2018-02-09 12:54:54 -07:00
|
|
|
conf_init(&Conf);
|
|
|
|
|
2017-12-29 13:09:19 -07:00
|
|
|
fallback = u_argv(argv);
|
2016-10-18 11:03:30 -06:00
|
|
|
Conf.wm_argv = u_argv(argv);
|
2018-02-04 15:56:26 -07:00
|
|
|
while ((ch = getopt(argc, argv, "c:d:v")) != -1) {
|
2007-04-27 11:58:48 -06:00
|
|
|
switch (ch) {
|
2008-03-23 09:09:21 -06:00
|
|
|
case 'c':
|
2018-02-09 12:54:54 -07:00
|
|
|
free(Conf.conf_file);
|
|
|
|
Conf.conf_file = xstrdup(optarg);
|
2008-03-23 09:09:21 -06:00
|
|
|
break;
|
2007-05-10 11:23:49 -06:00
|
|
|
case 'd':
|
|
|
|
display_name = optarg;
|
|
|
|
break;
|
2018-02-04 15:56:26 -07:00
|
|
|
case 'v':
|
|
|
|
Conf.debug++;
|
|
|
|
break;
|
2007-04-27 11:58:48 -06:00
|
|
|
default:
|
2008-02-13 14:04:19 -07:00
|
|
|
usage();
|
2007-04-27 11:58:48 -06:00
|
|
|
}
|
|
|
|
}
|
2007-05-10 11:23:49 -06:00
|
|
|
argc -= optind;
|
2007-05-21 01:53:11 -06:00
|
|
|
argv += optind;
|
2007-04-27 11:58:48 -06:00
|
|
|
|
2014-09-06 10:24:32 -06:00
|
|
|
if (signal(SIGCHLD, sighdlr) == SIG_ERR)
|
2008-04-15 14:24:41 -06:00
|
|
|
err(1, "signal");
|
2017-12-27 11:46:18 -07:00
|
|
|
if (signal(SIGHUP, sighdlr) == SIG_ERR)
|
|
|
|
err(1, "signal");
|
2007-04-27 11:58:48 -06:00
|
|
|
|
2018-02-09 12:54:54 -07:00
|
|
|
if (parse_config(Conf.conf_file, &Conf) == -1)
|
|
|
|
warnx("error parsing config file");
|
2012-12-17 17:14:41 -07:00
|
|
|
|
2017-12-22 14:27:45 -07:00
|
|
|
xfd = x_init(display_name);
|
2014-01-22 14:48:27 -07:00
|
|
|
cwm_status = CWM_RUNNING;
|
2015-11-12 10:56:54 -07:00
|
|
|
|
|
|
|
if (pledge("stdio rpath proc exec", NULL) == -1)
|
|
|
|
err(1, "pledge");
|
|
|
|
|
2017-12-27 10:04:35 -07:00
|
|
|
memset(&pfd, 0, sizeof(pfd));
|
|
|
|
pfd[0].fd = xfd;
|
|
|
|
pfd[0].events = POLLIN;
|
|
|
|
while (cwm_status == CWM_RUNNING) {
|
2014-01-22 14:48:27 -07:00
|
|
|
xev_process();
|
2017-12-27 10:04:35 -07:00
|
|
|
if (poll(pfd, 1, INFTIM) == -1) {
|
|
|
|
if (errno != EINTR)
|
|
|
|
warn("poll");
|
|
|
|
}
|
|
|
|
}
|
2009-04-15 08:01:45 -06:00
|
|
|
x_teardown();
|
2018-01-02 07:04:58 -07:00
|
|
|
if (cwm_status == CWM_EXEC_WM) {
|
2016-10-18 11:03:30 -06:00
|
|
|
u_exec(Conf.wm_argv);
|
2018-02-09 12:54:54 -07:00
|
|
|
warnx("'%s' failed to start, starting fallback", Conf.wm_argv);
|
2018-01-02 07:04:58 -07:00
|
|
|
u_exec(fallback);
|
|
|
|
}
|
2017-12-29 13:09:19 -07:00
|
|
|
|
2014-09-07 13:27:30 -06:00
|
|
|
return(0);
|
2007-04-27 11:58:48 -06:00
|
|
|
}
|
|
|
|
|
2017-12-22 14:27:45 -07:00
|
|
|
static int
|
2013-06-17 08:08:51 -06:00
|
|
|
x_init(const char *dpyname)
|
2007-04-27 11:58:48 -06:00
|
|
|
{
|
2012-07-18 15:53:22 -06:00
|
|
|
int i;
|
2007-04-27 11:58:48 -06:00
|
|
|
|
2008-07-22 14:42:24 -06:00
|
|
|
if ((X_Dpy = XOpenDisplay(dpyname)) == NULL)
|
2013-07-08 09:46:16 -06:00
|
|
|
errx(1, "unable to open display \"%s\"", XDisplayName(dpyname));
|
2007-04-27 11:58:48 -06:00
|
|
|
|
2011-06-23 23:58:51 -06:00
|
|
|
XSetErrorHandler(x_wmerrorhandler);
|
|
|
|
XSelectInput(X_Dpy, DefaultRootWindow(X_Dpy), SubstructureRedirectMask);
|
|
|
|
XSync(X_Dpy, False);
|
2007-04-27 11:58:48 -06:00
|
|
|
XSetErrorHandler(x_errorhandler);
|
|
|
|
|
2016-10-18 11:03:30 -06:00
|
|
|
Conf.xrandr = XRRQueryExtension(X_Dpy, &Conf.xrandr_event_base, &i);
|
2008-07-22 14:42:24 -06:00
|
|
|
|
2013-07-15 08:50:44 -06:00
|
|
|
conf_atoms();
|
2013-06-17 11:11:10 -06:00
|
|
|
conf_cursor(&Conf);
|
2011-06-24 00:52:23 -06:00
|
|
|
|
2013-04-12 08:46:30 -06:00
|
|
|
for (i = 0; i < ScreenCount(X_Dpy); i++)
|
|
|
|
screen_init(i);
|
2017-12-22 14:30:01 -07:00
|
|
|
|
2017-12-22 14:27:45 -07:00
|
|
|
return ConnectionNumber(X_Dpy);
|
2007-04-27 11:58:48 -06:00
|
|
|
}
|
|
|
|
|
2009-06-26 06:21:58 -06:00
|
|
|
static void
|
2009-04-15 08:01:45 -06:00
|
|
|
x_teardown(void)
|
|
|
|
{
|
2014-01-22 15:14:02 -07:00
|
|
|
struct screen_ctx *sc;
|
|
|
|
unsigned int i;
|
|
|
|
|
2014-01-31 17:25:04 -07:00
|
|
|
conf_clear(&Conf);
|
|
|
|
|
2014-01-22 15:14:02 -07:00
|
|
|
TAILQ_FOREACH(sc, &Screenq, entry) {
|
|
|
|
for (i = 0; i < CWM_COLOR_NITEMS; i++)
|
2014-02-02 09:29:04 -07:00
|
|
|
XftColorFree(X_Dpy, DefaultVisual(X_Dpy, sc->which),
|
|
|
|
DefaultColormap(X_Dpy, sc->which),
|
2014-01-22 15:14:02 -07:00
|
|
|
&sc->xftcolor[i]);
|
|
|
|
XftFontClose(X_Dpy, sc->xftfont);
|
2016-09-28 18:30:40 -06:00
|
|
|
XftDrawDestroy(sc->menu.xftdraw);
|
2016-09-28 18:21:55 -06:00
|
|
|
XDestroyWindow(X_Dpy, sc->menu.win);
|
2014-01-22 15:14:02 -07:00
|
|
|
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);
|
2009-04-15 08:01:45 -06:00
|
|
|
XCloseDisplay(X_Dpy);
|
|
|
|
}
|
|
|
|
|
2011-06-23 23:58:51 -06:00
|
|
|
static int
|
|
|
|
x_wmerrorhandler(Display *dpy, XErrorEvent *e)
|
|
|
|
{
|
|
|
|
errx(1, "root window unavailable - perhaps another wm is running?");
|
2014-09-07 13:27:30 -06:00
|
|
|
return(0);
|
2011-06-23 23:58:51 -06:00
|
|
|
}
|
2012-05-13 09:15:54 -06:00
|
|
|
|
2009-06-26 06:21:58 -06:00
|
|
|
static int
|
2007-04-27 11:58:48 -06:00
|
|
|
x_errorhandler(Display *dpy, XErrorEvent *e)
|
|
|
|
{
|
2013-05-14 07:39:53 -06:00
|
|
|
#ifdef DEBUG
|
2011-06-23 23:58:51 -06:00
|
|
|
char msg[80], number[80], req[80];
|
2007-04-27 11:58:48 -06:00
|
|
|
|
2011-06-23 23:58:51 -06:00
|
|
|
XGetErrorText(X_Dpy, e->error_code, msg, sizeof(msg));
|
2011-07-25 09:10:24 -06:00
|
|
|
(void)snprintf(number, sizeof(number), "%d", e->request_code);
|
2011-06-23 23:58:51 -06:00
|
|
|
XGetErrorDatabaseText(X_Dpy, "XRequest", number,
|
|
|
|
"<unknown>", req, sizeof(req));
|
2007-04-27 11:58:48 -06:00
|
|
|
|
2014-01-03 08:29:06 -07:00
|
|
|
warnx("%s(0x%x): %s", req, (unsigned int)e->resourceid, msg);
|
2007-04-27 11:58:48 -06:00
|
|
|
#endif
|
2014-09-07 13:27:30 -06:00
|
|
|
return(0);
|
2007-04-27 11:58:48 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-09-06 10:24:32 -06:00
|
|
|
sighdlr(int sig)
|
2007-04-27 11:58:48 -06:00
|
|
|
{
|
2008-07-11 08:21:28 -06:00
|
|
|
pid_t pid;
|
2014-09-06 10:24:32 -06: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;
|
2017-12-27 11:46:18 -07:00
|
|
|
case SIGHUP:
|
|
|
|
cwm_status = CWM_EXEC_WM;
|
|
|
|
break;
|
2014-09-06 10:24:32 -06:00
|
|
|
}
|
2008-05-06 09:12:04 -06:00
|
|
|
|
|
|
|
errno = save_errno;
|
2007-04-27 11:58:48 -06:00
|
|
|
}
|
2008-02-13 14:04:19 -07:00
|
|
|
|
2008-02-13 14:48:03 -07:00
|
|
|
__dead void
|
2008-02-13 14:04:19 -07:00
|
|
|
usage(void)
|
|
|
|
{
|
2008-07-11 08:21:28 -06:00
|
|
|
extern char *__progname;
|
2008-02-13 14:04:19 -07:00
|
|
|
|
2018-02-04 15:56:26 -07:00
|
|
|
(void)fprintf(stderr, "usage: %s [-v] [-c file] [-d display]\n",
|
2011-07-25 09:10:24 -06:00
|
|
|
__progname);
|
2008-02-13 14:04:19 -07:00
|
|
|
exit(1);
|
|
|
|
}
|