Better error message
[notion/jeffpc.git] / ioncore / group-ws.c
blob1e7329a6f9cc7f55b84d06a4f11f8473b1b48c26
1 /*
2 * ion/ioncore/group-ws.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
7 */
9 #include <string.h>
11 #include <libtu/minmax.h>
12 #include <libtu/objp.h>
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 #include "saveload.h"
32 /*{{{ Settings */
35 void ioncore_groupws_set(ExtlTab tab)
37 char *method=NULL;
38 int fpp;
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);
51 if(extl_table_gets_i(tab, "float_placement_padding", &fpp))
52 ioncore_placement_padding=maxof(0, fpp);
56 void ioncore_groupws_get(ExtlTab t)
58 extl_table_sets_s(t, "float_placement_method",
59 (ioncore_placement_method==PLACEMENT_UDLR
60 ? "udlr"
61 : (ioncore_placement_method==PLACEMENT_LRUD
62 ? "lrud"
63 : "random")));
64 extl_table_sets_i(t, "float_placement_padding", ioncore_placement_padding);
68 /*}}}*/
71 /*{{{ Attach stuff */
74 static bool groupws_attach_framed(WGroupWS *ws,
75 WGroupAttachParams *ap,
76 WFramedParam *fp,
77 WRegion *reg)
79 WRegionAttachData data;
81 data.type=REGION_ATTACH_REPARENT;
82 data.u.reg=reg;
84 return (region_attach_framed((WRegion*)ws, fp,
85 (WRegionAttachFn*)group_do_attach,
86 ap, &data)!=NULL);
90 bool groupws_handle_drop(WGroupWS *ws, int x, int y,
91 WRegion *dropped)
93 WGroupAttachParams ap=GROUPATTACHPARAMS_INIT;
94 WFramedParam fp=FRAMEDPARAM_INIT;
96 ap.switchto_set=TRUE;
97 ap.switchto=TRUE;
99 fp.inner_geom_gravity_set=TRUE;
100 fp.inner_geom.x=x;
101 fp.inner_geom.y=y;
102 fp.inner_geom.w=REGION_GEOM(dropped).w;
103 fp.inner_geom.h=REGION_GEOM(dropped).h;
104 fp.gravity=NorthWestGravity;
106 return groupws_attach_framed(ws, &ap, &fp, dropped);
110 /*EXTL_DOC
111 * Attach region \var{reg} on \var{ws}.
112 * At least the following fields in \var{t} are supported:
114 * \begin{tabularx}{\linewidth}{lX}
115 * \tabhead{Field & Description}
116 * \var{switchto} & Should the region be switched to (boolean)? Optional. \\
117 * \var{geom} & Geometry; \var{x} and \var{y}, if set, indicates top-left of
118 * the frame to be created while \var{width} and \var{height}, if set, indicate
119 * the size of the client window within that frame. Optional.
120 * \end{tabularx}
122 EXTL_EXPORT_AS(WGroupWS, attach_framed)
123 bool groupws_attach_framed_extl(WGroupWS *ws, WRegion *reg, ExtlTab t)
125 WGroupAttachParams ap=GROUPATTACHPARAMS_INIT;
126 WFramedParam frp=FRAMEDPARAM_INIT;
128 if(reg==NULL)
129 return FALSE;
131 groupattachparams_get(&ap, t, NULL);
133 /* Sensible size is given in framedparams */
134 if(ap.geom_set){
135 ap.geom_set=0;
136 ap.geom_weak_set=1;
137 ap.geom_weak=0;
139 frp.inner_geom_gravity_set=1;
140 frp.inner_geom=ap.geom;
141 frp.gravity=NorthWestGravity;
142 extl_table_gets_i(t, "gravity", &frp.gravity);
145 return groupws_attach_framed(ws, &ap, &frp, reg);
149 /*}}}*/
152 /*{{{ groupws_prepare_manage */
155 static WPHolder *groupws_do_prepare_manage(WGroupWS *ws,
156 const WClientWin *cwin,
157 const WManageParams *param)
159 WGroupAttachParams ap=GROUPATTACHPARAMS_INIT;
160 WFramedParam fp=FRAMEDPARAM_INIT;
161 WPHolder *ph;
164 fp.inner_geom_gravity_set=TRUE;
165 fp.inner_geom=param->geom;
166 fp.gravity=param->gravity;
168 groupattachparams_get(&ap, cwin->proptab, "attach_params");
170 if(param->userpos ||
171 !param->maprq || ioncore_g.opmode==IONCORE_OPMODE_INIT){
172 ap.geom_weak_set=1;
173 ap.geom_weak=0;
174 }else if(!ap.geom_weak_set){
175 ap.geom_weak_set=1;
176 ap.geom_weak=REGION_RQGEOM_WEAK_X|REGION_RQGEOM_WEAK_Y;
179 ph=(WPHolder*)create_grouppholder(&ws->grp, NULL, &ap);
181 if(ph!=NULL)
182 ph=pholder_either((WPHolder*)create_framedpholder(ph, &fp), ph);
184 if(ph!=NULL){
185 WGroupPHolder *gph;
186 WGroupAttachParams gp=GROUPATTACHPARAMS_INIT;
188 gp.switchto_set=1;
189 gp.switchto=1;
190 gp.bottom=1;
192 gph=create_grouppholder(NULL, NULL, &gp);
194 if(gph!=NULL){
195 gph->recreate_pholder=ph;
196 return (WPHolder*)gph;
200 return ph;
204 WPHolder *groupws_prepare_manage(WGroupWS *ws, const WClientWin *cwin,
205 const WManageParams *param,
206 int priority)
208 int cpriority=MANAGE_PRIORITY_SUB(priority, MANAGE_PRIORITY_GROUP);
209 int bpriority=MANAGE_PRIORITY_SUBX(priority, MANAGE_PRIORITY_GROUP);
210 WRegion *b=(ws->grp.bottom!=NULL ? ws->grp.bottom->reg : NULL);
211 WPHolder *ph=NULL;
212 bool act_b=(ws->grp.bottom==ws->grp.current_managed);
213 bool use_bottom;
215 if(b!=NULL && !HAS_DYN(b, region_prepare_manage))
216 b=NULL;
218 use_bottom=(act_b
219 ? !extl_table_is_bool_set(cwin->proptab, "float")
220 : act_b);
222 if(b!=NULL && use_bottom)
223 ph=region_prepare_manage(b, cwin, param, bpriority);
225 if(ph==NULL){
226 /* Check current */
227 WRegion *r=(ws->grp.current_managed!=NULL
228 ? ws->grp.current_managed->reg
229 : NULL);
231 if(r!=NULL && r!=b)
232 ph=region_prepare_manage(r, cwin, param, cpriority);
235 if(ph==NULL && MANAGE_PRIORITY_OK(priority, MANAGE_PRIORITY_GROUP))
236 ph=groupws_do_prepare_manage(ws, cwin, param);
238 if(ph==NULL && b!=NULL && !use_bottom)
239 ph=region_prepare_manage(b, cwin, param, cpriority);
241 return ph;
245 WPHolder *groupws_prepare_manage_transient(WGroupWS *ws, const WClientWin *cwin,
246 const WManageParams *param,
247 int unused)
249 WGroupAttachParams ap=GROUPATTACHPARAMS_INIT;
250 WFramedParam fp=FRAMEDPARAM_INIT;
251 WPHolder *ph;
252 bool tmp;
254 ap.stack_above=OBJ_CAST(REGION_PARENT(param->tfor), WRegion);
255 if(ap.stack_above==NULL)
256 return NULL;
258 fp.inner_geom_gravity_set=TRUE;
259 fp.inner_geom=param->geom;
260 fp.gravity=param->gravity;
261 fp.mode=FRAME_MODE_TRANSIENT;
263 groupattachparams_get(&ap, cwin->proptab, "attach_params");
265 if(!ap.geom_weak_set || param->userpos ||
266 !param->maprq || ioncore_g.opmode==IONCORE_OPMODE_INIT){
267 ap.geom_weak_set=1;
268 ap.geom_weak=0;
271 ph=(WPHolder*)create_grouppholder(&ws->grp, NULL, &ap);
273 return pholder_either((WPHolder*)create_framedpholder(ph, &fp), ph);
277 static bool group_empty_for_bottom_stdisp(WGroup *ws)
279 WGroupIterTmp tmp;
280 WStacking *st;
282 FOR_ALL_NODES_IN_GROUP(ws, st, tmp){
283 if(st!=ws->bottom && st!=ws->managed_stdisp)
284 return FALSE;
287 return TRUE;
291 static WRegion *groupws_managed_disposeroot(WGroupWS *ws, WRegion *reg)
293 if(group_bottom(&ws->grp)==reg){
294 if(group_empty_for_bottom_stdisp(&ws->grp))
295 return region_disposeroot((WRegion*)ws);
298 return reg;
302 /*}}}*/
305 /*{{{ WGroupWS class */
308 bool groupws_init(WGroupWS *ws, WWindow *parent, const WFitParams *fp)
310 if(!group_init(&(ws->grp), parent, fp, "Notion GroupWS"))
311 return FALSE;
313 ws->initial_outputs=extl_create_table();
315 ((WRegion*)ws)->flags|=REGION_GRAB_ON_PARENT;
317 region_add_bindmap((WRegion*)ws, ioncore_groupws_bindmap);
319 return TRUE;
323 WGroupWS *create_groupws(WWindow *parent, const WFitParams *fp)
325 CREATEOBJ_IMPL(WGroupWS, groupws, (p, parent, fp));
329 void groupws_deinit(WGroupWS *ws)
331 extl_unref_table(ws->initial_outputs);
332 group_deinit(&(ws->grp));
336 WRegion *groupws_load(WWindow *par, const WFitParams *fp,
337 ExtlTab tab)
339 WGroupWS *ws;
340 ExtlTab io;
342 ws=create_groupws(par, fp);
344 if(ws==NULL)
345 return NULL;
347 group_do_load(&ws->grp, tab);
349 if(extl_table_gets_t(tab, "initial_outputs", &io))
350 ws->initial_outputs=io;
352 return (WRegion*)ws;
355 ExtlTab groupws_get_configuration(WGroupWS *ws)
358 ExtlTab tab;
360 tab=group_get_configuration(&ws->grp);
361 extl_table_sets_t(tab, "initial_outputs", ws->initial_outputs);
362 return tab;
365 EXTL_SAFE
366 EXTL_EXPORT_MEMBER
367 ExtlTab groupws_get_initial_outputs(WGroupWS *ws)
369 return extl_ref_table(ws->initial_outputs);
372 EXTL_SAFE
373 EXTL_EXPORT_MEMBER
374 void groupws_set_initial_outputs(WGroupWS *ws, ExtlTab tab)
376 extl_unref_table(ws->initial_outputs);
377 ws->initial_outputs=extl_ref_table(tab);
381 static DynFunTab groupws_dynfuntab[]={
382 {(DynFun*)region_prepare_manage,
383 (DynFun*)groupws_prepare_manage},
385 {(DynFun*)region_prepare_manage_transient,
386 (DynFun*)groupws_prepare_manage_transient},
388 {(DynFun*)region_managed_disposeroot,
389 (DynFun*)groupws_managed_disposeroot},
391 {(DynFun*)region_handle_drop,
392 (DynFun*)groupws_handle_drop},
394 {region_manage_stdisp,
395 group_manage_stdisp},
397 {(DynFun*)region_get_configuration,
398 (DynFun*)groupws_get_configuration},
400 END_DYNFUNTAB
404 EXTL_EXPORT
405 IMPLCLASS(WGroupWS, WGroup, groupws_deinit, groupws_dynfuntab);
408 /*}}}*/