]> git.decadent.org.uk Git - ion3.git/blob - ioncore/group-ws.c
[svn-upgrade] Integrating new upstream version, ion3 (20071109)
[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 frp=FRAMEDPARAM_INIT;
124     
125     if(reg==NULL)
126         return FALSE;
127     
128     group_get_attach_params(&ws->grp, t, &ap);
129     
130     /* Sensible size is given in framedparams */
131     if(ap.geom_set){
132         ap.geom_set=0;
133         ap.geom_weak_set=1;
134         ap.geom_weak=0;
135         
136         frp.inner_geom_gravity_set=1;
137         frp.inner_geom=ap.geom;
138         frp.gravity=NorthWestGravity;
139         extl_table_gets_i(t, "gravity", &frp.gravity);
140     }
141     
142     return groupws_attach_framed(ws, &ap, &frp, reg);
143 }
144
145
146 /*}}}*/
147
148
149 /*{{{ groupws_prepare_manage */
150
151
152 static WPHolder *groupws_do_prepare_manage(WGroupWS *ws, 
153                                            const WClientWin *cwin,
154                                            const WManageParams *param, 
155                                            int geom_weak)
156 {
157     WGroupAttachParams ap=GROUPATTACHPARAMS_INIT;
158     WFramedParam fp=FRAMEDPARAM_INIT;
159     WPHolder *ph;
160     
161
162     fp.inner_geom_gravity_set=TRUE;
163     fp.inner_geom=param->geom;
164     fp.gravity=param->gravity;
165     
166     ap.geom_weak_set=1;
167     ap.geom_weak=geom_weak;
168
169     ph=(WPHolder*)create_grouppholder(&ws->grp, NULL, &ap);
170     
171     if(ph!=NULL)
172         ph=pholder_either((WPHolder*)create_framedpholder(ph, &fp), ph);
173     
174     if(ph!=NULL)
175         ph=pholder_either((WPHolder*)create_groupedpholder((WPHolder*)ph), ph);
176     
177     return ph;
178 }
179
180
181 WPHolder *groupws_prepare_manage(WGroupWS *ws, const WClientWin *cwin,
182                                  const WManageParams *param,
183                                  int priority)
184 {
185     int cpriority=MANAGE_PRIORITY_SUB(priority, MANAGE_PRIORITY_GROUP);
186     int bpriority=MANAGE_PRIORITY_SUBX(priority, MANAGE_PRIORITY_GROUP);
187     WRegion *b=(ws->grp.bottom!=NULL ? ws->grp.bottom->reg : NULL);
188     WPHolder *ph=NULL;
189     bool act_b=(ws->grp.bottom==ws->grp.current_managed);
190     bool use_bottom;
191     int weak=0;
192     
193     if(param->maprq && ioncore_g.opmode!=IONCORE_OPMODE_INIT
194        && !param->userpos){
195         /* When the window is mapped by application request, position
196          * request is only honoured if the position was given by the user
197          * and in case of a transient (the app may know better where to 
198          * place them) or if we're initialising.
199          */
200         weak=REGION_RQGEOM_WEAK_X|REGION_RQGEOM_WEAK_Y;
201     }
202
203     if(b!=NULL && !HAS_DYN(b, region_prepare_manage))
204         b=NULL;
205     
206     use_bottom=(act_b
207                 ? !extl_table_is_bool_set(cwin->proptab, "float")
208                 : act_b);
209     
210     if(b!=NULL && use_bottom)
211         ph=region_prepare_manage(b, cwin, param, bpriority);
212     
213     if(ph==NULL){
214         /* Check current */
215         WRegion *r=(ws->grp.current_managed!=NULL 
216                     ? ws->grp.current_managed->reg 
217                     : NULL);
218         
219         if(r!=NULL && r!=b)
220             ph=region_prepare_manage(r, cwin, param, cpriority);
221     }
222     
223     if(ph==NULL && MANAGE_PRIORITY_OK(priority, MANAGE_PRIORITY_GROUP))
224         ph=groupws_do_prepare_manage(ws, cwin, param, weak);
225     
226     if(ph==NULL && b!=NULL && !use_bottom)
227         ph=region_prepare_manage(b, cwin, param, cpriority);
228     
229     return ph;
230 }
231
232
233 WPHolder *groupws_prepare_manage_transient(WGroupWS *ws, const WClientWin *cwin,
234                                            const WManageParams *param,
235                                            int unused)
236 {
237     WGroupAttachParams ap=GROUPATTACHPARAMS_INIT;
238     WFramedParam fp=FRAMEDPARAM_INIT;
239     WPHolder *ph;
240     
241     ap.stack_above=OBJ_CAST(REGION_PARENT(param->tfor), WRegion);
242     if(ap.stack_above==NULL)
243         return NULL;
244     
245     fp.inner_geom_gravity_set=TRUE;
246     fp.inner_geom=param->geom;
247     fp.gravity=param->gravity;
248     fp.mode=FRAME_MODE_TRANSIENT;
249     
250     ap.geom_weak_set=1;
251     ap.geom_weak=0;
252
253     ph=(WPHolder*)create_grouppholder(&ws->grp, NULL, &ap);
254     
255     return pholder_either((WPHolder*)create_framedpholder(ph, &fp), ph);
256 }
257
258
259 WPHolder *groupws_get_rescue_pholder_for(WGroupWS *ws, 
260                                          WRegion *forwhat)
261 {
262     WGroupAttachParams ap=GROUPATTACHPARAMS_INIT;
263     WFramedParam fp=FRAMEDPARAM_INIT;
264     WPHolder *ph;
265     
266     ap.geom_set=TRUE;
267     ap.geom=REGION_GEOM(forwhat);
268
269     ap.geom_weak_set=1;
270     ap.geom_weak=(REGION_PARENT(forwhat)!=REGION_PARENT(ws)
271                   ? REGION_RQGEOM_WEAK_X|REGION_RQGEOM_WEAK_Y
272                   : 0);
273
274     ph=(WPHolder*)create_grouppholder(&ws->grp, NULL, &ap);
275     
276     return pholder_either((WPHolder*)create_framedpholder(ph, &fp), ph);
277 }
278
279
280 static bool group_empty_for_bottom_stdisp(WGroup *ws)
281 {
282     WGroupIterTmp tmp;
283     WStacking *st;
284     
285     FOR_ALL_NODES_IN_GROUP(ws, st, tmp){
286         if(st!=ws->bottom && st!=ws->managed_stdisp)
287             return FALSE;
288     }
289     
290     return TRUE;
291 }
292
293
294 static WRegion *groupws_managed_disposeroot(WGroupWS *ws, WRegion *reg)
295 {
296     if(group_bottom(&ws->grp)==reg){
297         if(group_empty_for_bottom_stdisp(&ws->grp)){
298             WRegion *tmpr=region_disposeroot((WRegion*)ws);
299             return (tmpr!=NULL ? tmpr : reg);
300         }
301     }
302     
303     return reg;
304 }
305
306
307 /*}}}*/
308
309
310 /*{{{ WGroupWS class */
311
312
313 bool groupws_init(WGroupWS *ws, WWindow *parent, const WFitParams *fp)
314 {
315     if(!group_init(&(ws->grp), parent, fp))
316         return FALSE;
317
318     ((WRegion*)ws)->flags|=REGION_GRAB_ON_PARENT;
319     
320     region_add_bindmap((WRegion*)ws, ioncore_groupws_bindmap);
321     
322     return TRUE;
323 }
324
325
326 WGroupWS *create_groupws(WWindow *parent, const WFitParams *fp)
327 {
328     CREATEOBJ_IMPL(WGroupWS, groupws, (p, parent, fp));
329 }
330
331
332 void groupws_deinit(WGroupWS *ws)
333 {    
334     group_deinit(&(ws->grp));
335 }
336
337
338 WRegion *groupws_load(WWindow *par, const WFitParams *fp, 
339                       ExtlTab tab)
340 {
341     WGroupWS *ws;
342     
343     ws=create_groupws(par, fp);
344     
345     if(ws==NULL)
346         return NULL;
347
348     group_do_load(&ws->grp, tab);
349     
350     return (WRegion*)ws;
351 }
352
353
354 static DynFunTab groupws_dynfuntab[]={
355     {(DynFun*)region_prepare_manage, 
356      (DynFun*)groupws_prepare_manage},
357     
358     {(DynFun*)region_prepare_manage_transient,
359      (DynFun*)groupws_prepare_manage_transient},
360      
361     {(DynFun*)region_managed_disposeroot,
362      (DynFun*)groupws_managed_disposeroot},
363     
364     {(DynFun*)region_handle_drop,
365      (DynFun*)groupws_handle_drop},
366     
367     {(DynFun*)region_get_rescue_pholder_for,
368      (DynFun*)groupws_get_rescue_pholder_for},
369     
370     {region_manage_stdisp,
371      group_manage_stdisp},
372     
373     END_DYNFUNTAB
374 };
375
376
377 EXTL_EXPORT
378 IMPLCLASS(WGroupWS, WGroup, groupws_deinit, groupws_dynfuntab);
379
380
381 /*}}}*/
382