/*
* 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
- * 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 <libtu/objp.h>
#include "mplex.h"
#include "mplexpholder.h"
#include "llist.h"
+#include "framedpholder.h"
+#include "basicpholder.h"
static void mplex_watch_handler(Watch *watch, Obj *mplex);
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;
}
-static WMPlexAttachParams dummy_param={0, 0, {0, 0, 0, 0}, 0, 0};
+static void mplex_get_attach_params(WMPlex *mplex, WStacking *st,
+ WMPlexAttachParams *param)
+{
+ 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;
+}
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));
return FALSE;
}
- if(param==NULL)
- param=&dummy_param;
-
if(st!=NULL){
- if(st->lnode!=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);
- else
- ph->param.flags|=MPLEX_ATTACH_UNNUMBERED;
-
- 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;
+ }
}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)){
/*}}}*/
-/*{{{ Move, attach, layer */
+/*{{{ Move, attach */
+
+
+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){
+ /* 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;
+}
+
+
+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;
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);
+ }
}
}
-WMPlexPHolder *mplex_get_rescue_pholder_for(WMPlex *mplex, WRegion *mgd)
+/*}}}*/
+
+
+/*{{ 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
}
{(DynFun*)pholder_do_target,
(DynFun*)mplexpholder_do_target},
+
+ {(DynFun*)pholder_do_root,
+ (DynFun*)mplexpholder_do_root},
END_DYNFUNTAB
};