X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=mod_tiling%2Fsplit.c;h=5e1abb47dcb9961145032f6210eb30cb95ae5f0c;hb=HEAD;hp=c3edc5e8bc3acff293ca12efe265cb858c4ada09;hpb=803afbc1cd633f6c025bcd9537e9b7e9aedadd0d;p=ion3.git diff --git a/mod_tiling/split.c b/mod_tiling/split.c index c3edc5e..5e1abb4 100644 --- a/mod_tiling/split.c +++ b/mod_tiling/split.c @@ -1,12 +1,9 @@ /* * ion/mod_tiling/split.c * - * Copyright (c) Tuomo Valkonen 1999-2007. + * Copyright (c) Tuomo Valkonen 1999-2009. * - * Ion is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. + * See the included file LICENSE for details. */ #include @@ -474,28 +471,28 @@ void splittree_scan_stdisp_rootward(WSplit *node) } -static WSplitSplit *splittree_scan_stdisp_parent(WSplit *node_, bool set_saw) +static WSplitST *splittree_scan_stdisp(WSplit *node_, bool set_saw) { - WSplitSplit *r, *node=OBJ_CAST(node_, WSplitSplit); + WSplitST *r=NULL; + WSplitSplit *node=OBJ_CAST(node_, WSplitSplit); if(node==NULL) return NULL; - if(OBJ_IS(node->tl, WSplitST)){ - if(set_saw) - saw_stdisp=(WSplitST*)node->tl; - return node; - } - - if(OBJ_IS(node->br, WSplitST)){ + r=OBJ_CAST(node->tl, WSplitST); + if(r==NULL) + r=OBJ_CAST(node->br, WSplitST); + + if(r!=NULL){ if(set_saw) - saw_stdisp=(WSplitST*)node->br; - return node; + saw_stdisp=r; + return r; } - - r=splittree_scan_stdisp_parent(node->tl, set_saw); + + r=splittree_scan_stdisp(node->tl, set_saw); if(r==NULL) - r=splittree_scan_stdisp_parent(node->br, set_saw); + r=splittree_scan_stdisp(node->br, set_saw); + return r; } @@ -507,26 +504,41 @@ static bool stdisp_immediate_child(WSplitSplit *node) } -static WSplit *move_stdisp_out_of_way(WSplit *node) +static WSplit *dodge_stdisp(WSplit *node, bool keep_within) { + WSplitST *stdisp; WSplitSplit *stdispp; - if(!OBJ_IS(node, WSplitSplit)) + stdisp=splittree_scan_stdisp(node, TRUE); + + if(stdisp==NULL) return node; - stdispp=splittree_scan_stdisp_parent(node, TRUE); - + stdispp=OBJ_CAST(((WSplit*)stdisp)->parent, WSplitSplit); + if(stdispp==NULL) return node; - - while(stdispp->tl!=node && stdispp->br!=node){ + + if((WSplit*)stdispp==node){ + /* Node itself immediately contains stdisp. Due to the way + * try_unsink works, stdisp this will not change, so another + * node must be used, if we want to fully dodge stdisp. + */ + return (keep_within + ? node + : (stdispp->tl==(WSplit*)stdisp + ? stdispp->br + : stdispp->tl)); + } + + do{ if(!split_try_unsink_stdisp(stdispp, FALSE, TRUE)){ warn(TR("Unable to move the status display out of way.")); return NULL; } - } + }while(stdispp->tl!=node && stdispp->br!=node); - return (WSplit*)stdispp; + return node; } @@ -1029,6 +1041,7 @@ err: void splittree_changeroot(WSplit *root, WSplit *node) { WTiling *ws=(WTiling*)(root->ws_if_root); + assert(ws!=NULL); assert(ws->split_tree==root); root->ws_if_root=NULL; @@ -1078,16 +1091,18 @@ WSplitRegion *splittree_split(WSplit *node, int dir, WPrimn primn, assert(node!=NULL && parent!=NULL); + splittree_begin_resize(); + + node=dodge_stdisp(node, FALSE); + + if(node==NULL) + return NULL; + if(OBJ_IS(node, WSplitST)){ warn(TR("Splitting the status display is not allowed.")); return NULL; } - splittree_begin_resize(); - - if(!move_stdisp_out_of_way(node)) - return NULL; - if(primn!=PRIMN_TL && primn!=PRIMN_BR) primn=PRIMN_BR; if(dir!=SPLIT_HORIZONTAL && dir!=SPLIT_VERTICAL) @@ -1219,13 +1234,23 @@ static void splitsplit_remove(WSplitSplit *node, WSplit *child, static int nstdisp=0; WSplitInner *parent; WSplit *other; + int hprimn=PRIMN_ANY, vprimn=PRIMN_ANY; assert(node->tl==child || node->br==child); - if(node->tl==child) + if(node->tl==child){ other=node->br; - else + if(node->dir==SPLIT_VERTICAL) + vprimn=PRIMN_TL; + else + hprimn=PRIMN_TL; + }else{ other=node->tl; + if(node->dir==SPLIT_VERTICAL) + vprimn=PRIMN_BR; + else + hprimn=PRIMN_BR; + } assert(other!=NULL); @@ -1247,7 +1272,7 @@ static void splitsplit_remove(WSplitSplit *node, WSplit *child, splittree_changeroot((WSplit*)node, other); if(reclaim_space) - split_resize(other, &(((WSplit*)node)->geom), PRIMN_ANY, PRIMN_ANY); + split_resize(other, &(((WSplit*)node)->geom), hprimn, vprimn); child->parent=NULL; @@ -1340,6 +1365,11 @@ WSplit *split_current_todir(WSplit *node, WPrimn hprimn, WPrimn vprimn, } +/* Note: both hprimn and vprimn are inverted when descending. Therefore + * one should be either PRIMN_NONE or PRIMN_ANY for sensible geometric + * navigation. (Both are PRIMN_TL or PRIMN_BR for pseudo-linear + * next/previous navigation.) + */ WSplit *splitsplit_nextto(WSplitSplit *node, WSplit *child, WPrimn hprimn, WPrimn vprimn, WSplitFilter *filter) @@ -1347,26 +1377,21 @@ WSplit *splitsplit_nextto(WSplitSplit *node, WSplit *child, WPrimn primn=(node->dir==SPLIT_HORIZONTAL ? hprimn : vprimn); WSplit *split=NULL, *nnode=NULL; - if(node->tl==child && (primn==PRIMN_BR || primn==PRIMN_ANY)){ + if(node->tl==child && (primn==PRIMN_BR || primn==PRIMN_ANY)) split=node->br; - primn=PRIMN_TL; - }else if(node->br==child && (primn==PRIMN_TL || primn==PRIMN_ANY)){ + else if(node->br==child && (primn==PRIMN_TL || primn==PRIMN_ANY)) split=node->tl; - primn=PRIMN_BR; - } if(split!=NULL){ - if(node->dir==SPLIT_HORIZONTAL){ - hprimn=primn; - vprimn=primn_none2any(vprimn); - }else{ - vprimn=primn; - hprimn=primn_none2any(vprimn); - } - - nnode=split_current_todir(split, hprimn, vprimn, filter); + nnode=split_current_todir(split, + primn_none2any(primn_invert(hprimn)), + primn_none2any(primn_invert(vprimn)), + filter); } - + + if(nnode==NULL) + nnode=split_nextto((WSplit*)node, hprimn, vprimn, filter); + return nnode; } @@ -1639,14 +1664,16 @@ static void splitsplit_flip_(WSplitSplit *split) /*EXTL_DOC - * Flip contents of \var{node}. + * Flip contents of \var{split}. */ EXTL_EXPORT_MEMBER void splitsplit_flip(WSplitSplit *split) { splittree_begin_resize(); - if(!move_stdisp_out_of_way((WSplit*)split)) + split=OBJ_CAST(dodge_stdisp((WSplit*)split, FALSE), WSplitSplit); + + if(split==NULL) return; splitsplit_flip_(split); @@ -1709,19 +1736,19 @@ static bool split_fliptrans_to(WSplit *node, const WRectangle *geom, * geometry calculation we move it immediately below node, and * resize stdisp's fixed parent node instead. */ - node2=move_stdisp_out_of_way(node); + node2=dodge_stdisp(node, TRUE); - if(node2==NULL) + if(node==NULL || node2!=node) return FALSE; - split_update_bounds(node2, TRUE); + split_update_bounds(node, TRUE); - split_do_rqgeom_(node2, geom, PRIMN_ANY, PRIMN_ANY, &rg, FALSE); + split_do_rqgeom_(node, geom, PRIMN_ANY, PRIMN_ANY, &rg, FALSE); - split_do_resize(node2, &rg, PRIMN_ANY, PRIMN_ANY, trans); + split_do_resize(node, &rg, PRIMN_ANY, PRIMN_ANY, trans); if(flip!=FLIP_NONE) - splittree_flip_dir(node2, flip); + splittree_flip_dir(node, flip); splittree_end_resize(); @@ -1817,8 +1844,8 @@ WSplit *splitsplit_br(WSplitSplit *split) } /*EXTL_DOC - * Returns the direction of \var{split}; either ''vertical'' or - * ''horizontal''. + * Returns the direction of \var{split}; either \codestr{vertical} or + * \codestr{horizontal}. */ EXTL_SAFE EXTL_EXPORT_MEMBER