Released version 3-2015061300
[notion.git] / ioncore / grouppholder.c
blob70063c543f0121d33c147041f8dd22f1317672bf
1 /*
2 * ion/ioncore/grouppholder.c
4 * Copyright (c) Tuomo Valkonen 2005-2009.
6 * See the included file LICENSE for details.
7 */
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>
15 #include "group.h"
16 #include "group-cw.h"
17 #include "grouppholder.h"
20 /*{{{ Primitives */
23 void grouppholder_do_link(WGroupPHolder *ph, WGroup *group, WRegion *stack_above)
25 ph->group=group;
27 if(group!=NULL){
28 LINK_ITEM_FIRST(group->phs, ph, next, prev);
29 }else{
30 /* This seems very crucial for detached pholders... */
31 ph->next=NULL;
32 ph->prev=ph;
35 /* We must move stack_above pointer into a Watch. */
36 if(stack_above!=NULL)
37 watch_setup(&(ph->stack_above_watch), (Obj*)stack_above, NULL);
41 static WGroupPHolder *get_head(WGroupPHolder *ph)
43 while(1){
44 /* ph->prev==NULL should not happen.. */
45 if(ph->prev==NULL || ph->prev->next==NULL)
46 break;
47 ph=ph->prev;
50 return ph;
54 void grouppholder_do_unlink(WGroupPHolder *ph)
56 WGroup *group=ph->group;
58 watch_reset(&(ph->stack_above_watch));
60 if(ph->recreate_pholder!=NULL){
61 if(ph->next!=NULL){
62 ph->next->recreate_pholder=ph->recreate_pholder;
63 }else{
64 /* It might be in use in attach chain! So defer. */
65 mainloop_defer_destroy((Obj*)ph->recreate_pholder);
67 ph->recreate_pholder=NULL;
70 if(group!=NULL){
71 UNLINK_ITEM(group->phs, ph, next, prev);
72 }else if(ph->prev!=NULL){
73 WGroupPHolder *next=ph->next;
75 ph->prev->next=next;
77 if(next==NULL){
78 next=get_head(ph);
79 assert(next->prev==ph);
81 next->prev=ph->prev;
82 }else{
83 /* ph should not be on a list, if prev pointer is NULL (whereas
84 * next alone can be NULL in our semi-doubly-linked lists).
86 assert(ph->next==NULL);
89 ph->group=NULL;
90 ph->next=NULL;
91 ph->prev=NULL;
95 /*}}}*/
98 /*{{{ Init/deinit */
100 static WGroupAttachParams dummy_param=GROUPATTACHPARAMS_INIT;
103 bool grouppholder_init(WGroupPHolder *ph, WGroup *ws,
104 const WStacking *st,
105 const WGroupAttachParams *param)
107 WRegion *stack_above=NULL;
109 pholder_init(&(ph->ph));
111 watch_init(&(ph->stack_above_watch));
112 ph->next=NULL;
113 ph->prev=NULL;
114 ph->group=NULL;
115 ph->recreate_pholder=NULL;
116 ph->param=(param==NULL ? dummy_param : *param);
118 if(st!=NULL){
119 /* TODO? Just link to the stacking structure to remember
120 * stacking order?
123 ph->param.szplcy_set=TRUE;
124 ph->param.szplcy=st->szplcy;
125 ph->param.level_set=TRUE;
126 ph->param.level=st->level;
128 if(st->reg!=NULL){
129 ph->param.geom_set=TRUE;
130 ph->param.geom=REGION_GEOM(st->reg);
133 if(st->above!=NULL && st->above->reg!=NULL)
134 ph->param.stack_above=st->above->reg;
136 ph->param.bottom=(st==ws->bottom);
139 ph->param.switchto_set=FALSE;
141 stack_above=ph->param.stack_above;
142 ph->param.stack_above=NULL;
144 grouppholder_do_link(ph, ws, stack_above);
146 return TRUE;
150 WGroupPHolder *create_grouppholder(WGroup *ws,
151 const WStacking *st,
152 const WGroupAttachParams *param)
154 CREATEOBJ_IMPL(WGroupPHolder, grouppholder, (p, ws, st, param));
158 void grouppholder_deinit(WGroupPHolder *ph)
160 grouppholder_do_unlink(ph);
162 pholder_deinit(&(ph->ph));
166 /*}}}*/
169 /*{{{ Dynfuns */
172 typedef struct{
173 WGroupPHolder *ph, *ph_head;
174 WRegionAttachData *data;
175 WRegion *reg_ret;
176 } RP;
179 static WRegion *recreate_handler(WWindow *par,
180 const WFitParams *fp,
181 void *rp_)
183 WGroupPHolder *phtmp;
184 RP *rp=(RP*)rp_;
185 WGroup *grp;
187 grp=(WGroup*)create_groupcw(par, fp);
189 if(grp==NULL)
190 return NULL;
192 rp->ph->param.whatever=(fp->mode&REGION_FIT_WHATEVER ? 1 : 0);
194 rp->reg_ret=group_do_attach(grp, &rp->ph->param, rp->data);
196 rp->ph->param.whatever=0;
198 if(rp->reg_ret==NULL){
199 destroy_obj((Obj*)grp);
200 return NULL;
201 }else{
202 grp->phs=rp->ph_head;
204 for(phtmp=grp->phs; phtmp!=NULL; phtmp=phtmp->next)
205 phtmp->group=grp;
208 if(fp->mode&REGION_FIT_WHATEVER)
209 REGION_GEOM(grp)=REGION_GEOM(rp->reg_ret);
211 return (WRegion*)grp;
216 static WRegion *grouppholder_attach_recreate(WGroupPHolder *ph, int flags,
217 WRegionAttachData *data)
219 WRegionAttachData data2;
220 WPHolder *rph;
221 WRegion *res;
222 RP rp;
224 rp.ph_head=get_head(ph);
226 assert(rp.ph_head!=NULL);
228 rph=rp.ph_head->recreate_pholder;
230 if(rph==NULL)
231 return NULL;
233 rp.ph=ph;
234 rp.data=data;
235 rp.reg_ret=NULL;
237 data2.type=REGION_ATTACH_NEW;
238 data2.u.n.fn=recreate_handler;
239 data2.u.n.param=&rp;
241 res=pholder_do_attach(rph, flags, &data2);
243 if(res!=NULL){
244 rp.ph_head->recreate_pholder=NULL;
245 /* It might be in use in attach chain! So defer. */
246 mainloop_defer_destroy((Obj*)rph);
249 return (flags&PHOLDER_ATTACH_RETURN_CREATEROOT
250 ? (WRegion*)res
251 : rp.reg_ret);
255 WRegion *grouppholder_do_attach(WGroupPHolder *ph, int flags,
256 WRegionAttachData *data)
258 WGroup *ws=ph->group;
259 WRegion *reg;
261 if(ws==NULL)
262 return grouppholder_attach_recreate(ph, flags, data);
264 ph->param.switchto_set=1;
265 ph->param.switchto=(flags&PHOLDER_ATTACH_SWITCHTO ? 1 : 0);
267 /* Get stack_above from Watch. */
268 ph->param.stack_above=(WRegion*)ph->stack_above_watch.obj;
270 reg=group_do_attach(ws, &ph->param, data);
272 ph->param.stack_above=NULL;
274 return reg;
278 bool grouppholder_do_goto(WGroupPHolder *ph)
280 return (ph->group!=NULL
281 ? region_goto((WRegion*)ph->group)
282 : (ph->recreate_pholder!=NULL
283 ? pholder_do_goto(ph->recreate_pholder)
284 : FALSE));
288 WRegion *grouppholder_do_target(WGroupPHolder *ph)
290 return (ph->group!=NULL
291 ? (WRegion*)ph->group
292 : (ph->recreate_pholder!=NULL
293 ? pholder_do_target(ph->recreate_pholder)
294 : NULL));
298 /*}}}*/
301 /*{{{ WGroup stuff */
304 WGroupPHolder *group_managed_get_pholder(WGroup *ws, WRegion *mgd)
306 WStacking *st=group_find_stacking(ws, mgd);
308 if(mgd==NULL)
309 return NULL;
310 else
311 return create_grouppholder(ws, st, NULL);
315 /*}}}*/
318 /*{{{ Class information */
321 static DynFunTab grouppholder_dynfuntab[]={
322 {(DynFun*)pholder_do_attach,
323 (DynFun*)grouppholder_do_attach},
325 {(DynFun*)pholder_do_goto,
326 (DynFun*)grouppholder_do_goto},
328 {(DynFun*)pholder_do_target,
329 (DynFun*)grouppholder_do_target},
331 END_DYNFUNTAB
334 IMPLCLASS(WGroupPHolder, WPHolder, grouppholder_deinit,
335 grouppholder_dynfuntab);
338 /*}}}*/