aboutsummaryrefslogtreecommitdiff
path: root/src/FbWinFrame.cc
diff options
context:
space:
mode:
authorMark Tiefenbruck <mark@fluxbox.org>2008-08-15 11:16:30 (GMT)
committerMark Tiefenbruck <mark@fluxbox.org>2008-08-15 11:16:30 (GMT)
commit1dab657708cd8246c2ce5a6aaa05cc5733e09c54 (patch)
treebd5a647d38f847dce1902536441a3c8ad6222881 /src/FbWinFrame.cc
parent6053ecc1b573e437dd0d1752670748c5c3679669 (diff)
downloadfluxbox_pavel-1dab657708cd8246c2ce5a6aaa05cc5733e09c54.zip
fluxbox_pavel-1dab657708cd8246c2ce5a6aaa05cc5733e09c54.tar.bz2
aspect ratios should take base size into account, fix size hint initialization
Diffstat (limited to 'src/FbWinFrame.cc')
-rw-r--r--src/FbWinFrame.cc94
1 files changed, 57 insertions, 37 deletions
diff --git a/src/FbWinFrame.cc b/src/FbWinFrame.cc
index d044dd7..eb8510e 100644
--- a/src/FbWinFrame.cc
+++ b/src/FbWinFrame.cc
@@ -1689,6 +1689,14 @@ void closestPointToAspect(unsigned int &ret_x, unsigned int &ret_y,
1689 ret_y = static_cast<unsigned int>(u * aspect_y); 1689 ret_y = static_cast<unsigned int>(u * aspect_y);
1690} 1690}
1691 1691
1692unsigned int increaseToMultiple(unsigned int val, unsigned int inc) {
1693 return val % inc ? val + inc - (val % inc) : val;
1694}
1695
1696unsigned int decreaseToMultiple(unsigned int val, unsigned int inc) {
1697 return val % inc ? val - (val % inc) : val;
1698}
1699
1692/** 1700/**
1693 * Changes width and height to the nearest (lower) value 1701 * Changes width and height to the nearest (lower) value
1694 * that conforms to it's size hints. 1702 * that conforms to it's size hints.
@@ -1700,12 +1708,7 @@ void closestPointToAspect(unsigned int &ret_x, unsigned int &ret_y,
1700 * See ICCCM section 4.1.2.3 1708 * See ICCCM section 4.1.2.3
1701 */ 1709 */
1702void FbWinFrame::SizeHints::apply(unsigned int &width, unsigned int &height, 1710void FbWinFrame::SizeHints::apply(unsigned int &width, unsigned int &height,
1703 bool maximizing) const { 1711 bool make_fit) const {
1704
1705 // we apply aspect ratios before incrementals
1706 // Too difficult to exactly satisfy both incremental+aspect
1707 // in most situations
1708 // (they really shouldn't happen at the same time anyway).
1709 1712
1710 /* aspect ratios are applied exclusive to the base size 1713 /* aspect ratios are applied exclusive to the base size
1711 * 1714 *
@@ -1713,8 +1716,6 @@ void FbWinFrame::SizeHints::apply(unsigned int &width, unsigned int &height,
1713 * ------------ < ------- < ------------ 1716 * ------------ < ------- < ------------
1714 * min_aspect_y height max_aspect_y 1717 * min_aspect_y height max_aspect_y
1715 * 1718 *
1716 * beware of integer maximum (so I'll use doubles instead and divide)
1717 *
1718 * The trick is how to get back to the aspect ratio with minimal 1719 * The trick is how to get back to the aspect ratio with minimal
1719 * change - do we modify x, y or both? 1720 * change - do we modify x, y or both?
1720 * A: we minimise the distance between the current point, and 1721 * A: we minimise the distance between the current point, and
@@ -1722,43 +1723,62 @@ void FbWinFrame::SizeHints::apply(unsigned int &width, unsigned int &height,
1722 * Consider that the aspect ratio is a line, and the current 1723 * Consider that the aspect ratio is a line, and the current
1723 * w/h is a point, so we're just using the formula for 1724 * w/h is a point, so we're just using the formula for
1724 * shortest distance from a point to a line! 1725 * shortest distance from a point to a line!
1725 *
1726 * When maximizing, we must not increase any of the sizes, because we
1727 * would end up with the window partly off a screen, so a simpler formula
1728 * is used in that case.
1729 */ 1726 */
1730 1727
1731 if (min_aspect_y > 0 && width*min_aspect_y < min_aspect_x*height) { 1728 // make respective to base_size
1732 if (maximizing) 1729 unsigned int w = width - base_width, h = height - base_height;
1733 height = width * min_aspect_y / min_aspect_x; 1730
1734 else 1731 if (min_aspect_y > 0 && w * min_aspect_y < min_aspect_x * h) {
1735 closestPointToAspect(width, height, width, height, 1732 closestPointToAspect(w, h, w, h, min_aspect_x, min_aspect_y);
1736 min_aspect_x, min_aspect_y); 1733 // new w must be > old w, new h must be < old h
1737 } else if (max_aspect_x > 0 && width*max_aspect_y > max_aspect_x*height) { 1734 w = increaseToMultiple(w, width_inc);
1738 if (maximizing) 1735 h = decreaseToMultiple(h, height_inc);
1739 width = height * max_aspect_x / max_aspect_y; 1736 } else if (max_aspect_x > 0 && w * max_aspect_y > max_aspect_x * h) {
1740 else 1737 closestPointToAspect(w, h, w, h, max_aspect_x, max_aspect_y);
1741 closestPointToAspect(width, height, width, height, 1738 // new w must be < old w, new h must be > old h
1742 max_aspect_x, max_aspect_y); 1739 w = decreaseToMultiple(w, width_inc);
1740 h = increaseToMultiple(h, height_inc);
1743 } 1741 }
1744 1742
1745 // Check minimum size 1743 // Check minimum size
1746 if (width < min_width) 1744 if (w + base_width < min_width) {
1747 width = min_width; 1745 w = increaseToMultiple(min_width - base_width, width_inc);
1746 // need to check maximum aspect again
1747 if (max_aspect_x > 0 && w * max_aspect_y > max_aspect_x * h)
1748 h = increaseToMultiple(w * max_aspect_y / max_aspect_x, height_inc);
1749 }
1750
1751 if (h + base_height < min_height) {
1752 h = increaseToMultiple(min_height - base_height, height_inc);
1753 // need to check minimum aspect again
1754 if (min_aspect_y > 0 && w * min_aspect_y < min_aspect_x * h)
1755 w = increaseToMultiple(h * min_aspect_x / min_aspect_y, width_inc);
1756 }
1748 1757
1749 if (height < min_height) 1758 unsigned int max_w = make_fit && (width < max_width || max_width == 0) ?
1750 height = min_height; 1759 width : max_width;
1760 unsigned int max_h = make_fit && (height < max_height || max_height == 0) ?
1761 height : max_height;
1751 1762
1752 // Check maximum size 1763 // Check maximum size
1753 if (max_width > 0 && width > max_width) 1764 if (max_w > 0 && w + base_width > max_w)
1754 width = max_width; 1765 w = max_w - base_width;
1766
1767 if (max_h > 0 && h + base_height > max_h)
1768 h = max_h - base_height;
1769
1770 w = decreaseToMultiple(w, width_inc);
1771 h = decreaseToMultiple(h, height_inc);
1772
1773 // need to check aspects one more time
1774 if (min_aspect_y > 0 && w * min_aspect_y < min_aspect_x * h)
1775 h = decreaseToMultiple(w * min_aspect_y / min_aspect_x, height_inc);
1755 1776
1756 if (max_height > 0 && height > max_height) 1777 if (max_aspect_x > 0 && w * max_aspect_y > max_aspect_x * h)
1757 height = max_height; 1778 w = decreaseToMultiple(h * max_aspect_x / max_aspect_y, width_inc);
1758 1779
1759 // enforce incremental size limits, wrt base size 1780 width = w + base_width;
1760 width -= (width - base_width) % width_inc; 1781 height = h + base_height;
1761 height -= (height - base_height) % height_inc;
1762} 1782}
1763 1783
1764// check if the given width and height satisfy the size hints 1784// 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 {
1775 if ((h - base_height) % height_inc != 0) 1795 if ((h - base_height) % height_inc != 0)
1776 return false; 1796 return false;
1777 1797
1778 if (min_aspect_x * h > w * min_aspect_y) 1798 if (min_aspect_x * (h - base_height) > (w - base_width) * min_aspect_y)
1779 return false; 1799 return false;
1780 1800
1781 if (max_aspect_x * h < w * max_aspect_y) 1801 if (max_aspect_x * (h - base_height) < (w - base_width) * max_aspect_y)
1782 return false; 1802 return false;
1783 1803
1784 return true; 1804 return true;