]> git.decadent.org.uk Git - ion3.git/blob - ioncore/sizehint.c
Imported Upstream version 20090110
[ion3.git] / ioncore / sizehint.c
1 /*
2  * ion/ioncore/sizehint.c
3  *
4  * Copyright (c) Tuomo Valkonen 1999-2009. 
5  *
6  * See the included file LICENSE for details.
7  */
8
9 #include <string.h>
10 #include <libtu/minmax.h>
11
12 #include "common.h"
13 #include "global.h"
14 #include "region.h"
15 #include "resize.h"
16 #include "sizehint.h"
17 #include "rootwin.h"
18
19
20 /*{{{ xsizehints_correct */
21
22
23 static void do_correct_aspect(int max_w, int max_h, int ax, int ay,
24                               int *wret, int *hret)
25 {
26     int w=*wret, h=*hret;
27
28     if(ax>ay){
29         h=(w*ay)/ax;
30         if(max_h>0 && h>max_h){
31             h=max_h;
32             w=(h*ax)/ay;
33         }
34     }else{
35         w=(h*ax)/ay;
36         if(max_w>0 && w>max_w){
37             w=max_w;
38             h=(w*ay)/ax;
39         }
40     }
41     
42     *wret=w;
43     *hret=h;
44 }
45
46
47 static void correct_aspect(int max_w, int max_h, const WSizeHints *hints,
48                            int *wret, int *hret)
49 {
50     if(!hints->aspect_set)
51         return;
52     
53     if(*wret*hints->max_aspect.y>*hret*hints->max_aspect.x){
54         do_correct_aspect(max_w, max_h,
55                           hints->min_aspect.x, hints->min_aspect.y,
56                           wret, hret);
57     }
58
59     if(*wret*hints->min_aspect.y<*hret*hints->min_aspect.x){
60         do_correct_aspect(max_w, max_h,
61                           hints->max_aspect.x, hints->max_aspect.y,
62                           wret, hret);
63     }
64 }
65
66
67 void sizehints_correct(const WSizeHints *hints, int *wp, int *hp, 
68                        bool min, bool override_no_constrain)
69 {
70     int w=*wp, tw, bw=(hints->base_set ? hints->base_width : 0);
71     int h=*hp, th, bh=(hints->base_set ? hints->base_height : 0);
72     int bs=0;
73     
74     if(min && hints->min_set){
75         w=maxof(w, hints->min_width);
76         h=maxof(h, hints->min_height);
77     }
78     
79     if(hints->no_constrain && !override_no_constrain){
80         *wp=w;
81         *hp=h;
82         return;
83     }
84     
85     tw=w-bw;
86     th=h-bh;
87     
88     if(tw>=0 && th>=0)
89         correct_aspect(tw, th, hints, &tw, &th);
90     
91     if(hints->inc_set){
92         if(tw>0)
93             tw=(tw/hints->width_inc)*hints->width_inc;
94         if(th>0)
95             th=(th/hints->height_inc)*hints->height_inc;
96     }
97     
98     w=tw+bw;
99     h=th+bh;
100     
101     if(hints->max_set){
102         w=minof(w, hints->max_width);
103         h=minof(h, hints->max_height);
104     }
105     
106     *wp=w;
107     *hp=h;
108 }
109
110
111 /*}}}*/
112
113
114 /*{{{ X size hints sanity adjustment */
115
116
117 void xsizehints_sanity_adjust(XSizeHints *hints)
118 {
119     if(!(hints->flags&PMinSize)){
120         if(hints->flags&PBaseSize){
121             hints->min_width=hints->base_width;
122             hints->min_height=hints->base_height;
123         }else{
124             hints->min_width=0;
125             hints->min_height=0;
126         }
127     }
128
129     hints->min_width=maxof(hints->min_width, 0);
130     hints->min_height=maxof(hints->min_height, 0);
131
132     if(!(hints->flags&PBaseSize) || hints->base_width<0)
133         hints->base_width=hints->min_width;
134     if(!(hints->flags&PBaseSize) || hints->base_height<0)
135         hints->base_height=hints->min_height;
136     
137     if(hints->flags&PMaxSize){
138         hints->max_width=maxof(hints->max_width, hints->min_width);
139         hints->max_height=maxof(hints->max_height, hints->min_height);
140     }
141     
142     hints->flags|=(PBaseSize|PMinSize);
143
144     if(hints->flags&PResizeInc){
145         if(hints->width_inc<=0 || hints->height_inc<=0){
146             warn(TR("Invalid client-supplied width/height increment."));
147             hints->flags&=~PResizeInc;
148         }
149     }
150     
151     if(hints->flags&PAspect){
152         if(hints->min_aspect.x<=0 || hints->min_aspect.y<=0 ||
153            hints->min_aspect.x<=0 || hints->min_aspect.y<=0){
154             warn(TR("Invalid client-supplied aspect-ratio."));
155             hints->flags&=~PAspect;
156         }
157     }
158     
159     if(!(hints->flags&PWinGravity))
160         hints->win_gravity=ForgetGravity;
161 }
162
163
164 /*}}}*/
165
166
167 /*{{{ xsizehints_adjust_for */
168
169
170 void sizehints_adjust_for(WSizeHints *hints, WRegion *reg)
171 {
172     WSizeHints tmp_hints;
173     
174     region_size_hints(reg, &tmp_hints);
175     
176     if(tmp_hints.min_set){
177         if(!hints->min_set){
178             hints->min_set=TRUE;
179             hints->min_width=tmp_hints.min_width;
180             hints->min_height=tmp_hints.min_height;
181         }else{
182             hints->min_width=maxof(hints->min_width,
183                                    tmp_hints.min_width);
184             hints->min_height=maxof(hints->min_height,
185                                     tmp_hints.min_height);
186         }
187     }
188     
189     if(tmp_hints.max_set && hints->max_set){
190         hints->max_width=maxof(hints->max_width,
191                                tmp_hints.max_width);
192         hints->max_height=maxof(hints->max_height,
193                                 tmp_hints.max_height);
194     }else{
195         hints->max_set=FALSE;
196     }
197 }
198
199
200 /*}}}*/
201
202
203 /*{{{ account_gravity */
204
205
206 int xgravity_deltax(int gravity, int left, int right)
207 {
208     int woff=left+right;
209
210     if(gravity==StaticGravity || gravity==ForgetGravity){
211         return -left;
212     }else if(gravity==NorthWestGravity || gravity==WestGravity ||
213              gravity==SouthWestGravity){
214         /* */
215     }else if(gravity==NorthEastGravity || gravity==EastGravity ||
216              gravity==SouthEastGravity){
217         /* geom->x=geom->w+geom->x-(geom->w+woff) */
218         return -woff;
219     }else if(gravity==CenterGravity || gravity==NorthGravity ||
220              gravity==SouthGravity){
221         /* geom->x=geom->x+geom->w/2-(geom->w+woff)/2 */
222         return -woff/2;
223     }
224     return 0;
225 }
226
227
228 int xgravity_deltay(int gravity, int top, int bottom)
229 {
230     int hoff=top+bottom;
231     
232     if(gravity==StaticGravity || gravity==ForgetGravity){
233         return -top;
234     }else if(gravity==NorthWestGravity || gravity==NorthGravity ||
235              gravity==NorthEastGravity){
236         /* */
237     }else if(gravity==SouthWestGravity || gravity==SouthGravity ||
238              gravity==SouthEastGravity){
239         /* geom->y=geom->y+geom->h-(geom->h+hoff) */
240         return -hoff;
241     }else if(gravity==CenterGravity || gravity==WestGravity ||
242              gravity==EastGravity){
243         /* geom->y=geom->y+geom->h/2-(geom->h+hoff)/2 */
244         return -hoff/2;
245     }
246     return 0;
247 }
248
249
250 void xgravity_translate(int gravity, WRegion *reg, WRectangle *geom)
251 {
252     int top=0, left=0, bottom=0, right=0;
253     WRootWin *root;
254
255     root=region_rootwin_of(reg);
256     region_rootpos(reg, &left, &top);
257     right=REGION_GEOM(root).w-left-REGION_GEOM(reg).w;
258     bottom=REGION_GEOM(root).h-top-REGION_GEOM(reg).h;
259
260     geom->x+=xgravity_deltax(gravity, left, right);
261     geom->y+=xgravity_deltay(gravity, top, bottom);
262 }
263
264
265 /*}}}*/
266
267
268 /*{{{ Init */
269
270
271 void xsizehints_to_sizehints(const XSizeHints *xh, WSizeHints *hints)
272 {
273     hints->max_width=xh->max_width;
274     hints->max_height=xh->max_height;
275     hints->min_width=xh->min_width;
276     hints->min_height=xh->min_height;
277     hints->base_width=xh->base_width;
278     hints->base_height=xh->base_height;
279     hints->width_inc=xh->width_inc;
280     hints->height_inc=xh->height_inc;
281     hints->min_aspect.x=xh->min_aspect.x;
282     hints->min_aspect.y=xh->min_aspect.y;
283     hints->max_aspect.x=xh->max_aspect.x;
284     hints->max_aspect.y=xh->max_aspect.y;
285     
286     hints->max_set=((xh->flags&PMaxSize)!=0);
287     hints->min_set=((xh->flags&PMinSize)!=0);
288     hints->base_set=((xh->flags&PBaseSize)!=0);
289     hints->inc_set=((xh->flags&PResizeInc)!=0);
290     hints->aspect_set=((xh->flags&PAspect)!=0);
291     hints->no_constrain=0;
292 }
293
294
295 void sizehints_clear(WSizeHints *hints)
296 {
297     hints->max_set=0;
298     hints->min_set=0;
299     hints->inc_set=0;
300     hints->base_set=0;
301     hints->aspect_set=0;
302     hints->no_constrain=0;
303 }
304
305
306 /*}}}*/