dwm.c
changeset 1310 1d52b420daa4
parent 1309 3affae730034
child 1311 47b3dbd9a7d3
equal deleted inserted replaced
1309:3affae730034 1310:1d52b420daa4
    61 enum { NetSupported, NetWMName, NetLast };              /* EWMH atoms */
    61 enum { NetSupported, NetWMName, NetLast };              /* EWMH atoms */
    62 enum { WMProtocols, WMDelete, WMName, WMState, WMLast };/* default atoms */
    62 enum { WMProtocols, WMDelete, WMName, WMState, WMLast };/* default atoms */
    63 enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
    63 enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
    64        ClkClientWin, ClkRootWin, ClkLast };             /* clicks */
    64        ClkClientWin, ClkRootWin, ClkLast };             /* clicks */
    65 
    65 
    66 /* typedefs */
       
    67 typedef unsigned int uint;
       
    68 typedef unsigned long ulong;
       
    69 
       
    70 typedef union {
    66 typedef union {
    71 	int i;
    67 	int i;
    72 	uint ui;
    68 	unsigned int ui;
    73 	float f;
    69 	float f;
    74 	void *v;
    70 	void *v;
    75 } Arg;
    71 } Arg;
    76 
    72 
    77 typedef struct {
    73 typedef struct {
    78 	uint click;
    74 	unsigned int click;
    79 	uint mask;
    75 	unsigned int mask;
    80 	uint button;
    76 	unsigned int button;
    81 	void (*func)(const Arg *arg);
    77 	void (*func)(const Arg *arg);
    82 	const Arg arg;
    78 	const Arg arg;
    83 } Button;
    79 } Button;
    84 
    80 
    85 typedef struct Client Client;
    81 typedef struct Client Client;
    87 	char name[256];
    83 	char name[256];
    88 	float mina, maxa;
    84 	float mina, maxa;
    89 	int x, y, w, h;
    85 	int x, y, w, h;
    90 	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
    86 	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
    91 	int bw, oldbw;
    87 	int bw, oldbw;
    92 	uint tags;
    88 	unsigned int tags;
    93 	Bool isfixed, isfloating, isurgent;
    89 	Bool isfixed, isfloating, isurgent;
    94 	Client *next;
    90 	Client *next;
    95 	Client *snext;
    91 	Client *snext;
    96 	Window win;
    92 	Window win;
    97 };
    93 };
    98 
    94 
    99 typedef struct {
    95 typedef struct {
   100 	int x, y, w, h;
    96 	int x, y, w, h;
   101 	ulong norm[ColLast];
    97 	unsigned long norm[ColLast];
   102 	ulong sel[ColLast];
    98 	unsigned long sel[ColLast];
   103 	Drawable drawable;
    99 	Drawable drawable;
   104 	GC gc;
   100 	GC gc;
   105 	struct {
   101 	struct {
   106 		int ascent;
   102 		int ascent;
   107 		int descent;
   103 		int descent;
   110 		XFontStruct *xfont;
   106 		XFontStruct *xfont;
   111 	} font;
   107 	} font;
   112 } DC; /* draw context */
   108 } DC; /* draw context */
   113 
   109 
   114 typedef struct {
   110 typedef struct {
   115 	uint mod;
   111 	unsigned int mod;
   116 	KeySym keysym;
   112 	KeySym keysym;
   117 	void (*func)(const Arg *);
   113 	void (*func)(const Arg *);
   118 	const Arg arg;
   114 	const Arg arg;
   119 } Key;
   115 } Key;
   120 
   116 
   125 
   121 
   126 typedef struct {
   122 typedef struct {
   127 	const char *class;
   123 	const char *class;
   128 	const char *instance;
   124 	const char *instance;
   129 	const char *title;
   125 	const char *title;
   130 	uint tags;
   126 	unsigned int tags;
   131 	Bool isfloating;
   127 	Bool isfloating;
   132 } Rule;
   128 } Rule;
   133 
   129 
   134 /* function declarations */
   130 /* function declarations */
   135 static void applyrules(Client *c);
   131 static void applyrules(Client *c);
   146 static void destroynotify(XEvent *e);
   142 static void destroynotify(XEvent *e);
   147 static void detach(Client *c);
   143 static void detach(Client *c);
   148 static void detachstack(Client *c);
   144 static void detachstack(Client *c);
   149 static void die(const char *errstr, ...);
   145 static void die(const char *errstr, ...);
   150 static void drawbar(void);
   146 static void drawbar(void);
   151 static void drawsquare(Bool filled, Bool empty, Bool invert, ulong col[ColLast]);
   147 static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]);
   152 static void drawtext(const char *text, ulong col[ColLast], Bool invert);
   148 static void drawtext(const char *text, unsigned long col[ColLast], Bool invert);
   153 static void enternotify(XEvent *e);
   149 static void enternotify(XEvent *e);
   154 static void expose(XEvent *e);
   150 static void expose(XEvent *e);
   155 static void focus(Client *c);
   151 static void focus(Client *c);
   156 static void focusin(XEvent *e);
   152 static void focusin(XEvent *e);
   157 static void focusstack(const Arg *arg);
   153 static void focusstack(const Arg *arg);
   158 static Client *getclient(Window w);
   154 static Client *getclient(Window w);
   159 static ulong getcolor(const char *colstr);
   155 static unsigned long getcolor(const char *colstr);
   160 static long getstate(Window w);
   156 static long getstate(Window w);
   161 static Bool gettextprop(Window w, Atom atom, char *text, uint size);
   157 static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
   162 static void grabbuttons(Client *c, Bool focused);
   158 static void grabbuttons(Client *c, Bool focused);
   163 static void grabkeys(void);
   159 static void grabkeys(void);
   164 static void initfont(const char *fontstr);
   160 static void initfont(const char *fontstr);
   165 static Bool isoccupied(uint t);
   161 static Bool isoccupied(unsigned int t);
   166 static Bool isprotodel(Client *c);
   162 static Bool isprotodel(Client *c);
   167 static Bool isurgent(uint t);
   163 static Bool isurgent(unsigned int t);
   168 static void keypress(XEvent *e);
   164 static void keypress(XEvent *e);
   169 static void killclient(const Arg *arg);
   165 static void killclient(const Arg *arg);
   170 static void manage(Window w, XWindowAttributes *wa);
   166 static void manage(Window w, XWindowAttributes *wa);
   171 static void mappingnotify(XEvent *e);
   167 static void mappingnotify(XEvent *e);
   172 static void maprequest(XEvent *e);
   168 static void maprequest(XEvent *e);
   184 static void setlayout(const Arg *arg);
   180 static void setlayout(const Arg *arg);
   185 static void setmfact(const Arg *arg);
   181 static void setmfact(const Arg *arg);
   186 static void setup(void);
   182 static void setup(void);
   187 static void spawn(const Arg *arg);
   183 static void spawn(const Arg *arg);
   188 static void tag(const Arg *arg);
   184 static void tag(const Arg *arg);
   189 static int textnw(const char *text, uint len);
   185 static int textnw(const char *text, unsigned int len);
   190 static void tile(void);
   186 static void tile(void);
   191 static void togglebar(const Arg *arg);
   187 static void togglebar(const Arg *arg);
   192 static void togglefloating(const Arg *arg);
   188 static void togglefloating(const Arg *arg);
   193 static void toggletag(const Arg *arg);
   189 static void toggletag(const Arg *arg);
   194 static void toggleview(const Arg *arg);
   190 static void toggleview(const Arg *arg);
   207 
   203 
   208 /* variables */
   204 /* variables */
   209 static char stext[256];
   205 static char stext[256];
   210 static int screen, sx, sy, sw, sh;
   206 static int screen, sx, sy, sw, sh;
   211 static int by, bh, blw, wx, wy, ww, wh;
   207 static int by, bh, blw, wx, wy, ww, wh;
   212 static uint seltags = 0, sellt = 0;
   208 static unsigned int seltags = 0, sellt = 0;
   213 static int (*xerrorxlib)(Display *, XErrorEvent *);
   209 static int (*xerrorxlib)(Display *, XErrorEvent *);
   214 static uint numlockmask = 0;
   210 static unsigned int numlockmask = 0;
   215 static void (*handler[LASTEvent]) (XEvent *) = {
   211 static void (*handler[LASTEvent]) (XEvent *) = {
   216 	[ButtonPress] = buttonpress,
   212 	[ButtonPress] = buttonpress,
   217 	[ConfigureRequest] = configurerequest,
   213 	[ConfigureRequest] = configurerequest,
   218 	[ConfigureNotify] = configurenotify,
   214 	[ConfigureNotify] = configurenotify,
   219 	[DestroyNotify] = destroynotify,
   215 	[DestroyNotify] = destroynotify,
   227 	[UnmapNotify] = unmapnotify
   223 	[UnmapNotify] = unmapnotify
   228 };
   224 };
   229 static Atom wmatom[WMLast], netatom[NetLast];
   225 static Atom wmatom[WMLast], netatom[NetLast];
   230 static Bool otherwm, readin;
   226 static Bool otherwm, readin;
   231 static Bool running = True;
   227 static Bool running = True;
   232 static uint tagset[] = {1, 1}; /* after start, first tag is selected */
   228 static unsigned int tagset[] = {1, 1}; /* after start, first tag is selected */
   233 static Client *clients = NULL;
   229 static Client *clients = NULL;
   234 static Client *sel = NULL;
   230 static Client *sel = NULL;
   235 static Client *stack = NULL;
   231 static Client *stack = NULL;
   236 static Cursor cursor[CurLast];
   232 static Cursor cursor[CurLast];
   237 static Display *dpy;
   233 static Display *dpy;
   239 static Layout *lt[] = { NULL, NULL };
   235 static Layout *lt[] = { NULL, NULL };
   240 static Window root, barwin;
   236 static Window root, barwin;
   241 /* configuration, allows nested code to access above variables */
   237 /* configuration, allows nested code to access above variables */
   242 #include "config.h"
   238 #include "config.h"
   243 
   239 
   244 /* compile-time check if all tags fit into an uint bit array. */
   240 /* compile-time check if all tags fit into an unsigned int bit array. */
   245 struct NumTags { char limitexceeded[sizeof(uint) * 8 < LENGTH(tags) ? -1 : 1]; };
   241 struct NumTags { char limitexceeded[sizeof(unsigned int) * 8 < LENGTH(tags) ? -1 : 1]; };
   246 
   242 
   247 /* function implementations */
   243 /* function implementations */
   248 void
   244 void
   249 applyrules(Client *c) {
   245 applyrules(Client *c) {
   250 	uint i;
   246 	unsigned int i;
   251 	Rule *r;
   247 	Rule *r;
   252 	XClassHint ch = { 0 };
   248 	XClassHint ch = { 0 };
   253 
   249 
   254 	/* rule matching */
   250 	/* rule matching */
   255 	XGetClassHint(dpy, c->win, &ch);
   251 	XGetClassHint(dpy, c->win, &ch);
   302 	stack = c;
   298 	stack = c;
   303 }
   299 }
   304 
   300 
   305 void
   301 void
   306 buttonpress(XEvent *e) {
   302 buttonpress(XEvent *e) {
   307 	uint i, x, click;
   303 	unsigned int i, x, click;
   308 	Arg arg = {0};
   304 	Arg arg = {0};
   309 	Client *c;
   305 	Client *c;
   310 	XButtonPressedEvent *ev = &e->xbutton;
   306 	XButtonPressedEvent *ev = &e->xbutton;
   311 
   307 
   312 	click = ClkRootWin;
   308 	click = ClkRootWin;
   544 	XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, ww, bh, 0, 0);
   540 	XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, ww, bh, 0, 0);
   545 	XSync(dpy, False);
   541 	XSync(dpy, False);
   546 }
   542 }
   547 
   543 
   548 void
   544 void
   549 drawsquare(Bool filled, Bool empty, Bool invert, ulong col[ColLast]) {
   545 drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) {
   550 	int x;
   546 	int x;
   551 	XGCValues gcv;
   547 	XGCValues gcv;
   552 	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
   548 	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
   553 
   549 
   554 	gcv.foreground = col[invert ? ColBG : ColFG];
   550 	gcv.foreground = col[invert ? ColBG : ColFG];
   565 		XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1);
   561 		XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1);
   566 	}
   562 	}
   567 }
   563 }
   568 
   564 
   569 void
   565 void
   570 drawtext(const char *text, ulong col[ColLast], Bool invert) {
   566 drawtext(const char *text, unsigned long col[ColLast], Bool invert) {
   571 	int i, x, y, h, len, olen;
   567 	int i, x, y, h, len, olen;
   572 	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
   568 	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
   573 	char buf[256];
   569 	char buf[256];
   574 
   570 
   575 	XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]);
   571 	XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]);
   677 
   673 
   678 	for(c = clients; c && c->win != w; c = c->next);
   674 	for(c = clients; c && c->win != w; c = c->next);
   679 	return c;
   675 	return c;
   680 }
   676 }
   681 
   677 
   682 ulong
   678 unsigned long
   683 getcolor(const char *colstr) {
   679 getcolor(const char *colstr) {
   684 	Colormap cmap = DefaultColormap(dpy, screen);
   680 	Colormap cmap = DefaultColormap(dpy, screen);
   685 	XColor color;
   681 	XColor color;
   686 
   682 
   687 	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
   683 	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
   692 long
   688 long
   693 getstate(Window w) {
   689 getstate(Window w) {
   694 	int format, status;
   690 	int format, status;
   695 	long result = -1;
   691 	long result = -1;
   696 	unsigned char *p = NULL;
   692 	unsigned char *p = NULL;
   697 	ulong n, extra;
   693 	unsigned long n, extra;
   698 	Atom real;
   694 	Atom real;
   699 
   695 
   700 	status = XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
   696 	status = XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
   701 			&real, &format, &n, &extra, (unsigned char **)&p);
   697 			&real, &format, &n, &extra, (unsigned char **)&p);
   702 	if(status != Success)
   698 	if(status != Success)
   706 	XFree(p);
   702 	XFree(p);
   707 	return result;
   703 	return result;
   708 }
   704 }
   709 
   705 
   710 Bool
   706 Bool
   711 gettextprop(Window w, Atom atom, char *text, uint size) {
   707 gettextprop(Window w, Atom atom, char *text, unsigned int size) {
   712 	char **list = NULL;
   708 	char **list = NULL;
   713 	int n;
   709 	int n;
   714 	XTextProperty name;
   710 	XTextProperty name;
   715 
   711 
   716 	if(!text || size == 0)
   712 	if(!text || size == 0)
   733 	return True;
   729 	return True;
   734 }
   730 }
   735 
   731 
   736 void
   732 void
   737 grabbuttons(Client *c, Bool focused) {
   733 grabbuttons(Client *c, Bool focused) {
   738 	uint i, j;
   734 	unsigned int i, j;
   739 	uint modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
   735 	unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
   740 
   736 
   741 	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
   737 	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
   742 	if(focused) {
   738 	if(focused) {
   743 		for(i = 0; i < LENGTH(buttons); i++)
   739 		for(i = 0; i < LENGTH(buttons); i++)
   744 			if(buttons[i].click == ClkClientWin)
   740 			if(buttons[i].click == ClkClientWin)
   749 		            BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
   745 		            BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
   750 }
   746 }
   751 
   747 
   752 void
   748 void
   753 grabkeys(void) {
   749 grabkeys(void) {
   754 	uint i, j;
   750 	unsigned int i, j;
   755 	KeyCode code;
   751 	KeyCode code;
   756 	XModifierKeymap *modmap;
   752 	XModifierKeymap *modmap;
   757 
   753 
   758 	/* init modifier map */
   754 	/* init modifier map */
   759 	modmap = XGetModifierMapping(dpy);
   755 	modmap = XGetModifierMapping(dpy);
   817 	}
   813 	}
   818 	dc.font.height = dc.font.ascent + dc.font.descent;
   814 	dc.font.height = dc.font.ascent + dc.font.descent;
   819 }
   815 }
   820 
   816 
   821 Bool
   817 Bool
   822 isoccupied(uint t) {
   818 isoccupied(unsigned int t) {
   823 	Client *c;
   819 	Client *c;
   824 
   820 
   825 	for(c = clients; c; c = c->next)
   821 	for(c = clients; c; c = c->next)
   826 		if(c->tags & 1 << t)
   822 		if(c->tags & 1 << t)
   827 			return True;
   823 			return True;
   842 	}
   838 	}
   843 	return ret;
   839 	return ret;
   844 }
   840 }
   845 
   841 
   846 Bool
   842 Bool
   847 isurgent(uint t) {
   843 isurgent(unsigned int t) {
   848 	Client *c;
   844 	Client *c;
   849 
   845 
   850 	for(c = clients; c; c = c->next)
   846 	for(c = clients; c; c = c->next)
   851 		if(c->isurgent && c->tags & 1 << t)
   847 		if(c->isurgent && c->tags & 1 << t)
   852 			return True;
   848 			return True;
   853 	return False;
   849 	return False;
   854 }
   850 }
   855 
   851 
   856 void
   852 void
   857 keypress(XEvent *e) {
   853 keypress(XEvent *e) {
   858 	uint i;
   854 	unsigned int i;
   859 	KeySym keysym;
   855 	KeySym keysym;
   860 	XKeyEvent *ev;
   856 	XKeyEvent *ev;
   861 
   857 
   862 	ev = &e->xkey;
   858 	ev = &e->xkey;
   863 	keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
   859 	keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
   977 }
   973 }
   978 
   974 
   979 void
   975 void
   980 movemouse(const Arg *arg) {
   976 movemouse(const Arg *arg) {
   981 	int x1, y1, ocx, ocy, di, nx, ny;
   977 	int x1, y1, ocx, ocy, di, nx, ny;
   982 	uint dui;
   978 	unsigned int dui;
   983 	Client *c;
   979 	Client *c;
   984 	Window dummy;
   980 	Window dummy;
   985 	XEvent ev;
   981 	XEvent ev;
   986 
   982 
   987 	if(!(c = sel))
   983 	if(!(c = sel))
  1214 run(void) {
  1210 run(void) {
  1215 	char *p;
  1211 	char *p;
  1216 	char sbuf[sizeof stext];
  1212 	char sbuf[sizeof stext];
  1217 	fd_set rd;
  1213 	fd_set rd;
  1218 	int r, xfd;
  1214 	int r, xfd;
  1219 	uint len, offset;
  1215 	unsigned int len, offset;
  1220 	XEvent ev;
  1216 	XEvent ev;
  1221 
  1217 
  1222 	/* main event loop, also reads status text from stdin */
  1218 	/* main event loop, also reads status text from stdin */
  1223 	XSync(dpy, False);
  1219 	XSync(dpy, False);
  1224 	xfd = ConnectionNumber(dpy);
  1220 	xfd = ConnectionNumber(dpy);
  1270 	}
  1266 	}
  1271 }
  1267 }
  1272 
  1268 
  1273 void
  1269 void
  1274 scan(void) {
  1270 scan(void) {
  1275 	uint i, num;
  1271 	unsigned int i, num;
  1276 	Window *wins, d1, d2;
  1272 	Window *wins, d1, d2;
  1277 	XWindowAttributes wa;
  1273 	XWindowAttributes wa;
  1278 
  1274 
  1279 	wins = NULL;
  1275 	wins = NULL;
  1280 	if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
  1276 	if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
  1331 	arrange();
  1327 	arrange();
  1332 }
  1328 }
  1333 
  1329 
  1334 void
  1330 void
  1335 setup(void) {
  1331 setup(void) {
  1336 	uint i;
  1332 	unsigned int i;
  1337 	int w;
  1333 	int w;
  1338 	XSetWindowAttributes wa;
  1334 	XSetWindowAttributes wa;
  1339 
  1335 
  1340 	/* init screen */
  1336 	/* init screen */
  1341 	screen = DefaultScreen(dpy);
  1337 	screen = DefaultScreen(dpy);
  1434 		arrange();
  1430 		arrange();
  1435 	}
  1431 	}
  1436 }
  1432 }
  1437 
  1433 
  1438 int
  1434 int
  1439 textnw(const char *text, uint len) {
  1435 textnw(const char *text, unsigned int len) {
  1440 	XRectangle r;
  1436 	XRectangle r;
  1441 
  1437 
  1442 	if(dc.font.set) {
  1438 	if(dc.font.set) {
  1443 		XmbTextExtents(dc.font.set, text, len, NULL, &r);
  1439 		XmbTextExtents(dc.font.set, text, len, NULL, &r);
  1444 		return r.width;
  1440 		return r.width;
  1447 }
  1443 }
  1448 
  1444 
  1449 void
  1445 void
  1450 tile(void) {
  1446 tile(void) {
  1451 	int x, y, h, w, mw;
  1447 	int x, y, h, w, mw;
  1452 	uint i, n;
  1448 	unsigned int i, n;
  1453 	Client *c;
  1449 	Client *c;
  1454 
  1450 
  1455 	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next), n++);
  1451 	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next), n++);
  1456 	if(n == 0)
  1452 	if(n == 0)
  1457 		return;
  1453 		return;
  1498 	arrange();
  1494 	arrange();
  1499 }
  1495 }
  1500 
  1496 
  1501 void
  1497 void
  1502 toggletag(const Arg *arg) {
  1498 toggletag(const Arg *arg) {
  1503 	uint mask = sel->tags ^ (arg->ui & TAGMASK);
  1499 	unsigned int mask = sel->tags ^ (arg->ui & TAGMASK);
  1504 
  1500 
  1505 	if(sel && mask) {
  1501 	if(sel && mask) {
  1506 		sel->tags = mask;
  1502 		sel->tags = mask;
  1507 		arrange();
  1503 		arrange();
  1508 	}
  1504 	}
  1509 }
  1505 }
  1510 
  1506 
  1511 void
  1507 void
  1512 toggleview(const Arg *arg) {
  1508 toggleview(const Arg *arg) {
  1513 	uint mask = tagset[seltags] ^ (arg->ui & TAGMASK);
  1509 	unsigned int mask = tagset[seltags] ^ (arg->ui & TAGMASK);
  1514 
  1510 
  1515 	if(mask) {
  1511 	if(mask) {
  1516 		tagset[seltags] = mask;
  1512 		tagset[seltags] = mask;
  1517 		clearurgent();
  1513 		clearurgent();
  1518 		arrange();
  1514 		arrange();