2 * ion/ioncore/mplexpholder.c
4 * Copyright (c) Tuomo Valkonen 2005-2007.
6 * See the included file LICENSE for details.
9 #include <libtu/objp.h>
10 #include <libtu/obj.h>
11 #include <libtu/pointer.h>
15 #include "mplexpholder.h"
17 #include "framedpholder.h"
18 #include "basicpholder.h"
21 static void mplex_watch_handler(Watch *watch, Obj *mplex);
27 static bool on_ph_list(WMPlexPHolder *ll, WMPlexPHolder *ph)
29 return ph->prev!=NULL;
33 static void mplexpholder_do_link(WMPlexPHolder *ph,
38 assert(mplex==(WMPlex*)ph->mplex_watch.obj && mplex!=NULL);
41 assert(after->after==or_after);
43 if(after->after!=NULL){
44 LINK_ITEM_AFTER(after->after->phs, after, ph, next, prev);
46 assert(on_ph_list(mplex->mx_phs, after));
47 LINK_ITEM_AFTER(mplex->mx_phs, after, ph, next, prev);
49 ph->after=after->after;
50 }else if(or_after!=NULL){
51 LINK_ITEM_FIRST(or_after->phs, ph, next, prev);
54 LINK_ITEM_FIRST(mplex->mx_phs, ph, next, prev);
60 void mplexpholder_do_unlink(WMPlexPHolder *ph, WMPlex *mplex)
62 if(ph->recreate_pholder!=NULL){
64 ph->prev->recreate_pholder=ph->recreate_pholder;
66 destroy_obj((Obj*)ph->recreate_pholder);
67 ph->recreate_pholder=NULL;
71 UNLINK_ITEM(ph->after->phs, ph, next, prev);
72 }else if(mplex!=NULL && on_ph_list(mplex->mx_phs, ph)){
73 UNLINK_ITEM(mplex->mx_phs, ph, next, prev);
75 WMPlexPHolder *next=ph->next;
77 assert((ph->next==NULL && ph->prev==NULL)
78 || ph->mplex_watch.obj==NULL);
81 ph->next->prev=ph->prev;
98 static void mplex_watch_handler(Watch *watch, Obj *mplex)
100 WMPlexPHolder *ph=FIELD_TO_STRUCT(WMPlexPHolder, mplex_watch, watch);
101 mplexpholder_do_unlink(ph, (WMPlex*)mplex);
102 pholder_redirect(&(ph->ph), (WRegion*)mplex);
106 static void mplex_get_attach_params(WMPlex *mplex, WStacking *st,
107 WMPlexAttachParams *param)
109 param->flags=(MPLEX_ATTACH_SIZEPOLICY|
112 (st->hidden ? MPLEX_ATTACH_HIDDEN : 0)|
113 (st->lnode==NULL ? MPLEX_ATTACH_UNNUMBERED : 0));
114 param->szplcy=st->szplcy;
115 param->geom=REGION_GEOM(st->reg);
116 param->level=st->level;
120 bool mplexpholder_init(WMPlexPHolder *ph, WMPlex *mplex, WStacking *st,
121 WMPlexAttachParams *param)
123 pholder_init(&(ph->ph));
125 watch_init(&(ph->mplex_watch));
130 ph->recreate_pholder=NULL;
132 if(!watch_setup(&(ph->mplex_watch), (Obj*)mplex, mplex_watch_handler)){
133 pholder_deinit(&(ph->ph));
138 mplex_get_attach_params(mplex, st, &ph->param);
141 mplexpholder_do_link(ph, mplex,
142 LIST_LAST(st->lnode->phs, next, prev),
146 static WMPlexAttachParams dummy_param={0, 0, {0, 0, 0, 0}, 0, 0};
153 if(!(param->flags&MPLEX_ATTACH_UNNUMBERED)){
154 int index=(param->flags&MPLEX_ATTACH_INDEX
156 : mplex_default_index(mplex));
157 WLListNode *or_after=llist_index_to_after(mplex->mx_list,
160 WMPlexPHolder *after=(index==LLIST_INDEX_LAST
162 ? LIST_LAST(or_after->phs, next, prev)
163 : LIST_LAST(mplex->mx_phs, next, prev))
166 mplexpholder_do_link(ph, mplex, after, or_after);
174 WMPlexPHolder *create_mplexpholder(WMPlex *mplex,
176 WMPlexAttachParams *param)
178 CREATEOBJ_IMPL(WMPlexPHolder, mplexpholder, (p, mplex, st, param));
182 void mplexpholder_deinit(WMPlexPHolder *ph)
184 mplexpholder_do_unlink(ph, (WMPlex*)ph->mplex_watch.obj);
185 watch_reset(&(ph->mplex_watch));
186 pholder_deinit(&(ph->ph));
193 /*{{{ Move, attach */
197 WMPlexPHolder *ph, *ph_head;
198 WRegionAttachData *data;
203 WRegion *recreate_handler(WWindow *par,
204 const WFitParams *fp,
208 WMPlexPHolder *ph=rp->ph, *ph_head=rp->ph_head, *phtmp;
209 WFramedParam *param=rp->param;
213 frame=create_frame(par, fp, param->mode);
218 /* Move pholders to frame */
219 frame->mplex.mx_phs=ph_head;
221 for(phtmp=frame->mplex.mx_phs; phtmp!=NULL; phtmp=phtmp->next)
222 watch_setup(&(phtmp->mplex_watch), (Obj*)frame, mplex_watch_handler);
225 if(fp->mode&(REGION_FIT_BOUNDS|REGION_FIT_WHATEVER))
226 ph->param.flags|=MPLEX_ATTACH_WHATEVER;
228 reg=mplex_do_attach_pholder(&frame->mplex, ph, rp->data);
230 ph->param.flags&=~MPLEX_ATTACH_WHATEVER;
234 for(phtmp=frame->mplex.mx_phs; phtmp!=NULL; phtmp=phtmp->next)
235 watch_reset(&(phtmp->mplex_watch));
236 frame->mplex.mx_phs=NULL;
238 destroy_obj((Obj*)frame);
242 frame_adjust_to_initial(frame, fp, param, reg);
244 return (WRegion*)frame;
249 static WMPlexPHolder *get_head(WMPlexPHolder *ph)
252 /* ph->prev==NULL should not happen.. */
253 if(ph->prev==NULL || ph->prev->next==NULL)
262 static WFramedPHolder *get_recreate_ph(WMPlexPHolder *ph)
264 return get_head(ph)->recreate_pholder;
268 static WRegion *mplexpholder_attach_recreate(WMPlexPHolder *ph, int flags,
269 WRegionAttachData *data)
271 WRegionAttachData data2;
277 rp.ph_head=get_head(ph);
279 assert(rp.ph_head!=NULL);
281 fph=rp.ph_head->recreate_pholder;
288 rp.param=&fph->param;
290 data2.type=REGION_ATTACH_NEW;
291 data2.u.n.fn=recreate_handler;
294 reg=pholder_do_attach(fph->cont, flags, &data2); /* == frame */
297 destroy_obj((Obj*)fph);
298 rp.ph_head->recreate_pholder=NULL;
305 WRegion *mplexpholder_do_attach(WMPlexPHolder *ph, int flags,
306 WRegionAttachData *data)
308 WMPlex *mplex=(WMPlex*)ph->mplex_watch.obj;
311 return mplexpholder_attach_recreate(ph, flags, data);
313 if(flags&PHOLDER_ATTACH_SWITCHTO)
314 ph->param.flags|=MPLEX_ATTACH_SWITCHTO;
316 ph->param.flags&=~MPLEX_ATTACH_SWITCHTO;
318 return mplex_do_attach_pholder(mplex, ph, data);
322 bool mplexpholder_move(WMPlexPHolder *ph, WMPlex *mplex,
323 WMPlexPHolder *after,
324 WLListNode *or_after)
327 mplexpholder_do_unlink(ph, (WMPlex*)ph->mplex_watch.obj);
329 watch_reset(&(ph->mplex_watch));
334 if(!watch_setup(&(ph->mplex_watch), (Obj*)mplex, mplex_watch_handler))
337 mplexpholder_do_link(ph, mplex, after, or_after);
343 bool mplexpholder_do_goto(WMPlexPHolder *ph)
345 WRegion *reg=(WRegion*)ph->mplex_watch.obj;
348 return region_goto(reg);
350 WFramedPHolder *fph=get_recreate_ph(ph);
353 ? pholder_do_goto((WPHolder*)fph)
359 WRegion *mplexpholder_do_target(WMPlexPHolder *ph)
361 WRegion *reg=(WRegion*)ph->mplex_watch.obj;
366 WFramedPHolder *fph=get_recreate_ph(ph);
369 ? pholder_do_target((WPHolder*)fph)
375 WPHolder *mplexpholder_do_root(WMPlexPHolder *ph)
377 WRegion *reg=(WRegion*)ph->mplex_watch.obj;
382 WFramedPHolder *fph=get_recreate_ph(ph);
388 root=pholder_root((WPHolder*)fph);
390 return (root!=(WPHolder*)fph
400 /*{{{ WMPlex routines */
403 void mplex_move_phs(WMPlex *mplex, WLListNode *node,
404 WMPlexPHolder *after,
405 WLListNode *or_after)
409 assert(node!=or_after);
411 while(node->phs!=NULL){
414 mplexpholder_do_unlink(ph, mplex);
415 mplexpholder_do_link(ph, mplex, after, or_after);
421 void mplex_move_phs_before(WMPlex *mplex, WLListNode *node)
423 WMPlexPHolder *after=NULL;
424 WLListNode *or_after;
426 or_after=LIST_PREV(mplex->mx_list, node, next, prev);
428 after=(or_after!=NULL
429 ? LIST_LAST(or_after->phs, next, prev)
430 : LIST_LAST(mplex->mx_phs, next, prev));
432 mplex_move_phs(mplex, node, after, or_after);
436 WMPlexPHolder *mplex_managed_get_pholder(WMPlex *mplex, WRegion *mgd)
438 WStacking *st=mplex_find_stacking(mplex, mgd);
443 return create_mplexpholder(mplex, st, NULL);
453 WRegion *mplex_rescue_attach(WMPlex *mplex, int flags, WRegionAttachData *data)
455 WMPlexAttachParams param;
459 /* Improved attach parametrisation hack for WMPlex source */
460 if(data->type==REGION_ATTACH_REPARENT){
461 WRegion *reg=data->u.reg;
462 WMPlex *src_mplex=REGION_MANAGER_CHK(reg, WMPlex);
464 WStacking *st=ioncore_find_stacking(reg);
466 mplex_get_attach_params(src_mplex, st, ¶m);
470 param.flags|=(MPLEX_ATTACH_INDEX|
471 (flags&PHOLDER_ATTACH_SWITCHTO ? MPLEX_ATTACH_SWITCHTO : 0));
472 param.index=LLIST_INDEX_LAST;
474 return mplex_do_attach(mplex, ¶m, data);
478 WPHolder *mplex_get_rescue_pholder_for(WMPlex *mplex, WRegion *mgd)
481 WStacking *st=mplex_find_stacking(mplex, mgd);
482 WMPlexAttachParams param;
484 param.flags=MPLEX_ATTACH_INDEX;
485 param.index=LLIST_INDEX_LAST;
487 return create_mplexpholder(mplex, st, ¶m);
489 return (WPHolder*)create_basicpholder((WRegion*)mplex,
490 (WBasicPHolderHandler*)mplex_rescue_attach);
498 /*{{{ Class information */
501 static DynFunTab mplexpholder_dynfuntab[]={
502 {(DynFun*)pholder_do_attach,
503 (DynFun*)mplexpholder_do_attach},
505 {(DynFun*)pholder_do_goto,
506 (DynFun*)mplexpholder_do_goto},
508 {(DynFun*)pholder_do_target,
509 (DynFun*)mplexpholder_do_target},
511 {(DynFun*)pholder_do_root,
512 (DynFun*)mplexpholder_do_root},
518 IMPLCLASS(WMPlexPHolder, WPHolder, mplexpholder_deinit,
519 mplexpholder_dynfuntab);