]> git.decadent.org.uk Git - ion3.git/blobdiff - ioncore/mplexpholder.c
[svn-upgrade] Integrating new upstream version, ion3 (20071220)
[ion3.git] / ioncore / mplexpholder.c
index 8bb7ddb1e89ee279d3f99ec0229b68dd3e956d63..3cbf5fdc2fa46a87471482c2d71502780fcae14a 100644 (file)
@@ -9,6 +9,7 @@
 #include <libtu/objp.h>
 #include <libtu/obj.h>
 #include <libtu/pointer.h>
+#include <libmainloop/defer.h>
 
 #include "common.h"
 #include "mplex.h"
@@ -18,9 +19,6 @@
 #include "basicpholder.h"
 
 
-static void mplex_watch_handler(Watch *watch, Obj *mplex);
-
-
 /*{{{ Primitives */
 
 
@@ -35,7 +33,7 @@ static void mplexpholder_do_link(WMPlexPHolder *ph,
                                  WMPlexPHolder *after,
                                  WLListNode *or_after)
 {
-    assert(mplex==(WMPlex*)ph->mplex_watch.obj && mplex!=NULL);
+    assert(mplex==(WMPlex*)ph->mplex && mplex!=NULL);
     
     if(after!=NULL){
         assert(after->after==or_after);
@@ -43,44 +41,60 @@ static void mplexpholder_do_link(WMPlexPHolder *ph,
         if(after->after!=NULL){
             LINK_ITEM_AFTER(after->after->phs, after, ph, next, prev);
         }else{
-            assert(on_ph_list(mplex->mx_phs, after));
-            LINK_ITEM_AFTER(mplex->mx_phs, after, ph, next, prev);
+            assert(on_ph_list(mplex->misc_phs, after));
+            LINK_ITEM_AFTER(mplex->misc_phs, after, ph, next, prev);
         }
         ph->after=after->after;
     }else if(or_after!=NULL){
         LINK_ITEM_FIRST(or_after->phs, ph, next, prev);
         ph->after=or_after;
     }else{
-        LINK_ITEM_FIRST(mplex->mx_phs, ph, next, prev);
+        LINK_ITEM_FIRST(mplex->misc_phs, ph, next, prev);
         ph->after=NULL;
     }
 }
 
 
+static WMPlexPHolder *get_head(WMPlexPHolder *ph)
+{
+    while(1){
+        /* ph->prev==NULL should not happen.. */
+        if(ph->prev==NULL || ph->prev->next==NULL)
+            break;
+        ph=ph->prev;
+    }
+    
+    return 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);
+        if(ph->next!=NULL){
+            ph->next->recreate_pholder=ph->recreate_pholder;
+        }else{
+            /* It might be in use in attach chain! So defer. */
+            mainloop_defer_destroy((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 if(mplex!=NULL && on_ph_list(mplex->misc_phs, ph)){
+        UNLINK_ITEM(mplex->misc_phs, ph, next, prev);
     }else{
         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;
+
+        if(next==NULL){
+            next=get_head(ph);
+            assert(next->prev==ph);
+        }
+        next->prev=ph->prev;
     }
     
     ph->after=NULL;
@@ -95,14 +109,6 @@ void mplexpholder_do_unlink(WMPlexPHolder *ph, WMPlex *mplex)
 /*{{{ Init/deinit */
 
 
-static void mplex_watch_handler(Watch *watch, Obj *mplex)
-{
-    WMPlexPHolder *ph=FIELD_TO_STRUCT(WMPlexPHolder, mplex_watch, watch);
-    mplexpholder_do_unlink(ph, (WMPlex*)mplex);
-    pholder_redirect(&(ph->ph), (WRegion*)mplex);
-}
-
-
 static void mplex_get_attach_params(WMPlex *mplex, WStacking *st,
                                     WMPlexAttachParams *param)
 {
@@ -120,27 +126,24 @@ static void mplex_get_attach_params(WMPlex *mplex, WStacking *st,
 bool mplexpholder_init(WMPlexPHolder *ph, WMPlex *mplex, WStacking *st,
                        WMPlexAttachParams *param)
 {
+    WLListNode *or_after=NULL;
+    WMPlexPHolder *after=NULL;
+    
     pholder_init(&(ph->ph));
 
-    watch_init(&(ph->mplex_watch));
+    ph->mplex=mplex;
     ph->after=NULL;
     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));
-        return FALSE;
-    }
 
     if(st!=NULL){
         mplex_get_attach_params(mplex, st, &ph->param);
         
         if(st->lnode!=NULL){
-            mplexpholder_do_link(ph, mplex, 
-                                 LIST_LAST(st->lnode->phs, next, prev), 
-                                 st->lnode);
+            after=LIST_LAST(st->lnode->phs, next, prev);
+            or_after=st->lnode;
         }
     }else{
         static WMPlexAttachParams dummy_param={0, 0, {0, 0, 0, 0}, 0, 0};
@@ -154,18 +157,17 @@ bool mplexpholder_init(WMPlexPHolder *ph, WMPlex *mplex, WStacking *st,
             int index=(param->flags&MPLEX_ATTACH_INDEX
                        ? param->index
                        : mplex_default_index(mplex));
-            WLListNode *or_after=llist_index_to_after(mplex->mx_list, 
-                                                      mplex->mx_current, 
-                                                      index);
-            WMPlexPHolder *after=(index==LLIST_INDEX_LAST
-                                  ? (or_after!=NULL
-                                     ? LIST_LAST(or_after->phs, next, prev) 
-                                     : LIST_LAST(mplex->mx_phs, next, prev))
-                                  : NULL);
-
-            mplexpholder_do_link(ph, mplex, after, or_after);
+            or_after=llist_index_to_after(mplex->mx_list, 
+                                          mplex->mx_current, index);
+            after=(index==LLIST_INDEX_LAST
+                   ? (or_after!=NULL
+                      ? LIST_LAST(or_after->phs, next, prev) 
+                      : LIST_LAST(mplex->misc_phs, next, prev))
+                   : NULL);
         }
     }
+
+    mplexpholder_do_link(ph, mplex, after, or_after);
     
     return TRUE;
 }
@@ -181,8 +183,7 @@ WMPlexPHolder *create_mplexpholder(WMPlex *mplex,
 
 void mplexpholder_deinit(WMPlexPHolder *ph)
 {
-    mplexpholder_do_unlink(ph, (WMPlex*)ph->mplex_watch.obj);
-    watch_reset(&(ph->mplex_watch));
+    mplexpholder_do_unlink(ph, ph->mplex);
     pholder_deinit(&(ph->ph));
 }
 
@@ -197,18 +198,18 @@ typedef struct{
     WMPlexPHolder *ph, *ph_head;
     WRegionAttachData *data;
     WFramedParam *param;
+    WRegion *reg_ret;
 } RP;
 
 
-WRegion *recreate_handler(WWindow *par, 
-                          const WFitParams *fp, 
-                          void *rp_)
+static 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);
     
@@ -216,49 +217,37 @@ WRegion *recreate_handler(WWindow *par,
         return NULL;
     
     /* Move pholders to frame */
-    frame->mplex.mx_phs=ph_head;
+    frame->mplex.misc_phs=ph_head;
     
-    for(phtmp=frame->mplex.mx_phs; phtmp!=NULL; phtmp=phtmp->next)
-        watch_setup(&(phtmp->mplex_watch), (Obj*)frame, mplex_watch_handler);
+    for(phtmp=frame->mplex.misc_phs; phtmp!=NULL; phtmp=phtmp->next)
+        phtmp->mplex=&frame->mplex;
         
     /* 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);
+    rp->reg_ret=mplex_do_attach_pholder(&frame->mplex, ph, rp->data);
 
     ph->param.flags&=~MPLEX_ATTACH_WHATEVER;
 
-    if(reg==NULL){
+    if(rp->reg_ret==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;
+        for(phtmp=frame->mplex.misc_phs; phtmp!=NULL; phtmp=phtmp->next)
+            phtmp->mplex=NULL;
+        
+        frame->mplex.misc_phs=NULL;
     
         destroy_obj((Obj*)frame);
         
         return NULL;
     }else{
-        frame_adjust_to_initial(frame, fp, param, reg);
+        frame_adjust_to_initial(frame, fp, param, rp->reg_ret);
         
         return (WRegion*)frame;
     }
 }
 
 
-static WMPlexPHolder *get_head(WMPlexPHolder *ph)
-{
-    while(1){
-        /* ph->prev==NULL should not happen.. */
-        if(ph->prev==NULL || ph->prev->next==NULL)
-            break;
-        ph=ph->prev;
-    }
-    
-    return ph;
-}
-
-
 static WFramedPHolder *get_recreate_ph(WMPlexPHolder *ph)
 {
     return get_head(ph)->recreate_pholder;
@@ -271,7 +260,7 @@ static WRegion *mplexpholder_attach_recreate(WMPlexPHolder *ph, int flags,
     WRegionAttachData data2;
     WFramedPHolder *fph;
     WPHolder *root;
-    WRegion *reg;
+    WRegion *frame;
     RP rp;
     
     rp.ph_head=get_head(ph);
@@ -286,26 +275,28 @@ static WRegion *mplexpholder_attach_recreate(WMPlexPHolder *ph, int flags,
     rp.ph=ph;
     rp.data=data;
     rp.param=&fph->param;
+    rp.reg_ret=NULL;
     
     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 */
+    frame=pholder_do_attach(fph->cont, flags, &data2);
     
-    if(reg!=NULL){
-        destroy_obj((Obj*)fph);
+    if(frame!=NULL){
         rp.ph_head->recreate_pholder=NULL;
+        /* It might be in use in attach chain! So defer. */
+        mainloop_defer_destroy((Obj*)fph);
     }
-
-    return reg;
+    
+    return rp.reg_ret;
 }
 
 
 WRegion *mplexpholder_do_attach(WMPlexPHolder *ph, int flags,
                                 WRegionAttachData *data)
 {
-    WMPlex *mplex=(WMPlex*)ph->mplex_watch.obj;
+    WMPlex *mplex=ph->mplex;
     
     if(mplex==NULL)
         return mplexpholder_attach_recreate(ph, flags, data);
@@ -322,18 +313,14 @@ WRegion *mplexpholder_do_attach(WMPlexPHolder *ph, int flags,
 bool mplexpholder_move(WMPlexPHolder *ph, WMPlex *mplex, 
                        WMPlexPHolder *after,
                        WLListNode *or_after)
-
 {
-    mplexpholder_do_unlink(ph, (WMPlex*)ph->mplex_watch.obj);
+    mplexpholder_do_unlink(ph, ph->mplex);
 
-    watch_reset(&(ph->mplex_watch));
-    
+    ph->mplex=mplex;
+        
     if(mplex==NULL)
         return TRUE;
     
-    if(!watch_setup(&(ph->mplex_watch), (Obj*)mplex, mplex_watch_handler))
-        return FALSE;
-
     mplexpholder_do_link(ph, mplex, after, or_after);
     
     return TRUE;
@@ -342,7 +329,7 @@ bool mplexpholder_move(WMPlexPHolder *ph, WMPlex *mplex,
 
 bool mplexpholder_do_goto(WMPlexPHolder *ph)
 {
-    WRegion *reg=(WRegion*)ph->mplex_watch.obj;
+    WRegion *reg=(WRegion*)ph->mplex;
     
     if(reg!=NULL){
         return region_goto(reg);
@@ -358,7 +345,7 @@ bool mplexpholder_do_goto(WMPlexPHolder *ph)
 
 WRegion *mplexpholder_do_target(WMPlexPHolder *ph)
 {
-    WRegion *reg=(WRegion*)ph->mplex_watch.obj;
+    WRegion *reg=(WRegion*)ph->mplex;
     
     if(reg!=NULL){
         return reg;
@@ -372,24 +359,16 @@ WRegion *mplexpholder_do_target(WMPlexPHolder *ph)
 }
 
 
-WPHolder *mplexpholder_do_root(WMPlexPHolder *ph)
+bool mplexpholder_stale(WMPlexPHolder *ph)
 {
-    WRegion *reg=(WRegion*)ph->mplex_watch.obj;
+    WRegion *reg=(WRegion*)ph->mplex;
     
     if(reg!=NULL){
-        return &ph->ph;
+        return FALSE;
     }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);
+        return (fph==NULL || pholder_stale((WPHolder*)fph));
     }
 }
 
@@ -427,7 +406,7 @@ void mplex_move_phs_before(WMPlex *mplex, WLListNode *node)
                          
     after=(or_after!=NULL
            ? LIST_LAST(or_after->phs, next, prev)
-           : LIST_LAST(mplex->mx_phs, next, prev));
+           : LIST_LAST(mplex->misc_phs, next, prev));
         
     mplex_move_phs(mplex, node, after, or_after);
 }
@@ -444,6 +423,33 @@ WMPlexPHolder *mplex_managed_get_pholder(WMPlex *mplex, WRegion *mgd)
 }
 
 
+void mplex_flatten_phs(WMPlex *mplex)
+{
+    WLListNode *node;
+    WLListIterTmp tmp;
+
+    FOR_ALL_NODES_ON_LLIST(node, mplex->mx_list, tmp){
+        WMPlexPHolder *last=(mplex->misc_phs==NULL ? NULL : mplex->misc_phs->prev);
+        mplex_move_phs(mplex, node, last, NULL);
+    }
+}
+
+
+void mplex_migrate_phs(WMPlex *src, WMPlex *dst)
+{
+    WLListNode *or_after=LIST_LAST(dst->mx_list, next, prev);
+    WMPlexPHolder *after=(or_after!=NULL
+                          ? LIST_LAST(or_after->phs, next, prev)
+                          : LIST_LAST(dst->misc_phs, next, prev));
+    
+    while(src->misc_phs!=NULL){
+        WMPlexPHolder *ph=src->misc_phs;
+        mplexpholder_move(ph, dst, after, or_after);
+        after=ph;
+    }
+}
+
+
 /*}}}*/
 
 
@@ -508,8 +514,8 @@ static DynFunTab mplexpholder_dynfuntab[]={
     {(DynFun*)pholder_do_target, 
      (DynFun*)mplexpholder_do_target},
      
-    {(DynFun*)pholder_do_root
-     (DynFun*)mplexpholder_do_root},
+    {(DynFun*)pholder_stale
+     (DynFun*)mplexpholder_stale},
 
     END_DYNFUNTAB
 };