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