Released version 3-2014010505
[notion.git] / ioncore / sizehint.c
blob0d5d51da08da6a18c64270f8fec38c76697e1aaa
1 /*
2 * ion/ioncore/sizehint.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
7 */
9 #include <string.h>
10 #include <libtu/minmax.h>
12 #include "common.h"
13 #include "global.h"
14 #include "region.h"
15 #include "resize.h"
16 #include "sizehint.h"
17 #include "rootwin.h"
20 /*{{{ xsizehints_correct */
23 static void do_correct_aspect(int max_w, int max_h, int ax, int ay,
24 int *wret, int *hret)
26 int w=*wret, h=*hret;
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;
34 }else{
35 w=(h*ax)/ay;
36 if(max_w>0 && w>max_w){
37 w=max_w;
38 h=(w*ay)/ax;
42 *wret=w;
43 *hret=h;
47 static void correct_aspect(int max_w, int max_h, const WSizeHints *hints,
48 int *wret, int *hret)
50 if(!hints->aspect_set)
51 return;
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);
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);
67 void sizehints_correct(const WSizeHints *hints, int *wp, int *hp,
68 bool min, bool override_no_constrain)
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;
74 if(min && hints->min_set){
75 w=maxof(w, hints->min_width);
76 h=maxof(h, hints->min_height);
79 if(hints->no_constrain && !override_no_constrain){
80 *wp=w;
81 *hp=h;
82 return;
85 tw=w-bw;
86 th=h-bh;
88 if(tw>=0 && th>=0)
89 correct_aspect(tw, th, hints, &tw, &th);
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;
98 w=tw+bw;
99 h=th+bh;
101 if(hints->max_set){
102 w=minof(w, hints->max_width);
103 h=minof(h, hints->max_height);
106 *wp=w;
107 *hp=h;
111 /*}}}*/
114 /*{{{ X size hints sanity adjustment */
117 void xsizehints_sanity_adjust(XSizeHints *hints)
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;
129 hints->min_width=maxof(hints->min_width, 0);
130 hints->min_height=maxof(hints->min_height, 0);
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;
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);
142 hints->flags|=(PBaseSize|PMinSize);
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;
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;
159 if(!(hints->flags&PWinGravity))
160 hints->win_gravity=ForgetGravity;
164 /*}}}*/
167 /*{{{ xsizehints_adjust_for */
170 void sizehints_adjust_for(WSizeHints *hints, WRegion *reg)
172 WSizeHints tmp_hints;
174 region_size_hints(reg, &tmp_hints);
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);
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;
200 /*}}}*/
203 /*{{{ account_gravity */
206 int xgravity_deltax(int gravity, int left, int right)
208 int woff=left+right;
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;
224 return 0;
228 int xgravity_deltay(int gravity, int top, int bottom)
230 int hoff=top+bottom;
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;
246 return 0;
250 void xgravity_translate(int gravity, WRegion *reg, WRectangle *geom)
252 int top=0, left=0, bottom=0, right=0;
253 WRootWin *root;
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;
260 geom->x+=xgravity_deltax(gravity, left, right);
261 geom->y+=xgravity_deltay(gravity, top, bottom);
265 /*}}}*/
268 /*{{{ Init */
271 void xsizehints_to_sizehints(const XSizeHints *xh, WSizeHints *hints)
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;
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;
295 void sizehints_clear(WSizeHints *hints)
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;
306 /*}}}*/