implemented tagging a client
This commit is contained in:
		
							parent
							
								
									b72588746f
								
							
						
					
					
						commit
						c47da143bd
					
				
							
								
								
									
										164
									
								
								client.c
									
									
									
									
									
								
							
							
						
						
									
										164
									
								
								client.c
									
									
									
									
									
								
							| @ -11,44 +11,76 @@ | |||||||
| 
 | 
 | ||||||
| #include "dwm.h" | #include "dwm.h" | ||||||
| 
 | 
 | ||||||
| static void (*arrange)(void *) = floating; | static void (*arrange)(Arg *) = floating; | ||||||
|  | 
 | ||||||
|  | static Client * | ||||||
|  | next(Client *c) | ||||||
|  | { | ||||||
|  | 	for(c = c->next; c && !c->tags[tsel]; c = c->next); | ||||||
|  | 	return c; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static Client * | ||||||
|  | prev(Client *c) | ||||||
|  | { | ||||||
|  | 	for(c = c->prev; c && !c->tags[tsel]; c = c->prev); | ||||||
|  | 	return c; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
| max(void *aux) | max(Arg *arg) | ||||||
| { | { | ||||||
| 	if(!stack) | 	if(!csel) | ||||||
| 		return; | 		return; | ||||||
| 	stack->x = sx; | 	csel->x = sx; | ||||||
| 	stack->y = sy; | 	csel->y = sy; | ||||||
| 	stack->w = sw - 2 * stack->border; | 	csel->w = sw - 2 * csel->border; | ||||||
| 	stack->h = sh - 2 * stack->border; | 	csel->h = sh - 2 * csel->border; | ||||||
| 	craise(stack); | 	craise(csel); | ||||||
| 	resize(stack); | 	resize(csel); | ||||||
| 	discard_events(EnterWindowMask); | 	discard_events(EnterWindowMask); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
| floating(void *aux) | tag(Arg *arg) | ||||||
|  | { | ||||||
|  | 	if(!csel) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	if(arg->i == tsel) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	if(csel->tags[arg->i]) | ||||||
|  | 		csel->tags[arg->i] = NULL; /* toggle tag */ | ||||||
|  | 	else | ||||||
|  | 		csel->tags[arg->i] = tags[arg->i]; | ||||||
|  | 	arrange(NULL); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | floating(Arg *arg) | ||||||
| { | { | ||||||
| 	Client *c; | 	Client *c; | ||||||
| 
 | 
 | ||||||
| 	arrange = floating; | 	arrange = floating; | ||||||
| 	for(c = stack; c; c = c->snext) | 	if(!csel) | ||||||
|  | 		return; | ||||||
|  | 	for(c = csel; c; c = next(c)) | ||||||
| 		resize(c); | 		resize(c); | ||||||
| 	discard_events(EnterWindowMask); | 	discard_events(EnterWindowMask); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
| tiling(void *aux) | tiling(Arg *arg) | ||||||
| { | { | ||||||
| 	Client *c; | 	Client *c; | ||||||
| 	int n, cols, rows, gw, gh, i, j; | 	int n, cols, rows, gw, gh, i, j; | ||||||
|     float rt, fd; |     float rt, fd; | ||||||
| 
 | 
 | ||||||
| 	arrange = tiling; | 	arrange = tiling; | ||||||
| 	if(!clients) | 	if(!csel) | ||||||
| 		return; | 		return; | ||||||
| 	for(n = 0, c = clients; c; c = c->next, n++); | 	for(n = 0, c = csel; c; c = next(c), n++); | ||||||
| 	rt = sqrt(n); | 	rt = sqrt(n); | ||||||
| 	if(modff(rt, &fd) < 0.5) | 	if(modff(rt, &fd) < 0.5) | ||||||
| 		rows = floor(rt); | 		rows = floor(rt); | ||||||
| @ -62,7 +94,7 @@ tiling(void *aux) | |||||||
| 	gw = (sw - 2)  / cols; | 	gw = (sw - 2)  / cols; | ||||||
| 	gh = (sh - 2) / rows; | 	gh = (sh - 2) / rows; | ||||||
| 
 | 
 | ||||||
| 	for(i = j = 0, c = clients; c; c = c->next) { | 	for(i = j = 0, c = csel; c; c = next(c)) { | ||||||
| 		c->x = i * gw; | 		c->x = i * gw; | ||||||
| 		c->y = j * gh; | 		c->y = j * gh; | ||||||
| 		c->w = gw; | 		c->w = gw; | ||||||
| @ -77,28 +109,44 @@ tiling(void *aux) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
| sel(void *aux) | prevc(Arg *arg) | ||||||
| { | { | ||||||
| 	const char *arg = aux; | 	Client *c; | ||||||
| 	Client *c = NULL; |  | ||||||
| 
 | 
 | ||||||
| 	if(!arg || !stack) | 	if(!csel) | ||||||
| 		return; | 		return; | ||||||
| 	if(!strncmp(arg, "next", 5)) | 
 | ||||||
| 		c = stack->snext ? stack->snext : stack; | 	if(!(c = prev(csel))) | ||||||
| 	else if(!strncmp(arg, "prev", 5)) | 		c = prev(cend); | ||||||
| 		for(c = stack; c && c->snext; c = c->snext); | 	if(c) { | ||||||
| 	if(!c) |  | ||||||
| 		c = stack; |  | ||||||
| 		craise(c); | 		craise(c); | ||||||
| 		XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); | 		XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); | ||||||
| 		focus(c); | 		focus(c); | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
| ckill(void *aux) | nextc(Arg *arg) | ||||||
| { | { | ||||||
| 	Client *c = stack; | 	Client *c; | ||||||
|  |     | ||||||
|  | 	if(!csel) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	if(!(c = next(csel))) | ||||||
|  | 		c = next(cstart); | ||||||
|  | 
 | ||||||
|  | 	if(c) { | ||||||
|  | 		craise(c); | ||||||
|  | 		XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); | ||||||
|  | 		focus(c); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | ckill(Arg *arg) | ||||||
|  | { | ||||||
|  | 	Client *c = csel; | ||||||
| 
 | 
 | ||||||
| 	if(!c) | 	if(!c) | ||||||
| 		return; | 		return; | ||||||
| @ -208,19 +256,12 @@ lower(Client *c) | |||||||
| void | void | ||||||
| focus(Client *c) | focus(Client *c) | ||||||
| { | { | ||||||
| 	Client **l, *old; | 	if(csel && csel != c) { | ||||||
| 
 | 		XSetWindowBorder(dpy, csel->win, dc.bg); | ||||||
| 	old = stack; | 		XMapWindow(dpy, csel->title); | ||||||
| 	for(l = &stack; *l && *l != c; l = &(*l)->snext); | 		draw_client(csel); | ||||||
| 	if(*l) |  | ||||||
| 		*l = c->snext; |  | ||||||
| 	c->snext = stack; |  | ||||||
| 	stack = c; |  | ||||||
| 	if(old && old != c) { |  | ||||||
| 		XSetWindowBorder(dpy, old->win, dc.bg); |  | ||||||
| 		XMapWindow(dpy, old->title); |  | ||||||
| 		draw_client(old); |  | ||||||
| 	} | 	} | ||||||
|  | 	csel = c; | ||||||
| 	XUnmapWindow(dpy, c->title); | 	XUnmapWindow(dpy, c->title); | ||||||
| 	XSetWindowBorder(dpy, c->win, dc.fg); | 	XSetWindowBorder(dpy, c->win, dc.fg); | ||||||
| 	draw_client(c); | 	draw_client(c); | ||||||
| @ -232,7 +273,7 @@ focus(Client *c) | |||||||
| void | void | ||||||
| manage(Window w, XWindowAttributes *wa) | manage(Window w, XWindowAttributes *wa) | ||||||
| { | { | ||||||
| 	Client *c, **l; | 	Client *c; | ||||||
| 	XSetWindowAttributes twa; | 	XSetWindowAttributes twa; | ||||||
| 
 | 
 | ||||||
| 	c = emallocz(sizeof(Client)); | 	c = emallocz(sizeof(Client)); | ||||||
| @ -258,9 +299,15 @@ manage(Window w, XWindowAttributes *wa) | |||||||
| 			CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa); | 			CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa); | ||||||
| 
 | 
 | ||||||
| 	update_name(c); | 	update_name(c); | ||||||
| 	for(l=&clients; *l; l=&(*l)->next); | 
 | ||||||
| 	c->next = *l; /* *l == nil */ | 	if(!cstart) | ||||||
| 	*l = c; | 		cstart = cend = c; | ||||||
|  | 	else { | ||||||
|  | 		cend->next = c; | ||||||
|  | 		c->prev = cend; | ||||||
|  | 		cend = c; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	XSetWindowBorderWidth(dpy, c->win, 1); | 	XSetWindowBorderWidth(dpy, c->win, 1); | ||||||
| 	XMapRaised(dpy, c->win); | 	XMapRaised(dpy, c->win); | ||||||
| 	XMapRaised(dpy, c->title); | 	XMapRaised(dpy, c->title); | ||||||
| @ -373,33 +420,42 @@ dummy_error_handler(Display *dsply, XErrorEvent *err) | |||||||
| void | void | ||||||
| unmanage(Client *c) | unmanage(Client *c) | ||||||
| { | { | ||||||
| 	Client **l; |  | ||||||
| 
 |  | ||||||
| 	XGrabServer(dpy); | 	XGrabServer(dpy); | ||||||
| 	XSetErrorHandler(dummy_error_handler); | 	XSetErrorHandler(dummy_error_handler); | ||||||
| 
 | 
 | ||||||
| 	XUngrabButton(dpy, AnyButton, AnyModifier, c->win); | 	XUngrabButton(dpy, AnyButton, AnyModifier, c->win); | ||||||
| 	XDestroyWindow(dpy, c->title); | 	XDestroyWindow(dpy, c->title); | ||||||
| 
 | 
 | ||||||
| 	for(l=&clients; *l && *l != c; l=&(*l)->next); | 	if(c->prev) { | ||||||
| 	*l = c->next; | 		c->prev->next = c->next; | ||||||
| 	for(l=&stack; *l && *l != c; l=&(*l)->snext); | 		if(csel == c) | ||||||
| 	*l = c->snext; | 			csel = c->prev; | ||||||
|  | 	} | ||||||
|  | 	if(c->next) { | ||||||
|  | 		c->next->prev = c->prev; | ||||||
|  | 		if(csel == c) | ||||||
|  | 			csel = c->next; | ||||||
|  | 	} | ||||||
|  | 	if(cstart == c) | ||||||
|  | 		cstart = c->next; | ||||||
|  | 	if(cend == c) | ||||||
|  | 		cend = c->prev; | ||||||
|  | 
 | ||||||
| 	free(c); | 	free(c); | ||||||
| 
 | 
 | ||||||
| 	XFlush(dpy); | 	XFlush(dpy); | ||||||
| 	XSetErrorHandler(error_handler); | 	XSetErrorHandler(error_handler); | ||||||
| 	XUngrabServer(dpy); | 	XUngrabServer(dpy); | ||||||
| 	arrange(NULL); | 	arrange(NULL); | ||||||
| 	if(stack) | 	if(csel) | ||||||
| 		focus(stack); | 		focus(csel); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Client * | Client * | ||||||
| gettitle(Window w) | gettitle(Window w) | ||||||
| { | { | ||||||
| 	Client *c; | 	Client *c; | ||||||
| 	for(c = clients; c; c = c->next) | 	for(c = cstart; c; c = c->next) | ||||||
| 		if(c->title == w) | 		if(c->title == w) | ||||||
| 			return c; | 			return c; | ||||||
| 	return NULL; | 	return NULL; | ||||||
| @ -409,7 +465,7 @@ Client * | |||||||
| getclient(Window w) | getclient(Window w) | ||||||
| { | { | ||||||
| 	Client *c; | 	Client *c; | ||||||
| 	for(c = clients; c; c = c->next) | 	for(c = cstart; c; c = c->next) | ||||||
| 		if(c->win == w) | 		if(c->win == w) | ||||||
| 			return c; | 			return c; | ||||||
| 	return NULL; | 	return NULL; | ||||||
| @ -419,7 +475,7 @@ void | |||||||
| draw_client(Client *c) | draw_client(Client *c) | ||||||
| { | { | ||||||
| 	int i; | 	int i; | ||||||
| 	if(c == stack) | 	if(c == csel) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	dc.x = dc.y = 0; | 	dc.x = dc.y = 0; | ||||||
|  | |||||||
							
								
								
									
										27
									
								
								dev.c
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								dev.c
									
									
									
									
									
								
							| @ -20,16 +20,21 @@ const char *browse[] = { "firefox", NULL }; | |||||||
| const char *xlock[] = { "xlock", NULL }; | const char *xlock[] = { "xlock", NULL }; | ||||||
| 
 | 
 | ||||||
| static Key key[] = { | static Key key[] = { | ||||||
| 	{ Mod1Mask, XK_Return, (void (*)(void *))spawn, term }, | 	{ Mod1Mask, XK_Return, spawn, { .argv = term } }, | ||||||
| 	{ Mod1Mask, XK_w, (void (*)(void *))spawn, browse }, | 	{ Mod1Mask, XK_w, spawn, { .argv = browse } }, | ||||||
| 	{ Mod1Mask, XK_l, (void (*)(void *))spawn, xlock }, | 	{ Mod1Mask, XK_l, spawn, { .argv = xlock } }, | ||||||
| 	{ Mod1Mask, XK_k, sel, "prev" },  | 	{ Mod1Mask, XK_k, prevc, { 0 } }, | ||||||
| 	{ Mod1Mask, XK_j, sel, "next" },  | 	{ Mod1Mask, XK_j, nextc, { 0 } },  | ||||||
| 	{ Mod1Mask, XK_t, tiling, NULL },  | 	{ Mod1Mask, XK_t, tiling, { 0 } },  | ||||||
| 	{ Mod1Mask, XK_f, floating, NULL },  | 	{ Mod1Mask, XK_f, floating, { 0 } },  | ||||||
| 	{ Mod1Mask, XK_m, max, NULL },  | 	{ Mod1Mask, XK_m, max, { 0 } },  | ||||||
| 	{ Mod1Mask | ShiftMask, XK_c, ckill, NULL },  | 	{ Mod1Mask, XK_0, tag, { .i = Tscratch } },  | ||||||
| 	{ Mod1Mask | ShiftMask, XK_q, quit, NULL }, | 	{ Mod1Mask, XK_1, tag, { .i = Tdev } },  | ||||||
|  | 	{ Mod1Mask, XK_2, tag, { .i = Tirc } },  | ||||||
|  | 	{ Mod1Mask, XK_3, tag, { .i = Twww } },  | ||||||
|  | 	{ Mod1Mask, XK_4, tag, { .i = Twork } },  | ||||||
|  | 	{ Mod1Mask | ShiftMask, XK_c, ckill, { 0 } },  | ||||||
|  | 	{ Mod1Mask | ShiftMask, XK_q, quit, { 0 } }, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /********** CUSTOMIZE **********/ | /********** CUSTOMIZE **********/ | ||||||
| @ -60,7 +65,7 @@ keypress(XEvent *e) | |||||||
| 	for(i = 0; i < len; i++) | 	for(i = 0; i < len; i++) | ||||||
| 		if((keysym == key[i].keysym) && (key[i].mod == ev->state)) { | 		if((keysym == key[i].keysym) && (key[i].mod == ev->state)) { | ||||||
| 			if(key[i].func) | 			if(key[i].func) | ||||||
| 				key[i].func(key[i].aux); | 				key[i].func(&key[i].arg); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										30
									
								
								dwm.h
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								dwm.h
									
									
									
									
									
								
							| @ -22,6 +22,12 @@ typedef struct DC DC; | |||||||
| typedef struct Client Client; | typedef struct Client Client; | ||||||
| typedef struct Fnt Fnt; | typedef struct Fnt Fnt; | ||||||
| typedef struct Key Key; | typedef struct Key Key; | ||||||
|  | typedef union Arg Arg; | ||||||
|  | 
 | ||||||
|  | union Arg { | ||||||
|  | 	const char **argv; | ||||||
|  | 	int i; | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| /* atoms */ | /* atoms */ | ||||||
| enum { WMProtocols, WMDelete, WMLast }; | enum { WMProtocols, WMDelete, WMLast }; | ||||||
| @ -62,14 +68,14 @@ struct Client { | |||||||
| 	Window trans; | 	Window trans; | ||||||
| 	Window title; | 	Window title; | ||||||
| 	Client *next; | 	Client *next; | ||||||
| 	Client *snext; | 	Client *prev; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Key { | struct Key { | ||||||
| 	unsigned long mod; | 	unsigned long mod; | ||||||
| 	KeySym keysym; | 	KeySym keysym; | ||||||
| 	void (*func)(void *aux); | 	void (*func)(Arg *arg); | ||||||
| 	void *aux; | 	Arg arg; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| extern Display *dpy; | extern Display *dpy; | ||||||
| @ -83,7 +89,7 @@ extern int tsel, screen, sx, sy, sw, sh, th; | |||||||
| extern char stext[1024], *tags[TLast]; | extern char stext[1024], *tags[TLast]; | ||||||
| 
 | 
 | ||||||
| extern DC dc; | extern DC dc; | ||||||
| extern Client *clients, *stack; | extern Client *cstart, *cend, *csel; | ||||||
| 
 | 
 | ||||||
| /* client.c */ | /* client.c */ | ||||||
| extern void manage(Window w, XWindowAttributes *wa); | extern void manage(Window w, XWindowAttributes *wa); | ||||||
| @ -97,11 +103,13 @@ extern void update_size(Client *c); | |||||||
| extern Client *gettitle(Window w); | extern Client *gettitle(Window w); | ||||||
| extern void craise(Client *c); | extern void craise(Client *c); | ||||||
| extern void lower(Client *c); | extern void lower(Client *c); | ||||||
| extern void ckill(void *aux); | extern void ckill(Arg *arg); | ||||||
| extern void sel(void *aux); | extern void nextc(Arg *arg); | ||||||
| extern void max(void *aux); | extern void prevc(Arg *arg); | ||||||
| extern void floating(void *aux); | extern void max(Arg *arg); | ||||||
| extern void tiling(void *aux); | extern void floating(Arg *arg); | ||||||
|  | extern void tiling(Arg *arg); | ||||||
|  | void tag(Arg *arg); | ||||||
| extern void gravitate(Client *c, Bool invert); | extern void gravitate(Client *c, Bool invert); | ||||||
| 
 | 
 | ||||||
| /* draw.c */ | /* draw.c */ | ||||||
| @ -125,7 +133,7 @@ extern void mmove(Client *c); | |||||||
| extern int error_handler(Display *dsply, XErrorEvent *e); | extern int error_handler(Display *dsply, XErrorEvent *e); | ||||||
| extern void send_message(Window w, Atom a, long value); | extern void send_message(Window w, Atom a, long value); | ||||||
| extern int win_proto(Window w); | extern int win_proto(Window w); | ||||||
| extern void quit(void *aux); | extern void quit(Arg *arg); | ||||||
| 
 | 
 | ||||||
| /* util.c */ | /* util.c */ | ||||||
| extern void error(const char *errstr, ...); | extern void error(const char *errstr, ...); | ||||||
| @ -133,5 +141,5 @@ extern void *emallocz(unsigned int size); | |||||||
| extern void *emalloc(unsigned int size); | extern void *emalloc(unsigned int size); | ||||||
| extern void *erealloc(void *ptr, unsigned int size); | extern void *erealloc(void *ptr, unsigned int size); | ||||||
| extern char *estrdup(const char *str); | extern char *estrdup(const char *str); | ||||||
| extern void spawn(char *argv[]); | extern void spawn(Arg *arg); | ||||||
| extern void swap(void **p1, void **p2); | extern void swap(void **p1, void **p2); | ||||||
|  | |||||||
							
								
								
									
										11
									
								
								main.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								main.c
									
									
									
									
									
								
							| @ -38,8 +38,9 @@ int tsel = Tdev; /* default tag */ | |||||||
| int screen, sx, sy, sw, sh, th; | int screen, sx, sy, sw, sh, th; | ||||||
| 
 | 
 | ||||||
| DC dc = {0}; | DC dc = {0}; | ||||||
| Client *clients = NULL; | Client *cstart = NULL; | ||||||
| Client *stack = NULL; | Client *cend = NULL; | ||||||
|  | Client *csel = NULL; | ||||||
| 
 | 
 | ||||||
| static Bool other_wm_running; | static Bool other_wm_running; | ||||||
| static const char version[] = | static const char version[] = | ||||||
| @ -168,13 +169,13 @@ startup_error_handler(Display *dpy, XErrorEvent *error) | |||||||
| static void | static void | ||||||
| cleanup() | cleanup() | ||||||
| { | { | ||||||
| 	while(clients) | 	while(csel) | ||||||
| 		unmanage(clients); | 		unmanage(csel); | ||||||
| 	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); | 	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
| quit(void *aux) | quit(Arg *arg) | ||||||
| { | { | ||||||
| 	running = False; | 	running = False; | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user