client.c
changeset 49 466591c2f967
parent 46 58307ad56ec1
child 50 148f25ed0ad7
equal deleted inserted replaced
48:ceff29af8c7b 49:466591c2f967
     9 #include <X11/Xatom.h>
     9 #include <X11/Xatom.h>
    10 #include <X11/Xutil.h>
    10 #include <X11/Xutil.h>
    11 
    11 
    12 #include "dwm.h"
    12 #include "dwm.h"
    13 
    13 
    14 static void (*arrange)(void *) = floating;
    14 static void (*arrange)(Arg *) = floating;
    15 
    15 
    16 void
    16 static Client *
    17 max(void *aux)
    17 next(Client *c)
    18 {
    18 {
    19 	if(!stack)
    19 	for(c = c->next; c && !c->tags[tsel]; c = c->next);
    20 		return;
    20 	return c;
    21 	stack->x = sx;
    21 }
    22 	stack->y = sy;
    22 
    23 	stack->w = sw - 2 * stack->border;
    23 static Client *
    24 	stack->h = sh - 2 * stack->border;
    24 prev(Client *c)
    25 	craise(stack);
    25 {
    26 	resize(stack);
    26 	for(c = c->prev; c && !c->tags[tsel]; c = c->prev);
       
    27 	return c;
       
    28 }
       
    29 
       
    30 void
       
    31 max(Arg *arg)
       
    32 {
       
    33 	if(!csel)
       
    34 		return;
       
    35 	csel->x = sx;
       
    36 	csel->y = sy;
       
    37 	csel->w = sw - 2 * csel->border;
       
    38 	csel->h = sh - 2 * csel->border;
       
    39 	craise(csel);
       
    40 	resize(csel);
    27 	discard_events(EnterWindowMask);
    41 	discard_events(EnterWindowMask);
    28 }
    42 }
    29 
    43 
    30 void
    44 void
    31 floating(void *aux)
    45 tag(Arg *arg)
       
    46 {
       
    47 	if(!csel)
       
    48 		return;
       
    49 
       
    50 	if(arg->i == tsel)
       
    51 		return;
       
    52 
       
    53 	if(csel->tags[arg->i])
       
    54 		csel->tags[arg->i] = NULL; /* toggle tag */
       
    55 	else
       
    56 		csel->tags[arg->i] = tags[arg->i];
       
    57 	arrange(NULL);
       
    58 }
       
    59 
       
    60 void
       
    61 floating(Arg *arg)
    32 {
    62 {
    33 	Client *c;
    63 	Client *c;
    34 
    64 
    35 	arrange = floating;
    65 	arrange = floating;
    36 	for(c = stack; c; c = c->snext)
    66 	if(!csel)
       
    67 		return;
       
    68 	for(c = csel; c; c = next(c))
    37 		resize(c);
    69 		resize(c);
    38 	discard_events(EnterWindowMask);
    70 	discard_events(EnterWindowMask);
    39 }
    71 }
    40 
    72 
    41 void
    73 void
    42 tiling(void *aux)
    74 tiling(Arg *arg)
    43 {
    75 {
    44 	Client *c;
    76 	Client *c;
    45 	int n, cols, rows, gw, gh, i, j;
    77 	int n, cols, rows, gw, gh, i, j;
    46     float rt, fd;
    78     float rt, fd;
    47 
    79 
    48 	arrange = tiling;
    80 	arrange = tiling;
    49 	if(!clients)
    81 	if(!csel)
    50 		return;
    82 		return;
    51 	for(n = 0, c = clients; c; c = c->next, n++);
    83 	for(n = 0, c = csel; c; c = next(c), n++);
    52 	rt = sqrt(n);
    84 	rt = sqrt(n);
    53 	if(modff(rt, &fd) < 0.5)
    85 	if(modff(rt, &fd) < 0.5)
    54 		rows = floor(rt);
    86 		rows = floor(rt);
    55 	else
    87 	else
    56 		rows = ceil(rt);
    88 		rows = ceil(rt);
    60 		cols = rows;
    92 		cols = rows;
    61 
    93 
    62 	gw = (sw - 2)  / cols;
    94 	gw = (sw - 2)  / cols;
    63 	gh = (sh - 2) / rows;
    95 	gh = (sh - 2) / rows;
    64 
    96 
    65 	for(i = j = 0, c = clients; c; c = c->next) {
    97 	for(i = j = 0, c = csel; c; c = next(c)) {
    66 		c->x = i * gw;
    98 		c->x = i * gw;
    67 		c->y = j * gh;
    99 		c->y = j * gh;
    68 		c->w = gw;
   100 		c->w = gw;
    69 		c->h = gh;
   101 		c->h = gh;
    70 		resize(c);
   102 		resize(c);
    75 	}
   107 	}
    76 	discard_events(EnterWindowMask);
   108 	discard_events(EnterWindowMask);
    77 }
   109 }
    78 
   110 
    79 void
   111 void
    80 sel(void *aux)
   112 prevc(Arg *arg)
    81 {
   113 {
    82 	const char *arg = aux;
   114 	Client *c;
    83 	Client *c = NULL;
   115 
    84 
   116 	if(!csel)
    85 	if(!arg || !stack)
   117 		return;
    86 		return;
   118 
    87 	if(!strncmp(arg, "next", 5))
   119 	if(!(c = prev(csel)))
    88 		c = stack->snext ? stack->snext : stack;
   120 		c = prev(cend);
    89 	else if(!strncmp(arg, "prev", 5))
   121 	if(c) {
    90 		for(c = stack; c && c->snext; c = c->snext);
   122 		craise(c);
    91 	if(!c)
   123 		XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2);
    92 		c = stack;
   124 		focus(c);
    93 	craise(c);
   125 	}
    94 	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2);
   126 }
    95 	focus(c);
   127 
    96 }
   128 void
    97 
   129 nextc(Arg *arg)
    98 void
   130 {
    99 ckill(void *aux)
   131 	Client *c;
   100 {
   132    
   101 	Client *c = stack;
   133 	if(!csel)
       
   134 		return;
       
   135 
       
   136 	if(!(c = next(csel)))
       
   137 		c = next(cstart);
       
   138 
       
   139 	if(c) {
       
   140 		craise(c);
       
   141 		XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2);
       
   142 		focus(c);
       
   143 	}
       
   144 }
       
   145 
       
   146 void
       
   147 ckill(Arg *arg)
       
   148 {
       
   149 	Client *c = csel;
   102 
   150 
   103 	if(!c)
   151 	if(!c)
   104 		return;
   152 		return;
   105 	if(c->proto & WM_PROTOCOL_DELWIN)
   153 	if(c->proto & WM_PROTOCOL_DELWIN)
   106 		send_message(c->win, wm_atom[WMProtocols], wm_atom[WMDelete]);
   154 		send_message(c->win, wm_atom[WMProtocols], wm_atom[WMDelete]);
   206 }
   254 }
   207 
   255 
   208 void
   256 void
   209 focus(Client *c)
   257 focus(Client *c)
   210 {
   258 {
   211 	Client **l, *old;
   259 	if(csel && csel != c) {
   212 
   260 		XSetWindowBorder(dpy, csel->win, dc.bg);
   213 	old = stack;
   261 		XMapWindow(dpy, csel->title);
   214 	for(l = &stack; *l && *l != c; l = &(*l)->snext);
   262 		draw_client(csel);
   215 	if(*l)
   263 	}
   216 		*l = c->snext;
   264 	csel = c;
   217 	c->snext = stack;
       
   218 	stack = c;
       
   219 	if(old && old != c) {
       
   220 		XSetWindowBorder(dpy, old->win, dc.bg);
       
   221 		XMapWindow(dpy, old->title);
       
   222 		draw_client(old);
       
   223 	}
       
   224 	XUnmapWindow(dpy, c->title);
   265 	XUnmapWindow(dpy, c->title);
   225 	XSetWindowBorder(dpy, c->win, dc.fg);
   266 	XSetWindowBorder(dpy, c->win, dc.fg);
   226 	draw_client(c);
   267 	draw_client(c);
   227 	XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
   268 	XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
   228 	XFlush(dpy);
   269 	XFlush(dpy);
   230 }
   271 }
   231 
   272 
   232 void
   273 void
   233 manage(Window w, XWindowAttributes *wa)
   274 manage(Window w, XWindowAttributes *wa)
   234 {
   275 {
   235 	Client *c, **l;
   276 	Client *c;
   236 	XSetWindowAttributes twa;
   277 	XSetWindowAttributes twa;
   237 
   278 
   238 	c = emallocz(sizeof(Client));
   279 	c = emallocz(sizeof(Client));
   239 	c->win = w;
   280 	c->win = w;
   240 	c->tx = c->x = wa->x;
   281 	c->tx = c->x = wa->x;
   256 			0, DefaultDepth(dpy, screen), CopyFromParent,
   297 			0, DefaultDepth(dpy, screen), CopyFromParent,
   257 			DefaultVisual(dpy, screen),
   298 			DefaultVisual(dpy, screen),
   258 			CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
   299 			CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
   259 
   300 
   260 	update_name(c);
   301 	update_name(c);
   261 	for(l=&clients; *l; l=&(*l)->next);
   302 
   262 	c->next = *l; /* *l == nil */
   303 	if(!cstart)
   263 	*l = c;
   304 		cstart = cend = c;
       
   305 	else {
       
   306 		cend->next = c;
       
   307 		c->prev = cend;
       
   308 		cend = c;
       
   309 	}
       
   310 
   264 	XSetWindowBorderWidth(dpy, c->win, 1);
   311 	XSetWindowBorderWidth(dpy, c->win, 1);
   265 	XMapRaised(dpy, c->win);
   312 	XMapRaised(dpy, c->win);
   266 	XMapRaised(dpy, c->title);
   313 	XMapRaised(dpy, c->title);
   267 	XGrabButton(dpy, Button1, Mod1Mask, c->win, False, ButtonPressMask,
   314 	XGrabButton(dpy, Button1, Mod1Mask, c->win, False, ButtonPressMask,
   268 			GrabModeAsync, GrabModeSync, None, None);
   315 			GrabModeAsync, GrabModeSync, None, None);
   371 }
   418 }
   372 
   419 
   373 void
   420 void
   374 unmanage(Client *c)
   421 unmanage(Client *c)
   375 {
   422 {
   376 	Client **l;
       
   377 
       
   378 	XGrabServer(dpy);
   423 	XGrabServer(dpy);
   379 	XSetErrorHandler(dummy_error_handler);
   424 	XSetErrorHandler(dummy_error_handler);
   380 
   425 
   381 	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
   426 	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
   382 	XDestroyWindow(dpy, c->title);
   427 	XDestroyWindow(dpy, c->title);
   383 
   428 
   384 	for(l=&clients; *l && *l != c; l=&(*l)->next);
   429 	if(c->prev) {
   385 	*l = c->next;
   430 		c->prev->next = c->next;
   386 	for(l=&stack; *l && *l != c; l=&(*l)->snext);
   431 		if(csel == c)
   387 	*l = c->snext;
   432 			csel = c->prev;
       
   433 	}
       
   434 	if(c->next) {
       
   435 		c->next->prev = c->prev;
       
   436 		if(csel == c)
       
   437 			csel = c->next;
       
   438 	}
       
   439 	if(cstart == c)
       
   440 		cstart = c->next;
       
   441 	if(cend == c)
       
   442 		cend = c->prev;
       
   443 
   388 	free(c);
   444 	free(c);
   389 
   445 
   390 	XFlush(dpy);
   446 	XFlush(dpy);
   391 	XSetErrorHandler(error_handler);
   447 	XSetErrorHandler(error_handler);
   392 	XUngrabServer(dpy);
   448 	XUngrabServer(dpy);
   393 	arrange(NULL);
   449 	arrange(NULL);
   394 	if(stack)
   450 	if(csel)
   395 		focus(stack);
   451 		focus(csel);
   396 }
   452 }
   397 
   453 
   398 Client *
   454 Client *
   399 gettitle(Window w)
   455 gettitle(Window w)
   400 {
   456 {
   401 	Client *c;
   457 	Client *c;
   402 	for(c = clients; c; c = c->next)
   458 	for(c = cstart; c; c = c->next)
   403 		if(c->title == w)
   459 		if(c->title == w)
   404 			return c;
   460 			return c;
   405 	return NULL;
   461 	return NULL;
   406 }
   462 }
   407 
   463 
   408 Client *
   464 Client *
   409 getclient(Window w)
   465 getclient(Window w)
   410 {
   466 {
   411 	Client *c;
   467 	Client *c;
   412 	for(c = clients; c; c = c->next)
   468 	for(c = cstart; c; c = c->next)
   413 		if(c->win == w)
   469 		if(c->win == w)
   414 			return c;
   470 			return c;
   415 	return NULL;
   471 	return NULL;
   416 }
   472 }
   417 
   473 
   418 void
   474 void
   419 draw_client(Client *c)
   475 draw_client(Client *c)
   420 {
   476 {
   421 	int i;
   477 	int i;
   422 	if(c == stack)
   478 	if(c == csel)
   423 		return;
   479 		return;
   424 
   480 
   425 	dc.x = dc.y = 0;
   481 	dc.x = dc.y = 0;
   426 	dc.h = c->th;
   482 	dc.h = c->th;
   427 
   483