X-Git-Url: https://git.decadent.org.uk/gitweb/?p=ion3.git;a=blobdiff_plain;f=ioncore%2Fmplexpholder.c;h=2c8461eeade2e9d93d001d973b159ee9ec81e521;hp=478ac2dd61e2152b5eb3a3cf88bed0af81fbb680;hb=HEAD;hpb=768d45580fc176cedd04db0b05621cdf596751d5 diff --git a/ioncore/mplexpholder.c b/ioncore/mplexpholder.c index 478ac2d..2c8461e 100644 --- a/ioncore/mplexpholder.c +++ b/ioncore/mplexpholder.c @@ -1,26 +1,22 @@ /* * ion/ioncore/mplexpholder.c * - * Copyright (c) Tuomo Valkonen 2005-2007. + * 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 #include #include +#include #include "common.h" #include "mplex.h" #include "mplexpholder.h" #include "llist.h" #include "framedpholder.h" - - -static void mplex_watch_handler(Watch *watch, Obj *mplex); +#include "basicpholder.h" /*{{{ Primitives */ @@ -37,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); @@ -45,44 +41,64 @@ 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{ + }else if(mplex!=NULL && on_ph_list(mplex->misc_phs, ph)){ + UNLINK_ITEM(mplex->misc_phs, ph, next, prev); + }else if(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->prev->next=next; + + if(next==NULL){ + next=get_head(ph); + assert(next->prev==ph); + } + next->prev=ph->prev; + }else{ + /* ph should not be on a list, if prev pointer is NULL (whereas + * next alone can be NULL in our semi-doubly-linked lists). + */ + assert(ph->next==NULL); } ph->after=NULL; @@ -97,71 +113,65 @@ void mplexpholder_do_unlink(WMPlexPHolder *ph, WMPlex *mplex) /*{{{ Init/deinit */ -static void mplex_watch_handler(Watch *watch, Obj *mplex) +static void mplex_get_attach_params(WMPlex *mplex, WStacking *st, + WMPlexAttachParams *param) { - WMPlexPHolder *ph=FIELD_TO_STRUCT(WMPlexPHolder, mplex_watch, watch); - mplexpholder_do_unlink(ph, (WMPlex*)mplex); - pholder_redirect(&(ph->ph), (WRegion*)mplex); + param->flags=(MPLEX_ATTACH_SIZEPOLICY| + MPLEX_ATTACH_GEOM| + MPLEX_ATTACH_LEVEL| + (st->hidden ? MPLEX_ATTACH_HIDDEN : 0)| + (st->lnode==NULL ? MPLEX_ATTACH_UNNUMBERED : 0)); + param->szplcy=st->szplcy; + param->geom=REGION_GEOM(st->reg); + param->level=st->level; } -static WMPlexAttachParams dummy_param={0, 0, {0, 0, 0, 0}, 0, 0}; - - 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(param==NULL) - param=&dummy_param; - if(st!=NULL){ - if(st->lnode!=NULL) - mplexpholder_do_link(ph, mplex, - LIST_LAST(st->lnode->phs, next, prev), - st->lnode); - else - ph->param.flags|=MPLEX_ATTACH_UNNUMBERED; + mplex_get_attach_params(mplex, st, &ph->param); - ph->param.flags|=(MPLEX_ATTACH_SIZEPOLICY| - MPLEX_ATTACH_GEOM| - MPLEX_ATTACH_LEVEL| - (st->hidden ? MPLEX_ATTACH_HIDDEN : 0)); - ph->param.szplcy=st->szplcy; - ph->param.geom=REGION_GEOM(st->reg); - ph->param.level=st->level; + if(st->lnode!=NULL){ + 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}; + + if(param==NULL) + param=&dummy_param; + ph->param=*param; if(!(param->flags&MPLEX_ATTACH_UNNUMBERED)){ 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; } @@ -177,8 +187,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)); } @@ -186,25 +195,25 @@ void mplexpholder_deinit(WMPlexPHolder *ph) /*}}}*/ -/*{{{ Move, attach, layer */ +/*{{{ Move, attach */ 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); @@ -212,49 +221,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; @@ -267,7 +264,7 @@ static WRegion *mplexpholder_attach_recreate(WMPlexPHolder *ph, int flags, WRegionAttachData data2; WFramedPHolder *fph; WPHolder *root; - WRegion *reg; + WRegion *res; RP rp; rp.ph_head=get_head(ph); @@ -282,26 +279,30 @@ 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 */ + res=pholder_do_attach(fph->cont, flags, &data2); - if(reg!=NULL){ - destroy_obj((Obj*)fph); + if(res!=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 (flags&PHOLDER_ATTACH_RETURN_CREATEROOT + ? (WRegion*)res + : 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); @@ -318,18 +319,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; @@ -338,7 +335,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); @@ -354,7 +351,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; @@ -368,24 +365,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)); } } @@ -423,7 +412,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); } @@ -440,11 +429,78 @@ WMPlexPHolder *mplex_managed_get_pholder(WMPlex *mplex, WRegion *mgd) } -WMPlexPHolder *mplex_get_rescue_pholder_for(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; + } +} + + +/*}}}*/ + + +/*{{ Rescue */ + + +WRegion *mplex_rescue_attach(WMPlex *mplex, int flags, WRegionAttachData *data) +{ + WMPlexAttachParams param; + + param.flags=0; + + /* Improved attach parametrisation hack for WMPlex source */ + if(data->type==REGION_ATTACH_REPARENT){ + WRegion *reg=data->u.reg; + WMPlex *src_mplex=REGION_MANAGER_CHK(reg, WMPlex); + if(src_mplex!=NULL){ + WStacking *st=ioncore_find_stacking(reg); + if(st!=NULL) + mplex_get_attach_params(src_mplex, st, ¶m); + } + } + + param.flags|=(MPLEX_ATTACH_INDEX| + (flags&PHOLDER_ATTACH_SWITCHTO ? MPLEX_ATTACH_SWITCHTO : 0)); + param.index=LLIST_INDEX_LAST; + + return mplex_do_attach(mplex, ¶m, data); +} + + +WPHolder *mplex_get_rescue_pholder_for(WMPlex *mplex, WRegion *mgd) { +#if 0 WStacking *st=mplex_find_stacking(mplex, mgd); + WMPlexAttachParams param; + + param.flags=MPLEX_ATTACH_INDEX; + param.index=LLIST_INDEX_LAST; - return create_mplexpholder(mplex, st, NULL); + return create_mplexpholder(mplex, st, ¶m); +#else + return (WPHolder*)create_basicpholder((WRegion*)mplex, + (WBasicPHolderHandler*)mplex_rescue_attach); +#endif } @@ -464,8 +520,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 };