2 * ion/ioncore/grouppholder.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>
14 #include <ioncore/common.h>
17 #include "grouppholder.h"
20 static void group_watch_handler(Watch *watch, Obj *ws);
26 void grouppholder_do_link(WGroupPHolder *ph, WGroup *group, WRegion *stack_above)
31 LINK_ITEM_FIRST(group->phs, ph, next, prev);
33 /* This seems very crucial for detached pholders... */
38 /* We must move stack_above pointer into a Watch. */
40 watch_setup(&(ph->stack_above_watch), (Obj*)stack_above, NULL);
44 static WGroupPHolder *get_head(WGroupPHolder *ph)
47 /* ph->prev==NULL should not happen.. */
48 if(ph->prev==NULL || ph->prev->next==NULL)
57 void grouppholder_do_unlink(WGroupPHolder *ph)
59 WGroup *group=ph->group;
61 watch_reset(&(ph->stack_above_watch));
63 if(ph->recreate_pholder!=NULL){
65 ph->next->recreate_pholder=ph->recreate_pholder;
67 /* It might be in use in attach chain! So defer. */
68 mainloop_defer_destroy((Obj*)ph->recreate_pholder);
70 ph->recreate_pholder=NULL;
74 UNLINK_ITEM(group->phs, ph, next, prev);
75 }else if(ph->prev!=NULL){
76 WGroupPHolder *next=ph->next;
82 assert(next->prev==ph);
86 /* ph should not be on a list, if prev pointer is NULL (whereas
87 * next alone can be NULL in our semi-doubly-linked lists).
89 assert(ph->next==NULL);
103 static WGroupAttachParams dummy_param=GROUPATTACHPARAMS_INIT;
106 bool grouppholder_init(WGroupPHolder *ph, WGroup *ws,
108 const WGroupAttachParams *param)
110 WRegion *stack_above=NULL;
112 pholder_init(&(ph->ph));
114 watch_init(&(ph->stack_above_watch));
118 ph->recreate_pholder=NULL;
119 ph->param=(param==NULL ? dummy_param : *param);
122 /* TODO? Just link to the stacking structure to remember
126 ph->param.szplcy_set=TRUE;
127 ph->param.szplcy=st->szplcy;
128 ph->param.level_set=TRUE;
129 ph->param.level=st->level;
132 ph->param.geom_set=TRUE;
133 ph->param.geom=REGION_GEOM(st->reg);
136 if(st->above!=NULL && st->above->reg!=NULL)
137 ph->param.stack_above=st->above->reg;
139 ph->param.bottom=(st==ws->bottom);
142 ph->param.switchto_set=FALSE;
144 stack_above=ph->param.stack_above;
145 ph->param.stack_above=NULL;
147 grouppholder_do_link(ph, ws, stack_above);
153 WGroupPHolder *create_grouppholder(WGroup *ws,
155 const WGroupAttachParams *param)
157 CREATEOBJ_IMPL(WGroupPHolder, grouppholder, (p, ws, st, param));
161 void grouppholder_deinit(WGroupPHolder *ph)
163 grouppholder_do_unlink(ph);
165 pholder_deinit(&(ph->ph));
175 static WPHolder *get_recreate_ph(WGroupPHolder *ph)
177 return get_head(ph)->recreate_pholder;
182 WGroupPHolder *ph, *ph_head;
183 WRegionAttachData *data;
188 static WRegion *recreate_handler(WWindow *par,
189 const WFitParams *fp,
192 WGroupPHolder *phtmp;
196 grp=(WGroup*)create_groupcw(par, fp);
201 rp->ph->param.whatever=(fp->mode®ION_FIT_WHATEVER ? 1 : 0);
203 rp->reg_ret=group_do_attach(grp, &rp->ph->param, rp->data);
205 rp->ph->param.whatever=0;
207 if(rp->reg_ret==NULL){
208 destroy_obj((Obj*)grp);
211 grp->phs=rp->ph_head;
213 for(phtmp=grp->phs; phtmp!=NULL; phtmp=phtmp->next)
217 if(fp->mode®ION_FIT_WHATEVER)
218 REGION_GEOM(grp)=REGION_GEOM(rp->reg_ret);
220 return (WRegion*)grp;
225 static WRegion *grouppholder_attach_recreate(WGroupPHolder *ph, int flags,
226 WRegionAttachData *data)
228 WRegionAttachData data2;
229 WPHolder *root, *rph;
233 rp.ph_head=get_head(ph);
235 assert(rp.ph_head!=NULL);
237 rph=rp.ph_head->recreate_pholder;
246 data2.type=REGION_ATTACH_NEW;
247 data2.u.n.fn=recreate_handler;
250 grp=(WGroup*)pholder_do_attach(rph, flags, &data2);
253 assert(OBJ_IS(grp, WGroup));
254 rp.ph_head->recreate_pholder=NULL;
255 /* It might be in use in attach chain! So defer. */
256 mainloop_defer_destroy((Obj*)rph);
263 WRegion *grouppholder_do_attach(WGroupPHolder *ph, int flags,
264 WRegionAttachData *data)
266 WGroup *ws=ph->group;
270 return grouppholder_attach_recreate(ph, flags, data);
272 ph->param.switchto_set=1;
273 ph->param.switchto=(flags&PHOLDER_ATTACH_SWITCHTO ? 1 : 0);
275 /* Get stack_above from Watch. */
276 ph->param.stack_above=(WRegion*)ph->stack_above_watch.obj;
278 reg=group_do_attach(ws, &ph->param, data);
280 ph->param.stack_above=NULL;
286 bool grouppholder_do_goto(WGroupPHolder *ph)
288 return (ph->group!=NULL
289 ? region_goto((WRegion*)ph->group)
290 : (ph->recreate_pholder!=NULL
291 ? pholder_do_goto(ph->recreate_pholder)
296 WRegion *grouppholder_do_target(WGroupPHolder *ph)
298 return (ph->group!=NULL
299 ? (WRegion*)ph->group
300 : (ph->recreate_pholder!=NULL
301 ? pholder_do_target(ph->recreate_pholder)
309 /*{{{ WGroup stuff */
312 WGroupPHolder *group_managed_get_pholder(WGroup *ws, WRegion *mgd)
314 WStacking *st=group_find_stacking(ws, mgd);
319 return create_grouppholder(ws, st, NULL);
326 /*{{{ Class information */
329 static DynFunTab grouppholder_dynfuntab[]={
330 {(DynFun*)pholder_do_attach,
331 (DynFun*)grouppholder_do_attach},
333 {(DynFun*)pholder_do_goto,
334 (DynFun*)grouppholder_do_goto},
336 {(DynFun*)pholder_do_target,
337 (DynFun*)grouppholder_do_target},
342 IMPLCLASS(WGroupPHolder, WPHolder, grouppholder_deinit,
343 grouppholder_dynfuntab);