X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=ioncore%2Fmanage.c;h=bcc8a5388a394de0b3919b747e6eba04ae160461;hb=ae4260bb64817c11f9a7140324cd3e3ba113e297;hp=f1d78a0a95ac567f82cb3870e5de232e1d62e778;hpb=8366314611bf30a0f31d25bf5f5023186fa87692;p=ion3.git diff --git a/ioncore/manage.c b/ioncore/manage.c index f1d78a0..bcc8a53 100644 --- a/ioncore/manage.c +++ b/ioncore/manage.c @@ -1,12 +1,9 @@ /* * ion/ioncore/manage.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 @@ -20,6 +17,10 @@ #include "pointer.h" #include "netwm.h" #include "extlconv.h" +#include "return.h" +#include "conf.h" +#include "detach.h" +#include "group-ws.h" /*{{{ Add */ @@ -34,16 +35,22 @@ WScreen *clientwin_find_suitable_screen(WClientWin *cwin, FOR_ALL_SCREENS(scr){ if(!region_same_rootwin((WRegion*)scr, (WRegion*)cwin)) continue; - if(REGION_IS_ACTIVE(scr)){ - found=scr; - if(!respectpos) - break; - } - - if(rectangle_contains(®ION_GEOM(scr), param->geom.x, param->geom.y)){ - found=scr; - if(respectpos) - break; + + if(!OBJ_IS(scr, WRootWin)){ + /* The root window itself is only a fallback */ + + if(REGION_IS_ACTIVE(scr)){ + found=scr; + if(!respectpos) + break; + } + + if(rectangle_contains(®ION_GEOM(scr), + param->geom.x, param->geom.y)){ + found=scr; + if(respectpos) + break; + } } if(found==NULL) @@ -54,23 +61,129 @@ WScreen *clientwin_find_suitable_screen(WClientWin *cwin, } +/*extern WRegion *ioncore_newly_created;*/ + + +static WPHolder *try_target(WClientWin *cwin, const WManageParams *param, + const char *target) +{ + WRegion *r=ioncore_lookup_region(target, NULL); + + if(r==NULL) + return NULL; + + return region_prepare_manage(r, cwin, param, MANAGE_PRIORITY_NONE); +} + + +static bool handle_target_winprops(WClientWin *cwin, const WManageParams *param, + WScreen *scr, WPHolder **ph_ret) +{ + char *layout=NULL, *target=NULL; + WPHolder *ph=NULL; + bool mgd=FALSE; + + if(extl_table_gets_s(cwin->proptab, "target", &target)) + ph=try_target(cwin, param, target); + + if(ph==NULL && extl_table_gets_s(cwin->proptab, "new_group", &layout)){ + ExtlTab lo=ioncore_get_layout(layout); + + free(layout); + + if(lo!=extl_table_none()){ + WMPlexAttachParams par=MPLEXATTACHPARAMS_INIT; + int mask=MPLEX_ATTACH_SWITCHTO; + WRegion *reg; + + if(param->switchto) + par.flags|=MPLEX_ATTACH_SWITCHTO; + + /*ioncore_newly_created=(WRegion*)cwin;*/ + + reg=mplex_attach_new_(&scr->mplex, &par, mask, lo); + + extl_unref_table(lo); + + /*ioncore_newly_created=NULL;*/ + + mgd=(region_manager((WRegion*)cwin)!=NULL); + + if(reg!=NULL && !mgd){ + if(target!=NULL) + ph=try_target(cwin, param, target); + + if(ph==NULL){ + ph=region_prepare_manage(reg, cwin, param, + MANAGE_PRIORITY_NONE); + + if(ph==NULL) + destroy_obj((Obj*)reg); + } + } + } + } + + if(target!=NULL) + free(target); + + *ph_ret=ph; + + return mgd; +} + + +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; - /* Check if param->tfor or any of its managers want to manage cwin. */ - if(param->tfor!=NULL){ - assert(param->tfor!=cwin); - ph=region_prepare_manage_transient((WRegion*)param->tfor, cwin, - param, 0); - } - /* Find a suitable screen */ scr=clientwin_find_suitable_screen(cwin, param); if(scr==NULL){ @@ -78,47 +191,46 @@ bool clientwin_do_manage_default(WClientWin *cwin, return FALSE; } + if(handle_target_winprops(cwin, param, scr, &ph)) + return TRUE; + + /* Check if param->tfor or any of its managers want to manage cwin. */ + if(ph==NULL && param->tfor!=NULL){ + 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 */ - 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; } - assert(cwin->fs_pholder==NULL); - cwin->fs_pholder=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; } @@ -130,29 +242,25 @@ bool clientwin_do_manage_default(WClientWin *cwin, 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); } @@ -183,10 +291,10 @@ WPHolder *region_prepare_manage_transient_default(WRegion *reg, 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) @@ -206,6 +314,14 @@ bool region_manage_clientwin(WRegion *reg, WClientWin *cwin, /*{{{ Rescue */ +DECLSTRUCT(WRescueInfo){ + WPHolder *ph; + WRegion *get_rescue; + bool failed_get; + bool test; +}; + + static WRegion *iter_children(void *st) { WRegion **nextp=(WRegion**)st; @@ -215,50 +331,101 @@ static WRegion *iter_children(void *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); } -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){ WRegion *tosave=iter(st); + WClientWin *cwin; if(tosave==NULL) break; - if(!OBJ_IS(tosave, WClientWin)){ - if(!region_rescue_clientwins(tosave, ph)) + cwin=OBJ_CAST(tosave, WClientWin); + + if(cwin==NULL){ + if(!region_rescue_clientwins(tosave, info)){ fails++; - }else{ - if(!pholder_attach(ph, 0, tosave)) + if(info->failed_get) + break; + } + }else if(info->test){ + fails++; + break; + }else if(!(cwin->flags&CLIENTWIN_UNMAP_RQ)){ + if(info->ph==NULL){ + info->ph=region_get_rescue_pholder(info->get_rescue); + if(info->ph==NULL){ + info->failed_get=TRUE; + break; + } + } + if(!pholder_attach(info->ph, 0, (WRegion*)cwin)) fails++; } } 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_param) +{ + WRescueInfo info; + bool ret; + + info.ph=ph_param; + info.test=FALSE; + info.get_rescue=reg; + info.failed_get=FALSE; + + ret=region_rescue_clientwins(reg, &info); + + if(info.ph!=ph_param) + destroy_obj((Obj*)info.ph); + + return ret; +} + + +bool region_rescue_needed(WRegion *reg) +{ + WRescueInfo info; + + info.ph=NULL; + info.test=TRUE; + info.get_rescue=reg; + info.failed_get=FALSE; + + return !region_rescue_clientwins(reg, &info); +} + + /*}}}*/