/*
* ion/ioncore/detach.c
*
- * Copyright (c) Tuomo Valkonen 1999-2007.
+ * Copyright (c) Tuomo Valkonen 1999-2009.
*
- * Ion is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
+ * See the included file LICENSE for details.
*/
+#include <string.h>
+
#include <libtu/objp.h>
#include <libtu/setparam.h>
#include <libtu/minmax.h>
#include <ioncore/common.h>
+#include <ioncore/global.h>
#include <ioncore/mplex.h>
#include <ioncore/focus.h>
#include <ioncore/group.h>
#include <ioncore/group-ws.h>
#include <ioncore/framedpholder.h>
#include <ioncore/return.h>
+#include <ioncore/sizehint.h>
+#include <ioncore/resize.h>
static void get_relative_geom(WRectangle *g, WRegion *reg, WRegion *mgr)
}
-bool ioncore_do_detach(WRegion *reg, WGroup *grp, WFrameMode framemode)
+static bool ioncore_do_detach(WRegion *reg, WGroup *grp, WFrameMode framemode,
+ uint framelevel)
{
WGroupAttachParams ap=GROUPATTACHPARAMS_INIT;
WRegionAttachData data;
}
if(framemode!=FRAME_MODE_UNKNOWN){
+ /* TODO: remove/obsolete this special case */
WFramedParam fpa=FRAMEDPARAM_INIT;
fpa.mode=framemode;
ap.geom_weak_set=TRUE;
ap.geom_weak=0;
+
+ ap.level_set=TRUE;
+ ap.level=framelevel+1;
get_relative_geom(&fpa.inner_geom, reg, (WRegion*)grp);
}else{
WStacking *st=ioncore_find_stacking(reg);
+ ap.level_set=TRUE;
+ ap.level=framelevel+1;
+
if(st!=NULL){
ap.szplcy=st->szplcy;
ap.szplcy_set=TRUE;
- ap.level=maxof(st->level, STACKING_LEVEL_NORMAL);
- ap.level_set=TRUE;
+ /* Hack for modal detached queries, while transients become
+ * non-modal detached.
+ */
+ if(st->level>STACKING_LEVEL_MODAL1)
+ ap.level=st->level;
}
ap.geom_set=TRUE;
*mode=FRAME_MODE_FLOATING;
- if(OBJ_IS(mplex, WFrame)
- && frame_mode((WFrame*)mplex)==FRAME_MODE_TRANSIENT){
- *mode=FRAME_MODE_TRANSIENT;
+ if(OBJ_IS(mplex, WFrame)){
+ WFrameMode mode2=frame_mode((WFrame*)mplex);
+ if(framemode_unalt(mode2)==FRAME_MODE_TRANSIENT)
+ *mode=mode2;
}
return (WRegion*)mplex;
}
-static WGroup *find_group(WRegion *reg)
+static WGroup *find_group(WRegion *reg, uint *level)
{
WRegion *mgr=REGION_MANAGER(reg);
while(mgr!=NULL){
+ reg=mgr;
mgr=REGION_MANAGER(mgr);
- if(OBJ_IS(mgr, WGroup))
+ if(OBJ_IS(mgr, WGroup)){
+ WStacking *st=ioncore_find_stacking((WRegion*)reg);
+ if(st!=NULL)
+ *level=st->level;
break;
+ }
}
return (WGroup*)mgr;
bool ioncore_detach(WRegion *reg, int sp)
{
- WPHolder *ph=region_get_return(reg);
WFrameMode mode;
WGroup *grp;
bool set, nset;
+ uint level=STACKING_LEVEL_NORMAL;
- reg=region_group_if_bottom(reg);
+ reg=region_groupleader_of(reg);
- grp=find_group(check_mplex(reg, &mode));
+ grp=find_group(check_mplex(reg, &mode), &level);
/* reg is only considered detached if there's no higher-level group
* to attach to, thus causing 'toggle' to cycle.
return set;
if(!set){
- return ioncore_do_detach(reg, grp, mode);
+ return ioncore_do_detach(reg, grp, mode, level);
}else{
WPHolder *ph=region_get_return(reg);
/*EXTL_DOC
- * Detach or reattach \var{reg}, depending on whether \var{how}
- * is 'set'/'unset'/'toggle'. (Detaching means making \var{reg}
- * managed by its nearest ancestor \type{WGroup}, framed if \var{reg} is
- * not itself \type{WFrame}. Reattaching means making it managed where
- * it used to be managed, if a return-placeholder exists.)
- * If \var{reg} is the 'bottom' of some group, the whole group is
- * detached. If \var{reg} is a \type{WWindow}, it is put into a
- * frame.
+ * Detach or reattach \var{reg} or any group it is the leader of
+ * (see \fnref{WRegion.groupleader_of}), depending on whether \var{how}
+ * is \codestr{set}, \codestr{unset} or \codestr{toggle}. If this
+ * region is not a window, it is put into a frame.
+ *
+ * Detaching a region means having it managed by its nearest ancestor
+ * \type{WGroup}. Reattaching means having it managed where it used
+ * to be managed, if a ``return placeholder'' exists.
+ *
+ * Additionally, setting \var{how} to \codestr{forget}, can be used to
+ * clear this return placeholder of the group leader of \var{reg}.
*/
EXTL_EXPORT_AS(ioncore, detach)
bool ioncore_detach_extl(WRegion *reg, const char *how)
if(how==NULL)
how="set";
+ if(strcmp(how, "forget")==0){
+ region_unset_return(region_groupleader_of(reg));
+ return FALSE;
+ }
+
return ioncore_detach(reg, libtu_string_to_setparam(how));
}
+void do_unsqueeze(WRegion *reg)
+{
+ WSizeHints h;
+
+ if(OBJ_IS(reg, WScreen))
+ return;
+
+ region_size_hints(reg, &h);
+
+ if(!h.min_set)
+ return;
+
+ if(h.min_width<=REGION_GEOM(reg).w &&
+ h.min_height<=REGION_GEOM(reg).h){
+ return;
+ }
+
+ ioncore_detach(reg, SETPARAM_SET);
+}
+
+
+/*EXTL_DOC
+ * Try to detach \var{reg} if it fits poorly in its
+ * current location. This function does not do anything,
+ * unless \var{override} is set or the \var{unsqueeze} option
+ * of \fnref{ioncore.set} is set.
+ */
+EXTL_EXPORT
+void ioncore_unsqueeze(WRegion *reg, bool override)
+{
+ if(ioncore_g.unsqueeze_enabled || override)
+ do_unsqueeze(reg);
+}
+
+