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