]> git.decadent.org.uk Git - ion3.git/blob - ioncore/group-ws.c
[svn-upgrade] Integrating new upstream version, ion3 (20070506)
[ion3.git] / ioncore / group-ws.c
1 /*
2  * ion/ioncore/group-ws.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/minmax.h>
12 #include <libtu/objp.h>
13
14 #include "common.h"
15 #include "global.h"
16 #include "region.h"
17 #include "focus.h"
18 #include "group.h"
19 #include "regbind.h"
20 #include "bindmaps.h"
21 #include "xwindow.h"
22 #include "group-ws.h"
23 #include "group-cw.h"
24 #include "grouppholder.h"
25 #include "groupedpholder.h"
26 #include "framedpholder.h"
27 #include "float-placement.h"
28 #include "resize.h"
29 #include "conf.h"
30
31
32 /*{{{ Settings */
33
34
35 void ioncore_groupws_set(ExtlTab tab)
36 {
37     char *method=NULL;
38     ExtlTab t;
39     
40     if(extl_table_gets_s(tab, "float_placement_method", &method)){
41         if(strcmp(method, "udlr")==0)
42             ioncore_placement_method=PLACEMENT_UDLR;
43         else if(strcmp(method, "lrud")==0)
44             ioncore_placement_method=PLACEMENT_LRUD;
45         else if(strcmp(method, "random")==0)
46             ioncore_placement_method=PLACEMENT_RANDOM;
47         else
48             warn(TR("Unknown placement method \"%s\"."), method);
49         free(method);
50     }
51 }
52
53
54 void ioncore_groupws_get(ExtlTab t)
55 {
56     extl_table_sets_s(t, "float_placement_method", 
57                       (ioncore_placement_method==PLACEMENT_UDLR
58                        ? "udlr" 
59                        : (ioncore_placement_method==PLACEMENT_LRUD
60                           ? "lrud" 
61                           : "random")));
62 }
63
64
65 /*}}}*/
66
67
68 /*{{{ Attach stuff */
69
70
71 static bool groupws_attach_framed(WGroupWS *ws, 
72                                   WGroupAttachParams *ap,
73                                   WFramedParam *fp,
74                                   WRegion *reg)
75 {
76     WRegionAttachData data;
77     
78     data.type=REGION_ATTACH_REPARENT;
79     data.u.reg=reg;
80     
81     return (region_attach_framed((WRegion*)ws, fp,
82                                  (WRegionAttachFn*)group_do_attach,
83                                  ap, &data)!=NULL);
84 }
85
86
87 bool groupws_handle_drop(WGroupWS *ws, int x, int y,
88                          WRegion *dropped)
89 {
90     WGroupAttachParams ap=GROUPATTACHPARAMS_INIT;
91     WFramedParam fp=FRAMEDPARAM_INIT;
92     
93     ap.switchto_set=TRUE;
94     ap.switchto=TRUE;
95     
96     fp.inner_geom_gravity_set=TRUE;
97     fp.inner_geom.x=x;
98     fp.inner_geom.y=y;
99     fp.inner_geom.w=REGION_GEOM(dropped).w;
100     fp.inner_geom.h=REGION_GEOM(dropped).h;
101     fp.gravity=NorthWestGravity;
102     
103     return groupws_attach_framed(ws, &ap, &fp, dropped);
104 }
105
106
107 /*EXTL_DOC
108  * Attach region \var{reg} on \var{ws}.
109  * At least the following fields in \var{t} are supported:
110  * 
111  * \begin{tabularx}{\linewidth}{lX}
112  *  \tabhead{Field & Description}
113  *  \var{switchto} & Should the region be switched to (boolean)? Optional. \\
114  *  \var{geom} & Geometry; \var{x} and \var{y}, if set, indicates top-left of 
115  *   the frame to be created while \var{width} and \var{height}, if set, indicate
116  *   the size of the client window within that frame. Optional.
117  * \end{tabularx}
118  */
119 EXTL_EXPORT_AS(WGroupWS, attach_framed)
120 bool groupws_attach_framed_extl(WGroupWS *ws, WRegion *reg, ExtlTab t)
121 {
122     WGroupAttachParams ap=GROUPATTACHPARAMS_INIT;
123     WFramedParam fp=FRAMEDPARAM_INIT;
124     ExtlTab gt;
125     
126     if(reg==NULL)
127         return FALSE;
128     
129     fp.gravity=ForgetGravity;
130     
131     if(extl_table_is_bool_set(t, "switchto")){
132         ap.switchto_set=TRUE;
133         ap.switchto=TRUE;
134     }
135     
136     if(extl_table_gets_t(t, "geom", &gt)){
137         int pos=0, size=0;
138         
139         fp.inner_geom.x=0;
140         fp.inner_geom.y=0;
141
142         if(extl_table_gets_i(gt, "x", &(ap.geom.x)))
143             pos++;
144         if(extl_table_gets_i(gt, "y", &(ap.geom.y)))
145             pos++;
146     
147         if(extl_table_gets_i(gt, "w", &(ap.geom.w)))
148             size++;
149         if(extl_table_gets_i(gt, "h", &(ap.geom.h)))
150             size++;
151         
152         fp.inner_geom.w=maxof(fp.inner_geom.w, 1);
153         fp.inner_geom.h=maxof(fp.inner_geom.h, 1);
154         
155         fp.inner_geom_gravity_set=(size==2 && pos==2);
156         
157         extl_unref_table(gt);
158     }
159     
160     return groupws_attach_framed(ws, &ap, &fp, reg);
161 }
162
163
164 /*}}}*/
165
166
167 /*{{{ groupws_prepare_manage */
168
169
170 static WPHolder *groupws_do_prepare_manage(WGroupWS *ws, 
171                                            const WClientWin *cwin,
172                                            const WManageParams *param, 
173                                            int geom_weak)
174 {
175     WGroupAttachParams ap=GROUPATTACHPARAMS_INIT;
176     WFramedParam fp=FRAMEDPARAM_INIT;
177     WPHolder *ph;
178     
179
180     fp.inner_geom_gravity_set=TRUE;
181     fp.inner_geom=param->geom;
182     fp.gravity=param->gravity;
183     
184     ap.geom_weak_set=1;
185     ap.geom_weak=geom_weak;
186
187     ph=(WPHolder*)create_grouppholder(&ws->grp, NULL, &ap);
188     
189     if(ph!=NULL)
190         ph=pholder_either((WPHolder*)create_framedpholder(ph, &fp), ph);
191     
192     if(ph!=NULL)
193         ph=pholder_either((WPHolder*)create_groupedpholder((WPHolder*)ph), ph);
194     
195     return ph;
196 }
197
198
199 WPHolder *groupws_prepare_manage(WGroupWS *ws, const WClientWin *cwin,
200                                  const WManageParams *param,
201                                  int priority)
202 {
203     int cpriority=MANAGE_PRIORITY_SUB(priority, MANAGE_PRIORITY_GROUP);
204     int bpriority=MANAGE_PRIORITY_SUBX(priority, MANAGE_PRIORITY_GROUP);
205     WRegion *b=(ws->grp.bottom!=NULL ? ws->grp.bottom->reg : NULL);
206     WPHolder *ph=NULL;
207     bool act_b=(ws->grp.bottom==ws->grp.current_managed);
208     bool use_bottom;
209     int weak=0;
210     
211     if(param->maprq && ioncore_g.opmode!=IONCORE_OPMODE_INIT
212        && !param->userpos){
213         /* When the window is mapped by application request, position
214          * request is only honoured if the position was given by the user
215          * and in case of a transient (the app may know better where to 
216          * place them) or if we're initialising.
217          */
218         weak=REGION_RQGEOM_WEAK_X|REGION_RQGEOM_WEAK_Y;
219     }
220
221     if(b!=NULL && !HAS_DYN(b, region_prepare_manage))
222         b=NULL;
223     
224     use_bottom=(act_b
225                 ? !extl_table_is_bool_set(cwin->proptab, "float")
226                 : act_b);
227     
228     if(b!=NULL && use_bottom)
229         ph=region_prepare_manage(b, cwin, param, bpriority);
230     
231     if(ph==NULL){
232         /* Check current */
233         WRegion *r=(ws->grp.current_managed!=NULL 
234                     ? ws->grp.current_managed->reg 
235                     : NULL);
236         
237         if(r!=NULL && r!=b)
238             ph=region_prepare_manage(r, cwin, param, cpriority);
239     }
240     
241     if(ph==NULL && MANAGE_PRIORITY_OK(priority, MANAGE_PRIORITY_GROUP))
242         ph=groupws_do_prepare_manage(ws, cwin, param, weak);
243     
244     if(ph==NULL && b!=NULL && !use_bottom)
245         ph=region_prepare_manage(b, cwin, param, cpriority);
246     
247     return ph;
248 }
249
250
251 WPHolder *groupws_prepare_manage_transient(WGroupWS *ws, const WClientWin *cwin,
252                                            const WManageParams *param,
253                                            int unused)
254 {
255     WGroupAttachParams ap=GROUPATTACHPARAMS_INIT;
256     WFramedParam fp=FRAMEDPARAM_INIT;
257     WPHolder *ph;
258     
259     ap.stack_above=OBJ_CAST(REGION_PARENT(param->tfor), WRegion);
260     if(ap.stack_above==NULL)
261         return NULL;
262     
263     fp.inner_geom_gravity_set=TRUE;
264     fp.inner_geom=param->geom;
265     fp.gravity=param->gravity;
266     fp.mode=FRAME_MODE_TRANSIENT;
267     
268     ap.geom_weak_set=1;
269     ap.geom_weak=0;
270
271     ph=(WPHolder*)create_grouppholder(&ws->grp, NULL, &ap);
272     
273     return pholder_either((WPHolder*)create_framedpholder(ph, &fp), ph);
274 }
275
276
277 WPHolder *groupws_get_rescue_pholder_for(WGroupWS *ws, 
278                                          WRegion *forwhat)
279 {
280     WGroupAttachParams ap=GROUPATTACHPARAMS_INIT;
281     WFramedParam fp=FRAMEDPARAM_INIT;
282     WPHolder *ph;
283     
284     ap.geom_set=TRUE;
285     ap.geom=REGION_GEOM(forwhat);
286
287     ap.geom_weak_set=1;
288     ap.geom_weak=(REGION_PARENT(forwhat)!=REGION_PARENT(ws)
289                   ? REGION_RQGEOM_WEAK_X|REGION_RQGEOM_WEAK_Y
290                   : 0);
291
292     ph=(WPHolder*)create_grouppholder(&ws->grp, NULL, &ap);
293     
294     return pholder_either((WPHolder*)create_framedpholder(ph, &fp), ph);
295 }
296
297
298 /*}}}*/
299
300
301 /*{{{ WGroupWS class */
302
303
304 bool groupws_init(WGroupWS *ws, WWindow *parent, const WFitParams *fp)
305 {
306     if(!group_init(&(ws->grp), parent, fp))
307         return FALSE;
308
309     ((WRegion*)ws)->flags|=REGION_GRAB_ON_PARENT;
310     
311     region_add_bindmap((WRegion*)ws, ioncore_groupws_bindmap);
312     
313     return TRUE;
314 }
315
316
317 WGroupWS *create_groupws(WWindow *parent, const WFitParams *fp)
318 {
319     CREATEOBJ_IMPL(WGroupWS, groupws, (p, parent, fp));
320 }
321
322
323 void groupws_deinit(WGroupWS *ws)
324 {    
325     group_deinit(&(ws->grp));
326 }
327
328
329 WRegion *groupws_load(WWindow *par, const WFitParams *fp, 
330                       ExtlTab tab)
331 {
332     WGroupWS *ws;
333     
334     ws=create_groupws(par, fp);
335     
336     if(ws==NULL)
337         return NULL;
338
339     group_do_load(&ws->grp, tab);
340     
341     return (WRegion*)ws;
342 }
343
344
345 static DynFunTab groupws_dynfuntab[]={
346     {(DynFun*)region_prepare_manage, 
347      (DynFun*)groupws_prepare_manage},
348     
349     {(DynFun*)region_prepare_manage_transient,
350      (DynFun*)groupws_prepare_manage_transient},
351     
352     {(DynFun*)region_handle_drop,
353      (DynFun*)groupws_handle_drop},
354     
355     {(DynFun*)region_get_rescue_pholder_for,
356      (DynFun*)groupws_get_rescue_pholder_for},
357     
358     {region_manage_stdisp,
359      group_manage_stdisp},
360     
361     END_DYNFUNTAB
362 };
363
364
365 EXTL_EXPORT
366 IMPLCLASS(WGroupWS, WGroup, groupws_deinit, groupws_dynfuntab);
367
368
369 /*}}}*/
370