Released version 3-2014010505
[notion.git] / ioncore / float-placement.c
blob808e95140c0d2f9bf0e4489bee32d965464673d1
1 /*
2 * ion/ioncore/float-placement.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
7 */
9 #include <string.h>
11 #include "common.h"
12 #include "group.h"
13 #include "float-placement.h"
16 WFloatPlacement ioncore_placement_method=PLACEMENT_LRUD;
17 int ioncore_placement_padding=1;
20 static void random_placement(WRectangle box, WRectangle *g)
22 box.w-=g->w;
23 box.h-=g->h;
24 g->x=box.x+(box.w<=0 ? 0 : rand()%box.w);
25 g->y=box.y+(box.h<=0 ? 0 : rand()%box.h);
29 static void ggeom(WRegion *reg, WRectangle *geom)
31 *geom=REGION_GEOM(reg);
35 static bool st_filt(WStacking *st, void *lvl)
37 uint level=*(uint*)lvl;
39 return (st->reg!=NULL &&
40 REGION_IS_MAPPED(st->reg) &&
41 st->level==level);
45 #define FOR_ALL_STACKING_NODES(VAR, WS, LVL, TMP) \
46 for(stacking_iter_init(&(TMP), group_get_stacking(ws), \
47 st_filt, &LVL), \
48 VAR=stacking_iter_nodes(&(TMP)); \
49 VAR!=NULL; \
50 VAR=stacking_iter_nodes(&(TMP)))
53 #define IGNORE_ST(ST, WS) ((ST)->reg==NULL || (ST)==(WS)->bottom)
56 static WRegion* is_occupied(WGroup *ws, uint level, const WRectangle *r)
58 WStackingIterTmp tmp;
59 WStacking *st;
60 WRectangle p;
62 FOR_ALL_STACKING_NODES(st, ws, level, tmp){
63 ggeom(st->reg, &p);
65 if(r->x>=p.x+p.w)
66 continue;
67 if(r->y>=p.y+p.h)
68 continue;
69 if(r->x+r->w<=p.x)
70 continue;
71 if(r->y+r->h<=p.y)
72 continue;
73 return st->reg;
76 return NULL;
80 static int next_least_x(WGroup *ws, uint level, int x)
82 WRectangle p;
83 int retx=REGION_GEOM(ws).x+REGION_GEOM(ws).w;
84 WStackingIterTmp tmp;
85 WStacking *st;
87 FOR_ALL_STACKING_NODES(st, ws, level, tmp){
88 ggeom(st->reg, &p);
90 if(p.x+p.w>x && p.x+p.w<retx)
91 retx=p.x+p.w;
94 return retx;
99 static int next_least_y(WGroup *ws, uint level, int y)
101 WRectangle p;
102 int rety=REGION_GEOM(ws).y+REGION_GEOM(ws).h;
103 WStackingIterTmp tmp;
104 WStacking *st;
106 FOR_ALL_STACKING_NODES(st, ws, level, tmp){
107 ggeom(st->reg, &p);
109 if(p.y+p.h>y && p.y+p.h<rety)
110 rety=p.y+p.h;
113 return rety;
117 static bool tiling_placement(WGroup *ws, uint level, WRectangle *g)
119 WRegion *p;
120 WRectangle r, r2;
121 int maxx, maxy;
123 r=REGION_GEOM(ws);
124 r.w=g->w;
125 r.h=g->h;
127 maxx=REGION_GEOM(ws).x+REGION_GEOM(ws).w;
128 maxy=REGION_GEOM(ws).y+REGION_GEOM(ws).h;
130 if(ioncore_placement_method==PLACEMENT_UDLR){
131 while(r.x<maxx){
132 p=is_occupied(ws, level, &r);
133 while(p!=NULL && r.y+r.h<maxy){
134 ggeom(p, &r2);
135 r.y=r2.y+r2.h+ioncore_placement_padding;
136 p=is_occupied(ws, level, &r);
138 if(r.y+r.h<maxy && r.x+r.w<maxx){
139 g->x=r.x;
140 g->y=r.y;
141 return TRUE;
142 }else{
143 r.x=next_least_x(ws, level, r.x)+ioncore_placement_padding;
144 r.y=0;
147 }else{
148 while(r.y<maxy){
149 p=is_occupied(ws, level, &r);
150 while(p!=NULL && r.x+r.w<maxx){
151 ggeom(p, &r2);
152 r.x=r2.x+r2.w+ioncore_placement_padding;
153 p=is_occupied(ws, level, &r);
155 if(r.y+r.h<maxy && r.x+r.w<maxx){
156 g->x=r.x;
157 g->y=r.y;
158 return TRUE;
159 }else{
160 r.y=next_least_y(ws, level, r.y)+ioncore_placement_padding;
161 r.x=0;
166 return FALSE;
171 void group_calc_placement(WGroup *ws, uint level, WRectangle *geom)
173 if(ioncore_placement_method!=PLACEMENT_RANDOM){
174 if(tiling_placement(ws, level, geom))
175 return;
177 random_placement(REGION_GEOM(ws), geom);