1 /* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
2  * See LICENSE file for license details.
3  */
4 #include "dat.h"
5 #include "fns.h"
6 
7 static Image*	divimg;
8 static Image*	divmask;
9 static CTuple	divcolor;
10 static Handlers	handlers;
11 
12 static Divide*
getdiv(Divide *** dp)13 getdiv(Divide ***dp) {
14 	WinAttr wa;
15 	Divide *d;
16 
17 	if(**dp)
18 		d = **dp;
19 	else {
20 		d = emallocz(sizeof *d);
21 
22 		wa.override_redirect = true;
23 		wa.cursor = cursor[CurDHArrow];
24 		wa.event_mask =
25 			  ExposureMask
26 			| EnterWindowMask
27 			| ButtonPressMask
28 			| ButtonReleaseMask;
29 		d->w = createwindow(&scr.root, Rect(0, 0, 1, 1), scr.depth,
30 				    InputOutput, &wa,
31 			  CWOverrideRedirect
32 			| CWEventMask
33 			| CWCursor);
34 		d->w->aux = d;
35 		sethandler(d->w, &handlers);
36 		**dp = d;
37 	}
38 	*dp = &d->next;
39 	return d;
40 }
41 
42 static void
mapdiv(Divide * d)43 mapdiv(Divide *d) {
44 	mapwin(d->w);
45 }
46 
47 static void
unmapdiv(Divide * d)48 unmapdiv(Divide *d) {
49 	unmapwin(d->w);
50 }
51 
52 void
div_set(Divide * d,int x)53 div_set(Divide *d, int x) {
54 	Rectangle r;
55 	int scrn;
56 
57 	scrn = d->left ? d->left->screen : d->right->screen;
58 
59 	d->x = x;
60 	r = rectaddpt(divimg->r, Pt(x - Dx(divimg->r)/2, 0));
61 	r.min.y = selview->r[scrn].min.y;
62 	r.max.y = selview->r[scrn].max.y;
63 
64 	reshapewin(d->w, r);
65 	mapdiv(d);
66 }
67 
68 static void
drawimg(Image * img,Color cbg,Color cborder,Divide * d)69 drawimg(Image *img, Color cbg, Color cborder, Divide *d) {
70 	Point pt[8];
71 	int n, start, w;
72 
73 	w = Dx(img->r)/2;
74 	n = 0;
75 	pt[n++] = Pt(w,		0);
76 	pt[n++] = Pt(0,		0);
77 	pt[n++] = Pt(w - 1,	w - 1);
78 
79 	pt[n++] = Pt(w - 1,	Dy(img->r));
80 	pt[n++] = Pt(w,		pt[n-1].y);
81 
82 	pt[n++] = Pt(w,		w - 1);
83 	pt[n++] = Pt(2*w - 1,	0);
84 	pt[n++] = Pt(w,		0);
85 
86 	start = d->left		? 0 : n/2;
87 	n = d->right && d->left ? n : n/2;
88 
89 	fillpoly(img, pt + start, n, cbg);
90 	drawpoly(img, pt + start, n, CapNotLast, 1, cborder);
91 }
92 
93 static void
drawdiv(Divide * d)94 drawdiv(Divide *d) {
95 
96 	fill(divmask, divmask->r, (Color){0});
97 	drawimg(divmask, (Color){1}, (Color){1}, d);
98 	drawimg(divimg, divcolor.bg, divcolor.border, d);
99 
100 	copyimage(d->w, divimg->r, divimg, ZP);
101 	setshapemask(d->w, divmask, ZP);
102 }
103 
104 static void
update_imgs(void)105 update_imgs(void) {
106 	Divide *d;
107 	int w, h;
108 
109 	w = 2 * (labelh(def.font) / 3);
110 	w = max(w, 10);
111 	/* XXX: Multihead. */
112 	h = Dy(scr.rect);
113 
114 	if(divimg) {
115 		if(w == Dx(divimg->r) && h == Dy(divimg->r)
116 		&& !memcmp(&divcolor, &def.normcolor, sizeof divcolor))
117 			return;
118 		freeimage(divimg);
119 		freeimage(divmask);
120 	}
121 
122 	divimg = allocimage(w, h, scr.depth);
123 	divmask = allocimage(w, h, 1);
124 	divcolor = def.normcolor;
125 
126 	for(d = divs; d && d->w->mapped; d = d->next)
127 		drawdiv(d);
128 }
129 
130 void
div_update_all(void)131 div_update_all(void) {
132 	Divide **dp, *d;
133 	Area *a, *ap;
134 	View *v;
135 	int s;
136 
137 	update_imgs();
138 
139 	v = selview;
140 	dp = &divs;
141 	ap = nil;
142 	foreach_column(v, s, a) {
143 		if (ap && ap->screen != s)
144 			ap = nil;
145 
146 		d = getdiv(&dp);
147 		d->left = ap;
148 		d->right = a;
149 		div_set(d, a->r.min.x);
150 		drawdiv(d);
151 		ap = a;
152 
153 		if(!a->next) {
154 			d = getdiv(&dp);
155 			d->left = a;
156 			d->right = nil;
157 			div_set(d, a->r.max.x);
158 			drawdiv(d);
159 		}
160 	}
161 	for(d = *dp; d; d = d->next)
162 		unmapdiv(d);
163 }
164 
165 /* Div Handlers */
166 static void
bdown_event(Window * w,XButtonEvent * e)167 bdown_event(Window *w, XButtonEvent *e) {
168 	Divide *d;
169 
170 	USED(e);
171 
172 	d = w->aux;
173 	mouse_resizecol(d);
174 }
175 
176 static void
expose_event(Window * w,XExposeEvent * e)177 expose_event(Window *w, XExposeEvent *e) {
178 	Divide *d;
179 
180 	USED(e);
181 
182 	d = w->aux;
183 	drawdiv(d);
184 }
185 
186 static Handlers handlers = {
187 	.bdown = bdown_event,
188 	.expose = expose_event,
189 };
190 
191