]> git.decadent.org.uk Git - ion3.git/blobdiff - mod_tiling/tiling.c
Imported Upstream version 20090110
[ion3.git] / mod_tiling / tiling.c
index 159f001a0a9af20f7980469f19dc9f3fc0ae10f1..48bbb86f506a3976f57258831660bb12a4710544 100644 (file)
@@ -1,12 +1,9 @@
 /*
  * ion/mod_tiling/tiling.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>
@@ -48,10 +45,6 @@ static WTilingIterTmp tiling_iter_default_tmp;
 /*{{{ Some helper routines */
 
 
-#define STDISP_OF(WS) \
-     ((WS)->stdispnode!=NULL ? (WS)->stdispnode->regnode.reg : NULL)
-
-
 static WSplitRegion *get_node_check(WTiling *ws, WRegion *reg)
 {
     WSplitRegion *node;
@@ -266,32 +259,6 @@ Window tiling_xwindow(const WTiling *ws)
 }
 
 
-/*
-WRegion *tiling_rqclose_propagate(WTiling *ws, WRegion *maybe_sub)
-{
-    return (region_rqclose((WRegion*)ws, FALSE) ? (WRegion*)ws : NULL);
-}
-*/
-
-WPHolder *tiling_prepare_manage_transient(WTiling *ws,
-                                          const WClientWin *transient,
-                                          const WManageParams *param,
-                                          int unused)
-{
-    /* Transient manager searches should not cross tilings unless
-     * explicitly floated.
-     */
-    if(extl_table_is_bool_set(transient->proptab, "float")){
-        return region_prepare_manage_transient_default((WRegion*)ws,
-                                                       transient,
-                                                       param,
-                                                       unused);
-    }else{
-         return NULL;
-    }
-}
-    
-
 /*}}}*/
 
 
@@ -465,6 +432,8 @@ void tiling_manage_stdisp(WTiling *ws, WRegion *stdisp,
         tiling_unmanage_stdisp(ws, TRUE, TRUE);
         return;
     }
+
+    stdisp->flags|=REGION_SKIP_FOCUS;
     
     dg=((WSplit*)(ws->stdispnode))->geom;
     
@@ -500,7 +469,7 @@ bool tiling_managed_add_default(WTiling *ws, WRegion *reg)
     Window bottom=None, top=None;
     WFrame *frame;
     
-    if(STDISP_OF(ws)!=reg){
+    if(TILING_STDISP_OF(ws)!=reg){
         if(!ptrlist_insert_last(&(ws->managed_list), reg))
             return FALSE;
     }
@@ -509,8 +478,7 @@ bool tiling_managed_add_default(WTiling *ws, WRegion *reg)
     
     frame=OBJ_CAST(reg, WFrame);
     if(frame!=NULL){
-        WFrameMode mode=frame_mode(frame);
-        if(mode!=FRAME_MODE_TILED && mode!=FRAME_MODE_TILED_ALT)
+        if(framemode_unalt(frame_mode(frame))!=FRAME_MODE_TILED)
             frame_set_mode(frame, FRAME_MODE_TILED);
     }
     
@@ -535,30 +503,25 @@ bool tiling_managed_add(WTiling *ws, WRegion *reg)
 }
 
 
-static WRegion *create_initial_frame(WTiling *ws, WWindow *parent,
-                                     const WFitParams *fp)
+bool tiling_do_attach_initial(WTiling *ws, WRegion *reg)
 {
-    WRegion *reg=ws->create_frame_fn(parent, fp);
-
-    if(reg==NULL)
-        return NULL;
+    assert(ws->split_tree==NULL);
+    
+    ws->split_tree=(WSplit*)create_splitregion(&REGION_GEOM(reg), reg);
+    if(ws->split_tree==NULL)
+        return FALSE;
     
-    ws->split_tree=(WSplit*)create_splitregion(&(fp->g), reg);
-    if(ws->split_tree==NULL){
-        destroy_obj((Obj*)reg);
-        return NULL;
-    }
     ws->split_tree->ws_if_root=ws;
     
     if(!tiling_managed_add(ws, reg)){
-        destroy_obj((Obj*)reg);
         destroy_obj((Obj*)ws->split_tree);
-        return NULL;
+        ws->split_tree=NULL;
+        return FALSE;
     }
-
-    return reg;
+    
+    return TRUE;
 }
