rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 1 | /* Copyright (c) 1994-1996 David Hogan, see README for licence details */ |
| 2 | #include <stdio.h> |
| 3 | #include <signal.h> |
| 4 | #include <errno.h> |
rsc | e62ba5e | 2004-03-21 23:24:28 +0000 | [diff] [blame] | 5 | #include <stdlib.h> |
| 6 | #include <unistd.h> |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 7 | #include <X11/X.h> |
| 8 | #include <X11/Xos.h> |
| 9 | #include <X11/Xlib.h> |
| 10 | #include <X11/Xutil.h> |
| 11 | #include <X11/Xatom.h> |
rsc | 8ad5179 | 2004-03-25 23:03:57 +0000 | [diff] [blame] | 12 | #ifdef SHAPE |
| 13 | #include <X11/extensions/shape.h> |
| 14 | #endif |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 15 | #include "dat.h" |
| 16 | #include "fns.h" |
| 17 | #include "patchlevel.h" |
| 18 | |
| 19 | char *version[] = |
| 20 | { |
rsc | cbeb0b2 | 2006-04-01 19:24:03 +0000 | [diff] [blame] | 21 | "rio version 1.0, Copyright (c) 1994-1996 David Hogan, (c) 2004 Russ Cox", 0 |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 22 | }; |
| 23 | |
| 24 | Display *dpy; |
| 25 | ScreenInfo *screens; |
| 26 | int initting; |
| 27 | XFontStruct *font; |
| 28 | int nostalgia; |
| 29 | char **myargv; |
| 30 | char *termprog; |
| 31 | char *shell; |
| 32 | Bool shape; |
| 33 | int _border = 4; |
rsc | 1cb3fa8 | 2004-03-29 12:00:15 +0000 | [diff] [blame] | 34 | int _corner = 25; |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 35 | int _inset = 1; |
| 36 | int curtime; |
| 37 | int debug; |
| 38 | int signalled; |
rsc | d2e350c | 2005-01-04 22:17:37 +0000 | [diff] [blame] | 39 | int scrolling; |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 40 | int num_screens; |
| 41 | int solidsweep = 0; |
rsc | 3ddda82 | 2004-12-28 23:21:40 +0000 | [diff] [blame] | 42 | int numvirtuals = 0; |
rsc | d52fb46 | 2005-08-11 03:38:16 +0000 | [diff] [blame] | 43 | int ffm = 0; |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 44 | |
rsc | aa80868 | 2004-04-19 19:35:17 +0000 | [diff] [blame] | 45 | Atom exit_rio; |
| 46 | Atom restart_rio; |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 47 | Atom wm_state; |
| 48 | Atom wm_change_state; |
| 49 | Atom wm_protocols; |
| 50 | Atom wm_delete; |
| 51 | Atom wm_take_focus; |
rsc | c005568 | 2004-03-30 05:01:53 +0000 | [diff] [blame] | 52 | Atom wm_lose_focus; |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 53 | Atom wm_colormaps; |
rsc | aa80868 | 2004-04-19 19:35:17 +0000 | [diff] [blame] | 54 | Atom _rio_running; |
| 55 | Atom _rio_hold_mode; |
Russ Cox | 71f6d60 | 2008-07-09 14:30:30 -0400 | [diff] [blame] | 56 | Atom wm_state_fullscreen; |
| 57 | Atom wm_state; |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 58 | |
| 59 | char *fontlist[] = { |
| 60 | "lucm.latin1.9", |
| 61 | "blit", |
rsc | e62ba5e | 2004-03-21 23:24:28 +0000 | [diff] [blame] | 62 | "*-lucidatypewriter-bold-*-14-*-75-*", |
| 63 | "*-lucidatypewriter-medium-*-12-*-75-*", |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 64 | "9x15bold", |
| 65 | "fixed", |
| 66 | "*", |
rsc | cbeb0b2 | 2006-04-01 19:24:03 +0000 | [diff] [blame] | 67 | 0 |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 68 | }; |
| 69 | |
| 70 | void |
| 71 | usage(void) |
| 72 | { |
rsc | d2e350c | 2005-01-04 22:17:37 +0000 | [diff] [blame] | 73 | fprintf(stderr, "usage: rio [-grey] [-font fname] [-s] [-term prog] [-version] [-virtuals num] [exit|restart]\n"); |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 74 | exit(1); |
| 75 | } |
| 76 | |
| 77 | int |
| 78 | main(int argc, char *argv[]) |
| 79 | { |
| 80 | int i, background, do_exit, do_restart; |
| 81 | char *fname; |
rsc | e62ba5e | 2004-03-21 23:24:28 +0000 | [diff] [blame] | 82 | int shape_event; |
rsc | 8ad5179 | 2004-03-25 23:03:57 +0000 | [diff] [blame] | 83 | #ifdef SHAPE |
| 84 | int dummy; |
| 85 | #endif |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 86 | |
rsc | e62ba5e | 2004-03-21 23:24:28 +0000 | [diff] [blame] | 87 | shape_event = 0; |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 88 | myargv = argv; /* for restart */ |
| 89 | |
| 90 | do_exit = do_restart = 0; |
rsc | 8ad5179 | 2004-03-25 23:03:57 +0000 | [diff] [blame] | 91 | background = 0; |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 92 | font = 0; |
| 93 | fname = 0; |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 94 | for(i = 1; i < argc; i++) |
| 95 | if(strcmp(argv[i], "-nostalgia") == 0) |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 96 | nostalgia++; |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 97 | else if(strcmp(argv[i], "-grey") == 0) |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 98 | background = 1; |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 99 | else if(strcmp(argv[i], "-debug") == 0) |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 100 | debug++; |
rsc | d52fb46 | 2005-08-11 03:38:16 +0000 | [diff] [blame] | 101 | /* |
| 102 | else if(strcmp(argv[i], "-ffm") == 0) |
| 103 | ffm++; |
| 104 | */ |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 105 | else if(strcmp(argv[i], "-font") == 0 && i+1<argc){ |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 106 | i++; |
| 107 | fname = argv[i]; |
| 108 | } |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 109 | else if(strcmp(argv[i], "-term") == 0 && i+1<argc) |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 110 | termprog = argv[++i]; |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 111 | else if(strcmp(argv[i], "-virtuals") == 0 && i+1<argc){ |
rsc | 3ddda82 | 2004-12-28 23:21:40 +0000 | [diff] [blame] | 112 | numvirtuals = atoi(argv[++i]); |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 113 | if(numvirtuals < 0 || numvirtuals > 12){ |
rsc | 3ddda82 | 2004-12-28 23:21:40 +0000 | [diff] [blame] | 114 | fprintf(stderr, "rio: wrong number of virtual displays, defaulting to 4\n"); |
| 115 | numvirtuals = 4; |
| 116 | } |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 117 | } else if(strcmp(argv[i], "-version") == 0){ |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 118 | fprintf(stderr, "%s", version[0]); |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 119 | if(PATCHLEVEL > 0) |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 120 | fprintf(stderr, "; patch level %d", PATCHLEVEL); |
| 121 | fprintf(stderr, "\n"); |
| 122 | exit(0); |
| 123 | } |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 124 | else if(strcmp(argv[i], "-s") == 0){ |
rsc | d2e350c | 2005-01-04 22:17:37 +0000 | [diff] [blame] | 125 | scrolling = 1; |
| 126 | } |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 127 | else if(argv[i][0] == '-') |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 128 | usage(); |
| 129 | else |
| 130 | break; |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 131 | for(; i < argc; i++) |
| 132 | if(strcmp(argv[i], "exit") == 0) |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 133 | do_exit++; |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 134 | else if(strcmp(argv[i], "restart") == 0) |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 135 | do_restart++; |
| 136 | else |
| 137 | usage(); |
| 138 | |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 139 | if(do_exit && do_restart) |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 140 | usage(); |
| 141 | |
| 142 | shell = (char *)getenv("SHELL"); |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 143 | if(shell == NULL) |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 144 | shell = DEFSHELL; |
| 145 | |
| 146 | dpy = XOpenDisplay(""); |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 147 | if(dpy == 0) |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 148 | fatal("can't open display"); |
| 149 | |
| 150 | initting = 1; |
| 151 | XSetErrorHandler(handler); |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 152 | if(signal(SIGTERM, sighandler) == SIG_IGN) |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 153 | signal(SIGTERM, SIG_IGN); |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 154 | if(signal(SIGINT, sighandler) == SIG_IGN) |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 155 | signal(SIGINT, SIG_IGN); |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 156 | if(signal(SIGHUP, sighandler) == SIG_IGN) |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 157 | signal(SIGHUP, SIG_IGN); |
| 158 | |
rsc | aa80868 | 2004-04-19 19:35:17 +0000 | [diff] [blame] | 159 | exit_rio = XInternAtom(dpy, "9WM_EXIT", False); |
| 160 | restart_rio = XInternAtom(dpy, "9WM_RESTART", False); |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 161 | |
| 162 | curtime = -1; /* don't care */ |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 163 | if(do_exit){ |
rsc | 56afeac | 2004-08-06 12:57:43 +0000 | [diff] [blame] | 164 | sendcmessage(DefaultRootWindow(dpy), exit_rio, 0L, 1, 1); |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 165 | XSync(dpy, False); |
| 166 | exit(0); |
| 167 | } |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 168 | if(do_restart){ |
rsc | 56afeac | 2004-08-06 12:57:43 +0000 | [diff] [blame] | 169 | sendcmessage(DefaultRootWindow(dpy), restart_rio, 0L, 1, 1); |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 170 | XSync(dpy, False); |
| 171 | exit(0); |
| 172 | } |
| 173 | |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 174 | if(0) XSynchronize(dpy, True); |
rsc | c005568 | 2004-03-30 05:01:53 +0000 | [diff] [blame] | 175 | |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 176 | 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); |
rsc | c005568 | 2004-03-30 05:01:53 +0000 | [diff] [blame] | 181 | wm_lose_focus = XInternAtom(dpy, "_9WM_LOSE_FOCUS", False); |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 182 | wm_colormaps = XInternAtom(dpy, "WM_COLORMAP_WINDOWS", False); |
rsc | aa80868 | 2004-04-19 19:35:17 +0000 | [diff] [blame] | 183 | _rio_running = XInternAtom(dpy, "_9WM_RUNNING", False); |
| 184 | _rio_hold_mode = XInternAtom(dpy, "_9WM_HOLD_MODE", False); |
Russ Cox | 71f6d60 | 2008-07-09 14:30:30 -0400 | [diff] [blame] | 185 | wm_state = XInternAtom(dpy, "_NET_WM_STATE", False); |
| 186 | wm_state_fullscreen = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 187 | |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 188 | if(fname != 0) |
| 189 | if((font = XLoadQueryFont(dpy, fname)) == 0) |
rsc | aa80868 | 2004-04-19 19:35:17 +0000 | [diff] [blame] | 190 | fprintf(stderr, "rio: warning: can't load font %s\n", fname); |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 191 | |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 192 | if(font == 0){ |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 193 | i = 0; |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 194 | for(;;){ |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 195 | fname = fontlist[i++]; |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 196 | if(fname == 0){ |
rsc | aa80868 | 2004-04-19 19:35:17 +0000 | [diff] [blame] | 197 | fprintf(stderr, "rio: warning: can't find a font\n"); |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 198 | break; |
| 199 | } |
| 200 | font = XLoadQueryFont(dpy, fname); |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 201 | if(font != 0) |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 202 | break; |
| 203 | } |
| 204 | } |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 205 | if(nostalgia){ |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 206 | _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 | |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 217 | for(i = 0; i < num_screens; i++) |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 218 | initscreen(&screens[i], i, background); |
| 219 | |
rsc | 3ddda82 | 2004-12-28 23:21:40 +0000 | [diff] [blame] | 220 | initb2menu(numvirtuals); |
| 221 | |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 222 | /* set selection so that 9term knows we're running */ |
| 223 | curtime = CurrentTime; |
rsc | aa80868 | 2004-04-19 19:35:17 +0000 | [diff] [blame] | 224 | XSetSelectionOwner(dpy, _rio_running, screens[0].menuwin, timestamp()); |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 225 | |
| 226 | XSync(dpy, False); |
| 227 | initting = 0; |
| 228 | |
| 229 | nofocus(); |
| 230 | |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 231 | for(i = 0; i < num_screens; i++) |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 232 | scanwins(&screens[i]); |
| 233 | |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 234 | keysetup(); |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 235 | mainloop(shape_event); |
rsc | e62ba5e | 2004-03-21 23:24:28 +0000 | [diff] [blame] | 236 | return 0; |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 237 | } |
| 238 | |
| 239 | void |
| 240 | initscreen(ScreenInfo *s, int i, int background) |
| 241 | { |
| 242 | char *ds, *colon, *dot1; |
| 243 | unsigned long mask; |
rsc | c005568 | 2004-03-30 05:01:53 +0000 | [diff] [blame] | 244 | unsigned long gmask; |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 245 | XGCValues gv; |
| 246 | XSetWindowAttributes attr; |
rsc | c005568 | 2004-03-30 05:01:53 +0000 | [diff] [blame] | 247 | XVisualInfo xvi; |
| 248 | XSetWindowAttributes attrs; |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 249 | |
| 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 | |
rsc | c005568 | 2004-03-30 05:01:53 +0000 | [diff] [blame] | 256 | /* |
| 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 | } |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 290 | if(DefaultDepth(dpy, i) != s->depth){ |
rsc | c005568 | 2004-03-30 05:01:53 +0000 | [diff] [blame] | 291 | s->def_cmap = XCreateColormap(dpy, s->root, s->vis, AllocNone); |
| 292 | } |
| 293 | |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 294 | ds = DisplayString(dpy); |
| 295 | colon = rindex(ds, ':'); |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 296 | if(colon && num_screens > 1){ |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 297 | 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 */ |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 301 | if(!dot1) |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 302 | dot1 = colon + strlen(colon); /* if not there, append */ |
| 303 | sprintf(dot1, ".%d", i); |
| 304 | } |
| 305 | else |
| 306 | s->display[0] = '\0'; |
| 307 | |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 308 | s->black = BlackPixel(dpy, i); |
| 309 | s->white = WhitePixel(dpy, i); |
rsc | 7934b1c | 2004-04-05 20:58:16 +0000 | [diff] [blame] | 310 | 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); |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 315 | 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; |
rsc | c005568 | 2004-03-30 05:01:53 +0000 | [diff] [blame] | 325 | gmask = GCForeground | GCBackground | GCFunction | GCLineWidth |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 326 | | GCSubwindowMode; |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 327 | if(font != 0){ |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 328 | gv.font = font->fid; |
rsc | c005568 | 2004-03-30 05:01:53 +0000 | [diff] [blame] | 329 | gmask |= GCFont; |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 330 | } |
rsc | c005568 | 2004-03-30 05:01:53 +0000 | [diff] [blame] | 331 | s->gc = XCreateGC(dpy, s->root, gmask, &gv); |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 332 | |
| 333 | gv.function = GXcopy; |
rsc | c005568 | 2004-03-30 05:01:53 +0000 | [diff] [blame] | 334 | s->gccopy = XCreateGC(dpy, s->root, gmask, &gv); |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 335 | |
| 336 | gv.foreground = s->red; |
rsc | c005568 | 2004-03-30 05:01:53 +0000 | [diff] [blame] | 337 | s->gcred = XCreateGC(dpy, s->root, gmask, &gv); |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 338 | |
rsc | 7934b1c | 2004-04-05 20:58:16 +0000 | [diff] [blame] | 339 | gv.foreground = colorpixel(dpy, s, s->depth, 0xEEEEEE, s->black); |
rsc | c005568 | 2004-03-30 05:01:53 +0000 | [diff] [blame] | 340 | s->gcsweep = XCreateGC(dpy, s->root, gmask, &gv); |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 341 | |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 342 | initcurs(s); |
| 343 | |
| 344 | attr.cursor = s->arrow; |
| 345 | attr.event_mask = SubstructureRedirectMask |
| 346 | | SubstructureNotifyMask | ColormapChangeMask |
rsc | d52fb46 | 2005-08-11 03:38:16 +0000 | [diff] [blame] | 347 | | ButtonPressMask | ButtonReleaseMask | PropertyChangeMask |
| 348 | | KeyPressMask | EnterWindowMask; |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 349 | mask = CWCursor|CWEventMask; |
| 350 | XChangeWindowAttributes(dpy, s->root, mask, &attr); |
| 351 | XSync(dpy, False); |
| 352 | |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 353 | if(background){ |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 354 | XSetWindowBackgroundPixmap(dpy, s->root, s->root_pixmap); |
| 355 | XClearWindow(dpy, s->root); |
rsc | 8ad5179 | 2004-03-25 23:03:57 +0000 | [diff] [blame] | 356 | } else |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 357 | system("xsetroot -solid grey30"); |
rsc | c005568 | 2004-03-30 05:01:53 +0000 | [diff] [blame] | 358 | |
rsc | 7934b1c | 2004-04-05 20:58:16 +0000 | [diff] [blame] | 359 | attrs.border_pixel = colorpixel(dpy, s, s->depth, 0x88CC88, s->black); |
| 360 | attrs.background_pixel = colorpixel(dpy, s, s->depth, 0xE9FFE9, s->white); |
rsc | c005568 | 2004-03-30 05:01:53 +0000 | [diff] [blame] | 361 | attrs.colormap = s->def_cmap; |
| 362 | |
| 363 | s->menuwin = XCreateWindow(dpy, s->root, 0, 0, 1, 1, 2, |
| 364 | s->depth, |
rsc | 1cb3fa8 | 2004-03-29 12:00:15 +0000 | [diff] [blame] | 365 | CopyFromParent, |
rsc | c005568 | 2004-03-30 05:01:53 +0000 | [diff] [blame] | 366 | s->vis, |
rsc | 7934b1c | 2004-04-05 20:58:16 +0000 | [diff] [blame] | 367 | CWBackPixel | CWBorderPixel | CWColormap, |
rsc | 1cb3fa8 | 2004-03-29 12:00:15 +0000 | [diff] [blame] | 368 | &attrs |
| 369 | ); |
rsc | c005568 | 2004-03-30 05:01:53 +0000 | [diff] [blame] | 370 | |
rsc | 7934b1c | 2004-04-05 20:58:16 +0000 | [diff] [blame] | 371 | |
| 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 | |
rsc | c005568 | 2004-03-30 05:01:53 +0000 | [diff] [blame] | 386 | attrs.border_pixel = s->red; |
rsc | 7934b1c | 2004-04-05 20:58:16 +0000 | [diff] [blame] | 387 | attrs.background_pixel = colorpixel(dpy, s, s->depth, 0xEEEEEE, s->black); |
rsc | c005568 | 2004-03-30 05:01:53 +0000 | [diff] [blame] | 388 | 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, |
rsc | 7934b1c | 2004-04-05 20:58:16 +0000 | [diff] [blame] | 393 | CWBackPixel | CWBorderPixel | CWColormap, |
rsc | c005568 | 2004-03-30 05:01:53 +0000 | [diff] [blame] | 394 | &attrs |
| 395 | ); |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 396 | } |
| 397 | |
| 398 | ScreenInfo* |
| 399 | getscreen(Window w) |
| 400 | { |
| 401 | int i; |
| 402 | |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 403 | for(i = 0; i < num_screens; i++) |
| 404 | if(screens[i].root == w) |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 405 | return &screens[i]; |
| 406 | |
| 407 | return 0; |
| 408 | } |
| 409 | |
| 410 | Time |
| 411 | timestamp(void) |
| 412 | { |
| 413 | XEvent ev; |
| 414 | |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 415 | if(curtime == CurrentTime){ |
rsc | aa80868 | 2004-04-19 19:35:17 +0000 | [diff] [blame] | 416 | XChangeProperty(dpy, screens[0].root, _rio_running, _rio_running, 8, |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 417 | PropModeAppend, (unsigned char *)"", 0); |
| 418 | XMaskEvent(dpy, PropertyChangeMask, &ev); |
| 419 | curtime = ev.xproperty.time; |
| 420 | } |
| 421 | return curtime; |
| 422 | } |
| 423 | |
| 424 | void |
rsc | 56afeac | 2004-08-06 12:57:43 +0000 | [diff] [blame] | 425 | sendcmessage(Window w, Atom a, long x, int isroot, int usemask) |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 426 | { |
| 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(); |
rsc | 2c1b986 | 2004-08-13 13:57:58 +0000 | [diff] [blame] | 438 | mask = 0; |
| 439 | if(usemask){ |
| 440 | mask |= KeyPressMask; /* seems to be necessary */ |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 441 | if(isroot) |
rsc | 2c1b986 | 2004-08-13 13:57:58 +0000 | [diff] [blame] | 442 | mask |= SubstructureRedirectMask; /* magic! */ |
| 443 | else |
| 444 | mask |= ExposureMask; /* not really correct but so be it */ |
| 445 | } |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 446 | status = XSendEvent(dpy, w, False, mask, &ev); |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 447 | if(status == 0) |
rsc | aa80868 | 2004-04-19 19:35:17 +0000 | [diff] [blame] | 448 | fprintf(stderr, "rio: sendcmessage failed\n"); |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 449 | } |
| 450 | |
| 451 | void |
| 452 | sendconfig(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 | |
| 469 | void |
| 470 | sighandler(void) |
| 471 | { |
| 472 | signalled = 1; |
| 473 | } |
| 474 | |
| 475 | void |
| 476 | getevent(XEvent *e) |
| 477 | { |
| 478 | int fd; |
| 479 | fd_set rfds; |
| 480 | struct timeval t; |
| 481 | |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 482 | if(!signalled){ |
| 483 | if(QLength(dpy) > 0){ |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 484 | 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; |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 491 | if(select(fd+1, &rfds, NULL, NULL, &t) == 1){ |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 492 | XNextEvent(dpy, e); |
| 493 | return; |
| 494 | } |
| 495 | XFlush(dpy); |
| 496 | FD_SET(fd, &rfds); |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 497 | if(select(fd+1, &rfds, NULL, NULL, NULL) == 1){ |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 498 | XNextEvent(dpy, e); |
| 499 | return; |
| 500 | } |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 501 | if(errno != EINTR || !signalled){ |
rsc | aa80868 | 2004-04-19 19:35:17 +0000 | [diff] [blame] | 502 | perror("rio: select failed"); |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 503 | exit(1); |
| 504 | } |
| 505 | } |
rsc | aa80868 | 2004-04-19 19:35:17 +0000 | [diff] [blame] | 506 | fprintf(stderr, "rio: exiting on signal\n"); |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 507 | cleanup(); |
| 508 | exit(1); |
| 509 | } |
| 510 | |
| 511 | void |
| 512 | cleanup(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; |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 520 | for(c = clients; c; c = next){ |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 521 | next = c->next; |
| 522 | i = normal(c); |
| 523 | c->next = cc[i]; |
| 524 | cc[i] = c; |
| 525 | } |
| 526 | |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 527 | for(i = 0; i < 2; i++){ |
| 528 | for(c = cc[i]; c; c = c->next){ |
| 529 | if(!withdrawn(c)){ |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 530 | 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()); |
rsc | ac33a34 | 2005-07-13 03:54:35 +0000 | [diff] [blame] | 539 | for(i = 0; i < num_screens; i++) |
rsc | 038e908 | 2004-03-21 04:27:28 +0000 | [diff] [blame] | 540 | cmapnofocus(&screens[i]); |
| 541 | XCloseDisplay(dpy); |
| 542 | } |