]> git.decadent.org.uk Git - ion3.git/blobdiff - ioncore/mplex.c
Update cfg_kludge_flash for Flash 10
[ion3.git] / ioncore / mplex.c
index a9ea894f6eaa696d8677957866221509d98aa244..5f0a87d3a5a8bd2cfe6786c42bd2ca32b977758c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * ion/ioncore/mplex.c
  *
- * Copyright (c) Tuomo Valkonen 1999-2007
+ * Copyright (c) Tuomo Valkonen 1999-2009
  *
  * See the included file LICENSE for details.
  */
 #include "saveload.h"
 #include "xwindow.h"
 #include "mplexpholder.h"
+#include "grouppholder.h"
 #include "llist.h"
 #include "names.h"
 #include "sizepolicy.h"
 #include "stacking.h"
 #include "group.h"
 #include "navi.h"
-#include "groupedpholder.h"
 
 
 #define SUBS_MAY_BE_MAPPED(MPLEX) \
@@ -98,7 +98,7 @@ bool mplex_do_init(WMPlex *mplex, WWindow *parent,
     
     mplex->mx_list=NULL;
     mplex->mx_current=NULL;
-    mplex->mx_phs=NULL;
+    mplex->misc_phs=NULL;
     mplex->mx_count=0;
     
     mplex->mgd=NULL;
@@ -147,8 +147,8 @@ void mplex_deinit(WMPlex *mplex)
     assert(mplex->mgd==NULL);
     assert(mplex->mx_list==NULL);
 
-    while(mplex->mx_phs!=NULL){
-        assert(mplexpholder_move(mplex->mx_phs, NULL, NULL, NULL));
+    while(mplex->misc_phs!=NULL){
+        assert(mplexpholder_move(mplex->misc_phs, NULL, NULL, NULL));
     }
     
     window_deinit((WWindow*)mplex);
@@ -246,7 +246,8 @@ WRegion *mplex_mx_nth(WMPlex *mplex, uint n)
 /*EXTL_DOC
  * 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
+ * The function is called in protected mode.
+ * This routine returns \code{true} if it reaches the end of list
  * without this happening.
  */
 EXTL_SAFE
@@ -263,7 +264,8 @@ bool mplex_mx_i(WMPlex *mplex, ExtlFn iterfn)
 /*EXTL_DOC
  * 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
+ * The function is called in protected mode.
+ * This routine returns \code{true} if it reaches the end of list
  * without this happening.
  */
 EXTL_SAFE
@@ -432,7 +434,8 @@ bool mplex_fitrep(WMPlex *mplex, WWindow *par, const WFitParams *fp)
     bool wchg=(REGION_GEOM(mplex).w!=fp->g.w);
     bool hchg=(REGION_GEOM(mplex).h!=fp->g.h);
     
-    window_do_fitrep(&(mplex->win), par, &(fp->g));
+    if(!window_fitrep(&(mplex->win), par, fp))
+        return FALSE;
     
     if(wchg || hchg){
         mplex_fit_managed(mplex);
@@ -492,9 +495,10 @@ static void mplex_managed_rqgeom(WMPlex *mplex, WRegion *sub,
     node=mplex_find_stacking(mplex, sub);
     
     assert(node!=NULL);
-
+    
+    fp.mode=0;
     mplex_managed_geom(mplex, &fp.g);
-
+    
     sizepolicy(&node->szplcy, sub, &rq->geom, rq->flags, &fp);
     
     if(geomret!=NULL)
@@ -642,13 +646,6 @@ WStacking *mplex_find_to_focus(WMPlex *mplex,
 }
 
 
-static WStacking *mplex_do_to_focus(WMPlex *mplex, WStacking *to_try,
-                                    PtrList **hidelist)
-{
-    return mplex_find_to_focus(mplex, to_try, NULL, hidelist);
-}
-
-
 static WStacking *mplex_do_to_focus_on(WMPlex *mplex, WStacking *node,
                                        WStacking *to_try, 
                                        PtrList **hidelist, bool *within)
@@ -668,7 +665,13 @@ static WStacking *mplex_do_to_focus_on(WMPlex *mplex, WStacking *node,
         }
     }
     
-    st=mplex_do_to_focus(mplex, node, hidelist);
+    st=mplex_find_to_focus(mplex, node, NULL, hidelist);
+    
+    /* If 'node' points to a group, it isn't actually on the stacking list. 
+     * Give it the focus, if there's nothing "proper" that could be focussed.
+     */
+    if(st==NULL && grp!=NULL && REGION_IS_MAPPED(grp))
+        st=node;
     
     if(st==node && within!=NULL)
         *within=TRUE;
@@ -695,30 +698,33 @@ static WStacking *has_stacking_within(WMPlex *mplex, WRegion *reg)
 }
 
 
+/* 1. Try keep focus in REGION_ACTIVE_SUB.
+ * 2. Choose something else, attempting previous in focus history.
+ */
 static WStacking *mplex_to_focus(WMPlex *mplex)
 {
-    WStacking *to_try=NULL;
+    WStacking *foc=NULL, *fallback=NULL;
     WRegion *reg=NULL;
-    WStacking *st;
     
-    to_try=maybe_focusable(REGION_ACTIVE_SUB(mplex));
+    foc=maybe_focusable(REGION_ACTIVE_SUB(mplex));
     
-    if(to_try==NULL){
-        /* Search focus history */
+    if(foc==NULL){
+        /* Search focus history if no specific attempt set.*/
         for(reg=ioncore_g.focus_current; reg!=NULL; reg=reg->active_next){
-            to_try=has_stacking_within(mplex, reg);
-            if(to_try!=NULL)
+            foc=has_stacking_within(mplex, reg);
+            if(foc!=NULL)
                 break;
         }
     }
     
-    st=mplex_do_to_focus(mplex, to_try, NULL);
-    
-    return (st!=NULL 
-            ? st 
-            : (mplex->mx_current!=NULL
-               ? mplex->mx_current->st
-               : NULL));
+    if(foc!=NULL){
+        /* In the history search case, 'foc' might point to a group,
+         * since we don't properly try to find a stacking within it...
+         */
+        return mplex_do_to_focus_on(mplex, foc, NULL, NULL, NULL);
+    }else{
+        return mplex_find_to_focus(mplex, NULL, NULL, NULL);
+    }
 }
 
 
@@ -727,6 +733,12 @@ void mplex_do_set_focus(WMPlex *mplex, bool warp)
     if(!MPLEX_MGD_UNVIEWABLE(mplex)){
         WStacking *st=mplex_to_focus(mplex);
         
+        if(st==NULL){
+            st=(mplex->mx_current!=NULL
+                ? mplex->mx_current->st
+                : NULL);
+        }
+        
         if(st!=NULL){
             region_do_set_focus(st->reg, warp);
             return;
@@ -737,6 +749,22 @@ void mplex_do_set_focus(WMPlex *mplex, bool warp)
 }
 
 
+static void mplex_refocus(WMPlex *mplex, WStacking *node, bool warp)
+{
+    bool within=FALSE;
+    WStacking *foc=NULL;
+    
+    if(node!=NULL)
+        foc=mplex_do_to_focus_on(mplex, node, NULL, NULL, &within);
+        
+    if(foc==NULL || !within)
+        foc=mplex_to_focus(mplex);
+    
+    if(foc!=NULL)
+        region_maybewarp(foc->reg, warp);
+}
+
+
 /*}}}*/
 
 
@@ -829,24 +857,6 @@ static void mplex_do_node_display(WMPlex *mplex, WStacking *node,
 }
 
 
-static bool mplex_refocus(WMPlex *mplex, WStacking *node, bool warp)
-{
-    WStacking *foc=NULL;
-    bool within=FALSE;
-    
-    if(node!=NULL)
-        foc=mplex_do_to_focus_on(mplex, node, NULL, NULL, &within);
-        
-    if(foc==NULL || !within)
-        foc=mplex_to_focus(mplex);
-    
-    if(foc!=NULL)
-        region_maybewarp(foc->reg, warp);
-    
-    return within;
-}
-
-
 bool mplex_do_prepare_focus(WMPlex *mplex, WStacking *node,
                             WStacking *sub, int flags, 
                             WPrepareFocusResult *res)
@@ -855,7 +865,7 @@ bool mplex_do_prepare_focus(WMPlex *mplex, WStacking *node,
     PtrList *hidelist=NULL;
     PtrList **hidelistp=(ew ? NULL : &hidelist);
     WStacking *foc;
-    bool within=FALSE;
+    /*bool within=FALSE;*/
     
     if(sub==NULL && node==NULL)
         return FALSE;
@@ -867,7 +877,7 @@ bool mplex_do_prepare_focus(WMPlex *mplex, WStacking *node,
     if(!region_prepare_focus((WRegion*)mplex, flags, res))
         return FALSE;
 
-    foc=mplex_do_to_focus_on(mplex, node, sub, hidelistp, &within);
+    foc=mplex_do_to_focus_on(mplex, node, sub, hidelistp, NULL /*&within*/);
 
     if(foc!=NULL){
         while(hidelist!=NULL){
@@ -886,7 +896,7 @@ bool mplex_do_prepare_focus(WMPlex *mplex, WStacking *node,
         res->reg=foc->reg;
         res->flags=flags;
         
-        return within;
+        return (foc==sub || (sub==NULL && foc==node));
     }else{
         return FALSE;
     }
@@ -1169,7 +1179,6 @@ bool mplex_managed_rqorder(WMPlex *mplex, WRegion *reg, WRegionOrder order)
 static bool mplex_stack(WMPlex *mplex, WStacking *st)
 {
     WStacking *tmp=NULL;
-    Window bottom=None, top=None;
     WStacking **stackingp=mplex_get_stackingp(mplex);
     
     if(stackingp==NULL)
@@ -1232,7 +1241,7 @@ bool mplex_do_attach_final(WMPlex *mplex, WRegion *reg, WMPlexPHolder *ph)
     
     sw=(!hidden && (param->flags&MPLEX_ATTACH_SWITCHTO 
                     || (param->flags&MPLEX_ATTACH_UNNUMBERED
-                        ? modal
+                        ? FALSE
                         : (mplex_current_node(mplex)==NULL))));
     
     hidden=(hidden || (!sw && !(param->flags&MPLEX_ATTACH_UNNUMBERED)));
@@ -1270,14 +1279,19 @@ bool mplex_do_attach_final(WMPlex *mplex, WRegion *reg, WMPlexPHolder *ph)
     node->pseudomodal=(param->flags&MPLEX_ATTACH_PSEUDOMODAL ? 1 : 0);
     
     if(lnode!=NULL){
+        WMPlexPHolder *ph2, *phn, *php;
+        
         llist_link_after(&(mplex->mx_list), 
                          (ph!=NULL ? ph->after : NULL), 
                          lnode);
         mplex->mx_count++;
         
-        /* Move following placeholders after new node */
-        while(ph->next!=NULL)
-            mplexpholder_move(ph->next, mplex, NULL, lnode);
+        
+        /* Move placeholders after new node */
+        for(php=NULL, ph2=ph; ph2!=NULL; php=ph2, ph2=phn){
+            phn=ph2->next;
+            mplexpholder_move(ph2, mplex, php, lnode);
+        }
     }
     
     LINK_ITEM(mplex->mgd, node, mgr_next, mgr_prev);
@@ -1293,6 +1307,7 @@ bool mplex_do_attach_final(WMPlex *mplex, WRegion *reg, WMPlexPHolder *ph)
     if(!(param->flags&MPLEX_ATTACH_WHATEVER)){
         WFitParams fp;
         
+        fp.mode=0;
         mplex_managed_geom(mplex, &(fp.g));
         
         sizepolicy(&node->szplcy, reg, 
@@ -1307,9 +1322,24 @@ bool mplex_do_attach_final(WMPlex *mplex, WRegion *reg, WMPlexPHolder *ph)
         mplex_do_node_display(mplex, node, FALSE);
     else
         region_unmap(reg);
-    
-    if(sw && mcf)
-        mplex_refocus(mplex, node, FALSE);
+        
+    if(mcf){
+        if(sw){
+            mplex_refocus(mplex, node, FALSE);
+        }else if(!hidden && 
+                 (level>=STACKING_LEVEL_MODAL1 || OBJ_IS(reg, WGroup))){
+            /* New modal regions may require focusing, so try to
+             * give focus back to currently active object.
+             * (There seems to be some problem with uncontained
+             * client windows still..)
+             */
+            mplex_refocus(mplex, NULL, FALSE);
+        }else if(!hidden){
+            region_pointer_focus_hack(reg);
+        }
+    }else if(!hidden){
+        region_pointer_focus_hack(reg);
+    }
     
     if(lnode!=NULL)
         mplex_managed_changed(mplex, MPLEX_CHANGE_ADD, sw, reg);
@@ -1318,18 +1348,24 @@ bool mplex_do_attach_final(WMPlex *mplex, WRegion *reg, WMPlexPHolder *ph)
 }
 
 
+static void mplex_attach_fp(WMPlex *mplex, const WMPlexAttachParams *param,
+                            WFitParams *fp)
+{
+    if(param->flags&MPLEX_ATTACH_GEOM)
+        fp->g=param->geom;
+    else
+        mplex_managed_geom(mplex, &(fp->g));
+    
+    fp->mode=REGION_FIT_WHATEVER|REGION_FIT_BOUNDS;
+}
+
+
 WRegion *mplex_do_attach_pholder(WMPlex *mplex, WMPlexPHolder *ph,
                                  WRegionAttachData *data)
 {
-    WMPlexAttachParams *param=&(ph->param);
     WFitParams fp;
     
-    if(param->flags&MPLEX_ATTACH_GEOM)
-        fp.g=param->geom;
-    else
-        mplex_managed_geom(mplex, &(fp.g));
-    
-    fp.mode=REGION_FIT_WHATEVER|REGION_FIT_BOUNDS;
+    mplex_attach_fp(mplex, &ph->param, &fp);
     
     return region_attach_helper((WRegion*)mplex, 
                                 (WWindow*)mplex, &fp,
@@ -1577,9 +1613,19 @@ WPHolder *mplex_prepare_manage(WMPlex *mplex, const WClientWin *cwin,
     mph=create_mplexpholder(mplex, NULL, &ap);
     
     if(mph!=NULL){
-        WGroupedPHolder *gph=create_groupedpholder((WPHolder*)mph);
-        if(gph!=NULL)
+        WGroupPHolder *gph;
+        WGroupAttachParams gp=GROUPATTACHPARAMS_INIT;
+        
+        gp.switchto_set=1;
+        gp.switchto=1;
+        gp.bottom=1;
+        
+        gph=create_grouppholder(NULL, NULL, &gp);
+        
+        if(gph!=NULL){
+            gph->recreate_pholder=(WPHolder*)mph;
             return (WPHolder*)gph;
+        }
     }
     
     return (WPHolder*)mph;
@@ -1662,11 +1708,40 @@ void mplex_managed_remove(WMPlex *mplex, WRegion *sub)
 }
 
 
+void mplex_child_removed(WMPlex *mplex, WRegion *sub)
+{
+    if(sub!=NULL && sub==(WRegion*)(mplex->stdispwatch.obj)){
+        watch_reset(&(mplex->stdispwatch));
+        mplex_set_stdisp(mplex, NULL, NULL);
+    }
+}
+
+
+/*}}}*/
+
+
+/*{{{ Rescue */
+
+
 bool mplex_rescue_clientwins(WMPlex *mplex, WRescueInfo *info)
 {
     bool ret1, ret2;
     WMPlexIterTmp tmp;
+    WLListIterTmp ltmp;
+    WLListNode *lnode, *was_current=mplex->mx_current;
+
+     
+    /* First all mx stuff to move them nicely to another mplex (when that 
+     * is the case), switching to the current region in the target if 
+     * allowed by ph_flags_mask region_rescue.
+     */
+    FOR_ALL_NODES_ON_LLIST(lnode, mplex->mx_list, ltmp){
+        int sw=(lnode==was_current ? PHOLDER_ATTACH_SWITCHTO : 0);
+        region_do_rescue_this(lnode->st->reg, info, sw);
+    }
     
+    /* Then the rest (possibly retrying failed mx stuff).
+     */
     mplex_iter_init(&tmp, mplex);
     ret1=region_rescue_some_clientwins((WRegion*)mplex, info,
                                        (WRegionIterator*)mplex_iter,
@@ -1678,40 +1753,11 @@ bool mplex_rescue_clientwins(WMPlex *mplex, WRescueInfo *info)
 }
 
 
-
-void mplex_child_removed(WMPlex *mplex, WRegion *sub)
-{
-    if(sub!=NULL && sub==(WRegion*)(mplex->stdispwatch.obj)){
-        watch_reset(&(mplex->stdispwatch));
-        mplex_set_stdisp(mplex, NULL, NULL);
-    }
-}
-
-
 /*}}}*/
 
 
 /*{{{ Status display support */
 
-#ifndef offsetof
-# define offsetof(T,F) ((size_t)((char*)&((T*)0L)->F-(char*)0L))
-#endif
-
-#define STRUCTOF(T, F, FADDR) \
-        ((T*)((char*)(FADDR)-offsetof(T, F)))
-
-
-static void stdisp_watch_handler(Watch *watch, Obj *obj)
-{
-    /*WMPlex *mplex=STRUCTOF(WMPlex, stdispinfo, 
-     STRUCTOF(WMPlexSTDispInfo, regwatch, watch));
-     WMPlexSTDispInfo *di=&(mplex->stdispinfo);
-     WGenWS *ws=OBJ_CAST(REGION_MANAGER(obj), WGenWS);
-     * 
-     if(ioncore_g.opmode!=IONCORE_OPMODE_DEINIT && ws!=NULL)
-     genws_unmanage_stdisp(ws, TRUE, FALSE);*/
-}
-
 
 bool mplex_set_stdisp(WMPlex *mplex, WRegion *reg, 
                       const WMPlexSTDispInfo *din)
@@ -1742,7 +1788,7 @@ bool mplex_set_stdisp(WMPlex *mplex, WRegion *reg,
                 region_detach_manager(oldstdisp);
         }
     }else{
-        watch_setup(&(mplex->stdispwatch), (Obj*)reg, stdisp_watch_handler);
+        watch_setup(&(mplex->stdispwatch), (Obj*)reg, NULL);
         
         mplex_remanage_stdisp(mplex);
     }
@@ -1836,7 +1882,7 @@ WRegion *mplex_set_stdisp_extl(WMPlex *mplex, ExtlTab t)
         
         data.type=REGION_ATTACH_LOAD;
         data.u.tab=t;
-            
+        
         stdisp=region_attach_helper((WRegion*)mplex, 
                                     (WWindow*)mplex, &fp,
                                     do_attach_stdisp, NULL,
@@ -2079,16 +2125,6 @@ ExtlTab mplex_get_configuration(WMPlex *mplex)
 }
 
 
-static WMPlex *tmp_mplex=NULL;
-static WMPlexAttachParams *tmp_par=NULL;
-
-static WPHolder *pholder_callback()
-{
-    assert(tmp_mplex!=NULL);
-    return (WPHolder*)create_mplexpholder(tmp_mplex, NULL, tmp_par);
-}
-
-
 void mplex_load_contents(WMPlex *mplex, ExtlTab tab)
 {
     ExtlTab substab, subtab;
@@ -2104,27 +2140,26 @@ void mplex_load_contents(WMPlex *mplex, ExtlTab tab)
         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=MPLEXATTACHPARAMS_INIT;
-                WRegionAttachData data;
-                char *tmp=NULL;
+                WFitParams fp;
+                WPHolder *ph;
                 
                 get_params(mplex, subtab, 0, &par);
+                mplex_attach_fp(mplex, &par, &fp);
                 
                 par.flags|=MPLEX_ATTACH_INDEX;
                 par.index=LLIST_INDEX_LAST;
                 
-                tmp_par=&par;
-                tmp_mplex=mplex;
-                
-                data.type=REGION_ATTACH_LOAD;
-                data.u.tab=subtab;
+                ph=(WPHolder*)create_mplexpholder(mplex, NULL, &par);
                 
-                ioncore_set_sm_pholder_callback(pholder_callback);
-    
-                mplex_do_attach(mplex, &par, &data);
-
-                tmp_mplex=NULL;
+                if(ph!=NULL){
+                    region_attach_load_helper((WRegion*)mplex, (WWindow*)mplex, &fp,
+                                              (WRegionDoAttachFn*)mplex_do_attach_final,
+                                              (void*)ph, subtab, &ph);
+                                              
+                    if(ph!=NULL)
+                        destroy_obj((Obj*)ph);
+                }
                 
                 extl_unref_table(subtab);
             }