X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=ioncore%2Fattach.c;h=5d81222a97663e6a1e05eba06b183cb0b818c02b;hb=ae4260bb64817c11f9a7140324cd3e3ba113e297;hp=4eeb64e65dc184cc6303c5a7127e1b4a0ff0a05b;hpb=803afbc1cd633f6c025bcd9537e9b7e9aedadd0d;p=ion3.git diff --git a/ioncore/attach.c b/ioncore/attach.c index 4eeb64e..5d81222 100644 --- a/ioncore/attach.c +++ b/ioncore/attach.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 @@ -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,10 +84,34 @@ 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; } @@ -138,35 +171,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); }