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"
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 res
=pholder_do_attach(rph
, flags
, &data2
);
253 rp
.ph_head
->recreate_pholder
=NULL
;
254 /* It might be in use in attach chain! So defer. */
255 mainloop_defer_destroy((Obj
*)rph
);
258 return (flags
&PHOLDER_ATTACH_RETURN_CREATEROOT
264 WRegion
*grouppholder_do_attach(WGroupPHolder
*ph
, int flags
,
265 WRegionAttachData
*data
)
267 WGroup
*ws
=ph
->group
;
271 return grouppholder_attach_recreate(ph
, flags
, data
);
273 ph
->param
.switchto_set
=1;
274 ph
->param
.switchto
=(flags
&PHOLDER_ATTACH_SWITCHTO
? 1 : 0);
276 /* Get stack_above from Watch. */
277 ph
->param
.stack_above
=(WRegion
*)ph
->stack_above_watch
.obj
;
279 reg
=group_do_attach(ws
, &ph
->param
, data
);
281 ph
->param
.stack_above
=NULL
;
287 bool grouppholder_do_goto(WGroupPHolder
*ph
)
289 return (ph
->group
!=NULL
290 ? region_goto((WRegion
*)ph
->group
)
291 : (ph
->recreate_pholder
!=NULL
292 ? pholder_do_goto(ph
->recreate_pholder
)
297 WRegion
*grouppholder_do_target(WGroupPHolder
*ph
)
299 return (ph
->group
!=NULL
300 ? (WRegion
*)ph
->group
301 : (ph
->recreate_pholder
!=NULL
302 ? pholder_do_target(ph
->recreate_pholder
)
310 /*{{{ WGroup stuff */
313 WGroupPHolder
*group_managed_get_pholder(WGroup
*ws
, WRegion
*mgd
)
315 WStacking
*st
=group_find_stacking(ws
, mgd
);
320 return create_grouppholder(ws
, st
, NULL
);
327 /*{{{ Class information */
330 static DynFunTab grouppholder_dynfuntab
[]={
331 {(DynFun
*)pholder_do_attach
,
332 (DynFun
*)grouppholder_do_attach
},
334 {(DynFun
*)pholder_do_goto
,
335 (DynFun
*)grouppholder_do_goto
},
337 {(DynFun
*)pholder_do_target
,
338 (DynFun
*)grouppholder_do_target
},
343 IMPLCLASS(WGroupPHolder
, WPHolder
, grouppholder_deinit
,
344 grouppholder_dynfuntab
);