]> git.decadent.org.uk Git - ion3.git/blobdiff - ioncore/attach.c
Update cfg_kludge_flash for Flash 10
[ion3.git] / ioncore / attach.c
index 23004cb143bbdaf284780ad5735c72439456208a..0ee74ab01743ba24a9b856fb3d2368f352e2c0eb 100644 (file)
@@ -1,12 +1,9 @@
 /*
  * ion/ioncore/attach.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 <string.h>
@@ -21,6 +18,7 @@
 #include "manage.h"
 #include "extlconv.h"
 #include "names.h"
+#include "focus.h"
 
 
 /*{{{ Helper */
@@ -35,7 +33,7 @@ static WRegion *doit_new(WRegion *mgr,
     
     if(reg==NULL)
         return NULL;
-    
+        
     if(!cont(mgr, reg, cont_param)){
         destroy_obj((Obj*)reg);
         return NULL;
@@ -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&REGION_FIT_WHATEVER){
         /* fp->g is not final; substitute size with current to avoid
@@ -75,38 +84,90 @@ 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);
 }
 
 
+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;
+    WRegion *reg=NULL;
     
     if(extl_table_gets_o(tab, "reg", (Obj**)&reg)){
         if(!OBJ_IS(reg, WRegion))
             return FALSE;
+    }/*else if(extl_table_is_bool_set(tab, "reg_use_new")){
+        reg=ioncore_newly_created;
+        if(reg==NULL)
+            return NULL;
+    }*/
+    
+    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, &p);
     }
-    
-    return doit_new(mgr, par, fp, cont, cont_param,
-                    (WRegionCreateFn*)wrap_load, &tab);
 }
 
+
+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,
@@ -116,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{
@@ -128,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);
 }