/*
* ion/mod_tiling/tiling.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
/*{{{ Some helper routines */
-#define STDISP_OF(WS) \
- ((WS)->stdispnode!=NULL ? (WS)->stdispnode->regnode.reg : NULL)
-
-
static WSplitRegion *get_node_check(WTiling *ws, WRegion *reg)
{
WSplitRegion *node;
}
-/*
-WRegion *tiling_rqclose_propagate(WTiling *ws, WRegion *maybe_sub)
-{
- return (region_rqclose((WRegion*)ws, FALSE) ? (WRegion*)ws : NULL);
-}
-*/
-
WPHolder *tiling_prepare_manage_transient(WTiling *ws,
const WClientWin *transient,
const WManageParams *param,
Window bottom=None, top=None;
WFrame *frame;
- if(STDISP_OF(ws)!=reg){
+ if(TILING_STDISP_OF(ws)!=reg){
if(!ptrlist_insert_last(&(ws->managed_list), reg))
return FALSE;
}
}
-static WRegion *create_initial_frame(WTiling *ws, WWindow *parent,
- const WFitParams *fp)
+bool tiling_do_attach_initial(WTiling *ws, WRegion *reg)
{
- WRegion *reg=ws->create_frame_fn(parent, fp);
-
- if(reg==NULL)
- return NULL;
+ assert(ws->split_tree==NULL);
+
+ ws->split_tree=(WSplit*)create_splitregion(®ION_GEOM(reg), reg);
+ if(ws->split_tree==NULL)
+ return FALSE;
- ws->split_tree=(WSplit*)create_splitregion(&(fp->g), reg);
- if(ws->split_tree==NULL){
- destroy_obj((Obj*)reg);
- return NULL;
- }
ws->split_tree->ws_if_root=ws;
if(!tiling_managed_add(ws, reg)){
- destroy_obj((Obj*)reg);
destroy_obj((Obj*)ws->split_tree);
- return NULL;
+ ws->split_tree=NULL;
+ return FALSE;
}
-
- return reg;
+
+ return TRUE;
}
-
+
static WRegion *create_frame_tiling(WWindow *parent, const WFitParams *fp)
{
: create_frame_tiling);
ws->stdispnode=NULL;
ws->managed_list=NULL;
-
+ ws->batchop=FALSE;
+
ws->dummywin=XCreateWindow(ioncore_g.dpy, parent->win,
fp->g.x, fp->g.y, 1, 1, 0,
CopyFromParent, InputOnly,
REGION_PLEASE_WARP);
if(ci){
- if(create_initial_frame(ws, parent, fp)==NULL){
+ WRegionAttachData data;
+ WRegion *res;
+
+ data.type=REGION_ATTACH_NEW;
+ data.u.n.fn=(WRegionCreateFn*)ws->create_frame_fn;
+ data.u.n.param=NULL;
+
+ res=region_attach_helper((WRegion*)ws, parent, fp,
+ (WRegionDoAttachFn*)tiling_do_attach_initial,
+ NULL, &data);
+
+ if(res==NULL){
XDestroyWindow(ioncore_g.dpy, ws->dummywin);
return FALSE;
}
}
-bool tiling_managed_may_destroy(WTiling *ws, WRegion *reg)
+WRegion *tiling_managed_disposeroot(WTiling *ws, WRegion *reg)
{
WTilingIterTmp tmp;
WRegion *mgd;
-
- FOR_ALL_MANAGED_BY_TILING(mgd, ws, tmp){
- if(mgd!=STDISP_OF(ws) && mgd!=reg){
- return TRUE;
- }
- }
- return region_manager_allows_destroying((WRegion*)ws);
-}
-
-
-bool tiling_may_destroy(WTiling *ws, WRegion *reg)
-{
- WTilingIterTmp tmp;
- WRegion *mgd;
+ if(ws->batchop)
+ return reg;
FOR_ALL_MANAGED_BY_TILING(mgd, ws, tmp){
- if(mgd!=STDISP_OF(ws)){
- warn(TR("Workspace not empty - refusing to destroy."));
- return FALSE;
- }
+ if(mgd!=TILING_STDISP_OF(ws) && mgd!=reg)
+ return reg;
}
- return TRUE;
+ return region_disposeroot((WRegion*)ws);
}
-bool tiling_rescue_clientwins(WTiling *ws, WPHolder *ph)
+bool tiling_rescue_clientwins(WTiling *ws, WRescueInfo *info)
{
WTilingIterTmp tmp;
ptrlist_iter_init(&tmp, ws->managed_list);
- return region_rescue_some_clientwins((WRegion*)ws, ph,
+ return region_rescue_some_clientwins((WRegion*)ws, info,
(WRegionIterator*)ptrlist_iter,
&tmp);
}
void tiling_do_managed_remove(WTiling *ws, WRegion *reg)
{
- if(STDISP_OF(ws)==reg){
+ if(TILING_STDISP_OF(ws)==reg){
ws->stdispnode->regnode.reg=NULL;
}else{
ptrlist_remove(&(ws->managed_list), reg);
void tiling_managed_remove(WTiling *ws, WRegion *reg)
{
- bool ds=OBJ_IS_BEING_DESTROYED(ws);
bool act=REGION_IS_ACTIVE(reg);
bool mcf=region_may_control_focus((WRegion*)ws);
WSplitRegion *node=get_node_check(ws, reg);
- WRegion *other;
+ bool norestore=(OBJ_IS_BEING_DESTROYED(ws) || ws->batchop);
+ WRegion *other=NULL;
- other=tiling_do_navi_next(ws, reg, REGION_NAVI_ANY, TRUE, FALSE);
+ if(!norestore)
+ other=tiling_do_navi_next(ws, reg, REGION_NAVI_ANY, TRUE, FALSE);
tiling_do_managed_remove(ws, reg);
if(node==(WSplitRegion*)(ws->stdispnode))
ws->stdispnode=NULL;
- if(node==NULL)
- return;
-
- splittree_remove((WSplit*)node, (!ds && other!=NULL));
-
- if(!ds){
- if(other==NULL)
- mainloop_defer_destroy((Obj*)ws);
- else if(act && mcf)
- region_warp(other);
+ if(node!=NULL){
+ bool reused=FALSE;
+
+ if(other==NULL && !norestore){
+ WWindow *par=REGION_PARENT(ws);
+ WFitParams fp;
+
+ assert(par!=NULL);
+
+ fp.g=node->split.geom;
+ fp.mode=REGION_FIT_EXACT;
+
+ other=(ws->create_frame_fn)(par, &fp);
+
+ if(other!=NULL){
+ node->reg=other;
+ tiling_managed_add(ws, other);
+ reused=TRUE;
+ }else{
+ warn(TR("Tiling in useless state."));
+ }
+ }
+
+ if(!reused)
+ splittree_remove((WSplit*)node, (!norestore && other!=NULL));
}
+
+ if(!norestore && other!=NULL && act && mcf)
+ region_warp(other);
}
}
-/*EXTL_DOC
- * Try to relocate regions managed by \var{frame} to another frame
- * and, if possible, destroy the frame.
- */
-EXTL_EXPORT_MEMBER
-bool tiling_unsplit_at(WTiling *ws, WFrame *frame)
+void do_unsplit(WRegion *reg)
{
- if(frame==NULL){
- warn(TR("Nil frame."));
- return FALSE;
+ WTiling *ws=REGION_MANAGER_CHK(reg, WTiling);
+ WPHolder *ph;
+ bool res;
+
+ if(ws==NULL)
+ return;
+
+ ph=region_get_rescue_pholder_for((WRegion*)ws, reg);
+
+ if(ph==NULL){
+ res=!region_rescue_needed(reg);
+ }else{
+ res=region_rescue(reg, ph);
+ destroy_obj((Obj*)ph);
}
- if(REGION_MANAGER(frame)!=(WRegion*)ws){
- warn(TR("The frame is not managed by the workspace."));
- return FALSE;
+ if(!res){
+ warn(TR("Unable to unsplit: Could not move client windows "
+ "elsewhere within the tiling."));
+ return;
}
- return region_rqclose((WRegion*)frame, TRUE);
+ destroy_obj((Obj*)reg);
+}
+
+
+/*EXTL_DOC
+ * Try to relocate regions managed by \var{reg} to another frame
+ * and, if possible, destroy it.
+ */
+EXTL_EXPORT_MEMBER
+void tiling_unsplit_at(WTiling *ws, WRegion *reg)
+{
+ if(reg==NULL || REGION_MANAGER(reg)!=(WRegion*)ws)
+ return;
+
+ mainloop_defer_action((Obj*)reg, (WDeferredAction*)do_unsplit);
}
/*EXTL_DOC
- * Returns a list of regions managed by the workspace (frames, mostly).
+ * Iterate over managed regions of \var{ws} 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 tiling_managed_list(WTiling *ws)
+bool tiling_managed_i(WTiling *ws, ExtlFn iterfn)
{
PtrListIterTmp tmp;
ptrlist_iter_init(&tmp, ws->managed_list);
- return extl_obj_iterable_to_table((ObjIterator*)ptrlist_iter, &tmp);
+ return extl_iter_objlist_(iterfn, (ObjIterator*)ptrlist_iter, &tmp);
}
{(DynFun*)region_get_configuration,
(DynFun*)tiling_get_configuration},
- {(DynFun*)region_managed_may_destroy,
- (DynFun*)tiling_managed_may_destroy},
-
- {(DynFun*)region_may_destroy,
- (DynFun*)tiling_may_destroy},
+ {(DynFun*)region_managed_disposeroot,
+ (DynFun*)tiling_managed_disposeroot},
{(DynFun*)region_current,
(DynFun*)tiling_current},