X-Git-Url: https://git.decadent.org.uk/gitweb/?p=ion3.git;a=blobdiff_plain;f=ioncore%2Fmplex.c;h=5f0a87d3a5a8bd2cfe6786c42bd2ca32b977758c;hp=a9ea894f6eaa696d8677957866221509d98aa244;hb=HEAD;hpb=ffce63bd5090c4076a267e29a754558d2feb88c3 diff --git a/ioncore/mplex.c b/ioncore/mplex.c index a9ea894..5f0a87d 100644 --- a/ioncore/mplex.c +++ b/ioncore/mplex.c @@ -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. */ @@ -33,13 +33,13 @@ #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=∥ - 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); }