dwm-meillo

annotate main.c @ 541:08d3d329270a

using MASTER 600 again, it is definately better, and using urxvtc for the moment (it doesn't flickers on refreshes, but this is not because of Marc Lehmann, it is because of the original rxvt code)
author arg@mig29
date Thu, 26 Oct 2006 12:13:41 +0200
parents 451f19d48845
children fe766305eed1
rev   line source
arg@532 1 /* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
garbeam@0 2 * See LICENSE file for license details.
garbeam@0 3 */
garbeam@0 4
garbeam@76 5 #include "dwm.h"
garbeam@59 6 #include <errno.h>
garbeam@0 7 #include <stdio.h>
garbeam@0 8 #include <stdlib.h>
garbeam@57 9 #include <string.h>
garbeam@59 10 #include <unistd.h>
arg@138 11 #include <sys/select.h>
garbeam@0 12 #include <X11/cursorfont.h>
arg@291 13 #include <X11/keysym.h>
garbeam@0 14 #include <X11/Xatom.h>
garbeam@0 15 #include <X11/Xproto.h>
garbeam@0 16
arg@333 17 /* extern */
arg@333 18
arg@333 19 char stext[1024];
arg@333 20 Bool *seltag;
arg@524 21 int bx, by, bw, bh, bmw, masterd, screen, sx, sy, sw, sh;
arg@524 22 unsigned int master, ntags, numlockmask;
arg@333 23 Atom wmatom[WMLast], netatom[NetLast];
arg@333 24 Bool running = True;
arg@333 25 Bool issel = True;
arg@333 26 Client *clients = NULL;
arg@333 27 Client *sel = NULL;
arg@446 28 Client *stack = NULL;
arg@333 29 Cursor cursor[CurLast];
arg@333 30 Display *dpy;
arg@333 31 DC dc = {0};
arg@333 32 Window root, barwin;
arg@333 33
garbeam@84 34 /* static */
garbeam@0 35
arg@123 36 static int (*xerrorxlib)(Display *, XErrorEvent *);
arg@302 37 static Bool otherwm, readin;
garbeam@0 38
garbeam@0 39 static void
arg@487 40 cleanup(void) {
arg@302 41 close(STDIN_FILENO);
garbeam@76 42 while(sel) {
arg@99 43 resize(sel, True, TopLeft);
garbeam@76 44 unmanage(sel);
garbeam@76 45 }
arg@295 46 if(dc.font.set)
arg@295 47 XFreeFontSet(dpy, dc.font.set);
arg@295 48 else
arg@295 49 XFreeFont(dpy, dc.font.xfont);
arg@292 50 XUngrabKey(dpy, AnyKey, AnyModifier, root);
arg@295 51 XFreePixmap(dpy, dc.drawable);
arg@295 52 XFreeGC(dpy, dc.gc);
arg@309 53 XDestroyWindow(dpy, barwin);
garbeam@76 54 XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
arg@292 55 XSync(dpy, False);
arg@433 56 free(seltag);
garbeam@76 57 }
garbeam@0 58
garbeam@0 59 static void
arg@487 60 scan(void) {
garbeam@0 61 unsigned int i, num;
arg@123 62 Window *wins, d1, d2;
garbeam@0 63 XWindowAttributes wa;
garbeam@0 64
arg@292 65 wins = NULL;
garbeam@0 66 if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
garbeam@0 67 for(i = 0; i < num; i++) {
garbeam@0 68 if(!XGetWindowAttributes(dpy, wins[i], &wa))
garbeam@0 69 continue;
garbeam@0 70 if(wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
garbeam@0 71 continue;
garbeam@0 72 if(wa.map_state == IsViewable)
garbeam@10 73 manage(wins[i], &wa);
garbeam@0 74 }
garbeam@0 75 }
garbeam@0 76 if(wins)
garbeam@0 77 XFree(wins);
garbeam@0 78 }
garbeam@0 79
arg@333 80 static void
arg@487 81 setup(void) {
arg@333 82 int i, j;
arg@333 83 unsigned int mask;
arg@333 84 Window w;
arg@333 85 XModifierKeymap *modmap;
arg@333 86 XSetWindowAttributes wa;
arg@333 87
arg@333 88 /* init atoms */
arg@333 89 wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
arg@333 90 wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
arg@333 91 netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
arg@333 92 netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
arg@333 93 XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
arg@333 94 PropModeReplace, (unsigned char *) netatom, NetLast);
arg@333 95 /* init cursors */
arg@333 96 cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
arg@333 97 cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
arg@333 98 cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
arg@532 99 /* init modifier map */
arg@333 100 modmap = XGetModifierMapping(dpy);
arg@333 101 for (i = 0; i < 8; i++) {
arg@333 102 for (j = 0; j < modmap->max_keypermod; j++) {
arg@333 103 if(modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock))
arg@333 104 numlockmask = (1 << i);
arg@333 105 }
arg@333 106 }
arg@333 107 XFree(modmap);
arg@532 108 /* select for events */
arg@461 109 wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask
arg@461 110 | EnterWindowMask | LeaveWindowMask;
arg@333 111 wa.cursor = cursor[CurNormal];
arg@333 112 XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
arg@333 113 grabkeys();
arg@333 114 initrregs();
arg@333 115 for(ntags = 0; tags[ntags]; ntags++);
arg@333 116 seltag = emallocz(sizeof(Bool) * ntags);
arg@333 117 seltag[0] = True;
arg@333 118 /* style */
arg@353 119 dc.norm[ColBG] = getcolor(NORMBGCOLOR);
arg@353 120 dc.norm[ColFG] = getcolor(NORMFGCOLOR);
arg@353 121 dc.sel[ColBG] = getcolor(SELBGCOLOR);
arg@353 122 dc.sel[ColFG] = getcolor(SELFGCOLOR);
arg@353 123 dc.status[ColBG] = getcolor(STATUSBGCOLOR);
arg@353 124 dc.status[ColFG] = getcolor(STATUSFGCOLOR);
arg@333 125 setfont(FONT);
arg@532 126 /* geometry */
arg@530 127 bmw = textw(TILESYMBOL) > textw(FLOATSYMBOL) ? textw(TILESYMBOL) : textw(FLOATSYMBOL);
arg@333 128 sx = sy = 0;
arg@333 129 sw = DisplayWidth(dpy, screen);
arg@333 130 sh = DisplayHeight(dpy, screen);
arg@524 131 master = MASTER;
arg@532 132 /* bar */
arg@333 133 bx = by = 0;
arg@333 134 bw = sw;
arg@353 135 dc.h = bh = dc.font.height + 2;
arg@333 136 wa.override_redirect = 1;
arg@333 137 wa.background_pixmap = ParentRelative;
arg@333 138 wa.event_mask = ButtonPressMask | ExposureMask;
arg@333 139 barwin = XCreateWindow(dpy, root, bx, by, bw, bh, 0, DefaultDepth(dpy, screen),
arg@333 140 CopyFromParent, DefaultVisual(dpy, screen),
arg@333 141 CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
arg@333 142 XDefineCursor(dpy, barwin, cursor[CurNormal]);
arg@333 143 XMapRaised(dpy, barwin);
arg@532 144 strcpy(stext, "dwm-"VERSION);
arg@532 145 /* pixmap for everything */
arg@333 146 dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
arg@333 147 dc.gc = XCreateGC(dpy, root, 0, 0);
arg@344 148 XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
arg@532 149 /* multihead support */
arg@333 150 issel = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask);
arg@333 151 }
arg@333 152
garbeam@76 153 /*
garbeam@76 154 * Startup Error handler to check if another window manager
garbeam@76 155 * is already running.
garbeam@76 156 */
garbeam@76 157 static int
arg@461 158 xerrorstart(Display *dsply, XErrorEvent *ee) {
garbeam@76 159 otherwm = True;
garbeam@76 160 return -1;
garbeam@76 161 }
garbeam@76 162
garbeam@84 163 /* extern */
garbeam@84 164
garbeam@13 165 int
arg@461 166 getproto(Window w) {
arg@329 167 int i, format, protos, status;
arg@328 168 unsigned long extra, res;
arg@328 169 Atom *protocols, real;
garbeam@13 170
arg@329 171 protos = 0;
arg@329 172 status = XGetWindowProperty(dpy, w, wmatom[WMProtocols], 0L, 20L, False,
arg@329 173 XA_ATOM, &real, &format, &res, &extra, (unsigned char **)&protocols);
arg@328 174 if(status != Success || protocols == 0)
garbeam@13 175 return protos;
arg@329 176 for(i = 0; i < res; i++)
garbeam@77 177 if(protocols[i] == wmatom[WMDelete])
arg@157 178 protos |= PROTODELWIN;
arg@328 179 free(protocols);
garbeam@13 180 return protos;
garbeam@13 181 }
garbeam@13 182
garbeam@13 183 void
arg@461 184 sendevent(Window w, Atom a, long value) {
garbeam@13 185 XEvent e;
garbeam@13 186
garbeam@13 187 e.type = ClientMessage;
garbeam@13 188 e.xclient.window = w;
garbeam@13 189 e.xclient.message_type = a;
garbeam@13 190 e.xclient.format = 32;
garbeam@13 191 e.xclient.data.l[0] = value;
garbeam@13 192 e.xclient.data.l[1] = CurrentTime;
garbeam@13 193 XSendEvent(dpy, w, False, NoEventMask, &e);
garbeam@79 194 XSync(dpy, False);
garbeam@13 195 }
garbeam@13 196
garbeam@76 197 void
arg@461 198 quit(Arg *arg) {
arg@302 199 readin = running = False;
garbeam@75 200 }
garbeam@75 201
arg@532 202 /* There's no way to check accesses to destroyed windows, thus those cases are
garbeam@84 203 * ignored (especially on UnmapNotify's). Other types of errors call Xlibs
arg@455 204 * default error handler, which may call exit.
garbeam@0 205 */
garbeam@10 206 int
arg@461 207 xerror(Display *dpy, XErrorEvent *ee) {
garbeam@75 208 if(ee->error_code == BadWindow
arg@123 209 || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch)
arg@123 210 || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable)
arg@123 211 || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable)
arg@123 212 || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable)
arg@123 213 || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch)
arg@458 214 || (ee->request_code == X_GrabKey && ee->error_code == BadAccess)
arg@458 215 || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable))
garbeam@0 216 return 0;
garbeam@34 217 fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
arg@123 218 ee->request_code, ee->error_code);
arg@455 219 return xerrorxlib(dpy, ee); /* may call exit */
garbeam@27 220 }
garbeam@27 221
garbeam@0 222 int
arg@461 223 main(int argc, char *argv[]) {
arg@333 224 int r, xfd;
garbeam@59 225 fd_set rd;
garbeam@0 226
arg@137 227 if(argc == 2 && !strncmp("-v", argv[1], 3)) {
arg@137 228 fputs("dwm-"VERSION", (C)opyright MMVI Anselm R. Garbe\n", stdout);
arg@137 229 exit(EXIT_SUCCESS);
garbeam@0 230 }
arg@137 231 else if(argc != 1)
arg@137 232 eprint("usage: dwm [-v]\n");
garbeam@0 233 dpy = XOpenDisplay(0);
garbeam@0 234 if(!dpy)
arg@197 235 eprint("dwm: cannot open display\n");
arg@265 236 xfd = ConnectionNumber(dpy);
garbeam@0 237 screen = DefaultScreen(dpy);
garbeam@0 238 root = RootWindow(dpy, screen);
garbeam@75 239 otherwm = False;
garbeam@75 240 XSetErrorHandler(xerrorstart);
arg@197 241 /* this causes an error if some other window manager is running */
garbeam@0 242 XSelectInput(dpy, root, SubstructureRedirectMask);
garbeam@78 243 XSync(dpy, False);
garbeam@75 244 if(otherwm)
garbeam@75 245 eprint("dwm: another window manager is already running\n");
garbeam@0 246
arg@292 247 XSync(dpy, False);
garbeam@78 248 XSetErrorHandler(NULL);
garbeam@75 249 xerrorxlib = XSetErrorHandler(xerror);
arg@275 250 XSync(dpy, False);
arg@333 251 setup();
garbeam@74 252 drawstatus();
garbeam@75 253 scan();
garbeam@3 254
arg@214 255 /* main event loop, also reads status text from stdin */
arg@242 256 XSync(dpy, False);
arg@292 257 procevent();
arg@302 258 readin = True;
garbeam@5 259 while(running) {
garbeam@59 260 FD_ZERO(&rd);
arg@164 261 if(readin)
arg@164 262 FD_SET(STDIN_FILENO, &rd);
arg@265 263 FD_SET(xfd, &rd);
arg@333 264 r = select(xfd + 1, &rd, NULL, NULL, NULL);
arg@333 265 if((r == -1) && (errno == EINTR))
garbeam@59 266 continue;
arg@333 267 if(r > 0) {
arg@164 268 if(readin && FD_ISSET(STDIN_FILENO, &rd)) {
arg@164 269 readin = NULL != fgets(stext, sizeof(stext), stdin);
arg@164 270 if(readin)
arg@164 271 stext[strlen(stext) - 1] = 0;
arg@162 272 else
arg@164 273 strcpy(stext, "broken pipe");
garbeam@74 274 drawstatus();
garbeam@59 275 }
garbeam@59 276 }
arg@333 277 else if(r < 0)
arg@316 278 eprint("select failed\n");
arg@293 279 procevent();
garbeam@5 280 }
garbeam@0 281 cleanup();
garbeam@0 282 XCloseDisplay(dpy);
garbeam@0 283 return 0;
garbeam@0 284 }