2 * ion/ioncore/mplexpholder.c
4 * Copyright (c) Tuomo Valkonen 2005-2007.
6 * Ion is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
12 #include <libtu/objp.h>
13 #include <libtu/obj.h>
14 #include <libtu/pointer.h>
18 #include "mplexpholder.h"
20 #include "framedpholder.h"
23 static void mplex_watch_handler(Watch *watch, Obj *mplex);
29 static bool on_ph_list(WMPlexPHolder *ll, WMPlexPHolder *ph)
31 return ph->prev!=NULL;
35 static void mplexpholder_do_link(WMPlexPHolder *ph,
40 assert(mplex==(WMPlex*)ph->mplex_watch.obj && mplex!=NULL);
43 assert(after->after==or_after);
45 if(after->after!=NULL){
46 LINK_ITEM_AFTER(after->after->phs, after, ph, next, prev);
48 assert(on_ph_list(mplex->mx_phs, after));
49 LINK_ITEM_AFTER(mplex->mx_phs, after, ph, next, prev);
51 ph->after=after->after;
52 }else if(or_after!=NULL){
53 LINK_ITEM_FIRST(or_after->phs, ph, next, prev);
56 LINK_ITEM_FIRST(mplex->mx_phs, ph, next, prev);
62 void mplexpholder_do_unlink(WMPlexPHolder *ph, WMPlex *mplex)
64 if(ph->recreate_pholder!=NULL){
66 ph->prev->recreate_pholder=ph->recreate_pholder;
68 destroy_obj((Obj*)ph->recreate_pholder);
69 ph->recreate_pholder=NULL;
73 UNLINK_ITEM(ph->after->phs, ph, next, prev);
74 }else if(mplex!=NULL && on_ph_list(mplex->mx_phs, ph)){
75 UNLINK_ITEM(mplex->mx_phs, ph, next, prev);
77 WMPlexPHolder *next=ph->next;
79 assert((ph->next==NULL && ph->prev==NULL)
80 || ph->mplex_watch.obj==NULL);
83 ph->next->prev=ph->prev;
100 static void mplex_watch_handler(Watch *watch, Obj *mplex)
102 WMPlexPHolder *ph=FIELD_TO_STRUCT(WMPlexPHolder, mplex_watch, watch);
103 mplexpholder_do_unlink(ph, (WMPlex*)mplex);
104 pholder_redirect(&(ph->ph), (WRegion*)mplex);
108 static WMPlexAttachParams dummy_param={0, 0, {0, 0, 0, 0}, 0, 0};
111 bool mplexpholder_init(WMPlexPHolder *ph, WMPlex *mplex, WStacking *st,
112 WMPlexAttachParams *param)
114 pholder_init(&(ph->ph));
116 watch_init(&(ph->mplex_watch));
121 ph->recreate_pholder=NULL;
123 if(!watch_setup(&(ph->mplex_watch), (Obj*)mplex, mplex_watch_handler)){
124 pholder_deinit(&(ph->ph));
133 mplexpholder_do_link(ph, mplex,
134 LIST_LAST(st->lnode->phs, next, prev),
137 ph->param.flags|=MPLEX_ATTACH_UNNUMBERED;
139 ph->param.flags|=(MPLEX_ATTACH_SIZEPOLICY|
142 (st->hidden ? MPLEX_ATTACH_HIDDEN : 0));
143 ph->param.szplcy=st->szplcy;
144 ph->param.geom=REGION_GEOM(st->reg);
145 ph->param.level=st->level;
149 if(!(param->flags&MPLEX_ATTACH_UNNUMBERED)){
150 int index=(param->flags&MPLEX_ATTACH_INDEX
152 : mplex_default_index(mplex));
153 WLListNode *or_after=llist_index_to_after(mplex->mx_list,
156 WMPlexPHolder *after=(index==LLIST_INDEX_LAST
158 ? LIST_LAST(or_after->phs, next, prev)
159 : LIST_LAST(mplex->mx_phs, next, prev))
162 mplexpholder_do_link(ph, mplex, after, or_after);
170 WMPlexPHolder *create_mplexpholder(WMPlex *mplex,
172 WMPlexAttachParams *param)
174 CREATEOBJ_IMPL(WMPlexPHolder, mplexpholder, (p, mplex, st, param));
178 void mplexpholder_deinit(WMPlexPHolder *ph)
180 mplexpholder_do_unlink(ph, (WMPlex*)ph->mplex_watch.obj);
181 watch_reset(&(ph->mplex_watch));
182 pholder_deinit(&(ph->ph));
189 /*{{{ Move, attach, layer */
193 WMPlexPHolder *ph, *ph_head;
194 WRegionAttachData *data;
199 WRegion *recreate_handler(WWindow *par,
200 const WFitParams *fp,
204 WMPlexPHolder *ph=rp->ph, *ph_head=rp->ph_head, *phtmp;
205 WFramedParam *param=rp->param;
209 frame=create_frame(par, fp, param->mode);
214 /* Move pholders to frame */
215 frame->mplex.mx_phs=ph_head;
217 for(phtmp=frame->mplex.mx_phs; phtmp!=NULL; phtmp=phtmp->next)
218 watch_setup(&(phtmp->mplex_watch), (Obj*)frame, mplex_watch_handler);
221 if(fp->mode&(REGION_FIT_BOUNDS|REGION_FIT_WHATEVER))
222 ph->param.flags|=MPLEX_ATTACH_WHATEVER;
224 reg=mplex_do_attach_pholder(&frame->mplex, ph, rp->data);
226 ph->param.flags&=~MPLEX_ATTACH_WHATEVER;
230 for(phtmp=frame->mplex.mx_phs; phtmp!=NULL; phtmp=phtmp->next)
231 watch_reset(&(phtmp->mplex_watch));
232 frame->mplex.mx_phs=NULL;
234 destroy_obj((Obj*)frame);
238 frame_adjust_to_initial(frame, fp, param, reg);
240 return (WRegion*)frame;
245 static WMPlexPHolder *get_head(WMPlexPHolder *ph)
248 /* ph->prev==NULL should not happen.. */
249 if(ph->prev==NULL || ph->prev->next==NULL)
258 static WFramedPHolder *get_recreate_ph(WMPlexPHolder *ph)
260 return get_head(ph)->recreate_pholder;
264 static WRegion *mplexpholder_attach_recreate(WMPlexPHolder *ph, int flags,
265 WRegionAttachData *data)
267 WRegionAttachData data2;
273 rp.ph_head=get_head(ph);
275 assert(rp.ph_head!=NULL);
277 fph=rp.ph_head->recreate_pholder;
284 rp.param=&fph->param;
286 data2.type=REGION_ATTACH_NEW;
287 data2.u.n.fn=recreate_handler;
290 reg=pholder_do_attach(fph->cont, flags, &data2); /* == frame */
293 destroy_obj((Obj*)fph);
294 rp.ph_head->recreate_pholder=NULL;
301 WRegion *mplexpholder_do_attach(WMPlexPHolder *ph, int flags,
302 WRegionAttachData *data)
304 WMPlex *mplex=(WMPlex*)ph->mplex_watch.obj;
307 return mplexpholder_attach_recreate(ph, flags, data);
309 if(flags&PHOLDER_ATTACH_SWITCHTO)
310 ph->param.flags|=MPLEX_ATTACH_SWITCHTO;
312 ph->param.flags&=~MPLEX_ATTACH_SWITCHTO;
314 return mplex_do_attach_pholder(mplex, ph, data);
318 bool mplexpholder_move(WMPlexPHolder *ph, WMPlex *mplex,
319 WMPlexPHolder *after,
320 WLListNode *or_after)
323 mplexpholder_do_unlink(ph, (WMPlex*)ph->mplex_watch.obj);
325 watch_reset(&(ph->mplex_watch));
330 if(!watch_setup(&(ph->mplex_watch), (Obj*)mplex, mplex_watch_handler))
333 mplexpholder_do_link(ph, mplex, after, or_after);
339 bool mplexpholder_do_goto(WMPlexPHolder *ph)
341 WRegion *reg=(WRegion*)ph->mplex_watch.obj;
344 return region_goto(reg);
346 WFramedPHolder *fph=get_recreate_ph(ph);
349 ? pholder_do_goto((WPHolder*)fph)
355 WRegion *mplexpholder_do_target(WMPlexPHolder *ph)
357 WRegion *reg=(WRegion*)ph->mplex_watch.obj;
362 WFramedPHolder *fph=get_recreate_ph(ph);
365 ? pholder_do_target((WPHolder*)fph)
371 WPHolder *mplexpholder_do_root(WMPlexPHolder *ph)
373 WRegion *reg=(WRegion*)ph->mplex_watch.obj;
378 WFramedPHolder *fph=get_recreate_ph(ph);
384 root=pholder_root((WPHolder*)fph);
386 return (root!=(WPHolder*)fph
396 /*{{{ WMPlex routines */
399 void mplex_move_phs(WMPlex *mplex, WLListNode *node,
400 WMPlexPHolder *after,
401 WLListNode *or_after)
405 assert(node!=or_after);
407 while(node->phs!=NULL){
410 mplexpholder_do_unlink(ph, mplex);
411 mplexpholder_do_link(ph, mplex, after, or_after);
417 void mplex_move_phs_before(WMPlex *mplex, WLListNode *node)
419 WMPlexPHolder *after=NULL;
420 WLListNode *or_after;
422 or_after=LIST_PREV(mplex->mx_list, node, next, prev);
424 after=(or_after!=NULL
425 ? LIST_LAST(or_after->phs, next, prev)
426 : LIST_LAST(mplex->mx_phs, next, prev));
428 mplex_move_phs(mplex, node, after, or_after);
432 WMPlexPHolder *mplex_managed_get_pholder(WMPlex *mplex, WRegion *mgd)
434 WStacking *st=mplex_find_stacking(mplex, mgd);
439 return create_mplexpholder(mplex, st, NULL);
443 WMPlexPHolder *mplex_get_rescue_pholder_for(WMPlex *mplex, WRegion *mgd)
445 WStacking *st=mplex_find_stacking(mplex, mgd);
447 return create_mplexpholder(mplex, st, NULL);
454 /*{{{ Class information */
457 static DynFunTab mplexpholder_dynfuntab[]={
458 {(DynFun*)pholder_do_attach,
459 (DynFun*)mplexpholder_do_attach},
461 {(DynFun*)pholder_do_goto,
462 (DynFun*)mplexpholder_do_goto},
464 {(DynFun*)pholder_do_target,
465 (DynFun*)mplexpholder_do_target},
467 {(DynFun*)pholder_do_root,
468 (DynFun*)mplexpholder_do_root},
474 IMPLCLASS(WMPlexPHolder, WPHolder, mplexpholder_deinit,
475 mplexpholder_dynfuntab);