2 * ion/ioncore/group-cw.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
11 #include <libtu/objp.h>
12 #include <libmainloop/defer.h>
16 #include "clientwin.h"
23 #include "framedpholder.h"
24 #include "grouppholder.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
;
45 groupattachparams_get(¶m
, cwin
->proptab
, "attach_params");
49 param
.level
=STACKING_LEVEL_MODAL1
;
52 if(!param
.szplcy_set
){
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
;
63 param
.switchto
=mp
->switchto
;
65 if(!ioncore_g
.framed_transients
){
69 return (WPHolder
*)create_grouppholder(&cwg
->grp
, NULL
, ¶m
);
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
, ¶m
);
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
))
89 /* Only catch windows with transient mode set to current here. */
90 if(clientwin_get_transient_mode(cwin
)!=TRANSIENT_MODE_CURRENT
)
93 return groupcw_transient_pholder(cwg
, cwin
, param
);
97 static bool groupcw_should_manage_transient(WGroupCW
*cwg
,
102 if(group_find_stacking(&cwg
->grp
, (WRegion
*)tfor
))
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
);
114 WPHolder
*groupcw_prepare_manage_transient(WGroupCW
*cwg
,
115 const WClientWin
*transient
,
116 const WManageParams
*param
,
119 WPHolder
*ph
=region_prepare_manage_transient_default((WRegion
*)cwg
,
124 if(ph
==NULL
&& groupcw_should_manage_transient(cwg
, param
->tfor
))
125 ph
=groupcw_transient_pholder(cwg
, transient
, param
);
131 static WRegion
*groupcw_managed_disposeroot(WGroupCW
*ws
, WRegion
*reg
)
137 FOR_ALL_NODES_IN_GROUP(&ws
->grp
, st
, tmp
){
138 if(st
!=ws
->grp
.managed_stdisp
&& st
->reg
!=reg
){
143 tmpr
=region_disposeroot((WRegion
*)ws
);
144 return (tmpr
!=NULL
? tmpr
: reg
);
155 * Toggle transients managed by \var{cwin} between top/bottom
159 void groupcw_toggle_transients_pos(WGroupCW
*cwg
)
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
;
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
);
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
);
198 name
=region_name((WRegion
*)cwg
);
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
);
227 static void group_migrate_phs_to_ph(WGroup
*group
, WPHolder
*rph
)
229 WGroupPHolder
*phs
, *ph
;
234 phs
->recreate_pholder
=rph
;
236 for(ph
=phs
; ph
!=NULL
; ph
=ph
->next
)
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
);
253 group_migrate_phs_to_ph(&cwg
->grp
, rph
);
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
))
274 region_add_bindmap((WRegion
*)cwg
, ioncore_groupcw_bindmap
);
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
)
295 ExtlTab substab
, subtab
;
298 cwg
=create_groupcw(par
, fp
);
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();
310 group_migrate_phs_to_ph(&cwg
->grp
, ph
);
312 destroy_obj((Obj
*)cwg
);
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
},
358 {(DynFun
*)region_rescue_clientwins
,
359 (DynFun
*)groupcw_rescue_clientwins
},
366 IMPLCLASS(WGroupCW
, WGroup
, groupcw_deinit
, groupcw_dynfuntab
);