Add comments to fork() logic for readibility
[notion/jeffpc.git] / ioncore / group-cw.c
blob6755d8b3106d7ffd9624ba91cd4c7618f6dd50f8
1 /*
2 * ion/ioncore/group-cw.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
7 */
9 #include <string.h>
11 #include <libtu/objp.h>
12 #include <libmainloop/defer.h>
14 #include "common.h"
15 #include "group-cw.h"
16 #include "clientwin.h"
17 #include "regbind.h"
18 #include "bindmaps.h"
19 #include "frame.h"
20 #include "resize.h"
21 #include "pholder.h"
22 #include "names.h"
23 #include "framedpholder.h"
24 #include "grouppholder.h"
25 #include "return.h"
26 #include "saveload.h"
29 #define DFLT_SZPLCY SIZEPOLICY_FREE_GLUE__SOUTH
32 /*{{{ Add/remove managed */
37 static WPHolder *groupcw_transient_pholder(WGroupCW *cwg,
38 const WClientWin *cwin,
39 const WManageParams *mp)
41 WGroupAttachParams param=GROUPATTACHPARAMS_INIT;
42 WFramedParam fp=FRAMEDPARAM_INIT;
43 WPHolder *ph;
45 groupattachparams_get(&param, cwin->proptab, "attach_params");
47 if(!param.level_set){
48 param.level_set=1;
49 param.level=STACKING_LEVEL_MODAL1;
52 if(!param.szplcy_set){
53 param.szplcy_set=1;
54 param.szplcy=cwg->transient_szplcy;
57 if(!param.geom_weak_set){
58 param.geom_weak_set=1;
59 param.geom_weak=REGION_RQGEOM_WEAK_ALL;
62 param.switchto_set=1;
63 param.switchto=mp->switchto;
65 if(!ioncore_g.framed_transients){
66 param.geom_set=TRUE;
67 param.geom=mp->geom;
69 return (WPHolder*)create_grouppholder(&cwg->grp, NULL, &param);
70 }else{
71 fp.inner_geom_gravity_set=1;
72 fp.inner_geom=mp->geom;
73 fp.gravity=ForgetGravity;
74 fp.mode=FRAME_MODE_TRANSIENT;
76 ph=(WPHolder*)create_grouppholder(&cwg->grp, NULL, &param);
78 return pholder_either((WPHolder*)create_framedpholder(ph, &fp), ph);
83 WPHolder *groupcw_prepare_manage(WGroupCW *cwg, const WClientWin *cwin,
84 const WManageParams *param, int priority)
86 if(!MANAGE_PRIORITY_OK(priority, MANAGE_PRIORITY_GROUP))
87 return NULL;
89 /* Only catch windows with transient mode set to current here. */
90 if(clientwin_get_transient_mode(cwin)!=TRANSIENT_MODE_CURRENT)
91 return NULL;
93 return groupcw_transient_pholder(cwg, cwin, param);
97 static bool groupcw_should_manage_transient(WGroupCW *cwg,
98 WClientWin *tfor)
100 WRegion *mgr;
102 if(group_find_stacking(&cwg->grp, (WRegion*)tfor))
103 return TRUE;
105 mgr=REGION_MANAGER(tfor);
107 if(mgr!=NULL && ioncore_g.framed_transients && OBJ_IS(mgr, WFrame))
108 return (group_find_stacking(&cwg->grp, mgr)!=NULL);
110 return FALSE;
114 WPHolder *groupcw_prepare_manage_transient(WGroupCW *cwg,
115 const WClientWin *transient,
116 const WManageParams *param,
117 int unused)
119 WPHolder *ph=region_prepare_manage_transient_default((WRegion*)cwg,
120 transient,
121 param,
122 unused);
124 if(ph==NULL && groupcw_should_manage_transient(cwg, param->tfor))
125 ph=groupcw_transient_pholder(cwg, transient, param);
127 return ph;
131 static WRegion *groupcw_managed_disposeroot(WGroupCW *ws, WRegion *reg)
133 WGroupIterTmp tmp;
134 WStacking *st;
135 WRegion *tmpr;
137 FOR_ALL_NODES_IN_GROUP(&ws->grp, st, tmp){
138 if(st!=ws->grp.managed_stdisp && st->reg!=reg){
139 return reg;
143 tmpr=region_disposeroot((WRegion*)ws);
144 return (tmpr!=NULL ? tmpr : reg);
148 /*}}}*/
151 /*{{{ Misc. */
154 /*_EXTL_DOC
155 * Toggle transients managed by \var{cwin} between top/bottom
156 * of the window.
158 EXTL_EXPORT_MEMBER
159 void groupcw_toggle_transients_pos(WGroupCW *cwg)
161 WStacking *st;
162 WGroupIterTmp tmp;
164 if((cwg->transient_szplcy&SIZEPOLICY_VERT_MASK)==SIZEPOLICY_VERT_TOP){
165 cwg->transient_szplcy&=~SIZEPOLICY_VERT_MASK;
166 cwg->transient_szplcy|=SIZEPOLICY_VERT_BOTTOM;
167 }else{
168 cwg->transient_szplcy&=~SIZEPOLICY_VERT_MASK;
169 cwg->transient_szplcy|=SIZEPOLICY_VERT_TOP;
172 FOR_ALL_NODES_IN_GROUP(&cwg->grp, st, tmp){
173 st->szplcy&=~SIZEPOLICY_VERT_MASK;
174 st->szplcy|=(cwg->transient_szplcy&SIZEPOLICY_VERT_MASK);
176 if(st->reg!=NULL){
177 WFitParams fp;
179 fp.mode=0;
180 fp.g=REGION_GEOM(cwg);
182 sizepolicy(&st->szplcy, st->reg, NULL,
183 REGION_RQGEOM_WEAK_ALL, &fp);
184 region_fitrep(st->reg, NULL, &fp);
190 const char *groupcw_displayname(WGroupCW *cwg)
192 const char *name=NULL;
194 if(cwg->grp.bottom!=NULL && cwg->grp.bottom->reg!=NULL)
195 name=region_name(cwg->grp.bottom->reg);
197 if(name==NULL)
198 name=region_name((WRegion*)cwg);
200 return name;
204 void groupcw_managed_notify(WGroupCW *cwg, WRegion *reg, WRegionNotify how)
206 if(group_bottom(&cwg->grp)==reg && how==ioncore_g.notifies.name){
207 /* Title has changed */
208 region_notify_change((WRegion*)cwg, how);
211 group_managed_notify(&cwg->grp, reg, how);
215 void groupcw_bottom_set(WGroupCW *cwg)
217 region_notify_change((WRegion*)cwg, ioncore_g.notifies.name);
221 /*}}}*/
224 /*{{{ Rescue */
227 static void group_migrate_phs_to_ph(WGroup *group, WPHolder *rph)
229 WGroupPHolder *phs, *ph;
231 phs=group->phs;
232 group->phs=NULL;
234 phs->recreate_pholder=rph;
236 for(ph=phs; ph!=NULL; ph=ph->next)
237 ph->group=NULL;
241 bool groupcw_rescue_clientwins(WGroupCW *cwg, WRescueInfo *info)
243 bool ret=group_rescue_clientwins(&cwg->grp, info);
245 /* If this group can be recreated, arrange remaining placeholders
246 * to do so. This takes care of e.g. recreating client window groups
247 * when recreating layout delayedly under a session manager.
249 if(cwg->grp.phs!=NULL){
250 WPHolder *rph=region_make_return_pholder((WRegion*)cwg);
252 if(rph!=NULL)
253 group_migrate_phs_to_ph(&cwg->grp, rph);
256 return ret;
260 /*}}}*/
264 /*{{{ WGroupCW class */
267 bool groupcw_init(WGroupCW *cwg, WWindow *parent, const WFitParams *fp)
269 cwg->transient_szplcy=DFLT_SZPLCY;
271 if(!group_init(&(cwg->grp), parent, fp))
272 return FALSE;
274 region_add_bindmap((WRegion*)cwg, ioncore_groupcw_bindmap);
276 return TRUE;
280 WGroupCW *create_groupcw(WWindow *parent, const WFitParams *fp)
282 CREATEOBJ_IMPL(WGroupCW, groupcw, (p, parent, fp));
286 void groupcw_deinit(WGroupCW *cwg)
288 group_deinit(&(cwg->grp));
292 WRegion *groupcw_load(WWindow *par, const WFitParams *fp, ExtlTab tab)
294 WGroupCW *cwg;
295 ExtlTab substab, subtab;
296 int i, n;
298 cwg=create_groupcw(par, fp);
300 if(cwg==NULL)
301 return NULL;
303 group_do_load(&cwg->grp, tab);
305 if(cwg->grp.managed_list==NULL){
306 if(cwg->grp.phs!=NULL){
307 /* Session management hack */
308 WPHolder *ph=ioncore_get_load_pholder();
309 if(ph!=NULL)
310 group_migrate_phs_to_ph(&cwg->grp, ph);
312 destroy_obj((Obj*)cwg);
313 return NULL;
316 return (WRegion*)cwg;
320 static DynFunTab groupcw_dynfuntab[]={
321 {(DynFun*)region_prepare_manage,
322 (DynFun*)groupcw_prepare_manage},
324 {(DynFun*)region_prepare_manage_transient,
325 (DynFun*)groupcw_prepare_manage_transient},
328 {(DynFun*)region_handle_drop,
329 (DynFun*)groupcw_handle_drop},
331 {(DynFun*)group_do_add_managed,
332 (DynFun*)groupcw_do_add_managed},
336 {(DynFun*)region_get_rescue_pholder_for,
337 (DynFun*)groupcw_get_rescue_pholder_for},
340 {(DynFun*)region_prepare_manage,
341 (DynFun*)groupcw_prepare_manage},
343 {(DynFun*)region_prepare_manage_transient,
344 (DynFun*)groupcw_prepare_manage_transient},
346 {(DynFun*)region_managed_disposeroot,
347 (DynFun*)groupcw_managed_disposeroot},
349 {(DynFun*)region_displayname,
350 (DynFun*)groupcw_displayname},
352 {region_managed_notify,
353 groupcw_managed_notify},
355 {group_bottom_set,
356 groupcw_bottom_set},
358 {(DynFun*)region_rescue_clientwins,
359 (DynFun*)groupcw_rescue_clientwins},
361 END_DYNFUNTAB
365 EXTL_EXPORT
366 IMPLCLASS(WGroupCW, WGroup, groupcw_deinit, groupcw_dynfuntab);
369 /*}}}*/