X-Git-Url: https://git.decadent.org.uk/gitweb/?p=ion3.git;a=blobdiff_plain;f=ioncore%2Fattach.c;h=0ee74ab01743ba24a9b856fb3d2368f352e2c0eb;hp=4eeb64e65dc184cc6303c5a7127e1b4a0ff0a05b;hb=HEAD;hpb=471a5e5f9928e2d324b2e10422a420f458bd63ff diff --git a/ioncore/attach.c b/ioncore/attach.c index 4eeb64e..0ee74ab 100644 --- a/ioncore/attach.c +++ b/ioncore/attach.c @@ -1,12 +1,9 @@ /* * ion/ioncore/attach.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 @@ -21,6 +18,7 @@ #include "manage.h" #include "extlconv.h" #include "names.h" +#include "focus.h" /*{{{ Helper */ @@ -51,9 +49,20 @@ static WRegion *doit_reparent(WRegion *mgr, WRegion *reg) { WFitParams fp2; - - if(!region_attach_reparent_check(mgr, reg)) + WRegion *disposeroot; + + if(!region_ancestor_check(mgr, reg)){ + warn(TR("Attempt to make region %s manage its ancestor %s."), + region_name(mgr), region_name(reg)); + return NULL; + } + + disposeroot=region_disposeroot(reg); + + if(disposeroot==NULL){ + /* Region may not be reparented */ return NULL; + } if(fp->mode®ION_FIT_WHATEVER){ /* fp->g is not final; substitute size with current to avoid @@ -75,18 +84,46 @@ static WRegion *doit_reparent(WRegion *mgr, region_detach_manager(reg); if(!cont(mgr, reg, cont_param)){ - #warning "TODO: What?" + WScreen *scr=region_screen_of(reg); + + warn(TR("Unexpected attach error: " + "trying to recover by attaching to screen.")); + + if(scr!=NULL){ + /* Try to attach to screen, to have `reg` attached at least + * somewhere. For better recovery, we could try to get + * a placeholder for `reg` before we detach it, but this + * would add unnecessary overhead in the usual succesfull + * case. (This failure is supposed to be _very_ rare!) + * We intentionally also do not region_postdetach_dispose + * on recovery. + */ + int flags=(region_may_control_focus(reg) + ? MPLEX_ATTACH_SWITCHTO + : 0); + if(mplex_attach_simple(&scr->mplex, reg, flags)!=NULL) + return NULL; + } + + warn(TR("Failed recovery.")); + return NULL; } - + + region_postdetach_dispose(reg, disposeroot); + return reg; } -static WRegion *wrap_load(WWindow *par, const WFitParams *fp, - ExtlTab *tab) +typedef struct{ + ExtlTab tab; + WPHolder **sm_ph_p; +} WLP; + +static WRegion *wrap_load(WWindow *par, const WFitParams *fp, WLP *p) { - return create_region_load(par, fp, *tab); + return create_region_load(par, fp, p->tab, p->sm_ph_p); } @@ -96,7 +133,7 @@ WRegion *ioncore_newly_created=NULL; static WRegion *doit_load(WRegion *mgr, WWindow *par, const WFitParams *fp, WRegionDoAttachFn *cont, void *cont_param, - ExtlTab tab) + ExtlTab tab, WPHolder **sm_ph) { WRegion *reg=NULL; @@ -112,11 +149,25 @@ static WRegion *doit_load(WRegion *mgr, if(reg!=NULL){ return doit_reparent(mgr, par, fp, cont, cont_param, reg); }else{ + WLP p; + p.tab=tab; + p.sm_ph_p=sm_ph; + return doit_new(mgr, par, fp, cont, cont_param, - (WRegionCreateFn*)wrap_load, &tab); + (WRegionCreateFn*)wrap_load, &p); } } + +WRegion *region_attach_load_helper(WRegion *mgr, + WWindow *par, const WFitParams *fp, + WRegionDoAttachFn *fn, void *fn_param, + ExtlTab tab, WPHolder **sm_ph) +{ + return doit_load(mgr, par, fp, fn, fn_param, tab, sm_ph); +} + + WRegion *region_attach_helper(WRegion *mgr, WWindow *par, const WFitParams *fp, WRegionDoAttachFn *fn, void *fn_param, @@ -126,7 +177,7 @@ WRegion *region_attach_helper(WRegion *mgr, return doit_new(mgr, par, fp, fn, fn_param, data->u.n.fn, data->u.n.param); }else if(data->type==REGION_ATTACH_LOAD){ - return doit_load(mgr, par, fp, fn, fn_param, data->u.tab); + return doit_load(mgr, par, fp, fn, fn_param, data->u.tab, NULL); }else if(data->type==REGION_ATTACH_REPARENT){ return doit_reparent(mgr, par, fp, fn, fn_param, data->u.reg); }else{ @@ -138,35 +189,35 @@ WRegion *region_attach_helper(WRegion *mgr, /*}}}*/ -/*{{{ Reparent check */ +/*{{{ Reparent check etc. */ -bool region_attach_reparent_check(WRegion *mgr, WRegion *reg) +bool region_ancestor_check(WRegion *dst, WRegion *reg) { WRegion *reg2; - /*if(REGION_MANAGER(reg)==mgr){ - warn(TR("Same manager.")); - return FALSE; - }*/ - /* Check that reg is not a parent or manager of mgr */ - for(reg2=mgr; reg2!=NULL; reg2=REGION_MANAGER(reg2)){ + for(reg2=dst; reg2!=NULL; reg2=REGION_MANAGER(reg2)){ if(reg2==reg) - goto err; + return FALSE; } - for(reg2=REGION_PARENT_REG(mgr); reg2!=NULL; reg2=REGION_PARENT_REG(reg2)){ + for(reg2=REGION_PARENT_REG(dst); reg2!=NULL; reg2=REGION_PARENT_REG(reg2)){ if(reg2==reg) - goto err; + return FALSE; } return TRUE; - -err: - warn(TR("Attempt to make region %s manage its ancestor %s."), - region_name(mgr), region_name(reg)); - return FALSE; +} + + +void region_postdetach_dispose(WRegion *reg, WRegion *disposeroot) +{ + /* disposeroot should be destroyed (as empty and useless) unless it + * still, in fact, is an ancestor of reg. + */ + if(disposeroot!=reg && region_ancestor_check(reg, disposeroot)) + region_dispose(disposeroot); }