2 * ion/ioncore/group-cw.c
4 * Copyright (c) Tuomo Valkonen 1999-2008.
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 */
35 static WPHolder *groupcw_transient_pholder(WGroupCW *cwg,
36 const WClientWin *cwin,
37 const WManageParams *mp)
39 WGroupAttachParams param=GROUPATTACHPARAMS_INIT;
40 WFramedParam fp=FRAMEDPARAM_INIT;
44 param.level=STACKING_LEVEL_MODAL1;
47 param.szplcy=cwg->transient_szplcy;
52 param.geom_weak_set=1;
53 param.geom_weak=REGION_RQGEOM_WEAK_ALL;
55 if(!ioncore_g.framed_transients){
59 return (WPHolder*)create_grouppholder(&cwg->grp, NULL, ¶m);
61 fp.inner_geom_gravity_set=1;
62 fp.inner_geom=mp->geom;
63 fp.gravity=ForgetGravity;
64 fp.mode=FRAME_MODE_TRANSIENT;
66 ph=(WPHolder*)create_grouppholder(&cwg->grp, NULL, ¶m);
68 return pholder_either((WPHolder*)create_framedpholder(ph, &fp), ph);
73 WPHolder *groupcw_prepare_manage(WGroupCW *cwg, const WClientWin *cwin,
74 const WManageParams *param, int priority)
76 if(!MANAGE_PRIORITY_OK(priority, MANAGE_PRIORITY_GROUP))
79 /* Only catch windows with transient mode set to current here. */
80 if(clientwin_get_transient_mode(cwin)!=TRANSIENT_MODE_CURRENT)
83 return groupcw_transient_pholder(cwg, cwin, param);
87 static bool groupcw_should_manage_transient(WGroupCW *cwg,
92 if(group_find_stacking(&cwg->grp, (WRegion*)tfor))
95 mgr=REGION_MANAGER(tfor);
97 if(mgr!=NULL && ioncore_g.framed_transients && OBJ_IS(mgr, WFrame))
98 return (group_find_stacking(&cwg->grp, mgr)!=NULL);
104 WPHolder *groupcw_prepare_manage_transient(WGroupCW *cwg,
105 const WClientWin *transient,
106 const WManageParams *param,
109 WPHolder *ph=region_prepare_manage_transient_default((WRegion*)cwg,
114 if(ph==NULL && groupcw_should_manage_transient(cwg, param->tfor))
115 ph=groupcw_transient_pholder(cwg, transient, param);
121 static WRegion *groupcw_managed_disposeroot(WGroupCW *ws, WRegion *reg)
127 FOR_ALL_NODES_IN_GROUP(&ws->grp, st, tmp){
128 if(st!=ws->grp.managed_stdisp && st->reg!=reg){
133 tmpr=region_disposeroot((WRegion*)ws);
134 return (tmpr!=NULL ? tmpr : reg);
145 * Toggle transients managed by \var{cwin} between top/bottom
149 void groupcw_toggle_transients_pos(WGroupCW *cwg)
154 if((cwg->transient_szplcy&SIZEPOLICY_VERT_MASK)==SIZEPOLICY_VERT_TOP){
155 cwg->transient_szplcy&=~SIZEPOLICY_VERT_MASK;
156 cwg->transient_szplcy|=SIZEPOLICY_VERT_BOTTOM;
158 cwg->transient_szplcy&=~SIZEPOLICY_VERT_MASK;
159 cwg->transient_szplcy|=SIZEPOLICY_VERT_TOP;
162 FOR_ALL_NODES_IN_GROUP(&cwg->grp, st, tmp){
163 st->szplcy&=~SIZEPOLICY_VERT_MASK;
164 st->szplcy|=(cwg->transient_szplcy&SIZEPOLICY_VERT_MASK);
170 fp.g=REGION_GEOM(cwg);
172 sizepolicy(&st->szplcy, st->reg, NULL,
173 REGION_RQGEOM_WEAK_ALL, &fp);
174 region_fitrep(st->reg, NULL, &fp);
180 const char *groupcw_displayname(WGroupCW *cwg)
182 const char *name=NULL;
184 if(cwg->grp.bottom!=NULL && cwg->grp.bottom->reg!=NULL)
185 name=region_name(cwg->grp.bottom->reg);
188 name=region_name((WRegion*)cwg);
194 void groupcw_managed_notify(WGroupCW *cwg, WRegion *reg, WRegionNotify how)
196 if(group_bottom(&cwg->grp)==reg && how==ioncore_g.notifies.name){
197 /* Title has changed */
198 region_notify_change((WRegion*)cwg, how);
201 group_managed_notify(&cwg->grp, reg, how);
205 void groupcw_bottom_set(WGroupCW *cwg)
207 region_notify_change((WRegion*)cwg, ioncore_g.notifies.name);
217 static void group_migrate_phs_to_ph(WGroup *group, WPHolder *rph)
219 WGroupPHolder *phs, *ph;
224 phs->recreate_pholder=rph;
226 for(ph=phs; ph!=NULL; ph=ph->next)
231 bool groupcw_rescue_clientwins(WGroupCW *cwg, WRescueInfo *info)
233 bool ret=group_rescue_clientwins(&cwg->grp, info);
235 /* If this group can be recreated, arrange remaining placeholders
236 * to do so. This takes care of e.g. recreating client window groups
237 * when recreating layout delayedly under a session manager.
239 if(cwg->grp.phs!=NULL){
240 WPHolder *rph=region_make_return_pholder((WRegion*)cwg);
243 group_migrate_phs_to_ph(&cwg->grp, rph);
254 /*{{{ WGroupCW class */
257 bool groupcw_init(WGroupCW *cwg, WWindow *parent, const WFitParams *fp)
259 cwg->transient_szplcy=DFLT_SZPLCY;
261 if(!group_init(&(cwg->grp), parent, fp))
264 region_add_bindmap((WRegion*)cwg, ioncore_groupcw_bindmap);
270 WGroupCW *create_groupcw(WWindow *parent, const WFitParams *fp)
272 CREATEOBJ_IMPL(WGroupCW, groupcw, (p, parent, fp));
276 void groupcw_deinit(WGroupCW *cwg)
278 group_deinit(&(cwg->grp));
282 WRegion *groupcw_load(WWindow *par, const WFitParams *fp, ExtlTab tab)
285 ExtlTab substab, subtab;
288 cwg=create_groupcw(par, fp);
293 group_do_load(&cwg->grp, tab);
295 if(cwg->grp.managed_list==NULL){
296 if(cwg->grp.phs!=NULL){
297 /* Session management hack */
298 WPHolder *ph=ioncore_get_load_pholder();
300 group_migrate_phs_to_ph(&cwg->grp, ph);
302 destroy_obj((Obj*)cwg);
306 return (WRegion*)cwg;
310 static DynFunTab groupcw_dynfuntab[]={
311 {(DynFun*)region_prepare_manage,
312 (DynFun*)groupcw_prepare_manage},
314 {(DynFun*)region_prepare_manage_transient,
315 (DynFun*)groupcw_prepare_manage_transient},
318 {(DynFun*)region_handle_drop,
319 (DynFun*)groupcw_handle_drop},
321 {(DynFun*)group_do_add_managed,
322 (DynFun*)groupcw_do_add_managed},
326 {(DynFun*)region_get_rescue_pholder_for,
327 (DynFun*)groupcw_get_rescue_pholder_for},
330 {(DynFun*)region_prepare_manage,
331 (DynFun*)groupcw_prepare_manage},
333 {(DynFun*)region_prepare_manage_transient,
334 (DynFun*)groupcw_prepare_manage_transient},
336 {(DynFun*)region_managed_disposeroot,
337 (DynFun*)groupcw_managed_disposeroot},
339 {(DynFun*)region_displayname,
340 (DynFun*)groupcw_displayname},
342 {region_managed_notify,
343 groupcw_managed_notify},
348 {(DynFun*)region_rescue_clientwins,
349 (DynFun*)groupcw_rescue_clientwins},
356 IMPLCLASS(WGroupCW, WGroup, groupcw_deinit, groupcw_dynfuntab);