]> git.decadent.org.uk Git - ion3.git/blobdiff - ioncore/mplex.c
Merge commit '20070318' into HEAD
[ion3.git] / ioncore / mplex.c
index 158b9ffa42f1b9a74c17b950ef355e28f77de32c..28dc48a1a58fe92a18ba812c3afb35ea92894fc3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * ion/ioncore/mplex.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
@@ -94,8 +94,8 @@ WStacking *mplex_iter_nodes(WMPlexIterTmp *tmp)
 /*{{{ Destroy/create mplex */
 
 
-bool mplex_do_init(WMPlex *mplex, WWindow *parent, Window win,
-                   const WFitParams *fp, bool create)
+bool mplex_do_init(WMPlex *mplex, WWindow *parent, 
+                   const WFitParams *fp, Window win)
 {
     mplex->flags=0;
     
@@ -110,21 +110,13 @@ bool mplex_do_init(WMPlex *mplex, WWindow *parent, Window win,
     mplex->stdispinfo.pos=MPLEX_STDISP_BL;
     mplex->stdispinfo.fullsize=FALSE;
     
-    if(create){
-        if(!window_init((WWindow*)mplex, parent, fp))
-            return FALSE;
-    }else{
-        if(!window_do_init((WWindow*)mplex, parent, win, fp))
-            return FALSE;
-    }
+    if(!window_do_init((WWindow*)mplex, parent, fp, win))
+        return FALSE;
     
     mplex->win.region.flags|=REGION_BINDINGS_ARE_GRABBED;
     
     window_select_input(&(mplex->win), IONCORE_EVENTMASK_CWINMGR);
     
-    region_add_bindmap((WRegion*)mplex, ioncore_mplex_bindmap);
-    region_add_bindmap((WRegion*)mplex, ioncore_mplex_toplevel_bindmap);
-    
     region_register((WRegion*)mplex);
     
     /* Call this to set MPLEX_MANAGED_UNVIEWABLE if necessary. */
@@ -136,7 +128,7 @@ bool mplex_do_init(WMPlex *mplex, WWindow *parent, Window win,
 
 bool mplex_init(WMPlex *mplex, WWindow *parent, const WFitParams *fp)
 {
-    return mplex_do_init(mplex, parent, None, fp, TRUE);
+    return mplex_do_init(mplex, parent, fp, None);
 }
 
 
@@ -166,17 +158,6 @@ void mplex_deinit(WMPlex *mplex)
 }
 
 
-bool mplex_may_destroy(WMPlex *mplex)
-{
-    if(mplex->mgd!=NULL){
-        warn(TR("Refusing to destroy - not empty."));
-        return FALSE;
-    }
-    
-    return TRUE;
-}
-
-
 /*}}}*/
 
 
@@ -266,40 +247,45 @@ WRegion *mplex_mx_nth(WMPlex *mplex, uint n)
 
 
 /*EXTL_DOC
- * Returns a list of regions on the numbered/mutually exclusive list of 
- * \var{mplex}.
+ * Iterate over numbered/mutually exclusive region list of \var{mplex} 
+ * until \var{iterfn} returns \code{false}.
+ * The function itself returns \code{true} if it reaches the end of list
+ * without this happening.
  */
 EXTL_SAFE
 EXTL_EXPORT_MEMBER
-ExtlTab mplex_mx_list(WMPlex *mplex)
+bool mplex_mx_i(WMPlex *mplex, ExtlFn iterfn)
 {
     WLListIterTmp tmp;
     llist_iter_init(&tmp, mplex->mx_list);
     
-    return extl_obj_iterable_to_table((ObjIterator*)llist_iter_regions, &tmp);
+    return extl_iter_objlist_(iterfn, (ObjIterator*)llist_iter_regions, &tmp);
 }
 
 
 /*EXTL_DOC
- * Returns a list of all regions managed by \var{mplex}.
+ * Iterate over managed regions of \var{mplex} until \var{iterfn} returns
+ * \code{false}.
+ * The function itself returns \code{true} if it reaches the end of list
+ * without this happening.
  */
 EXTL_SAFE
 EXTL_EXPORT_MEMBER
-ExtlTab mplex_managed_list(WMPlex *mplex)
+bool mplex_managed_i(WMPlex *mplex, ExtlFn iterfn)
 {
     WMPlexIterTmp tmp;
     mplex_iter_init(&tmp, mplex);
     
-    return extl_obj_iterable_to_table((ObjIterator*)mplex_iter, &tmp);
+    return extl_iter_objlist_(iterfn, (ObjIterator*)mplex_iter, &tmp);
 }
 
 
 /*EXTL_DOC
- * Set index of \var{reg} within the multiplexer to \var{index} within 
- * the mutually exclusive list. Special values for \var{index} are:
+ * Set index of \var{reg} to \var{index} within the mutually exclusive 
+ * list of \var{mplex}. Special values for \var{index} are:
  * \begin{tabularx}{\linewidth}{lX}
- *   $-1$ & After \fnref{WMPlex.mx_current}. \\
- *   $-2$ & Last. \\
+ *   $-1$ & Last. \\
+ *   $-2$ & After \fnref{WMPlex.mx_current}. \\
  * \end{tabularx}
  */
 EXTL_EXPORT_MEMBER
@@ -330,8 +316,6 @@ void mplex_set_index(WMPlex *mplex, WRegion *reg, int index)
         llist_unlink(&(mplex->mx_list), lnode);
     }
     
-    /* TODO: Support remove? */
-    
     after=llist_index_to_after(mplex->mx_list, mplex->mx_current, index);
     llist_link_after(&(mplex->mx_list), after, lnode);
     mplex_managed_changed(mplex, MPLEX_CHANGE_REORDER, FALSE, reg);
@@ -339,9 +323,9 @@ void mplex_set_index(WMPlex *mplex, WRegion *reg, int index)
 
 
 /*EXTL_DOC
- * Get index of \var{reg} within the multiplexer on list 1. The first region 
- * managed by \var{mplex} has index zero. If \var{reg} is not managed by 
- * \var{mplex}, -1 is returned.
+ * Get index of \var{reg} on the mutually exclusive list of \var{mplex}.
+ * The indices begin from zero.. If \var{reg} is not on the list,
+ * -1 is returned.
  */
 EXTL_SAFE
 EXTL_EXPORT_MEMBER
@@ -514,7 +498,7 @@ static void mplex_managed_rqgeom(WMPlex *mplex, WRegion *sub,
 
     mplex_managed_geom(mplex, &fp.g);
 
-    sizepolicy(&node->szplcy, sub, &rq->geom, &rq->flags, &fp);
+    sizepolicy(&node->szplcy, sub, &rq->geom, rq->flags, &fp);
     
     if(geomret!=NULL)
         *geomret=fp.g;
@@ -530,7 +514,7 @@ static void mplex_managed_rqgeom(WMPlex *mplex, WRegion *sub,
 /*{{{ Focus  */
 
 
-static WRegion *mplex_do_to_focus(WMPlex *mplex, WStacking *to_try)
+static WStacking *mplex_do_to_focus(WMPlex *mplex, WStacking *to_try)
 {
     WStacking *stacking=mplex_get_stacking(mplex);
     WStacking *st=NULL;
@@ -544,28 +528,54 @@ static WRegion *mplex_do_to_focus(WMPlex *mplex, WStacking *to_try)
     st=stacking_find_to_focus_mapped(stacking, to_try, NULL);
     
     if(st!=NULL)
-        return st->reg;
+        return st;
     else if(mplex->mx_current!=NULL)
-        return mplex->mx_current->st->reg;
+        return mplex->mx_current->st;
     else
         return NULL;
 }
 
 
-WRegion *mplex_to_focus(WMPlex *mplex)
+static WStacking *maybe_focusable(WRegion *reg)
 {
-    WRegion *reg=REGION_ACTIVE_SUB(mplex);
-    WStacking *to_try=NULL;
+    if(reg==NULL || !REGION_IS_MAPPED(reg))
+        return NULL;
+
+    return ioncore_find_stacking(reg);
+}
+
+
+static WStacking *stacking_within(WMPlex *mplex, WRegion *reg)
+{
+    while(reg!=NULL && REGION_MANAGER(reg)!=(WRegion*)mplex)
+        reg=REGION_MANAGER(reg);
     
-    if(reg!=NULL)
-        to_try=ioncore_find_stacking(reg);
+    return maybe_focusable(reg);
+}
 
+
+static WStacking *mplex_to_focus(WMPlex *mplex)
+{
+    WStacking *to_try=NULL;
+    WRegion *reg=NULL;
+    
+    to_try=maybe_focusable(REGION_ACTIVE_SUB(mplex));
+    
+    if(to_try==NULL){
+        /* Search focus history */
+        for(reg=ioncore_g.focus_current; reg!=NULL; reg=reg->active_next){
+            to_try=stacking_within(mplex, reg);
+            if(to_try!=NULL)
+                break;
+        }
+    }
+    
     return mplex_do_to_focus(mplex, to_try);
 }
 
 
-static WRegion *mplex_do_to_focus_on(WMPlex *mplex, WStacking *node,
-                                     WStacking *to_try)
+static WStacking *mplex_do_to_focus_on(WMPlex *mplex, WStacking *node,
+                                       WStacking *to_try)
 {
     WStacking *stacking=mplex_get_stacking(mplex);
     WStacking *st=NULL;
@@ -576,42 +586,40 @@ static WRegion *mplex_do_to_focus_on(WMPlex *mplex, WStacking *node,
     if(to_try!=NULL && (to_try->reg==NULL || !REGION_IS_MAPPED(to_try->reg)))
         to_try=NULL;
     
-    st=stacking_find_to_focus_mapped(stacking, to_try, node->reg);
-    
-    return (st!=NULL ? st->reg : NULL);
+    return stacking_find_to_focus_mapped(stacking, to_try, node->reg);
 }
 
 
-static WRegion *mplex_to_focus_on(WMPlex *mplex, WStacking *node,
-                                  WStacking *to_try)
+static WStacking *mplex_to_focus_on(WMPlex *mplex, WStacking *node,
+                                    WStacking *to_try)
 {
-    WRegion *reg;
     WGroup *grp=OBJ_CAST(node->reg, WGroup);
+    WStacking *st;
     
     if(grp!=NULL){
         if(to_try==NULL)
             to_try=grp->current_managed;
-        reg=mplex_do_to_focus_on(mplex, node, to_try);
-        if(reg!=NULL || to_try!=NULL)
-            return reg;
+        st=mplex_do_to_focus_on(mplex, node, to_try);
+        if(st!=NULL || to_try!=NULL)
+            return st;
         /* We don't know whether something is blocking focus here,
          * or if there was nothing to focus (as node->reg itself
          * isn't on the stacking list).
          */
     }
     
-    reg=mplex_do_to_focus(mplex, node);
-    return (reg==node->reg ? reg : NULL);
+    st=mplex_do_to_focus(mplex, node);
+    return (st==node ? st : NULL);
 }
 
 
 void mplex_do_set_focus(WMPlex *mplex, bool warp)
 {
     if(!MPLEX_MGD_UNVIEWABLE(mplex)){
-        WRegion *reg=mplex_to_focus(mplex);
+        WStacking *st=mplex_to_focus(mplex);
         
-        if(reg!=NULL){
-            region_do_set_focus(reg, warp);
+        if(st!=NULL){
+            region_do_set_focus(st->reg, warp);
             return;
         }
     }
@@ -633,25 +641,19 @@ static void mplex_do_remanage_stdisp(WMPlex *mplex, WRegion *sub)
     /* Move stdisp */
     if(sub!=NULL && CAN_MANAGE_STDISP(sub)){
         if(stdisp!=NULL){
-            WRegion *mgrw=region_managed_within((WRegion*)mplex, stdisp);
-            if(mgrw!=sub){
-                WRegion *mgr=REGION_MANAGER(stdisp);
-                if(mgr!=NULL){
-                    if(CAN_MANAGE_STDISP(mgr))
-                        region_unmanage_stdisp(mgr, FALSE, FALSE);
-                    region_detach_manager(stdisp);
-                }
-                
-                region_manage_stdisp(sub, stdisp, 
-                                     &(mplex->stdispinfo));
+            WRegion *omgr=REGION_MANAGER(stdisp);
+            if(omgr!=sub && omgr!=NULL){
+                if(CAN_MANAGE_STDISP(omgr))
+                    region_unmanage_stdisp(omgr, FALSE, FALSE);
+                region_detach_manager(stdisp);
             }
+            
+            region_manage_stdisp(sub, stdisp, 
+                                 &(mplex->stdispinfo));
         }else{
             region_unmanage_stdisp(sub, TRUE, FALSE);
         }
-    }/*else if(stdisp!=NULL){
-        region_detach_manager(stdisp);
-        region_unmap(stdisp);
-    }*/
+    }
 }
 
 
@@ -702,11 +704,13 @@ static void mplex_do_node_display(WMPlex *mplex, WStacking *node,
          * no visible netscape windows.
          */
         {
-            #warning "TODO: less ugly hack"
             WGroup *grp=(WGroup*)OBJ_CAST(sub, WGroupCW);
-            if(grp!=NULL && grp->bottom!=NULL){
-                region_managed_rqorder((WRegion*)grp, grp->bottom->reg, 
-                                       REGION_ORDER_BACK);
+            if(grp!=NULL){
+                WRegion *bottom=group_bottom(grp);
+                if(bottom!=NULL){
+                    region_managed_rqorder((WRegion*)grp, bottom,
+                                           REGION_ORDER_BACK);
+                }
             }
         }
         
@@ -718,7 +722,7 @@ static void mplex_do_node_display(WMPlex *mplex, WStacking *node,
 
 static bool mplex_refocus(WMPlex *mplex, WStacking *node, bool warp)
 {
-    WRegion *foc=NULL;
+    WStacking *foc=NULL;
     bool ret=TRUE;
     
     if(node!=NULL){
@@ -731,8 +735,8 @@ static bool mplex_refocus(WMPlex *mplex, WStacking *node, bool warp)
         foc=mplex_to_focus(mplex);
     }
     
-    if(foc!=NULL /* && !REGION_IS_ACTIVE(foc) */ )
-        region_maybewarp(foc, warp);
+    if(foc!=NULL)
+        region_maybewarp(foc->reg, warp);
     
     return ret;
 }
@@ -742,7 +746,7 @@ bool mplex_do_prepare_focus(WMPlex *mplex, WStacking *node,
                             WStacking *sub, int flags, 
                             WPrepareFocusResult *res)
 {
-    WRegion *foc;
+    WStacking *foc;
     
     if(sub==NULL && node==NULL)
         return FALSE;
@@ -760,13 +764,20 @@ bool mplex_do_prepare_focus(WMPlex *mplex, WStacking *node,
         foc=mplex_do_to_focus(mplex, sub);
 
     if(foc!=NULL){
-        res->reg=foc;
+        if(ioncore_g.autoraise && 
+           !(flags&REGION_GOTO_ENTERWINDOW) &&
+           foc->level>STACKING_LEVEL_BOTTOM){
+            WStacking **stackingp=mplex_get_stackingp(mplex);
+            stacking_restack(stackingp, foc, None, NULL, NULL, FALSE);
+        }
+        
+        res->reg=foc->reg;
         res->flags=flags;
         
         if(sub==NULL)
-            return (foc==node->reg);
+            return (foc==node);
         else
-            return (foc==sub->reg);
+            return (foc==sub);
     }else{
         return FALSE;
     }
@@ -921,11 +932,11 @@ typedef WStacking *NxtFn(WMPlex *mplex, WStacking *st, bool wrap);
 
 
 static WRegion *do_navi(WMPlex *mplex, WStacking *sti, 
-                        NxtFn *fn, WRegionNaviData *data, bool sti_ok)
+                        NxtFn *fn, WRegionNaviData *data, 
+                        bool sti_ok, bool wrap)
 {
     WStacking *st, *stacking;
     uint min_level=0;
-    bool wrap=FALSE;
     
     stacking=mplex_get_stacking(mplex);
     
@@ -943,13 +954,8 @@ static WRegion *do_navi(WMPlex *mplex, WStacking *sti,
             if(OBJ_IS(st->reg, WGroup)){
                 /* WGroup navigation code should respect modal stuff. */
                 WRegion *res=region_navi_cont((WRegion*)mplex, st->reg, data);
-                if(res!=NULL){
-                    if(res!=st->reg){
-                        return res;
-                    }else{
-                        #warning "TODO: What to do?"
-                    }
-                }
+                if(res!=NULL && res!=st->reg)
+                    return res;
             }else{
                 if(st->level>=min_level && !PASSIVE(st))
                     return region_navi_cont((WRegion*)mplex, st->reg, data);
@@ -968,20 +974,22 @@ WRegion *mplex_navi_first(WMPlex *mplex, WRegionNavi nh,
                           WRegionNaviData *data)
 {
     WStacking *lst=mplex->mgd;
-
-    if(lst==NULL)
-        return region_navi_cont((WRegion*)mplex, NULL, data);
+    WRegion *res=NULL;
     
-    if(nh==REGION_NAVI_ANY){
-        /* ? */
-    }
+    if(lst!=NULL){
+        if(nh==REGION_NAVI_ANY){
+            /* ? */
+        }
     
-    if(nh==REGION_NAVI_ANY || nh==REGION_NAVI_END || 
-       nh==REGION_NAVI_BOTTOM || nh==REGION_NAVI_RIGHT){
-        return do_navi(mplex, lst, mplex_prv, data, TRUE);
-    }else{
-        return do_navi(mplex, lst->mgr_prev, mplex_nxt, data, TRUE);
+        if(nh==REGION_NAVI_ANY || nh==REGION_NAVI_END || 
+           nh==REGION_NAVI_BOTTOM || nh==REGION_NAVI_RIGHT){
+            res=do_navi(mplex, lst, mplex_prv, data, TRUE, TRUE);
+        }else{
+            res=do_navi(mplex, lst->mgr_prev, mplex_nxt, data, TRUE, TRUE);
+        }
     }
+    
+    return region_navi_cont((WRegion*)mplex, res, data);
 }
 
     
@@ -989,6 +997,7 @@ WRegion *mplex_navi_next(WMPlex *mplex, WRegion *rel, WRegionNavi nh,
                          WRegionNaviData *data)
 {
     WStacking *st;
+    WRegion *res;
     
     if(rel!=NULL){
         st=mplex_find_stacking(mplex, rel);
@@ -999,17 +1008,19 @@ WRegion *mplex_navi_next(WMPlex *mplex, WRegion *rel, WRegionNavi nh,
     }else{
         return mplex_navi_first(mplex, nh, data);
     }
-        
+    
     if(nh==REGION_NAVI_ANY){
         /* ? */
     }
     
     if(nh==REGION_NAVI_ANY || nh==REGION_NAVI_END || 
        nh==REGION_NAVI_BOTTOM || nh==REGION_NAVI_RIGHT){
-        return do_navi(mplex, st, mplex_nxt, data, FALSE);
+        res=do_navi(mplex, st, mplex_nxt, data, FALSE, FALSE);
     }else{
-        return do_navi(mplex, st, mplex_prv, data, FALSE);
+        res=do_navi(mplex, st, mplex_prv, data, FALSE, FALSE);
     }
+    
+    return region_navi_cont((WRegion*)mplex, res, data);
 }
 
 
@@ -1082,12 +1093,20 @@ bool mplex_do_attach_final(WMPlex *mplex, WRegion *reg, WMPlexPHolder *ph)
     WLListNode *lnode=NULL;
     WMPlexAttachParams *param=&ph->param;
     bool mx_was_empty, sw, modal, mcf, hidden;
+    WSizePolicy szplcy;
     uint level;
     
     mcf=region_may_control_focus((WRegion*)mplex);
     
     mx_was_empty=(mplex->mx_list==NULL);
     
+    szplcy=((param->flags&MPLEX_ATTACH_SIZEPOLICY &&
+             param->szplcy!=SIZEPOLICY_DEFAULT)
+            ? param->szplcy
+            : (param->flags&MPLEX_ATTACH_UNNUMBERED
+               ? SIZEPOLICY_FULL_BOUNDS
+               : SIZEPOLICY_FULL_EXACT));
+
     modal=(param->flags&MPLEX_ATTACH_LEVEL
            ? param->level>=STACKING_LEVEL_MODAL1
            : param->flags&MPLEX_ATTACH_MODAL);
@@ -1111,7 +1130,6 @@ bool mplex_do_attach_final(WMPlex *mplex, WRegion *reg, WMPlexPHolder *ph)
     
     hidden=(hidden || (!sw && !(param->flags&MPLEX_ATTACH_UNNUMBERED)));
     
-    
     node=create_stacking();
     
     if(node==NULL)
@@ -1140,7 +1158,7 @@ bool mplex_do_attach_final(WMPlex *mplex, WRegion *reg, WMPlexPHolder *ph)
     }
 
     node->hidden=TRUE;
-    node->szplcy=param->szplcy;
+    node->szplcy=szplcy;
     node->level=level;
     
     if(lnode!=NULL){
@@ -1161,6 +1179,19 @@ bool mplex_do_attach_final(WMPlex *mplex, WRegion *reg, WMPlexPHolder *ph)
     
     region_set_manager(reg, (WRegion*)mplex);
     
+    if(!(param->flags&MPLEX_ATTACH_WHATEVER)){
+        WFitParams fp;
+        
+        mplex_managed_geom(mplex, &(fp.g));
+        
+        sizepolicy(&node->szplcy, reg, 
+                   (param->flags&MPLEX_ATTACH_GEOM ? &(param->geom) : NULL),
+                   0, &fp);
+        
+        if(rectangle_compare(&fp.g, &REGION_GEOM(reg))!=RECTANGLE_SAME)
+            region_fitrep(reg, NULL, &fp);
+    }
+    
     if(!hidden)
         mplex_do_node_display(mplex, node, FALSE);
     else
@@ -1180,37 +1211,19 @@ WRegion *mplex_do_attach_pholder(WMPlex *mplex, WMPlexPHolder *ph,
                                  WRegionAttachData *data)
 {
     WMPlexAttachParams *param=&(ph->param);
-    WSizePolicy szplcy=param->szplcy;
     WFitParams fp;
-    WRegion *reg;
-    
-    param->szplcy=(param->flags&MPLEX_ATTACH_SIZEPOLICY &&
-                   param->szplcy!=SIZEPOLICY_DEFAULT
-                   ? param->szplcy
-                   : (param->flags&MPLEX_ATTACH_UNNUMBERED
-                      ? SIZEPOLICY_FULL_BOUNDS
-                      : SIZEPOLICY_FULL_EXACT));
-    
-    mplex_managed_geom(mplex, &(fp.g));
-    
-    sizepolicy(&param->szplcy, NULL, 
-               (param->flags&MPLEX_ATTACH_GEOM 
-                ? &(param->geom)
-                : NULL),
-               0, &fp);
     
-    if(param->flags&MPLEX_ATTACH_WHATEVER)
-        fp.mode|=REGION_FIT_WHATEVER;
-    
-    reg=region_attach_helper((WRegion*)mplex, 
-                             (WWindow*)mplex, &fp,
-                             (WRegionDoAttachFn*)mplex_do_attach_final,
-                             (void*)ph, data);
+    if(param->flags&MPLEX_ATTACH_GEOM)
+        fp.g=param->geom;
+    else
+        mplex_managed_geom(mplex, &(fp.g));
     
-    /* restore */
-    ph->param.szplcy=szplcy;
+    fp.mode=REGION_FIT_WHATEVER|REGION_FIT_BOUNDS;
     
-    return reg;
+    return region_attach_helper((WRegion*)mplex, 
+                                (WWindow*)mplex, &fp,
+                                (WRegionDoAttachFn*)mplex_do_attach_final,
+                                (void*)ph, data);
 }
 
 
@@ -1265,51 +1278,44 @@ WRegion *mplex_attach_simple(WMPlex *mplex, WRegion *reg, int flags)
 }
 
 
-static void get_params(WMPlex *mplex, ExtlTab tab, WMPlexAttachParams *par)
+static void get_params(WMPlex *mplex, ExtlTab tab, int mask,
+                       WMPlexAttachParams *par)
 {
     int layer=1;
     int tmp;
+    int ok=~mask;
     
-    par->flags=0;
-    
-    if(extl_table_gets_i(tab, "layer", &tmp)){
-        /* backwards compatibility */
-        if(tmp==2){
-            par->flags|=MPLEX_ATTACH_UNNUMBERED;
-            if(!extl_table_is_bool_set(tab, "passive"))
-                par->flags|=MPLEX_ATTACH_MODAL;
-        }
-    }
-
     if(extl_table_gets_i(tab, "level", &tmp)){
-        if(tmp>=0){
+        if(tmp>=0 && ok&MPLEX_ATTACH_LEVEL){
             par->flags|=MPLEX_ATTACH_LEVEL;
             par->level=tmp;
         }
     }
     
     if(extl_table_is_bool_set(tab, "modal"))
-        par->flags|=MPLEX_ATTACH_MODAL;
+        par->flags|=MPLEX_ATTACH_MODAL&ok;
 
     if(extl_table_is_bool_set(tab, "unnumbered"))
-        par->flags|=MPLEX_ATTACH_UNNUMBERED;
+        par->flags|=MPLEX_ATTACH_UNNUMBERED&ok;
     
     if(extl_table_is_bool_set(tab, "switchto"))
-        par->flags|=MPLEX_ATTACH_SWITCHTO;
+        par->flags|=MPLEX_ATTACH_SWITCHTO&ok;
 
     if(extl_table_is_bool_set(tab, "hidden"))
-        par->flags|=MPLEX_ATTACH_HIDDEN;
+        par->flags|=MPLEX_ATTACH_HIDDEN&ok;
 
     if(extl_table_gets_i(tab, "index", &(par->index)))
-        par->flags|=MPLEX_ATTACH_INDEX;
+        par->flags|=MPLEX_ATTACH_INDEX&ok;
 
     if(extl_table_gets_i(tab, "sizepolicy", &tmp)){
-        par->flags|=MPLEX_ATTACH_SIZEPOLICY;
-        par->szplcy=tmp;
+        if(ok&MPLEX_ATTACH_SIZEPOLICY){
+            par->flags|=MPLEX_ATTACH_SIZEPOLICY;
+            par->szplcy=tmp;
+        }
     }
     
     if(extl_table_gets_rectangle(tab, "geom", &par->geom))
-        par->flags|=MPLEX_ATTACH_GEOM;
+        par->flags|=MPLEX_ATTACH_GEOM&ok;
 }
 
 
@@ -1321,13 +1327,13 @@ static void get_params(WMPlex *mplex, ExtlTab tab, WMPlexAttachParams *par)
 EXTL_EXPORT_MEMBER
 WRegion *mplex_attach(WMPlex *mplex, WRegion *reg, ExtlTab param)
 {
-    WMPlexAttachParams par;
+    WMPlexAttachParams par=MPLEXATTACHPARAMS_INIT;
     WRegionAttachData data;
 
     if(reg==NULL)
         return NULL;
     
-    get_params(mplex, param, &par);
+    get_params(mplex, param, 0, &par);
     
     data.type=REGION_ATTACH_REPARENT;
     data.u.reg=reg;
@@ -1336,6 +1342,20 @@ WRegion *mplex_attach(WMPlex *mplex, WRegion *reg, ExtlTab param)
 }
 
 
+WRegion *mplex_attach_new_(WMPlex *mplex, WMPlexAttachParams *par, 
+                           int mask, ExtlTab param)
+{
+    WRegionAttachData data;
+    
+    get_params(mplex, param, mask, par);
+    
+    data.type=REGION_ATTACH_LOAD;
+    data.u.tab=param;
+    
+    return mplex_do_attach(mplex, par, &data);
+}
+
+
 /*EXTL_DOC
  * Create a new region to be managed by \var{mplex}. At least the following
  * fields in \var{param} are understood (all but \var{type} are optional).
@@ -1354,8 +1374,7 @@ WRegion *mplex_attach(WMPlex *mplex, WRegion *reg, ExtlTab param)
  *  \var{hidden} & (boolean) Attach hidden, if not prevented
  *                  by e.g. the mutually exclusive list being empty.
  *                  This option overrides \var{switchto}. \\
- *  \var{sizepolicy} & (integer) Size policy.
- *                     (TODO: document them somewhere.) \\
+ *  \var{sizepolicy} & (integer) Size policy. \\
  *  \var{geom} & (table) Geometry specification. \\
  * \end{tabularx}
  * 
@@ -1365,28 +1384,9 @@ WRegion *mplex_attach(WMPlex *mplex, WRegion *reg, ExtlTab param)
 EXTL_EXPORT_MEMBER
 WRegion *mplex_attach_new(WMPlex *mplex, ExtlTab param)
 {
-    WMPlexAttachParams par;
-    WRegionAttachData data;
+    WMPlexAttachParams par=MPLEXATTACHPARAMS_INIT;
     
-    get_params(mplex, param, &par);
-    
-    data.type=REGION_ATTACH_LOAD;
-    data.u.tab=param;
-    
-    return mplex_do_attach(mplex, &par, &data);
-}
-
-
-/*EXTL_DOC
- * Attach all tagged regions to \var{mplex}.
- */
-EXTL_EXPORT_MEMBER
-void mplex_attach_tagged(WMPlex *mplex)
-{
-    WRegion *reg;
-    
-    while((reg=ioncore_tags_take_first())!=NULL)
-        mplex_attach_simple(mplex, reg, 0);
+    return mplex_attach_new_(mplex, &par, 0, param);
 }
 
 
@@ -1441,7 +1441,7 @@ WPHolder *mplex_prepare_manage(WMPlex *mplex, const WClientWin *cwin,
     
     ap.flags=((param->switchto ? MPLEX_ATTACH_SWITCHTO : 0)
               |MPLEX_ATTACH_SIZEPOLICY);
-    ap.szplcy=SIZEPOLICY_FULL_BOUNDS;
+    ap.szplcy=SIZEPOLICY_FULL_EXACT;
     
     mph=create_mplexpholder(mplex, NULL, &ap);
     
@@ -1531,17 +1531,17 @@ void mplex_managed_remove(WMPlex *mplex, WRegion *sub)
 }
 
 
-bool mplex_rescue_clientwins(WMPlex *mplex, WPHolder *ph)
+bool mplex_rescue_clientwins(WMPlex *mplex, WRescueInfo *info)
 {
     bool ret1, ret2;
     WMPlexIterTmp tmp;
     
     mplex_iter_init(&tmp, mplex);
-    ret1=region_rescue_some_clientwins((WRegion*)mplex, ph,
+    ret1=region_rescue_some_clientwins((WRegion*)mplex, info,
                                        (WRegionIterator*)mplex_iter,
                                        &tmp);
     
-    ret2=region_rescue_child_clientwins((WRegion*)mplex, ph);
+    ret2=region_rescue_child_clientwins((WRegion*)mplex, info);
     
     return (ret1 && ret2);
 }
@@ -1597,17 +1597,14 @@ bool mplex_set_stdisp(WMPlex *mplex, WRegion *reg,
         
         if(!CAN_MANAGE_STDISP(mgr))
             mgr=NULL;
-        
-        if(oldstdisp!=reg){
-            mainloop_defer_destroy((Obj*)oldstdisp);
-            watch_reset(&(mplex->stdispwatch));
-        }
     }
     
     if(din!=NULL)
         mplex->stdispinfo=*din;
     
     if(reg==NULL){
+        watch_reset(&(mplex->stdispwatch));
+        
         if(mgr!=NULL){
             region_unmanage_stdisp(mgr, TRUE, FALSE);
             if(oldstdisp!=NULL)
@@ -1619,6 +1616,9 @@ bool mplex_set_stdisp(WMPlex *mplex, WRegion *reg,
         mplex_remanage_stdisp(mplex);
     }
     
+    if(oldstdisp!=NULL && oldstdisp!=reg)
+        mainloop_defer_destroy((Obj*)oldstdisp);
+    
     return TRUE;
 }
 
@@ -1889,7 +1889,6 @@ static void save_node(WMPlex *mplex, ExtlTab subs, int *n,
     st=region_get_configuration(node->reg);
     
     if(st!=extl_table_none()){
-        /*"TODO: better switchto saving? */
         if(mplex->mx_current!=NULL && node==mplex->mx_current->st)
             extl_table_sets_b(st, "switchto", TRUE);
         extl_table_sets_i(st, "sizepolicy", node->szplcy);
@@ -1920,7 +1919,7 @@ ExtlTab mplex_get_configuration(WMPlex *mplex)
     tab=region_get_base_configuration((WRegion*)mplex);
     
     subs=extl_create_table();
-    extl_table_sets_t(tab, "subs", subs);
+    extl_table_sets_t(tab, "managed", subs);
     
     /* First the numbered/mutually exclusive nodes */
     FOR_ALL_NODES_ON_LLIST(lnode, mplex->mx_list, ltmp){
@@ -1964,16 +1963,17 @@ void mplex_load_contents(WMPlex *mplex, ExtlTab tab)
         extl_unref_table(subtab);
     }*/
     
-    if(extl_table_gets_t(tab, "subs", &substab)){
+    if(extl_table_gets_t(tab, "managed", &substab) ||
+       extl_table_gets_t(tab, "subs", &substab)){
         n=extl_table_get_n(substab);
         for(i=1; i<=n; i++){
             if(extl_table_geti_t(substab, i, &subtab)){
                 /*mplex_attach_new(mplex, subtab);*/
-                WMPlexAttachParams par;
+                WMPlexAttachParams par=MPLEXATTACHPARAMS_INIT;
                 WRegionAttachData data;
                 char *tmp=NULL;
                 
-                get_params(mplex, subtab, &par);
+                get_params(mplex, subtab, 0, &par);
                 
                 par.flags|=MPLEX_ATTACH_INDEX;
                 par.index=LLIST_INDEX_LAST;
@@ -2059,9 +2059,6 @@ static DynFunTab mplex_dynfuntab[]={
     {(DynFun*)region_get_rescue_pholder_for,
      (DynFun*)mplex_get_rescue_pholder_for},
 
-    {(DynFun*)region_may_destroy,
-     (DynFun*)mplex_may_destroy},
-    
     {(DynFun*)region_navi_first,
      (DynFun*)mplex_navi_first},