]> git.decadent.org.uk Git - ion3.git/blobdiff - ioncore/group.c
[svn-upgrade] Integrating new upstream version, ion3 (20071109)
[ion3.git] / ioncore / group.c
index 9c67348fe2a26442a696def5b14523ec2c55bfd7..e39b20241f3e3b45a4e643a92fcd8c2297944b6c 100644 (file)
@@ -45,6 +45,8 @@ static void group_place_stdisp(WGroup *ws, WWindow *parent,
 
 static void group_remanage_stdisp(WGroup *ws);
 
+static void group_do_set_bottom(WGroup *grp, WStacking *st);
+
 
 /*{{{ Stacking list stuff */
 
@@ -232,26 +234,9 @@ static WStacking *find_to_focus(WGroup *ws, WStacking *st, bool group_only)
 }
 
 
-static bool group_refocus_(WGroup *ws, WStacking *st)
-{
-    if(st!=ws->current_managed && st->reg!=NULL){
-        if(region_may_control_focus((WRegion*)ws))
-            region_set_focus(st->reg);
-        else
-            ws->current_managed=st;
-        return TRUE;
-    }
-    
-    return FALSE;
-}
-
-
 static void group_do_set_focus(WGroup *ws, bool warp)
 {
-    WStacking *st=ws->current_managed;
-    
-    if(st==NULL || st->reg==NULL)
-        st=find_to_focus(ws, NULL, TRUE);
+    WStacking *st=find_to_focus(ws, ws->current_managed, FALSE);
     
     if(st!=NULL && st->reg!=NULL)
         region_do_set_focus(st->reg, warp);
@@ -311,51 +296,40 @@ void group_managed_remove(WGroup *ws, WRegion *reg)
     st=group_find_stacking(ws, reg);
 
     if(st!=NULL){
-        next_st=stacking_unstack(REGION_PARENT(ws), st);
-        
-        UNLINK_ITEM(ws->managed_list, st, mgr_next, mgr_prev);
+        if(st==ws->bottom){
+            was_bottom=TRUE;
+            group_do_set_bottom(ws, NULL);
+        }
         
         if(st==ws->managed_stdisp){
             ws->managed_stdisp=NULL;
             was_stdisp=TRUE;
         }
-        
-        if(st==ws->bottom){
-            ws->bottom=NULL;
-            was_bottom=TRUE;
-        }
             
         if(st==ws->current_managed){
             ws->current_managed=NULL;
             was_current=TRUE;
         }
         
+        next_st=stacking_unstack(REGION_PARENT(ws), st);
+        UNLINK_ITEM(ws->managed_list, st, mgr_next, mgr_prev);
         stacking_unassoc(st);
         stacking_free(st);
     }
     
     region_unset_manager(reg, (WRegion*)ws);
     
-    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.
-             */
-            group_remanage_stdisp(ws);
-        }
-        
-        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 
-             * fail if it is pointing somewhere else).
-             */
-            WStacking *stf=find_to_focus(ws, next_st, TRUE);
-            if(stf!=NULL && mcf){
-                region_maybewarp_now(stf->reg, FALSE);
-            }else{
-                ws->current_managed=stf;
-            }
+    if(!OBJ_IS_BEING_DESTROYED(ws) && 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 
+         * fail if it is pointing somewhere else).
+         */
+        WStacking *stf=find_to_focus(ws, next_st, TRUE);
+        if(stf!=NULL && mcf){
+            region_maybewarp_now(stf->reg, FALSE);
+        }else{
+            ws->current_managed=stf;
         }
     }
 }
@@ -450,47 +424,37 @@ bool group_rescue_clientwins(WGroup *ws, WRescueInfo *info)
 }
 
 
