💾 Archived View for gemini.rmf-dev.com › repo › Vaati › cwm › files › f81a2f684d447ad4b9ce05487ddd05… captured on 2023-03-20 at 18:16:20. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-01-29)
-=-=-=-=-=-=-
0 /*
1 * calmwm - the calm window manager
2 *
3 * Copyright (c) 2004 Marius Aamodt Eriksen <marius@monkey.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 *
17 * $OpenBSD$
18 */
19
20 #include <sys/types.h>
21 #include <sys/queue.h>
22 #include <sys/wait.h>
23
24 #include <err.h>
25 #include <errno.h>
26 #include <getopt.h>
27 #include <limits.h>
28 #include <locale.h>
29 #include <poll.h>
30 #include <signal.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35
36 #include "calmwm.h"
37
38 Display *X_Dpy;
39 Time Last_Event_Time = CurrentTime;
40 Atom cwmh[CWMH_NITEMS];
41 Atom ewmh[EWMH_NITEMS];
42 struct screen_q Screenq = TAILQ_HEAD_INITIALIZER(Screenq);
43 struct conf Conf;
44 volatile sig_atomic_t cwm_status;
45
46 __dead void usage(void);
47 static void sighdlr(int);
48 static int x_errorhandler(Display *, XErrorEvent *);
49 static int x_init(const char *);
50 static void x_teardown(void);
51 static int x_wmerrorhandler(Display *, XErrorEvent *);
52
53 int
54 main(int argc, char **argv)
55 {
56 char *display_name = NULL;
57 char *fallback;
58 int ch, xfd, nflag = 0;
59 struct pollfd pfd[1];
60
61 if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
62 warnx("no locale support");
63 mbtowc(NULL, NULL, MB_CUR_MAX);
64
65 conf_init(&Conf);
66
67 fallback = u_argv(argv);
68 Conf.wm_argv = u_argv(argv);
69 while ((ch = getopt(argc, argv, "c:d:nv")) != -1) {
70 switch (ch) {
71 case 'c':
72 free(Conf.conf_file);
73 Conf.conf_file = xstrdup(optarg);
74 break;
75 case 'd':
76 display_name = optarg;
77 break;
78 case 'n':
79 nflag = 1;
80 break;
81 case 'v':
82 Conf.debug++;
83 break;
84 default:
85 usage();
86 }
87 }
88 argc -= optind;
89 argv += optind;
90
91 if (signal(SIGCHLD, sighdlr) == SIG_ERR ||
92 signal(SIGHUP, sighdlr) == SIG_ERR ||
93 signal(SIGINT, sighdlr) == SIG_ERR ||
94 signal(SIGTERM, sighdlr) == SIG_ERR)
95 err(1, "signal");
96
97 if (parse_config(Conf.conf_file, &Conf) == -1) {
98 warnx("error parsing config file");
99 if (nflag)
100 return 1;
101 }
102 if (nflag)
103 return 0;
104
105 xfd = x_init(display_name);
106 cwm_status = CWM_RUNNING;
107
108 if (pledge("stdio rpath proc exec", NULL) == -1)
109 err(1, "pledge");
110
111 memset(&pfd, 0, sizeof(pfd));
112 pfd[0].fd = xfd;
113 pfd[0].events = POLLIN;
114 while (cwm_status == CWM_RUNNING) {
115 xev_process();
116 if (poll(pfd, 1, INFTIM) == -1) {
117 if (errno != EINTR)
118 warn("poll");
119 }
120 }
121 x_teardown();
122 if (cwm_status == CWM_EXEC_WM) {
123 u_exec(Conf.wm_argv);
124 warnx("'%s' failed to start, starting fallback", Conf.wm_argv);
125 u_exec(fallback);
126 }
127
128 return 0;
129 }
130
131 static int
132 x_init(const char *dpyname)
133 {
134 int i;
135
136 if ((X_Dpy = XOpenDisplay(dpyname)) == NULL)
137 errx(1, "unable to open display \"%s\"", XDisplayName(dpyname));
138
139 XSetErrorHandler(x_wmerrorhandler);
140 XSelectInput(X_Dpy, DefaultRootWindow(X_Dpy), SubstructureRedirectMask);
141 XSync(X_Dpy, False);
142 XSetErrorHandler(x_errorhandler);
143
144 Conf.xrandr = XRRQueryExtension(X_Dpy, &Conf.xrandr_event_base, &i);
145
146 xu_atom_init();
147 conf_cursor(&Conf);
148
149 for (i = 0; i < ScreenCount(X_Dpy); i++)
150 screen_init(i);
151
152 return ConnectionNumber(X_Dpy);
153 }
154
155 static void
156 x_teardown(void)
157 {
158 struct screen_ctx *sc;
159 unsigned int i;
160
161 conf_clear(&Conf);
162
163 TAILQ_FOREACH(sc, &Screenq, entry) {
164 for (i = 0; i < CWM_COLOR_NITEMS; i++)
165 XftColorFree(X_Dpy, DefaultVisual(X_Dpy, sc->which),
166 DefaultColormap(X_Dpy, sc->which),
167 &sc->xftcolor[i]);
168 XftFontClose(X_Dpy, sc->xftfont);
169 XUngrabKey(X_Dpy, AnyKey, AnyModifier, sc->rootwin);
170 }
171 XUngrabPointer(X_Dpy, CurrentTime);
172 XUngrabKeyboard(X_Dpy, CurrentTime);
173 for (i = 0; i < CF_NITEMS; i++)
174 XFreeCursor(X_Dpy, Conf.cursor[i]);
175 XSync(X_Dpy, False);
176 XSetInputFocus(X_Dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
177 XCloseDisplay(X_Dpy);
178 }
179
180 static int
181 x_wmerrorhandler(Display *dpy, XErrorEvent *e)
182 {
183 errx(1, "root window unavailable - perhaps another wm is running?");
184 return 0;
185 }
186
187 static int
188 x_errorhandler(Display *dpy, XErrorEvent *e)
189 {
190 #ifdef DEBUG
191 char msg[80], number[80], req[80];
192
193 XGetErrorText(X_Dpy, e->error_code, msg, sizeof(msg));
194 (void)snprintf(number, sizeof(number), "%d", e->request_code);
195 XGetErrorDatabaseText(X_Dpy, "XRequest", number,
196 "<unknown>", req, sizeof(req));
197
198 warnx("%s(0x%x): %s", req, (unsigned int)e->resourceid, msg);
199 #endif
200 return 0;
201 }
202
203 static void
204 sighdlr(int sig)
205 {
206 pid_t pid;
207 int save_errno = errno, status;
208
209 switch (sig) {
210 case SIGCHLD:
211 /* Collect dead children. */
212 while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) > 0 ||
213 (pid < 0 && errno == EINTR))
214 ;
215 break;
216 case SIGHUP:
217 cwm_status = CWM_EXEC_WM;
218 break;
219 case SIGINT:
220 case SIGTERM:
221 cwm_status = CWM_QUIT;
222 break;
223 }
224
225 errno = save_errno;
226 }
227
228 __dead void
229 usage(void)
230 {
231 extern char *__progname;
232
233 (void)fprintf(stderr, "usage: %s [-nv] [-c file] [-d display]\n",
234 __progname);
235 exit(1);
236 }
237