]> git.decadent.org.uk Git - ion3.git/blobdiff - mod_tiling/ops.c
Imported Upstream version 20090110
[ion3.git] / mod_tiling / ops.c
index c86a80a94f6bbb2fc69a88b6b034d1d3b83bb0ea..f09d5029287606c85736c02055518abb4408223e 100644 (file)
 /*
  * ion/mod_tiling/ops.c
  *
- * Copyright (c) Tuomo Valkonen 1999-2006
+ * 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 <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(&REGION_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;
 }
 
 
@@ -158,14 +64,13 @@ bool mod_tiling_mkbottom(WRegion *reg)
     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;
     }
@@ -185,6 +90,74 @@ bool mod_tiling_mkbottom(WRegion *reg)
     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, &param, &data);
+        
+        if(reg2==NULL)
+            warn(TR("Unable to move a region from tiling to group."));
+    }
+    
+    tiling->batchop=FALSE;
+    
+    region_dispose((WRegion*)tiling);
+    
+    return TRUE;
+}
+
+
+/*}}}*/
+