]> git.decadent.org.uk Git - ion3.git/blobdiff - ioncore/attach.c
[svn-upgrade] Integrating new upstream version, ion3 (20070318)
[ion3.git] / ioncore / attach.c
index 4eeb64e65dc184cc6303c5a7127e1b4a0ff0a05b..a1dc7addf23200034454ea5281bcffaccefb91d8 100644 (file)
@@ -21,6 +21,7 @@
 #include "manage.h"
 #include "extlconv.h"
 #include "names.h"
+#include "focus.h"
 
 
 /*{{{ Helper */
@@ -51,9 +52,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&REGION_FIT_WHATEVER){
         /* fp->g is not final; substitute size with current to avoid
@@ -75,10 +87,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 +174,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);
 }