]> git.decadent.org.uk Git - ion3.git/blobdiff - ioncore/framedpholder.c
Update cfg_kludge_flash for Flash 10
[ion3.git] / ioncore / framedpholder.c
index 43375f2d2a51cb1f7c2a3c770999e426653b602c..60c6291ba6c894a58520427b742c2778993cdab1 100644 (file)
@@ -1,12 +1,9 @@
 /*
  * ion/ioncore/framedpholder.c
  *
- * Copyright (c) Tuomo Valkonen 2005-2006
+ * Copyright (c) Tuomo Valkonen 2005-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 <libtu/objp.h>
@@ -16,6 +13,7 @@
 #include "frame.h"
 #include "framedpholder.h"
 #include "sizehint.h"
+#include "resize.h"
 
 
 /*{{{ Init/deinit */
@@ -31,6 +29,8 @@ bool framedpholder_init(WFramedPHolder *ph, WPHolder *cont,
     ph->cont=cont;
     ph->param=*param;
     
+    watch_init(&ph->frame_watch);
+    
     return TRUE;
 }
  
@@ -50,6 +50,7 @@ void framedpholder_deinit(WFramedPHolder *ph)
     }
     
     pholder_deinit(&(ph->ph));
+    watch_reset(&ph->frame_watch);
 }
 
 
@@ -62,9 +63,61 @@ void framedpholder_deinit(WFramedPHolder *ph)
 typedef struct{
     WRegionAttachData *data;
     WFramedParam *param;
+    WRegion *reg_ret;
 } AP;
 
 
+void frame_adjust_to_initial(WFrame *frame, const WFitParams *fp, 
+                             const WFramedParam *param, WRegion *reg)
+{
+    WRectangle rqg, mg;
+    WSizeHints szh;
+    int iw, ih;
+    if(!(fp->mode&(REGION_FIT_BOUNDS|REGION_FIT_WHATEVER)))
+        return;
+
+    mplex_managed_geom((WMPlex*)frame, &mg);
+    
+    /* Adjust geometry */
+    if(!param->inner_geom_gravity_set){
+        iw=REGION_GEOM(reg).w;
+        ih=REGION_GEOM(reg).h;
+        rqg.x=REGION_GEOM(frame).x;
+        rqg.y=REGION_GEOM(frame).y;
+    }else{
+        int bl=mg.x;
+        int br=REGION_GEOM(frame).w-(mg.x+mg.w);
+        int bt=mg.y;
+        int bb=REGION_GEOM(frame).h-(mg.y+mg.h);
+        
+        iw=param->inner_geom.w;
+        ih=param->inner_geom.h;
+        
+        rqg.x=(/*fp->g.x+*/param->inner_geom.x+
+               xgravity_deltax(param->gravity, bl, br));
+        rqg.y=(/*fp->g.y+*/param->inner_geom.y+
+               xgravity_deltay(param->gravity, bt, bb));
+    }
+    
+    /* Some apps seem to request geometries inconsistent with their size hints,
+     * so correct for that here.
+     * Because WGroup(CW) sets no_constrain on the size hints, we have
+     * to set override_no_constrain to force the frame to have the size
+     * of the 'bottom' of the group.
+     */
+    region_size_hints(reg, &szh);
+    sizehints_correct(&szh, &iw, &ih, TRUE, TRUE);
+    rqg.w=maxof(1, iw+(REGION_GEOM(frame).w-mg.w));
+    rqg.h=maxof(1, ih+(REGION_GEOM(frame).h-mg.h));
+    
+    if(!(fp->mode&REGION_FIT_WHATEVER))
+        rectangle_constrain(&rqg, &fp->g);
+    
+    region_fit((WRegion*)frame, &rqg, REGION_FIT_EXACT);
+}
+
+
 WRegion *framed_handler(WWindow *par, 
                         const WFitParams *fp, 
                         void *ap_)
