2 * ion/mod_tiling/splitext.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
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>
21 #include "splitfloat.h"
22 #include "panehandle.h"
25 #define GEOM(X) (((WSplit*)(X))->geom)
31 static void splitfloat_set_borderlines(WSplitFloat
*split
)
33 int dir
=split
->ssplit
.dir
;
35 split
->tlpwin
->bline
=(dir
==SPLIT_HORIZONTAL
37 : GR_BORDERLINE_BOTTOM
);
39 split
->brpwin
->bline
=(dir
==SPLIT_HORIZONTAL
45 bool splitfloat_init(WSplitFloat
*split
, const WRectangle
*geom
,
49 WWindow
*par
=REGION_PARENT(ws
);
54 fp
.mode
=REGION_FIT_EXACT
;
55 split
->tlpwin
=create_panehandle(par
, &fp
);
56 if(split
->tlpwin
==NULL
)
60 fp
.mode
=REGION_FIT_EXACT
;
61 split
->brpwin
=create_panehandle(par
, &fp
);
62 if(split
->brpwin
==NULL
){
63 destroy_obj((Obj
*)split
->tlpwin
);
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
);
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
));
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
;
101 tmp
->splitfloat
=NULL
;
102 destroy_obj((Obj
*)tmp
);
105 if(split
->brpwin
!=NULL
){
106 WPaneHandle
*tmp
=split
->brpwin
;
108 tmp
->splitfloat
=NULL
;
109 destroy_obj((Obj
*)tmp
);
112 splitsplit_deinit(&(split
->ssplit
));
119 /*{{{ X window handling */
122 static void stack_stacking_reg(WRegion
*reg
,
123 Window
*bottomret
, Window
*topret
)
125 Window b
=None
, t
=None
;
128 region_stacking(reg
, &b
, &t
);
137 static void stack_stacking_split(WSplit
*split
,
138 Window
*bottomret
, Window
*topret
)
140 Window b
=None
, t
=None
;
143 split_stacking(split
, &b
, &t
);
152 static void splitfloat_stacking(WSplitFloat
*split
,
153 Window
*bottomret
, Window
*topret
)
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
);
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
;
177 region_restack(reg
, *other
, *mode
);
178 region_stacking(reg
, &b
, &t
);
187 static void stack_restack_split(WSplit
*split
, Window
*other
, int *mode
)
189 Window b
=None
, t
=None
;
192 split_restack(split
, *other
, *mode
);
193 split_stacking(split
, &b
, &t
);
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
);
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
);
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
);
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
);
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
);
289 int delta
=split
->tlpwin
->bdw
.top
;
290 g
->h
=maxof(1, g
->h
-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
);
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
);
312 int delta
=split
->tlpwin
->bdw
.top
;
313 g
->h
=maxof(1, g
->h
+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
,
328 assert(other
==split
->ssplit
.tl
|| other
==split
->ssplit
.br
);
330 if(dir
!=split
->ssplit
.dir
)
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
;
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
;
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
;
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
);
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
);
392 node
->max_h
=infadd(tl_max_h
, br_max_h
);
393 node
->min_h
=minof(tl_min_h
, br_min_h
);
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
;
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
)
431 static void adjust_sizes(int *tls_
, int *brs_
, int nsize
,
432 int tlmin
, int brmin
, int tlmax
, int brmax
,
435 int tls
=maxof(0, *tls_
);
436 int brs
=maxof(0, *brs_
);
437 nsize
=maxof(1, nsize
);
440 tls
=maxof(1, nsize
-brs
);
441 bound(&tls
, tlmin
, tlmax
);
443 bound(&brs
, brmin
, brmax
);
445 bound(&tls
, tlmin
, tlmax
);
446 }else if(primn
==PRIMN_BR
){
447 brs
=maxof(1, nsize
-tls
);
448 bound(&brs
, brmin
, brmax
);
450 bound(&tls
, tlmin
, tlmax
);
452 bound(&brs
, brmin
, brmax
);
453 }else{ /* && PRIMN_ANY */
454 tls
=tls
*nsize
/maxof(2, tls
+brs
);
455 bound(&tls
, tlmin
, tlmax
);
457 bound(&brs
, brmin
, brmax
);
459 bound(&tls
, tlmin
, tlmax
);
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 WRectangle
*og
=&((WSplit
*)split
)->geom
;
482 int dir
=split
->ssplit
.dir
;
485 splitfloat_tl_cnt_to_pwin(split
, &tlg
);
486 splitfloat_br_cnt_to_pwin(split
, &brg
);
489 if(dir
==SPLIT_VERTICAL
){
490 dir
=SPLIT_HORIZONTAL
;
491 split
->tlpwin
->bline
=GR_BORDERLINE_RIGHT
;
492 split
->brpwin
->bline
=GR_BORDERLINE_LEFT
;
495 split
->tlpwin
->bline
=GR_BORDERLINE_BOTTOM
;
496 split
->brpwin
->bline
=GR_BORDERLINE_TOP
;
498 split
->ssplit
.dir
=dir
;
501 if(dir
==SPLIT_VERTICAL
){
502 if(ng
->h
<=tlg
.h
+brg
.h
){
504 ntlg
.h
=minof(tlg
.w
, ng
->h
*2/3);
505 nbrg
.h
=minof(brg
.w
, ng
->h
*2/3);
506 adjust_size(&ntlg
.h
, dir
, split
, split
->ssplit
.tl
);
507 adjust_size(&nbrg
.h
, dir
, split
, split
->ssplit
.br
);
508 adjust
=(ng
->h
>ntlg
.h
+nbrg
.h
);
510 ntlg
.h
=minof(ng
->h
, tlg
.h
);
511 nbrg
.h
=minof(ng
->h
, brg
.h
);
520 adjust_sizes(&ntlg
.h
, &nbrg
.h
, ng
->h
,
521 splitfloat_get_min(split
, dir
, split
->ssplit
.tl
),
522 splitfloat_get_min(split
, dir
, split
->ssplit
.br
),
523 splitfloat_get_max(split
, dir
, split
->ssplit
.tl
),
524 splitfloat_get_max(split
, dir
, split
->ssplit
.br
),
528 nbrg
.y
=ng
->y
+ng
->h
-nbrg
.h
;
530 if(ng
->w
<=tlg
.w
+brg
.w
){
532 ntlg
.w
=minof(tlg
.h
, ng
->w
*2/3);
533 nbrg
.w
=minof(brg
.h
, ng
->w
*2/3);
534 adjust_size(&ntlg
.w
, dir
, split
, split
->ssplit
.tl
);
535 adjust_size(&nbrg
.w
, dir
, split
, split
->ssplit
.br
);
536 adjust
=(ng
->w
>ntlg
.w
+nbrg
.w
);
538 ntlg
.w
=minof(ng
->w
, tlg
.w
);
539 nbrg
.w
=minof(ng
->w
, brg
.w
);
548 adjust_sizes(&ntlg
.w
, &nbrg
.w
, ng
->w
,
549 splitfloat_get_min(split
, dir
, split
->ssplit
.tl
),
550 splitfloat_get_min(split
, dir
, split
->ssplit
.br
),
551 splitfloat_get_max(split
, dir
, split
->ssplit
.tl
),
552 splitfloat_get_max(split
, dir
, split
->ssplit
.br
),
556 nbrg
.x
=ng
->x
+ng
->w
-nbrg
.w
;
561 splitfloat_update_handles(split
, &ntlg
, &nbrg
);
563 splitfloat_tl_pwin_to_cnt(split
, &ntlg
);
564 split_do_resize(split
->ssplit
.tl
, &ntlg
, hprimn
, vprimn
, transpose
);
565 splitfloat_br_pwin_to_cnt(split
, &nbrg
);
566 split_do_resize(split
->ssplit
.br
, &nbrg
, hprimn
, vprimn
, transpose
);
570 static void calc_amount(int *amount
, int *oamount
,
571 int rs
, WSplitSplit
*p
, int omax
,
572 const WRectangle
*ng
, const WRectangle
*og
)
577 if(p
->dir
==SPLIT_VERTICAL
)
578 *amount
=maxof(0, minof(rs
, GEOM(p
).h
-ng
->h
));
580 *amount
=maxof(0, minof(rs
, GEOM(p
).w
-ng
->w
));
582 if(p
->dir
==SPLIT_VERTICAL
){
583 int overlap
=maxof(0, og
->h
-(GEOM(p
).h
-ng
->h
));
584 *amount
=-minof(-rs
, overlap
);
585 *oamount
=maxof(0, minof(*amount
-rs
, omax
-og
->h
));
588 int overlap
=maxof(0, og
->w
-(GEOM(p
).w
-ng
->w
));
589 *amount
=-minof(-rs
, overlap
);
590 *oamount
=maxof(0, minof(*amount
-rs
, omax
-og
->w
));
597 static void splitfloat_do_rqsize(WSplitFloat
*split
, WSplit
*node
,
598 RootwardAmount
*ha
, RootwardAmount
*va
,
599 WRectangle
*rg
, bool tryonly
)
601 int hprimn
=PRIMN_ANY
, vprimn
=PRIMN_ANY
;
602 WRectangle pg
, og
, ng
, nog
, nng
;
605 int amount
=0, oamount
=0, omax
;
607 WSplitSplit
*p
=&(split
->ssplit
);
609 assert(!ha
->any
|| ha
->tl
==0);
610 assert(!va
->any
|| va
->tl
==0);
611 assert(p
->tl
==node
|| p
->br
==node
);
624 if(thisnode
==PRIMN_TL
){
625 splitfloat_tl_cnt_to_pwin(split
, &ng
);
626 splitfloat_br_cnt_to_pwin(split
, &og
);
628 splitfloat_br_cnt_to_pwin(split
, &ng
);
629 splitfloat_tl_cnt_to_pwin(split
, &og
);
632 ca
=(p
->dir
==SPLIT_VERTICAL
? va
: ha
);
634 omax
=splitfloat_get_max(split
, p
->dir
, other
);
636 if(thisnode
==PRIMN_TL
|| ca
->any
){
637 calc_amount(&amount
, &oamount
, ca
->br
, p
, omax
, &ng
, &og
);
639 }else/*if(thisnode==PRIMN_BR)*/{
640 calc_amount(&amount
, &oamount
, ca
->tl
, p
, omax
, &ng
, &og
);
644 if(((WSplit
*)p
)->parent
==NULL
/*||
645 (ha->tl==0 && ha->br==0 && va->tl==0 && va->br==0)*/){
646 pg
=((WSplit
*)p
)->geom
;
648 splitinner_do_rqsize(((WSplit
*)p
)->parent
, (WSplit
*)p
, ha
, va
,
652 assert(pg
.w
>=0 && pg
.h
>=0);
657 if(p
->dir
==SPLIT_VERTICAL
){
658 nog
.h
=minof(pg
.h
, maxof(0, og
.h
+oamount
));
659 nng
.h
=minof(pg
.h
, maxof(0, ng
.h
+amount
+pg
.h
-GEOM(p
).h
));
660 if(thisnode
==PRIMN_TL
)
661 nog
.y
=pg
.y
+pg
.h
-nog
.h
;
663 nng
.y
=pg
.y
+pg
.h
-nng
.h
;
666 nog
.w
=minof(pg
.w
, maxof(0, og
.w
+oamount
));
667 nng
.w
=minof(pg
.w
, maxof(0, ng
.w
+amount
+pg
.w
-GEOM(p
).w
));
668 if(thisnode
==PRIMN_TL
)
669 nog
.x
=pg
.x
+pg
.w
-nog
.w
;
671 nng
.x
=pg
.x
+pg
.w
-nng
.w
;
678 if(thisnode
==PRIMN_TL
){
679 splitfloat_update_handles(split
, &nng
, &nog
);
680 splitfloat_br_pwin_to_cnt(split
, &nog
);
682 splitfloat_update_handles(split
, &nog
, &nng
);
683 splitfloat_tl_pwin_to_cnt(split
, &nog
);
686 /* Entä jos 'other' on stdisp? */
687 split_do_resize(other
, &nog
, hprimn
, vprimn
, FALSE
);
691 if(thisnode
==PRIMN_TL
)
692 splitfloat_tl_pwin_to_cnt(split
, rg
);
694 splitfloat_br_pwin_to_cnt(split
, rg
);
698 void splitfloat_flip(WSplitFloat
*split
)
702 splitsplit_flip_default(&split
->ssplit
);
704 tlg
=split
->ssplit
.tl
->geom
;
705 brg
=split
->ssplit
.br
->geom
;
707 splitfloat_tl_cnt_to_pwin(split
, &tlg
);
708 splitfloat_br_cnt_to_pwin(split
, &brg
);
709 splitfloat_update_handles(split
, &tlg
, &brg
);
716 /*{{{ Loading code */
721 static void adjust_tls_brs(int *tls
, int *brs
, int total
)
729 *tls
=total
*(*tls
)/(*tls
+*brs
);
733 *tls
=minof(maxof(MINS
, *tls
), total
);
734 *brs
=minof(maxof(MINS
, *brs
), total
);
738 static void calc_tlg_brg(const WRectangle
*geom
, int tls
, int brs
, int dir
,
739 WRectangle
*tlg
, WRectangle
*brg
)
744 if(dir
==SPLIT_HORIZONTAL
){
745 adjust_tls_brs(&tls
, &brs
, geom
->w
);
748 brg
->x
=geom
->x
+geom
->w
-brs
;
750 adjust_tls_brs(&tls
, &brs
, geom
->h
);
753 brg
->y
=geom
->y
+geom
->h
-brs
;
758 WSplit
*load_splitfloat(WTiling
*ws
, const WRectangle
*geom
, ExtlTab tab
)
760 WSplit
*tl
=NULL
, *br
=NULL
;
768 set
+=(extl_table_gets_i(tab
, "tls", &tls
)==TRUE
);
769 set
+=(extl_table_gets_i(tab
, "brs", &brs
)==TRUE
);
770 set
+=(extl_table_gets_s(tab
, "dir", &dir_str
)==TRUE
);
775 if(strcmp(dir_str
, "vertical")==0){
777 }else if(strcmp(dir_str
, "horizontal")==0){
778 dir
=SPLIT_HORIZONTAL
;
780 warn(TR("Invalid direction."));
786 split
=create_splitfloat(geom
, ws
, dir
);
790 if(!extl_table_is_bool_set(tab
, "tls_brs_incl_handles")){
791 if(split
->ssplit
.dir
==SPLIT_HORIZONTAL
){
792 tls
+=split
->tlpwin
->bdw
.right
;
793 brs
+=split
->brpwin
->bdw
.left
;
795 tls
+=split
->tlpwin
->bdw
.bottom
;
796 brs
+=split
->brpwin
->bdw
.top
;
800 calc_tlg_brg(geom
, tls
, brs
, dir
, &tlg
, &brg
);
802 splitfloat_update_handles(split
, &tlg
, &brg
);
804 if(extl_table_gets_t(tab
, "tl", &subtab
)){
806 splitfloat_tl_pwin_to_cnt(split
, &g
);
807 tl
=tiling_load_node(ws
, &g
, subtab
);
808 extl_unref_table(subtab
);
811 if(extl_table_gets_t(tab
, "br", &subtab
)){
817 splitfloat_br_pwin_to_cnt(split
, &g
);
819 br
=tiling_load_node(ws
, &g
, subtab
);
820 extl_unref_table(subtab
);
823 if(tl
==NULL
|| br
==NULL
){
824 destroy_obj((Obj
*)split
);
826 split_do_resize(tl
, geom
, PRIMN_ANY
, PRIMN_ANY
, FALSE
);
830 split_do_resize(br
, geom
, PRIMN_ANY
, PRIMN_ANY
, FALSE
);
836 tl
->parent
=(WSplitInner
*)split
;
837 br
->parent
=(WSplitInner
*)split
;
842 return (WSplit
*)split
;
852 WSplitRegion
*splittree_split_floating(WSplit
*node
, int dir
, int primn
,
853 int nmins
, WRegionSimpleCreateFn
*fn
,
860 WRectangle gn
, go
, gnc
, goc
;
866 if(primn
!=PRIMN_TL
&& primn
!=PRIMN_BR
)
869 split_update_bounds(split_find_root(node
), TRUE
);
871 sf
=create_splitfloat(&node
->geom
, ws
, dir
);
876 omins
=(dir
==SPLIT_VERTICAL
? node
->min_h
: node
->min_w
);
877 s
=split_size(node
, dir
);
887 mins
=maxof(omins
+bo
, nmins
+bn
);
889 /* Potentially resize old node. */
891 splittree_begin_resize();
894 WRectangle ng
=node
->geom
, rg
;
895 if(dir
==SPLIT_VERTICAL
)
900 split_do_rqgeom_(node
, &ng
, TRUE
, TRUE
, &rg
, TRUE
);
901 rs
=(dir
==SPLIT_VERTICAL
? rg
.h
: rg
.w
);
903 warn(TR("Unable to split: not enough free space."));
904 destroy_obj((Obj
*)sf
);
907 split_do_rqgeom_(node
, &ng
, TRUE
, TRUE
, &rg
, FALSE
);
908 s
=split_size(node
, dir
);
910 splittree_scan_stdisp_rootward(node
);
913 /* Calculate geometries. */
915 sn
=maxof(nmins
+bn
, s
/2);
916 so
=maxof(omins
+bo
, s
-s
/2);
918 ((WSplit
*)sf
)->geom
=node
->geom
;
921 calc_tlg_brg(&(node
->geom
), sn
, so
, dir
, &gn
, &go
);
922 splitfloat_update_handles(sf
, &gn
, &go
);
923 gnc
=gn
; splitfloat_tl_pwin_to_cnt(sf
, &gnc
);
924 goc
=go
; splitfloat_br_pwin_to_cnt(sf
, &goc
);
926 calc_tlg_brg(&(node
->geom
), so
, sn
, dir
, &go
, &gn
);
927 splitfloat_update_handles(sf
, &go
, &gn
);
928 goc
=go
; splitfloat_tl_pwin_to_cnt(sf
, &goc
);
929 gnc
=gn
; splitfloat_br_pwin_to_cnt(sf
, &gnc
);
932 /* Create the region. */
934 fp
.mode
=REGION_FIT_EXACT
;
937 nreg
=fn(REGION_PARENT(ws
), &fp
);
940 destroy_obj((Obj
*)sf
);
944 nnode
=create_splitregion(&(fp
.g
), nreg
);
946 destroy_obj((Obj
*)nreg
);
947 destroy_obj((Obj
*)sf
);
951 /* Now that everything's ok, resize and move original node. */
953 split_do_resize(node
, &goc
,
954 (dir
==SPLIT_HORIZONTAL
? primn
: PRIMN_ANY
),
955 (dir
==SPLIT_VERTICAL
? primn
: PRIMN_ANY
),
958 /* Set up split structure. */
963 splitinner_replace(psplit
, node
, (WSplit
*)sf
);
965 splittree_changeroot(node
, (WSplit
*)sf
);
967 node
->parent
=(WSplitInner
*)sf
;
968 ((WSplit
*)nnode
)->parent
=(WSplitInner
*)sf
;
972 sf
->ssplit
.br
=(WSplit
*)nnode
;
974 sf
->ssplit
.tl
=(WSplit
*)nnode
;
978 /*splittree_end_resize();*/
990 static DynFunTab splitfloat_dynfuntab
[]={
991 {split_update_bounds
, splitfloat_update_bounds
},
992 {split_do_resize
, splitfloat_do_resize
},
993 {splitinner_do_rqsize
, splitfloat_do_rqsize
},
994 {split_stacking
, splitfloat_stacking
},
995 {split_restack
, splitfloat_restack
},
996 {split_reparent
, splitfloat_reparent
},
997 {split_map
, splitfloat_map
},
998 {split_unmap
, splitfloat_unmap
},
999 {splitsplit_flip
, splitfloat_flip
},
1005 IMPLCLASS(WSplitFloat
, WSplitSplit
, splitfloat_deinit
, splitfloat_dynfuntab
);