windowmaker-wl/src/geom.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;
}