2 * ion/ioncore/sizehint.c
4 * Copyright (c) Tuomo Valkonen 1999-2007.
6 * Ion is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
13 #include <libtu/minmax.h>
23 /*{{{ xsizehints_correct */
26 static void do_correct_aspect(int max_w, int max_h, int ax, int ay,
33 if(max_h>0 && h>max_h){
39 if(max_w>0 && w>max_w){
50 static void correct_aspect(int max_w, int max_h, const WSizeHints *hints,
53 if(!hints->aspect_set)
56 if(*wret*hints->max_aspect.y>*hret*hints->max_aspect.x){
57 do_correct_aspect(max_w, max_h,
58 hints->min_aspect.x, hints->min_aspect.y,
62 if(*wret*hints->min_aspect.y<*hret*hints->min_aspect.x){
63 do_correct_aspect(max_w, max_h,
64 hints->max_aspect.x, hints->max_aspect.y,
70 void sizehints_correct(const WSizeHints *hints, int *wp, int *hp,
71 bool min, bool override_no_constrain)
78 w=maxof(w, hints->min_width);
79 h=maxof(h, hints->min_height);
82 if(hints->no_constrain && !override_no_constrain){
88 if(w>=hints->min_width && h>=hints->min_height)
89 correct_aspect(w, h, hints, &w, &h);
92 w=minof(w, hints->max_width);
93 h=minof(h, hints->max_height);
97 /* base size should be set to 0 if none given by user program */
98 bs=(hints->base_set ? hints->base_width : 0);
100 w=((w-bs)/hints->width_inc)*hints->width_inc+bs;
101 bs=(hints->base_set ? hints->base_height : 0);
103 h=((h-bs)/hints->height_inc)*hints->height_inc+bs;
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;
129 if(hints->min_width<0)
131 if(hints->min_height<0)
134 if(!(hints->flags&PBaseSize) || hints->base_width<0)
135 hints->base_width=hints->min_width;
136 if(!(hints->flags&PBaseSize) || hints->base_height<0)
137 hints->base_height=hints->min_height;
140 if(hints->flags&PMaxSize){
141 if(hints->max_width<hints->min_width)
142 hints->max_width=hints->min_width;
143 if(hints->max_height<hints->min_height)
144 hints->max_height=hints->min_height;
147 hints->flags|=(PBaseSize|PMinSize);
149 if(hints->flags&PResizeInc){
150 if(hints->width_inc<=0 || hints->height_inc<=0){
151 warn(TR("Invalid client-supplied width/height increment."));
152 hints->flags&=~PResizeInc;
156 if(hints->flags&PAspect){
157 if(hints->min_aspect.x<=0 || hints->min_aspect.y<=0 ||
158 hints->min_aspect.x<=0 || hints->min_aspect.y<=0){
159 warn(TR("Invalid client-supplied aspect-ratio."));
160 hints->flags&=~PAspect;
164 if(!(hints->flags&PWinGravity))
165 hints->win_gravity=ForgetGravity;
172 /*{{{ xsizehints_adjust_for */
175 void sizehints_adjust_for(WSizeHints *hints, WRegion *reg)
177 WSizeHints tmp_hints;
179 region_size_hints(reg, &tmp_hints);
181 if(tmp_hints.min_set){
184 hints->min_width=tmp_hints.min_width;
185 hints->min_height=tmp_hints.min_height;
187 hints->min_width=maxof(hints->min_width,
188 tmp_hints.min_width);
189 hints->min_height=maxof(hints->min_height,
190 tmp_hints.min_height);
194 if(tmp_hints.max_set && hints->max_set){
195 hints->max_width=maxof(hints->max_width,
196 tmp_hints.max_width);
197 hints->max_height=maxof(hints->max_height,
198 tmp_hints.max_height);
200 hints->max_set=FALSE;
208 /*{{{ account_gravity */
211 int xgravity_deltax(int gravity, int left, int right)
215 if(gravity==StaticGravity || gravity==ForgetGravity){
217 }else if(gravity==NorthWestGravity || gravity==WestGravity ||
218 gravity==SouthWestGravity){
220 }else if(gravity==NorthEastGravity || gravity==EastGravity ||
221 gravity==SouthEastGravity){
222 /* geom->x=geom->w+geom->x-(geom->w+woff) */
224 }else if(gravity==CenterGravity || gravity==NorthGravity ||
225 gravity==SouthGravity){
226 /* geom->x=geom->x+geom->w/2-(geom->w+woff)/2 */
233 int xgravity_deltay(int gravity, int top, int bottom)
237 if(gravity==StaticGravity || gravity==ForgetGravity){
239 }else if(gravity==NorthWestGravity || gravity==NorthGravity ||
240 gravity==NorthEastGravity){
242 }else if(gravity==SouthWestGravity || gravity==SouthGravity ||
243 gravity==SouthEastGravity){
244 /* geom->y=geom->y+geom->h-(geom->h+hoff) */
246 }else if(gravity==CenterGravity || gravity==WestGravity ||
247 gravity==EastGravity){
248 /* geom->y=geom->y+geom->h/2-(geom->h+hoff)/2 */
255 void xgravity_translate(int gravity, WRegion *reg, WRectangle *geom)
257 int top=0, left=0, bottom=0, right=0;
260 root=region_rootwin_of(reg);
261 region_rootpos(reg, &left, &top);
262 right=REGION_GEOM(root).w-left-REGION_GEOM(reg).w;
263 bottom=REGION_GEOM(root).h-top-REGION_GEOM(reg).h;
265 geom->x+=xgravity_deltax(gravity, left, right);
266 geom->y+=xgravity_deltay(gravity, top, bottom);
276 void xsizehints_to_sizehints(const XSizeHints *xh, WSizeHints *hints)
278 hints->max_width=xh->max_width;
279 hints->max_height=xh->max_height;
280 hints->min_width=xh->min_width;
281 hints->min_height=xh->min_height;
282 hints->base_width=xh->base_width;
283 hints->base_height=xh->base_height;
284 hints->width_inc=xh->width_inc;
285 hints->height_inc=xh->height_inc;
286 hints->min_aspect.x=xh->min_aspect.x;
287 hints->min_aspect.y=xh->min_aspect.y;
288 hints->max_aspect.x=xh->max_aspect.x;
289 hints->max_aspect.y=xh->max_aspect.y;
291 hints->max_set=((xh->flags&PMaxSize)!=0);
292 hints->min_set=((xh->flags&PMinSize)!=0);
293 hints->base_set=((xh->flags&PBaseSize)!=0);
294 hints->inc_set=((xh->flags&PResizeInc)!=0);
295 hints->aspect_set=((xh->flags&PAspect)!=0);
296 hints->no_constrain=0;
300 void sizehints_clear(WSizeHints *hints)
307 hints->no_constrain=0;