main.c
changeset 990 70f6fcd100b7
parent 989 5f7018237edb
child 991 277c0e5bd0df
equal deleted inserted replaced
989:5f7018237edb 990:70f6fcd100b7
     1 /* See LICENSE file for copyright and license details. */
       
     2 #include "dwm.h"
       
     3 #include <errno.h>
       
     4 #include <locale.h>
       
     5 #include <stdio.h>
       
     6 #include <stdlib.h>
       
     7 #include <string.h>
       
     8 #include <unistd.h>
       
     9 #include <sys/select.h>
       
    10 #include <X11/cursorfont.h>
       
    11 #include <X11/keysym.h>
       
    12 #include <X11/Xatom.h>
       
    13 #include <X11/Xproto.h>
       
    14 #include <X11/Xutil.h>
       
    15 
       
    16 /* extern */
       
    17 
       
    18 char stext[256];
       
    19 int screen, sx, sy, sw, sh, wax, way, waw, wah;
       
    20 unsigned int ntags;
       
    21 unsigned int numlockmask = 0;
       
    22 Atom wmatom[WMLast], netatom[NetLast];
       
    23 Bool *seltags;
       
    24 Bool selscreen = True;
       
    25 Client *clients = NULL;
       
    26 Client *sel = NULL;
       
    27 Client *stack = NULL;
       
    28 Cursor cursor[CurLast];
       
    29 Display *dpy;
       
    30 Window root;
       
    31 
       
    32 /* static */
       
    33 
       
    34 static int (*xerrorxlib)(Display *, XErrorEvent *);
       
    35 static Bool otherwm, readin;
       
    36 static Bool running = True;
       
    37 
       
    38 static void
       
    39 cleanup(void) {
       
    40 	close(STDIN_FILENO);
       
    41 	while(stack) {
       
    42 		unban(stack);
       
    43 		unmanage(stack);
       
    44 	}
       
    45 	if(dc.font.set)
       
    46 		XFreeFontSet(dpy, dc.font.set);
       
    47 	else
       
    48 		XFreeFont(dpy, dc.font.xfont);
       
    49 	XUngrabKey(dpy, AnyKey, AnyModifier, root);
       
    50 	XFreePixmap(dpy, dc.drawable);
       
    51 	XFreeGC(dpy, dc.gc);
       
    52 	XDestroyWindow(dpy, barwin);
       
    53 	XFreeCursor(dpy, cursor[CurNormal]);
       
    54 	XFreeCursor(dpy, cursor[CurResize]);
       
    55 	XFreeCursor(dpy, cursor[CurMove]);
       
    56 	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
       
    57 	XSync(dpy, False);
       
    58 	free(seltags);
       
    59 }
       
    60 
       
    61 static long
       
    62 getstate(Window w) {
       
    63 	int format, status;
       
    64 	long result = -1;
       
    65 	unsigned char *p = NULL;
       
    66 	unsigned long n, extra;
       
    67 	Atom real;
       
    68 
       
    69 	status = XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
       
    70 			&real, &format, &n, &extra, (unsigned char **)&p);
       
    71 	if(status != Success)
       
    72 		return -1;
       
    73 	if(n != 0)
       
    74 		result = *p;
       
    75 	XFree(p);
       
    76 	return result;
       
    77 }
       
    78 
       
    79 static void
       
    80 scan(void) {
       
    81 	unsigned int i, num;
       
    82 	Window *wins, d1, d2;
       
    83 	XWindowAttributes wa;
       
    84 
       
    85 	wins = NULL;
       
    86 	if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
       
    87 		for(i = 0; i < num; i++) {
       
    88 			if(!XGetWindowAttributes(dpy, wins[i], &wa)
       
    89 			|| wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
       
    90 				continue;
       
    91 			if(wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
       
    92 				manage(wins[i], &wa);
       
    93 		}
       
    94 		for(i = 0; i < num; i++) { /* now the transients */
       
    95 			if(!XGetWindowAttributes(dpy, wins[i], &wa))
       
    96 				continue;
       
    97 			if(XGetTransientForHint(dpy, wins[i], &d1)
       
    98 			&& (wa.map_state == IsViewable || getstate(wins[i]) == IconicState))
       
    99 				manage(wins[i], &wa);
       
   100 		}
       
   101 	}
       
   102 	if(wins)
       
   103 		XFree(wins);
       
   104 }
       
   105 
       
   106 static void
       
   107 setup(void) {
       
   108 	int i, j;
       
   109 	unsigned int mask;
       
   110 	Window w;
       
   111 	XModifierKeymap *modmap;
       
   112 	XSetWindowAttributes wa;
       
   113 
       
   114 	/* init atoms */
       
   115 	wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
       
   116 	wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
       
   117 	wmatom[WMName] = XInternAtom(dpy, "WM_NAME", False);
       
   118 	wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
       
   119 	netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
       
   120 	netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
       
   121 	XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
       
   122 			PropModeReplace, (unsigned char *) netatom, NetLast);
       
   123 	/* init cursors */
       
   124 	cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
       
   125 	cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
       
   126 	cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
       
   127 	/* init modifier map */
       
   128 	modmap = XGetModifierMapping(dpy);
       
   129 	for (i = 0; i < 8; i++)
       
   130 		for (j = 0; j < modmap->max_keypermod; j++) {
       
   131 			if(modmap->modifiermap[i * modmap->max_keypermod + j]
       
   132 					== XKeysymToKeycode(dpy, XK_Num_Lock))
       
   133 				numlockmask = (1 << i);
       
   134 		}
       
   135 	XFreeModifiermap(modmap);
       
   136 	/* select for events */
       
   137 	wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask
       
   138 		| EnterWindowMask | LeaveWindowMask | StructureNotifyMask;
       
   139 	wa.cursor = cursor[CurNormal];
       
   140 	XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
       
   141 	XSelectInput(dpy, root, wa.event_mask);
       
   142 	grabkeys();
       
   143 	compileregs();
       
   144 	for(ntags = 0; tags[ntags]; ntags++);
       
   145 	seltags = emallocz(sizeof(Bool) * ntags);
       
   146 	seltags[0] = True;
       
   147 	/* geometry */
       
   148 	sx = sy = 0;
       
   149 	sw = DisplayWidth(dpy, screen);
       
   150 	sh = DisplayHeight(dpy, screen);
       
   151 	initstyle();
       
   152 	initlayouts();
       
   153 	initbar();
       
   154 	/* multihead support */
       
   155 	selscreen = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask);
       
   156 }
       
   157 
       
   158 /*
       
   159  * Startup Error handler to check if another window manager
       
   160  * is already running.
       
   161  */
       
   162 static int
       
   163 xerrorstart(Display *dsply, XErrorEvent *ee) {
       
   164 	otherwm = True;
       
   165 	return -1;
       
   166 }
       
   167 
       
   168 /* extern */
       
   169 
       
   170 Bool
       
   171 gettextprop(Window w, Atom atom, char *text, unsigned int size) {
       
   172 	char **list = NULL;
       
   173 	int n;
       
   174 	XTextProperty name;
       
   175 
       
   176 	if(!text || size == 0)
       
   177 		return False;
       
   178 	text[0] = '\0';
       
   179 	XGetTextProperty(dpy, w, &name, atom);
       
   180 	if(!name.nitems)
       
   181 		return False;
       
   182 	if(name.encoding == XA_STRING)
       
   183 		strncpy(text, (char *)name.value, size - 1);
       
   184 	else {
       
   185 		if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
       
   186 		&& n > 0 && *list)
       
   187 		{
       
   188 			strncpy(text, *list, size - 1);
       
   189 			XFreeStringList(list);
       
   190 		}
       
   191 	}
       
   192 	text[size - 1] = '\0';
       
   193 	XFree(name.value);
       
   194 	return True;
       
   195 }
       
   196 
       
   197 void
       
   198 quit(const char *arg) {
       
   199 	readin = running = False;
       
   200 }
       
   201 
       
   202 /* There's no way to check accesses to destroyed windows, thus those cases are
       
   203  * ignored (especially on UnmapNotify's).  Other types of errors call Xlibs
       
   204  * default error handler, which may call exit.
       
   205  */
       
   206 int
       
   207 xerror(Display *dpy, XErrorEvent *ee) {
       
   208 	if(ee->error_code == BadWindow
       
   209 	|| (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch)
       
   210 	|| (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable)
       
   211 	|| (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable)
       
   212 	|| (ee->request_code == X_PolySegment && ee->error_code == BadDrawable)
       
   213 	|| (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch)
       
   214 	|| (ee->request_code == X_GrabKey && ee->error_code == BadAccess)
       
   215 	|| (ee->request_code == X_CopyArea && ee->error_code == BadDrawable))
       
   216 		return 0;
       
   217 	fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
       
   218 		ee->request_code, ee->error_code);
       
   219 	return xerrorxlib(dpy, ee); /* may call exit */
       
   220 }
       
   221 
       
   222 int
       
   223 main(int argc, char *argv[]) {
       
   224 	char *p;
       
   225 	int r, xfd;
       
   226 	fd_set rd;
       
   227 	XEvent ev;
       
   228 
       
   229 	if(argc == 2 && !strcmp("-v", argv[1]))
       
   230 		eprint("dwm-"VERSION", © 2006-2007 A. R. Garbe, S. van Dijk, J. Salmi, P. Hruby, S. Nagy\n");
       
   231 	else if(argc != 1)
       
   232 		eprint("usage: dwm [-v]\n");
       
   233 	setlocale(LC_CTYPE, "");
       
   234 	if(!(dpy = XOpenDisplay(0)))
       
   235 		eprint("dwm: cannot open display\n");
       
   236 	xfd = ConnectionNumber(dpy);
       
   237 	screen = DefaultScreen(dpy);
       
   238 	root = RootWindow(dpy, screen);
       
   239 	otherwm = False;
       
   240 	XSetErrorHandler(xerrorstart);
       
   241 	/* this causes an error if some other window manager is running */
       
   242 	XSelectInput(dpy, root, SubstructureRedirectMask);
       
   243 	XSync(dpy, False);
       
   244 	if(otherwm)
       
   245 		eprint("dwm: another window manager is already running\n");
       
   246 
       
   247 	XSync(dpy, False);
       
   248 	XSetErrorHandler(NULL);
       
   249 	xerrorxlib = XSetErrorHandler(xerror);
       
   250 	XSync(dpy, False);
       
   251 	setup();
       
   252 	drawbar();
       
   253 	scan();
       
   254 
       
   255 	/* main event loop, also reads status text from stdin */
       
   256 	XSync(dpy, False);
       
   257 	readin = True;
       
   258 	while(running) {
       
   259 		FD_ZERO(&rd);
       
   260 		if(readin)
       
   261 			FD_SET(STDIN_FILENO, &rd);
       
   262 		FD_SET(xfd, &rd);
       
   263 		if(select(xfd + 1, &rd, NULL, NULL, NULL) == -1) {
       
   264 			if(errno == EINTR)
       
   265 				continue;
       
   266 			eprint("select failed\n");
       
   267 		}
       
   268 		if(FD_ISSET(STDIN_FILENO, &rd)) {
       
   269 			switch(r = read(STDIN_FILENO, stext, sizeof stext - 1)) {
       
   270 			case -1:
       
   271 				strncpy(stext, strerror(errno), sizeof stext - 1);
       
   272 				stext[sizeof stext - 1] = '\0';
       
   273 				readin = False;
       
   274 				break;
       
   275 			case 0:
       
   276 				strncpy(stext, "EOF", 4);
       
   277 				readin = False;
       
   278 				break;
       
   279 			default:
       
   280 				for(stext[r] = '\0', p = stext + strlen(stext) - 1; p >= stext && *p == '\n'; *p-- = '\0');
       
   281 				for(; p >= stext && *p != '\n'; --p);
       
   282 				if(p > stext)
       
   283 					strncpy(stext, p + 1, sizeof stext);
       
   284 			}
       
   285 			drawbar();
       
   286 		}
       
   287 		while(XPending(dpy)) {
       
   288 			XNextEvent(dpy, &ev);
       
   289 			if(handler[ev.type])
       
   290 				(handler[ev.type])(&ev); /* call handler */
       
   291 		}
       
   292 	}
       
   293 	cleanup();
       
   294 	XCloseDisplay(dpy);
       
   295 	return 0;
       
   296 }