wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

area.c (5344B)


      1 /* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
      2  * See LICENSE file for license details.
      3  */
      4 #include "dat.h"
      5 #include <math.h>
      6 #include <limits.h>
      7 #include "fns.h"
      8 
      9 Client*
     10 area_selclient(Area *a) {
     11 	if(a && a->sel)
     12 		return a->sel->client;
     13 	return nil;
     14 }
     15 
     16 int
     17 area_idx(Area *a) {
     18 	View *v;
     19 	Area *ap;
     20 	uint i;
     21 
     22 	v = a->view;
     23 	if(a->floating)
     24 		return -1;
     25 	i = 1;
     26 	for(ap=v->areas[a->screen]; a != ap; ap=ap->next)
     27 		i++;
     28 	return i;
     29 }
     30 
     31 static Rectangle
     32 area_rect(void *v) {
     33 	Area *a;
     34 
     35 	a = v;
     36 	return a->r;
     37 }
     38 
     39 Area*
     40 area_find(View *v, Rectangle r, int dir, bool wrap) {
     41 	static Vector_ptr vec;
     42 	Area *a;
     43 	int s;
     44 
     45 	vec.n = 0;
     46 	foreach_column(v, s, a)
     47 		vector_ppush(&vec, a);
     48 
     49 	return findthing(r, dir, &vec, area_rect, wrap);
     50 }
     51 
     52 int
     53 afmt(Fmt *f) {
     54 	Area *a;
     55 
     56 	a = va_arg(f->args, Area*);
     57 	if(a == nil)
     58 		return fmtstrcpy(f, "<nil>");
     59 	if(a->floating)
     60 		return fmtstrcpy(f, "~");
     61 	if(a->screen > 0 || (f->flags & FmtSharp))
     62 		return fmtprint(f, "%d:%d", a->screen, area_idx(a));
     63 	return fmtprint(f, "%d", area_idx(a));
     64 }
     65 
     66 char*
     67 area_name(Area *a) {
     68 
     69 	if(a == nil)
     70 		return "<nil>";
     71 	if(a->floating)
     72 		return "~";
     73 	return sxprint("%d", area_idx(a));
     74 }
     75 
     76 Area*
     77 area_create(View *v, Area *pos, int scrn, uint width) {
     78 	static ushort id = 1;
     79 	int i, j;
     80 	uint minwidth, index;
     81 	int numcols;
     82 	Area *a;
     83 
     84 	assert(!pos || pos->screen == scrn);
     85 	SET(index);
     86 	if(v->areas) { /* Creating a column. */
     87 		minwidth = column_minwidth();
     88 		index = pos ? area_idx(pos) : 0;
     89 		numcols = 0;
     90 		for(a=v->areas[scrn]; a; a=a->next)
     91 			numcols++;
     92 
     93 		/* TODO: Need a better sizing/placing algorithm. */
     94 		if(width == 0) {
     95 			if(numcols >= 0) {
     96 				width = view_newcolwidth(v, scrn, index);
     97 				if(width == 0)
     98 					width = Dx(v->r[scrn]) / (numcols + 1);
     99 			}
    100 			else
    101 				width = Dx(v->r[scrn]);
    102 		}
    103 
    104 		if(width < minwidth)
    105 			width = minwidth;
    106 		minwidth = numcols * minwidth + minwidth;
    107 		if(minwidth > Dx(v->r[scrn]))
    108 			return nil;
    109 
    110 		i = minwidth - Dx(v->pad[scrn]) - Dx(v->r[scrn]);
    111 		if(i > 0 && Dx(v->pad[scrn])) {
    112 			j = min(i/2, v->pad[scrn].min.x);
    113 			v->pad[scrn].min.x -= j;
    114 			v->pad[scrn].max.x += i - j;
    115 		}
    116 
    117 		view_scale(v, scrn, Dx(v->r[scrn]) - width);
    118 	}
    119 
    120 	a = emallocz(sizeof *a);
    121 	a->view = v;
    122 	a->screen = scrn;
    123 	a->id = id++;
    124 	a->floating = !v->floating;
    125 	if(a->floating)
    126 		a->mode = Coldefault;
    127 	else
    128 		a->mode = def.colmode;
    129 	a->frame = nil;
    130 	a->sel = nil;
    131 
    132 	a->r = v->r[scrn];
    133 	a->r.min.x = 0;
    134 	a->r.max.x = width;
    135 
    136 	if(a->floating) {
    137 		v->floating = a;
    138 		a->screen = -1;
    139 	}
    140 	else if(pos) {
    141 		a->next = pos->next;
    142 		a->prev = pos;
    143 	}
    144 	else {
    145 		a->next = v->areas[scrn];
    146 		v->areas[scrn] = a;
    147 	}
    148 	if(a->prev)
    149 		a->prev->next = a;
    150 	if(a->next)
    151 		a->next->prev = a;
    152 
    153 	if(v->sel == nil && !a->floating)
    154 		area_focus(a);
    155 
    156 	if(!a->floating)
    157 		event("CreateColumn %ud\n", index);
    158 	return a;
    159 }
    160 
    161 void
    162 area_destroy(Area *a) {
    163 	Area *newfocus;
    164 	View *v;
    165 	int idx;
    166 
    167 	v = a->view;
    168 
    169 	if(a->frame)
    170 		die("destroying non-empty area");
    171 
    172 	if(v->revert == a)
    173 		v->revert = nil;
    174 	if(v->oldsel == a)
    175 		v->oldsel = nil;
    176 
    177 	idx = area_idx(a);
    178 
    179 	if(a->prev && !a->prev->floating)
    180 		newfocus = a->prev;
    181 	else
    182 		newfocus = a->next;
    183 
    184 	/* Can only destroy the floating area when destroying a
    185 	 * view---after destroying all columns.
    186 	 */
    187 	assert(!a->floating || !v->areas[0]);
    188 	if(a->prev)
    189 		a->prev->next = a->next;
    190 	else if(!a->floating)
    191 		v->areas[a->screen] = a->next;
    192 	else
    193 		v->floating = nil;
    194 	if(a->next)
    195 		a->next->prev = a->prev;
    196 
    197 	if(newfocus && v->sel == a)
    198 		area_focus(newfocus);
    199 
    200 	view_arrange(v);
    201 	event("DestroyArea %d\n", idx);
    202 
    203 	free(a);
    204 }
    205 
    206 void
    207 area_moveto(Area *to, Frame *f) {
    208 	Area *from;
    209 
    210 	assert(to->view == f->view);
    211 
    212 	if(f->client->fullscreen >= 0 && !to->floating)
    213 		return;
    214 
    215 	from = f->area;
    216 	if(from == to)
    217 		return;
    218 
    219 	area_detach(f);
    220 
    221 	/* Temporary kludge. */
    222 	if(!to->floating
    223 	&& to->floating != from->floating
    224 	&& !eqrect(f->colr, ZR))
    225 		column_attachrect(to, f, f->colr);
    226 	else
    227 		area_attach(to, f);
    228 }
    229 
    230 void
    231 area_setsel(Area *a, Frame *f) {
    232 	View *v;
    233 
    234 	v = a->view;
    235 	/* XXX: Stack. */
    236 	for(; f && f->collapsed && f->anext; f=f->anext)
    237 		;
    238 	for(; f && f->collapsed && f->aprev; f=f->aprev)
    239 		;
    240 
    241 	if(a == v->sel && f)
    242 		frame_focus(f);
    243 	else
    244 		a->sel = f;
    245 }
    246 
    247 void
    248 area_attach(Area *a, Frame *f) {
    249 
    250 	f->area = a;
    251 	if(a->floating)
    252 		float_attach(a, f);
    253 	else
    254 		column_attach(a, f);
    255 
    256 	view_arrange(a->view);
    257 	event("AreaAttach %s %a %#C\n", a->view->name, a, f->client);
    258 
    259 	if(btassert("4 full", a->frame && a->sel == nil))
    260 		a->sel = a->frame;
    261 }
    262 
    263 void
    264 area_detach(Frame *f) {
    265 	View *v;
    266 	Area *a;
    267 
    268 	a = f->area;
    269 	v = a->view;
    270 
    271 	event("AreaDetach %s %a %#C\n", v->name, a, f->client);
    272 	if(a->floating)
    273 		float_detach(f);
    274 	else
    275 		column_detach(f);
    276 
    277 	if(v->sel->sel == nil && v->floating->sel)
    278 	if(!v->floating->sel->client->nofocus)
    279 		v->sel = v->floating;
    280 
    281 	view_arrange(v);
    282 }
    283 
    284 void
    285 area_focus(Area *a) {
    286 	Frame *f;
    287 	View *v;
    288 	Area *old_a;
    289 
    290 	v = a->view;
    291 	f = a->sel;
    292 	old_a = v->sel;
    293 
    294 	if(!a->floating && view_fullscreen_p(v, a->screen))
    295 		return;
    296 
    297 	v->sel = a;
    298 	if(!a->floating) {
    299 		v->selcol = area_idx(a);
    300 		v->selscreen = a->screen;
    301 	}
    302 	if(a != old_a)
    303 		v->oldsel = nil;
    304 
    305 	if(old_a && a->floating != old_a->floating) {
    306 		v->revert = old_a;
    307 		if(v->floating->max)
    308 			view_update(v);
    309 	}
    310 
    311 	if(v == selview) {
    312 		move_focus(old_a->sel, f);
    313 		client_focus(f ? f->client : nil);
    314 
    315 		if(a != old_a)
    316 			event("AreaFocus %a\n", a);
    317 	}
    318 }
    319