/*
* ion/ioncore/manage.c
*
- * Copyright (c) Tuomo Valkonen 1999-2007.
+ * Copyright (c) Tuomo Valkonen 1999-2008.
*
- * 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 <libtu/objp.h>
#include "extlconv.h"
#include "return.h"
#include "conf.h"
+#include "detach.h"
#include "group-ws.h"
if(r==NULL)
return NULL;
-
- return region_prepare_manage(r, cwin, param, MANAGE_REDIR_PREFER_NO);
+
+ if(!region_same_rootwin(r, (WRegion*)cwin))
+ return NULL;
+
+ return region_prepare_manage(r, cwin, param, MANAGE_PRIORITY_NONE);
}
if(ph==NULL){
ph=region_prepare_manage(reg, cwin, param,
- MANAGE_REDIR_PREFER_YES);
+ MANAGE_PRIORITY_NONE);
if(ph==NULL)
destroy_obj((Obj*)reg);
}
+static bool try_fullscreen(WClientWin *cwin, WScreen *dflt,
+ const WManageParams *param)
+{
+ WScreen *fs_scr=NULL;
+ bool fs=FALSE, tmp;
+
+ /* Check fullscreen mode. (This is intentionally not done
+ * for transients and windows with target winprops.)
+ */
+ if(extl_table_gets_b(cwin->proptab, "fullscreen", &tmp)){
+ if(!tmp)
+ return FALSE;
+ fs_scr=dflt;
+ }
+
+ if(fs_scr==NULL)
+ fs_scr=netwm_check_initial_fullscreen(cwin);
+
+ if(fs_scr==NULL)
+ fs_scr=clientwin_fullscreen_chkrq(cwin, param->geom.w, param->geom.h);
+
+ if(fs_scr!=NULL){
+ WPHolder *fs_ph=region_prepare_manage((WRegion*)fs_scr, cwin, param,
+ MANAGE_PRIORITY_NOREDIR);
+
+ if(fs_ph!=NULL){
+ int swf=(param->switchto ? PHOLDER_ATTACH_SWITCHTO : 0);
+
+ cwin->flags|=CLIENTWIN_FS_RQ;
+
+ fs=pholder_attach(fs_ph, swf, (WRegion*)cwin);
+
+ if(!fs)
+ cwin->flags&=~CLIENTWIN_FS_RQ;
+
+ destroy_obj((Obj*)fs_ph);
+ }
+ }
+
+ return fs;
+}
+
+
bool clientwin_do_manage_default(WClientWin *cwin,
const WManageParams *param)
{
- WRegion *r=NULL, *r2;
WScreen *scr=NULL;
WPHolder *ph=NULL;
- int fs=-1;
- int swf;
- bool ok, tmp;
+ int swf=(param->switchto ? PHOLDER_ATTACH_SWITCHTO : 0);
+ bool ok, uq=FALSE;
/* Find a suitable screen */
scr=clientwin_find_suitable_screen(cwin, param);
assert(param->tfor!=cwin);
ph=region_prepare_manage_transient((WRegion*)param->tfor, cwin,
param, 0);
+ uq=TRUE;
}
if(ph==NULL){
/* Find a placeholder for non-fullscreen state */
ph=region_prepare_manage((WRegion*)scr, cwin, param,
- MANAGE_REDIR_PREFER_YES);
-
- /* Check fullscreen mode. (This is intentionally not done
- * for transients and windows with target winprops.)
- */
- if(extl_table_gets_b(cwin->proptab, "fullscreen", &tmp))
- fs=tmp;
-
- if(fs<0)
- fs=netwm_check_initial_fullscreen(cwin, param->switchto);
-
- if(fs<0){
- fs=clientwin_check_fullscreen_request(cwin,
- param->geom.w,
- param->geom.h,
- param->switchto);
- }
- }
-
- if(fs>0){
- /* Full-screen mode succesfull. */
- if(pholder_target(ph)==(WRegion*)scr){
- /* Discard useless placeholder. */
+ MANAGE_PRIORITY_NONE);
+
+ if(try_fullscreen(cwin, scr, param)){
+ if(pholder_target(ph)!=(WRegion*)region_screen_of((WRegion*)cwin)){
+ WRegion *grp=region_groupleader_of((WRegion*)cwin);
+ if(region_do_set_return(grp, ph))
+ return TRUE;
+ }
destroy_obj((Obj*)ph);
return TRUE;
}
- if(!region_do_set_return((WRegion*)cwin, ph))
- destroy_obj((Obj*)ph);
-
- return TRUE;
}
-
+
if(ph==NULL)
return FALSE;
/* Not in full-screen mode; use the placeholder to attach. */
- swf=(param->switchto ? PHOLDER_ATTACH_SWITCHTO : 0);
ok=pholder_attach(ph, swf, (WRegion*)cwin);
+
destroy_obj((Obj*)ph);
+ if(uq && ok)
+ ioncore_unsqueeze((WRegion*)cwin, FALSE);
+
return ok;
}
WPHolder *region_prepare_manage(WRegion *reg, const WClientWin *cwin,
- const WManageParams *param, int redir)
+ const WManageParams *param, int priority)
{
WPHolder *ret=NULL;
CALL_DYN_RET(ret, WPHolder*, region_prepare_manage, reg,
- (reg, cwin, param, redir));
+ (reg, cwin, param, priority));
return ret;
}
WPHolder *region_prepare_manage_default(WRegion *reg, const WClientWin *cwin,
- const WManageParams *param, int redir)
+ const WManageParams *param, int priority)
{
- WRegion *curr;
-
- if(redir==MANAGE_REDIR_STRICT_NO)
- return NULL;
-
- curr=region_current(reg);
+ int cpriority=MANAGE_PRIORITY_SUB(priority, MANAGE_PRIORITY_NONE);
+ WRegion *curr=region_current(reg);
if(curr==NULL)
return NULL;
- return region_prepare_manage(curr, cwin, param, MANAGE_REDIR_PREFER_YES);
+ return region_prepare_manage(curr, cwin, param, cpriority);
}
bool region_manage_clientwin(WRegion *reg, WClientWin *cwin,
- const WManageParams *par, int redir)
+ const WManageParams *par, int priority)
{
bool ret;
- WPHolder *ph=region_prepare_manage(reg, cwin, par, redir);
+ WPHolder *ph=region_prepare_manage(reg, cwin, par, priority);
int swf=(par->switchto ? PHOLDER_ATTACH_SWITCHTO : 0);
if(ph==NULL)
/*{{{ Rescue */
+DECLSTRUCT(WRescueInfo){
+ WPHolder *ph;
+ WRegion *get_rescue;
+ bool failed_get;
+ bool test;
+ int flags;
+};
+
+
static WRegion *iter_children(void *st)
{
WRegion **nextp=(WRegion**)st;
}
-bool region_rescue_child_clientwins(WRegion *reg, WPHolder *ph)
+bool region_rescue_child_clientwins(WRegion *reg, WRescueInfo *info)
{
WRegion *next=reg->children;
- return region_rescue_some_clientwins(reg, ph, iter_children, &next);
+ return region_rescue_some_clientwins(reg, info, iter_children, &next);
+}
+
+
+WPHolder *rescueinfo_pholder(WRescueInfo *info)
+{
+ if(info->test)
+ return NULL;
+
+ if(info->ph==NULL){
+ info->ph=region_get_rescue_pholder(info->get_rescue);
+ if(info->ph==NULL){
+ info->failed_get=TRUE;
+ return NULL;
+ }
+ }
+
+ return info->ph;
+}
+
+
+/* Bah, unsplitissä oikestaan pitäisi tehä non-deep rescue */
+
+bool region_do_rescue_this(WRegion *tosave_, WRescueInfo *info, int ph_flags)
+{
+ WClientWin *cwin=OBJ_CAST(tosave_, WClientWin);
+ WRegion *tosave=NULL;
+
+ if(cwin!=NULL){
+ if(cwin->flags&CLIENTWIN_UNMAP_RQ)
+ return TRUE;
+ tosave=(WRegion*)cwin;
+ }else if(info->flags®ION_RESCUE_NODEEP){
+ tosave=tosave_;
+ }else{
+ /* Try to rescue whole groups. */
+ /*tosave=(WRegion*)OBJ_CAST(tosave_, WGroupCW);*/
+ }
+
+ if(tosave==NULL){
+ return region_rescue_clientwins(tosave_, info);
+ }else{
+ int phf=(info->flags®ION_RESCUE_PHFLAGS_OK ? ph_flags : 0);
+ WPHolder *ph=rescueinfo_pholder(info);
+
+ return (ph==NULL
+ ? FALSE
+ : pholder_attach(info->ph, phf, tosave));
+ }
}
-bool region_rescue_some_clientwins(WRegion *reg, WPHolder *ph,
+bool region_rescue_some_clientwins(WRegion *reg, WRescueInfo *info,
WRegionIterator *iter, void *st)
{
bool res=FALSE;
int fails=0;
+ if(info->failed_get)
+ return FALSE;
+
reg->flags|=REGION_CWINS_BEING_RESCUED;
while(TRUE){
if(tosave==NULL)
break;
-
- if(!OBJ_IS(tosave, WClientWin)){
- if(!region_rescue_clientwins(tosave, ph))
- fails++;
- }else{
- if(!pholder_attach(ph, 0, tosave))
- fails++;
+
+ if(!region_do_rescue_this(tosave, info, 0)){
+ fails++;
+ if(info->failed_get)
+ break;
}
}
reg->flags&=~REGION_CWINS_BEING_RESCUED;
- return (fails==0);
+ return (fails==0 && !info->failed_get);
}
-bool region_rescue_clientwins(WRegion *reg, WPHolder *ph)
+bool region_rescue_clientwins(WRegion *reg, WRescueInfo *info)
{
bool ret=FALSE;
- CALL_DYN_RET(ret, bool, region_rescue_clientwins, reg, (reg, ph));
+ CALL_DYN_RET(ret, bool, region_rescue_clientwins, reg, (reg, info));
return ret;
}
+bool region_rescue(WRegion *reg, WPHolder *ph, int flags)
+{
+ WRescueInfo info;
+ bool ret;
+
+ info.ph=ph;
+ info.flags=flags;
+ info.test=FALSE;
+ info.get_rescue=reg;
+ info.failed_get=FALSE;
+
+ ret=region_rescue_clientwins(reg, &info);
+
+ if(info.ph!=ph)
+ destroy_obj((Obj*)info.ph);
+
+ return ret;
+}
+
+
+bool region_rescue_needed(WRegion *reg)
+{
+ WRescueInfo info;
+
+ info.ph=NULL;
+ info.flags=0;
+ info.test=TRUE;
+ info.get_rescue=reg;
+ info.failed_get=FALSE;
+
+ return !region_rescue_clientwins(reg, &info);
+}
+
+
/*}}}*/