X-Git-Url: https://git.decadent.org.uk/gitweb/?p=ion3.git;a=blobdiff_plain;f=ioncore%2Fframedpholder.c;h=60c6291ba6c894a58520427b742c2778993cdab1;hp=43375f2d2a51cb1f7c2a3c770999e426653b602c;hb=e3aec18706513a87eaa7839dfdaf7e0fcd0d8d2a;hpb=8366314611bf30a0f31d25bf5f5023186fa87692 diff --git a/ioncore/framedpholder.c b/ioncore/framedpholder.c index 43375f2..60c6291 100644 --- a/ioncore/framedpholder.c +++ b/ioncore/framedpholder.c @@ -1,12 +1,9 @@ /* * ion/ioncore/framedpholder.c * - * Copyright (c) Tuomo Valkonen 2005-2006. + * Copyright (c) Tuomo Valkonen 2005-2009. * - * 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 @@ -16,6 +13,7 @@ #include "frame.h" #include "framedpholder.h" #include "sizehint.h" +#include "resize.h" /*{{{ Init/deinit */ @@ -31,6 +29,8 @@ bool framedpholder_init(WFramedPHolder *ph, WPHolder *cont, ph->cont=cont; ph->param=*param; + watch_init(&ph->frame_watch); + return TRUE; } @@ -50,6 +50,7 @@ void framedpholder_deinit(WFramedPHolder *ph) } pholder_deinit(&(ph->ph)); + watch_reset(&ph->frame_watch); } @@ -62,9 +63,61 @@ void framedpholder_deinit(WFramedPHolder *ph) typedef struct{ WRegionAttachData *data; WFramedParam *param; + WRegion *reg_ret; } AP; +void frame_adjust_to_initial(WFrame *frame, const WFitParams *fp, + const WFramedParam *param, WRegion *reg) +{ + WRectangle rqg, mg; + WSizeHints szh; + int iw, ih; + + if(!(fp->mode&(REGION_FIT_BOUNDS|REGION_FIT_WHATEVER))) + return; + + mplex_managed_geom((WMPlex*)frame, &mg); + + /* Adjust geometry */ + if(!param->inner_geom_gravity_set){ + iw=REGION_GEOM(reg).w; + ih=REGION_GEOM(reg).h; + rqg.x=REGION_GEOM(frame).x; + rqg.y=REGION_GEOM(frame).y; + }else{ + int bl=mg.x; + int br=REGION_GEOM(frame).w-(mg.x+mg.w); + int bt=mg.y; + int bb=REGION_GEOM(frame).h-(mg.y+mg.h); + + iw=param->inner_geom.w; + ih=param->inner_geom.h; + + rqg.x=(/*fp->g.x+*/param->inner_geom.x+ + xgravity_deltax(param->gravity, bl, br)); + rqg.y=(/*fp->g.y+*/param->inner_geom.y+ + xgravity_deltay(param->gravity, bt, bb)); + } + + /* Some apps seem to request geometries inconsistent with their size hints, + * so correct for that here. + * Because WGroup(CW) sets no_constrain on the size hints, we have + * to set override_no_constrain to force the frame to have the size + * of the 'bottom' of the group. + */ + region_size_hints(reg, &szh); + sizehints_correct(&szh, &iw, &ih, TRUE, TRUE); + rqg.w=maxof(1, iw+(REGION_GEOM(frame).w-mg.w)); + rqg.h=maxof(1, ih+(REGION_GEOM(frame).h-mg.h)); + + if(!(fp->mode®ION_FIT_WHATEVER)) + rectangle_constrain(&rqg, &fp->g); + + region_fit((WRegion*)frame, &rqg, REGION_FIT_EXACT); +} + + WRegion *framed_handler(WWindow *par, const WFitParams *fp, void *ap_) @@ -72,14 +125,10 @@ WRegion *framed_handler(WWindow *par, AP *ap=(AP*)ap_; WMPlexAttachParams mp=MPLEXATTACHPARAMS_INIT; WFramedParam *param=ap->param; - WRectangle rqg, mg; WFrame *frame; WRegion *reg; - if(param->mkframe!=NULL) - frame=(WFrame*)(param->mkframe)(par, fp); - else - frame=create_frame(par, fp, FRAME_MODE_FLOATING); + frame=create_frame(par, fp, param->mode); if(frame==NULL) return NULL; @@ -89,40 +138,14 @@ WRegion *framed_handler(WWindow *par, reg=mplex_do_attach(&frame->mplex, &mp, ap->data); + ap->reg_ret=reg; + if(reg==NULL){ destroy_obj((Obj*)frame); return NULL; } - - if(!(fp->mode&(REGION_FIT_BOUNDS|REGION_FIT_WHATEVER))) - return (WRegion*)frame; - - mplex_managed_geom((WMPlex*)frame, &mg); - - /* Adjust geometry */ - if(!param->inner_geom_gravity_set){ - rqg.x=REGION_GEOM(frame).x; - rqg.y=REGION_GEOM(frame).y; - rqg.w=maxof(1, REGION_GEOM(reg).w+(REGION_GEOM(frame).w-mg.w)); - rqg.h=maxof(1, REGION_GEOM(reg).h+(REGION_GEOM(frame).h-mg.h)); - }else{ - int bl=mg.x; - int br=REGION_GEOM(frame).w-(mg.x+mg.w); - int bt=mg.y; - int bb=REGION_GEOM(frame).h-(mg.y+mg.h); - - rqg.x=(fp->g.x+param->inner_geom.x+ - xgravity_deltax(param->gravity, bl, br)); - rqg.y=(fp->g.y+param->inner_geom.y+ - xgravity_deltay(param->gravity, bt, bb)); - rqg.w=maxof(1, param->inner_geom.w+(REGION_GEOM(frame).w-mg.w)); - rqg.h=maxof(1, param->inner_geom.h+(REGION_GEOM(frame).h-mg.h)); - } - - if(!(fp->mode®ION_FIT_WHATEVER)) - rectangle_constrain(&rqg, &fp->g); - region_fit((WRegion*)frame, &rqg, REGION_FIT_EXACT); + frame_adjust_to_initial(frame, fp, param, reg); return (WRegion*)frame; } @@ -141,6 +164,7 @@ WRegion *region_attach_framed(WRegion *reg, WFramedParam *param, ap.data=data; ap.param=param; + ap.reg_ret=NULL; return fn(reg, fn_param, &data2); } @@ -150,8 +174,16 @@ WRegion *framedpholder_do_attach(WFramedPHolder *ph, int flags, WRegionAttachData *data) { WRegionAttachData data2; + WFrame *frame; AP ap; + frame=(WFrame*)ph->frame_watch.obj; + + if(frame!=NULL){ + WMPlexAttachParams mp=MPLEXATTACHPARAMS_INIT; + return mplex_do_attach(&frame->mplex, &mp, data); + } + if(ph->cont==NULL) return FALSE; @@ -161,8 +193,18 @@ WRegion *framedpholder_do_attach(WFramedPHolder *ph, int flags, ap.data=data; ap.param=&ph->param; + ap.reg_ret=NULL; - return pholder_attach_(ph->cont, flags, &data2); + frame=(WFrame*)pholder_do_attach(ph->cont, flags, &data2); + + if(frame!=NULL){ + assert(OBJ_IS(frame, WFrame)); + watch_setup(&ph->frame_watch, (Obj*)frame, NULL); + } + + return (flags&PHOLDER_ATTACH_RETURN_CREATEROOT + ? (WRegion*)frame + : ap.reg_ret); } @@ -174,19 +216,34 @@ WRegion *framedpholder_do_attach(WFramedPHolder *ph, int flags, bool framedpholder_do_goto(WFramedPHolder *ph) { - if(ph->cont!=NULL) - return pholder_goto(ph->cont); + WRegion *frame=(WRegion*)ph->frame_watch.obj; - return FALSE; + if(frame!=NULL) + return region_goto((WRegion*)frame); + else if(ph->cont!=NULL) + return pholder_goto(ph->cont); + else + return FALSE; } WRegion *framedpholder_do_target(WFramedPHolder *ph) { - if(ph->cont!=NULL) - return pholder_target(ph->cont); + WRegion *frame=(WRegion*)ph->frame_watch.obj; + + return (frame!=NULL + ? frame + : (ph->cont!=NULL + ? pholder_target(ph->cont) + : NULL)); +} + + +bool framedpholder_stale(WFramedPHolder *ph) +{ + WRegion *frame=(WRegion*)ph->frame_watch.obj; - return NULL; + return (frame==NULL && (ph->cont==NULL || pholder_stale(ph->cont))); } @@ -205,6 +262,9 @@ static DynFunTab framedpholder_dynfuntab[]={ {(DynFun*)pholder_do_target, (DynFun*)framedpholder_do_target}, + + {(DynFun*)pholder_stale, + (DynFun*)framedpholder_stale}, END_DYNFUNTAB };