161 lines
4.3 KiB
C
161 lines
4.3 KiB
C
/*
|
|
* geom.c -- backend-neutral window geometry constraint functions
|
|
*
|
|
* Contains only pure geometry arithmetic: no Xlib, no display calls.
|
|
* Unit tests link this file standalone (without -lX11).
|
|
*
|
|
* Phase 5: extracted from window.c.
|
|
*/
|
|
|
|
#include "wconfig.h"
|
|
|
|
#include "WindowMaker.h" /* WPreferences, wPreferences */
|
|
#include "screen.h" /* WScreen */
|
|
#include "window.h" /* WWindow, WNormalHints */
|
|
#include "geom.h"
|
|
|
|
/*
|
|
*----------------------------------------------------------------------
|
|
* wWindowConstrainSize--
|
|
* Constrains size for the client window, taking the maximal size,
|
|
* window resize increments and other size hints into account.
|
|
*
|
|
* Returns:
|
|
* The closest size to what was given that the client window can
|
|
* have.
|
|
*
|
|
*----------------------------------------------------------------------
|
|
*/
|
|
void wWindowConstrainSize(WWindow *wwin, unsigned int *nwidth, unsigned int *nheight)
|
|
{
|
|
int width = (int)*nwidth;
|
|
int height = (int)*nheight;
|
|
int winc = 1;
|
|
int hinc = 1;
|
|
int minW = 1, minH = 1;
|
|
int maxW = wwin->screen_ptr->scr_width * 2;
|
|
int maxH = wwin->screen_ptr->scr_height * 2;
|
|
int minAX = -1, minAY = -1;
|
|
int maxAX = -1, maxAY = -1;
|
|
int baseW = 0;
|
|
int baseH = 0;
|
|
|
|
if (wwin->normal_hints) {
|
|
if (!wwin->flags.maximized) {
|
|
winc = wwin->normal_hints->width_inc;
|
|
hinc = wwin->normal_hints->height_inc;
|
|
}
|
|
if (wwin->normal_hints->min_width > minW)
|
|
minW = wwin->normal_hints->min_width;
|
|
if (wwin->normal_hints->min_height > minH)
|
|
minH = wwin->normal_hints->min_height;
|
|
if (wwin->normal_hints->max_width < maxW)
|
|
maxW = wwin->normal_hints->max_width;
|
|
if (wwin->normal_hints->max_height < maxH)
|
|
maxH = wwin->normal_hints->max_height;
|
|
|
|
if (wwin->normal_hints->flags & WNH_P_ASPECT) {
|
|
minAX = wwin->normal_hints->min_aspect.x;
|
|
minAY = wwin->normal_hints->min_aspect.y;
|
|
maxAX = wwin->normal_hints->max_aspect.x;
|
|
maxAY = wwin->normal_hints->max_aspect.y;
|
|
}
|
|
|
|
baseW = wwin->normal_hints->base_width;
|
|
baseH = wwin->normal_hints->base_height;
|
|
}
|
|
|
|
/* trust the mins provided by the client but not the maxs */
|
|
if (width < minW)
|
|
width = minW;
|
|
if (height < minH)
|
|
height = minH;
|
|
|
|
/* if only one dimension is over the top, set a default 4/3 ratio */
|
|
if (width > maxW && height < maxH)
|
|
width = height * 4 / 3;
|
|
else if(height > maxH && width < maxW)
|
|
height = width * 3 / 4;
|
|
else if(width > maxW && height > maxH) {
|
|
/* if both are over the top, set size to almost fullscreen */
|
|
height = wwin->screen_ptr->scr_height - 2 * wPreferences.icon_size;
|
|
width = wwin->screen_ptr->scr_width - 2 * wPreferences.icon_size;
|
|
}
|
|
|
|
/* aspect ratio code borrowed from olwm */
|
|
if (minAX > 0) {
|
|
/* adjust max aspect ratio */
|
|
if (!(maxAX == 1 && maxAY == 1) && width * maxAY > height * maxAX) {
|
|
if (maxAX > maxAY) {
|
|
height = (width * maxAY) / maxAX;
|
|
if (height > maxH) {
|
|
height = maxH;
|
|
width = (height * maxAX) / maxAY;
|
|
}
|
|
} else {
|
|
width = (height * maxAX) / maxAY;
|
|
if (width > maxW) {
|
|
width = maxW;
|
|
height = (width * maxAY) / maxAX;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* adjust min aspect ratio */
|
|
if (!(minAX == 1 && minAY == 1) && width * minAY < height * minAX) {
|
|
if (minAX > minAY) {
|
|
height = (width * minAY) / minAX;
|
|
if (height < minH) {
|
|
height = minH;
|
|
width = (height * minAX) / minAY;
|
|
}
|
|
} else {
|
|
width = (height * minAX) / minAY;
|
|
if (width < minW) {
|
|
width = minW;
|
|
height = (width * minAY) / minAX;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!wwin->flags.maximized) {
|
|
if (baseW != 0)
|
|
width = (((width - baseW) / winc) * winc) + baseW;
|
|
else
|
|
width = (((width - minW) / winc) * winc) + minW;
|
|
|
|
if (baseH != 0)
|
|
height = (((height - baseH) / hinc) * hinc) + baseH;
|
|
else
|
|
height = (((height - minH) / hinc) * hinc) + minH;
|
|
}
|
|
|
|
/* broken stupid apps may cause preposterous values for these.. */
|
|
if (width > 0)
|
|
*nwidth = width;
|
|
if (height > 0)
|
|
*nheight = height;
|
|
}
|
|
|
|
void wWindowCropSize(WWindow *wwin, unsigned int maxW, unsigned int maxH,
|
|
unsigned int *width, unsigned int *height)
|
|
{
|
|
int baseW = 0, baseH = 0;
|
|
int winc = 1, hinc = 1;
|
|
|
|
if (wwin->normal_hints) {
|
|
baseW = wwin->normal_hints->base_width;
|
|
baseH = wwin->normal_hints->base_height;
|
|
|
|
winc = wwin->normal_hints->width_inc;
|
|
hinc = wwin->normal_hints->height_inc;
|
|
}
|
|
|
|
if (*width > maxW)
|
|
*width = maxW - (maxW - baseW) % winc;
|
|
|
|
if (*height > maxH)
|
|
*height = maxH - (maxH - baseH) % hinc;
|
|
}
|