X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=mod_tiling%2Ftiling.c;h=6fec3723b095675a06c429a934a2ce056375f7a6;hb=ae4260bb64817c11f9a7140324cd3e3ba113e297;hp=2ab56b01c11cddc2cbadac90b71b66eb29d45738;hpb=8366314611bf30a0f31d25bf5f5023186fa87692;p=ion3.git diff --git a/mod_tiling/tiling.c b/mod_tiling/tiling.c index 2ab56b0..6fec372 100644 --- a/mod_tiling/tiling.c +++ b/mod_tiling/tiling.c @@ -1,12 +1,9 @@ /* * ion/mod_tiling/tiling.c * - * Copyright (c) Tuomo Valkonen 1999-2006. + * Copyright (c) Tuomo Valkonen 1999-2007. * - * 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 @@ -48,10 +45,6 @@ static WTilingIterTmp tiling_iter_default_tmp; /*{{{ Some helper routines */ -#define STDISP_OF(WS) \ - ((WS)->stdispnode!=NULL ? (WS)->stdispnode->regnode.reg : NULL) - - static WSplitRegion *get_node_check(WTiling *ws, WRegion *reg) { WSplitRegion *node; @@ -266,32 +259,6 @@ Window tiling_xwindow(const WTiling *ws) } -/* -WRegion *tiling_rqclose_propagate(WTiling *ws, WRegion *maybe_sub) -{ - return (region_rqclose((WRegion*)ws, FALSE) ? (WRegion*)ws : NULL); -} -*/ - -WPHolder *tiling_prepare_manage_transient(WTiling *ws, - const WClientWin *transient, - const WManageParams *param, - int unused) -{ - /* Transient manager searches should not cross tilings unless - * explicitly floated. - */ - if(extl_table_is_bool_set(transient->proptab, "float")){ - return region_prepare_manage_transient_default((WRegion*)ws, - transient, - param, - unused); - }else{ - return NULL; - } -} - - /*}}}*/ @@ -500,7 +467,7 @@ bool tiling_managed_add_default(WTiling *ws, WRegion *reg) Window bottom=None, top=None; WFrame *frame; - if(STDISP_OF(ws)!=reg){ + if(TILING_STDISP_OF(ws)!=reg){ if(!ptrlist_insert_last(&(ws->managed_list), reg)) return FALSE; } @@ -535,30 +502,25 @@ bool tiling_managed_add(WTiling *ws, WRegion *reg) } -static WRegion *create_initial_frame(WTiling *ws, WWindow *parent, - const WFitParams *fp) +bool tiling_do_attach_initial(WTiling *ws, WRegion *reg) { - WRegion *reg=ws->create_frame_fn(parent, fp); - - if(reg==NULL) - return NULL; + assert(ws->split_tree==NULL); + + ws->split_tree=(WSplit*)create_splitregion(®ION_GEOM(reg), reg); + if(ws->split_tree==NULL) + return FALSE; - ws->split_tree=(WSplit*)create_splitregion(&(fp->g), reg); - if(ws->split_tree==NULL){ - destroy_obj((Obj*)reg); - return NULL; - } ws->split_tree->ws_if_root=ws; if(!tiling_managed_add(ws, reg)){ - destroy_obj((Obj*)reg); destroy_obj((Obj*)ws->split_tree); - return NULL; + ws->split_tree=NULL; + return FALSE; } - - return reg; + + return TRUE; } - + static WRegion *create_frame_tiling(WWindow *parent, const WFitParams *fp) { @@ -575,7 +537,8 @@ bool tiling_init(WTiling *ws, WWindow *parent, const WFitParams *fp, : create_frame_tiling); ws->stdispnode=NULL; ws->managed_list=NULL; - + ws->batchop=FALSE; + ws->dummywin=XCreateWindow(ioncore_g.dpy, parent->win, fp->g.x, fp->g.y, 1, 1, 0, CopyFromParent, InputOnly, @@ -589,7 +552,18 @@ bool tiling_init(WTiling *ws, WWindow *parent, const WFitParams *fp, REGION_PLEASE_WARP); if(ci){ - if(create_initial_frame(ws, parent, fp)==NULL){ + WRegionAttachData data; + WRegion *res; + + data.type=REGION_ATTACH_NEW; + data.u.n.fn=(WRegionCreateFn*)ws->create_frame_fn; + data.u.n.param=NULL; + + res=region_attach_helper((WRegion*)ws, parent, fp, + (WRegionDoAttachFn*)tiling_do_attach_initial, + NULL, &data); + + if(res==NULL){ XDestroyWindow(ioncore_g.dpy, ws->dummywin); return FALSE; } @@ -648,44 +622,30 @@ void tiling_deinit(WTiling *ws) } -bool tiling_managed_may_destroy(WTiling *ws, WRegion *reg) +WRegion *tiling_managed_disposeroot(WTiling *ws, WRegion *reg) { WTilingIterTmp tmp; WRegion *mgd; - - FOR_ALL_MANAGED_BY_TILING(mgd, ws, tmp){ - if(mgd!=STDISP_OF(ws) && mgd!=reg){ - return TRUE; - } - } - return region_manager_allows_destroying((WRegion*)ws); -} - - -bool tiling_may_destroy(WTiling *ws, WRegion *reg) -{ - WTilingIterTmp tmp; - WRegion *mgd; + if(ws->batchop) + return reg; FOR_ALL_MANAGED_BY_TILING(mgd, ws, tmp){ - if(mgd!=STDISP_OF(ws)){ - warn(TR("Workspace not empty - refusing to destroy.")); - return FALSE; - } + if(mgd!=TILING_STDISP_OF(ws) && mgd!=reg) + return reg; } - return TRUE; + return region_disposeroot((WRegion*)ws); } -bool tiling_rescue_clientwins(WTiling *ws, WPHolder *ph) +bool tiling_rescue_clientwins(WTiling *ws, WRescueInfo *info) { WTilingIterTmp tmp; ptrlist_iter_init(&tmp, ws->managed_list); - return region_rescue_some_clientwins((WRegion*)ws, ph, + return region_rescue_some_clientwins((WRegion*)ws, info, (WRegionIterator*)ptrlist_iter, &tmp); } @@ -693,7 +653,7 @@ bool tiling_rescue_clientwins(WTiling *ws, WPHolder *ph) void tiling_do_managed_remove(WTiling *ws, WRegion *reg) { - if(STDISP_OF(ws)==reg){ + if(TILING_STDISP_OF(ws)==reg){ ws->stdispnode->regnode.reg=NULL; }else{ ptrlist_remove(&(ws->managed_list), reg); @@ -711,30 +671,49 @@ static bool nostdispfilter(WSplit *node) void tiling_managed_remove(WTiling *ws, WRegion *reg) { - bool ds=OBJ_IS_BEING_DESTROYED(ws); bool act=REGION_IS_ACTIVE(reg); bool mcf=region_may_control_focus((WRegion*)ws); WSplitRegion *node=get_node_check(ws, reg); - WRegion *other; + bool norestore=(OBJ_IS_BEING_DESTROYED(ws) || ws->batchop); + WRegion *other=NULL; - other=tiling_do_navi_next(ws, reg, REGION_NAVI_ANY, TRUE, FALSE); + if(!norestore) + other=tiling_do_navi_next(ws, reg, REGION_NAVI_ANY, TRUE, FALSE); tiling_do_managed_remove(ws, reg); if(node==(WSplitRegion*)(ws->stdispnode)) ws->stdispnode=NULL; - if(node==NULL) - return; - - splittree_remove((WSplit*)node, (!ds && other!=NULL)); - - if(!ds){ - if(other==NULL) - mainloop_defer_destroy((Obj*)ws); - else if(act && mcf) - region_warp(other); + if(node!=NULL){ + bool reused=FALSE; + + if(other==NULL && !norestore){ + WWindow *par=REGION_PARENT(ws); + WFitParams fp; + + assert(par!=NULL); + + fp.g=node->split.geom; + fp.mode=REGION_FIT_EXACT; + + other=(ws->create_frame_fn)(par, &fp); + + if(other!=NULL){ + node->reg=other; + tiling_managed_add(ws, other); + reused=TRUE; + }else{ + warn(TR("Tiling in useless state.")); + } + } + + if(!reused) + splittree_remove((WSplit*)node, (!norestore && other!=NULL)); } + + if(!norestore && other!=NULL && act && mcf) + region_warp(other); } @@ -1020,9 +999,10 @@ static WFrame *tiling_do_split(WTiling *ws, WSplit *node, /*EXTL_DOC - * Create a new frame on \var{ws} above/below/left of/right of - * \var{node} as indicated by \var{dirstr}. If \var{dirstr} is - * prefixed with ''floating:'' a floating split is created. + * Create a new frame on \var{ws} \codestr{above}, \codestr{below} + * \codestr{left} of, or \codestr{right} of \var{node} as indicated + * by \var{dirstr}. If \var{dirstr} is prefixed with + * \codestr{floating:} a floating split is created. */ EXTL_EXPORT_MEMBER WFrame *tiling_split(WTiling *ws, WSplit *node, const char *dirstr) @@ -1048,11 +1028,12 @@ WFrame *tiling_split_top(WTiling *ws, const char *dirstr) /*EXTL_DOC * Split \var{frame} creating a new frame to direction \var{dirstr} - * (one of ''left'', ''right'', ''top'' or ''bottom'') of \var{frame}. + * (one of \codestr{left}, \codestr{right}, \codestr{top} or + * \codestr{bottom}) of \var{frame}. * If \var{attach_current} is set, the region currently displayed in * \var{frame}, if any, is moved to thenew frame. - * If \var{dirstr} is prefixed with ''floating:'' a floating split is - * created. + * If \var{dirstr} is prefixed with \codestr{floating:}, a floating + * split is created. */ EXTL_EXPORT_MEMBER WFrame *tiling_split_at(WTiling *ws, WFrame *frame, const char *dirstr, @@ -1086,24 +1067,45 @@ WFrame *tiling_split_at(WTiling *ws, WFrame *frame, const char *dirstr, } -/*EXTL_DOC - * Try to relocate regions managed by \var{frame} to another frame - * and, if possible, destroy the frame. - */ -EXTL_EXPORT_MEMBER -bool tiling_unsplit_at(WTiling *ws, WFrame *frame) +void do_unsplit(WRegion *reg) { - if(frame==NULL){ - warn(TR("Nil frame.")); - return FALSE; + WTiling *ws=REGION_MANAGER_CHK(reg, WTiling); + WPHolder *ph; + bool res; + + if(ws==NULL) + return; + + ph=region_get_rescue_pholder_for((WRegion*)ws, reg); + + if(ph==NULL){ + res=!region_rescue_needed(reg); + }else{ + res=region_rescue(reg, ph); + destroy_obj((Obj*)ph); } - if(REGION_MANAGER(frame)!=(WRegion*)ws){ - warn(TR("The frame is not managed by the workspace.")); - return FALSE; + if(!res){ + warn(TR("Unable to unsplit: Could not move client windows " + "elsewhere within the tiling.")); + return; } - return region_rqclose((WRegion*)frame, TRUE); + destroy_obj((Obj*)reg); +} + + +/*EXTL_DOC + * Try to relocate regions managed by \var{reg} to another frame + * and, if possible, destroy it. + */ +EXTL_EXPORT_MEMBER +void tiling_unsplit_at(WTiling *ws, WRegion *reg) +{ + if(reg==NULL || REGION_MANAGER(reg)!=(WRegion*)ws) + return; + + mainloop_defer_action((Obj*)reg, (WDeferredAction*)do_unsplit); } @@ -1125,17 +1127,20 @@ WRegion *tiling_current(WTiling *ws) /*EXTL_DOC - * Returns a list of regions managed by the workspace (frames, mostly). + * Iterate over managed regions of \var{ws} until \var{iterfn} returns + * \code{false}. + * The function itself returns \code{true} if it reaches the end of list + * without this happening. */ EXTL_SAFE EXTL_EXPORT_MEMBER -ExtlTab tiling_managed_list(WTiling *ws) +bool tiling_managed_i(WTiling *ws, ExtlFn iterfn) { PtrListIterTmp tmp; ptrlist_iter_init(&tmp, ws->managed_list); - return extl_obj_iterable_to_table((ObjIterator*)ptrlist_iter, &tmp); + return extl_iter_objlist_(iterfn, (ObjIterator*)ptrlist_iter, &tmp); } @@ -1152,7 +1157,8 @@ WSplit *tiling_split_tree(WTiling *ws) /*EXTL_DOC * Return the most previously active region next to \var{reg} in - * direction \var{dirstr} (left/right/up/down). The region \var{reg} + * direction \var{dirstr} (\codestr{left}, \codestr{right}, \codestr{up}, + * or \codestr{down}). The region \var{reg} * must be managed by \var{ws}. If \var{any} is not set, the status display * is not considered. */ @@ -1173,8 +1179,8 @@ WRegion *tiling_nextto(WTiling *ws, WRegion *reg, const char *dirstr, /*EXTL_DOC * Return the most previously active region on \var{ws} with no * other regions next to it in direction \var{dirstr} - * (left/right/up/down). If \var{any} is not set, the status - * display is not considered. + * (\codestr{left}, \codestr{right}, \codestr{up}, or \codestr{down}). + * If \var{any} is not set, the status display is not considered. */ EXTL_SAFE EXTL_EXPORT_MEMBER @@ -1350,8 +1356,8 @@ WSplitSplit *tiling_set_floating(WTiling *ws, WSplitSplit *split, int sp) /*EXTL_DOC * Toggle floating of a split's sides at \var{split} as indicated by the - * parameter \var{how} (set/unset/toggle). A split of the appropriate is - * returned, if there was a change. + * parameter \var{how} (\codestr{set}, \codestr{unset}, or \codestr{toggle}). + * A split of the appropriate is returned, if there was a change. */ EXTL_EXPORT_AS(WTiling, set_floating) WSplitSplit *tiling_set_floating_extl(WTiling *ws, WSplitSplit *split, @@ -1365,9 +1371,10 @@ WSplitSplit *tiling_set_floating_extl(WTiling *ws, WSplitSplit *split, /*EXTL_DOC * Toggle floating of the sides of a split containin \var{reg} as indicated - * by the parameters \var{how} (set/unset/toggle) and \var{dirstr} - * (left/right/up/down/any). The new status is returned (and \code{false} - * also on error). + * by the parameters \var{how} (\codestr{set}, \codestr{unset}, or + * \codestr{toggle}) and \var{dirstr} (\codestr{left}, \codestr{right}, + * \codestr{up}, or \codestr{down}). The new status is returned + * (and \code{false} also on error). */ EXTL_EXPORT_AS(WTiling, set_floating_at) bool tiling_set_floating_at_extl(WTiling *ws, WRegion *reg, const char *how, @@ -1713,11 +1720,8 @@ static DynFunTab tiling_dynfuntab[]={ {(DynFun*)region_get_configuration, (DynFun*)tiling_get_configuration}, - {(DynFun*)region_managed_may_destroy, - (DynFun*)tiling_managed_may_destroy}, - - {(DynFun*)region_may_destroy, - (DynFun*)tiling_may_destroy}, + {(DynFun*)region_managed_disposeroot, + (DynFun*)tiling_managed_disposeroot}, {(DynFun*)region_current, (DynFun*)tiling_current}, @@ -1749,9 +1753,6 @@ static DynFunTab tiling_dynfuntab[]={ {(DynFun*)region_xwindow, (DynFun*)tiling_xwindow}, - {(DynFun*)region_prepare_manage_transient, - (DynFun*)tiling_prepare_manage_transient}, - END_DYNFUNTAB };