2 * ion/ioncore/grouppholder.c
4 * Copyright (c) Tuomo Valkonen 2005-2009.
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"
23 void grouppholder_do_link(WGroupPHolder
*ph
, WGroup
*group
, WRegion
*stack_above
)
28 LINK_ITEM_FIRST(group
->phs
, ph
, next
, prev
);
30 /* This seems very crucial for detached pholders... */
35 /* We must move stack_above pointer into a Watch. */
37 watch_setup(&(ph
->stack_above_watch
), (Obj
*)stack_above
, NULL
);
41 static WGroupPHolder
*get_head(WGroupPHolder
*ph
)
44 /* ph->prev==NULL should not happen.. */
45 if(ph
->prev
==NULL
|| ph
->prev
->next
==NULL
)
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
){
62 ph
->next
->recreate_pholder
=ph
->recreate_pholder
;
64 /* It might be in use in attach chain! So defer. */
65 mainloop_defer_destroy((Obj
*)ph
->recreate_pholder
);
67 ph
->recreate_pholder
=NULL
;
71 UNLINK_ITEM(group
->phs
, ph
, next
, prev
);
72 }else if(ph
->prev
!=NULL
){
73 WGroupPHolder
*next
=ph
->next
;
79 assert(next
->prev
==ph
);
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
);
100 static WGroupAttachParams dummy_param
=GROUPATTACHPARAMS_INIT
;
103 bool grouppholder_init(WGroupPHolder
*ph
, WGroup
*ws
,
105 const WGroupAttachParams
*param
)
107 WRegion
*stack_above
=NULL
;
109 pholder_init(&(ph
->ph
));
111 watch_init(&(ph
->stack_above_watch
));
115 ph
->recreate_pholder
=NULL
;
116 ph
->param
=(param
==NULL
? dummy_param
: *param
);
119 /* TODO? Just link to the stacking structure to remember
123 ph
->param
.szplcy_set
=TRUE
;
124 ph
->param
.szplcy
=st
->szplcy
;
125 ph
->param
.level_set
=TRUE
;
126 ph
->param
.level
=st
->level
;
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
);
150 WGroupPHolder
*create_grouppholder(WGroup
*ws
,
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
));
173 WGroupPHolder
*ph
, *ph_head
;
174 WRegionAttachData
*data
;
179 static WRegion
*recreate_handler(WWindow
*par
,
180 const WFitParams
*fp
,
183 WGroupPHolder
*phtmp
;
187 grp
=(WGroup
*)create_groupcw(par
, fp
);
192 rp
->ph
->param
.whatever
=(fp
->mode
®ION_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
);
202 grp
->phs
=rp
->ph_head
;
204 for(phtmp
=grp
->phs
; phtmp
!=NULL
; phtmp
=phtmp
->next
)
208 if(fp
->mode
®ION_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
;
224 rp
.ph_head
=get_head(ph
);
226 assert(rp
.ph_head
!=NULL
);
228 rph
=rp
.ph_head
->recreate_pholder
;
237 data2
.type
=REGION_ATTACH_NEW
;
238 data2
.u
.n
.fn
=recreate_handler
;
241 res
=pholder_do_attach(rph
, flags
, &data2
);
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
255 WRegion
*grouppholder_do_attach(WGroupPHolder
*ph
, int flags
,
256 WRegionAttachData
*data
)
258 WGroup
*ws
=ph
->group
;
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
;
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
)
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
)
301 /*{{{ WGroup stuff */
304 WGroupPHolder
*group_managed_get_pholder(WGroup
*ws
, WRegion
*mgd
)
306 WStacking
*st
=group_find_stacking(ws
, mgd
);
311 return create_grouppholder(ws
, st
, NULL
);
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
},
334 IMPLCLASS(WGroupPHolder
, WPHolder
, grouppholder_deinit
,
335 grouppholder_dynfuntab
);