aspect ratios should take base size into account, fix size hint initialization
This commit is contained in:
parent
6053ecc1b5
commit
1dab657708
2 changed files with 109 additions and 105 deletions
|
@ -1689,6 +1689,14 @@ void closestPointToAspect(unsigned int &ret_x, unsigned int &ret_y,
|
||||||
ret_y = static_cast<unsigned int>(u * aspect_y);
|
ret_y = static_cast<unsigned int>(u * aspect_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int increaseToMultiple(unsigned int val, unsigned int inc) {
|
||||||
|
return val % inc ? val + inc - (val % inc) : val;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int decreaseToMultiple(unsigned int val, unsigned int inc) {
|
||||||
|
return val % inc ? val - (val % inc) : val;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes width and height to the nearest (lower) value
|
* Changes width and height to the nearest (lower) value
|
||||||
* that conforms to it's size hints.
|
* that conforms to it's size hints.
|
||||||
|
@ -1700,12 +1708,7 @@ void closestPointToAspect(unsigned int &ret_x, unsigned int &ret_y,
|
||||||
* See ICCCM section 4.1.2.3
|
* See ICCCM section 4.1.2.3
|
||||||
*/
|
*/
|
||||||
void FbWinFrame::SizeHints::apply(unsigned int &width, unsigned int &height,
|
void FbWinFrame::SizeHints::apply(unsigned int &width, unsigned int &height,
|
||||||
bool maximizing) const {
|
bool make_fit) const {
|
||||||
|
|
||||||
// we apply aspect ratios before incrementals
|
|
||||||
// Too difficult to exactly satisfy both incremental+aspect
|
|
||||||
// in most situations
|
|
||||||
// (they really shouldn't happen at the same time anyway).
|
|
||||||
|
|
||||||
/* aspect ratios are applied exclusive to the base size
|
/* aspect ratios are applied exclusive to the base size
|
||||||
*
|
*
|
||||||
|
@ -1713,8 +1716,6 @@ void FbWinFrame::SizeHints::apply(unsigned int &width, unsigned int &height,
|
||||||
* ------------ < ------- < ------------
|
* ------------ < ------- < ------------
|
||||||
* min_aspect_y height max_aspect_y
|
* min_aspect_y height max_aspect_y
|
||||||
*
|
*
|
||||||
* beware of integer maximum (so I'll use doubles instead and divide)
|
|
||||||
*
|
|
||||||
* The trick is how to get back to the aspect ratio with minimal
|
* The trick is how to get back to the aspect ratio with minimal
|
||||||
* change - do we modify x, y or both?
|
* change - do we modify x, y or both?
|
||||||
* A: we minimise the distance between the current point, and
|
* A: we minimise the distance between the current point, and
|
||||||
|
@ -1722,43 +1723,62 @@ void FbWinFrame::SizeHints::apply(unsigned int &width, unsigned int &height,
|
||||||
* Consider that the aspect ratio is a line, and the current
|
* Consider that the aspect ratio is a line, and the current
|
||||||
* w/h is a point, so we're just using the formula for
|
* w/h is a point, so we're just using the formula for
|
||||||
* shortest distance from a point to a line!
|
* shortest distance from a point to a line!
|
||||||
*
|
|
||||||
* When maximizing, we must not increase any of the sizes, because we
|
|
||||||
* would end up with the window partly off a screen, so a simpler formula
|
|
||||||
* is used in that case.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (min_aspect_y > 0 && width*min_aspect_y < min_aspect_x*height) {
|
// make respective to base_size
|
||||||
if (maximizing)
|
unsigned int w = width - base_width, h = height - base_height;
|
||||||
height = width * min_aspect_y / min_aspect_x;
|
|
||||||
else
|
if (min_aspect_y > 0 && w * min_aspect_y < min_aspect_x * h) {
|
||||||
closestPointToAspect(width, height, width, height,
|
closestPointToAspect(w, h, w, h, min_aspect_x, min_aspect_y);
|
||||||
min_aspect_x, min_aspect_y);
|
// new w must be > old w, new h must be < old h
|
||||||
} else if (max_aspect_x > 0 && width*max_aspect_y > max_aspect_x*height) {
|
w = increaseToMultiple(w, width_inc);
|
||||||
if (maximizing)
|
h = decreaseToMultiple(h, height_inc);
|
||||||
width = height * max_aspect_x / max_aspect_y;
|
} else if (max_aspect_x > 0 && w * max_aspect_y > max_aspect_x * h) {
|
||||||
else
|
closestPointToAspect(w, h, w, h, max_aspect_x, max_aspect_y);
|
||||||
closestPointToAspect(width, height, width, height,
|
// new w must be < old w, new h must be > old h
|
||||||
max_aspect_x, max_aspect_y);
|
w = decreaseToMultiple(w, width_inc);
|
||||||
|
h = increaseToMultiple(h, height_inc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check minimum size
|
// Check minimum size
|
||||||
if (width < min_width)
|
if (w + base_width < min_width) {
|
||||||
width = min_width;
|
w = increaseToMultiple(min_width - base_width, width_inc);
|
||||||
|
// need to check maximum aspect again
|
||||||
|
if (max_aspect_x > 0 && w * max_aspect_y > max_aspect_x * h)
|
||||||
|
h = increaseToMultiple(w * max_aspect_y / max_aspect_x, height_inc);
|
||||||
|
}
|
||||||
|
|
||||||
if (height < min_height)
|
if (h + base_height < min_height) {
|
||||||
height = min_height;
|
h = increaseToMultiple(min_height - base_height, height_inc);
|
||||||
|
// need to check minimum aspect again
|
||||||
|
if (min_aspect_y > 0 && w * min_aspect_y < min_aspect_x * h)
|
||||||
|
w = increaseToMultiple(h * min_aspect_x / min_aspect_y, width_inc);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int max_w = make_fit && (width < max_width || max_width == 0) ?
|
||||||
|
width : max_width;
|
||||||
|
unsigned int max_h = make_fit && (height < max_height || max_height == 0) ?
|
||||||
|
height : max_height;
|
||||||
|
|
||||||
// Check maximum size
|
// Check maximum size
|
||||||
if (max_width > 0 && width > max_width)
|
if (max_w > 0 && w + base_width > max_w)
|
||||||
width = max_width;
|
w = max_w - base_width;
|
||||||
|
|
||||||
if (max_height > 0 && height > max_height)
|
if (max_h > 0 && h + base_height > max_h)
|
||||||
height = max_height;
|
h = max_h - base_height;
|
||||||
|
|
||||||
// enforce incremental size limits, wrt base size
|
w = decreaseToMultiple(w, width_inc);
|
||||||
width -= (width - base_width) % width_inc;
|
h = decreaseToMultiple(h, height_inc);
|
||||||
height -= (height - base_height) % height_inc;
|
|
||||||
|
// need to check aspects one more time
|
||||||
|
if (min_aspect_y > 0 && w * min_aspect_y < min_aspect_x * h)
|
||||||
|
h = decreaseToMultiple(w * min_aspect_y / min_aspect_x, height_inc);
|
||||||
|
|
||||||
|
if (max_aspect_x > 0 && w * max_aspect_y > max_aspect_x * h)
|
||||||
|
w = decreaseToMultiple(h * max_aspect_x / max_aspect_y, width_inc);
|
||||||
|
|
||||||
|
width = w + base_width;
|
||||||
|
height = h + base_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the given width and height satisfy the size hints
|
// check if the given width and height satisfy the size hints
|
||||||
|
@ -1775,10 +1795,10 @@ bool FbWinFrame::SizeHints::valid(unsigned int w, unsigned int h) const {
|
||||||
if ((h - base_height) % height_inc != 0)
|
if ((h - base_height) % height_inc != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (min_aspect_x * h > w * min_aspect_y)
|
if (min_aspect_x * (h - base_height) > (w - base_width) * min_aspect_y)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (max_aspect_x * h < w * max_aspect_y)
|
if (max_aspect_x * (h - base_height) < (w - base_width) * max_aspect_y)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
120
src/WinClient.cc
120
src/WinClient.cc
|
@ -82,14 +82,6 @@ WinClient::WinClient(Window win, BScreen &screen, FluxboxWindow *fbwin):
|
||||||
m_mwm_hint(0),
|
m_mwm_hint(0),
|
||||||
m_strut(0) {
|
m_strut(0) {
|
||||||
|
|
||||||
m_size_hints.min_width = m_size_hints.min_height =
|
|
||||||
m_size_hints.width_inc = m_size_hints.height_inc =
|
|
||||||
m_size_hints.base_width = m_size_hints.base_height = 1;
|
|
||||||
|
|
||||||
m_size_hints.max_width = m_size_hints.max_height =
|
|
||||||
m_size_hints.min_aspect_x = m_size_hints.min_aspect_y =
|
|
||||||
m_size_hints.max_aspect_x = m_size_hints.max_aspect_y = 0;
|
|
||||||
|
|
||||||
updateWMProtocols();
|
updateWMProtocols();
|
||||||
updateMWMHints();
|
updateMWMHints();
|
||||||
updateWMHints();
|
updateWMHints();
|
||||||
|
@ -471,73 +463,65 @@ void WinClient::updateWMHints() {
|
||||||
void WinClient::updateWMNormalHints() {
|
void WinClient::updateWMNormalHints() {
|
||||||
long icccm_mask;
|
long icccm_mask;
|
||||||
XSizeHints sizehint;
|
XSizeHints sizehint;
|
||||||
if (! XGetWMNormalHints(display(), window(), &sizehint, &icccm_mask)) {
|
if (!XGetWMNormalHints(display(), window(), &sizehint, &icccm_mask))
|
||||||
m_size_hints.min_width = m_size_hints.min_height =
|
sizehint.flags = 0;
|
||||||
m_size_hints.base_width = m_size_hints.base_height =
|
|
||||||
m_size_hints.width_inc = m_size_hints.height_inc = 1;
|
normal_hint_flags = sizehint.flags;
|
||||||
|
|
||||||
|
if (sizehint.flags & PMinSize) {
|
||||||
|
m_size_hints.min_width = sizehint.min_width;
|
||||||
|
m_size_hints.min_height = sizehint.min_height;
|
||||||
|
} else
|
||||||
|
m_size_hints.min_width = m_size_hints.min_height = 1;
|
||||||
|
|
||||||
|
if (sizehint.flags & PBaseSize) {
|
||||||
|
m_size_hints.base_width = sizehint.base_width;
|
||||||
|
m_size_hints.base_height = sizehint.base_height;
|
||||||
|
if (!(sizehint.flags & PMinSize)) {
|
||||||
|
m_size_hints.min_width = m_size_hints.base_width;
|
||||||
|
m_size_hints.min_height = m_size_hints.base_height;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
m_size_hints.base_width = m_size_hints.base_height = 0;
|
||||||
|
|
||||||
|
if (sizehint.flags & PMaxSize) {
|
||||||
|
m_size_hints.max_width = sizehint.max_width;
|
||||||
|
m_size_hints.max_height = sizehint.max_height;
|
||||||
|
} else {
|
||||||
m_size_hints.max_width = 0; // unbounded
|
m_size_hints.max_width = 0; // unbounded
|
||||||
m_size_hints.max_height = 0;
|
m_size_hints.max_height = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sizehint.flags & PResizeInc) {
|
||||||
|
m_size_hints.width_inc = sizehint.width_inc;
|
||||||
|
m_size_hints.height_inc = sizehint.height_inc;
|
||||||
|
} else
|
||||||
|
m_size_hints.width_inc = m_size_hints.height_inc = 1;
|
||||||
|
|
||||||
|
if (sizehint.flags & PAspect) {
|
||||||
|
m_size_hints.min_aspect_x = sizehint.min_aspect.x;
|
||||||
|
m_size_hints.min_aspect_y = sizehint.min_aspect.y;
|
||||||
|
m_size_hints.max_aspect_x = sizehint.max_aspect.x;
|
||||||
|
m_size_hints.max_aspect_y = sizehint.max_aspect.y;
|
||||||
|
} else
|
||||||
m_size_hints.min_aspect_x = m_size_hints.min_aspect_y =
|
m_size_hints.min_aspect_x = m_size_hints.min_aspect_y =
|
||||||
m_size_hints.max_aspect_x = m_size_hints.max_aspect_y = 0;
|
m_size_hints.max_aspect_x = m_size_hints.max_aspect_y = 0;
|
||||||
|
|
||||||
|
if (sizehint.flags & PWinGravity)
|
||||||
|
m_win_gravity = sizehint.win_gravity;
|
||||||
|
else
|
||||||
m_win_gravity = NorthWestGravity;
|
m_win_gravity = NorthWestGravity;
|
||||||
} else {
|
|
||||||
normal_hint_flags = sizehint.flags;
|
|
||||||
|
|
||||||
if (sizehint.flags & PMinSize) {
|
// some sanity checks
|
||||||
m_size_hints.min_width = sizehint.min_width;
|
if (m_size_hints.width_inc == 0)
|
||||||
m_size_hints.min_height = sizehint.min_height;
|
m_size_hints.width_inc = 1;
|
||||||
if (!(sizehint.flags & PBaseSize)) {
|
if (m_size_hints.height_inc == 0)
|
||||||
m_size_hints.base_width = m_size_hints.min_width;
|
m_size_hints.height_inc = 1;
|
||||||
m_size_hints.base_height = m_size_hints.min_height;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
m_size_hints.min_width = m_size_hints.min_height = 1;
|
|
||||||
m_size_hints.base_width = m_size_hints.base_height = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sizehint.flags & PBaseSize) {
|
if (m_size_hints.base_width > m_size_hints.min_width)
|
||||||
m_size_hints.base_width = sizehint.base_width;
|
m_size_hints.min_width = m_size_hints.base_width;
|
||||||
m_size_hints.base_height = sizehint.base_height;
|
if (m_size_hints.base_height > m_size_hints.min_height)
|
||||||
if (!(sizehint.flags & PMinSize)) {
|
m_size_hints.min_height = m_size_hints.base_height;
|
||||||
m_size_hints.min_width = m_size_hints.base_width;
|
|
||||||
m_size_hints.min_height = m_size_hints.base_height;
|
|
||||||
}
|
|
||||||
} // default set in PMinSize
|
|
||||||
|
|
||||||
if (sizehint.flags & PMaxSize) {
|
|
||||||
m_size_hints.max_width = sizehint.max_width;
|
|
||||||
m_size_hints.max_height = sizehint.max_height;
|
|
||||||
} else {
|
|
||||||
m_size_hints.max_width = 0; // unbounded
|
|
||||||
m_size_hints.max_height = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sizehint.flags & PResizeInc) {
|
|
||||||
m_size_hints.width_inc = sizehint.width_inc;
|
|
||||||
m_size_hints.height_inc = sizehint.height_inc;
|
|
||||||
} else
|
|
||||||
m_size_hints.width_inc = m_size_hints.height_inc = 1;
|
|
||||||
|
|
||||||
if (m_size_hints.width_inc == 0)
|
|
||||||
m_size_hints.width_inc = 1;
|
|
||||||
if (m_size_hints.height_inc == 0)
|
|
||||||
m_size_hints.height_inc = 1;
|
|
||||||
|
|
||||||
if (sizehint.flags & PAspect) {
|
|
||||||
m_size_hints.min_aspect_x = sizehint.min_aspect.x;
|
|
||||||
m_size_hints.min_aspect_y = sizehint.min_aspect.y;
|
|
||||||
m_size_hints.max_aspect_x = sizehint.max_aspect.x;
|
|
||||||
m_size_hints.max_aspect_y = sizehint.max_aspect.y;
|
|
||||||
} else
|
|
||||||
m_size_hints.min_aspect_x = m_size_hints.min_aspect_y =
|
|
||||||
m_size_hints.max_aspect_x = m_size_hints.max_aspect_y = 0;
|
|
||||||
|
|
||||||
if (sizehint.flags & PWinGravity)
|
|
||||||
m_win_gravity = sizehint.win_gravity;
|
|
||||||
else
|
|
||||||
m_win_gravity = NorthWestGravity;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Window WinClient::getGroupLeftWindow() const {
|
Window WinClient::getGroupLeftWindow() const {
|
||||||
|
|
Loading…
Reference in a new issue