4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
11 #include <libtu/objp.h>
12 #include <libtu/setparam.h>
13 #include <libtu/minmax.h>
15 #include <ioncore/common.h>
16 #include <ioncore/global.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>
23 #include <ioncore/sizehint.h>
24 #include <ioncore/resize.h>
27 static void get_relative_geom(WRectangle
*g
, WRegion
*reg
, WRegion
*mgr
)
29 WWindow
*rel
=REGION_PARENT(mgr
), *w
;
33 for(w
=REGION_PARENT(reg
);
34 w
!=rel
&& (WRegion
*)w
!=mgr
;
37 g
->x
+=REGION_GEOM(w
).x
;
38 g
->y
+=REGION_GEOM(w
).y
;
43 static bool ioncore_do_detach(WRegion
*reg
, WGroup
*grp
, WFrameMode framemode
,
46 WGroupAttachParams ap
=GROUPATTACHPARAMS_INIT
;
47 WRegionAttachData data
;
53 ap
.switchto
=region_may_control_focus(reg
);
55 data
.type
=REGION_ATTACH_REPARENT
;
58 ph
=region_unset_get_return(reg
);
61 ph
=region_make_return_pholder(reg
);
65 if(framemode
!=FRAME_MODE_UNKNOWN
){
66 /* TODO: remove/obsolete this special case */
67 WFramedParam fpa
=FRAMEDPARAM_INIT
;
70 fpa
.inner_geom_gravity_set
=TRUE
;
71 fpa
.gravity
=ForgetGravity
;
73 ap
.geom_weak_set
=TRUE
;
77 ap
.level
=framelevel
+1;
79 get_relative_geom(&fpa
.inner_geom
, reg
, (WRegion
*)grp
);
81 ret
=(region_attach_framed((WRegion
*)grp
, &fpa
,
82 (WRegionAttachFn
*)group_do_attach
,
85 WStacking
*st
=ioncore_find_stacking(reg
);
88 ap
.level
=framelevel
+1;
94 /* Hack for modal detached queries, while transients become
97 if(st
->level
>STACKING_LEVEL_MODAL1
)
102 get_relative_geom(&ap
.geom
, reg
, (WRegion
*)grp
);
104 ret
=(group_do_attach(grp
, &ap
, &data
)!=NULL
);
108 destroy_obj((Obj
*)ph
);
109 else if(!region_do_set_return(reg
, ph
))
110 destroy_obj((Obj
*)ph
);
116 static WRegion
*check_mplex(WRegion
*reg
, WFrameMode
*mode
)
118 WMPlex
*mplex
=REGION_MANAGER_CHK(reg
, WMPlex
);
120 if(OBJ_IS(reg
, WWindow
) || mplex
==NULL
){
121 *mode
=FRAME_MODE_UNKNOWN
;
125 *mode
=FRAME_MODE_FLOATING
;
127 if(OBJ_IS(mplex
, WFrame
)){
128 WFrameMode mode2
=frame_mode((WFrame
*)mplex
);
129 if(framemode_unalt(mode2
)==FRAME_MODE_TRANSIENT
)
133 return (WRegion
*)mplex
;
137 static WGroup
*find_group(WRegion
*reg
, uint
*level
)
139 WRegion
*mgr
=REGION_MANAGER(reg
);
143 mgr
=REGION_MANAGER(mgr
);
144 if(OBJ_IS(mgr
, WGroup
)){
145 WStacking
*st
=ioncore_find_stacking((WRegion
*)reg
);
156 bool ioncore_detach(WRegion
*reg
, int sp
)
161 uint level
=STACKING_LEVEL_NORMAL
;
163 reg
=region_groupleader_of(reg
);
165 grp
=find_group(check_mplex(reg
, &mode
), &level
);
167 /* reg is only considered detached if there's no higher-level group
168 * to attach to, thus causing 'toggle' to cycle.
171 nset
=libtu_do_setparam(sp
, set
);
177 return ioncore_do_detach(reg
, grp
, mode
, level
);
179 WPHolder
*ph
=region_get_return(reg
);
182 if(!pholder_attach_mcfgoto(ph
, PHOLDER_ATTACH_SWITCHTO
, reg
)){
183 warn(TR("Failed to reattach."));
186 region_unset_return(reg
);
195 * Detach or reattach \var{reg} or any group it is the leader of
196 * (see \fnref{WRegion.groupleader_of}), depending on whether \var{how}
197 * is \codestr{set}, \codestr{unset} or \codestr{toggle}. If this
198 * region is not a window, it is put into a frame.
200 * Detaching a region means having it managed by its nearest ancestor
201 * \type{WGroup}. Reattaching means having it managed where it used
202 * to be managed, if a ``return placeholder'' exists.
204 * Additionally, setting \var{how} to \codestr{forget}, can be used to
205 * clear this return placeholder of the group leader of \var{reg}.
207 EXTL_EXPORT_AS(ioncore
, detach
)
208 bool ioncore_detach_extl(WRegion
*reg
, const char *how
)
213 if(strcmp(how
, "forget")==0){
214 region_unset_return(region_groupleader_of(reg
));
218 return ioncore_detach(reg
, libtu_string_to_setparam(how
));
222 void do_unsqueeze(WRegion
*reg
)
226 if(OBJ_IS(reg
, WScreen
))
229 region_size_hints(reg
, &h
);
234 if(h
.min_width
<=REGION_GEOM(reg
).w
&&
235 h
.min_height
<=REGION_GEOM(reg
).h
){
239 ioncore_detach(reg
, SETPARAM_SET
);
244 * Try to detach \var{reg} if it fits poorly in its
245 * current location. This function does not do anything,
246 * unless \var{override} is set or the \var{unsqueeze} option
247 * of \fnref{ioncore.set} is set.
250 void ioncore_unsqueeze(WRegion
*reg
, bool override
)
252 if(ioncore_g
.unsqueeze_enabled
|| override
)