/*
* ion/ioncore/attach.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 <string.h>
#include "manage.h"
#include "extlconv.h"
#include "names.h"
+#include "focus.h"
/*{{{ Helper */
if(reg==NULL)
return NULL;
-
+
if(!cont(mgr, reg, cont_param)){
destroy_obj((Obj*)reg);
return NULL;
WRegion *reg)
{
WFitParams fp2;
-
- if(!region_attach_reparent_check(mgr, reg))
+ WRegion *disposeroot;
+
+ if(!region_ancestor_check(mgr, reg)){
+ warn(TR("Attempt to make region %s manage its ancestor %s."),
+ region_name(mgr), region_name(reg));
return NULL;
+ }
+
+ disposeroot=region_disposeroot(reg);
+
+ if(disposeroot==NULL){
+ /* Region may not be reparented */
+ return NULL;
+ }
if(fp->mode®ION_FIT_WHATEVER){
/* fp->g is not final; substitute size with current to avoid
region_detach_manager(reg);
if(!cont(mgr, reg, cont_param)){
- #warning "TODO: What?"
+ WScreen *scr=region_screen_of(reg);
+
+ warn(TR("Unexpected attach error: "
+ "trying to recover by attaching to screen."));
+
+ if(scr!=NULL){
+ /* Try to attach to screen, to have `reg` attached at least
+ * somewhere. For better recovery, we could try to get
+ * a placeholder for `reg` before we detach it, but this
+ * would add unnecessary overhead in the usual succesfull
+ * case. (This failure is supposed to be _very_ rare!)
+ * We intentionally also do not region_postdetach_dispose
+ * on recovery.
+ */
+ int flags=(region_may_control_focus(reg)
+ ? MPLEX_ATTACH_SWITCHTO
+ : 0);
+ if(mplex_attach_simple(&scr->mplex, reg, flags)!=NULL)
+ return NULL;
+ }
+
+ warn(TR("Failed recovery."));
+
return NULL;
}
-
+
+ region_postdetach_dispose(reg, disposeroot);
+
return reg;
}
}
+WRegion *ioncore_newly_created=NULL;
+
+
static WRegion *doit_load(WRegion *mgr,
WWindow *par, const WFitParams *fp,
WRegionDoAttachFn *cont, void *cont_param,
ExtlTab tab)
{
- WRegion *reg;
+ WRegion *reg=NULL;
if(extl_table_gets_o(tab, "reg", (Obj**)®)){
if(!OBJ_IS(reg, WRegion))
return FALSE;
+ }/*else if(extl_table_is_bool_set(tab, "reg_use_new")){
+ reg=ioncore_newly_created;
+ if(reg==NULL)
+ return NULL;
+ }*/
+
+ if(reg!=NULL){
return doit_reparent(mgr, par, fp, cont, cont_param, reg);
+ }else{
+ return doit_new(mgr, par, fp, cont, cont_param,
+ (WRegionCreateFn*)wrap_load, &tab);
}
-
- return doit_new(mgr, par, fp, cont, cont_param,
- (WRegionCreateFn*)wrap_load, &tab);
}
WRegion *region_attach_helper(WRegion *mgr,
/*}}}*/
-/*{{{ Reparent check */
+/*{{{ Reparent check etc. */
-bool region_attach_reparent_check(WRegion *mgr, WRegion *reg)
+bool region_ancestor_check(WRegion *dst, WRegion *reg)
{
WRegion *reg2;
- /*if(REGION_MANAGER(reg)==mgr){
- warn(TR("Same manager."));
- return FALSE;
- }*/
-
/* Check that reg is not a parent or manager of mgr */
- for(reg2=mgr; reg2!=NULL; reg2=REGION_MANAGER(reg2)){
+ for(reg2=dst; reg2!=NULL; reg2=REGION_MANAGER(reg2)){
if(reg2==reg)
- goto err;
+ return FALSE;
}
- for(reg2=REGION_PARENT_REG(mgr); reg2!=NULL; reg2=REGION_PARENT_REG(reg2)){
+ for(reg2=REGION_PARENT_REG(dst); reg2!=NULL; reg2=REGION_PARENT_REG(reg2)){
if(reg2==reg)
- goto err;
+ return FALSE;
}
return TRUE;
-
-err:
- warn(TR("Attempt to make region %s manage its ancestor %s."),
- region_name(mgr), region_name(reg));
- return FALSE;
+}
+
+
+void region_postdetach_dispose(WRegion *reg, WRegion *disposeroot)
+{
+ /* disposeroot should be destroyed (as empty and useless) unless it
+ * still, in fact, is an ancestor of reg.
+ */
+ if(disposeroot!=reg && region_ancestor_check(reg, disposeroot))
+ region_dispose(disposeroot);
}