X-Git-Url: https://git.decadent.org.uk/gitweb/?p=ion3.git;a=blobdiff_plain;f=ioncore%2Fgroup.c;h=3db079526e8ece8bbcb89b258207e12cd4bb7227;hp=591fcd757dd4f1a609f658a12de71d597f527f5c;hb=HEAD;hpb=8366314611bf30a0f31d25bf5f5023186fa87692 diff --git a/ioncore/group.c b/ioncore/group.c index 591fcd7..3db0795 100644 --- a/ioncore/group.c +++ b/ioncore/group.c @@ -1,12 +1,9 @@ /* * ion/ioncore/group.c * - * Copyright (c) Tuomo Valkonen 1999-2006. + * 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 @@ -40,11 +37,15 @@ #include "grouppholder.h" #include "frame.h" #include "float-placement.h" +#include "return.h" static void group_place_stdisp(WGroup *ws, WWindow *parent, int pos, WRegion *stdisp); +static void group_remanage_stdisp(WGroup *ws); + +static void group_do_set_bottom(WGroup *grp, WStacking *st); /*{{{ Stacking list stuff */ @@ -233,26 +234,9 @@ static WStacking *find_to_focus(WGroup *ws, WStacking *st, bool group_only) } -static bool group_refocus_(WGroup *ws, WStacking *st) -{ - if(st!=ws->current_managed && st->reg!=NULL){ - if(region_may_control_focus((WRegion*)ws)) - region_set_focus(st->reg); - else - ws->current_managed=st; - return TRUE; - } - - return FALSE; -} - - static void group_do_set_focus(WGroup *ws, bool warp) { - WStacking *st=ws->current_managed; - - if(st==NULL || st->reg==NULL) - st=find_to_focus(ws, NULL, TRUE); + WStacking *st=find_to_focus(ws, ws->current_managed, FALSE); if(st!=NULL && st->reg!=NULL) region_do_set_focus(st->reg, warp); @@ -279,19 +263,21 @@ static bool group_managed_prepare_focus(WGroup *ws, WRegion *reg, return mplex_do_prepare_focus(mplex, node, st, flags, res); }else{ - WStacking *stacking; - if(!region_prepare_focus((WRegion*)ws, flags, res)) return FALSE; - stacking=group_get_stacking(ws); st=find_to_focus(ws, st, FALSE); -#warning "TODO: raise in some cases (not enter-window)?" - if(st==NULL) return FALSE; + if(ioncore_g.autoraise && + !(flags®ION_GOTO_ENTERWINDOW) && + st->level>STACKING_LEVEL_BOTTOM){ + WStacking **stackingp=group_get_stackingp(ws); + stacking_restack(stackingp, st, None, NULL, NULL, FALSE); + } + res->reg=st->reg; res->flags=flags; @@ -300,87 +286,61 @@ static bool group_managed_prepare_focus(WGroup *ws, WRegion *reg, } -static bool group_essentially_empty(WGroup *ws) -{ - WGroupIterTmp tmp; - WStacking *st; - - FOR_ALL_NODES_IN_GROUP(ws, st, tmp){ - if(st!=ws->managed_stdisp) - return FALSE; - } - - return TRUE; -} - - void group_managed_remove(WGroup *ws, WRegion *reg) { bool mcf=region_may_control_focus((WRegion*)ws); - bool ds=OBJ_IS_BEING_DESTROYED(ws); WStacking *st, *next_st=NULL; bool was_stdisp=FALSE, was_bottom=FALSE; - bool dest=FALSE; - bool cur=FALSE; + bool was_current=FALSE; st=group_find_stacking(ws, reg); if(st!=NULL){ - next_st=stacking_unstack(REGION_PARENT(ws), st); - - UNLINK_ITEM(ws->managed_list, st, mgr_next, mgr_prev); + if(st==ws->bottom){ + was_bottom=TRUE; + group_do_set_bottom(ws, NULL); + } if(st==ws->managed_stdisp){ ws->managed_stdisp=NULL; was_stdisp=TRUE; } - - if(st==ws->bottom){ - ws->bottom=NULL; - was_bottom=TRUE; - if(ws->bottom_last_close && group_essentially_empty(ws)) - dest=TRUE; - } if(st==ws->current_managed){ - cur=TRUE; ws->current_managed=NULL; + was_current=TRUE; } + next_st=stacking_unstack(REGION_PARENT(ws), st); + UNLINK_ITEM(ws->managed_list, st, mgr_next, mgr_prev); stacking_unassoc(st); stacking_free(st); } region_unset_manager(reg, (WRegion*)ws); - - if(!dest && !ds){ - if(was_bottom && !was_stdisp && ws->managed_stdisp==NULL){ - /* We should probably be managing any stdisp, that 'bottom' - * was managing. - */ - WMPlex *mplex=OBJ_CAST(REGION_MANAGER(ws), WMPlex); - - if(mplex!=NULL - && mplex->mx_current!=NULL - && mplex->mx_current->st->reg==(WRegion*)ws){ - mplex_remanage_stdisp(mplex); - } - } - - if(cur){ - WStacking *stf=find_to_focus(ws, next_st, TRUE); - if(stf!=NULL) - region_warp(stf->reg); + + if(!OBJ_IS_BEING_DESTROYED(ws) && was_current){ + /* This may still potentially cause problems when focus + * change is pending. Perhaps we should use region_await_focus, + * if it is pointing to our child (and region_may_control_focus + * fail if it is pointing somewhere else). + */ + WStacking *stf=find_to_focus(ws, next_st, TRUE); + if(stf!=NULL && mcf){ + region_maybewarp_now(stf->reg, FALSE); + }else{ + ws->current_managed=stf; } - }else if(dest && !ds){ - mainloop_defer_destroy((Obj*)ws); } } -static void group_managed_activated(WGroup *ws, WRegion *reg) +void group_managed_notify(WGroup *ws, WRegion *reg, WRegionNotify how) { - ws->current_managed=group_find_stacking(ws, reg); + if(how==ioncore_g.notifies.activated || + how==ioncore_g.notifies.pseudoactivated){ + ws->current_managed=group_find_stacking(ws, reg); + } } @@ -396,6 +356,7 @@ bool group_init(WGroup *ws, WWindow *par, const WFitParams *fp) ws->managed_stdisp=NULL; ws->bottom=NULL; ws->managed_list=NULL; + ws->phs=NULL; ws->dummywin=XCreateWindow(ioncore_g.dpy, par->win, fp->g.x, fp->g.y, 1, 1, 0, @@ -446,43 +407,131 @@ void group_deinit(WGroup *ws) XDeleteContext(ioncore_g.dpy, ws->dummywin, ioncore_g.win_context); XDestroyWindow(ioncore_g.dpy, ws->dummywin); ws->dummywin=None; - + + while(ws->phs!=NULL) + grouppholder_do_unlink(ws->phs); + region_deinit(&ws->reg); } - -bool group_rescue_clientwins(WGroup *ws, WPHolder *ph) +bool group_rescue_clientwins(WGroup *ws, WRescueInfo *info) { WGroupIterTmp tmp; group_iter_init_nostdisp(&tmp, ws); - return region_rescue_some_clientwins((WRegion*)ws, ph, + return region_rescue_some_clientwins((WRegion*)ws, info, (WRegionIterator*)group_iter, &tmp); } -bool group_may_destroy(WGroup *ws) +WPHolder *group_get_rescue_pholder_for(WGroup *ws, + WRegion *forwhat) +{ + WGroupAttachParams ap=GROUPATTACHPARAMS_INIT; + WFramedParam fp=FRAMEDPARAM_INIT; + WPHolder *ph; + + ap.geom_set=TRUE; + ap.geom=REGION_GEOM(forwhat); + + ap.geom_weak_set=1; + + if(REGION_PARENT(forwhat)==REGION_PARENT(ws)){ + ap.geom.x-=REGION_GEOM(ws).x; + ap.geom.y-=REGION_GEOM(ws).y; + }else{ + ap.geom_weak=REGION_RQGEOM_WEAK_X|REGION_RQGEOM_WEAK_Y; + } + + /* frame mode */ + /*{ + WFrame *frame=OBJ_CAST(forwhat, WFrame); + if(frame!=NULL) + fp.mode=frame->mode; + }*/ + + ph=(WPHolder*)create_grouppholder(ws, NULL, &ap); + + return pholder_either((WPHolder*)create_framedpholder(ph, &fp), ph); +} + + + +/*}}}*/ + + +/*{{{ Bottom */ + + +void group_bottom_set(WGroup *grp) { - bool ret=group_essentially_empty(ws); - if(!ret) - warn(TR("Workspace not empty - refusing to destroy.")); - return ret; + CALL_DYN(group_bottom_set, grp, (grp)); +} + + +static void group_do_set_bottom(WGroup *grp, WStacking *st) +{ + WStacking *was=grp->bottom; + WStacking *std=grp->managed_stdisp; + + grp->bottom=st; + + if(!OBJ_IS_BEING_DESTROYED(grp)){ + bool noremanage=((was==st) || + (was==NULL && std==NULL) || + (st!=NULL && st==std) || + (st==NULL && was==std)); + + if(!noremanage && + (st==NULL || HAS_DYN(st->reg, region_manage_stdisp))){ + group_remanage_stdisp(grp); + } + + group_bottom_set(grp); + } } -static bool group_managed_may_destroy(WGroup *ws, WRegion *reg) +/*EXTL_DOC + * Sets the `bottom' of \var{ws}. The region \var{reg} must already + * be managed by \var{ws}, unless \code{nil}. + */ +EXTL_EXPORT_MEMBER +bool group_set_bottom(WGroup *ws, WRegion *reg) { + WStacking *st=NULL; + + if(reg!=NULL){ + st=group_find_stacking(ws, reg); + + if(st==NULL) + return FALSE; + } + + group_do_set_bottom(ws, st); + return TRUE; } +/*EXTL_DOC + * Returns the `bottom' of \var{ws}. + */ +EXTL_SAFE +EXTL_EXPORT_MEMBER +WRegion *group_bottom(WGroup *ws) +{ + return (ws->bottom!=NULL ? ws->bottom->reg : NULL); +} + + /*}}}*/ -/*{{{ attach */ +/*{{{ Attach */ WStacking *group_do_add_managed(WGroup *ws, WRegion *reg, int level, @@ -518,8 +567,7 @@ WStacking *group_do_add_managed_default(WGroup *ws, WRegion *reg, int level, frame=OBJ_CAST(reg, WFrame); if(frame!=NULL){ - WFrameMode m=frame_mode(frame); - if(m!=FRAME_MODE_FLOATING && m!=FRAME_MODE_TRANSIENT) + if(framemode_unalt(frame_mode(frame))==FRAME_MODE_TILED) frame_set_mode(frame, FRAME_MODE_FLOATING); } @@ -550,6 +598,14 @@ static void geom_group_to_parent(WGroup *ws, const WRectangle *g, } +static int group_must_focus(WGroup *ws, WStacking *st) +{ + WStacking *stacking=group_get_stacking(ws); + + return (stacking!=NULL && stacking_must_focus(stacking, st)); +} + + bool group_do_attach_final(WGroup *ws, WRegion *reg, const WGroupAttachParams *param) @@ -562,60 +618,67 @@ bool group_do_attach_final(WGroup *ws, int weak; bool sw; + /* Stacking */ + if(param->stack_above!=NULL) + stabove=group_find_stacking(ws, param->stack_above); + + level=(stabove!=NULL + ? stabove->level + : (param->level_set + ? param->level + : STACKING_LEVEL_NORMAL)); + /* Fit */ szplcy=(param->szplcy_set ? param->szplcy : (param->bottom ? SIZEPOLICY_FULL_EXACT - : SIZEPOLICY_UNCONSTRAINED)); - - weak=(param->geom_weak_set - ? param->geom_weak - : (param->geom_set - ? 0 - : REGION_RQGEOM_WEAK_ALL)); - - if(param->geom_set) - geom_group_to_parent(ws, ¶m->geom, &g); - else - g=REGION_GEOM(reg); - - /* If the requested geometry does not overlap the workspaces's geometry, - * position request is never honoured. - */ - if((g.x+g.w<=REGION_GEOM(ws).x) || - (g.y+g.h<=REGION_GEOM(ws).y) || - (g.x>=REGION_GEOM(ws).x+REGION_GEOM(ws).w) || - (g.y>=REGION_GEOM(ws).y+REGION_GEOM(ws).h)){ - weak|=REGION_RQGEOM_WEAK_X|REGION_RQGEOM_WEAK_X; - } + : SIZEPOLICY_VISIBILITY_CONSTRAINED)); + + if(!param->whatever){ + weak=(param->geom_weak_set + ? param->geom_weak + : (param->geom_set + ? 0 + : REGION_RQGEOM_WEAK_ALL)); + + if(param->geom_set) + geom_group_to_parent(ws, ¶m->geom, &g); + else + g=REGION_GEOM(reg); + + /* If the requested geometry does not overlap the workspaces's geometry, + * position request is never honoured. + */ + if((g.x+g.w<=REGION_GEOM(ws).x) || + (g.x>=REGION_GEOM(ws).x+REGION_GEOM(ws).w)){ + weak|=REGION_RQGEOM_WEAK_X; + } + + if((g.y+g.h<=REGION_GEOM(ws).y) || + (g.y>=REGION_GEOM(ws).y+REGION_GEOM(ws).h)){ + weak|=REGION_RQGEOM_WEAK_Y; + } - if((weak&(REGION_RQGEOM_WEAK_X|REGION_RQGEOM_WEAK_Y)) - ==(REGION_RQGEOM_WEAK_X|REGION_RQGEOM_WEAK_Y) && - (szplcy==SIZEPOLICY_UNCONSTRAINED || - szplcy==SIZEPOLICY_FREE || - szplcy==SIZEPOLICY_FREE_GLUE /* without flags */)){ - group_calc_placement(ws, &g); - } + if(weak&(REGION_RQGEOM_WEAK_X|REGION_RQGEOM_WEAK_Y) && + (szplcy==SIZEPOLICY_UNCONSTRAINED || + szplcy==SIZEPOLICY_VISIBILITY_CONSTRAINED || + szplcy==SIZEPOLICY_FREE || + szplcy==SIZEPOLICY_FREE_GLUE /* without flags */)){ + /* TODO: use 'weak'? */ + group_calc_placement(ws, level, &g); + } - fp.g=REGION_GEOM(ws); - fp.mode=REGION_FIT_EXACT; + fp.g=REGION_GEOM(ws); + fp.mode=REGION_FIT_EXACT; - sizepolicy(&szplcy, reg, &g, weak, &fp); + sizepolicy(&szplcy, reg, &g, weak, &fp); - if(rectangle_compare(&fp.g, ®ION_GEOM(reg))!=RECTANGLE_SAME) - region_fitrep(reg, NULL, &fp); + if(rectangle_compare(&fp.g, ®ION_GEOM(reg))!=RECTANGLE_SAME) + region_fitrep(reg, NULL, &fp); + } - /* Stacking & add */ - if(param->stack_above!=NULL) - stabove=group_find_stacking(ws, param->stack_above); - - level=(stabove!=NULL - ? stabove->level - : (param->level_set - ? param->level - : STACKING_LEVEL_NORMAL)); - + /* Add */ st=group_do_add_managed(ws, reg, level, szplcy); if(st==NULL) @@ -624,74 +687,66 @@ bool group_do_attach_final(WGroup *ws, if(stabove!=NULL) st->above=stabove; - /* Misc. */ - if(param->bottom){ - ws->bottom=st; - - if(HAS_DYN(reg, region_manage_stdisp) && ws->managed_stdisp!=NULL){ - WMPlex *mplex=OBJ_CAST(REGION_MANAGER(ws), WMPlex); - if(mplex!=NULL){ /* should always hold */ - WMPlexSTDispInfo di; - WRegion *stdisp=NULL; - mplex_get_stdisp(mplex, &stdisp, &di); - if(stdisp!=NULL){ - assert(stdisp==ws->managed_stdisp->reg); - /* WARNING! Calls back to group code (managed_remove). */ - region_manage_stdisp(reg, stdisp, &di); - } - } - } - } + if(param->bottom) + group_do_set_bottom(ws, st); - sw=(param->switchto_set ? param->switchto : ioncore_g.switchto_new); + /* Focus */ + sw=((param->switchto_set ? param->switchto : ioncore_g.switchto_new) + ? st==find_to_focus(ws, st, FALSE) + : group_must_focus(ws, st)); - if(sw || st->level>=STACKING_LEVEL_MODAL1){ - WStacking *stf=find_to_focus(ws, st, FALSE); - - if(stf==st){ - /* Ok, the new region can be focused */ - group_refocus_(ws, stf); - } + if(sw){ + if(region_may_control_focus((WRegion*)ws)) + region_set_focus(st->reg); + else + ws->current_managed=st; + }else if(region_is_fully_mapped(reg)){ + region_pointer_focus_hack(reg); } - + return TRUE; } +static void group_attach_fp(WGroup *ws, const WGroupAttachParams *param, + WFitParams *fp) +{ + if(param->geom_set){ + geom_group_to_parent(ws, ¶m->geom, &fp->g); + fp->mode=REGION_FIT_EXACT; + }else{ + fp->g=REGION_GEOM(ws); + fp->mode=REGION_FIT_BOUNDS|REGION_FIT_WHATEVER; + } +} + + WRegion *group_do_attach(WGroup *ws, /*const*/ WGroupAttachParams *param, WRegionAttachData *data) { WFitParams fp; - WWindow *par; WRegion *reg; - + if(ws->bottom!=NULL && param->bottom){ warn(TR("'bottom' already set.")); return NULL; } - par=REGION_PARENT(ws); - assert(par!=NULL); - - if(param->geom_set){ - geom_group_to_parent(ws, ¶m->geom, &fp.g); - fp.mode=REGION_FIT_EXACT; - }else{ - fp.g=REGION_GEOM(ws); - fp.mode=REGION_FIT_BOUNDS|REGION_FIT_WHATEVER; - } - - return region_attach_helper((WRegion*) ws, par, &fp, + group_attach_fp(ws, param, &fp); + + return region_attach_helper((WRegion*) ws, REGION_PARENT(ws), &fp, (WRegionDoAttachFn*)group_do_attach_final, /*(const WRegionAttachParams*)*/param, data); /* ^^^^ doesn't seem to work. */ } -static void get_params(WGroup *ws, ExtlTab tab, WGroupAttachParams *par) +void group_get_attach_params(WGroup *ws, ExtlTab tab, + WGroupAttachParams *par) { int tmp; + bool tmpb; char *tmps; ExtlTab g; @@ -701,27 +756,29 @@ static void get_params(WGroup *ws, ExtlTab tab, WGroupAttachParams *par) par->geom_set=0; par->bottom=0; - if(extl_table_gets_i(tab, "level", &tmp)){ - if(tmp>=0){ - par->level_set=STACKING_LEVEL_NORMAL; - par->level=tmp; - } - } - if(extl_table_is_bool_set(tab, "bottom")){ par->level=STACKING_LEVEL_BOTTOM; par->level_set=1; par->bottom=1; } + if(extl_table_gets_i(tab, "level", &tmp)){ + if(tmp>=0){ + par->level_set=1; + par->level=tmp; + } + } + if(!par->level_set && extl_table_is_bool_set(tab, "modal")){ par->level=STACKING_LEVEL_MODAL1; par->level_set=1; } - if(extl_table_is_bool_set(tab, "switchto")) - par->switchto=1; - + if(extl_table_gets_b(tab, "switchto", &tmpb)){ + par->switchto=(tmpb!=0); + par->switchto_set=1; + } + if(extl_table_gets_i(tab, "sizepolicy", &tmp)){ par->szplcy_set=1; par->szplcy=tmp; @@ -766,7 +823,7 @@ WRegion *group_attach(WGroup *ws, WRegion *reg, ExtlTab param) if(reg==NULL) return NULL; - get_params(ws, param, &par); + group_get_attach_params(ws, param, &par); data.type=REGION_ATTACH_REPARENT; data.u.reg=reg; @@ -781,12 +838,14 @@ WRegion *group_attach(WGroup *ws, WRegion *reg, ExtlTab param) * * \begin{tabularx}{\linewidth}{lX} * \tabhead{Field & Description} - * \var{type} & Class name (a string) of the object to be created. Mandatory. \\ - * \var{name} & Name of the object to be created (a string). Optional. \\ - * \var{switchto} & Should the region be switched to (boolean)? Optional. \\ - * \var{level} & Stacking level; default is 1. \\ - * \var{modal} & Make object modal; ignored if level is set. \\ - * \var{sizepolicy} & Size policy. \\ + * \var{type} & (string) Class of the object to be created. Mandatory. \\ + * \var{name} & (string) Name of the object to be created. \\ + * \var{switchto} & (boolean) Should the region be switched to? \\ + * \var{level} & (integer) Stacking level; default is 1. \\ + * \var{modal} & (boolean) Make object modal; ignored if level is set. \\ + * \var{sizepolicy} & (string) Size policy; see Section \ref{sec:sizepolicies}. \\ + * \var{bottom} & (boolean) Mark the attached region as the + * ``bottom'' of \var{ws}. \\ * \end{tabularx} * * In addition parameters to the region to be created are passed in this @@ -798,7 +857,7 @@ WRegion *group_attach_new(WGroup *ws, ExtlTab param) WGroupAttachParams par=GROUPATTACHPARAMS_INIT; WRegionAttachData data; - get_params(ws, param, &par); + group_get_attach_params(ws, param, &par); data.type=REGION_ATTACH_LOAD; data.u.tab=param; @@ -816,29 +875,34 @@ WRegion *group_attach_new(WGroup *ws, ExtlTab param) static int stdisp_szplcy(const WMPlexSTDispInfo *di, WRegion *stdisp) { int pos=di->pos; + int policy=0, gravity=0; if(di->fullsize){ if(region_orientation(stdisp)==REGION_ORIENTATION_VERTICAL){ if(pos==MPLEX_STDISP_TL || pos==MPLEX_STDISP_BL) - return SIZEPOLICY_STRETCH_LEFT; + policy=SIZEPOLICY_STRETCH_LEFT; else - return SIZEPOLICY_STRETCH_RIGHT; + policy=SIZEPOLICY_STRETCH_RIGHT; }else{ if(pos==MPLEX_STDISP_TL || pos==MPLEX_STDISP_TR) - return SIZEPOLICY_STRETCH_TOP; + policy=SIZEPOLICY_STRETCH_TOP; else - return SIZEPOLICY_STRETCH_BOTTOM; + policy=SIZEPOLICY_STRETCH_BOTTOM; } }else{ - if(pos==MPLEX_STDISP_TL) - return SIZEPOLICY_GRAVITY_NORTHWEST; - else if(pos==MPLEX_STDISP_BL) - return SIZEPOLICY_GRAVITY_SOUTHWEST; - else if(pos==MPLEX_STDISP_TR) - return SIZEPOLICY_GRAVITY_NORTHEAST; - else /*if(pos=MPLEX_STDISP_BR)*/ - return SIZEPOLICY_GRAVITY_SOUTHEAST; + policy=SIZEPOLICY_GRAVITY; } + + if(pos==MPLEX_STDISP_TL) + gravity=SIZEPOLICY_VERT_TOP|SIZEPOLICY_HORIZ_LEFT; + else if(pos==MPLEX_STDISP_BL) + gravity=SIZEPOLICY_VERT_BOTTOM|SIZEPOLICY_HORIZ_LEFT; + else if(pos==MPLEX_STDISP_TR) + gravity=SIZEPOLICY_VERT_TOP|SIZEPOLICY_HORIZ_RIGHT; + else /*if(pos=MPLEX_STDISP_BR)*/ + gravity=SIZEPOLICY_VERT_BOTTOM|SIZEPOLICY_HORIZ_RIGHT; + + return (policy|gravity); } @@ -872,14 +936,36 @@ void group_manage_stdisp(WGroup *ws, WRegion *stdisp, STACKING_LEVEL_ON_TOP, szplcy); } - + + stdisp->flags|=REGION_SKIP_FOCUS; + fp.g=REGION_GEOM(ws); + fp.mode=0; + sizepolicy(&ws->managed_stdisp->szplcy, stdisp, NULL, 0, &fp); region_fitrep(stdisp, NULL, &fp); } +static void group_remanage_stdisp(WGroup *ws) +{ + WMPlex *mplex=OBJ_CAST(REGION_MANAGER(ws), WMPlex); + + if(mplex!=NULL && + mplex->mx_current!=NULL && + mplex->mx_current->st->reg==(WRegion*)ws){ + mplex_remanage_stdisp(mplex); + } +} + + +/*}}}*/ + + +/*{{{ Geometry requests */ + + void group_managed_rqgeom(WGroup *ws, WRegion *reg, const WRQGeomParams *rq, WRectangle *geomret) @@ -894,6 +980,7 @@ void group_managed_rqgeom(WGroup *ws, WRegion *reg, fp.mode=REGION_FIT_EXACT; }else{ fp.g=REGION_GEOM(ws); + fp.mode=0; sizepolicy(&st->szplcy, reg, &rq->geom, rq->flags, &fp); } @@ -947,12 +1034,6 @@ static WStacking *prv(WGroup *ws, WStacking *st, bool wrap) typedef WStacking *NxtFn(WGroup *ws, WStacking *st, bool wrap); -static bool mapped_filt(WStacking *st, void *unused) -{ - return (st->reg!=NULL && REGION_IS_MAPPED(st->reg)); -} - - static bool focusable(WGroup *ws, WStacking *st, uint min_level) { return (st->reg!=NULL @@ -971,7 +1052,7 @@ static WStacking *do_get_next(WGroup *ws, WStacking *sti, stacking=group_get_stacking(ws); if(stacking!=NULL) - min_level=stacking_min_level(stacking, mapped_filt, NULL); + min_level=stacking_min_level_mapped(stacking); st=sti; while(1){ @@ -985,7 +1066,7 @@ static WStacking *do_get_next(WGroup *ws, WStacking *sti, } if(sti_ok && focusable(ws, sti, min_level)) - return st; + return sti; return NULL; } @@ -1082,8 +1163,6 @@ void group_restack(WGroup *ws, Window other, int mode) WStacking *group_find_stacking(WGroup *ws, WRegion *r) { - WStacking *st; - if(r==NULL || REGION_MANAGER(r)!=(WRegion*)ws) return NULL; @@ -1136,26 +1215,20 @@ bool group_managed_rqorder(WGroup *grp, WRegion *reg, WRegionOrder order) /*EXTL_DOC - * Returns the 'bottom' of \var{ws}. - */ -EXTL_EXPORT_MEMBER -WRegion *group_bottom(WGroup *ws) -{ - return (ws->bottom!=NULL ? ws->bottom->reg : NULL); -} - - -/*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 is called in protected mode. + * This routine returns \code{true} if it reaches the end of list + * without this happening. */ EXTL_SAFE EXTL_EXPORT_MEMBER -ExtlTab group_managed_list(WGroup *ws) +bool group_managed_i(WGroup *ws, ExtlFn iterfn) { WGroupIterTmp tmp; group_iter_init(&tmp, ws); - return extl_obj_iterable_to_table((ObjIterator*)group_iter, &tmp); + return extl_iter_objlist_(iterfn, (ObjIterator*)group_iter, &tmp); } @@ -1182,6 +1255,34 @@ Window group_xwindow(const WGroup *ws) } +/*EXTL_DOC + * Returns the group of \var{reg}, if it is managed by one, + * and \var{reg} itself otherwise. + */ +/*EXTL_EXPORT_MEMBER +WRegion *region_group_of(WRegion *reg) +{ + WRegion *mgr=REGION_MANAGER(reg); + + return (OBJ_IS(mgr, WGroup) ? mgr : reg); +}*/ + + +/*EXTL_DOC + * Returns the group of \var{reg}, if \var{reg} is its bottom, + * and \var{reg} itself otherwise. + */ +EXTL_EXPORT_MEMBER +WRegion *region_groupleader_of(WRegion *reg) +{ + WGroup *grp=REGION_MANAGER_CHK(reg, WGroup); + + return ((grp!=NULL && group_bottom(grp)==reg) + ? (WRegion*)grp + : reg); +} + + /*}}}*/ @@ -1212,7 +1313,8 @@ static ExtlTab group_get_configuration(WGroup *ws) subtab=region_get_configuration(st->reg); if(subtab!=extl_table_none()){ - extl_table_sets_i(subtab, "sizepolicy", st->szplcy); + extl_table_sets_s(subtab, "sizepolicy", + sizepolicy2string(st->szplcy)); extl_table_sets_i(subtab, "level", st->level); tmpg=REGION_GEOM(st->reg); @@ -1236,7 +1338,7 @@ static ExtlTab group_get_configuration(WGroup *ws) return tab; } - + void group_do_load(WGroup *ws, ExtlTab tab) { ExtlTab substab, subtab; @@ -1246,15 +1348,29 @@ void group_do_load(WGroup *ws, ExtlTab tab) n=extl_table_get_n(substab); for(i=1; i<=n; i++){ if(extl_table_geti_t(substab, i, &subtab)){ - group_attach_new(ws, subtab); + WGroupAttachParams par=GROUPATTACHPARAMS_INIT; + WRegionAttachData data; + WFitParams fp; + WPHolder *ph; + + group_get_attach_params(ws, subtab, &par); + group_attach_fp(ws, &par, &fp); + + ph=(WPHolder*)create_grouppholder(ws, NULL, &par); + + region_attach_load_helper((WRegion*)ws, REGION_PARENT(ws), &fp, + (WRegionDoAttachFn*)group_do_attach_final, + (void*)&par, subtab, &ph); + + if(ph!=NULL) + destroy_obj((Obj*)ph); + extl_unref_table(subtab); } } extl_unref_table(substab); } - - ws->bottom_last_close=extl_table_is_bool_set(tab, "bottom_last_close"); } @@ -1295,8 +1411,8 @@ static DynFunTab group_dynfuntab[]={ {region_do_set_focus, group_do_set_focus}, - {region_managed_activated, - group_managed_activated}, + {region_managed_notify, + group_managed_notify}, {region_managed_remove, group_managed_remove}, @@ -1304,12 +1420,6 @@ static DynFunTab group_dynfuntab[]={ {(DynFun*)region_get_configuration, (DynFun*)group_get_configuration}, - {(DynFun*)region_may_destroy, - (DynFun*)group_may_destroy}, - - {(DynFun*)region_managed_may_destroy, - (DynFun*)group_managed_may_destroy}, - {(DynFun*)region_current, (DynFun*)group_current}, @@ -1348,6 +1458,9 @@ static DynFunTab group_dynfuntab[]={ {(DynFun*)region_managed_rqorder, (DynFun*)group_managed_rqorder}, + + {(DynFun*)region_get_rescue_pholder_for, + (DynFun*)group_get_rescue_pholder_for}, END_DYNFUNTAB };