aewl

changeset 49:466591c2f967

implemented tagging a client
author Anselm R. Garbe <garbeam@wmii.de>
date Thu, 13 Jul 2006 17:09:35 +0200
parents ceff29af8c7b
children 148f25ed0ad7
files client.c dev.c dwm.h main.c util.c
diffstat 5 files changed, 156 insertions(+), 85 deletions(-) [+]
line diff
     1.1 --- a/client.c	Thu Jul 13 14:33:22 2006 +0200
     1.2 +++ b/client.c	Thu Jul 13 17:09:35 2006 +0200
     1.3 @@ -11,44 +11,76 @@
     1.4  
     1.5  #include "dwm.h"
     1.6  
     1.7 -static void (*arrange)(void *) = floating;
     1.8 +static void (*arrange)(Arg *) = floating;
     1.9 +
    1.10 +static Client *
    1.11 +next(Client *c)
    1.12 +{
    1.13 +	for(c = c->next; c && !c->tags[tsel]; c = c->next);
    1.14 +	return c;
    1.15 +}
    1.16 +
    1.17 +static Client *
    1.18 +prev(Client *c)
    1.19 +{
    1.20 +	for(c = c->prev; c && !c->tags[tsel]; c = c->prev);
    1.21 +	return c;
    1.22 +}
    1.23  
    1.24  void
    1.25 -max(void *aux)
    1.26 +max(Arg *arg)
    1.27  {
    1.28 -	if(!stack)
    1.29 +	if(!csel)
    1.30  		return;
    1.31 -	stack->x = sx;
    1.32 -	stack->y = sy;
    1.33 -	stack->w = sw - 2 * stack->border;
    1.34 -	stack->h = sh - 2 * stack->border;
    1.35 -	craise(stack);
    1.36 -	resize(stack);
    1.37 +	csel->x = sx;
    1.38 +	csel->y = sy;
    1.39 +	csel->w = sw - 2 * csel->border;
    1.40 +	csel->h = sh - 2 * csel->border;
    1.41 +	craise(csel);
    1.42 +	resize(csel);
    1.43  	discard_events(EnterWindowMask);
    1.44  }
    1.45  
    1.46  void
    1.47 -floating(void *aux)
    1.48 +tag(Arg *arg)
    1.49 +{
    1.50 +	if(!csel)
    1.51 +		return;
    1.52 +
    1.53 +	if(arg->i == tsel)
    1.54 +		return;
    1.55 +
    1.56 +	if(csel->tags[arg->i])
    1.57 +		csel->tags[arg->i] = NULL; /* toggle tag */
    1.58 +	else
    1.59 +		csel->tags[arg->i] = tags[arg->i];
    1.60 +	arrange(NULL);
    1.61 +}
    1.62 +
    1.63 +void
    1.64 +floating(Arg *arg)
    1.65  {
    1.66  	Client *c;
    1.67  
    1.68  	arrange = floating;
    1.69 -	for(c = stack; c; c = c->snext)
    1.70 +	if(!csel)
    1.71 +		return;
    1.72 +	for(c = csel; c; c = next(c))
    1.73  		resize(c);
    1.74  	discard_events(EnterWindowMask);
    1.75  }
    1.76  
    1.77  void
    1.78 -tiling(void *aux)
    1.79 +tiling(Arg *arg)
    1.80  {
    1.81  	Client *c;
    1.82  	int n, cols, rows, gw, gh, i, j;
    1.83      float rt, fd;
    1.84  
    1.85  	arrange = tiling;
    1.86 -	if(!clients)
    1.87 +	if(!csel)
    1.88  		return;
    1.89 -	for(n = 0, c = clients; c; c = c->next, n++);
    1.90 +	for(n = 0, c = csel; c; c = next(c), n++);
    1.91  	rt = sqrt(n);
    1.92  	if(modff(rt, &fd) < 0.5)
    1.93  		rows = floor(rt);
    1.94 @@ -62,7 +94,7 @@
    1.95  	gw = (sw - 2)  / cols;
    1.96  	gh = (sh - 2) / rows;
    1.97  
    1.98 -	for(i = j = 0, c = clients; c; c = c->next) {
    1.99 +	for(i = j = 0, c = csel; c; c = next(c)) {
   1.100  		c->x = i * gw;
   1.101  		c->y = j * gh;
   1.102  		c->w = gw;
   1.103 @@ -77,28 +109,44 @@
   1.104  }
   1.105  
   1.106  void
   1.107 -sel(void *aux)
   1.108 +prevc(Arg *arg)
   1.109  {
   1.110 -	const char *arg = aux;
   1.111 -	Client *c = NULL;
   1.112 +	Client *c;
   1.113  
   1.114 -	if(!arg || !stack)
   1.115 +	if(!csel)
   1.116  		return;
   1.117 -	if(!strncmp(arg, "next", 5))
   1.118 -		c = stack->snext ? stack->snext : stack;
   1.119 -	else if(!strncmp(arg, "prev", 5))
   1.120 -		for(c = stack; c && c->snext; c = c->snext);
   1.121 -	if(!c)
   1.122 -		c = stack;
   1.123 -	craise(c);
   1.124 -	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2);
   1.125 -	focus(c);
   1.126 +
   1.127 +	if(!(c = prev(csel)))
   1.128 +		c = prev(cend);
   1.129 +	if(c) {
   1.130 +		craise(c);
   1.131 +		XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2);
   1.132 +		focus(c);
   1.133 +	}
   1.134  }
   1.135  
   1.136  void
   1.137 -ckill(void *aux)
   1.138 +nextc(Arg *arg)
   1.139  {
   1.140 -	Client *c = stack;
   1.141 +	Client *c;
   1.142 +   
   1.143 +	if(!csel)
   1.144 +		return;
   1.145 +
   1.146 +	if(!(c = next(csel)))
   1.147 +		c = next(cstart);
   1.148 +
   1.149 +	if(c) {
   1.150 +		craise(c);
   1.151 +		XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2);
   1.152 +		focus(c);
   1.153 +	}
   1.154 +}
   1.155 +
   1.156 +void
   1.157 +ckill(Arg *arg)
   1.158 +{
   1.159 +	Client *c = csel;
   1.160  
   1.161  	if(!c)
   1.162  		return;
   1.163 @@ -208,19 +256,12 @@
   1.164  void
   1.165  focus(Client *c)
   1.166  {
   1.167 -	Client **l, *old;
   1.168 -
   1.169 -	old = stack;
   1.170 -	for(l = &stack; *l && *l != c; l = &(*l)->snext);
   1.171 -	if(*l)
   1.172 -		*l = c->snext;
   1.173 -	c->snext = stack;
   1.174 -	stack = c;
   1.175 -	if(old && old != c) {
   1.176 -		XSetWindowBorder(dpy, old->win, dc.bg);
   1.177 -		XMapWindow(dpy, old->title);
   1.178 -		draw_client(old);
   1.179 +	if(csel && csel != c) {
   1.180 +		XSetWindowBorder(dpy, csel->win, dc.bg);
   1.181 +		XMapWindow(dpy, csel->title);
   1.182 +		draw_client(csel);
   1.183  	}
   1.184 +	csel = c;
   1.185  	XUnmapWindow(dpy, c->title);
   1.186  	XSetWindowBorder(dpy, c->win, dc.fg);
   1.187  	draw_client(c);
   1.188 @@ -232,7 +273,7 @@
   1.189  void
   1.190  manage(Window w, XWindowAttributes *wa)
   1.191  {
   1.192 -	Client *c, **l;
   1.193 +	Client *c;
   1.194  	XSetWindowAttributes twa;
   1.195  
   1.196  	c = emallocz(sizeof(Client));
   1.197 @@ -258,9 +299,15 @@
   1.198  			CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
   1.199  
   1.200  	update_name(c);
   1.201 -	for(l=&clients; *l; l=&(*l)->next);
   1.202 -	c->next = *l; /* *l == nil */
   1.203 -	*l = c;
   1.204 +
   1.205 +	if(!cstart)
   1.206 +		cstart = cend = c;
   1.207 +	else {
   1.208 +		cend->next = c;
   1.209 +		c->prev = cend;
   1.210 +		cend = c;
   1.211 +	}
   1.212 +
   1.213  	XSetWindowBorderWidth(dpy, c->win, 1);
   1.214  	XMapRaised(dpy, c->win);
   1.215  	XMapRaised(dpy, c->title);
   1.216 @@ -373,33 +420,42 @@
   1.217  void
   1.218  unmanage(Client *c)
   1.219  {
   1.220 -	Client **l;
   1.221 -
   1.222  	XGrabServer(dpy);
   1.223  	XSetErrorHandler(dummy_error_handler);
   1.224  
   1.225  	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
   1.226  	XDestroyWindow(dpy, c->title);
   1.227  
   1.228 -	for(l=&clients; *l && *l != c; l=&(*l)->next);
   1.229 -	*l = c->next;
   1.230 -	for(l=&stack; *l && *l != c; l=&(*l)->snext);
   1.231 -	*l = c->snext;
   1.232 +	if(c->prev) {
   1.233 +		c->prev->next = c->next;
   1.234 +		if(csel == c)
   1.235 +			csel = c->prev;
   1.236 +	}
   1.237 +	if(c->next) {
   1.238 +		c->next->prev = c->prev;
   1.239 +		if(csel == c)
   1.240 +			csel = c->next;
   1.241 +	}
   1.242 +	if(cstart == c)
   1.243 +		cstart = c->next;
   1.244 +	if(cend == c)
   1.245 +		cend = c->prev;
   1.246 +
   1.247  	free(c);
   1.248  
   1.249  	XFlush(dpy);
   1.250  	XSetErrorHandler(error_handler);
   1.251  	XUngrabServer(dpy);
   1.252  	arrange(NULL);
   1.253 -	if(stack)
   1.254 -		focus(stack);
   1.255 +	if(csel)
   1.256 +		focus(csel);
   1.257  }
   1.258  
   1.259  Client *
   1.260  gettitle(Window w)
   1.261  {
   1.262  	Client *c;
   1.263 -	for(c = clients; c; c = c->next)
   1.264 +	for(c = cstart; c; c = c->next)
   1.265  		if(c->title == w)
   1.266  			return c;
   1.267  	return NULL;
   1.268 @@ -409,7 +465,7 @@
   1.269  getclient(Window w)
   1.270  {
   1.271  	Client *c;
   1.272 -	for(c = clients; c; c = c->next)
   1.273 +	for(c = cstart; c; c = c->next)
   1.274  		if(c->win == w)
   1.275  			return c;
   1.276  	return NULL;
   1.277 @@ -419,7 +475,7 @@
   1.278  draw_client(Client *c)
   1.279  {
   1.280  	int i;
   1.281 -	if(c == stack)
   1.282 +	if(c == csel)
   1.283  		return;
   1.284  
   1.285  	dc.x = dc.y = 0;
     2.1 --- a/dev.c	Thu Jul 13 14:33:22 2006 +0200
     2.2 +++ b/dev.c	Thu Jul 13 17:09:35 2006 +0200
     2.3 @@ -20,16 +20,21 @@
     2.4  const char *xlock[] = { "xlock", NULL };
     2.5  
     2.6  static Key key[] = {
     2.7 -	{ Mod1Mask, XK_Return, (void (*)(void *))spawn, term },
     2.8 -	{ Mod1Mask, XK_w, (void (*)(void *))spawn, browse },
     2.9 -	{ Mod1Mask, XK_l, (void (*)(void *))spawn, xlock },
    2.10 -	{ Mod1Mask, XK_k, sel, "prev" }, 
    2.11 -	{ Mod1Mask, XK_j, sel, "next" }, 
    2.12 -	{ Mod1Mask, XK_t, tiling, NULL }, 
    2.13 -	{ Mod1Mask, XK_f, floating, NULL }, 
    2.14 -	{ Mod1Mask, XK_m, max, NULL }, 
    2.15 -	{ Mod1Mask | ShiftMask, XK_c, ckill, NULL }, 
    2.16 -	{ Mod1Mask | ShiftMask, XK_q, quit, NULL },
    2.17 +	{ Mod1Mask, XK_Return, spawn, { .argv = term } },
    2.18 +	{ Mod1Mask, XK_w, spawn, { .argv = browse } },
    2.19 +	{ Mod1Mask, XK_l, spawn, { .argv = xlock } },
    2.20 +	{ Mod1Mask, XK_k, prevc, { 0 } },
    2.21 +	{ Mod1Mask, XK_j, nextc, { 0 } }, 
    2.22 +	{ Mod1Mask, XK_t, tiling, { 0 } }, 
    2.23 +	{ Mod1Mask, XK_f, floating, { 0 } }, 
    2.24 +	{ Mod1Mask, XK_m, max, { 0 } }, 
    2.25 +	{ Mod1Mask, XK_0, tag, { .i = Tscratch } }, 
    2.26 +	{ Mod1Mask, XK_1, tag, { .i = Tdev } }, 
    2.27 +	{ Mod1Mask, XK_2, tag, { .i = Tirc } }, 
    2.28 +	{ Mod1Mask, XK_3, tag, { .i = Twww } }, 
    2.29 +	{ Mod1Mask, XK_4, tag, { .i = Twork } }, 
    2.30 +	{ Mod1Mask | ShiftMask, XK_c, ckill, { 0 } }, 
    2.31 +	{ Mod1Mask | ShiftMask, XK_q, quit, { 0 } },
    2.32  };
    2.33  
    2.34  /********** CUSTOMIZE **********/
    2.35 @@ -60,7 +65,7 @@
    2.36  	for(i = 0; i < len; i++)
    2.37  		if((keysym == key[i].keysym) && (key[i].mod == ev->state)) {
    2.38  			if(key[i].func)
    2.39 -				key[i].func(key[i].aux);
    2.40 +				key[i].func(&key[i].arg);
    2.41  			return;
    2.42  		}
    2.43  }
     3.1 --- a/dwm.h	Thu Jul 13 14:33:22 2006 +0200
     3.2 +++ b/dwm.h	Thu Jul 13 17:09:35 2006 +0200
     3.3 @@ -22,6 +22,12 @@
     3.4  typedef struct Client Client;
     3.5  typedef struct Fnt Fnt;
     3.6  typedef struct Key Key;
     3.7 +typedef union Arg Arg;
     3.8 +
     3.9 +union Arg {
    3.10 +	const char **argv;
    3.11 +	int i;
    3.12 +};
    3.13  
    3.14  /* atoms */
    3.15  enum { WMProtocols, WMDelete, WMLast };
    3.16 @@ -62,14 +68,14 @@
    3.17  	Window trans;
    3.18  	Window title;
    3.19  	Client *next;
    3.20 -	Client *snext;
    3.21 +	Client *prev;
    3.22  };
    3.23  
    3.24  struct Key {
    3.25  	unsigned long mod;
    3.26  	KeySym keysym;
    3.27 -	void (*func)(void *aux);
    3.28 -	void *aux;
    3.29 +	void (*func)(Arg *arg);
    3.30 +	Arg arg;
    3.31  };
    3.32  
    3.33  extern Display *dpy;
    3.34 @@ -83,7 +89,7 @@
    3.35  extern char stext[1024], *tags[TLast];
    3.36  
    3.37  extern DC dc;
    3.38 -extern Client *clients, *stack;
    3.39 +extern Client *cstart, *cend, *csel;
    3.40  
    3.41  /* client.c */
    3.42  extern void manage(Window w, XWindowAttributes *wa);
    3.43 @@ -97,11 +103,13 @@
    3.44  extern Client *gettitle(Window w);
    3.45  extern void craise(Client *c);
    3.46  extern void lower(Client *c);
    3.47 -extern void ckill(void *aux);
    3.48 -extern void sel(void *aux);
    3.49 -extern void max(void *aux);
    3.50 -extern void floating(void *aux);
    3.51 -extern void tiling(void *aux);
    3.52 +extern void ckill(Arg *arg);
    3.53 +extern void nextc(Arg *arg);
    3.54 +extern void prevc(Arg *arg);
    3.55 +extern void max(Arg *arg);
    3.56 +extern void floating(Arg *arg);
    3.57 +extern void tiling(Arg *arg);
    3.58 +void tag(Arg *arg);
    3.59  extern void gravitate(Client *c, Bool invert);
    3.60  
    3.61  /* draw.c */
    3.62 @@ -125,7 +133,7 @@
    3.63  extern int error_handler(Display *dsply, XErrorEvent *e);
    3.64  extern void send_message(Window w, Atom a, long value);
    3.65  extern int win_proto(Window w);
    3.66 -extern void quit(void *aux);
    3.67 +extern void quit(Arg *arg);
    3.68  
    3.69  /* util.c */
    3.70  extern void error(const char *errstr, ...);
    3.71 @@ -133,5 +141,5 @@
    3.72  extern void *emalloc(unsigned int size);
    3.73  extern void *erealloc(void *ptr, unsigned int size);
    3.74  extern char *estrdup(const char *str);
    3.75 -extern void spawn(char *argv[]);
    3.76 +extern void spawn(Arg *arg);
    3.77  extern void swap(void **p1, void **p2);
     4.1 --- a/main.c	Thu Jul 13 14:33:22 2006 +0200
     4.2 +++ b/main.c	Thu Jul 13 17:09:35 2006 +0200
     4.3 @@ -38,8 +38,9 @@
     4.4  int screen, sx, sy, sw, sh, th;
     4.5  
     4.6  DC dc = {0};
     4.7 -Client *clients = NULL;
     4.8 -Client *stack = NULL;
     4.9 +Client *cstart = NULL;
    4.10 +Client *cend = NULL;
    4.11 +Client *csel = NULL;
    4.12  
    4.13  static Bool other_wm_running;
    4.14  static const char version[] =
    4.15 @@ -168,13 +169,13 @@
    4.16  static void
    4.17  cleanup()
    4.18  {
    4.19 -	while(clients)
    4.20 -		unmanage(clients);
    4.21 +	while(csel)
    4.22 +		unmanage(csel);
    4.23  	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
    4.24  }
    4.25  
    4.26  void
    4.27 -quit(void *aux)
    4.28 +quit(Arg *arg)
    4.29  {
    4.30  	running = False;
    4.31  }
     5.1 --- a/util.c	Thu Jul 13 14:33:22 2006 +0200
     5.2 +++ b/util.c	Thu Jul 13 17:09:35 2006 +0200
     5.3 @@ -75,8 +75,9 @@
     5.4  }
     5.5  
     5.6  void
     5.7 -spawn(char *argv[])
     5.8 +spawn(Arg *arg)
     5.9  {
    5.10 +	char **argv = (char **)arg->argv;
    5.11  	if(!argv || !argv[0])
    5.12  		return;
    5.13  	if(fork() == 0) {