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 wa=w-hints->base_width;
89 ha=h-hints->base_height;
92 correct_aspect(wa, ha, hints, &wa, &ha);
93 w=wa+hints->base_width;
94 h=ha+hints->base_height;
98 w=minof(w, hints->max_width);
99 h=minof(h, hints->max_height);
103 /* base size should be set to 0 if none given by user program */
104 bs=(hints->base_set ? hints->base_width : 0);
106 w=((w-bs)/hints->width_inc)*hints->width_inc+bs;
107 bs=(hints->base_set ? hints->base_height : 0);
109 h=((h-bs)/hints->height_inc)*hints->height_inc+bs;
120 /*{{{ X size hints sanity adjustment */
123 void xsizehints_sanity_adjust(XSizeHints *hints)
125 if(!(hints->flags&PMinSize)){
126 if(hints->flags&PBaseSize){
127 hints->min_width=hints->base_width;
128 hints->min_height=hints->base_height;
135 if(hints->min_width<0)
137 if(hints->min_height<0)
140 if(!(hints->flags&PBaseSize) || hints->base_width<0)
142 if(!(hints->flags&PBaseSize) || hints->base_height<0)
143 hints->base_height=0;
146 if(hints->flags&PMaxSize){
147 if(hints->max_width<hints->min_width)
148 hints->max_width=hints->min_width;
149 if(hints->max_height<hints->min_height)
150 hints->max_height=hints->min_height;
153 hints->flags|=(PBaseSize|PMinSize);
155 if(hints->flags&PResizeInc){
156 if(hints->width_inc<=0 || hints->height_inc<=0){
157 warn(TR("Invalid client-supplied width/height increment."));
158 hints->flags&=~PResizeInc;
162 if(hints->flags&PAspect){
163 if(hints->min_aspect.x<=0 || hints->min_aspect.y<=0 ||
164 hints->min_aspect.x<=0 || hints->min_aspect.y<=0){
165 warn(TR("Invalid client-supplied aspect-ratio."));
166 hints->flags&=~PAspect;
170 if(!(hints->flags&PWinGravity))
171 hints->win_gravity=ForgetGravity;
178 /*{{{ xsizehints_adjust_for */
181 void sizehints_adjust_for(WSizeHints *hints, WRegion *reg)
183 WSizeHints tmp_hints;
185 region_size_hints(reg, &tmp_hints);
187 if(tmp_hints.min_set){
190 hints->min_width=tmp_hints.min_width;
191 hints->min_height=tmp_hints.min_height;
193 hints->min_width=maxof(hints->min_width,
194 tmp_hints.min_width);
195 hints->min_height=maxof(hints->min_height,
196 tmp_hints.min_height);
200 if(tmp_hints.max_set && hints->max_set){
201 hints->max_width=maxof(hints->max_width,
202 tmp_hints.max_width);
203 hints->max_height=maxof(hints->max_height,
204 tmp_hints.max_height);
206 hints->max_set=FALSE;
214 /*{{{ account_gravity */
217 int xgravity_deltax(int gravity, int left, int right)
221 if(gravity==StaticGravity || gravity==ForgetGravity){
223 }else if(gravity==NorthWestGravity || gravity==WestGravity ||
224 gravity==SouthWestGravity){
226 }else if(gravity==NorthEastGravity || gravity==EastGravity ||
227 gravity==SouthEastGravity){
228 /* geom->x=geom->w+geom->x-(geom->w+woff) */
230 }else if(gravity==CenterGravity || gravity==NorthGravity ||
231 gravity==SouthGravity){
232 /* geom->x=geom->x+geom->w/2-(geom->w+woff)/2 */
239 int xgravity_deltay(int gravity, int top, int bottom)
243 if(gravity==StaticGravity || gravity==ForgetGravity){
245 }else if(gravity==NorthWestGravity || gravity==NorthGravity ||
246 gravity==NorthEastGravity){
248 }else if(gravity==SouthWestGravity || gravity==SouthGravity ||
249 gravity==SouthEastGravity){
250 /* geom->y=geom->y+geom->h-(geom->h+hoff) */
252 }else if(gravity==CenterGravity || gravity==WestGravity ||
253 gravity==EastGravity){
254 /* geom->y=geom->y+geom->h/2-(geom->h+hoff)/2 */
261 void xgravity_translate(int gravity, WRegion *reg, WRectangle *geom)
263 int top=0, left=0, bottom=0, right=0;
266 root=region_rootwin_of(reg);
267 region_rootpos(reg, &left, &top);
268 right=REGION_GEOM(root).w-left-REGION_GEOM(reg).w;
269 bottom=REGION_GEOM(root).h-top-REGION_GEOM(reg).h;
271 geom->x+=xgravity_deltax(gravity, left, right);
272 geom->y+=xgravity_deltay(gravity, top, bottom);
282 void xsizehints_to_sizehints(const XSizeHints *xh, WSizeHints *hints)
284 hints->max_width=xh->max_width;
285 hints->max_height=xh->max_height;
286 hints->min_width=xh->min_width;
287 hints->min_height=xh->min_height;
288 hints->base_width=xh->base_width;
289 hints->base_height=xh->base_height;
290 hints->width_inc=xh->width_inc;
291 hints->height_inc=xh->height_inc;
292 hints->min_aspect.x=xh->min_aspect.x;
293 hints->min_aspect.y=xh->min_aspect.y;
294 hints->max_aspect.x=xh->max_aspect.x;
295 hints->max_aspect.y=xh->max_aspect.y;
297 hints->max_set=((xh->flags&PMaxSize)!=0);
298 hints->min_set=((xh->flags&PMinSize)!=0);
299 hints->base_set=((xh->flags&PBaseSize)!=0);
300 hints->inc_set=((xh->flags&PResizeInc)!=0);
301 hints->aspect_set=((xh->flags&PAspect)!=0);
302 hints->no_constrain=0;
306 void sizehints_clear(WSizeHints *hints)
313 hints->no_constrain=0;