X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=ioncore%2Fgroup.c;h=9c67348fe2a26442a696def5b14523ec2c55bfd7;hb=ae4260bb64817c11f9a7140324cd3e3ba113e297;hp=538db141f11d9abe6c3b7fd6e785fa9faa659679;hpb=803afbc1cd633f6c025bcd9537e9b7e9aedadd0d;p=ion3.git diff --git a/ioncore/group.c b/ioncore/group.c index 538db14..9c67348 100644 --- a/ioncore/group.c +++ b/ioncore/group.c @@ -3,10 +3,7 @@ * * 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 @@ -46,6 +43,7 @@ static void group_place_stdisp(WGroup *ws, WWindow *parent, int pos, WRegion *stdisp); +static void group_remanage_stdisp(WGroup *ws); /*{{{ Stacking list stuff */ @@ -280,19 +278,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; @@ -301,28 +301,12 @@ 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); @@ -339,13 +323,11 @@ void group_managed_remove(WGroup *ws, WRegion *reg) 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; } stacking_unassoc(st); @@ -354,21 +336,15 @@ void group_managed_remove(WGroup *ws, WRegion *reg) region_unset_manager(reg, (WRegion*)ws); - if(!dest && !ds){ + if(!OBJ_IS_BEING_DESTROYED(ws)){ 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); - } + group_remanage_stdisp(ws); } - if(cur){ + if(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 @@ -381,13 +357,11 @@ void group_managed_remove(WGroup *ws, WRegion *reg) ws->current_managed=stf; } } - }else if(dest && !ds){ - region_dispose((WRegion*)ws, mcf); } } -static void group_managed_notify(WGroup *ws, WRegion *reg, WRegionNotify how) +void group_managed_notify(WGroup *ws, WRegion *reg, WRegionNotify how) { if(how==ioncore_g.notifies.activated || how==ioncore_g.notifies.pseudoactivated){ @@ -464,37 +438,100 @@ void group_deinit(WGroup *ws) -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) +static bool group_empty_for_bottom_stdisp(WGroup *ws) { - bool ret=group_essentially_empty(ws); - if(!ret) - warn(TR("Workspace not empty - refusing to destroy.")); - return ret; + WGroupIterTmp tmp; + WStacking *st; + + FOR_ALL_NODES_IN_GROUP(ws, st, tmp){ + if(st!=ws->bottom && st!=ws->managed_stdisp) + return FALSE; + } + + return TRUE; } -static bool group_managed_may_destroy(WGroup *ws, WRegion *reg) +static WRegion *group_managed_disposeroot(WGroup *ws, WRegion *reg) { + if(group_bottom(ws)==reg){ + if(group_empty_for_bottom_stdisp(ws)) + return region_disposeroot((WRegion*)ws); + } + + return reg; +} + + +/*}}}*/ + + +/*{{{ Bottom */ + + +static void group_do_set_bottom(WGroup *grp, WStacking *st) +{ + WStacking *was=grp->bottom; + + grp->bottom=st; + + if(st!=was){ + if(st==NULL || HAS_DYN(st->reg, region_manage_stdisp)) + group_remanage_stdisp(grp); + + } +} + + +/*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, @@ -531,7 +568,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(m==FRAME_MODE_TILED || m==FRAME_MODE_TILED_ALT) frame_set_mode(frame, FRAME_MODE_FLOATING); } @@ -574,6 +611,16 @@ 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 @@ -610,7 +657,7 @@ bool group_do_attach_final(WGroup *ws, szplcy==SIZEPOLICY_FREE || szplcy==SIZEPOLICY_FREE_GLUE /* without flags */)){ /* TODO: use 'weak'? */ - group_calc_placement(ws, &g); + group_calc_placement(ws, level, &g); } fp.g=REGION_GEOM(ws); @@ -621,16 +668,7 @@ bool group_do_attach_final(WGroup *ws, 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) @@ -639,25 +677,10 @@ 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); + /* Focus */ sw=(param->switchto_set ? param->switchto : ioncore_g.switchto_new); if(sw || st->level>=STACKING_LEVEL_MODAL1){ @@ -716,6 +739,12 @@ static void get_params(WGroup *ws, ExtlTab tab, WGroupAttachParams *par) par->geom_set=0; par->bottom=0; + 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=STACKING_LEVEL_NORMAL; @@ -723,12 +752,6 @@ static void get_params(WGroup *ws, ExtlTab tab, WGroupAttachParams *par) } } - if(extl_table_is_bool_set(tab, "bottom")){ - par->level=STACKING_LEVEL_BOTTOM; - par->level_set=1; - par->bottom=1; - } - if(!par->level_set && extl_table_is_bool_set(tab, "modal")){ par->level=STACKING_LEVEL_MODAL1; par->level_set=1; @@ -796,12 +819,12 @@ 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}. \\ * \end{tabularx} * * In addition parameters to the region to be created are passed in this @@ -895,6 +918,24 @@ void group_manage_stdisp(WGroup *ws, WRegion *stdisp, } +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) @@ -962,12 +1003,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 @@ -986,7 +1021,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){ @@ -1148,16 +1183,6 @@ bool group_managed_rqorder(WGroup *grp, WRegion *reg, WRegionOrder order) /*{{{ Misc. */ -/*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 * Iterate over managed regions of \var{ws} until \var{iterfn} returns * \code{false}. @@ -1198,14 +1223,31 @@ Window group_xwindow(const WGroup *ws) } -WRegion *region_group_if_bottom(WRegion *reg) +/*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); - if(grp!=NULL && group_bottom(grp)==reg) - return (WRegion*)grp; - else - return reg; + return ((grp!=NULL && group_bottom(grp)==reg) + ? (WRegion*)grp + : reg); } @@ -1239,7 +1281,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); @@ -1280,8 +1323,6 @@ void group_do_load(WGroup *ws, ExtlTab tab) extl_unref_table(substab); } - - ws->bottom_last_close=extl_table_is_bool_set(tab, "bottom_last_close"); } @@ -1331,11 +1372,8 @@ 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_managed_disposeroot, + (DynFun*)group_managed_disposeroot}, {(DynFun*)region_current, (DynFun*)group_current},