]> git.decadent.org.uk Git - ion3.git/blob - ioncore/group-cw.c
8181af80bd96bc60f5294dd69277445da479417b
[ion3.git] / ioncore / group-cw.c
1 /*
2  * ion/ioncore/group-cw.c
3  *
4  * Copyright (c) Tuomo Valkonen 1999-2007. 
5  *
6  * Ion is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  */
11
12 #include <string.h>
13
14 #include <libtu/objp.h>
15 #include <libmainloop/defer.h>
16
17 #include "common.h"
18 #include "group-cw.h"
19 #include "clientwin.h"
20 #include "regbind.h"
21 #include "bindmaps.h"
22 #include "frame.h"
23 #include "resize.h"
24 #include "pholder.h"
25 #include "names.h"
26 #include "framedpholder.h"
27 #include "grouppholder.h"
28
29
30 #define DFLT_SZPLCY SIZEPOLICY_FREE_GLUE__SOUTH
31
32
33 /*{{{ Add/remove managed */
34
35
36 static WPHolder *groupcw_transient_pholder(WGroupCW *cwg, 
37                                            const WClientWin *cwin,
38                                            const WManageParams *mp)
39 {
40     WGroupAttachParams param=GROUPATTACHPARAMS_INIT;
41     WFramedParam fp=FRAMEDPARAM_INIT;
42     WPHolder *ph;
43     
44     param.level_set=1;
45     param.level=STACKING_LEVEL_MODAL1;
46     
47     param.szplcy_set=1;
48     param.szplcy=cwg->transient_szplcy;
49     
50     param.switchto_set=1;
51     param.switchto=1;
52
53     param.geom_weak_set=1;
54     param.geom_weak=REGION_RQGEOM_WEAK_ALL;
55     
56     if(!ioncore_g.framed_transients){
57         param.geom_set=TRUE;
58         param.geom=mp->geom;
59         
60         return (WPHolder*)create_grouppholder(&cwg->grp, NULL, &param);
61     }else{
62         fp.inner_geom_gravity_set=1;
63         fp.inner_geom=mp->geom;
64         fp.gravity=ForgetGravity;
65         fp.mode=FRAME_MODE_TRANSIENT;
66         
67         ph=(WPHolder*)create_grouppholder(&cwg->grp, NULL, &param);
68         
69         return pholder_either((WPHolder*)create_framedpholder(ph, &fp), ph);
70     }
71 }
72
73
74 WPHolder *groupcw_prepare_manage(WGroupCW *cwg, const WClientWin *cwin,
75                                  const WManageParams *param, int redir)
76 {
77     if(redir==MANAGE_REDIR_STRICT_YES)
78         return NULL;
79     
80     /* Only catch windows with transient mode set to current here. */
81     if(clientwin_get_transient_mode(cwin)!=TRANSIENT_MODE_CURRENT)
82         return NULL;
83     
84     return groupcw_transient_pholder(cwg, cwin, param);
85 }
86
87
88 static bool groupcw_should_manage_transient(WGroupCW *cwg, 
89                                             WClientWin *tfor)
90 {
91     WRegion *mgr;
92     
93     if(group_find_stacking(&cwg->grp, (WRegion*)tfor))
94         return TRUE;
95  
96     mgr=REGION_MANAGER(tfor);
97     
98     if(mgr!=NULL && ioncore_g.framed_transients && OBJ_IS(mgr, WFrame))
99         return (group_find_stacking(&cwg->grp, mgr)!=NULL);
100     
101     return FALSE;
102 }
103
104
105 WPHolder *groupcw_prepare_manage_transient(WGroupCW *cwg, 
106                                            const WClientWin *transient,
107                                            const WManageParams *param,
108                                            int unused)
109 {
110     WPHolder *ph=region_prepare_manage_transient_default((WRegion*)cwg,
111                                                          transient,
112                                                          param,
113                                                          unused);
114     
115     if(ph==NULL && groupcw_should_manage_transient(cwg, param->tfor))
116         ph=groupcw_transient_pholder(cwg, transient, param);
117
118     return ph;
119 }
120
121
122 /*}}}*/
123
124
125 /*{{{ Misc. */
126
127
128 /*_EXTL_DOC
129  * Toggle transients managed by \var{cwin} between top/bottom
130  * of the window.
131  */
132 EXTL_EXPORT_MEMBER
133 void groupcw_toggle_transients_pos(WGroupCW *cwg)
134 {
135     WStacking *st;
136     WGroupIterTmp tmp;
137     
138     if((cwg->transient_szplcy&SIZEPOLICY_VERT_MASK)==SIZEPOLICY_VERT_TOP){
139         cwg->transient_szplcy&=~SIZEPOLICY_VERT_MASK;
140         cwg->transient_szplcy|=SIZEPOLICY_VERT_BOTTOM;
141     }else{
142         cwg->transient_szplcy&=~SIZEPOLICY_VERT_MASK;
143         cwg->transient_szplcy|=SIZEPOLICY_VERT_TOP;
144     }
145
146     FOR_ALL_NODES_IN_GROUP(&cwg->grp, st, tmp){
147         st->szplcy&=~SIZEPOLICY_VERT_MASK;
148         st->szplcy|=(cwg->transient_szplcy&SIZEPOLICY_VERT_MASK);
149         
150         if(st->reg!=NULL){
151             WFitParams fp;
152
153             fp.g=REGION_GEOM(cwg);
154             
155             sizepolicy(&st->szplcy, st->reg, NULL, 
156                        REGION_RQGEOM_WEAK_ALL, &fp);
157             region_fitrep(st->reg, NULL, &fp);
158         }
159     }
160 }
161
162
163 const char *groupcw_displayname(WGroupCW *cwg)
164 {
165     const char *name=NULL;
166     
167     if(cwg->grp.bottom!=NULL && cwg->grp.bottom->reg!=NULL)
168         name=region_name(cwg->grp.bottom->reg);
169     
170     if(name==NULL)
171         name=region_name((WRegion*)cwg);
172     
173     return name;
174 }
175
176
177 void groupcw_managed_notify(WGroupCW *cwg, WRegion *reg, WRegionNotify how)
178 {
179     if(group_bottom(&cwg->grp)==reg && how==ioncore_g.notifies.name){
180         /* Title has changed */
181         region_notify_change((WRegion*)cwg, how);
182     }
183     
184     group_managed_notify(&cwg->grp, reg, how);
185 }
186
187
188 /*}}}*/
189
190
191 /*{{{ WGroupCW class */
192
193
194 bool groupcw_init(WGroupCW *cwg, WWindow *parent, const WFitParams *fp)
195 {
196     cwg->transient_szplcy=DFLT_SZPLCY;
197     
198     if(!group_init(&(cwg->grp), parent, fp))
199         return FALSE;
200     
201     region_add_bindmap((WRegion*)cwg, ioncore_groupcw_bindmap);
202     
203     return TRUE;
204 }
205
206
207 WGroupCW *create_groupcw(WWindow *parent, const WFitParams *fp)
208 {
209     CREATEOBJ_IMPL(WGroupCW, groupcw, (p, parent, fp));
210 }
211
212
213 void groupcw_deinit(WGroupCW *cwg)
214 {    
215     group_deinit(&(cwg->grp));
216 }
217
218
219 WRegion *groupcw_load(WWindow *par, const WFitParams *fp, ExtlTab tab)
220 {
221     WGroupCW *ws;
222     ExtlTab substab, subtab;
223     int i, n;
224     
225     ws=create_groupcw(par, fp);
226     
227     if(ws==NULL)
228         return NULL;
229         
230     if(!extl_table_gets_t(tab, "managed", &substab))
231         return (WRegion*)ws;
232
233     n=extl_table_get_n(substab);
234     for(i=1; i<=n; i++){
235         if(extl_table_geti_t(substab, i, &subtab)){
236             group_attach_new(&ws->grp, subtab);
237             extl_unref_table(subtab);
238         }
239     }
240     
241     extl_unref_table(substab);
242     
243     if(ws->grp.managed_list==NULL){
244         destroy_obj((Obj*)ws);
245         return NULL;
246     }
247
248     return (WRegion*)ws;
249 }
250
251
252 static DynFunTab groupcw_dynfuntab[]={
253     {(DynFun*)region_prepare_manage, 
254      (DynFun*)groupcw_prepare_manage},
255     
256     {(DynFun*)region_prepare_manage_transient,
257      (DynFun*)groupcw_prepare_manage_transient},
258     
259     /*
260     {(DynFun*)region_handle_drop,
261      (DynFun*)groupcw_handle_drop},
262     
263     {(DynFun*)group_do_add_managed,
264      (DynFun*)groupcw_do_add_managed},
265     */
266     
267     /*
268     {(DynFun*)region_get_rescue_pholder_for,
269      (DynFun*)groupcw_get_rescue_pholder_for},
270      */
271     
272     {(DynFun*)region_prepare_manage,
273      (DynFun*)groupcw_prepare_manage},
274
275     {(DynFun*)region_prepare_manage_transient,
276      (DynFun*)groupcw_prepare_manage_transient},
277     
278     {(DynFun*)region_displayname,
279      (DynFun*)groupcw_displayname},
280     
281     {region_managed_notify,
282      groupcw_managed_notify},
283     
284     END_DYNFUNTAB
285 };
286
287
288 EXTL_EXPORT
289 IMPLCLASS(WGroupCW, WGroup, groupcw_deinit, groupcw_dynfuntab);
290
291
292 /*}}}*/
293