static void group_place_stdisp(WGroup *ws, WWindow *parent,
int pos, WRegion *stdisp);
+static void group_remanage_stdisp(WGroup *ws);
/*{{{ Stacking list stuff */
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®ION_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;
}
-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);
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);
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
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){
-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,
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
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);
if(rectangle_compare(&fp.g, ®ION_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)
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){
}
+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)
/*{{{ 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}.
}
-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);
}
extl_unref_table(substab);
}
-
- ws->bottom_last_close=extl_table_is_bool_set(tab, "bottom_last_close");
}
{(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},