162 lines
3.8 KiB
C
162 lines
3.8 KiB
C
|
/*
|
||
|
FvwmButtons v2.0.41-plural-Z-alpha, copyright 1996, Jarl Totland
|
||
|
|
||
|
* This module, and the entire GoodStuff program, and the concept for
|
||
|
* interfacing this module to the Window Manager, are all original work
|
||
|
* by Robert Nation
|
||
|
*
|
||
|
* Copyright 1993, Robert Nation. No guarantees or warantees or anything
|
||
|
* are provided or implied in any way whatsoever. Use this program at your
|
||
|
* own risk. Permission to use this program for any purpose is given,
|
||
|
* as long as the copyright is kept intact.
|
||
|
|
||
|
*/
|
||
|
|
||
|
#include "misc.h"
|
||
|
|
||
|
/**
|
||
|
*** ConstrainSize()
|
||
|
*** Adjust a given width and height to account for the constraints imposed by
|
||
|
*** size hints.
|
||
|
*** The general algorithm, especially the aspect ratio stuff, is borrowed from
|
||
|
*** uwm's CheckConsistency routine.
|
||
|
**/
|
||
|
void ConstrainSize (XSizeHints *hints, int *widthp, int *heightp)
|
||
|
{
|
||
|
#define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
|
||
|
|
||
|
int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta;
|
||
|
int baseWidth, baseHeight;
|
||
|
int dwidth = *widthp, dheight = *heightp;
|
||
|
|
||
|
if(hints->flags & PMinSize)
|
||
|
{
|
||
|
minWidth = hints->min_width;
|
||
|
minHeight = hints->min_height;
|
||
|
if(hints->flags & PBaseSize)
|
||
|
{
|
||
|
baseWidth = hints->base_width;
|
||
|
baseHeight = hints->base_height;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
baseWidth = hints->min_width;
|
||
|
baseHeight = hints->min_height;
|
||
|
}
|
||
|
}
|
||
|
else if(hints->flags & PBaseSize)
|
||
|
{
|
||
|
minWidth = hints->base_width;
|
||
|
minHeight = hints->base_height;
|
||
|
baseWidth = hints->base_width;
|
||
|
baseHeight = hints->base_height;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
minWidth = 1;
|
||
|
minHeight = 1;
|
||
|
baseWidth = 1;
|
||
|
baseHeight = 1;
|
||
|
}
|
||
|
|
||
|
if(hints->flags & PMaxSize)
|
||
|
{
|
||
|
maxWidth = hints->max_width;
|
||
|
maxHeight = hints->max_height;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
maxWidth = 10000;
|
||
|
maxHeight = 10000;
|
||
|
}
|
||
|
if(hints->flags & PResizeInc)
|
||
|
{
|
||
|
xinc = hints->width_inc;
|
||
|
yinc = hints->height_inc;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
xinc = 1;
|
||
|
yinc = 1;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* First, clamp to min and max values
|
||
|
*/
|
||
|
if (dwidth < minWidth) dwidth = minWidth;
|
||
|
if (dheight < minHeight) dheight = minHeight;
|
||
|
|
||
|
if (dwidth > maxWidth) dwidth = maxWidth;
|
||
|
if (dheight > maxHeight) dheight = maxHeight;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Second, fit to base + N * inc
|
||
|
*/
|
||
|
dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth;
|
||
|
dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Third, adjust for aspect ratio
|
||
|
*/
|
||
|
#define maxAspectX hints->max_aspect.x
|
||
|
#define maxAspectY hints->max_aspect.y
|
||
|
#define minAspectX hints->min_aspect.x
|
||
|
#define minAspectY hints->min_aspect.y
|
||
|
/*
|
||
|
* The math looks like this:
|
||
|
*
|
||
|
* minAspectX dwidth maxAspectX
|
||
|
* ---------- <= ------- <= ----------
|
||
|
* minAspectY dheight maxAspectY
|
||
|
*
|
||
|
* If that is multiplied out, then the width and height are
|
||
|
* invalid in the following situations:
|
||
|
*
|
||
|
* minAspectX * dheight > minAspectY * dwidth
|
||
|
* maxAspectX * dheight < maxAspectY * dwidth
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
if (hints->flags & PAspect)
|
||
|
{
|
||
|
if (minAspectX * dheight > minAspectY * dwidth)
|
||
|
{
|
||
|
delta = makemult(minAspectX * dheight / minAspectY - dwidth,
|
||
|
xinc);
|
||
|
if (dwidth + delta <= maxWidth)
|
||
|
dwidth += delta;
|
||
|
else
|
||
|
{
|
||
|
delta = makemult(dheight - dwidth*minAspectY/minAspectX,
|
||
|
yinc);
|
||
|
if (dheight - delta >= minHeight) dheight -= delta;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (maxAspectX * dheight < maxAspectY * dwidth)
|
||
|
{
|
||
|
delta = makemult(dwidth * maxAspectY / maxAspectX - dheight,
|
||
|
yinc);
|
||
|
if (dheight + delta <= maxHeight)
|
||
|
dheight += delta;
|
||
|
else
|
||
|
{
|
||
|
delta = makemult(dwidth - maxAspectX*dheight/maxAspectY,
|
||
|
xinc);
|
||
|
if (dwidth - delta >= minWidth) dwidth -= delta;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*widthp = dwidth;
|
||
|
*heightp = dheight;
|
||
|
return;
|
||
|
#undef makemult
|
||
|
#undef maxAspectX
|
||
|
#undef maxAspectY
|
||
|
#undef minAspectX
|
||
|
#undef minAspectY
|
||
|
}
|