]> git.decadent.org.uk Git - ion3.git/blobdiff - ioncore/group.c
[svn-upgrade] Integrating new upstream version, ion3 (20070318)
[ion3.git] / ioncore / group.c
index 538db141f11d9abe6c3b7fd6e785fa9faa659679..61a32358b73031ff4fe40c1d8bbbd8e51e159556 100644 (file)
@@ -46,6 +46,7 @@
 static void group_place_stdisp(WGroup *ws, WWindow *parent,
                                  int pos, WRegion *stdisp);
 
+static void group_remanage_stdisp(WGroup *ws);
 
 
 /*{{{ Stacking list stuff */
@@ -280,19 +281,21 @@ static bool group_managed_prepare_focus(WGroup *ws, WRegion *reg,
         return mplex_do_prepare_focus(mplex, node, st,
                                       flags, res);
     }else{
-        WStacking *stacking;
-        
         if(!region_prepare_focus((WRegion*)ws, flags, res))
             return FALSE;
 
-        stacking=group_get_stacking(ws);
         st=find_to_focus(ws, st, FALSE);
         
-#warning "TODO: raise in some cases (not enter-window)?"
-        
         if(st==NULL)
             return FALSE;
         
+        if(ioncore_g.autoraise && 
+           !(flags&REGION_GOTO_ENTERWINDOW) &&
+           st->level>STACKING_LEVEL_BOTTOM){
+            WStacking **stackingp=group_get_stackingp(ws);
+            stacking_restack(stackingp, st, None, NULL, NULL, FALSE);
+        }
+        
         res->reg=st->reg;
         res->flags=flags;
         
@@ -301,28 +304,12 @@ static bool group_managed_prepare_focus(WGroup *ws, WRegion *reg,
 }
 
 
-static bool group_essentially_empty(WGroup *ws)
-{
-    WGroupIterTmp tmp;
-    WStacking *st;
-    
-    FOR_ALL_NODES_IN_GROUP(ws, st, tmp){
-        if(st!=ws->managed_stdisp)
-            return FALSE;
-    }
-    
-    return TRUE;
-}
-
-
 void group_managed_remove(WGroup *ws, WRegion *reg)
 {
     bool mcf=region_may_control_focus((WRegion*)ws);
-    bool ds=OBJ_IS_BEING_DESTROYED(ws);
     WStacking *st, *next_st=NULL;
     bool was_stdisp=FALSE, was_bottom=FALSE;
-    bool dest=FALSE;
-    bool cur=FALSE;
+    bool was_current=FALSE;
     
     st=group_find_stacking(ws, reg);
 
@@ -339,13 +326,11 @@ void group_managed_remove(WGroup *ws, WRegion *reg)
         if(st==ws->bottom){
             ws->bottom=NULL;
             was_bottom=TRUE;
-            if(ws->bottom_last_close && group_essentially_empty(ws))
-                dest=TRUE;
         }
             
         if(st==ws->current_managed){
-            cur=TRUE;
             ws->current_managed=NULL;
+            was_current=TRUE;
         }
         
         stacking_unassoc(st);
@@ -354,21 +339,15 @@ void group_managed_remove(WGroup *ws, WRegion *reg)
     
     region_unset_manager(reg, (WRegion*)ws);
     
-    if(!dest && !ds){
+    if(!OBJ_IS_BEING_DESTROYED(ws)){
         if(was_bottom && !was_stdisp && ws->managed_stdisp==NULL){
             /* We should probably be managing any stdisp, that 'bottom' 
              * was managing.
              */
-            WMPlex *mplex=OBJ_CAST(REGION_MANAGER(ws), WMPlex);
-            
-            if(mplex!=NULL 
-               && mplex->mx_current!=NULL 
-               && mplex->mx_current->st->reg==(WRegion*)ws){
-                mplex_remanage_stdisp(mplex);
-            }
+            group_remanage_stdisp(ws);
         }
         
-        if(cur){
+        if(was_current){
             /* This may still potentially cause problems when focus
              * change is pending. Perhaps we should use region_await_focus,
              * if it is pointing to our child (and region_may_control_focus 
@@ -381,13 +360,11 @@ void group_managed_remove(WGroup *ws, WRegion *reg)
                 ws->current_managed=stf;
             }
         }
-    }else if(dest && !ds){
-        region_dispose((WRegion*)ws, mcf);
     }
 }
 
 
-static void group_managed_notify(WGroup *ws, WRegion *reg, WRegionNotify how)
+void group_managed_notify(WGroup *ws, WRegion *reg, WRegionNotify how)
 {
     if(how==ioncore_g.notifies.activated || 
        how==ioncore_g.notifies.pseudoactivated){
@@ -464,37 +441,100 @@ void group_deinit(WGroup *ws)
 
 
     
-bool group_rescue_clientwins(WGroup *ws, WPHolder *ph)
+bool group_rescue_clientwins(WGroup *ws, WRescueInfo *info)
 {
     WGroupIterTmp tmp;
     
     group_iter_init_nostdisp(&tmp, ws);
     
-    return region_rescue_some_clientwins((WRegion*)ws, ph,
+    return region_rescue_some_clientwins((WRegion*)ws, info,
                                          (WRegionIterator*)group_iter,
                                          &tmp);
 }
 
 
-bool group_may_destroy(WGroup *ws)
+static bool group_empty_for_bottom_stdisp(WGroup *ws)
+{
+    WGroupIterTmp tmp;
+    WStacking *st;
+    
+    FOR_ALL_NODES_IN_GROUP(ws, st, tmp){
+        if(st!=ws->bottom && st!=ws->managed_stdisp)
+            return FALSE;
+    }
+    
+    return TRUE;
+}
+
+
+static WRegion *group_managed_disposeroot(WGroup *ws, WRegion *reg)
+{
+    if(group_bottom(ws)==reg){
+        if(group_empty_for_bottom_stdisp(ws))
+            return region_disposeroot((WRegion*)ws);
+    }
+    
+    return reg;
+}
+
+
+/*}}}*/
+
+
+/*{{{ Bottom */
+
+
+static void group_do_set_bottom(WGroup *grp, WStacking *st)
 {
-    bool ret=group_essentially_empty(ws);
-    if(!ret)
-        warn(TR("Workspace not empty - refusing to destroy."));
-    return ret;
+    WStacking *was=grp->bottom;
+    
+    grp->bottom=st;
+    
+    if(st!=was){
+        if(st==NULL || HAS_DYN(st->reg, region_manage_stdisp))
+            group_remanage_stdisp(grp);
+        
+    }
 }
 
 
-static bool group_managed_may_destroy(WGroup *ws, WRegion *reg)
+/*EXTL_DOC
+ * Sets the 'bottom' of \var{ws}. The region \var{reg} must already
+ * be managed by \var{ws}, unless \code{nil}.
+ */
+EXTL_EXPORT_MEMBER
+bool group_set_bottom(WGroup *ws, WRegion *reg)
 {
+    WStacking *st=NULL;
+    
+    if(reg!=NULL){
+        st=group_find_stacking(ws, reg);
+        
+        if(st==NULL)
+            return FALSE;
+    }
+        
+    group_do_set_bottom(ws, st);
+    
     return TRUE;
 }
 
 
+/*EXTL_DOC
+ * Returns the 'bottom' of \var{ws}.
+ */
+EXTL_SAFE
+EXTL_EXPORT_MEMBER
+WRegion *group_bottom(WGroup *ws)
+{
+    return (ws->bottom!=NULL ? ws->bottom->reg : NULL);
+}
+
+
 /*}}}*/
 
 
-/*{{{ attach */
+/*{{{ Attach */
 
 
 WStacking *group_do_add_managed(WGroup *ws, WRegion *reg, int level,
@@ -574,6 +614,16 @@ bool group_do_attach_final(WGroup *ws,
     int weak;
     bool sw;
     
+    /* Stacking  */
+    if(param->stack_above!=NULL)
+        stabove=group_find_stacking(ws, param->stack_above);
+
+    level=(stabove!=NULL
+           ? stabove->level
+           : (param->level_set 
+              ? param->level 
+              : STACKING_LEVEL_NORMAL));
+    
     /* Fit */
     szplcy=(param->szplcy_set
             ? param->szplcy
@@ -610,7 +660,7 @@ bool group_do_attach_final(WGroup *ws,
          szplcy==SIZEPOLICY_FREE ||
          szplcy==SIZEPOLICY_FREE_GLUE /* without flags */)){
         /* TODO: use 'weak'? */
-        group_calc_placement(ws, &g);
+        group_calc_placement(ws, level, &g);
     }
 
     fp.g=REGION_GEOM(ws);
@@ -621,16 +671,7 @@ bool group_do_attach_final(WGroup *ws,
     if(rectangle_compare(&fp.g, &REGION_GEOM(reg))!=RECTANGLE_SAME)
         region_fitrep(reg, NULL, &fp);
     
-    /* Stacking & add */
-    if(param->stack_above!=NULL)
-        stabove=group_find_stacking(ws, param->stack_above);
-
-    level=(stabove!=NULL
-           ? stabove->level
-           : (param->level_set 
-              ? param->level 
-              : STACKING_LEVEL_NORMAL));
-
+    /* Add */
     st=group_do_add_managed(ws, reg, level, szplcy);
     
     if(st==NULL)
@@ -639,25 +680,10 @@ bool group_do_attach_final(WGroup *ws,
     if(stabove!=NULL)
         st->above=stabove;
 
-    /* Misc. */
-    if(param->bottom){
-        ws->bottom=st;
-        
-        if(HAS_DYN(reg, region_manage_stdisp) && ws->managed_stdisp!=NULL){
-            WMPlex *mplex=OBJ_CAST(REGION_MANAGER(ws), WMPlex);
-            if(mplex!=NULL){ /* should always hold */
-                WMPlexSTDispInfo di;
-                WRegion *stdisp=NULL;
-                mplex_get_stdisp(mplex, &stdisp, &di);
-                if(stdisp!=NULL){
-                    assert(stdisp==ws->managed_stdisp->reg);
-                    /* WARNING! Calls back to group code (managed_remove). */
-                    region_manage_stdisp(reg, stdisp, &di);
-                }
-            }
-        }
-    }
+    if(param->bottom)
+        group_do_set_bottom(ws, st);
     
+    /* Focus */
     sw=(param->switchto_set ? param->switchto : ioncore_g.switchto_new);
     
     if(sw || st->level>=STACKING_LEVEL_MODAL1){
@@ -895,6 +921,24 @@ void group_manage_stdisp(WGroup *ws, WRegion *stdisp,
 }
 
 
+static void group_remanage_stdisp(WGroup *ws)
+{
+    WMPlex *mplex=OBJ_CAST(REGION_MANAGER(ws), WMPlex);
+    
+    if(mplex!=NULL && 
+       mplex->mx_current!=NULL && 
+       mplex->mx_current->st->reg==(WRegion*)ws){
+        mplex_remanage_stdisp(mplex);
+    }
+}
+
+
+/*}}}*/
+
+
+/*{{{ Geometry requests */
+
+
 void group_managed_rqgeom(WGroup *ws, WRegion *reg,
                           const WRQGeomParams *rq,
                           WRectangle *geomret)
@@ -1148,16 +1192,6 @@ bool group_managed_rqorder(WGroup *grp, WRegion *reg, WRegionOrder order)
 /*{{{ Misc. */
 
 
-/*EXTL_DOC
- * Returns the 'bottom' of \var{ws}.
- */
-EXTL_EXPORT_MEMBER
-WRegion *group_bottom(WGroup *ws)
-{
-    return (ws->bottom!=NULL ? ws->bottom->reg : NULL);
-}
-
-
 /*EXTL_DOC
  * Iterate over managed regions of \var{ws} until \var{iterfn} returns
  * \code{false}.
@@ -1198,14 +1232,31 @@ Window group_xwindow(const WGroup *ws)
 }
 
 
-WRegion *region_group_if_bottom(WRegion *reg)
+/*EXTL_DOC
+ * Returns the group of \var{reg}, if it is managed by one,
+ * and \var{reg} itself otherwise.
+ */
+/*EXTL_EXPORT_MEMBER
+WRegion *region_group_of(WRegion *reg)
+{
+    WRegion *mgr=REGION_MANAGER(reg);
+    
+    return (OBJ_IS(mgr, WGroup) ? mgr : reg);
+}*/
+
+
+/*EXTL_DOC
+ * Returns the group of \var{reg}, if \var{reg} is its bottom,
+ * and \var{reg} itself otherwise.
+ */
+EXTL_EXPORT_MEMBER
+WRegion *region_groupleader_of(WRegion *reg)
 {
     WGroup *grp=REGION_MANAGER_CHK(reg, WGroup);
     
-    if(grp!=NULL && group_bottom(grp)==reg)
-        return (WRegion*)grp;
-    else
-        return reg;
+    return ((grp!=NULL && group_bottom(grp)==reg)
+            ? (WRegion*)grp
+            : reg);
 }
 
 
@@ -1280,8 +1331,6 @@ void group_do_load(WGroup *ws, ExtlTab tab)
         
         extl_unref_table(substab);
     }
-
-    ws->bottom_last_close=extl_table_is_bool_set(tab, "bottom_last_close");
 }
 
 
@@ -1331,11 +1380,8 @@ static DynFunTab group_dynfuntab[]={
     {(DynFun*)region_get_configuration, 
      (DynFun*)group_get_configuration},
 
-    {(DynFun*)region_may_destroy,
-     (DynFun*)group_may_destroy},
-
-    {(DynFun*)region_managed_may_destroy,
-     (DynFun*)group_managed_may_destroy},
+    {(DynFun*)region_managed_disposeroot,
+     (DynFun*)group_managed_disposeroot},
 
     {(DynFun*)region_current,
      (DynFun*)group_current},