X-Git-Url: https://git.decadent.org.uk/gitweb/?p=ion3.git;a=blobdiff_plain;f=ioncore%2Fgrouppholder.c;h=052f67725941761d643e4f2d1a286054146f607c;hp=3c2ed30d244334d13a44a2e0a6f227ced3225e5e;hb=HEAD;hpb=d2a43a53786878c1273313249d3b49f6cd559b00 diff --git a/ioncore/grouppholder.c b/ioncore/grouppholder.c index 3c2ed30..052f677 100644 --- a/ioncore/grouppholder.c +++ b/ioncore/grouppholder.c @@ -1,7 +1,7 @@ /* * ion/ioncore/grouppholder.c * - * Copyright (c) Tuomo Valkonen 2005-2007. + * Copyright (c) Tuomo Valkonen 2005-2009. * * See the included file LICENSE for details. */ @@ -9,26 +9,97 @@ #include #include #include +#include #include #include "group.h" +#include "group-cw.h" #include "grouppholder.h" static void group_watch_handler(Watch *watch, Obj *ws); -/*{{{ Init/deinit */ +/*{{{ Primitives */ + + +void grouppholder_do_link(WGroupPHolder *ph, WGroup *group, WRegion *stack_above) +{ + ph->group=group; + + if(group!=NULL){ + LINK_ITEM_FIRST(group->phs, ph, next, prev); + }else{ + /* This seems very crucial for detached pholders... */ + ph->next=NULL; + ph->prev=ph; + } + + /* We must move stack_above pointer into a Watch. */ + if(stack_above!=NULL) + watch_setup(&(ph->stack_above_watch), (Obj*)stack_above, NULL); +} -static void group_watch_handler(Watch *watch, Obj *ws) +static WGroupPHolder *get_head(WGroupPHolder *ph) { - WGroupPHolder *ph=FIELD_TO_STRUCT(WGroupPHolder, - group_watch, watch); - pholder_redirect(&(ph->ph), (WRegion*)ws); + while(1){ + /* ph->prev==NULL should not happen.. */ + if(ph->prev==NULL || ph->prev->next==NULL) + break; + ph=ph->prev; + } + + return ph; } +void grouppholder_do_unlink(WGroupPHolder *ph) +{ + WGroup *group=ph->group; + + watch_reset(&(ph->stack_above_watch)); + + 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(group!=NULL){ + UNLINK_ITEM(group->phs, ph, next, prev); + }else if(ph->prev!=NULL){ + WGroupPHolder *next=ph->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->group=NULL; + ph->next=NULL; + ph->prev=NULL; +} + + +/*}}}*/ + + +/*{{{ Init/deinit */ + static WGroupAttachParams dummy_param=GROUPATTACHPARAMS_INIT; @@ -36,22 +107,17 @@ bool grouppholder_init(WGroupPHolder *ph, WGroup *ws, const WStacking *st, const WGroupAttachParams *param) { + WRegion *stack_above=NULL; + pholder_init(&(ph->ph)); - watch_init(&(ph->group_watch)); watch_init(&(ph->stack_above_watch)); - - if(ws!=NULL){ - if(!watch_setup(&(ph->group_watch), (Obj*)ws, - group_watch_handler)){ - pholder_deinit(&(ph->ph)); - return FALSE; - } - } - - if(param==NULL) - param=&dummy_param; - + ph->next=NULL; + ph->prev=NULL; + ph->group=NULL; + ph->recreate_pholder=NULL; + ph->param=(param==NULL ? dummy_param : *param); + if(st!=NULL){ /* TODO? Just link to the stacking structure to remember * stacking order? @@ -71,22 +137,18 @@ bool grouppholder_init(WGroupPHolder *ph, WGroup *ws, ph->param.stack_above=st->above->reg; ph->param.bottom=(st==ws->bottom); - }else{ - ph->param=*param; } - + ph->param.switchto_set=FALSE; - - if(ph->param.stack_above!=NULL){ - /* We must move stack_above pointer into a Watch. */ - watch_setup(&(ph->stack_above_watch), - (Obj*)ph->param.stack_above, NULL); - ph->param.stack_above=NULL; - } + + stack_above=ph->param.stack_above; + ph->param.stack_above=NULL; + + grouppholder_do_link(ph, ws, stack_above); return TRUE; } - + WGroupPHolder *create_grouppholder(WGroup *ws, const WStacking *st, @@ -98,8 +160,8 @@ WGroupPHolder *create_grouppholder(WGroup *ws, void grouppholder_deinit(WGroupPHolder *ph) { - watch_reset(&(ph->group_watch)); - watch_reset(&(ph->stack_above_watch)); + grouppholder_do_unlink(ph); + pholder_deinit(&(ph->ph)); } @@ -110,15 +172,104 @@ void grouppholder_deinit(WGroupPHolder *ph) /*{{{ Dynfuns */ +static WPHolder *get_recreate_ph(WGroupPHolder *ph) +{ + return get_head(ph)->recreate_pholder; +} + + +typedef struct{ + WGroupPHolder *ph, *ph_head; + WRegionAttachData *data; + WRegion *reg_ret; +} RP; + + +static WRegion *recreate_handler(WWindow *par, + const WFitParams *fp, + void *rp_) +{ + WGroupPHolder *phtmp; + RP *rp=(RP*)rp_; + WGroup *grp; + + grp=(WGroup*)create_groupcw(par, fp); + + if(grp==NULL) + return NULL; + + rp->ph->param.whatever=(fp->mode®ION_FIT_WHATEVER ? 1 : 0); + + rp->reg_ret=group_do_attach(grp, &rp->ph->param, rp->data); + + rp->ph->param.whatever=0; + + if(rp->reg_ret==NULL){ + destroy_obj((Obj*)grp); + return NULL; + }else{ + grp->phs=rp->ph_head; + + for(phtmp=grp->phs; phtmp!=NULL; phtmp=phtmp->next) + phtmp->group=grp; + } + + if(fp->mode®ION_FIT_WHATEVER) + REGION_GEOM(grp)=REGION_GEOM(rp->reg_ret); + + return (WRegion*)grp; +} + + + +static WRegion *grouppholder_attach_recreate(WGroupPHolder *ph, int flags, + WRegionAttachData *data) +{ + WRegionAttachData data2; + WPHolder *root, *rph; + WRegion *res; + RP rp; + + rp.ph_head=get_head(ph); + + assert(rp.ph_head!=NULL); + + rph=rp.ph_head->recreate_pholder; + + if(rph==NULL) + return NULL; + + rp.ph=ph; + rp.data=data; + rp.reg_ret=NULL; + + data2.type=REGION_ATTACH_NEW; + data2.u.n.fn=recreate_handler; + data2.u.n.param=&rp; + + res=pholder_do_attach(rph, 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*)rph); + } + + return (flags&PHOLDER_ATTACH_RETURN_CREATEROOT + ? (WRegion*)res + : rp.reg_ret); +} + + WRegion *grouppholder_do_attach(WGroupPHolder *ph, int flags, WRegionAttachData *data) { - WGroup *ws=(WGroup*)ph->group_watch.obj; + WGroup *ws=ph->group; WRegion *reg; if(ws==NULL) - return FALSE; - + return grouppholder_attach_recreate(ph, flags, data); + ph->param.switchto_set=1; ph->param.switchto=(flags&PHOLDER_ATTACH_SWITCHTO ? 1 : 0); @@ -135,18 +286,21 @@ WRegion *grouppholder_do_attach(WGroupPHolder *ph, int flags, bool grouppholder_do_goto(WGroupPHolder *ph) { - WGroup *ws=(WGroup*)ph->group_watch.obj; - - if(ws!=NULL) - return region_goto((WRegion*)ws); - - return FALSE; + return (ph->group!=NULL + ? region_goto((WRegion*)ph->group) + : (ph->recreate_pholder!=NULL + ? pholder_do_goto(ph->recreate_pholder) + : FALSE)); } WRegion *grouppholder_do_target(WGroupPHolder *ph) { - return (WRegion*)ph->group_watch.obj; + return (ph->group!=NULL + ? (WRegion*)ph->group + : (ph->recreate_pholder!=NULL + ? pholder_do_target(ph->recreate_pholder) + : NULL)); }