blob: 4bf87852e79573958839127241cec5ed9a6a764c [file] [log] [blame]
rsc038e9082004-03-21 04:27:28 +00001/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
2#include <stdio.h>
3#include <signal.h>
4#include <errno.h>
rsce62ba5e2004-03-21 23:24:28 +00005#include <stdlib.h>
6#include <unistd.h>
rsc038e9082004-03-21 04:27:28 +00007#include <X11/X.h>
8#include <X11/Xos.h>
9#include <X11/Xlib.h>
10#include <X11/Xutil.h>
11#include <X11/Xatom.h>
rsc8ad51792004-03-25 23:03:57 +000012#ifdef SHAPE
13#include <X11/extensions/shape.h>
14#endif
rsc038e9082004-03-21 04:27:28 +000015#include "dat.h"
16#include "fns.h"
17#include "patchlevel.h"
18
19char *version[] =
20{
rsccbeb0b22006-04-01 19:24:03 +000021 "rio version 1.0, Copyright (c) 1994-1996 David Hogan, (c) 2004 Russ Cox", 0
rsc038e9082004-03-21 04:27:28 +000022};
23
24Display *dpy;
25ScreenInfo *screens;
26int initting;
27XFontStruct *font;
28int nostalgia;
29char **myargv;
30char *termprog;
31char *shell;
32Bool shape;
33int _border = 4;
rsc1cb3fa82004-03-29 12:00:15 +000034int _corner = 25;
rsc038e9082004-03-21 04:27:28 +000035int _inset = 1;
36int curtime;
37int debug;
38int signalled;
rscd2e350c2005-01-04 22:17:37 +000039int scrolling;
rsc038e9082004-03-21 04:27:28 +000040int num_screens;
41int solidsweep = 0;
rsc3ddda822004-12-28 23:21:40 +000042int numvirtuals = 0;
rscd52fb462005-08-11 03:38:16 +000043int ffm = 0;
rsc038e9082004-03-21 04:27:28 +000044
rscaa808682004-04-19 19:35:17 +000045Atom exit_rio;
46Atom restart_rio;
rsc038e9082004-03-21 04:27:28 +000047Atom wm_state;
48Atom wm_change_state;
49Atom wm_protocols;
50Atom wm_delete;
51Atom wm_take_focus;
rscc0055682004-03-30 05:01:53 +000052Atom wm_lose_focus;
rsc038e9082004-03-21 04:27:28 +000053Atom wm_colormaps;
rscaa808682004-04-19 19:35:17 +000054Atom _rio_running;
55Atom _rio_hold_mode;
Russ Cox71f6d602008-07-09 14:30:30 -040056Atom wm_state_fullscreen;
57Atom wm_state;
rsc038e9082004-03-21 04:27:28 +000058
59char *fontlist[] = {
60 "lucm.latin1.9",
61 "blit",
rsce62ba5e2004-03-21 23:24:28 +000062 "*-lucidatypewriter-bold-*-14-*-75-*",
63 "*-lucidatypewriter-medium-*-12-*-75-*",
rsc038e9082004-03-21 04:27:28 +000064 "9x15bold",
65 "fixed",
66 "*",
rsccbeb0b22006-04-01 19:24:03 +000067 0
rsc038e9082004-03-21 04:27:28 +000068};
69
70void
71usage(void)
72{
rscd2e350c2005-01-04 22:17:37 +000073 fprintf(stderr, "usage: rio [-grey] [-font fname] [-s] [-term prog] [-version] [-virtuals num] [exit|restart]\n");
rsc038e9082004-03-21 04:27:28 +000074 exit(1);
75}
76
77int
78main(int argc, char *argv[])
79{
80 int i, background, do_exit, do_restart;
81 char *fname;
rsce62ba5e2004-03-21 23:24:28 +000082 int shape_event;
rsc8ad51792004-03-25 23:03:57 +000083#ifdef SHAPE
84 int dummy;
85#endif
rsc038e9082004-03-21 04:27:28 +000086
rsce62ba5e2004-03-21 23:24:28 +000087 shape_event = 0;
rsc038e9082004-03-21 04:27:28 +000088 myargv = argv; /* for restart */
89
90 do_exit = do_restart = 0;
rsc8ad51792004-03-25 23:03:57 +000091 background = 0;
rsc038e9082004-03-21 04:27:28 +000092 font = 0;
93 fname = 0;
rscac33a342005-07-13 03:54:35 +000094 for(i = 1; i < argc; i++)
95 if(strcmp(argv[i], "-nostalgia") == 0)
rsc038e9082004-03-21 04:27:28 +000096 nostalgia++;
rscac33a342005-07-13 03:54:35 +000097 else if(strcmp(argv[i], "-grey") == 0)
rsc038e9082004-03-21 04:27:28 +000098 background = 1;
rscac33a342005-07-13 03:54:35 +000099 else if(strcmp(argv[i], "-debug") == 0)
rsc038e9082004-03-21 04:27:28 +0000100 debug++;
rscd52fb462005-08-11 03:38:16 +0000101 /*
102 else if(strcmp(argv[i], "-ffm") == 0)
103 ffm++;
104 */
rscac33a342005-07-13 03:54:35 +0000105 else if(strcmp(argv[i], "-font") == 0 && i+1<argc){
rsc038e9082004-03-21 04:27:28 +0000106 i++;
107 fname = argv[i];
108 }
rscac33a342005-07-13 03:54:35 +0000109 else if(strcmp(argv[i], "-term") == 0 && i+1<argc)
rsc038e9082004-03-21 04:27:28 +0000110 termprog = argv[++i];
rscac33a342005-07-13 03:54:35 +0000111 else if(strcmp(argv[i], "-virtuals") == 0 && i+1<argc){
rsc3ddda822004-12-28 23:21:40 +0000112 numvirtuals = atoi(argv[++i]);
rscac33a342005-07-13 03:54:35 +0000113 if(numvirtuals < 0 || numvirtuals > 12){
rsc3ddda822004-12-28 23:21:40 +0000114 fprintf(stderr, "rio: wrong number of virtual displays, defaulting to 4\n");
115 numvirtuals = 4;
116 }
rscac33a342005-07-13 03:54:35 +0000117 } else if(strcmp(argv[i], "-version") == 0){
rsc038e9082004-03-21 04:27:28 +0000118 fprintf(stderr, "%s", version[0]);
rscac33a342005-07-13 03:54:35 +0000119 if(PATCHLEVEL > 0)
rsc038e9082004-03-21 04:27:28 +0000120 fprintf(stderr, "; patch level %d", PATCHLEVEL);
121 fprintf(stderr, "\n");
122 exit(0);
123 }
rscac33a342005-07-13 03:54:35 +0000124 else if(strcmp(argv[i], "-s") == 0){
rscd2e350c2005-01-04 22:17:37 +0000125 scrolling = 1;
126 }
rscac33a342005-07-13 03:54:35 +0000127 else if(argv[i][0] == '-')
rsc038e9082004-03-21 04:27:28 +0000128 usage();
129 else
130 break;
rscac33a342005-07-13 03:54:35 +0000131 for(; i < argc; i++)
132 if(strcmp(argv[i], "exit") == 0)
rsc038e9082004-03-21 04:27:28 +0000133 do_exit++;
rscac33a342005-07-13 03:54:35 +0000134 else if(strcmp(argv[i], "restart") == 0)
rsc038e9082004-03-21 04:27:28 +0000135 do_restart++;
136 else
137 usage();
138
rscac33a342005-07-13 03:54:35 +0000139 if(do_exit && do_restart)
rsc038e9082004-03-21 04:27:28 +0000140 usage();
141
142 shell = (char *)getenv("SHELL");
rscac33a342005-07-13 03:54:35 +0000143 if(shell == NULL)
rsc038e9082004-03-21 04:27:28 +0000144 shell = DEFSHELL;
145
146 dpy = XOpenDisplay("");
rscac33a342005-07-13 03:54:35 +0000147 if(dpy == 0)
rsc038e9082004-03-21 04:27:28 +0000148 fatal("can't open display");
149
150 initting = 1;
151 XSetErrorHandler(handler);
rscac33a342005-07-13 03:54:35 +0000152 if(signal(SIGTERM, sighandler) == SIG_IGN)
rsc038e9082004-03-21 04:27:28 +0000153 signal(SIGTERM, SIG_IGN);
rscac33a342005-07-13 03:54:35 +0000154 if(signal(SIGINT, sighandler) == SIG_IGN)
rsc038e9082004-03-21 04:27:28 +0000155 signal(SIGINT, SIG_IGN);
rscac33a342005-07-13 03:54:35 +0000156 if(signal(SIGHUP, sighandler) == SIG_IGN)
rsc038e9082004-03-21 04:27:28 +0000157 signal(SIGHUP, SIG_IGN);
158
rscaa808682004-04-19 19:35:17 +0000159 exit_rio = XInternAtom(dpy, "9WM_EXIT", False);
160 restart_rio = XInternAtom(dpy, "9WM_RESTART", False);
rsc038e9082004-03-21 04:27:28 +0000161
162 curtime = -1; /* don't care */
rscac33a342005-07-13 03:54:35 +0000163 if(do_exit){
rsc56afeac2004-08-06 12:57:43 +0000164 sendcmessage(DefaultRootWindow(dpy), exit_rio, 0L, 1, 1);
rsc038e9082004-03-21 04:27:28 +0000165 XSync(dpy, False);
166 exit(0);
167 }
rscac33a342005-07-13 03:54:35 +0000168 if(do_restart){
rsc56afeac2004-08-06 12:57:43 +0000169 sendcmessage(DefaultRootWindow(dpy), restart_rio, 0L, 1, 1);
rsc038e9082004-03-21 04:27:28 +0000170 XSync(dpy, False);
171 exit(0);
172 }
173
rscac33a342005-07-13 03:54:35 +0000174 if(0) XSynchronize(dpy, True);
rscc0055682004-03-30 05:01:53 +0000175
rsc038e9082004-03-21 04:27:28 +0000176 wm_state = XInternAtom(dpy, "WM_STATE", False);
177 wm_change_state = XInternAtom(dpy, "WM_CHANGE_STATE", False);
178 wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False);
179 wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
180 wm_take_focus = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
rscc0055682004-03-30 05:01:53 +0000181 wm_lose_focus = XInternAtom(dpy, "_9WM_LOSE_FOCUS", False);
rsc038e9082004-03-21 04:27:28 +0000182 wm_colormaps = XInternAtom(dpy, "WM_COLORMAP_WINDOWS", False);
rscaa808682004-04-19 19:35:17 +0000183 _rio_running = XInternAtom(dpy, "_9WM_RUNNING", False);
184 _rio_hold_mode = XInternAtom(dpy, "_9WM_HOLD_MODE", False);
Russ Cox71f6d602008-07-09 14:30:30 -0400185 wm_state = XInternAtom(dpy, "_NET_WM_STATE", False);
186 wm_state_fullscreen = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
rsc038e9082004-03-21 04:27:28 +0000187
rscac33a342005-07-13 03:54:35 +0000188 if(fname != 0)
189 if((font = XLoadQueryFont(dpy, fname)) == 0)
rscaa808682004-04-19 19:35:17 +0000190 fprintf(stderr, "rio: warning: can't load font %s\n", fname);
rsc038e9082004-03-21 04:27:28 +0000191
rscac33a342005-07-13 03:54:35 +0000192 if(font == 0){
rsc038e9082004-03-21 04:27:28 +0000193 i = 0;
rscac33a342005-07-13 03:54:35 +0000194 for(;;){
rsc038e9082004-03-21 04:27:28 +0000195 fname = fontlist[i++];
rscac33a342005-07-13 03:54:35 +0000196 if(fname == 0){
rscaa808682004-04-19 19:35:17 +0000197 fprintf(stderr, "rio: warning: can't find a font\n");
rsc038e9082004-03-21 04:27:28 +0000198 break;
199 }
200 font = XLoadQueryFont(dpy, fname);
rscac33a342005-07-13 03:54:35 +0000201 if(font != 0)
rsc038e9082004-03-21 04:27:28 +0000202 break;
203 }
204 }
rscac33a342005-07-13 03:54:35 +0000205 if(nostalgia){
rsc038e9082004-03-21 04:27:28 +0000206 _border--;
207 _inset--;
208 }
209
210#ifdef SHAPE
211 shape = XShapeQueryExtension(dpy, &shape_event, &dummy);
212#endif
213
214 num_screens = ScreenCount(dpy);
215 screens = (ScreenInfo *)malloc(sizeof(ScreenInfo) * num_screens);
216
rscac33a342005-07-13 03:54:35 +0000217 for(i = 0; i < num_screens; i++)
rsc038e9082004-03-21 04:27:28 +0000218 initscreen(&screens[i], i, background);
219
rsc3ddda822004-12-28 23:21:40 +0000220 initb2menu(numvirtuals);
221
rsc038e9082004-03-21 04:27:28 +0000222 /* set selection so that 9term knows we're running */
223 curtime = CurrentTime;
rscaa808682004-04-19 19:35:17 +0000224 XSetSelectionOwner(dpy, _rio_running, screens[0].menuwin, timestamp());
rsc038e9082004-03-21 04:27:28 +0000225
226 XSync(dpy, False);
227 initting = 0;
228
229 nofocus();
230
rscac33a342005-07-13 03:54:35 +0000231 for(i = 0; i < num_screens; i++)
rsc038e9082004-03-21 04:27:28 +0000232 scanwins(&screens[i]);
233
rscac33a342005-07-13 03:54:35 +0000234 keysetup();
rsc038e9082004-03-21 04:27:28 +0000235 mainloop(shape_event);
rsce62ba5e2004-03-21 23:24:28 +0000236 return 0;
rsc038e9082004-03-21 04:27:28 +0000237}
238
239void
240initscreen(ScreenInfo *s, int i, int background)
241{
242 char *ds, *colon, *dot1;
243 unsigned long mask;
rscc0055682004-03-30 05:01:53 +0000244 unsigned long gmask;
rsc038e9082004-03-21 04:27:28 +0000245 XGCValues gv;
246 XSetWindowAttributes attr;
rscc0055682004-03-30 05:01:53 +0000247 XVisualInfo xvi;
248 XSetWindowAttributes attrs;
rsc038e9082004-03-21 04:27:28 +0000249
250 s->num = i;
251 s->root = RootWindow(dpy, i);
252 s->def_cmap = DefaultColormap(dpy, i);
253 s->min_cmaps = MinCmapsOfScreen(ScreenOfDisplay(dpy, i));
254 s->depth = DefaultDepth(dpy, i);
255
rscc0055682004-03-30 05:01:53 +0000256 /*
257 * Figure out underlying screen format.
258 */
259 if(XMatchVisualInfo(dpy, i, 16, TrueColor, &xvi)
260 || XMatchVisualInfo(dpy, i, 16, DirectColor, &xvi)){
261 s->vis = xvi.visual;
262 s->depth = 16;
263 }
264 else
265 if(XMatchVisualInfo(dpy, i, 15, TrueColor, &xvi)
266 || XMatchVisualInfo(dpy, i, 15, DirectColor, &xvi)){
267 s->vis = xvi.visual;
268 s->depth = 15;
269 }
270 else
271 if(XMatchVisualInfo(dpy, i, 24, TrueColor, &xvi)
272 || XMatchVisualInfo(dpy, i, 24, DirectColor, &xvi)){
273 s->vis = xvi.visual;
274 s->depth = 24;
275 }
276 else
277 if(XMatchVisualInfo(dpy, i, 8, PseudoColor, &xvi)
278 || XMatchVisualInfo(dpy, i, 8, StaticColor, &xvi)){
279 s->vis = xvi.visual;
280 s->depth = 8;
281 }
282 else{
283 s->depth = DefaultDepth(dpy, i);
284 if(s->depth != 8){
285 fprintf(stderr, "can't understand depth %d screen", s->depth);
286 exit(1);
287 }
288 s->vis = DefaultVisual(dpy, i);
289 }
rscac33a342005-07-13 03:54:35 +0000290 if(DefaultDepth(dpy, i) != s->depth){
rscc0055682004-03-30 05:01:53 +0000291 s->def_cmap = XCreateColormap(dpy, s->root, s->vis, AllocNone);
292 }
293
rsc038e9082004-03-21 04:27:28 +0000294 ds = DisplayString(dpy);
295 colon = rindex(ds, ':');
rscac33a342005-07-13 03:54:35 +0000296 if(colon && num_screens > 1){
rsc038e9082004-03-21 04:27:28 +0000297 strcpy(s->display, "DISPLAY=");
298 strcat(s->display, ds);
299 colon = s->display + 8 + (colon - ds); /* use version in buf */
300 dot1 = index(colon, '.'); /* first period after colon */
rscac33a342005-07-13 03:54:35 +0000301 if(!dot1)
rsc038e9082004-03-21 04:27:28 +0000302 dot1 = colon + strlen(colon); /* if not there, append */
303 sprintf(dot1, ".%d", i);
304 }
305 else
306 s->display[0] = '\0';
307
rsc038e9082004-03-21 04:27:28 +0000308 s->black = BlackPixel(dpy, i);
309 s->white = WhitePixel(dpy, i);
rsc7934b1c2004-04-05 20:58:16 +0000310 s->activeholdborder = colorpixel(dpy, s, s->depth, 0x000099, s->white);
311 s->inactiveholdborder = colorpixel(dpy, s, s->depth, 0x005DBB, s->black);
312 s->activeborder = colorpixel(dpy, s, s->depth, 0x55AAAA, s->black);
313 s->inactiveborder = colorpixel(dpy, s, s->depth, 0x9EEEEE, s->white);
314 s->red = colorpixel(dpy, s, s->depth, 0xDD0000, s->white);
rsc038e9082004-03-21 04:27:28 +0000315 s->width = WidthOfScreen(ScreenOfDisplay(dpy, i));
316 s->height = HeightOfScreen(ScreenOfDisplay(dpy, i));
317 s->bkup[0] = XCreatePixmap(dpy, s->root, 2*s->width, BORDER, DefaultDepth(dpy, i));
318 s->bkup[1] = XCreatePixmap(dpy, s->root, BORDER, 2*s->height, DefaultDepth(dpy, i));
319
320 gv.foreground = s->black^s->white;
321 gv.background = s->white;
322 gv.function = GXxor;
323 gv.line_width = 0;
324 gv.subwindow_mode = IncludeInferiors;
rscc0055682004-03-30 05:01:53 +0000325 gmask = GCForeground | GCBackground | GCFunction | GCLineWidth
rsc038e9082004-03-21 04:27:28 +0000326 | GCSubwindowMode;
rscac33a342005-07-13 03:54:35 +0000327 if(font != 0){
rsc038e9082004-03-21 04:27:28 +0000328 gv.font = font->fid;
rscc0055682004-03-30 05:01:53 +0000329 gmask |= GCFont;
rsc038e9082004-03-21 04:27:28 +0000330 }
rscc0055682004-03-30 05:01:53 +0000331 s->gc = XCreateGC(dpy, s->root, gmask, &gv);
rsc038e9082004-03-21 04:27:28 +0000332
333 gv.function = GXcopy;
rscc0055682004-03-30 05:01:53 +0000334 s->gccopy = XCreateGC(dpy, s->root, gmask, &gv);
rsc038e9082004-03-21 04:27:28 +0000335
336 gv.foreground = s->red;
rscc0055682004-03-30 05:01:53 +0000337 s->gcred = XCreateGC(dpy, s->root, gmask, &gv);
rsc038e9082004-03-21 04:27:28 +0000338
rsc7934b1c2004-04-05 20:58:16 +0000339 gv.foreground = colorpixel(dpy, s, s->depth, 0xEEEEEE, s->black);
rscc0055682004-03-30 05:01:53 +0000340 s->gcsweep = XCreateGC(dpy, s->root, gmask, &gv);
rsc038e9082004-03-21 04:27:28 +0000341
rsc038e9082004-03-21 04:27:28 +0000342 initcurs(s);
343
344 attr.cursor = s->arrow;
345 attr.event_mask = SubstructureRedirectMask
346 | SubstructureNotifyMask | ColormapChangeMask
rscd52fb462005-08-11 03:38:16 +0000347 | ButtonPressMask | ButtonReleaseMask | PropertyChangeMask
348 | KeyPressMask | EnterWindowMask;
rsc038e9082004-03-21 04:27:28 +0000349 mask = CWCursor|CWEventMask;
350 XChangeWindowAttributes(dpy, s->root, mask, &attr);
351 XSync(dpy, False);
352
rscac33a342005-07-13 03:54:35 +0000353 if(background){
rsc038e9082004-03-21 04:27:28 +0000354 XSetWindowBackgroundPixmap(dpy, s->root, s->root_pixmap);
355 XClearWindow(dpy, s->root);
rsc8ad51792004-03-25 23:03:57 +0000356 } else
rsc038e9082004-03-21 04:27:28 +0000357 system("xsetroot -solid grey30");
rscc0055682004-03-30 05:01:53 +0000358
rsc7934b1c2004-04-05 20:58:16 +0000359 attrs.border_pixel = colorpixel(dpy, s, s->depth, 0x88CC88, s->black);
360 attrs.background_pixel = colorpixel(dpy, s, s->depth, 0xE9FFE9, s->white);
rscc0055682004-03-30 05:01:53 +0000361 attrs.colormap = s->def_cmap;
362
363 s->menuwin = XCreateWindow(dpy, s->root, 0, 0, 1, 1, 2,
364 s->depth,
rsc1cb3fa82004-03-29 12:00:15 +0000365 CopyFromParent,
rscc0055682004-03-30 05:01:53 +0000366 s->vis,
rsc7934b1c2004-04-05 20:58:16 +0000367 CWBackPixel | CWBorderPixel | CWColormap,
rsc1cb3fa82004-03-29 12:00:15 +0000368 &attrs
369 );
rscc0055682004-03-30 05:01:53 +0000370
rsc7934b1c2004-04-05 20:58:16 +0000371
372 gv.foreground = colorpixel(dpy, s, s->depth, 0xE9FFE9, s->white);
373 s->gcmenubg = XCreateGC(dpy, s->menuwin, gmask, &gv);
374
375 gv.foreground = colorpixel(dpy, s, s->depth, 0x448844, s->black);
376 s->gcmenubgs = XCreateGC(dpy, s->menuwin, gmask, &gv);
377
378 gv.foreground = s->black;
379 gv.background = colorpixel(dpy, s, s->depth, 0xE9FFE9, s->white);
380 s->gcmenufg = XCreateGC(dpy, s->menuwin, gmask, &gv);
381
382 gv.foreground = colorpixel(dpy, s, s->depth, 0xE9FFE9, s->white);
383 gv.background = colorpixel(dpy, s, s->depth, 0x448844, s->black);
384 s->gcmenufgs = XCreateGC(dpy, s->menuwin, gmask, &gv);
385
rscc0055682004-03-30 05:01:53 +0000386 attrs.border_pixel = s->red;
rsc7934b1c2004-04-05 20:58:16 +0000387 attrs.background_pixel = colorpixel(dpy, s, s->depth, 0xEEEEEE, s->black);
rscc0055682004-03-30 05:01:53 +0000388 attrs.colormap = s->def_cmap;
389 s->sweepwin = XCreateWindow(dpy, s->root, 0, 0, 1, 1, 4,
390 s->depth,
391 CopyFromParent,
392 s->vis,
rsc7934b1c2004-04-05 20:58:16 +0000393 CWBackPixel | CWBorderPixel | CWColormap,
rscc0055682004-03-30 05:01:53 +0000394 &attrs
395 );
rsc038e9082004-03-21 04:27:28 +0000396}
397
398ScreenInfo*
399getscreen(Window w)
400{
401 int i;
402
rscac33a342005-07-13 03:54:35 +0000403 for(i = 0; i < num_screens; i++)
404 if(screens[i].root == w)
rsc038e9082004-03-21 04:27:28 +0000405 return &screens[i];
406
407 return 0;
408}
409
410Time
411timestamp(void)
412{
413 XEvent ev;
414
rscac33a342005-07-13 03:54:35 +0000415 if(curtime == CurrentTime){
rscaa808682004-04-19 19:35:17 +0000416 XChangeProperty(dpy, screens[0].root, _rio_running, _rio_running, 8,
rsc038e9082004-03-21 04:27:28 +0000417 PropModeAppend, (unsigned char *)"", 0);
418 XMaskEvent(dpy, PropertyChangeMask, &ev);
419 curtime = ev.xproperty.time;
420 }
421 return curtime;
422}
423
424void
rsc56afeac2004-08-06 12:57:43 +0000425sendcmessage(Window w, Atom a, long x, int isroot, int usemask)
rsc038e9082004-03-21 04:27:28 +0000426{
427 XEvent ev;
428 int status;
429 long mask;
430
431 memset(&ev, 0, sizeof(ev));
432 ev.xclient.type = ClientMessage;
433 ev.xclient.window = w;
434 ev.xclient.message_type = a;
435 ev.xclient.format = 32;
436 ev.xclient.data.l[0] = x;
437 ev.xclient.data.l[1] = timestamp();
rsc2c1b9862004-08-13 13:57:58 +0000438 mask = 0;
439 if(usemask){
440 mask |= KeyPressMask; /* seems to be necessary */
rscac33a342005-07-13 03:54:35 +0000441 if(isroot)
rsc2c1b9862004-08-13 13:57:58 +0000442 mask |= SubstructureRedirectMask; /* magic! */
443 else
444 mask |= ExposureMask; /* not really correct but so be it */
445 }
rsc038e9082004-03-21 04:27:28 +0000446 status = XSendEvent(dpy, w, False, mask, &ev);
rscac33a342005-07-13 03:54:35 +0000447 if(status == 0)
rscaa808682004-04-19 19:35:17 +0000448 fprintf(stderr, "rio: sendcmessage failed\n");
rsc038e9082004-03-21 04:27:28 +0000449}
450
451void
452sendconfig(Client *c)
453{
454 XConfigureEvent ce;
455
456 ce.type = ConfigureNotify;
457 ce.event = c->window;
458 ce.window = c->window;
459 ce.x = c->x;
460 ce.y = c->y;
461 ce.width = c->dx;
462 ce.height = c->dy;
463 ce.border_width = c->border;
464 ce.above = None;
465 ce.override_redirect = 0;
466 XSendEvent(dpy, c->window, False, StructureNotifyMask, (XEvent*)&ce);
467}
468
469void
470sighandler(void)
471{
472 signalled = 1;
473}
474
475void
476getevent(XEvent *e)
477{
478 int fd;
479 fd_set rfds;
480 struct timeval t;
481
rscac33a342005-07-13 03:54:35 +0000482 if(!signalled){
483 if(QLength(dpy) > 0){
rsc038e9082004-03-21 04:27:28 +0000484 XNextEvent(dpy, e);
485 return;
486 }
487 fd = ConnectionNumber(dpy);
488 FD_ZERO(&rfds);
489 FD_SET(fd, &rfds);
490 t.tv_sec = t.tv_usec = 0;
rscac33a342005-07-13 03:54:35 +0000491 if(select(fd+1, &rfds, NULL, NULL, &t) == 1){
rsc038e9082004-03-21 04:27:28 +0000492 XNextEvent(dpy, e);
493 return;
494 }
495 XFlush(dpy);
496 FD_SET(fd, &rfds);
rscac33a342005-07-13 03:54:35 +0000497 if(select(fd+1, &rfds, NULL, NULL, NULL) == 1){
rsc038e9082004-03-21 04:27:28 +0000498 XNextEvent(dpy, e);
499 return;
500 }
rscac33a342005-07-13 03:54:35 +0000501 if(errno != EINTR || !signalled){
rscaa808682004-04-19 19:35:17 +0000502 perror("rio: select failed");
rsc038e9082004-03-21 04:27:28 +0000503 exit(1);
504 }
505 }
rscaa808682004-04-19 19:35:17 +0000506 fprintf(stderr, "rio: exiting on signal\n");
rsc038e9082004-03-21 04:27:28 +0000507 cleanup();
508 exit(1);
509}
510
511void
512cleanup(void)
513{
514 Client *c, *cc[2], *next;
515 XWindowChanges wc;
516 int i;
517
518 /* order of un-reparenting determines final stacking order... */
519 cc[0] = cc[1] = 0;
rscac33a342005-07-13 03:54:35 +0000520 for(c = clients; c; c = next){
rsc038e9082004-03-21 04:27:28 +0000521 next = c->next;
522 i = normal(c);
523 c->next = cc[i];
524 cc[i] = c;
525 }
526
rscac33a342005-07-13 03:54:35 +0000527 for(i = 0; i < 2; i++){
528 for(c = cc[i]; c; c = c->next){
529 if(!withdrawn(c)){
rsc038e9082004-03-21 04:27:28 +0000530 XReparentWindow(dpy, c->window, c->screen->root,
531 c->x, c->y);
532 }
533 wc.border_width = c->border;
534 XConfigureWindow(dpy, c->window, CWBorderWidth, &wc);
535 }
536 }
537
538 XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, timestamp());
rscac33a342005-07-13 03:54:35 +0000539 for(i = 0; i < num_screens; i++)
rsc038e9082004-03-21 04:27:28 +0000540 cmapnofocus(&screens[i]);
541 XCloseDisplay(dpy);
542}