4 * Copyright (c) Tuomo Valkonen 1999-2007.
6 * Ion is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
12 #include <libtu/objp.h>
13 #include <libtu/setparam.h>
14 #include <libtu/minmax.h>
16 #include <ioncore/common.h>
17 #include <ioncore/mplex.h>
18 #include <ioncore/focus.h>
19 #include <ioncore/group.h>
20 #include <ioncore/group-ws.h>
21 #include <ioncore/framedpholder.h>
22 #include <ioncore/return.h>
25 static void get_relative_geom(WRectangle *g, WRegion *reg, WRegion *mgr)
27 WWindow *rel=REGION_PARENT(mgr), *w;
31 for(w=REGION_PARENT(reg);
32 w!=rel && (WRegion*)w!=mgr;
35 g->x+=REGION_GEOM(w).x;
36 g->y+=REGION_GEOM(w).y;
41 bool ioncore_do_detach(WRegion *reg, WGroup *grp, WFrameMode framemode)
43 WGroupAttachParams ap=GROUPATTACHPARAMS_INIT;
44 WRegionAttachData data;
50 ap.switchto=region_may_control_focus(reg);
52 data.type=REGION_ATTACH_REPARENT;
55 ph=region_unset_get_return(reg);
58 ph=region_make_return_pholder(reg);
62 if(framemode!=FRAME_MODE_UNKNOWN){
63 WFramedParam fpa=FRAMEDPARAM_INIT;
66 fpa.inner_geom_gravity_set=TRUE;
67 fpa.gravity=ForgetGravity;
69 ap.geom_weak_set=TRUE;
72 get_relative_geom(&fpa.inner_geom, reg, (WRegion*)grp);
74 ret=(region_attach_framed((WRegion*)grp, &fpa,
75 (WRegionAttachFn*)group_do_attach,
78 WStacking *st=ioncore_find_stacking(reg);
84 ap.level=maxof(st->level, STACKING_LEVEL_NORMAL);
89 get_relative_geom(&ap.geom, reg, (WRegion*)grp);
91 ret=(group_do_attach(grp, &ap, &data)!=NULL);
95 destroy_obj((Obj*)ph);
96 else if(!region_do_set_return(reg, ph))
97 destroy_obj((Obj*)ph);
103 static WRegion *check_mplex(WRegion *reg, WFrameMode *mode)
105 WMPlex *mplex=REGION_MANAGER_CHK(reg, WMPlex);
107 if(OBJ_IS(reg, WWindow) || mplex==NULL){
108 *mode=FRAME_MODE_UNKNOWN;
112 *mode=FRAME_MODE_FLOATING;
114 if(OBJ_IS(mplex, WFrame)
115 && frame_mode((WFrame*)mplex)==FRAME_MODE_TRANSIENT){
116 *mode=FRAME_MODE_TRANSIENT;
119 return (WRegion*)mplex;
123 static WGroup *find_group(WRegion *reg)
125 WRegion *mgr=REGION_MANAGER(reg);
128 mgr=REGION_MANAGER(mgr);
129 if(OBJ_IS(mgr, WGroup))
137 bool ioncore_detach(WRegion *reg, int sp)
139 WPHolder *ph=region_get_return(reg);
144 reg=region_group_if_bottom(reg);
146 grp=find_group(check_mplex(reg, &mode));
148 /* reg is only considered detached if there's no higher-level group
149 * to attach to, thus causing 'toggle' to cycle.
152 nset=libtu_do_setparam(sp, set);
158 return ioncore_do_detach(reg, grp, mode);
160 WPHolder *ph=region_get_return(reg);
163 if(!pholder_attach_mcfgoto(ph, PHOLDER_ATTACH_SWITCHTO, reg)){
164 warn(TR("Failed to reattach."));
167 region_unset_return(reg);
176 * Detach or reattach \var{reg}, depending on whether \var{how}
177 * is 'set'/'unset'/'toggle'. (Detaching means making \var{reg}
178 * managed by its nearest ancestor \type{WGroup}, framed if \var{reg} is
179 * not itself \type{WFrame}. Reattaching means making it managed where
180 * it used to be managed, if a return-placeholder exists.)
181 * If \var{reg} is the 'bottom' of some group, the whole group is
182 * detached. If \var{reg} is a \type{WWindow}, it is put into a
185 EXTL_EXPORT_AS(ioncore, detach)
186 bool ioncore_detach_extl(WRegion *reg, const char *how)
191 return ioncore_detach(reg, libtu_string_to_setparam(how));