]> git.decadent.org.uk Git - ion3.git/blobdiff - ioncore/mplexpholder.c
[svn-upgrade] Integrating new upstream version, ion3 (20070203)
[ion3.git] / ioncore / mplexpholder.c
index 51166f77edbbc478a41368f20d77e73e20ac4588..f6d089a2a5cc89fbbbcbec7fb9f1739c90a184ec 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * ion/ioncore/mplexpholder.c
  *
- * Copyright (c) Tuomo Valkonen 2005-2006
+ * Copyright (c) Tuomo Valkonen 2005-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
@@ -17,6 +17,7 @@
 #include "mplex.h"
 #include "mplexpholder.h"
 #include "llist.h"
+#include "framedpholder.h"
 
 
 static void mplex_watch_handler(Watch *watch, Obj *mplex);
@@ -60,12 +61,28 @@ static void mplexpholder_do_link(WMPlexPHolder *ph,
 
 void mplexpholder_do_unlink(WMPlexPHolder *ph, WMPlex *mplex)
 {
+    if(ph->recreate_pholder!=NULL){
+        if(ph->prev!=NULL)
+            ph->prev->recreate_pholder=ph->recreate_pholder;
+        else
+            destroy_obj((Obj*)ph->recreate_pholder);
+        ph->recreate_pholder=NULL;
+    }
+    
     if(ph->after!=NULL){
         UNLINK_ITEM(ph->after->phs, ph, next, prev);
     }else if(mplex!=NULL && on_ph_list(mplex->mx_phs, ph)){
         UNLINK_ITEM(mplex->mx_phs, ph, next, prev);
     }else{
-        assert(ph->next==NULL && ph->prev==NULL);
+        WMPlexPHolder *next=ph->next;
+    
+        assert((ph->next==NULL && ph->prev==NULL)
+               || ph->mplex_watch.obj==NULL);
+        
+        if(ph->next!=NULL)
+            ph->next->prev=ph->prev;
+        if(ph->prev!=NULL)
+            ph->prev->next=next;
     }
     
     ph->after=NULL;
@@ -101,6 +118,7 @@ bool mplexpholder_init(WMPlexPHolder *ph, WMPlex *mplex, WStacking *st,
     ph->next=NULL;
     ph->prev=NULL;
     ph->param.flags=0;
+    ph->recreate_pholder=NULL;
     
     if(!watch_setup(&(ph->mplex_watch), (Obj*)mplex, mplex_watch_handler)){
         pholder_deinit(&(ph->ph));
@@ -171,14 +189,121 @@ void mplexpholder_deinit(WMPlexPHolder *ph)
 /*{{{ Move, attach, layer */
 
 
+typedef struct{
+    WMPlexPHolder *ph, *ph_head;
+    WRegionAttachData *data;
+    WFramedParam *param;
+} RP;
+
+
+WRegion *recreate_handler(WWindow *par, 
+                          const WFitParams *fp, 
+                          void *rp_)
+{
+    RP *rp=(RP*)rp_;
+    WMPlexPHolder *ph=rp->ph, *ph_head=rp->ph_head, *phtmp;
+    WFramedParam *param=rp->param;
+    WFrame *frame;
+    WRegion *reg;
+    
+    frame=create_frame(par, fp, param->mode);
+    
+    if(frame==NULL)
+        return NULL;
+    
+    /* Move pholders to frame */
+    frame->mplex.mx_phs=ph_head;
+    
+    for(phtmp=frame->mplex.mx_phs; phtmp!=NULL; phtmp=phtmp->next)
+        watch_setup(&(phtmp->mplex_watch), (Obj*)frame, mplex_watch_handler);
+        
+    /* Attach */
+    if(fp->mode&(REGION_FIT_BOUNDS|REGION_FIT_WHATEVER))
+        ph->param.flags|=MPLEX_ATTACH_WHATEVER;
+    
+    reg=mplex_do_attach_pholder(&frame->mplex, ph, rp->data);
+
+    ph->param.flags&=~MPLEX_ATTACH_WHATEVER;
+
+    if(reg==NULL){
+        /* Try to recover */
+        for(phtmp=frame->mplex.mx_phs; phtmp!=NULL; phtmp=phtmp->next)
+            watch_reset(&(phtmp->mplex_watch));
+        frame->mplex.mx_phs=NULL;
+    
+        destroy_obj((Obj*)frame);
+        
+        return NULL;
+    }else{
+        frame_adjust_to_initial(frame, fp, param, reg);
+        
+        return (WRegion*)frame;
+    }
+}
+
+
+static WMPlexPHolder *get_head(WMPlexPHolder *ph)
+{
+    while(1){
+        if(ph->prev->next==NULL)
+            break;
+        ph=ph->prev;
+    }
+    
+    return ph;
+}
+
+
+static WFramedPHolder *get_recreate_ph(WMPlexPHolder *ph)
+{
+    return get_head(ph)->recreate_pholder;
+}
+
+    
+static WRegion *mplexpholder_attach_recreate(WMPlexPHolder *ph, int flags,
+                                             WRegionAttachData *data)
+{
+    WRegionAttachData data2;
+    WFramedPHolder *fph;
+    WPHolder *root;
+    WRegion *reg;
+    RP rp;
+    
+    rp.ph_head=get_head(ph);
+    
+    assert(rp.ph_head!=NULL);
+    
+    fph=rp.ph_head->recreate_pholder;
+    
+    if(fph==NULL)
+        return NULL;
+    
+    rp.ph=ph;
+    rp.data=data;
+    rp.param=&fph->param;
+    
+    data2.type=REGION_ATTACH_NEW;
+    data2.u.n.fn=recreate_handler;
+    data2.u.n.param=&rp;
+    
+    reg=pholder_do_attach(fph->cont, flags, &data2); /* == frame */
+    
+    if(reg!=NULL){
+        destroy_obj((Obj*)fph);
+        rp.ph_head->recreate_pholder=NULL;
+    }
+
+    return reg;
+}
+
+
 WRegion *mplexpholder_do_attach(WMPlexPHolder *ph, int flags,
                                 WRegionAttachData *data)
 {
     WMPlex *mplex=(WMPlex*)ph->mplex_watch.obj;
-    WRegion *reg=NULL;
     
     if(mplex==NULL)
-        return FALSE;
+        return mplexpholder_attach_recreate(ph, flags, data);
     
     if(flags&PHOLDER_ATTACH_SWITCHTO)
         ph->param.flags|=MPLEX_ATTACH_SWITCHTO;
@@ -212,18 +337,55 @@ bool mplexpholder_move(WMPlexPHolder *ph, WMPlex *mplex,
 
 bool mplexpholder_do_goto(WMPlexPHolder *ph)
 {
-    WMPlex *mplex=(WMPlex*)ph->mplex_watch.obj;
-    
-    if(mplex!=NULL)
-        return region_goto((WRegion*)mplex);
+    WRegion *reg=(WRegion*)ph->mplex_watch.obj;
     
-    return FALSE;
+    if(reg!=NULL){
+        return region_goto(reg);
+    }else{
+        WFramedPHolder *fph=get_recreate_ph(ph);
+        
+        return (fph!=NULL
+                ? pholder_do_goto((WPHolder*)fph)
+                : FALSE);
+    }
 }
 
 
 WRegion *mplexpholder_do_target(WMPlexPHolder *ph)
 {
-    return (WRegion*)ph->mplex_watch.obj;
+    WRegion *reg=(WRegion*)ph->mplex_watch.obj;
+    
+    if(reg!=NULL){
+        return reg;
+    }else{
+        WFramedPHolder *fph=get_recreate_ph(ph);
+        
+        return (fph!=NULL
+                ? pholder_do_target((WPHolder*)fph)
+                : NULL);
+    }
+}
+
+
+WPHolder *mplexpholder_do_root(WMPlexPHolder *ph)
+{
+    WRegion *reg=(WRegion*)ph->mplex_watch.obj;
+    
+    if(reg!=NULL){
+        return &ph->ph;
+    }else{
+        WFramedPHolder *fph=get_recreate_ph(ph);
+        WPHolder *root;
+        
+        if(fph==NULL)
+            return NULL;
+    
+        root=pholder_root((WPHolder*)fph);
+    
+        return (root!=(WPHolder*)fph
+                ? root
+                : &ph->ph);
+    }
 }
 
 
@@ -300,6 +462,9 @@ static DynFunTab mplexpholder_dynfuntab[]={
 
     {(DynFun*)pholder_do_target, 
      (DynFun*)mplexpholder_do_target},
+     
+    {(DynFun*)pholder_do_root, 
+     (DynFun*)mplexpholder_do_root},
 
     END_DYNFUNTAB
 };