/*
* 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
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
+ * See the included file LICENSE for details.
*/
#include <limits.h>
/*{{{ 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;
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. */
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);
}
}
-bool mplex_may_destroy(WMPlex *mplex)
-{
- if(mplex->mgd!=NULL){
- warn(TR("Refusing to destroy - not empty."));
- return FALSE;
- }
-
- return TRUE;
-}
-
-
/*}}}*/
/*EXTL_DOC
- * Returns the \var{n}:th object managed by \var{mplex} on the
- * \var{l}:th layer.
+ * Returns the \var{n}:th object on the mutually exclusive
+ * list of \var{mplex}.
*/
EXTL_SAFE
EXTL_EXPORT_MEMBER
/*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
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);
/*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
/*EXTL_DOC
- * Move \var{r} ''right'' within objects managed by \var{mplex} on list 1.
+ * Move \var{r} ``right'' within objects managed by \var{mplex} on list 1.
*/
EXTL_EXPORT_MEMBER
void mplex_inc_index(WMPlex *mplex, WRegion *r)
/*EXTL_DOC
- * Move \var{r} ''right'' within objects managed by \var{mplex} on list 1.
+ * Move \var{r} ``left'' within objects managed by \var{mplex} on list 1.
*/
EXTL_EXPORT_MEMBER
void mplex_dec_index(WMPlex *mplex, WRegion *r)
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;
/*{{{ Focus */
-static WRegion *mplex_do_to_focus(WMPlex *mplex, WStacking *to_try)
+typedef struct{
+ WMPlex *mplex;
+ WStacking *to_try;
+ WStacking *group_st;
+ PtrList **hidelist;
+ bool try_hard;
+} FiltData;
+
+
+static WRegion *manager_within(WMPlex *mplex, WStacking *st)
{
- WStacking *stacking=mplex_get_stacking(mplex);
- WStacking *st=NULL;
-
- if(stacking==NULL)
- return NULL;
+ return region_managed_within((WRegion*)mplex, st->reg);
+}
- 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, NULL);
+static WStacking *stacking_within(WMPlex *mplex, WStacking *st)
+{
+ WRegion *reg=manager_within(mplex, st);
- if(st!=NULL)
- return st->reg;
- else if(mplex->mx_current!=NULL)
- return mplex->mx_current->st->reg;
- else
- return NULL;
+ return (reg==NULL
+ ? NULL
+ : (reg==st->reg
+ ? st
+ : ioncore_find_stacking(reg)));
}
-WRegion *mplex_to_focus(WMPlex *mplex)
+/* Mutually exclusive regions can't be pseudomodal */
+#define IS_PSEUDOMODAL(ST) ((ST)->lnode==NULL && (ST)->pseudomodal)
+
+
+static bool mapped_pseudomodal_include_filt(WStacking *st, void *data_)
{
- WRegion *reg=REGION_ACTIVE_SUB(mplex);
- WStacking *to_try=NULL;
+ FiltData *data=(FiltData*)data_;
+ WStacking *stw;
- if(reg!=NULL)
- to_try=ioncore_find_stacking(reg);
+ if(st->reg==NULL || !REGION_IS_MAPPED(st->reg))
+ return FALSE;
+
+ if(!data->hidelist
+ || (data->to_try==NULL && data->group_st==NULL)
+ || st->level<STACKING_LEVEL_MODAL1){
+ return TRUE;
+ }
+
+ /* Ok, modal node in the way. Let's see if it is pseudomodal
+ * and can be hidden.
+ */
+
+ stw=stacking_within(data->mplex, st);
+
+ /* This should not happen */
+ if(stw==NULL || stw->reg==NULL)
+ return FALSE;
+
+ /* The node is within the same group, so it can not be hidden.
+ * Latter case should not happen.
+ */
+ if(stw==data->group_st || stw==data->to_try)
+ return TRUE;
+
+ if(IS_PSEUDOMODAL(stw)){
+ /* Don't insert multiple times. */
+ return !ptrlist_reinsert_first(data->hidelist, stw);
+ }
+
+ return TRUE;
+}
+
- return mplex_do_to_focus(mplex, to_try);
+static bool mgr_pseudomodal_approve_filt(WStacking *st, void *data_)
+{
+ FiltData *data=(FiltData*)data_;
+
+ return (data->group_st==NULL || st==data->group_st ||
+ manager_within(data->mplex, st)==data->group_st->reg);
}
-static WRegion *mplex_do_to_focus_on(WMPlex *mplex, WStacking *node,
- WStacking *to_try)
+WStacking *mplex_find_to_focus(WMPlex *mplex,
+ WStacking *to_try,
+ WStacking *group_st,
+ PtrList **hidelist)
{
+ WStackingFilter *fi=mapped_pseudomodal_include_filt;
+ WStackingFilter *fa=mgr_pseudomodal_approve_filt;
WStacking *stacking=mplex_get_stacking(mplex);
- WStacking *st=NULL;
+ FiltData data;
+ WStacking *st;
if(stacking==NULL)
return NULL;
-
+
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);
+ data.mplex=mplex;
+ data.to_try=to_try;
+ data.group_st=group_st;
+ data.hidelist=hidelist;
- return (st!=NULL ? st->reg : NULL);
+ st=stacking_find_to_focus(stacking, to_try, fi, fa, &data);
+
+ if(st==NULL && hidelist!=NULL)
+ ptrlist_clear(hidelist);
+
+ return st;
}
-static WRegion *mplex_to_focus_on(WMPlex *mplex, WStacking *node,
- WStacking *to_try)
+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)
{
- 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_find_to_focus(mplex, to_try, node, hidelist);
+ if(st!=NULL || to_try!=NULL)
+ return st;
+ if(hidelist!=NULL)
+ ptrlist_clear(hidelist);
/* 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, hidelist);
+
+ if(st==node)
+ return st;
+
+ if(hidelist!=NULL)
+ ptrlist_clear(hidelist);
+
+ return NULL;
+}
+
+
+static WStacking *maybe_focusable(WRegion *reg)
+{
+ if(reg==NULL || !REGION_IS_MAPPED(reg))
+ return NULL;
+
+ return ioncore_find_stacking(reg);
+}
+
+
+static WStacking *has_stacking_within(WMPlex *mplex, WRegion *reg)
+{
+ while(reg!=NULL && REGION_MANAGER(reg)!=(WRegion*)mplex)
+ reg=REGION_MANAGER(reg);
+
+ return maybe_focusable(reg);
+}
+
+
+static WStacking *mplex_to_focus(WMPlex *mplex)
+{
+ WStacking *to_try=NULL;
+ WRegion *reg=NULL;
+ WStacking *st;
+
+ 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=has_stacking_within(mplex, reg);
+ if(to_try!=NULL)
+ break;
+ }
+ }
+
+ st=mplex_do_to_focus(mplex, to_try, NULL);
+
+ return (st!=NULL
+ ? st
+ : (mplex->mx_current!=NULL
+ ? mplex->mx_current->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;
}
}
/* 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);
- }*/
+ }
}
* 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);
+ }
}
}
static bool mplex_refocus(WMPlex *mplex, WStacking *node, bool warp)
{
- WRegion *foc=NULL;
+ WStacking *foc=NULL;
bool ret=TRUE;
if(node!=NULL){
- foc=mplex_to_focus_on(mplex, node, NULL);
+ foc=mplex_do_to_focus_on(mplex, node, NULL, NULL);
ret=(foc!=NULL);
}
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;
}
WStacking *sub, int flags,
WPrepareFocusResult *res)
{
- WRegion *foc;
+ bool ew=(flags®ION_GOTO_ENTERWINDOW);
+ PtrList *hidelist=NULL;
+ PtrList **hidelistp=(ew ? NULL : &hidelist);
+ WStacking *foc;
if(sub==NULL && node==NULL)
return FALSE;
/* Display the node in any case */
- if(node!=NULL && !(flags®ION_GOTO_ENTERWINDOW))
+ if(node!=NULL && !ew)
mplex_do_node_display(mplex, node, TRUE);
if(!region_prepare_focus((WRegion*)mplex, flags, res))
return FALSE;
if(node!=NULL)
- foc=mplex_to_focus_on(mplex, node, sub);
+ foc=mplex_do_to_focus_on(mplex, node, sub, hidelistp);
else
- foc=mplex_do_to_focus(mplex, sub);
+ foc=mplex_do_to_focus(mplex, sub, hidelistp);
if(foc!=NULL){
- res->reg=foc;
+ while(hidelist!=NULL){
+ WStacking *st=(WStacking*)ptrlist_take_first(&hidelist);
+ st->hidden=TRUE;
+ region_unmap(st->reg);
+ }
+
+ if(ioncore_g.autoraise &&
+ !(flags®ION_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;
}
/*EXTL_DOC
* Set the visibility of the region \var{reg} on \var{mplex}
- * as specified with the parameter \var{how} (set/unset/toggle).
+ * as specified with the parameter \var{how}
+ * (one of \codestr{set}, \codestr{unset}, or \codestr{toggle}).
* The resulting state is returned.
*/
EXTL_EXPORT_AS(WMPlex, set_hidden)
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);
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);
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);
}
WRegionNaviData *data)
{
WStacking *st;
+ WRegion *res;
if(rel!=NULL){
st=mplex_find_stacking(mplex, rel);
}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);
}
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);
+ && param->level>=STACKING_LEVEL_MODAL1);
level=(param->flags&MPLEX_ATTACH_LEVEL
? param->level
- : (param->flags&MPLEX_ATTACH_MODAL
- ? STACKING_LEVEL_MODAL1
- : (param->flags&MPLEX_ATTACH_UNNUMBERED
- ? STACKING_LEVEL_NORMAL
- : STACKING_LEVEL_BOTTOM)));
+ : (param->flags&MPLEX_ATTACH_UNNUMBERED
+ ? STACKING_LEVEL_NORMAL
+ : STACKING_LEVEL_BOTTOM));
hidden=(param->flags&MPLEX_ATTACH_HIDDEN
&& (param->flags&MPLEX_ATTACH_UNNUMBERED
hidden=(hidden || (!sw && !(param->flags&MPLEX_ATTACH_UNNUMBERED)));
-
node=create_stacking();
if(node==NULL)
}
node->hidden=TRUE;
- node->szplcy=param->szplcy;
+ node->szplcy=szplcy;
node->level=level;
+ node->pseudomodal=(param->flags&MPLEX_ATTACH_PSEUDOMODAL ? 1 : 0);
if(lnode!=NULL){
llist_link_after(&(mplex->mx_list),
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, ®ION_GEOM(reg))!=RECTANGLE_SAME)
+ region_fitrep(reg, NULL, &fp);
+ }
+
if(!hidden)
mplex_do_node_display(mplex, node, FALSE);
else
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(¶m->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);
}
}
-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;
-
- 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){
- par->flags|=MPLEX_ATTACH_LEVEL;
- par->level=tmp;
+ char *tmpstr;
+ int ok=~mask;
+
+ if(ok&MPLEX_ATTACH_LEVEL){
+ if(extl_table_gets_i(tab, "level", &tmp)){
+ if(tmp>=0){
+ par->flags|=MPLEX_ATTACH_LEVEL;
+ par->level=tmp;
+ }
}
- }
- if(extl_table_is_bool_set(tab, "modal"))
- par->flags|=MPLEX_ATTACH_MODAL;
+ if(extl_table_is_bool_set(tab, "modal"))
+ par->level=maxof(par->level, STACKING_LEVEL_MODAL1);
+ }
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_is_bool_set(tab, "pseudomodal"))
+ par->flags|=MPLEX_ATTACH_PSEUDOMODAL&ok;
if(extl_table_gets_i(tab, "index", &(par->index)))
- par->flags|=MPLEX_ATTACH_INDEX;
-
- if(extl_table_gets_i(tab, "sizepolicy", &tmp)){
- par->flags|=MPLEX_ATTACH_SIZEPOLICY;
- par->szplcy=tmp;
+ par->flags|=MPLEX_ATTACH_INDEX&ok;
+
+ if(ok&MPLEX_ATTACH_SIZEPOLICY){
+ if(extl_table_gets_s(tab, "sizepolicy", &tmpstr)){
+ WSizePolicy tmpp;
+ if(string2sizepolicy(tmpstr, &tmpp)){
+ par->flags|=MPLEX_ATTACH_SIZEPOLICY;
+ par->szplcy=tmpp;
+ }
+ free(tmpstr);
+ }else if(extl_table_gets_i(tab, "sizepolicy", &tmp)){
+ /* Backwards compat. numeric version */
+ 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;
}
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;
}
+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).
* \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{pseudomodal} & (boolean) The attached region is ``pseudomodal''
+ * if the stacking level dictates it to be modal.
+ * This means that the region may be hidden to display
+ * regions with lesser stacking levels. \\
+ * \var{sizepolicy} & (string) Size policy; see Section \ref{sec:sizepolicies}. \\
* \var{geom} & (table) Geometry specification. \\
* \end{tabularx}
*
EXTL_EXPORT_MEMBER
WRegion *mplex_attach_new(WMPlex *mplex, ExtlTab param)
{
- WMPlexAttachParams par;
- WRegionAttachData data;
-
- 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;
+ WMPlexAttachParams par=MPLEXATTACHPARAMS_INIT;
- while((reg=ioncore_tags_take_first())!=NULL)
- mplex_attach_simple(mplex, reg, 0);
+ return mplex_attach_new_(mplex, &par, 0, param);
}
WPHolder *mplex_prepare_manage(WMPlex *mplex, const WClientWin *cwin,
- const WManageParams *param, int redir)
+ const WManageParams *param, int priority)
{
+ int cpriority=MANAGE_PRIORITY_SUB(priority, MANAGE_PRIORITY_NORMAL);
WMPlexAttachParams ap;
WPHolder *ph=NULL;
WMPlexPHolder *mph;
WLListNode *after;
- if(redir==MANAGE_REDIR_STRICT_YES || redir==MANAGE_REDIR_PREFER_YES){
+ /* Check current */ {
WStacking *cur=mplex_current_node(mplex);
if(cur!=NULL){
- ph=region_prepare_manage(cur->reg, cwin, param,
- MANAGE_REDIR_PREFER_YES);
+ ph=region_prepare_manage(cur->reg, cwin, param, cpriority);
if(ph!=NULL)
return ph;
}
if(mplex->mx_current!=NULL && mplex->mx_current->st!=cur){
ph=region_prepare_manage(mplex->mx_current->st->reg,
- cwin, param,
- MANAGE_REDIR_PREFER_YES);
+ cwin, param, cpriority);
if(ph!=NULL)
return ph;
}
}
- if(redir==MANAGE_REDIR_STRICT_YES)
+ if(!MANAGE_PRIORITY_OK(priority, MANAGE_PRIORITY_NORMAL))
return NULL;
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);
}
-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);
}
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)
mplex_remanage_stdisp(mplex);
}
+ if(oldstdisp!=NULL && oldstdisp!=reg)
+ mainloop_defer_destroy((Obj*)oldstdisp);
+
return TRUE;
}
*
* \begin{tabularx}{\linewidth}{lX}
* \tabhead{Field & Description}
- * \var{pos} & The corner of the screen to place the status display
- * in. One of \code{tl}, \code{tr}, \var{bl} or \var{br}. \\
- * \var{action} & If this field is set to \code{keep}, \var{corner}
- * and \var{orientation} are changed for the existing
- * status display. If this field is set to \var{remove},
+ * \var{pos} & (string) The corner of the screen to place the status
+ * display in: one of \codestr{tl}, \codestr{tr}, \codestr{bl}
+ * or \codestr{br}. \\
+ * \var{fullsize} & (boolean) Waste all available space. \\
+ * \var{action} & (string) If this field is set to \codestr{keep},
+ * \var{pos} and \var{fullsize} are changed for the existing
+ * status display. If this field is set to \codestr{remove},
* the existing status display is removed. If this
- * field is not set or is set to \code{replace}, a
+ * field is not set or is set to \codestr{replace}, a
* new status display is created and the old, if any,
* removed. \\
* \end{tabularx}
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);
+ extl_table_sets_s(st, "sizepolicy",
+ sizepolicy2string(node->szplcy));
extl_table_sets_i(st, "level", node->level);
g=extl_table_from_rectangle(®ION_GEOM(node->reg));
extl_table_sets_t(st, "geom", g);
extl_unref_table(g);
if(STACKING_IS_HIDDEN(node))
extl_table_sets_b(st, "hidden", TRUE);
+ if(STACKING_IS_PSEUDOMODAL(node))
+ extl_table_sets_b(st, "pseudomodal", TRUE);
if(unnumbered)
extl_table_sets_b(st, "unnumbered", TRUE);
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){
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;
{(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},