X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=ioncore%2Fmplexpholder.c;h=2c8461eeade2e9d93d001d973b159ee9ec81e521;hb=e3aec18706513a87eaa7839dfdaf7e0fcd0d8d2a;hp=51166f77edbbc478a41368f20d77e73e20ac4588;hpb=8366314611bf30a0f31d25bf5f5023186fa87692;p=ion3.git diff --git a/ioncore/mplexpholder.c b/ioncore/mplexpholder.c index 51166f7..2c8461e 100644 --- a/ioncore/mplexpholder.c +++ b/ioncore/mplexpholder.c @@ -1,25 +1,22 @@ /* * ion/ioncore/mplexpholder.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 #include #include +#include #include "common.h" #include "mplex.h" #include "mplexpholder.h" #include "llist.h" - - -static void mplex_watch_handler(Watch *watch, Obj *mplex); +#include "framedpholder.h" +#include "basicpholder.h" /*{{{ Primitives */ @@ -36,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); @@ -44,28 +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->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 if(ph->prev!=NULL){ + WMPlexPHolder *next=ph->next; + + ph->prev->next=next; + + if(next==NULL){ + next=get_head(ph); + assert(next->prev==ph); + } + next->prev=ph->prev; }else{ - assert(ph->next==NULL && ph->prev==NULL); + /* 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; @@ -80,70 +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; - - if(!watch_setup(&(ph->mplex_watch), (Obj*)mplex, mplex_watch_handler)){ - pholder_deinit(&(ph->ph)); - return FALSE; - } + ph->recreate_pholder=NULL; - 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; } @@ -159,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)); } @@ -168,17 +195,117 @@ void mplexpholder_deinit(WMPlexPHolder *ph) /*}}}*/ -/*{{{ Move, attach, layer */ +/*{{{ Move, attach */ + + +typedef struct{ + WMPlexPHolder *ph, *ph_head; + WRegionAttachData *data; + WFramedParam *param; + WRegion *reg_ret; +} 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; + + frame=create_frame(par, fp, param->mode); + + if(frame==NULL) + return NULL; + + /* Move pholders to frame */ + frame->mplex.misc_phs=ph_head; + + 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; + + rp->reg_ret=mplex_do_attach_pholder(&frame->mplex, ph, rp->data); + + ph->param.flags&=~MPLEX_ATTACH_WHATEVER; + + if(rp->reg_ret==NULL){ + /* Try to recover */ + 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, rp->reg_ret); + + return (WRegion*)frame; + } +} + + +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 *res; + 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; + rp.reg_ret=NULL; + + data2.type=REGION_ATTACH_NEW; + data2.u.n.fn=recreate_handler; + data2.u.n.param=&rp; + + res=pholder_do_attach(fph->cont, flags, &data2); + + 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 (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; - WRegion *reg=NULL; + WMPlex *mplex=ph->mplex; if(mplex==NULL) - return FALSE; + return mplexpholder_attach_recreate(ph, flags, data); if(flags&PHOLDER_ATTACH_SWITCHTO) ph->param.flags|=MPLEX_ATTACH_SWITCHTO; @@ -192,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; @@ -212,18 +335,47 @@ 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; - 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; + + if(reg!=NULL){ + return reg; + }else{ + WFramedPHolder *fph=get_recreate_ph(ph); + + return (fph!=NULL + ? pholder_do_target((WPHolder*)fph) + : NULL); + } +} + + +bool mplexpholder_stale(WMPlexPHolder *ph) +{ + WRegion *reg=(WRegion*)ph->mplex; + + if(reg!=NULL){ + return FALSE; + }else{ + WFramedPHolder *fph=get_recreate_ph(ph); + + return (fph==NULL || pholder_stale((WPHolder*)fph)); + } } @@ -260,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); } @@ -277,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 } @@ -300,6 +519,9 @@ static DynFunTab mplexpholder_dynfuntab[]={ {(DynFun*)pholder_do_target, (DynFun*)mplexpholder_do_target}, + + {(DynFun*)pholder_stale, + (DynFun*)mplexpholder_stale}, END_DYNFUNTAB };