2 * ion/ioncore/mplexpholder.c
4 * Copyright (c) Tuomo Valkonen 2005-2008.
6 * See the included file LICENSE for details.
9 #include <libtu/objp.h>
10 #include <libtu/obj.h>
11 #include <libtu/pointer.h>
12 #include <libmainloop/defer.h>
16 #include "mplexpholder.h"
18 #include "framedpholder.h"
19 #include "basicpholder.h"
25 static bool on_ph_list(WMPlexPHolder *ll, WMPlexPHolder *ph)
27 return ph->prev!=NULL;
31 static void mplexpholder_do_link(WMPlexPHolder *ph,
36 assert(mplex==(WMPlex*)ph->mplex && mplex!=NULL);
39 assert(after->after==or_after);
41 if(after->after!=NULL){
42 LINK_ITEM_AFTER(after->after->phs, after, ph, next, prev);
44 assert(on_ph_list(mplex->misc_phs, after));
45 LINK_ITEM_AFTER(mplex->misc_phs, after, ph, next, prev);
47 ph->after=after->after;
48 }else if(or_after!=NULL){
49 LINK_ITEM_FIRST(or_after->phs, ph, next, prev);
52 LINK_ITEM_FIRST(mplex->misc_phs, ph, next, prev);
58 static WMPlexPHolder *get_head(WMPlexPHolder *ph)
61 /* ph->prev==NULL should not happen.. */
62 if(ph->prev==NULL || ph->prev->next==NULL)
71 void mplexpholder_do_unlink(WMPlexPHolder *ph, WMPlex *mplex)
73 if(ph->recreate_pholder!=NULL){
75 ph->next->recreate_pholder=ph->recreate_pholder;
77 /* It might be in use in attach chain! So defer. */
78 mainloop_defer_destroy((Obj*)ph->recreate_pholder);
80 ph->recreate_pholder=NULL;
84 UNLINK_ITEM(ph->after->phs, ph, next, prev);
85 }else if(mplex!=NULL && on_ph_list(mplex->misc_phs, ph)){
86 UNLINK_ITEM(mplex->misc_phs, ph, next, prev);
88 WMPlexPHolder *next=ph->next;
95 assert(next->prev==ph);
112 static void mplex_get_attach_params(WMPlex *mplex, WStacking *st,
113 WMPlexAttachParams *param)
115 param->flags=(MPLEX_ATTACH_SIZEPOLICY|
118 (st->hidden ? MPLEX_ATTACH_HIDDEN : 0)|
119 (st->lnode==NULL ? MPLEX_ATTACH_UNNUMBERED : 0));
120 param->szplcy=st->szplcy;
121 param->geom=REGION_GEOM(st->reg);
122 param->level=st->level;
126 bool mplexpholder_init(WMPlexPHolder *ph, WMPlex *mplex, WStacking *st,
127 WMPlexAttachParams *param)
129 WLListNode *or_after=NULL;
130 WMPlexPHolder *after=NULL;
132 pholder_init(&(ph->ph));
139 ph->recreate_pholder=NULL;
142 mplex_get_attach_params(mplex, st, &ph->param);
145 after=LIST_LAST(st->lnode->phs, next, prev);
149 static WMPlexAttachParams dummy_param={0, 0, {0, 0, 0, 0}, 0, 0};
156 if(!(param->flags&MPLEX_ATTACH_UNNUMBERED)){
157 int index=(param->flags&MPLEX_ATTACH_INDEX
159 : mplex_default_index(mplex));
160 or_after=llist_index_to_after(mplex->mx_list,
161 mplex->mx_current, index);
162 after=(index==LLIST_INDEX_LAST
164 ? LIST_LAST(or_after->phs, next, prev)
165 : LIST_LAST(mplex->misc_phs, next, prev))
170 mplexpholder_do_link(ph, mplex, after, or_after);
176 WMPlexPHolder *create_mplexpholder(WMPlex *mplex,
178 WMPlexAttachParams *param)
180 CREATEOBJ_IMPL(WMPlexPHolder, mplexpholder, (p, mplex, st, param));
184 void mplexpholder_deinit(WMPlexPHolder *ph)
186 mplexpholder_do_unlink(ph, ph->mplex);
187 pholder_deinit(&(ph->ph));
194 /*{{{ Move, attach */
198 WMPlexPHolder *ph, *ph_head;
199 WRegionAttachData *data;
205 static WRegion *recreate_handler(WWindow *par,
206 const WFitParams *fp,
210 WMPlexPHolder *ph=rp->ph, *ph_head=rp->ph_head, *phtmp;
211 WFramedParam *param=rp->param;
214 frame=create_frame(par, fp, param->mode);
219 /* Move pholders to frame */
220 frame->mplex.misc_phs=ph_head;
222 for(phtmp=frame->mplex.misc_phs; phtmp!=NULL; phtmp=phtmp->next)
223 phtmp->mplex=&frame->mplex;
226 if(fp->mode&(REGION_FIT_BOUNDS|REGION_FIT_WHATEVER))
227 ph->param.flags|=MPLEX_ATTACH_WHATEVER;
229 rp->reg_ret=mplex_do_attach_pholder(&frame->mplex, ph, rp->data);
231 ph->param.flags&=~MPLEX_ATTACH_WHATEVER;
233 if(rp->reg_ret==NULL){
235 for(phtmp=frame->mplex.misc_phs; phtmp!=NULL; phtmp=phtmp->next)
238 frame->mplex.misc_phs=NULL;
240 destroy_obj((Obj*)frame);
244 frame_adjust_to_initial(frame, fp, param, rp->reg_ret);
246 return (WRegion*)frame;
251 static WFramedPHolder *get_recreate_ph(WMPlexPHolder *ph)
253 return get_head(ph)->recreate_pholder;
257 static WRegion *mplexpholder_attach_recreate(WMPlexPHolder *ph, int flags,
258 WRegionAttachData *data)
260 WRegionAttachData data2;
266 rp.ph_head=get_head(ph);
268 assert(rp.ph_head!=NULL);
270 fph=rp.ph_head->recreate_pholder;
277 rp.param=&fph->param;
280 data2.type=REGION_ATTACH_NEW;
281 data2.u.n.fn=recreate_handler;
284 frame=pholder_do_attach(fph->cont, flags, &data2);
287 rp.ph_head->recreate_pholder=NULL;
288 /* It might be in use in attach chain! So defer. */
289 mainloop_defer_destroy((Obj*)fph);
296 WRegion *mplexpholder_do_attach(WMPlexPHolder *ph, int flags,
297 WRegionAttachData *data)
299 WMPlex *mplex=ph->mplex;
302 return mplexpholder_attach_recreate(ph, flags, data);
304 if(flags&PHOLDER_ATTACH_SWITCHTO)
305 ph->param.flags|=MPLEX_ATTACH_SWITCHTO;
307 ph->param.flags&=~MPLEX_ATTACH_SWITCHTO;
309 return mplex_do_attach_pholder(mplex, ph, data);
313 bool mplexpholder_move(WMPlexPHolder *ph, WMPlex *mplex,
314 WMPlexPHolder *after,
315 WLListNode *or_after)
317 mplexpholder_do_unlink(ph, ph->mplex);
324 mplexpholder_do_link(ph, mplex, after, or_after);
330 bool mplexpholder_do_goto(WMPlexPHolder *ph)
332 WRegion *reg=(WRegion*)ph->mplex;
335 return region_goto(reg);
337 WFramedPHolder *fph=get_recreate_ph(ph);
340 ? pholder_do_goto((WPHolder*)fph)
346 WRegion *mplexpholder_do_target(WMPlexPHolder *ph)
348 WRegion *reg=(WRegion*)ph->mplex;
353 WFramedPHolder *fph=get_recreate_ph(ph);
356 ? pholder_do_target((WPHolder*)fph)
362 bool mplexpholder_stale(WMPlexPHolder *ph)
364 WRegion *reg=(WRegion*)ph->mplex;
369 WFramedPHolder *fph=get_recreate_ph(ph);
371 return (fph==NULL || pholder_stale((WPHolder*)fph));
379 /*{{{ WMPlex routines */
382 void mplex_move_phs(WMPlex *mplex, WLListNode *node,
383 WMPlexPHolder *after,
384 WLListNode *or_after)
388 assert(node!=or_after);
390 while(node->phs!=NULL){
393 mplexpholder_do_unlink(ph, mplex);
394 mplexpholder_do_link(ph, mplex, after, or_after);
400 void mplex_move_phs_before(WMPlex *mplex, WLListNode *node)
402 WMPlexPHolder *after=NULL;
403 WLListNode *or_after;
405 or_after=LIST_PREV(mplex->mx_list, node, next, prev);
407 after=(or_after!=NULL
408 ? LIST_LAST(or_after->phs, next, prev)
409 : LIST_LAST(mplex->misc_phs, next, prev));
411 mplex_move_phs(mplex, node, after, or_after);
415 WMPlexPHolder *mplex_managed_get_pholder(WMPlex *mplex, WRegion *mgd)
417 WStacking *st=mplex_find_stacking(mplex, mgd);
422 return create_mplexpholder(mplex, st, NULL);
426 void mplex_flatten_phs(WMPlex *mplex)
431 FOR_ALL_NODES_ON_LLIST(node, mplex->mx_list, tmp){
432 WMPlexPHolder *last=(mplex->misc_phs==NULL ? NULL : mplex->misc_phs->prev);
433 mplex_move_phs(mplex, node, last, NULL);
438 void mplex_migrate_phs(WMPlex *src, WMPlex *dst)
440 WLListNode *or_after=LIST_LAST(dst->mx_list, next, prev);
441 WMPlexPHolder *after=(or_after!=NULL
442 ? LIST_LAST(or_after->phs, next, prev)
443 : LIST_LAST(dst->misc_phs, next, prev));
445 while(src->misc_phs!=NULL){
446 WMPlexPHolder *ph=src->misc_phs;
447 mplexpholder_move(ph, dst, after, or_after);
459 WRegion *mplex_rescue_attach(WMPlex *mplex, int flags, WRegionAttachData *data)
461 WMPlexAttachParams param;
465 /* Improved attach parametrisation hack for WMPlex source */
466 if(data->type==REGION_ATTACH_REPARENT){
467 WRegion *reg=data->u.reg;
468 WMPlex *src_mplex=REGION_MANAGER_CHK(reg, WMPlex);
470 WStacking *st=ioncore_find_stacking(reg);
472 mplex_get_attach_params(src_mplex, st, ¶m);
476 param.flags|=(MPLEX_ATTACH_INDEX|
477 (flags&PHOLDER_ATTACH_SWITCHTO ? MPLEX_ATTACH_SWITCHTO : 0));
478 param.index=LLIST_INDEX_LAST;
480 return mplex_do_attach(mplex, ¶m, data);
484 WPHolder *mplex_get_rescue_pholder_for(WMPlex *mplex, WRegion *mgd)
487 WStacking *st=mplex_find_stacking(mplex, mgd);
488 WMPlexAttachParams param;
490 param.flags=MPLEX_ATTACH_INDEX;
491 param.index=LLIST_INDEX_LAST;
493 return create_mplexpholder(mplex, st, ¶m);
495 return (WPHolder*)create_basicpholder((WRegion*)mplex,
496 (WBasicPHolderHandler*)mplex_rescue_attach);
504 /*{{{ Class information */
507 static DynFunTab mplexpholder_dynfuntab[]={
508 {(DynFun*)pholder_do_attach,
509 (DynFun*)mplexpholder_do_attach},
511 {(DynFun*)pholder_do_goto,
512 (DynFun*)mplexpholder_do_goto},
514 {(DynFun*)pholder_do_target,
515 (DynFun*)mplexpholder_do_target},
517 {(DynFun*)pholder_stale,
518 (DynFun*)mplexpholder_stale},
524 IMPLCLASS(WMPlexPHolder, WPHolder, mplexpholder_deinit,
525 mplexpholder_dynfuntab);