dwm.c
changeset 1226 6830cb2bbecf
parent 1225 6211d430f5da
child 1227 1f0e2de78c35
equal deleted inserted replaced
1225:6211d430f5da 1226:6830cb2bbecf
    58 enum { ColBorder, ColFG, ColBG, ColLast };              /* color */
    58 enum { ColBorder, ColFG, ColBG, ColLast };              /* color */
    59 enum { NetSupported, NetWMName, NetLast };              /* EWMH atoms */
    59 enum { NetSupported, NetWMName, NetLast };              /* EWMH atoms */
    60 enum { WMProtocols, WMDelete, WMName, WMState, WMLast };/* default atoms */
    60 enum { WMProtocols, WMDelete, WMName, WMState, WMLast };/* default atoms */
    61 
    61 
    62 /* typedefs */
    62 /* typedefs */
       
    63 typedef unsigned int uint;
    63 typedef struct Client Client;
    64 typedef struct Client Client;
    64 struct Client {
    65 struct Client {
    65 	char name[256];
    66 	char name[256];
    66 	int x, y, w, h;
    67 	int x, y, w, h;
    67 	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
    68 	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
    68 	int minax, maxax, minay, maxay;
    69 	int minax, maxax, minay, maxay;
    69 	long flags;
    70 	long flags;
    70 	unsigned int bw, oldbw;
    71 	uint bw, oldbw;
    71 	Bool isbanned, isfixed, isfloating, isurgent;
    72 	Bool isbanned, isfixed, isfloating, isurgent;
    72 	unsigned int tags;
    73 	uint tags;
    73 	Client *next;
    74 	Client *next;
    74 	Client *prev;
    75 	Client *prev;
    75 	Client *snext;
    76 	Client *snext;
    76 	Window win;
    77 	Window win;
    77 };
    78 };
   106 
   107 
   107 typedef struct {
   108 typedef struct {
   108 	const char *class;
   109 	const char *class;
   109 	const char *instance;
   110 	const char *instance;
   110 	const char *title;
   111 	const char *title;
   111 	unsigned int tags;
   112 	uint tags;
   112 	Bool isfloating;
   113 	Bool isfloating;
   113 } Rule;
   114 } Rule;
   114 
   115 
   115 /* function declarations */
   116 /* function declarations */
   116 void applyrules(Client *c);
   117 void applyrules(Client *c);
   128 void detach(Client *c);
   129 void detach(Client *c);
   129 void detachstack(Client *c);
   130 void detachstack(Client *c);
   130 void drawbar(void);
   131 void drawbar(void);
   131 void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]);
   132 void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]);
   132 void drawtext(const char *text, unsigned long col[ColLast], Bool invert);
   133 void drawtext(const char *text, unsigned long col[ColLast], Bool invert);
   133 void *emallocz(unsigned int size);
   134 void *emallocz(uint size);
   134 void enternotify(XEvent *e);
   135 void enternotify(XEvent *e);
   135 void eprint(const char *errstr, ...);
   136 void eprint(const char *errstr, ...);
   136 void expose(XEvent *e);
   137 void expose(XEvent *e);
   137 void focus(Client *c);
   138 void focus(Client *c);
   138 void focusin(XEvent *e);
   139 void focusin(XEvent *e);
   139 void focusnext(const void *arg);
   140 void focusnext(const void *arg);
   140 void focusprev(const void *arg);
   141 void focusprev(const void *arg);
   141 Client *getclient(Window w);
   142 Client *getclient(Window w);
   142 unsigned long getcolor(const char *colstr);
   143 unsigned long getcolor(const char *colstr);
   143 long getstate(Window w);
   144 long getstate(Window w);
   144 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
   145 Bool gettextprop(Window w, Atom atom, char *text, uint size);
   145 void grabbuttons(Client *c, Bool focused);
   146 void grabbuttons(Client *c, Bool focused);
   146 void grabkeys(void);
   147 void grabkeys(void);
   147 void initfont(const char *fontstr);
   148 void initfont(const char *fontstr);
   148 Bool isoccupied(unsigned int t);
   149 Bool isoccupied(uint t);
   149 Bool isprotodel(Client *c);
   150 Bool isprotodel(Client *c);
   150 Bool isurgent(unsigned int t);
   151 Bool isurgent(uint t);
   151 Bool isvisible(Client *c);
   152 Bool isvisible(Client *c);
   152 void keypress(XEvent *e);
   153 void keypress(XEvent *e);
   153 void killclient(const void *arg);
   154 void killclient(const void *arg);
   154 void manage(Window w, XWindowAttributes *wa);
   155 void manage(Window w, XWindowAttributes *wa);
   155 void mappingnotify(XEvent *e);
   156 void mappingnotify(XEvent *e);
   166 void setclientstate(Client *c, long state);
   167 void setclientstate(Client *c, long state);
   167 void setmfact(const void *arg);
   168 void setmfact(const void *arg);
   168 void setup(void);
   169 void setup(void);
   169 void spawn(const void *arg);
   170 void spawn(const void *arg);
   170 void tag(const void *arg);
   171 void tag(const void *arg);
   171 unsigned int textnw(const char *text, unsigned int len);
   172 uint textnw(const char *text, uint len);
   172 unsigned int textw(const char *text);
   173 uint textw(const char *text);
   173 void tile(void);
   174 void tile(void);
   174 void tileresize(Client *c, int x, int y, int w, int h);
   175 void tileresize(Client *c, int x, int y, int w, int h);
   175 void togglebar(const void *arg);
   176 void togglebar(const void *arg);
   176 void togglefloating(const void *arg);
   177 void togglefloating(const void *arg);
   177 void togglelayout(const void *arg);
   178 void togglelayout(const void *arg);
   196 /* variables */
   197 /* variables */
   197 char stext[256];
   198 char stext[256];
   198 int screen, sx, sy, sw, sh;
   199 int screen, sx, sy, sw, sh;
   199 int bx, by, bw, bh, blw, wx, wy, ww, wh;
   200 int bx, by, bw, bh, blw, wx, wy, ww, wh;
   200 int mx, my, mw, mh, tx, ty, tw, th;
   201 int mx, my, mw, mh, tx, ty, tw, th;
   201 unsigned int seltags = 0;
   202 uint seltags = 0;
   202 int (*xerrorxlib)(Display *, XErrorEvent *);
   203 int (*xerrorxlib)(Display *, XErrorEvent *);
   203 unsigned int numlockmask = 0;
   204 uint numlockmask = 0;
   204 void (*handler[LASTEvent]) (XEvent *) = {
   205 void (*handler[LASTEvent]) (XEvent *) = {
   205 	[ButtonPress] = buttonpress,
   206 	[ButtonPress] = buttonpress,
   206 	[ConfigureRequest] = configurerequest,
   207 	[ConfigureRequest] = configurerequest,
   207 	[ConfigureNotify] = configurenotify,
   208 	[ConfigureNotify] = configurenotify,
   208 	[DestroyNotify] = destroynotify,
   209 	[DestroyNotify] = destroynotify,
   216 	[UnmapNotify] = unmapnotify
   217 	[UnmapNotify] = unmapnotify
   217 };
   218 };
   218 Atom wmatom[WMLast], netatom[NetLast];
   219 Atom wmatom[WMLast], netatom[NetLast];
   219 Bool otherwm, readin;
   220 Bool otherwm, readin;
   220 Bool running = True;
   221 Bool running = True;
   221 unsigned int tagset[] = {1, 1}; /* after start, first tag is selected */
   222 uint tagset[] = {1, 1}; /* after start, first tag is selected */
   222 Client *clients = NULL;
   223 Client *clients = NULL;
   223 Client *sel = NULL;
   224 Client *sel = NULL;
   224 Client *stack = NULL;
   225 Client *stack = NULL;
   225 Cursor cursor[CurLast];
   226 Cursor cursor[CurLast];
   226 Display *dpy;
   227 Display *dpy;
   230 Window root, barwin;
   231 Window root, barwin;
   231 
   232 
   232 /* configuration, allows nested code to access above variables */
   233 /* configuration, allows nested code to access above variables */
   233 #include "config.h"
   234 #include "config.h"
   234 
   235 
   235 /* check if all tags will fit into a unsigned int bitarray. */
   236 /* check if all tags will fit into a uint bitarray. */
   236 static char tags_is_a_sign_that_your_IQ[sizeof(int) * 8 < LENGTH(tags) ? -1 : 1];
   237 static char tags_is_a_sign_that_your_IQ[sizeof(int) * 8 < LENGTH(tags) ? -1 : 1];
   237 
   238 
   238 /* function implementations */
   239 /* function implementations */
   239 
   240 
   240 void
   241 void
   241 applyrules(Client *c) {
   242 applyrules(Client *c) {
   242 	unsigned int i;
   243 	uint i;
   243 	Rule *r;
   244 	Rule *r;
   244 	XClassHint ch = { 0 };
   245 	XClassHint ch = { 0 };
   245 
   246 
   246 	/* rule matching */
   247 	/* rule matching */
   247 	XGetClassHint(dpy, c->win, &ch);
   248 	XGetClassHint(dpy, c->win, &ch);
   303 	c->isbanned = True;
   304 	c->isbanned = True;
   304 }
   305 }
   305 
   306 
   306 void
   307 void
   307 buttonpress(XEvent *e) {
   308 buttonpress(XEvent *e) {
   308 	unsigned int i, x, mask;
   309 	uint i, x, mask;
   309 	Client *c;
   310 	Client *c;
   310 	XButtonPressedEvent *ev = &e->xbutton;
   311 	XButtonPressedEvent *ev = &e->xbutton;
   311 
   312 
   312 	if(ev->window == barwin) {
   313 	if(ev->window == barwin) {
   313 		x = 0;
   314 		x = 0;
   559 }
   560 }
   560 
   561 
   561 void
   562 void
   562 drawtext(const char *text, unsigned long col[ColLast], Bool invert) {
   563 drawtext(const char *text, unsigned long col[ColLast], Bool invert) {
   563 	int x, y, w, h;
   564 	int x, y, w, h;
   564 	unsigned int len, olen;
   565 	uint len, olen;
   565 	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
   566 	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
   566 	char buf[256];
   567 	char buf[256];
   567 
   568 
   568 	XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]);
   569 	XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]);
   569 	XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
   570 	XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
   594 	else
   595 	else
   595 		XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
   596 		XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
   596 }
   597 }
   597 
   598 
   598 void *
   599 void *
   599 emallocz(unsigned int size) {
   600 emallocz(uint size) {
   600 	void *res = calloc(1, size);
   601 	void *res = calloc(1, size);
   601 
   602 
   602 	if(!res)
   603 	if(!res)
   603 		eprint("fatal: could not malloc() %u bytes\n", size);
   604 		eprint("fatal: could not malloc() %u bytes\n", size);
   604 	return res;
   605 	return res;
   733 	XFree(p);
   734 	XFree(p);
   734 	return result;
   735 	return result;
   735 }
   736 }
   736 
   737 
   737 Bool
   738 Bool
   738 gettextprop(Window w, Atom atom, char *text, unsigned int size) {
   739 gettextprop(Window w, Atom atom, char *text, uint size) {
   739 	char **list = NULL;
   740 	char **list = NULL;
   740 	int n;
   741 	int n;
   741 	XTextProperty name;
   742 	XTextProperty name;
   742 
   743 
   743 	if(!text || size == 0)
   744 	if(!text || size == 0)
   761 }
   762 }
   762 
   763 
   763 void
   764 void
   764 grabbuttons(Client *c, Bool focused) {
   765 grabbuttons(Client *c, Bool focused) {
   765 	int i, j;
   766 	int i, j;
   766 	unsigned int buttons[]   = { Button1, Button2, Button3 };
   767 	uint buttons[]   = { Button1, Button2, Button3 };
   767 	unsigned int modifiers[] = { MODKEY, MODKEY|LockMask, MODKEY|numlockmask,
   768 	uint modifiers[] = { MODKEY, MODKEY|LockMask, MODKEY|numlockmask,
   768 				MODKEY|numlockmask|LockMask} ;
   769 				MODKEY|numlockmask|LockMask} ;
   769 
   770 
   770 	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
   771 	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
   771 	if(focused)
   772 	if(focused)
   772 		for(i = 0; i < LENGTH(buttons); i++)
   773 		for(i = 0; i < LENGTH(buttons); i++)
   778 			BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
   779 			BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
   779 }
   780 }
   780 
   781 
   781 void
   782 void
   782 grabkeys(void) {
   783 grabkeys(void) {
   783 	unsigned int i, j;
   784 	uint i, j;
   784 	KeyCode code;
   785 	KeyCode code;
   785 	XModifierKeymap *modmap;
   786 	XModifierKeymap *modmap;
   786 
   787 
   787 	/* init modifier map */
   788 	/* init modifier map */
   788 	modmap = XGetModifierMapping(dpy);
   789 	modmap = XGetModifierMapping(dpy);
   846 	}
   847 	}
   847 	dc.font.height = dc.font.ascent + dc.font.descent;
   848 	dc.font.height = dc.font.ascent + dc.font.descent;
   848 }
   849 }
   849 
   850 
   850 Bool
   851 Bool
   851 isoccupied(unsigned int t) {
   852 isoccupied(uint t) {
   852 	Client *c;
   853 	Client *c;
   853 
   854 
   854 	for(c = clients; c; c = c->next)
   855 	for(c = clients; c; c = c->next)
   855 		if(c->tags & 1 << t)
   856 		if(c->tags & 1 << t)
   856 			return True;
   857 			return True;
   871 	}
   872 	}
   872 	return ret;
   873 	return ret;
   873 }
   874 }
   874 
   875 
   875 Bool
   876 Bool
   876 isurgent(unsigned int t) {
   877 isurgent(uint t) {
   877 	Client *c;
   878 	Client *c;
   878 
   879 
   879 	for(c = clients; c; c = c->next)
   880 	for(c = clients; c; c = c->next)
   880 		if(c->isurgent && c->tags & 1 << t)
   881 		if(c->isurgent && c->tags & 1 << t)
   881 			return True;
   882 			return True;
   887 	return c->tags & tagset[seltags];
   888 	return c->tags & tagset[seltags];
   888 }
   889 }
   889 
   890 
   890 void
   891 void
   891 keypress(XEvent *e) {
   892 keypress(XEvent *e) {
   892 	unsigned int i;
   893 	uint i;
   893 	KeySym keysym;
   894 	KeySym keysym;
   894 	XKeyEvent *ev;
   895 	XKeyEvent *ev;
   895 
   896 
   896 	ev = &e->xkey;
   897 	ev = &e->xkey;
   897 	keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
   898 	keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
  1002 }
  1003 }
  1003 
  1004 
  1004 void
  1005 void
  1005 movemouse(Client *c) {
  1006 movemouse(Client *c) {
  1006 	int x1, y1, ocx, ocy, di, nx, ny;
  1007 	int x1, y1, ocx, ocy, di, nx, ny;
  1007 	unsigned int dui;
  1008 	uint dui;
  1008 	Window dummy;
  1009 	Window dummy;
  1009 	XEvent ev;
  1010 	XEvent ev;
  1010 
  1011 
  1011 	ocx = nx = c->x;
  1012 	ocx = nx = c->x;
  1012 	ocy = ny = c->y;
  1013 	ocy = ny = c->y;
  1228 run(void) {
  1229 run(void) {
  1229 	char *p;
  1230 	char *p;
  1230 	char sbuf[sizeof stext];
  1231 	char sbuf[sizeof stext];
  1231 	fd_set rd;
  1232 	fd_set rd;
  1232 	int r, xfd;
  1233 	int r, xfd;
  1233 	unsigned int len, offset;
  1234 	uint len, offset;
  1234 	XEvent ev;
  1235 	XEvent ev;
  1235 
  1236 
  1236 	/* main event loop, also reads status text from stdin */
  1237 	/* main event loop, also reads status text from stdin */
  1237 	XSync(dpy, False);
  1238 	XSync(dpy, False);
  1238 	xfd = ConnectionNumber(dpy);
  1239 	xfd = ConnectionNumber(dpy);
  1284 	}
  1285 	}
  1285 }
  1286 }
  1286 
  1287 
  1287 void
  1288 void
  1288 scan(void) {
  1289 scan(void) {
  1289 	unsigned int i, num;
  1290 	uint i, num;
  1290 	Window *wins, d1, d2;
  1291 	Window *wins, d1, d2;
  1291 	XWindowAttributes wa;
  1292 	XWindowAttributes wa;
  1292 
  1293 
  1293 	wins = NULL;
  1294 	wins = NULL;
  1294 	if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
  1295 	if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
  1334 	arrange();
  1335 	arrange();
  1335 }
  1336 }
  1336 
  1337 
  1337 void
  1338 void
  1338 setup(void) {
  1339 setup(void) {
  1339 	unsigned int i, w;
  1340 	uint i, w;
  1340 	XSetWindowAttributes wa;
  1341 	XSetWindowAttributes wa;
  1341 
  1342 
  1342 	/* init screen */
  1343 	/* init screen */
  1343 	screen = DefaultScreen(dpy);
  1344 	screen = DefaultScreen(dpy);
  1344 	root = RootWindow(dpy, screen);
  1345 	root = RootWindow(dpy, screen);
  1439 		sel->tags = *(int *)arg & TAGMASK;
  1440 		sel->tags = *(int *)arg & TAGMASK;
  1440 		arrange();
  1441 		arrange();
  1441 	}
  1442 	}
  1442 }
  1443 }
  1443 
  1444 
  1444 unsigned int
  1445 uint
  1445 textnw(const char *text, unsigned int len) {
  1446 textnw(const char *text, uint len) {
  1446 	XRectangle r;
  1447 	XRectangle r;
  1447 
  1448 
  1448 	if(dc.font.set) {
  1449 	if(dc.font.set) {
  1449 		XmbTextExtents(dc.font.set, text, len, NULL, &r);
  1450 		XmbTextExtents(dc.font.set, text, len, NULL, &r);
  1450 		return r.width;
  1451 		return r.width;
  1451 	}
  1452 	}
  1452 	return XTextWidth(dc.font.xfont, text, len);
  1453 	return XTextWidth(dc.font.xfont, text, len);
  1453 }
  1454 }
  1454 
  1455 
  1455 unsigned int
  1456 uint
  1456 textw(const char *text) {
  1457 textw(const char *text) {
  1457 	return textnw(text, strlen(text)) + dc.font.height;
  1458 	return textnw(text, strlen(text)) + dc.font.height;
  1458 }
  1459 }
  1459 
  1460 
  1460 void
  1461 void
  1461 tile(void) {
  1462 tile(void) {
  1462 	int x, y, h, w;
  1463 	int x, y, h, w;
  1463 	unsigned int i, n;
  1464 	uint i, n;
  1464 	Client *c;
  1465 	Client *c;
  1465 
  1466 
  1466 	for(n = 0, c = nextunfloating(clients); c; c = nextunfloating(c->next), n++);
  1467 	for(n = 0, c = nextunfloating(clients); c; c = nextunfloating(c->next), n++);
  1467 	if(n == 0)
  1468 	if(n == 0)
  1468 		return;
  1469 		return;
  1522 	arrange();
  1523 	arrange();
  1523 }
  1524 }
  1524 
  1525 
  1525 void
  1526 void
  1526 togglelayout(const void *arg) {
  1527 togglelayout(const void *arg) {
  1527 	unsigned int i;
  1528 	uint i;
  1528 
  1529 
  1529 	if(!arg) {
  1530 	if(!arg) {
  1530 		if(++lt == &layouts[LENGTH(layouts)])
  1531 		if(++lt == &layouts[LENGTH(layouts)])
  1531 			lt = &layouts[0];
  1532 			lt = &layouts[0];
  1532 	}
  1533 	}