2wm

dual window manager prototype (minimalist dwm with no tags, just one view)
git clone git://git.suckless.org/2wm
Log | Files | Refs | README | LICENSE

view.c (4938B)


      1 /* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
      2  * See LICENSE file for license details.
      3  */
      4 #include "2wm.h"
      5 #include <regex.h>
      6 #include <stdio.h>
      7 #include <stdlib.h>
      8 #include <string.h>
      9 #include <sys/types.h>
     10 #include <X11/Xutil.h>
     11 
     12 
     13 typedef struct { regex_t *regex; } RReg;
     14 
     15 /* static */
     16 
     17 FLOATS
     18 
     19 static RReg *rreg = NULL;
     20 static unsigned int reglen = 0;
     21 
     22 static Client *
     23 getnext(Client *c) {
     24 	for(; c && c->view != view; c = c->next);
     25 	return c;
     26 }
     27 
     28 static Client *
     29 getprev(Client *c) {
     30 	for(; c && c->view != view; c = c->prev);
     31 	return c;
     32 }
     33 
     34 static Client *
     35 nexttiled(Client *c) {
     36 	for(c = getnext(c); c && c->isfloat; c = getnext(c->next));
     37 	return c;
     38 }
     39 
     40 static void
     41 pop(Client *c) {
     42 	detachclient(c);
     43 	if(clients)
     44 		clients->prev = c;
     45 	c->next = clients;
     46 	clients = c;
     47 }
     48 
     49 static void
     50 togglemax(Client *c) {
     51 	XEvent ev;
     52 		
     53 	if(c->isfixed)
     54 		return;
     55 
     56 	if((c->ismax = !c->ismax)) {
     57 		c->rx = c->x; c->x = sx;
     58 		c->ry = c->y; c->y = sy;
     59 		c->rw = c->w; c->w = sw - 2 * BORDERPX;
     60 		c->rh = c->h; c->h = sh - 2 * BORDERPX;
     61 	}
     62 	else {
     63 		c->x = c->rx;
     64 		c->y = c->ry;
     65 		c->w = c->rw;
     66 		c->h = c->rh;
     67 	}
     68 	resize(c, True);
     69 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
     70 }
     71 
     72 /* extern */
     73 
     74 void
     75 arrange(void) {
     76 	unsigned int i, n, mw, mh, tw, th;
     77 	Client *c;
     78 
     79 	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
     80 		n++;
     81 	/* window geoms */
     82 	mh = (n > nmaster) ? sh / nmaster : sh / (n > 0 ? n : 1);
     83 	mw = (n > nmaster) ? (sw * master) / 1000 : sw;
     84 	th = (n > nmaster) ? sh / (n - nmaster) : 0;
     85 	tw = sw - mw;
     86 
     87 	for(i = 0, c = clients; c; c = c->next)
     88 		if(c->view == view) {
     89 			if(c->isfloat) {
     90 				resize(c, True);
     91 				continue;
     92 			}
     93 			c->ismax = False;
     94 			c->x = sx;
     95 			c->y = sy;
     96 			if(i < nmaster) {
     97 				c->y += i * mh;
     98 				c->w = mw - 2 * BORDERPX;
     99 				c->h = mh - 2 * BORDERPX;
    100 			}
    101 			else {  /* tile window */
    102 				c->x += mw;
    103 				c->w = tw - 2 * BORDERPX;
    104 				if(th > 2 * BORDERPX) {
    105 					c->y += (i - nmaster) * th;
    106 					c->h = th - 2 * BORDERPX;
    107 				}
    108 				else /* fallback if th <= 2 * BORDERPX */
    109 					c->h = sh - 2 * BORDERPX;
    110 			}
    111 			resize(c, False);
    112 			i++;
    113 		}
    114 		else
    115 			XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
    116 	if(!sel || sel->view != view) {
    117 		for(c = stack; c && c->view != view; c = c->snext);
    118 		focus(c);
    119 	}
    120 	restack();
    121 }
    122 
    123 void
    124 attach(Arg *arg) {
    125 	Client *c;
    126 
    127 	for(c = clients; c && c->view == view; c = c->next);
    128 	if(!c)
    129 		return;
    130 	c->view = !c->view;
    131 	pop(c);
    132 	focus(c);
    133 	arrange();
    134 }
    135 
    136 void
    137 detach(Arg *arg) {
    138 	if(!sel)
    139 		return;
    140 	sel->view = !sel->view;
    141 	pop(sel);
    142 	arrange();
    143 }
    144 
    145 void
    146 focusnext(Arg *arg) {
    147 	Client *c;
    148    
    149 	if(!sel)
    150 		return;
    151 	if(!(c = getnext(sel->next)))
    152 		c = getnext(clients);
    153 	if(c) {
    154 		focus(c);
    155 		restack();
    156 	}
    157 }
    158 
    159 void
    160 focusprev(Arg *arg) {
    161 	Client *c;
    162 
    163 	if(!sel)
    164 		return;
    165 	if(!(c = getprev(sel->prev))) {
    166 		for(c = clients; c && c->next; c = c->next);
    167 		c = getprev(c);
    168 	}
    169 	if(c) {
    170 		focus(c);
    171 		restack();
    172 	}
    173 }
    174 
    175 void
    176 incnmaster(Arg *arg) {
    177 	if((nmaster + arg->i < 1) || (sh / (nmaster + arg->i) <= 2 * BORDERPX))
    178 		return;
    179 	nmaster += arg->i;
    180 	if(sel)
    181 		arrange();
    182 }
    183 
    184 void
    185 initrregs(void) {
    186 	unsigned int i;
    187 	regex_t *reg;
    188 
    189 	if(rreg)
    190 		return;
    191 	for(reglen = 0; floats[reglen]; reglen++);
    192 	rreg = emallocz(reglen * sizeof(RReg));
    193 	for(i = 0; i < reglen; i++)
    194 		if(floats[i]) {
    195 			reg = emallocz(sizeof(regex_t));
    196 			if(regcomp(reg, floats[i], REG_EXTENDED))
    197 				free(reg);
    198 			else
    199 				rreg[i].regex = reg;
    200 		}
    201 }
    202 
    203 Bool
    204 isfloat(Client *c) {
    205 	char prop[512];
    206 	unsigned int i;
    207 	regmatch_t tmp;
    208 	Bool ret = False;
    209 	XClassHint ch = { 0 };
    210 
    211 	XGetClassHint(dpy, c->win, &ch);
    212 	snprintf(prop, sizeof prop, "%s:%s:%s",
    213 			ch.res_class ? ch.res_class : "",
    214 			ch.res_name ? ch.res_name : "", c->name);
    215 	for(i = 0; i < reglen; i++)
    216 		if(rreg[i].regex && !regexec(rreg[i].regex, prop, 1, &tmp, 0)) {
    217 			ret = True;
    218 			break;
    219 		}
    220 	if(ch.res_class)
    221 		XFree(ch.res_class);
    222 	if(ch.res_name)
    223 		XFree(ch.res_name);
    224 	return ret;
    225 }
    226 
    227 void
    228 resizemaster(Arg *arg) {
    229 	if(arg->i == 0)
    230 		master = MASTER;
    231 	else {
    232 		if(sw * (master + arg->i) / 1000 >= sw - 2 * BORDERPX
    233 			|| sw * (master + arg->i) / 1000 <= 2 * BORDERPX)
    234 			return;
    235 		master += arg->i;
    236 	}
    237 	arrange();
    238 }
    239 
    240 void
    241 restack(void) {
    242 	Client *c;
    243 	XEvent ev;
    244 
    245 	if(!sel)
    246 		return;
    247 	if(sel->isfloat)
    248 		XRaiseWindow(dpy, sel->win);
    249 	else
    250 		XLowerWindow(dpy, sel->win);
    251 	for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
    252 		if(c == sel)
    253 			continue;
    254 		XLowerWindow(dpy, c->win);
    255 	}
    256 	XSync(dpy, False);
    257 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
    258 }
    259 
    260 void
    261 togglefloat(Arg *arg) {
    262 	if(!sel)
    263 		return;
    264 	sel->isfloat = !sel->isfloat;
    265 	arrange();
    266 }
    267 
    268 void
    269 toggleview(Arg *arg) {
    270 	view = !view;
    271 	arrange();
    272 }
    273 
    274 void
    275 zoom(Arg *arg) {
    276 	unsigned int n;
    277 	Client *c;
    278 
    279 	if(!sel)
    280 		return;
    281 	if(sel->isfloat) {
    282 		togglemax(sel);
    283 		return;
    284 	}
    285 	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
    286 		n++;
    287 
    288 	if((c = sel) == nexttiled(clients))
    289 		if(!(c = nexttiled(c->next)))
    290 			return;
    291 	pop(c);
    292 	focus(c);
    293 	arrange();
    294 }