-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 */
 
 
+void group_bottom_set(WGroup *grp)
+{
+    CALL_DYN(group_bottom_set, grp, (grp));
+}
+
+
 static void group_do_set_bottom(WGroup *grp, WStacking *st)
 {
     WStacking *was=grp->bottom;
+    WStacking *std=grp->managed_stdisp;
     
     grp->bottom=st;
     
-    if(st!=was){
-        if(st==NULL || HAS_DYN(st->reg, region_manage_stdisp))
+    if(!OBJ_IS_BEING_DESTROYED(grp)){
+        bool noremanage=((was==st) ||
+                         (was==NULL && std==NULL) || 
+                         (st!=NULL && st==std) || 
+                         (st==NULL && was==std));
+        
+        if(!noremanage &&
+           (st==NULL || HAS_DYN(st->reg, region_manage_stdisp))){
             group_remanage_stdisp(grp);
+        }
         
+        group_bottom_set(grp);
     }
 }
 
@@ -599,6 +563,14 @@ static void geom_group_to_parent(WGroup *ws, const WRectangle *g,
 }
 
 
+static int group_must_focus(WGroup *ws, WStacking *st)
+{
+    WStacking *stacking=group_get_stacking(ws);
+    
+    return (stacking!=NULL && stacking_must_focus(stacking, st));
+}
+
+
 bool group_do_attach_final(WGroup *ws, 
                            WRegion *reg,
                            const WGroupAttachParams *param)
@@ -681,15 +653,15 @@ bool group_do_attach_final(WGroup *ws,
         group_do_set_bottom(ws, st);
     
     /* Focus */
-    sw=(param->switchto_set ? param->switchto : ioncore_g.switchto_new);
+    sw=((param->switchto_set ? param->switchto : ioncore_g.switchto_new)
+        ? st==find_to_focus(ws, st, FALSE)
+        : group_must_focus(ws, st));
     
-    if(sw || st->level>=STACKING_LEVEL_MODAL1){
-        WStacking *stf=find_to_focus(ws, st, FALSE);
-        
-        if(stf==st){
-            /* Ok, the new region can be focused */
-            group_refocus_(ws, stf);
-        }
+    if(sw){
+        if(region_may_control_focus((WRegion*)ws))
+            region_set_focus(st->reg);
+        else
+            ws->current_managed=st;
     }
     
     return TRUE;
@@ -727,9 +699,11 @@ WRegion *group_do_attach(WGroup *ws,
 }
 
 
-static void get_params(WGroup *ws, ExtlTab tab, WGroupAttachParams *par)
+void group_get_attach_params(WGroup *ws, ExtlTab tab, 
+                             WGroupAttachParams *par)
 {
     int tmp;
+    bool tmpb;
     char *tmps;
     ExtlTab g;
     
@@ -747,7 +721,7 @@ static void get_params(WGroup *ws, ExtlTab tab, WGroupAttachParams *par)
     
     if(extl_table_gets_i(tab, "level", &tmp)){
         if(tmp>=0){
-            par->level_set=STACKING_LEVEL_NORMAL;
+            par->level_set=1;
             par->level=tmp;
         }
     }
@@ -757,9 +731,11 @@ static void get_params(WGroup *ws, ExtlTab tab, WGroupAttachParams *par)
         par->level_set=1;
     }
     
-    if(extl_table_is_bool_set(tab, "switchto"))
-        par->switchto=1;
-
+    if(extl_table_gets_b(tab, "switchto", &tmpb)){
+        par->switchto=(tmpb!=0);
+        par->switchto_set=1;
+    }
+    
     if(extl_table_gets_i(tab, "sizepolicy", &tmp)){
         par->szplcy_set=1;
         par->szplcy=tmp;
@@ -804,7 +780,7 @@ WRegion *group_attach(WGroup *ws, WRegion *reg, ExtlTab param)
     if(reg==NULL)
         return NULL;
     
-    get_params(ws, param, &par);
+    group_get_attach_params(ws, param, &par);
     
     data.type=REGION_ATTACH_REPARENT;
     data.u.reg=reg;
@@ -825,6 +801,8 @@ WRegion *group_attach(WGroup *ws, WRegion *reg, ExtlTab param)
  *  \var{level} & (integer) Stacking level; default is 1. \\
  *  \var{modal} & (boolean) Make object modal; ignored if level is set. \\
  *  \var{sizepolicy} & (string) Size policy; see Section \ref{sec:sizepolicies}. \\
+ *  \var{bottom} & (boolean) Mark the attached region as the
+ *                 ``bottom'' of \var{ws}. \\
  * \end{tabularx}
  * 
  * In addition parameters to the region to be created are passed in this 
@@ -836,7 +814,7 @@ WRegion *group_attach_new(WGroup *ws, ExtlTab param)
     WGroupAttachParams par=GROUPATTACHPARAMS_INIT;
     WRegionAttachData data;
 
-    get_params(ws, param, &par);
+    group_get_attach_params(ws, param, &par);
     
     data.type=REGION_ATTACH_LOAD;
     data.u.tab=param;
@@ -854,29 +832,34 @@ WRegion *group_attach_new(WGroup *ws, ExtlTab param)
 static int stdisp_szplcy(const WMPlexSTDispInfo *di, WRegion *stdisp)
 {
     int pos=di->pos;
+    int policy=0, gravity=0;
     
     if(di->fullsize){
         if(region_orientation(stdisp)==REGION_ORIENTATION_VERTICAL){
             if(pos==MPLEX_STDISP_TL || pos==MPLEX_STDISP_BL)
-                return SIZEPOLICY_STRETCH_LEFT;
+                policy=SIZEPOLICY_STRETCH_LEFT;
             else
-                return SIZEPOLICY_STRETCH_RIGHT;
+                policy=SIZEPOLICY_STRETCH_RIGHT;
         }else{
             if(pos==MPLEX_STDISP_TL || pos==MPLEX_STDISP_TR)
-                return SIZEPOLICY_STRETCH_TOP;
+                policy=SIZEPOLICY_STRETCH_TOP;
             else
-                return SIZEPOLICY_STRETCH_BOTTOM;
+                policy=SIZEPOLICY_STRETCH_BOTTOM;
         }
     }else{
-        if(pos==MPLEX_STDISP_TL)
-            return SIZEPOLICY_GRAVITY_NORTHWEST;
-        else if(pos==MPLEX_STDISP_BL)
-            return SIZEPOLICY_GRAVITY_SOUTHWEST;
-        else if(pos==MPLEX_STDISP_TR)
-            return SIZEPOLICY_GRAVITY_NORTHEAST;
-        else /*if(pos=MPLEX_STDISP_BR)*/
-            return SIZEPOLICY_GRAVITY_SOUTHEAST;
+        policy=SIZEPOLICY_GRAVITY;
     }
+    
+    if(pos==MPLEX_STDISP_TL)
+        gravity=SIZEPOLICY_VERT_TOP|SIZEPOLICY_HORIZ_LEFT;
+    else if(pos==MPLEX_STDISP_BL)
+        gravity=SIZEPOLICY_VERT_BOTTOM|SIZEPOLICY_HORIZ_LEFT;
+    else if(pos==MPLEX_STDISP_TR)
+        gravity=SIZEPOLICY_VERT_TOP|SIZEPOLICY_HORIZ_RIGHT;
+    else /*if(pos=MPLEX_STDISP_BR)*/
+        gravity=SIZEPOLICY_VERT_BOTTOM|SIZEPOLICY_HORIZ_RIGHT;
+    
+    return (policy|gravity);
 }
 
 
@@ -910,7 +893,9 @@ void group_manage_stdisp(WGroup *ws, WRegion *stdisp,
                                                 STACKING_LEVEL_ON_TOP, 
                                                 szplcy);
     }
-
+    
+    stdisp->flags|=REGION_SKIP_FOCUS;
+    
     fp.g=REGION_GEOM(ws);
     sizepolicy(&ws->managed_stdisp->szplcy, stdisp, NULL, 0, &fp);
 
@@ -1372,9 +1357,6 @@ static DynFunTab group_dynfuntab[]={
     {(DynFun*)region_get_configuration, 
      (DynFun*)group_get_configuration},
 
-    {(DynFun*)region_managed_disposeroot,
-     (DynFun*)group_managed_disposeroot},
-
     {(DynFun*)region_current,
      (DynFun*)group_current},