Mercurial > hg > index.fcgi > dwm > dwm-3.6.1-12pba
diff main.c @ 0:7024076fa948
initial add
author | paulo@localhost |
---|---|
date | Sun, 22 Mar 2009 23:26:35 -0700 |
parents | |
children | faa4cb9d7bd6 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/main.c Sun Mar 22 23:26:35 2009 -0700 1.3 @@ -0,0 +1,338 @@ 1.4 +/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com> 1.5 + * See LICENSE file for license details. 1.6 + */ 1.7 + 1.8 +#include "dwm.h" 1.9 +#include <errno.h> 1.10 +#include <locale.h> 1.11 +#include <stdio.h> 1.12 +#include <stdlib.h> 1.13 +#include <string.h> 1.14 +#include <unistd.h> 1.15 +#include <sys/select.h> 1.16 +#include <X11/cursorfont.h> 1.17 +#include <X11/keysym.h> 1.18 +#include <X11/Xatom.h> 1.19 +#include <X11/Xproto.h> 1.20 + 1.21 +/* extern */ 1.22 + 1.23 +char stext[256]; 1.24 +int screen, sx, sy, sw, sh, wax, way, waw, wah; 1.25 +unsigned int bh, ntags, numlockmask; 1.26 +Atom wmatom[WMLast], netatom[NetLast]; 1.27 +Bool *seltag; 1.28 +Bool selscreen = True; 1.29 +Client *clients = NULL; 1.30 +Client *sel = NULL; 1.31 +Client *stack = NULL; 1.32 +Cursor cursor[CurLast]; 1.33 +Display *dpy; 1.34 +DC dc = {0}; 1.35 +Window root, barwin; 1.36 + 1.37 +/* static */ 1.38 + 1.39 +static int (*xerrorxlib)(Display *, XErrorEvent *); 1.40 +static Bool otherwm, readin; 1.41 +static Bool running = True; 1.42 + 1.43 +static void 1.44 +cleanup(void) { 1.45 + close(STDIN_FILENO); 1.46 + while(stack) { 1.47 + if(stack->isbanned) 1.48 + XMoveWindow(dpy, stack->win, stack->x, stack->y); 1.49 + unmanage(stack); 1.50 + } 1.51 + if(dc.font.set) 1.52 + XFreeFontSet(dpy, dc.font.set); 1.53 + else 1.54 + XFreeFont(dpy, dc.font.xfont); 1.55 + XUngrabKey(dpy, AnyKey, AnyModifier, root); 1.56 + XFreePixmap(dpy, dc.drawable); 1.57 + XFreeGC(dpy, dc.gc); 1.58 + XDestroyWindow(dpy, barwin); 1.59 + XFreeCursor(dpy, cursor[CurNormal]); 1.60 + XFreeCursor(dpy, cursor[CurResize]); 1.61 + XFreeCursor(dpy, cursor[CurMove]); 1.62 + XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); 1.63 + XSync(dpy, False); 1.64 + free(seltag); 1.65 +} 1.66 + 1.67 +static unsigned long 1.68 +initcolor(const char *colstr) { 1.69 + Colormap cmap = DefaultColormap(dpy, screen); 1.70 + XColor color; 1.71 + 1.72 + if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) 1.73 + eprint("error, cannot allocate color '%s'\n", colstr); 1.74 + return color.pixel; 1.75 +} 1.76 + 1.77 +static void 1.78 +initfont(const char *fontstr) { 1.79 + char *def, **missing; 1.80 + int i, n; 1.81 + 1.82 + missing = NULL; 1.83 + if(dc.font.set) 1.84 + XFreeFontSet(dpy, dc.font.set); 1.85 + dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def); 1.86 + if(missing) { 1.87 + while(n--) 1.88 + fprintf(stderr, "missing fontset: %s\n", missing[n]); 1.89 + XFreeStringList(missing); 1.90 + } 1.91 + if(dc.font.set) { 1.92 + XFontSetExtents *font_extents; 1.93 + XFontStruct **xfonts; 1.94 + char **font_names; 1.95 + dc.font.ascent = dc.font.descent = 0; 1.96 + font_extents = XExtentsOfFontSet(dc.font.set); 1.97 + n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); 1.98 + for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) { 1.99 + if(dc.font.ascent < (*xfonts)->ascent) 1.100 + dc.font.ascent = (*xfonts)->ascent; 1.101 + if(dc.font.descent < (*xfonts)->descent) 1.102 + dc.font.descent = (*xfonts)->descent; 1.103 + xfonts++; 1.104 + } 1.105 + } 1.106 + else { 1.107 + if(dc.font.xfont) 1.108 + XFreeFont(dpy, dc.font.xfont); 1.109 + dc.font.xfont = NULL; 1.110 + if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr))) 1.111 + eprint("error, cannot load font: '%s'\n", fontstr); 1.112 + dc.font.ascent = dc.font.xfont->ascent; 1.113 + dc.font.descent = dc.font.xfont->descent; 1.114 + } 1.115 + dc.font.height = dc.font.ascent + dc.font.descent; 1.116 +} 1.117 + 1.118 +static void 1.119 +scan(void) { 1.120 + unsigned int i, num; 1.121 + Window *wins, d1, d2; 1.122 + XWindowAttributes wa; 1.123 + 1.124 + wins = NULL; 1.125 + if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { 1.126 + for(i = 0; i < num; i++) { 1.127 + if(!XGetWindowAttributes(dpy, wins[i], &wa) 1.128 + || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) 1.129 + continue; 1.130 + if(wa.map_state == IsViewable) 1.131 + manage(wins[i], &wa); 1.132 + } 1.133 + } 1.134 + if(wins) 1.135 + XFree(wins); 1.136 +} 1.137 + 1.138 +static void 1.139 +setup(void) { 1.140 + int i, j; 1.141 + unsigned int mask; 1.142 + Window w; 1.143 + XModifierKeymap *modmap; 1.144 + XSetWindowAttributes wa; 1.145 + 1.146 + /* init atoms */ 1.147 + wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); 1.148 + wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); 1.149 + wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); 1.150 + netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); 1.151 + netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); 1.152 + XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, 1.153 + PropModeReplace, (unsigned char *) netatom, NetLast); 1.154 + /* init cursors */ 1.155 + cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); 1.156 + cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); 1.157 + cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); 1.158 + /* init modifier map */ 1.159 + numlockmask = 0; 1.160 + modmap = XGetModifierMapping(dpy); 1.161 + for (i = 0; i < 8; i++) 1.162 + for (j = 0; j < modmap->max_keypermod; j++) { 1.163 + if(modmap->modifiermap[i * modmap->max_keypermod + j] 1.164 + == XKeysymToKeycode(dpy, XK_Num_Lock)) 1.165 + numlockmask = (1 << i); 1.166 + } 1.167 + XFreeModifiermap(modmap); 1.168 + /* select for events */ 1.169 + wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask 1.170 + | EnterWindowMask | LeaveWindowMask; 1.171 + wa.cursor = cursor[CurNormal]; 1.172 + XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); 1.173 + grabkeys(); 1.174 + compileregs(); 1.175 + for(ntags = 0; tags[ntags]; ntags++); 1.176 + seltag = emallocz(sizeof(Bool) * ntags); 1.177 + seltag[0] = True; 1.178 + /* style */ 1.179 + dc.norm[ColBorder] = initcolor(NORMBORDERCOLOR); 1.180 + dc.norm[ColBG] = initcolor(NORMBGCOLOR); 1.181 + dc.norm[ColFG] = initcolor(NORMFGCOLOR); 1.182 + dc.sel[ColBorder] = initcolor(SELBORDERCOLOR); 1.183 + dc.sel[ColBG] = initcolor(SELBGCOLOR); 1.184 + dc.sel[ColFG] = initcolor(SELFGCOLOR); 1.185 + initfont(FONT); 1.186 + /* geometry */ 1.187 + sx = sy = 0; 1.188 + sw = DisplayWidth(dpy, screen); 1.189 + sh = DisplayHeight(dpy, screen); 1.190 + initlayouts(); 1.191 + /* bar */ 1.192 + dc.h = bh = dc.font.height + 2; 1.193 + wa.override_redirect = 1; 1.194 + wa.background_pixmap = ParentRelative; 1.195 + wa.event_mask = ButtonPressMask | ExposureMask; 1.196 + barwin = XCreateWindow(dpy, root, sx, sy + (TOPBAR ? 0 : sh - bh), sw, bh, 0, 1.197 + DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen), 1.198 + CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); 1.199 + XDefineCursor(dpy, barwin, cursor[CurNormal]); 1.200 + XMapRaised(dpy, barwin); 1.201 + strcpy(stext, "dwm-"VERSION); 1.202 + /* windowarea */ 1.203 + wax = sx; 1.204 + way = sy + (TOPBAR ? bh : 0); 1.205 + wah = sh - bh; 1.206 + waw = sw; 1.207 + /* pixmap for everything */ 1.208 + dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); 1.209 + dc.gc = XCreateGC(dpy, root, 0, 0); 1.210 + XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); 1.211 + /* multihead support */ 1.212 + selscreen = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask); 1.213 +} 1.214 + 1.215 +/* 1.216 + * Startup Error handler to check if another window manager 1.217 + * is already running. 1.218 + */ 1.219 +static int 1.220 +xerrorstart(Display *dsply, XErrorEvent *ee) { 1.221 + otherwm = True; 1.222 + return -1; 1.223 +} 1.224 + 1.225 +/* extern */ 1.226 + 1.227 +void 1.228 +sendevent(Window w, Atom a, long value) { 1.229 + XEvent e; 1.230 + 1.231 + e.type = ClientMessage; 1.232 + e.xclient.window = w; 1.233 + e.xclient.message_type = a; 1.234 + e.xclient.format = 32; 1.235 + e.xclient.data.l[0] = value; 1.236 + e.xclient.data.l[1] = CurrentTime; 1.237 + XSendEvent(dpy, w, False, NoEventMask, &e); 1.238 + XSync(dpy, False); 1.239 +} 1.240 + 1.241 +void 1.242 +quit(Arg *arg) { 1.243 + readin = running = False; 1.244 +} 1.245 + 1.246 +/* There's no way to check accesses to destroyed windows, thus those cases are 1.247 + * ignored (especially on UnmapNotify's). Other types of errors call Xlibs 1.248 + * default error handler, which may call exit. 1.249 + */ 1.250 +int 1.251 +xerror(Display *dpy, XErrorEvent *ee) { 1.252 + if(ee->error_code == BadWindow 1.253 + || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) 1.254 + || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) 1.255 + || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) 1.256 + || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) 1.257 + || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) 1.258 + || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) 1.259 + || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) 1.260 + return 0; 1.261 + fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", 1.262 + ee->request_code, ee->error_code); 1.263 + return xerrorxlib(dpy, ee); /* may call exit */ 1.264 +} 1.265 + 1.266 +int 1.267 +main(int argc, char *argv[]) { 1.268 + char *p; 1.269 + int r, xfd; 1.270 + fd_set rd; 1.271 + XEvent ev; 1.272 + 1.273 + if(argc == 2 && !strncmp("-v", argv[1], 3)) 1.274 + eprint("dwm-"VERSION", (C)opyright MMVI-MMVII Anselm R. Garbe\n"); 1.275 + else if(argc != 1) 1.276 + eprint("usage: dwm [-v]\n"); 1.277 + setlocale(LC_CTYPE, ""); 1.278 + if(!(dpy = XOpenDisplay(0))) 1.279 + eprint("dwm: cannot open display\n"); 1.280 + xfd = ConnectionNumber(dpy); 1.281 + screen = DefaultScreen(dpy); 1.282 + root = RootWindow(dpy, screen); 1.283 + otherwm = False; 1.284 + XSetErrorHandler(xerrorstart); 1.285 + /* this causes an error if some other window manager is running */ 1.286 + XSelectInput(dpy, root, SubstructureRedirectMask); 1.287 + XSync(dpy, False); 1.288 + if(otherwm) 1.289 + eprint("dwm: another window manager is already running\n"); 1.290 + 1.291 + XSync(dpy, False); 1.292 + XSetErrorHandler(NULL); 1.293 + xerrorxlib = XSetErrorHandler(xerror); 1.294 + XSync(dpy, False); 1.295 + setup(); 1.296 + drawstatus(); 1.297 + scan(); 1.298 + 1.299 + /* main event loop, also reads status text from stdin */ 1.300 + XSync(dpy, False); 1.301 + readin = True; 1.302 + while(running) { 1.303 + FD_ZERO(&rd); 1.304 + if(readin) 1.305 + FD_SET(STDIN_FILENO, &rd); 1.306 + FD_SET(xfd, &rd); 1.307 + if(select(xfd + 1, &rd, NULL, NULL, NULL) == -1) { 1.308 + if(errno == EINTR) 1.309 + continue; 1.310 + eprint("select failed\n"); 1.311 + } 1.312 + if(FD_ISSET(STDIN_FILENO, &rd)) { 1.313 + switch(r = read(STDIN_FILENO, stext, sizeof stext - 1)) { 1.314 + case -1: 1.315 + strncpy(stext, strerror(errno), sizeof stext - 1); 1.316 + stext[sizeof stext - 1] = '\0'; 1.317 + readin = False; 1.318 + break; 1.319 + case 0: 1.320 + strncpy(stext, "EOF", 4); 1.321 + readin = False; 1.322 + break; 1.323 + default: 1.324 + for(stext[r] = '\0', p = stext + strlen(stext) - 1; p >= stext && *p == '\n'; *p-- = '\0'); 1.325 + for(; p >= stext && *p != '\n'; --p); 1.326 + if(p > stext) 1.327 + strncpy(stext, p + 1, sizeof stext); 1.328 + } 1.329 + drawstatus(); 1.330 + } 1.331 + if(FD_ISSET(xfd, &rd)) 1.332 + while(XPending(dpy)) { 1.333 + XNextEvent(dpy, &ev); 1.334 + if(handler[ev.type]) 1.335 + (handler[ev.type])(&ev); /* call handler */ 1.336 + } 1.337 + } 1.338 + cleanup(); 1.339 + XCloseDisplay(dpy); 1.340 + return 0; 1.341 +}