/*
* ion/mod_tiling/ops.c
*
- * Copyright (c) Tuomo Valkonen 1999-2006.
+ * Copyright (c) Tuomo Valkonen 1999-2007.
*
* 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
*/
#include <libtu/objp.h>
-
#include <ioncore/common.h>
#include <ioncore/mplex.h>
#include <ioncore/focus.h>
+#include <ioncore/return.h>
#include <ioncore/group.h>
-#include <ioncore/group-ws.h>
-#include <ioncore/framedpholder.h>
#include "tiling.h"
-static WGroup *find_group(WRegion *reg, bool *detach_framed)
-{
- WRegion *mgr=REGION_MANAGER(reg);
- bool was_grouped=FALSE;
-
- if(OBJ_IS(mgr, WMPlex)){
- WMPlex *mplex=(WMPlex*)mgr;
- *detach_framed=TRUE;
- mgr=REGION_MANAGER(mgr);
- if(OBJ_IS(mgr, WGroup)){
- assert(mplex->mgd!=NULL);
- if(mplex->mgd->reg==reg && mplex->mgd->mgr_next==NULL){
- /* Nothing to detach */
- return NULL;
- }
- }
- }else{
- was_grouped=OBJ_IS(mgr, WGroup);
- *detach_framed=FALSE;
- }
-
- while(mgr!=NULL){
- mgr=REGION_MANAGER(mgr);
- if(OBJ_IS(mgr, WGroup))
- break;
- }
-
- if(mgr==NULL && was_grouped)
- warn(TR("Already detached."));
-
- return (WGroup*)mgr;
-}
-
-
-static void get_relative_geom(WRectangle *g, WRegion *reg, WRegion *mgr)
-{
- WWindow *rel=REGION_PARENT(mgr), *w;
-
- *g=REGION_GEOM(reg);
-
- for(w=REGION_PARENT(reg);
- w!=rel && (WRegion*)w!=mgr;
- w=REGION_PARENT(w)){
-
- g->x+=REGION_GEOM(w).x;
- g->y+=REGION_GEOM(w).y;
- }
-}
-
-
-/*EXTL_DOC
- * Detach \var{reg}, i.e. make it managed by its nearest ancestor
- * \type{WGroup}, framed if \var{reg} is not itself \type{WFrame}.
- */
-EXTL_EXPORT
-bool mod_tiling_detach(WRegion *reg)
-{
- bool detach_framed=!OBJ_IS(reg, WFrame);
- WGroupAttachParams ap=GROUPATTACHPARAMS_INIT;
- WRegionAttachData data;
- WGroup *grp;
-
- grp=find_group(reg, &detach_framed);
-
- if(grp==NULL)
- return FALSE;
-
- ap.switchto_set=TRUE;
- ap.switchto=region_may_control_focus(reg);
-
- ap.geom_set=TRUE;
- get_relative_geom(&ap.geom, reg, (WRegion*)grp);
-
- /* TODO: Retain (root-relative) geometry of reg for framed
- * detach instead of making a frame of this size?
- */
-
- data.type=REGION_ATTACH_REPARENT;
- data.u.reg=reg;
-
- if(detach_framed){
- WFramedParam fp=FRAMEDPARAM_INIT;
-
- return (region_attach_framed((WRegion*)grp, &fp,
- (WRegionAttachFn*)group_do_attach,
- &ap, &data)!=NULL);
- }else{
- return (group_do_attach(grp, &ap, &data)!=NULL);
- }
-}
+/*{{{ mkbottom */
static WRegion *mkbottom_fn(WWindow *parent, const WFitParams *fp,
void *param)
{
- WRegion *reg=(WRegion*)param;
+ WRegion *reg=(WRegion*)param, *res;
+ WRegionAttachData data;
WTiling *tiling;
- WSplitRegion *node=NULL;
+ WFitParams fp2;
- if(!region_fitrep(reg, parent, fp))
- return NULL;
+ fp2.mode=REGION_FIT_EXACT;
+ fp2.g=fp->g;
- tiling=create_tiling(parent, fp, NULL, FALSE);
+ tiling=create_tiling(parent, &fp2, NULL, FALSE);
if(tiling==NULL)
return NULL;
-
- node=create_splitregion(®ION_GEOM(tiling), reg);
- if(node!=NULL){
- tiling->split_tree=(WSplit*)node;
- tiling->split_tree->ws_if_root=tiling;
-
- region_detach_manager(reg);
- if(tiling_managed_add(tiling, reg))
- return (WRegion*)tiling;
-
- #warning "TODO: reattach?"
-
- destroy_obj((Obj*)tiling->split_tree);
- tiling->split_tree=NULL;
- }
+ data.type=REGION_ATTACH_REPARENT;
+ data.u.reg=reg;
- destroy_obj((Obj*)tiling);
- return NULL;
+ /* Warning! Potentially dangerous call to remove a `reg` from the same
+ * group we're being attached to, and from the attach routine of which
+ * this function is called from!
+ */
+ res=region_attach_helper((WRegion*)tiling, parent, &fp2,
+ (WRegionDoAttachFn*)tiling_do_attach_initial,
+ NULL, &data);
+
+ if(res==NULL){
+ destroy_obj((Obj*)tiling);
+ return NULL;
+ }
+
+ return (WRegion*)tiling;
}
WGroup *grp=REGION_MANAGER_CHK(reg, WGroup);
WGroupAttachParams ap=GROUPATTACHPARAMS_INIT;
WRegionAttachData data;
- WRegion *tiling;
if(grp==NULL){
warn(TR("Not member of a group"));
return FALSE;
}
- if(grp->bottom!=NULL){
+ if(group_bottom(grp)!=NULL){
warn(TR("Manager group already has bottom"));
return FALSE;
}
data.u.n.fn=mkbottom_fn;
data.u.n.param=reg;
- /* kele... poisto samalla kuin attach */
+ /* See the "Warning!" above. */
return (group_do_attach(grp, &ap, &data)!=NULL);
}
+
+
+/*}}}*/
+
+
+/*{{{ untile */
+
+
+/*EXTL_DOC
+ * If \var{tiling} is managed by some group, float the frames in
+ * the tiling in that group, and dispose of \var{tiling}.
+ */
+EXTL_EXPORT
+bool mod_tiling_untile(WTiling *tiling)
+{
+ WGroup *grp=REGION_MANAGER_CHK(tiling, WGroup);
+ WGroupAttachParams param=GROUPATTACHPARAMS_INIT;
+ WTilingIterTmp tmp;
+ WRegion *reg, *reg2;
+
+ if(grp==NULL){
+ warn(TR("Not member of a group"));
+ return FALSE;
+ }
+
+ if(group_bottom(grp)==(WRegion*)tiling)
+ group_set_bottom(grp, NULL);
+
+ /* Setting `batchop` will stop `tiling_managed_remove` from
+ * resizing remaining frames into freed space. It will also
+ * stop the tiling from being destroyed by actions of
+ * `tiling_managed_disposeroot`.
+ */
+ tiling->batchop=TRUE;
+
+ FOR_ALL_MANAGED_BY_TILING(reg, tiling, tmp){
+ WRegionAttachData data;
+
+ /* Don't bother with the status display */
+ if(reg==TILING_STDISP_OF(tiling))
+ continue;
+
+ /* Don't bother with regions containing no client windows. */
+ if(!region_rescue_needed(reg))
+ continue;
+
+ data.type=REGION_ATTACH_REPARENT;
+ data.u.reg=reg;
+
+ param.geom_set=TRUE;
+ param.geom=REGION_GEOM(reg);
+
+ reg2=group_do_attach(grp, ¶m, &data);
+
+ if(reg2==NULL)
+ warn(TR("Unable to move a region from tiling to group."));
+ }
+
+ tiling->batchop=FALSE;
+
+ region_dispose((WRegion*)tiling);
+
+ return TRUE;
+}
+
+
+/*}}}*/
+