/*
* ion/ioncore/mplexpholder.c
*
- * Copyright (c) Tuomo Valkonen 2005-2007.
+ * Copyright (c) Tuomo Valkonen 2005-2008.
*
* See the included file LICENSE for details.
*/
#include <libtu/objp.h>
#include <libtu/obj.h>
#include <libtu/pointer.h>
+#include <libmainloop/defer.h>
#include "common.h"
#include "mplex.h"
#include "basicpholder.h"
-static void mplex_watch_handler(Watch *watch, Obj *mplex);
-
-
/*{{{ Primitives */
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);
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;
/*{{{ 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)
{
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};
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;
}
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));
}
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);
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;
WRegionAttachData data2;
WFramedPHolder *fph;
WPHolder *root;
- WRegion *reg;
+ WRegion *frame;
RP rp;
rp.ph_head=get_head(ph);
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);
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;
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);
WRegion *mplexpholder_do_target(WMPlexPHolder *ph)
{
- WRegion *reg=(WRegion*)ph->mplex_watch.obj;
+ WRegion *reg=(WRegion*)ph->mplex;
if(reg!=NULL){
return reg;
}
-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));
}
}
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);
}
}
+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;
+ }
+}
+
+
/*}}}*/
{(DynFun*)pholder_do_target,
(DynFun*)mplexpholder_do_target},
- {(DynFun*)pholder_do_root,
- (DynFun*)mplexpholder_do_root},
+ {(DynFun*)pholder_stale,
+ (DynFun*)mplexpholder_stale},
END_DYNFUNTAB
};