@@ -72,14 +125,10 @@ WRegion *framed_handler(WWindow *par,
     AP *ap=(AP*)ap_;
     WMPlexAttachParams mp=MPLEXATTACHPARAMS_INIT;
     WFramedParam *param=ap->param;
-    WRectangle rqg, mg;
     WFrame *frame;
     WRegion *reg;
     
-    if(param->mkframe!=NULL)
-        frame=(WFrame*)(param->mkframe)(par, fp);
-    else
-        frame=create_frame(par, fp, FRAME_MODE_FLOATING);
+    frame=create_frame(par, fp, param->mode);
     
     if(frame==NULL)
         return NULL;
@@ -89,40 +138,14 @@ WRegion *framed_handler(WWindow *par,
 
     reg=mplex_do_attach(&frame->mplex, &mp, ap->data);
     
+    ap->reg_ret=reg;
+    
     if(reg==NULL){
         destroy_obj((Obj*)frame);
         return NULL;
     }
-
-    if(!(fp->mode&(REGION_FIT_BOUNDS|REGION_FIT_WHATEVER)))
-        return (WRegion*)frame;
-
-    mplex_managed_geom((WMPlex*)frame, &mg);
-
-    /* Adjust geometry */
-    if(!param->inner_geom_gravity_set){
-        rqg.x=REGION_GEOM(frame).x;
-        rqg.y=REGION_GEOM(frame).y;
-        rqg.w=maxof(1, REGION_GEOM(reg).w+(REGION_GEOM(frame).w-mg.w));
-        rqg.h=maxof(1, REGION_GEOM(reg).h+(REGION_GEOM(frame).h-mg.h));
-    }else{
-        int bl=mg.x;
-        int br=REGION_GEOM(frame).w-(mg.x+mg.w);
-        int bt=mg.y;
-        int bb=REGION_GEOM(frame).h-(mg.y+mg.h);
-        
-        rqg.x=(fp->g.x+param->inner_geom.x+
-               xgravity_deltax(param->gravity, bl, br));
-        rqg.y=(fp->g.y+param->inner_geom.y+
-               xgravity_deltay(param->gravity, bt, bb));
-        rqg.w=maxof(1, param->inner_geom.w+(REGION_GEOM(frame).w-mg.w));
-        rqg.h=maxof(1, param->inner_geom.h+(REGION_GEOM(frame).h-mg.h));
-    }
-
-    if(!(fp->mode&REGION_FIT_WHATEVER))
-        rectangle_constrain(&rqg, &fp->g);
     
-    region_fit((WRegion*)frame, &rqg, REGION_FIT_EXACT);
+    frame_adjust_to_initial(frame, fp, param, reg);
     
     return (WRegion*)frame;
 }
@@ -141,6 +164,7 @@ WRegion *region_attach_framed(WRegion *reg, WFramedParam *param,
     
     ap.data=data;
     ap.param=param;
+    ap.reg_ret=NULL;
     
     return fn(reg, fn_param, &data2);
 }
@@ -150,8 +174,16 @@ WRegion *framedpholder_do_attach(WFramedPHolder *ph, int flags,
                                  WRegionAttachData *data)
 {
     WRegionAttachData data2;
+    WFrame *frame;
     AP ap;
     
+    frame=(WFrame*)ph->frame_watch.obj;
+    
+    if(frame!=NULL){
+        WMPlexAttachParams mp=MPLEXATTACHPARAMS_INIT;
+        return mplex_do_attach(&frame->mplex, &mp, data);
+    }
+    
     if(ph->cont==NULL)
         return FALSE;
 
@@ -161,8 +193,18 @@ WRegion *framedpholder_do_attach(WFramedPHolder *ph, int flags,
     
     ap.data=data;
     ap.param=&ph->param;
+    ap.reg_ret=NULL;
         
-    return pholder_attach_(ph->cont, flags, &data2);
+    frame=(WFrame*)pholder_do_attach(ph->cont, flags, &data2);
+    
+    if(frame!=NULL){
+        assert(OBJ_IS(frame, WFrame));
+        watch_setup(&ph->frame_watch, (Obj*)frame, NULL);
+    }
+    
+    return (flags&PHOLDER_ATTACH_RETURN_CREATEROOT
+            ? (WRegion*)frame
+            : ap.reg_ret);
 }
 
 
@@ -174,19 +216,34 @@ WRegion *framedpholder_do_attach(WFramedPHolder *ph, int flags,
 
 bool framedpholder_do_goto(WFramedPHolder *ph)
 {
-    if(ph->cont!=NULL)
-        return pholder_goto(ph->cont);
+    WRegion *frame=(WRegion*)ph->frame_watch.obj;
     
-    return FALSE;
+    if(frame!=NULL)
+        return region_goto((WRegion*)frame);
+    else if(ph->cont!=NULL)
+        return pholder_goto(ph->cont);
+    else
+        return FALSE;
 }
 
 
 WRegion *framedpholder_do_target(WFramedPHolder *ph)
 {
-    if(ph->cont!=NULL)
-        return pholder_target(ph->cont);
+    WRegion *frame=(WRegion*)ph->frame_watch.obj;
+    
+    return (frame!=NULL
+            ? frame
+            : (ph->cont!=NULL
+               ? pholder_target(ph->cont)
+               : NULL));
+}
+
+
+bool framedpholder_stale(WFramedPHolder *ph)
+{
+    WRegion *frame=(WRegion*)ph->frame_watch.obj;
     
-    return NULL;
+    return (frame==NULL && (ph->cont==NULL || pholder_stale(ph->cont)));
 }
 
 
@@ -205,6 +262,9 @@ static DynFunTab framedpholder_dynfuntab[]={
 
     {(DynFun*)pholder_do_target, 
      (DynFun*)framedpholder_do_target},
+     
+    {(DynFun*)pholder_stale, 
+     (DynFun*)framedpholder_stale},
     
     END_DYNFUNTAB
 };