Remove commented-out variables
[notion.git] / mod_tiling / splitfloat.c
blob11b2ab3001b02e6212554de267a5f443cd88fafc
1 /*
2 * ion/mod_tiling/splitext.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
7 */
9 #include <string.h>
10 #include <limits.h>
11 #include <libtu/objp.h>
12 #include <libtu/minmax.h>
13 #include <ioncore/common.h>
14 #include <ioncore/global.h>
15 #include <ioncore/rootwin.h>
16 #include <ioncore/xwindow.h>
17 #include <ioncore/window.h>
19 #include "tiling.h"
20 #include "split.h"
21 #include "splitfloat.h"
22 #include "panehandle.h"
25 #define GEOM(X) (((WSplit*)(X))->geom)
28 /*{{{ Init/deinit */
31 static void splitfloat_set_borderlines(WSplitFloat *split)
33 int dir=split->ssplit.dir;
35 split->tlpwin->bline=(dir==SPLIT_HORIZONTAL
36 ? GR_BORDERLINE_RIGHT
37 : GR_BORDERLINE_BOTTOM);
39 split->brpwin->bline=(dir==SPLIT_HORIZONTAL
40 ? GR_BORDERLINE_LEFT
41 : GR_BORDERLINE_TOP);
45 bool splitfloat_init(WSplitFloat *split, const WRectangle *geom,
46 WTiling *ws, int dir)
48 WFitParams fp;
49 WWindow *par=REGION_PARENT(ws);
51 assert(par!=NULL);
53 fp.g=*geom;
54 fp.mode=REGION_FIT_EXACT;
55 split->tlpwin=create_panehandle(par, &fp);
56 if(split->tlpwin==NULL)
57 return FALSE;
59 fp.g=*geom;
60 fp.mode=REGION_FIT_EXACT;
61 split->brpwin=create_panehandle(par, &fp);
62 if(split->brpwin==NULL){
63 destroy_obj((Obj*)split->tlpwin);
64 return FALSE;
67 ((WRegion*)split->brpwin)->flags|=REGION_SKIP_FOCUS;
68 ((WRegion*)split->tlpwin)->flags|=REGION_SKIP_FOCUS;
70 if(!splitsplit_init(&(split->ssplit), geom, dir)){
71 destroy_obj((Obj*)split->brpwin);
72 destroy_obj((Obj*)split->tlpwin);
73 return FALSE;
76 split->tlpwin->splitfloat=split;
77 split->brpwin->splitfloat=split;
79 splitfloat_set_borderlines(split);
81 if(REGION_IS_MAPPED(ws)){
82 region_map((WRegion*)(split->tlpwin));
83 region_map((WRegion*)(split->brpwin));
86 return TRUE;
90 WSplitFloat *create_splitfloat(const WRectangle *geom, WTiling *ws, int dir)
92 CREATEOBJ_IMPL(WSplitFloat, splitfloat, (p, geom, ws, dir));
96 void splitfloat_deinit(WSplitFloat *split)
98 if(split->tlpwin!=NULL){
99 WPaneHandle *tmp=split->tlpwin;
100 split->tlpwin=NULL;
101 tmp->splitfloat=NULL;
102 destroy_obj((Obj*)tmp);
105 if(split->brpwin!=NULL){
106 WPaneHandle *tmp=split->brpwin;
107 split->brpwin=NULL;
108 tmp->splitfloat=NULL;
109 destroy_obj((Obj*)tmp);
112 splitsplit_deinit(&(split->ssplit));
116 /*}}}*/
119 /*{{{ X window handling */
122 static void stack_stacking_reg(WRegion *reg,
123 Window *bottomret, Window *topret)
125 Window b=None, t=None;
127 if(reg!=NULL){
128 region_stacking(reg, &b, &t);
129 if(*bottomret==None)
130 *bottomret=b;
131 if(t!=None)
132 *topret=t;
137 static void stack_stacking_split(WSplit *split,
138 Window *bottomret, Window *topret)
140 Window b=None, t=None;
142 if(split!=NULL){
143 split_stacking(split, &b, &t);
144 if(*bottomret==None)
145 *bottomret=b;
146 if(t!=None)
147 *topret=t;
152 static void splitfloat_stacking(WSplitFloat *split,
153 Window *bottomret, Window *topret)
155 *bottomret=None;
156 *topret=None;
158 if(split->ssplit.current!=SPLIT_CURRENT_TL){
159 stack_stacking_reg((WRegion*)split->tlpwin, bottomret, topret);
160 stack_stacking_split(split->ssplit.tl, bottomret, topret);
161 stack_stacking_reg((WRegion*)split->brpwin, bottomret, topret);
162 stack_stacking_split(split->ssplit.br, bottomret, topret);
163 }else{
164 stack_stacking_reg((WRegion*)split->brpwin, bottomret, topret);
165 stack_stacking_split(split->ssplit.br, bottomret, topret);
166 stack_stacking_reg((WRegion*)split->tlpwin, bottomret, topret);
167 stack_stacking_split(split->ssplit.tl, bottomret, topret);
172 static void stack_restack_reg(WRegion *reg, Window *other, int *mode)
174 Window b=None, t=None;
176 if(reg!=NULL){
177 region_restack(reg, *other, *mode);
178 region_stacking(reg, &b, &t);
179 if(t!=None){
180 *other=t;
181 *mode=Above;
187 static void stack_restack_split(WSplit *split, Window *other, int *mode)
189 Window b=None, t=None;
191 if(split!=NULL){
192 split_restack(split, *other, *mode);
193 split_stacking(split, &b, &t);
194 if(t!=None){
195 *other=t;
196 *mode=Above;
203 static void splitfloat_restack(WSplitFloat *split, Window other, int mode)
205 if(split->ssplit.current!=SPLIT_CURRENT_TL){
206 stack_restack_reg((WRegion*)split->tlpwin, &other, &mode);
207 stack_restack_split(split->ssplit.tl, &other, &mode);
208 stack_restack_reg((WRegion*)split->brpwin, &other, &mode);
209 stack_restack_split(split->ssplit.br, &other, &mode);
210 }else{
211 stack_restack_reg((WRegion*)split->brpwin, &other, &mode);
212 stack_restack_split(split->ssplit.br, &other, &mode);
213 stack_restack_reg((WRegion*)split->tlpwin, &other, &mode);
214 stack_restack_split(split->ssplit.tl, &other, &mode);
219 static void splitfloat_map(WSplitFloat *split)
221 region_map((WRegion*)(split->tlpwin));
222 region_map((WRegion*)(split->brpwin));
223 splitinner_forall((WSplitInner*)split, split_map);
227 static void splitfloat_unmap(WSplitFloat *split)
229 region_unmap((WRegion*)(split->tlpwin));
230 region_unmap((WRegion*)(split->brpwin));
231 splitinner_forall((WSplitInner*)split, split_unmap);
235 static void reparentreg(WRegion *reg, WWindow *target)
237 WRectangle g=REGION_GEOM(reg);
238 region_reparent(reg, target, &g, REGION_FIT_EXACT);
242 static void splitfloat_reparent(WSplitFloat *split, WWindow *target)
244 if(split->ssplit.current!=SPLIT_CURRENT_TL){
245 reparentreg((WRegion*)split->tlpwin, target);
246 split_reparent(split->ssplit.tl, target);
247 reparentreg((WRegion*)split->brpwin, target);
248 split_reparent(split->ssplit.br, target);
249 }else{
250 reparentreg((WRegion*)split->brpwin, target);
251 split_reparent(split->ssplit.br, target);
252 reparentreg((WRegion*)split->tlpwin, target);
253 split_reparent(split->ssplit.tl, target);
258 /*}}}*/
261 /*{{{ Geometry */
264 #define TL_BORDER(SF) ((SF)->ssplit.dir==SPLIT_VERTICAL \
265 ? (SF)->tlpwin->bdw.bottom \
266 : (SF)->tlpwin->bdw.right)
268 #define BR_BORDER(SF) ((SF)->ssplit.dir==SPLIT_VERTICAL \
269 ? (SF)->brpwin->bdw.top \
270 : (SF)->brpwin->bdw.left)
273 void splitfloat_tl_pwin_to_cnt(WSplitFloat *split, WRectangle *g)
275 if(split->ssplit.dir==SPLIT_HORIZONTAL)
276 g->w=maxof(1, g->w-split->tlpwin->bdw.right);
277 else
278 g->h=maxof(1, g->h-split->tlpwin->bdw.bottom);
282 void splitfloat_br_pwin_to_cnt(WSplitFloat *split, WRectangle *g)
284 if(split->ssplit.dir==SPLIT_HORIZONTAL){
285 int delta=split->tlpwin->bdw.left;
286 g->w=maxof(1, g->w-delta);
287 g->x+=delta;
288 }else{
289 int delta=split->tlpwin->bdw.top;
290 g->h=maxof(1, g->h-delta);
291 g->y+=delta;
296 void splitfloat_tl_cnt_to_pwin(WSplitFloat *split, WRectangle *g)
298 if(split->ssplit.dir==SPLIT_HORIZONTAL)
299 g->w=maxof(1, g->w+split->tlpwin->bdw.right);
300 else
301 g->h=maxof(1, g->h+split->tlpwin->bdw.bottom);
305 void splitfloat_br_cnt_to_pwin(WSplitFloat *split, WRectangle *g)
307 if(split->ssplit.dir==SPLIT_HORIZONTAL){
308 int delta=split->tlpwin->bdw.left;
309 g->w=maxof(1, g->w+delta);
310 g->x-=delta;
311 }else{
312 int delta=split->tlpwin->bdw.top;
313 g->h=maxof(1, g->h+delta);
314 g->y-=delta;
319 static int infadd(int x, int y)
321 return ((x==INT_MAX || y==INT_MAX) ? INT_MAX : (x+y));
325 static int splitfloat_get_handle(WSplitFloat *split, int dir,
326 WSplit *other)
328 assert(other==split->ssplit.tl || other==split->ssplit.br);
330 if(dir!=split->ssplit.dir)
331 return 0;
333 if(dir==SPLIT_VERTICAL){
334 if(other==split->ssplit.tl)
335 return split->tlpwin->bdw.right;
336 else if(other==split->ssplit.br)
337 return split->tlpwin->bdw.left;
338 }else{
339 if(other==split->ssplit.tl)
340 return split->tlpwin->bdw.bottom;
341 else if(other==split->ssplit.br)
342 return split->tlpwin->bdw.top;
345 return 0;
349 static int splitfloat_get_max(WSplitFloat *split, int dir, WSplit *other)
351 return infadd((dir==SPLIT_VERTICAL ? other->max_h : other->max_w),
352 splitfloat_get_handle(split, dir, other));
356 static int splitfloat_get_min(WSplitFloat *split, int dir, WSplit *other)
358 return ((dir==SPLIT_VERTICAL ? other->min_h : other->min_w)
359 +splitfloat_get_handle(split, dir, other));
363 static void splitfloat_update_bounds(WSplitFloat *split, bool recursive)
365 WSplit *tl=split->ssplit.tl, *br=split->ssplit.br;
366 WSplit *node=(WSplit*)split;
367 int tl_max_w, br_max_w, tl_max_h, br_max_h;
368 int tl_min_w, br_min_w, tl_min_h, br_min_h;
370 if(recursive){
371 split_update_bounds(tl, recursive);
372 split_update_bounds(br, recursive);
375 tl_max_w=splitfloat_get_max(split, SPLIT_HORIZONTAL, tl);
376 br_max_w=splitfloat_get_max(split, SPLIT_HORIZONTAL, br);
377 tl_max_h=splitfloat_get_max(split, SPLIT_VERTICAL, tl);
378 br_max_h=splitfloat_get_max(split, SPLIT_VERTICAL, br);
379 tl_min_w=splitfloat_get_min(split, SPLIT_HORIZONTAL, tl);
380 br_min_w=splitfloat_get_min(split, SPLIT_HORIZONTAL, br);
381 tl_min_h=splitfloat_get_min(split, SPLIT_VERTICAL, tl);
382 br_min_h=splitfloat_get_min(split, SPLIT_VERTICAL, br);
384 if(split->ssplit.dir==SPLIT_HORIZONTAL){
385 node->max_w=infadd(tl_max_w, br_max_w);
386 node->min_w=minof(tl_min_w, br_min_w);
387 node->unused_w=0;
388 node->min_h=maxof(tl_min_h, br_min_h);
389 node->max_h=maxof(minof(tl_max_h, br_max_h), node->min_h);
390 node->unused_h=minof(tl->unused_h, br->unused_h);
391 }else{
392 node->max_h=infadd(tl_max_h, br_max_h);
393 node->min_h=minof(tl_min_h, br_min_h);
394 node->unused_h=0;
395 node->min_w=maxof(tl_min_w, br_min_w);
396 node->max_w=maxof(minof(tl_max_w, br_max_w), node->min_w);
397 node->unused_w=minof(tl->unused_w, br->unused_w);
402 void splitfloat_update_handles(WSplitFloat *split, const WRectangle *tlg_,
403 const WRectangle *brg_)
405 WRectangle tlg=*tlg_, brg=*brg_;
407 if(split->ssplit.dir==SPLIT_HORIZONTAL){
408 tlg.w=split->tlpwin->bdw.right;
409 tlg.x=tlg_->x+tlg_->w-tlg.w;
410 brg.w=split->brpwin->bdw.left;
411 }else{
412 tlg.h=split->tlpwin->bdw.bottom;
413 tlg.y=tlg_->y+tlg_->h-tlg.h;
414 brg.h=split->brpwin->bdw.top;
417 region_fit((WRegion*)split->tlpwin, &tlg, REGION_FIT_EXACT);
418 region_fit((WRegion*)split->brpwin, &brg, REGION_FIT_EXACT);
422 static void bound(int *what, int min, int max)
424 if(*what<min)
425 *what=min;
426 else if(*what>max)
427 *what=max;
431 static void adjust_sizes(int *tls_, int *brs_, int nsize,
432 int tlmin, int brmin, int tlmax, int brmax,
433 int primn)
435 int tls=maxof(0, *tls_);
436 int brs=maxof(0, *brs_);
437 nsize=maxof(1, nsize);
439 if(primn==PRIMN_TL){
440 tls=maxof(1, nsize-brs);
441 bound(&tls, tlmin, tlmax);
442 brs=nsize-tls;
443 bound(&brs, brmin, brmax);
444 tls=nsize-brs;
445 bound(&tls, tlmin, tlmax);
446 }else if(primn==PRIMN_BR){
447 brs=maxof(1, nsize-tls);
448 bound(&brs, brmin, brmax);
449 tls=nsize-brs;
450 bound(&tls, tlmin, tlmax);
451 brs=nsize-tls;
452 bound(&brs, brmin, brmax);
453 }else{ /* && PRIMN_ANY */
454 tls=tls*nsize/maxof(2, tls+brs);
455 bound(&tls, tlmin, tlmax);
456 brs=nsize-tls;
457 bound(&brs, brmin, brmax);
458 tls=nsize-brs;
459 bound(&tls, tlmin, tlmax);
462 *tls_=tls;
463 *brs_=brs;
467 static void adjust_size(int *sz, int dir, WSplitFloat *f, WSplit *s)
469 int mi=splitfloat_get_min(f, dir, s);
470 int ma=splitfloat_get_max(f, dir, s);
471 *sz=maxof(mi, minof(*sz, ma));
475 static void splitfloat_do_resize(WSplitFloat *split, const WRectangle *ng,
476 int hprimn, int vprimn, bool transpose)
478 WRectangle tlg=GEOM(split->ssplit.tl);
479 WRectangle brg=GEOM(split->ssplit.br);
480 WRectangle ntlg=*ng, nbrg=*ng;
481 int dir=split->ssplit.dir;
482 bool adjust=TRUE;
484 splitfloat_tl_cnt_to_pwin(split, &tlg);
485 splitfloat_br_cnt_to_pwin(split, &brg);
487 if(transpose){
488 if(dir==SPLIT_VERTICAL){
489 dir=SPLIT_HORIZONTAL;
490 split->tlpwin->bline=GR_BORDERLINE_RIGHT;
491 split->brpwin->bline=GR_BORDERLINE_LEFT;
492 }else{
493 dir=SPLIT_VERTICAL;
494 split->tlpwin->bline=GR_BORDERLINE_BOTTOM;
495 split->brpwin->bline=GR_BORDERLINE_TOP;
497 split->ssplit.dir=dir;
500 if(dir==SPLIT_VERTICAL){
501 if(ng->h<=tlg.h+brg.h){
502 if(transpose){
503 ntlg.h=minof(tlg.w, ng->h*2/3);
504 nbrg.h=minof(brg.w, ng->h*2/3);
505 adjust_size(&ntlg.h, dir, split, split->ssplit.tl);
506 adjust_size(&nbrg.h, dir, split, split->ssplit.br);
507 adjust=(ng->h>ntlg.h+nbrg.h);
508 }else{
509 ntlg.h=minof(ng->h, tlg.h);
510 nbrg.h=minof(ng->h, brg.h);
511 adjust=FALSE;
513 }else{
514 ntlg.h=tlg.h;
515 nbrg.h=brg.h;
518 if(adjust){
519 adjust_sizes(&ntlg.h, &nbrg.h, ng->h,
520 splitfloat_get_min(split, dir, split->ssplit.tl),
521 splitfloat_get_min(split, dir, split->ssplit.br),
522 splitfloat_get_max(split, dir, split->ssplit.tl),
523 splitfloat_get_max(split, dir, split->ssplit.br),
524 vprimn);
527 nbrg.y=ng->y+ng->h-nbrg.h;
528 }else{
529 if(ng->w<=tlg.w+brg.w){
530 if(transpose){
531 ntlg.w=minof(tlg.h, ng->w*2/3);
532 nbrg.w=minof(brg.h, ng->w*2/3);
533 adjust_size(&ntlg.w, dir, split, split->ssplit.tl);
534 adjust_size(&nbrg.w, dir, split, split->ssplit.br);
535 adjust=(ng->w>ntlg.w+nbrg.w);
536 }else{
537 ntlg.w=minof(ng->w, tlg.w);
538 nbrg.w=minof(ng->w, brg.w);
539 adjust=FALSE;
541 }else{
542 ntlg.w=tlg.w;
543 nbrg.w=brg.w;
546 if(adjust){
547 adjust_sizes(&ntlg.w, &nbrg.w, ng->w,
548 splitfloat_get_min(split, dir, split->ssplit.tl),
549 splitfloat_get_min(split, dir, split->ssplit.br),
550 splitfloat_get_max(split, dir, split->ssplit.tl),
551 splitfloat_get_max(split, dir, split->ssplit.br),
552 hprimn);
555 nbrg.x=ng->x+ng->w-nbrg.w;
558 GEOM(split)=*ng;
560 splitfloat_update_handles(split, &ntlg, &nbrg);
562 splitfloat_tl_pwin_to_cnt(split, &ntlg);
563 split_do_resize(split->ssplit.tl, &ntlg, hprimn, vprimn, transpose);
564 splitfloat_br_pwin_to_cnt(split, &nbrg);
565 split_do_resize(split->ssplit.br, &nbrg, hprimn, vprimn, transpose);
569 static void calc_amount(int *amount, int *oamount,
570 int rs, WSplitSplit *p, int omax,
571 const WRectangle *ng, const WRectangle *og)
573 *oamount=0;
575 if(rs>=0){
576 if(p->dir==SPLIT_VERTICAL)
577 *amount=maxof(0, minof(rs, GEOM(p).h-ng->h));
578 else
579 *amount=maxof(0, minof(rs, GEOM(p).w-ng->w));
580 }else{
581 if(p->dir==SPLIT_VERTICAL){
582 int overlap=maxof(0, og->h-(GEOM(p).h-ng->h));
583 *amount=-minof(-rs, overlap);
584 *oamount=maxof(0, minof(*amount-rs, omax-og->h));
585 *amount-=*oamount;
586 }else{
587 int overlap=maxof(0, og->w-(GEOM(p).w-ng->w));
588 *amount=-minof(-rs, overlap);
589 *oamount=maxof(0, minof(*amount-rs, omax-og->w));
590 *amount-=*oamount;
596 static void splitfloat_do_rqsize(WSplitFloat *split, WSplit *node,
597 RootwardAmount *ha, RootwardAmount *va,
598 WRectangle *rg, bool tryonly)
600 int hprimn=PRIMN_ANY, vprimn=PRIMN_ANY;
601 WRectangle pg, og, ng, nog, nng;
602 RootwardAmount *ca;
603 WSplit *other;
604 int amount=0, oamount=0, omax;
605 int thisnode;
606 WSplitSplit *p=&(split->ssplit);
608 assert(!ha->any || ha->tl==0);
609 assert(!va->any || va->tl==0);
610 assert(p->tl==node || p->br==node);
612 if(p->tl==node){
613 other=p->br;
614 thisnode=PRIMN_TL;
615 }else{
616 other=p->tl;
617 thisnode=PRIMN_BR;
620 ng=GEOM(node);
621 og=GEOM(other);
623 if(thisnode==PRIMN_TL){
624 splitfloat_tl_cnt_to_pwin(split, &ng);
625 splitfloat_br_cnt_to_pwin(split, &og);
626 }else{
627 splitfloat_br_cnt_to_pwin(split, &ng);
628 splitfloat_tl_cnt_to_pwin(split, &og);
631 ca=(p->dir==SPLIT_VERTICAL ? va : ha);
633 omax=splitfloat_get_max(split, p->dir, other);
635 if(thisnode==PRIMN_TL || ca->any){
636 calc_amount(&amount, &oamount, ca->br, p, omax, &ng, &og);
637 ca->br-=amount;
638 }else/*if(thisnode==PRIMN_BR)*/{
639 calc_amount(&amount, &oamount, ca->tl, p, omax, &ng, &og);
640 ca->tl-=amount;
643 if(((WSplit*)p)->parent==NULL /*||
644 (ha->tl==0 && ha->br==0 && va->tl==0 && va->br==0)*/){
645 pg=((WSplit*)p)->geom;
646 }else{
647 splitinner_do_rqsize(((WSplit*)p)->parent, (WSplit*)p, ha, va,
648 &pg, tryonly);
651 assert(pg.w>=0 && pg.h>=0);
653 nog=pg;
654 nng=pg;
656 if(p->dir==SPLIT_VERTICAL){
657 nog.h=minof(pg.h, maxof(0, og.h+oamount));
658 nng.h=minof(pg.h, maxof(0, ng.h+amount+pg.h-GEOM(p).h));
659 if(thisnode==PRIMN_TL)
660 nog.y=pg.y+pg.h-nog.h;
661 else
662 nng.y=pg.y+pg.h-nng.h;
663 vprimn=thisnode;
664 }else{
665 nog.w=minof(pg.w, maxof(0, og.w+oamount));
666 nng.w=minof(pg.w, maxof(0, ng.w+amount+pg.w-GEOM(p).w));
667 if(thisnode==PRIMN_TL)
668 nog.x=pg.x+pg.w-nog.w;
669 else
670 nng.x=pg.x+pg.w-nng.w;
671 hprimn=thisnode;
674 if(!tryonly){
675 GEOM(p)=pg;
677 if(thisnode==PRIMN_TL){
678 splitfloat_update_handles(split, &nng, &nog);
679 splitfloat_br_pwin_to_cnt(split, &nog);
680 }else{
681 splitfloat_update_handles(split, &nog, &nng);
682 splitfloat_tl_pwin_to_cnt(split, &nog);
685 /* Entä jos 'other' on stdisp? */
686 split_do_resize(other, &nog, hprimn, vprimn, FALSE);
689 *rg=nng;
690 if(thisnode==PRIMN_TL)
691 splitfloat_tl_pwin_to_cnt(split, rg);
692 else
693 splitfloat_br_pwin_to_cnt(split, rg);
697 void splitfloat_flip(WSplitFloat *split)
699 WRectangle tlg, brg;
701 splitsplit_flip_default(&split->ssplit);
703 tlg=split->ssplit.tl->geom;
704 brg=split->ssplit.br->geom;
706 splitfloat_tl_cnt_to_pwin(split, &tlg);
707 splitfloat_br_cnt_to_pwin(split, &brg);
708 splitfloat_update_handles(split, &tlg, &brg);
712 /*}}}*/
715 /*{{{ Loading code */
718 #define MINS 8
720 static void adjust_tls_brs(int *tls, int *brs, int total)
722 if(*tls<=0)
723 *tls=MINS;
724 if(*brs<=0)
725 *brs=MINS;
727 if(*tls+*brs<total){
728 *tls=total*(*tls)/(*tls+*brs);
729 *brs=total-(*tls);
732 *tls=minof(maxof(MINS, *tls), total);
733 *brs=minof(maxof(MINS, *brs), total);
737 static void calc_tlg_brg(const WRectangle *geom, int tls, int brs, int dir,
738 WRectangle *tlg, WRectangle *brg)
740 *tlg=*geom;
741 *brg=*geom;
743 if(dir==SPLIT_HORIZONTAL){
744 adjust_tls_brs(&tls, &brs, geom->w);
745 tlg->w=tls;
746 brg->w=brs;
747 brg->x=geom->x+geom->w-brs;
748 }else{
749 adjust_tls_brs(&tls, &brs, geom->h);
750 tlg->h=tls;
751 brg->h=brs;
752 brg->y=geom->y+geom->h-brs;
757 WSplit *load_splitfloat(WTiling *ws, const WRectangle *geom, ExtlTab tab)
759 WSplit *tl=NULL, *br=NULL;
760 WSplitFloat *split;
761 char *dir_str;
762 int dir, brs, tls;
763 ExtlTab subtab;
764 WRectangle tlg, brg;
765 int set=0;
767 set+=(extl_table_gets_i(tab, "tls", &tls)==TRUE);
768 set+=(extl_table_gets_i(tab, "brs", &brs)==TRUE);
769 set+=(extl_table_gets_s(tab, "dir", &dir_str)==TRUE);
771 if(set!=3)
772 return NULL;
774 if(strcmp(dir_str, "vertical")==0){
775 dir=SPLIT_VERTICAL;
776 }else if(strcmp(dir_str, "horizontal")==0){
777 dir=SPLIT_HORIZONTAL;
778 }else{
779 warn(TR("Invalid direction."));
780 free(dir_str);
781 return NULL;
783 free(dir_str);
785 split=create_splitfloat(geom, ws, dir);
786 if(split==NULL)
787 return NULL;
789 if(!extl_table_is_bool_set(tab, "tls_brs_incl_handles")){
790 if(split->ssplit.dir==SPLIT_HORIZONTAL){
791 tls+=split->tlpwin->bdw.right;
792 brs+=split->brpwin->bdw.left;
793 }else{
794 tls+=split->tlpwin->bdw.bottom;
795 brs+=split->brpwin->bdw.top;
799 calc_tlg_brg(geom, tls, brs, dir, &tlg, &brg);
801 splitfloat_update_handles(split, &tlg, &brg);
803 if(extl_table_gets_t(tab, "tl", &subtab)){
804 WRectangle g=tlg;
805 splitfloat_tl_pwin_to_cnt(split, &g);
806 tl=tiling_load_node(ws, &g, subtab);
807 extl_unref_table(subtab);
810 if(extl_table_gets_t(tab, "br", &subtab)){
811 WRectangle g;
812 if(tl==NULL){
813 g=*geom;
814 }else{
815 g=brg;
816 splitfloat_br_pwin_to_cnt(split, &g);
818 br=tiling_load_node(ws, &g, subtab);
819 extl_unref_table(subtab);
822 if(tl==NULL || br==NULL){
823 destroy_obj((Obj*)split);
824 if(tl!=NULL){
825 split_do_resize(tl, geom, PRIMN_ANY, PRIMN_ANY, FALSE);
826 return tl;
828 if(br!=NULL){
829 split_do_resize(br, geom, PRIMN_ANY, PRIMN_ANY, FALSE);
830 return br;
832 return NULL;
835 tl->parent=(WSplitInner*)split;
836 br->parent=(WSplitInner*)split;
838 split->ssplit.tl=tl;
839 split->ssplit.br=br;
841 return (WSplit*)split;
845 /*}}}*/
848 /*{{{ Split */
851 WSplitRegion *splittree_split_floating(WSplit *node, int dir, int primn,
852 int nmins, WRegionSimpleCreateFn *fn,
853 WTiling *ws)
855 WSplitFloat *sf;
856 int omins, mins;
857 int sn, so, s, rs;
858 int bn, bo;
859 WRectangle gn, go, gnc, goc;
860 WFitParams fp;
861 WRegion *nreg;
862 WSplitRegion *nnode;
863 WSplitInner *psplit;
865 if(primn!=PRIMN_TL && primn!=PRIMN_BR)
866 primn=PRIMN_BR;
868 split_update_bounds(split_find_root(node), TRUE);
870 sf=create_splitfloat(&node->geom, ws, dir);
872 if(sf==NULL)
873 return NULL;
875 omins=(dir==SPLIT_VERTICAL ? node->min_h : node->min_w);
876 s=split_size(node, dir);
878 if(primn==PRIMN_BR){
879 bn=BR_BORDER(sf);
880 bo=TL_BORDER(sf);
881 }else{
882 bn=TL_BORDER(sf);
883 bo=BR_BORDER(sf);
886 mins=maxof(omins+bo, nmins+bn);
888 /* Potentially resize old node. */
890 splittree_begin_resize();
892 if(mins>s){
893 WRectangle ng=node->geom, rg;
894 if(dir==SPLIT_VERTICAL)
895 ng.h=mins;
896 else
897 ng.w=mins;
899 split_do_rqgeom_(node, &ng, TRUE, TRUE, &rg, TRUE);
900 rs=(dir==SPLIT_VERTICAL ? rg.h : rg.w);
901 if(rs<mins){
902 warn(TR("Unable to split: not enough free space."));
903 destroy_obj((Obj*)sf);
904 return NULL;
906 split_do_rqgeom_(node, &ng, TRUE, TRUE, &rg, FALSE);
907 s=split_size(node, dir);
908 }else{
909 splittree_scan_stdisp_rootward(node);
912 /* Calculate geometries. */
914 sn=maxof(nmins+bn, s/2);
915 so=maxof(omins+bo, s-s/2);
917 ((WSplit*)sf)->geom=node->geom;
919 if(primn==PRIMN_TL){
920 calc_tlg_brg(&(node->geom), sn, so, dir, &gn, &go);
921 splitfloat_update_handles(sf, &gn, &go);
922 gnc=gn; splitfloat_tl_pwin_to_cnt(sf, &gnc);
923 goc=go; splitfloat_br_pwin_to_cnt(sf, &goc);
924 }else{
925 calc_tlg_brg(&(node->geom), so, sn, dir, &go, &gn);
926 splitfloat_update_handles(sf, &go, &gn);
927 goc=go; splitfloat_tl_pwin_to_cnt(sf, &goc);
928 gnc=gn; splitfloat_br_pwin_to_cnt(sf, &gnc);
931 /* Create the region. */
933 fp.mode=REGION_FIT_EXACT;
934 fp.g=gnc;
936 nreg=fn(REGION_PARENT(ws), &fp);
938 if(nreg==NULL){
939 destroy_obj((Obj*)sf);
940 return NULL;
943 nnode=create_splitregion(&(fp.g), nreg);
944 if(nnode==NULL){
945 destroy_obj((Obj*)nreg);
946 destroy_obj((Obj*)sf);
947 return NULL;
950 /* Now that everything's ok, resize and move original node. */
952 split_do_resize(node, &goc,
953 (dir==SPLIT_HORIZONTAL ? primn : PRIMN_ANY),
954 (dir==SPLIT_VERTICAL ? primn : PRIMN_ANY),
955 FALSE);
957 /* Set up split structure. */
959 psplit=node->parent;
961 if(psplit!=NULL)
962 splitinner_replace(psplit, node, (WSplit*)sf);
963 else
964 splittree_changeroot(node, (WSplit*)sf);
966 node->parent=(WSplitInner*)sf;
967 ((WSplit*)nnode)->parent=(WSplitInner*)sf;
969 if(primn==PRIMN_BR){
970 sf->ssplit.tl=node;
971 sf->ssplit.br=(WSplit*)nnode;
972 }else{
973 sf->ssplit.tl=(WSplit*)nnode;
974 sf->ssplit.br=node;
977 /*splittree_end_resize();*/
979 return nnode;
983 /*}}}*/
986 /*{{{ The class */
989 static DynFunTab splitfloat_dynfuntab[]={
990 {split_update_bounds, splitfloat_update_bounds},
991 {split_do_resize, splitfloat_do_resize},
992 {splitinner_do_rqsize, splitfloat_do_rqsize},
993 {split_stacking, splitfloat_stacking},
994 {split_restack, splitfloat_restack},
995 {split_reparent, splitfloat_reparent},
996 {split_map, splitfloat_map},
997 {split_unmap, splitfloat_unmap},
998 {splitsplit_flip, splitfloat_flip},
999 END_DYNFUNTAB,
1003 EXTL_EXPORT
1004 IMPLCLASS(WSplitFloat, WSplitSplit, splitfloat_deinit, splitfloat_dynfuntab);
1007 /*}}}*/