-
+                                      
 
 static WRegion *create_frame_tiling(WWindow *parent, const WFitParams *fp)
 {
@@ -575,7 +538,8 @@ bool tiling_init(WTiling *ws, WWindow *parent, const WFitParams *fp,
                          : create_frame_tiling);
     ws->stdispnode=NULL;
     ws->managed_list=NULL;
-
+    ws->batchop=FALSE;
+    
     ws->dummywin=XCreateWindow(ioncore_g.dpy, parent->win,
                                 fp->g.x, fp->g.y, 1, 1, 0,
                                 CopyFromParent, InputOnly,
@@ -589,7 +553,18 @@ bool tiling_init(WTiling *ws, WWindow *parent, const WFitParams *fp,
                     REGION_PLEASE_WARP);
     
     if(ci){
-        if(create_initial_frame(ws, parent, fp)==NULL){
+        WRegionAttachData data;
+        WRegion *res;
+        
+        data.type=REGION_ATTACH_NEW;
+        data.u.n.fn=(WRegionCreateFn*)ws->create_frame_fn;
+        data.u.n.param=NULL;
+    
+        res=region_attach_helper((WRegion*)ws, parent, fp,
+                                 (WRegionDoAttachFn*)tiling_do_attach_initial, 
+                                 NULL, &data);
+
+        if(res==NULL){
             XDestroyWindow(ioncore_g.dpy, ws->dummywin);
             return FALSE;
         }
@@ -648,44 +623,30 @@ void tiling_deinit(WTiling *ws)
 }
 
 
-bool tiling_managed_may_destroy(WTiling *ws, WRegion *reg)
+WRegion *tiling_managed_disposeroot(WTiling *ws, WRegion *reg)
 {
     WTilingIterTmp tmp;
     WRegion *mgd;
-
-    FOR_ALL_MANAGED_BY_TILING(mgd, ws, tmp){
-        if(mgd!=STDISP_OF(ws) && mgd!=reg){
-            return TRUE;
-        }
-    }
     
-    return region_manager_allows_destroying((WRegion*)ws);
-}
-
-
-bool tiling_may_destroy(WTiling *ws, WRegion *reg)
-{
-    WTilingIterTmp tmp;
-    WRegion *mgd;
+    if(ws->batchop)
+        return reg;
     
     FOR_ALL_MANAGED_BY_TILING(mgd, ws, tmp){
-        if(mgd!=STDISP_OF(ws)){
-            warn(TR("Workspace not empty - refusing to destroy."));
-            return FALSE;
-        }
+        if(mgd!=TILING_STDISP_OF(ws) && mgd!=reg)
+            return reg;
     }
     
-    return TRUE;
+    return region_disposeroot((WRegion*)ws);
 }
 
 
-bool tiling_rescue_clientwins(WTiling *ws, WPHolder *ph)
+bool tiling_rescue_clientwins(WTiling *ws, WRescueInfo *info)
 {
     WTilingIterTmp tmp;
     
     ptrlist_iter_init(&tmp, ws->managed_list);
     
-    return region_rescue_some_clientwins((WRegion*)ws, ph,
+    return region_rescue_some_clientwins((WRegion*)ws, info,
                                          (WRegionIterator*)ptrlist_iter, 
                                          &tmp);
 }
@@ -693,13 +654,14 @@ bool tiling_rescue_clientwins(WTiling *ws, WPHolder *ph)
 
 void tiling_do_managed_remove(WTiling *ws, WRegion *reg)
 {
-    if(STDISP_OF(ws)==reg){
+    if(TILING_STDISP_OF(ws)==reg){
         ws->stdispnode->regnode.reg=NULL;
     }else{
         ptrlist_remove(&(ws->managed_list), reg);
     }
 
     region_unset_manager(reg, (WRegion*)ws);
+    splittree_set_node_of(reg, NULL);
 }
 
 
@@ -711,30 +673,50 @@ static bool nostdispfilter(WSplit *node)
 
 void tiling_managed_remove(WTiling *ws, WRegion *reg)
 {
-    bool ds=OBJ_IS_BEING_DESTROYED(ws);
     bool act=REGION_IS_ACTIVE(reg);
     bool mcf=region_may_control_focus((WRegion*)ws);
     WSplitRegion *node=get_node_check(ws, reg);
-    WRegion *other;
+    bool norestore=(OBJ_IS_BEING_DESTROYED(ws) || ws->batchop);
+    WRegion *other=NULL;
 
-    other=tiling_do_navi_next(ws, reg, REGION_NAVI_ANY, TRUE, FALSE);
+    if(!norestore)
+        other=tiling_do_navi_next(ws, reg, REGION_NAVI_ANY, TRUE, FALSE);
     
     tiling_do_managed_remove(ws, reg);
 
     if(node==(WSplitRegion*)(ws->stdispnode))
         ws->stdispnode=NULL;
     
-    if(node==NULL)
-        return;
-    
-    splittree_remove((WSplit*)node, (!ds && other!=NULL));
-    
-    if(!ds){
-        if(other==NULL)
-            region_dispose((WRegion*)ws, mcf);
-        else if(act && mcf)
-            region_warp(other);
+    if(node!=NULL){
+        bool reused=FALSE;
+        
+        if(other==NULL && !norestore){
+            WWindow *par=REGION_PARENT(ws);
+            WFitParams fp;
+            
+            assert(par!=NULL);
+            
+            fp.g=node->split.geom;
+            fp.mode=REGION_FIT_EXACT;
+            
+            other=(ws->create_frame_fn)(par, &fp);
+            
+            if(other!=NULL){
+                node->reg=other;
+                splittree_set_node_of(other, node);
+                tiling_managed_add(ws, other);
+                reused=TRUE;
+            }else{
+                warn(TR("Tiling in useless state."));
+            }
+        }
+        
+        if(!reused)
+            splittree_remove((WSplit*)node, (!norestore && other!=NULL));
     }
+    
+    if(!norestore && other!=NULL && act && mcf)
+        region_warp(other);
 }
 
 
@@ -1010,19 +992,16 @@ static WFrame *tiling_do_split(WTiling *ws, WSplit *node,
         destroy_obj((Obj*)newframe);
         return NULL;
     }
-
-    /* Restack */
-    if(ws->split_tree!=NULL)
-        split_restack(ws->split_tree, ws->dummywin, Above);
     
     return newframe;
 }
 
 
 /*EXTL_DOC
- * Create a new frame on \var{ws} above/below/left of/right of
- * \var{node} as indicated by \var{dirstr}. If \var{dirstr} is 
- * prefixed with ''floating:'' a floating split is created.
+ * Create a new frame on \var{ws} \codestr{above}, \codestr{below}
+ * \codestr{left} of, or \codestr{right} of \var{node} as indicated
+ *  by \var{dirstr}. If \var{dirstr} is  prefixed with 
+ * \codestr{floating:} a floating split is created.
  */
 EXTL_EXPORT_MEMBER
 WFrame *tiling_split(WTiling *ws, WSplit *node, const char *dirstr)
@@ -1048,11 +1027,12 @@ WFrame *tiling_split_top(WTiling *ws, const char *dirstr)
 
 /*EXTL_DOC
  * Split \var{frame} creating a new frame to direction \var{dirstr}
- * (one of ''left'', ''right'', ''top'' or ''bottom'') of \var{frame}.
+ * (one of \codestr{left}, \codestr{right}, \codestr{top} or 
+ * \codestr{bottom}) of \var{frame}.
  * If \var{attach_current} is set, the region currently displayed in
  * \var{frame}, if any, is moved to thenew frame.
- * If \var{dirstr} is prefixed with ''floating:'' a floating split is
- * created.
+ * If \var{dirstr} is prefixed with \codestr{floating:}, a floating
+ * split is created.
  */
 EXTL_EXPORT_MEMBER
 WFrame *tiling_split_at(WTiling *ws, WFrame *frame, const char *dirstr, 
@@ -1087,23 +1067,25 @@ WFrame *tiling_split_at(WTiling *ws, WFrame *frame, const char *dirstr,
 
 
 /*EXTL_DOC
- * Try to relocate regions managed by \var{frame} to another frame
- * and, if possible, destroy the frame.
+ * Try to relocate regions managed by \var{reg} to another frame
+ * and, if possible, destroy it.
  */
 EXTL_EXPORT_MEMBER
-bool tiling_unsplit_at(WTiling *ws, WFrame *frame)
+void tiling_unsplit_at(WTiling *ws, WRegion *reg)
 {
-    if(frame==NULL){
-        warn(TR("Nil frame."));
-        return FALSE;
-    }
+    WPHolder *ph;
     
-    if(REGION_MANAGER(frame)!=(WRegion*)ws){
-        warn(TR("The frame is not managed by the workspace."));
-        return FALSE;
+    if(reg==NULL || REGION_MANAGER(reg)!=(WRegion*)ws)
+        return;
+    
+    ph=region_get_rescue_pholder_for((WRegion*)ws, reg);
+    
+    if(ph!=NULL){
+        region_rescue(reg, ph, REGION_RESCUE_NODEEP|REGION_RESCUE_PHFLAGS_OK);
+        destroy_obj((Obj*)ph);
     }
     
-    return region_rqclose((WRegion*)frame, TRUE);
+    region_defer_rqdispose(reg);
 }
 
 
@@ -1127,7 +1109,8 @@ WRegion *tiling_current(WTiling *ws)
 /*EXTL_DOC
  * Iterate over managed regions of \var{ws} until \var{iterfn} returns
  * \code{false}.
- * The function itself returns \code{true} if it reaches the end of list
+ * The function is called in protected mode.
+ * This routine returns \code{true} if it reaches the end of list
  * without this happening.
  */
 EXTL_SAFE
@@ -1155,7 +1138,8 @@ WSplit *tiling_split_tree(WTiling *ws)
 
 /*EXTL_DOC
  * Return the most previously active region next to \var{reg} in
- * direction \var{dirstr} (left/right/up/down). The region \var{reg}
+ * direction \var{dirstr} (\codestr{left}, \codestr{right}, \codestr{up},
+ * or \codestr{down}). The region \var{reg}
  * must be managed by \var{ws}. If \var{any} is not set, the status display
  * is not considered.
  */
@@ -1176,8 +1160,8 @@ WRegion *tiling_nextto(WTiling *ws, WRegion *reg, const char *dirstr,
 /*EXTL_DOC
  * Return the most previously active region on \var{ws} with no
  * other regions next to it in  direction \var{dirstr} 
- * (left/right/up/down). If \var{any} is not set, the status 
- * display is not considered.
+ * (\codestr{left}, \codestr{right}, \codestr{up}, or \codestr{down}). 
+ * If \var{any} is not set, the status display is not considered.
  */
 EXTL_SAFE
 EXTL_EXPORT_MEMBER
@@ -1353,8 +1337,8 @@ WSplitSplit *tiling_set_floating(WTiling *ws, WSplitSplit *split, int sp)
 
 /*EXTL_DOC
  * Toggle floating of a split's sides at \var{split} as indicated by the 
- * parameter \var{how} (set/unset/toggle). A split of the appropriate is 
- * returned, if there was a change.
+ * parameter \var{how} (\codestr{set}, \codestr{unset}, or \codestr{toggle}).
+ * A split of the appropriate is returned, if there was a change.
  */
 EXTL_EXPORT_AS(WTiling, set_floating)
 WSplitSplit *tiling_set_floating_extl(WTiling *ws, WSplitSplit *split, 
@@ -1368,9 +1352,10 @@ WSplitSplit *tiling_set_floating_extl(WTiling *ws, WSplitSplit *split,
 
 /*EXTL_DOC
  * Toggle floating of the sides of a split containin \var{reg} as indicated 
- * by the parameters \var{how} (set/unset/toggle) and \var{dirstr}
- * (left/right/up/down/any). The new status is returned (and \code{false}
- * also on error).
+ * by the parameters \var{how} (\codestr{set}, \codestr{unset}, or 
+ * \codestr{toggle}) and \var{dirstr} (\codestr{left}, \codestr{right}, 
+ * \codestr{up}, or \codestr{down}). The new status is returned 
+ * (and \code{false} also on error).
  */
 EXTL_EXPORT_AS(WTiling, set_floating_at)
 bool tiling_set_floating_at_extl(WTiling *ws, WRegion *reg, const char *how,
@@ -1716,11 +1701,8 @@ static DynFunTab tiling_dynfuntab[]={
     {(DynFun*)region_get_configuration,
      (DynFun*)tiling_get_configuration},
 
-    {(DynFun*)region_managed_may_destroy,
-     (DynFun*)tiling_managed_may_destroy},
-
-    {(DynFun*)region_may_destroy,
-     (DynFun*)tiling_may_destroy},
+    {(DynFun*)region_managed_disposeroot,
+     (DynFun*)tiling_managed_disposeroot},
 
     {(DynFun*)region_current,
      (DynFun*)tiling_current},
@@ -1752,9 +1734,6 @@ static DynFunTab tiling_dynfuntab[]={
     {(DynFun*)region_xwindow,
      (DynFun*)tiling_xwindow},
     
-    {(DynFun*)region_prepare_manage_transient,
-     (DynFun*)tiling_prepare_manage_transient},
-     
     END_DYNFUNTAB
 };