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