summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/FbWinFrame.cc253
-rw-r--r--src/FbWinFrame.hh16
-rw-r--r--src/WinClient.cc25
-rw-r--r--src/WinClient.hh2
-rw-r--r--src/Window.cc20
5 files changed, 138 insertions, 178 deletions
diff --git a/src/FbWinFrame.cc b/src/FbWinFrame.cc
index 4734b2b..d044dd7 100644
--- a/src/FbWinFrame.cc
+++ b/src/FbWinFrame.cc
@@ -1459,138 +1459,6 @@ void FbWinFrame::applyDecorations() {
1459 frameExtentSig().notify(); 1459 frameExtentSig().notify();
1460} 1460}
1461 1461
1462/* For aspect ratios
1463 Note that its slightly simplified in that only the
1464 line gradient is given - this is because for aspect
1465 ratios, we always have the line going through the origin
1466
1467 * Based on this formula:
1468 http://astronomy.swin.edu.au/~pbourke/geometry/pointline/
1469
1470 Note that a gradient from origin goes through ( grad , 1 )
1471 */
1472
1473void closestPointToLine(double &ret_x, double &ret_y,
1474 double point_x, double point_y,
1475 double gradient) {
1476 double u = (point_x * gradient + point_y) /
1477 (gradient*gradient + 1);
1478
1479 ret_x = u*gradient;
1480 ret_y = u;
1481}
1482
1483/**
1484 * Changes width and height to the nearest (lower) value
1485 * that conforms to it's size hints.
1486 *
1487 * display_* give the values that would be displayed
1488 * to the user when resizing.
1489 * We use pointers for display_* since they are optional.
1490 *
1491 * See ICCCM section 4.1.2.3
1492 */
1493void FbWinFrame::applySizeHints(int &width, int &height,
1494 int *display_width, int *display_height,
1495 bool maximizing) {
1496
1497 int i = width, j = height;
1498
1499 // Check minimum size
1500 if (width < 0 || width < static_cast<signed>(m_size_hints.min_width))
1501 width = m_size_hints.min_width;
1502
1503 if (height < 0 || height < static_cast<signed>(m_size_hints.min_height))
1504 height = m_size_hints.min_height;
1505
1506 // Check maximum size
1507 if (m_size_hints.max_width > 0 && width > static_cast<signed>(m_size_hints.max_width))
1508 width = m_size_hints.max_width;
1509
1510 if (m_size_hints.max_height > 0 && height > static_cast<signed>(m_size_hints.max_height))
1511 height = m_size_hints.max_height;
1512
1513 // we apply aspect ratios before incrementals
1514 // Too difficult to exactly satisfy both incremental+aspect
1515 // in most situations
1516 // (they really shouldn't happen at the same time anyway).
1517
1518 /* aspect ratios are applied exclusive to the m_size_hints.base_width
1519 *
1520 * m_size_hints.min_aspect_x width m_size_hints.max_aspect_x
1521 * ------------ < ------- < ------------
1522 * m_size_hints.min_aspect_y height m_size_hints.max_aspect_y
1523 *
1524 * beware of integer maximum (so I'll use doubles instead and divide)
1525 *
1526 * The trick is how to get back to the aspect ratio with minimal
1527 * change - do we modify x, y or both?
1528 * A: we minimise the distance between the current point, and
1529 * the target aspect ratio (consider them as x,y coordinates)
1530 * Consider that the aspect ratio is a line, and the current
1531 * w/h is a point, so we're just using the formula for
1532 * shortest distance from a point to a line!
1533 *
1534 * When maximizing, we must not increase any of the sizes, because we
1535 * would end up with the window partly off a screen, so a simpler formula
1536 * is used in that case.
1537 */
1538
1539 if (m_size_hints.min_aspect_y > 0 && m_size_hints.max_aspect_y > 0 &&
1540 (height - m_size_hints.base_height) > 0) {
1541 double widthd = static_cast<double>(width - m_size_hints.base_width);
1542 double heightd = static_cast<double>(height - m_size_hints.base_height);
1543
1544 double min = static_cast<double>(m_size_hints.min_aspect_x) /
1545 static_cast<double>(m_size_hints.min_aspect_y);
1546
1547 double max = static_cast<double>(m_size_hints.max_aspect_x) /
1548 static_cast<double>(m_size_hints.max_aspect_y);
1549
1550 double actual = widthd / heightd;
1551
1552 if (max > 0 && min > 0 && actual > 0) { // don't even try otherwise
1553 bool changed = false;
1554 if (actual < min) {
1555 changed = true;
1556 if (maximizing)
1557 heightd = widthd / min;
1558 else
1559 closestPointToLine(widthd, heightd, widthd, heightd, min);
1560 } else if (actual > max) {
1561 changed = true;
1562 if (maximizing)
1563 widthd = heightd * max;
1564 else
1565 closestPointToLine(widthd, heightd, widthd, heightd, max);
1566 }
1567
1568 if (changed) {
1569 width = static_cast<int>(widthd) + m_size_hints.base_width;
1570 height = static_cast<int>(heightd) + m_size_hints.base_height;
1571 }
1572 }
1573 }
1574
1575 // enforce incremental size limits, wrt base size
1576 // only calculate this if we really need to
1577 i = (width - static_cast<signed>(m_size_hints.base_width)) /
1578 static_cast<signed>(m_size_hints.width_inc);
1579 width = i*static_cast<signed>(m_size_hints.width_inc) +
1580 static_cast<signed>(m_size_hints.base_width);
1581
1582 j = (height - static_cast<signed>(m_size_hints.base_height)) /
1583 static_cast<signed>(m_size_hints.height_inc);
1584 height = j*static_cast<signed>(m_size_hints.height_inc) +
1585 static_cast<signed>(m_size_hints.base_height);
1586
1587 if (display_width)
1588 *display_width = i;
1589
1590 if (display_height)
1591 *display_height = j;
1592}
1593
1594bool FbWinFrame::setBorderWidth(bool do_move) { 1462bool FbWinFrame::setBorderWidth(bool do_move) {
1595 unsigned int border_width = theme()->border().width(); 1463 unsigned int border_width = theme()->border().width();
1596 unsigned int win_bw = m_decoration_mask & DECORM_BORDER ? border_width : 0; 1464 unsigned int win_bw = m_decoration_mask & DECORM_BORDER ? border_width : 0;
@@ -1800,3 +1668,124 @@ int FbWinFrame::yOffset() const {
1800 return 0; 1668 return 0;
1801} 1669}
1802 1670
1671/* For aspect ratios
1672 Note that its slightly simplified in that only the
1673 line gradient is given - this is because for aspect
1674 ratios, we always have the line going through the origin
1675
1676 * Based on this formula:
1677 http://astronomy.swin.edu.au/~pbourke/geometry/pointline/
1678
1679 Note that a gradient from origin goes through ( grad , 1 )
1680 */
1681
1682void closestPointToAspect(unsigned int &ret_x, unsigned int &ret_y,
1683 unsigned int point_x, unsigned int point_y,
1684 unsigned int aspect_x, unsigned int aspect_y) {
1685 double u = static_cast<double>(point_x * aspect_x + point_y * aspect_y) /
1686 static_cast<double>(aspect_x * aspect_x + aspect_y * aspect_y);
1687
1688 ret_x = static_cast<unsigned int>(u * aspect_x);
1689 ret_y = static_cast<unsigned int>(u * aspect_y);
1690}
1691
1692/**
1693 * Changes width and height to the nearest (lower) value
1694 * that conforms to it's size hints.
1695 *
1696 * display_* give the values that would be displayed
1697 * to the user when resizing.
1698 * We use pointers for display_* since they are optional.
1699 *
1700 * See ICCCM section 4.1.2.3
1701 */
1702void FbWinFrame::SizeHints::apply(unsigned int &width, unsigned int &height,
1703 bool maximizing) 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
1710 /* aspect ratios are applied exclusive to the base size
1711 *
1712 * min_aspect_x width max_aspect_x
1713 * ------------ < ------- < ------------
1714 * min_aspect_y height max_aspect_y
1715 *
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 * change - do we modify x, y or both?
1720 * A: we minimise the distance between the current point, and
1721 * the target aspect ratio (consider them as x,y coordinates)
1722 * 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 * 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 */
1730
1731 if (min_aspect_y > 0 && width*min_aspect_y < min_aspect_x*height) {
1732 if (maximizing)
1733 height = width * min_aspect_y / min_aspect_x;
1734 else
1735 closestPointToAspect(width, height, width, height,
1736 min_aspect_x, min_aspect_y);
1737 } else if (max_aspect_x > 0 && width*max_aspect_y > max_aspect_x*height) {
1738 if (maximizing)
1739 width = height * max_aspect_x / max_aspect_y;
1740 else
1741 closestPointToAspect(width, height, width, height,
1742 max_aspect_x, max_aspect_y);
1743 }
1744
1745 // Check minimum size
1746 if (width < min_width)
1747 width = min_width;
1748
1749 if (height < min_height)
1750 height = min_height;
1751
1752 // Check maximum size
1753 if (max_width > 0 && width > max_width)
1754 width = max_width;
1755
1756 if (max_height > 0 && height > max_height)
1757 height = max_height;
1758
1759 // enforce incremental size limits, wrt base size
1760 width -= (width - base_width) % width_inc;
1761 height -= (height - base_height) % height_inc;
1762}
1763
1764// check if the given width and height satisfy the size hints
1765bool FbWinFrame::SizeHints::valid(unsigned int w, unsigned int h) const {
1766 if (w < min_width || h < min_height)
1767 return false;
1768
1769 if (w > max_width || h > max_height)
1770 return false;
1771
1772 if ((w - base_width) % width_inc != 0)
1773 return false;
1774
1775 if ((h - base_height) % height_inc != 0)
1776 return false;
1777
1778 if (min_aspect_x * h > w * min_aspect_y)
1779 return false;
1780
1781 if (max_aspect_x * h < w * max_aspect_y)
1782 return false;
1783
1784 return true;
1785}
1786
1787void FbWinFrame::SizeHints::displaySize(int &i, int &j,
1788 unsigned int width, unsigned int height) const {
1789 i = static_cast<signed>(width - base_width) / width_inc;
1790 j = static_cast<signed>(height - base_height) / height_inc;
1791}
diff --git a/src/FbWinFrame.hh b/src/FbWinFrame.hh
index d2a27c9..70f0a4c 100644
--- a/src/FbWinFrame.hh
+++ b/src/FbWinFrame.hh
@@ -96,6 +96,11 @@ public:
96 }; 96 };
97 97
98 typedef struct SizeHints { 98 typedef struct SizeHints {
99 void apply(unsigned int &w, unsigned int &h,
100 bool maximizing = false) const;
101 bool valid(unsigned int width, unsigned int height) const;
102 void displaySize(int &i, int &j,
103 unsigned int width, unsigned int height) const;
99 unsigned int min_width; 104 unsigned int min_width;
100 unsigned int max_width; 105 unsigned int max_width;
101 unsigned int min_height; 106 unsigned int min_height;
@@ -200,16 +205,7 @@ public:
200 /// remove any handler for the windows 205 /// remove any handler for the windows
201 void removeEventHandler(); 206 void removeEventHandler();
202 207
203 /** 208 const SizeHints &sizeHints() const { return m_size_hints; }
204 * Changes width and height to the nearest (lower) value
205 * that conforms to it's size hints.
206 *
207 * display_* give the values that would be displayed
208 * to the user when resizing.
209 * We use pointers for display_* since they are optional.
210 */
211 void applySizeHints(int &width, int &height, int *display_width = 0,
212 int *display_height = 0, bool maximizing = false);
213 void setSizeHints(const SizeHints &hint) { m_size_hints = hint; } 209 void setSizeHints(const SizeHints &hint) { m_size_hints = hint; }
214 210
215 void setDecorationMask(unsigned int mask) { m_decoration_mask = mask; } 211 void setDecorationMask(unsigned int mask) { m_decoration_mask = mask; }
diff --git a/src/WinClient.cc b/src/WinClient.cc
index b9602ec..f421013 100644
--- a/src/WinClient.cc
+++ b/src/WinClient.cc
@@ -690,31 +690,6 @@ void WinClient::updateWMProtocols() {
690 690
691} 691}
692 692
693// check if the given width and height satisfy the size hints
694bool WinClient::checkSizeHints(unsigned int width, unsigned int height) {
695 if (width < m_size_hints.min_width || height < m_size_hints.min_height)
696 return false;
697
698 if (width > m_size_hints.max_width || height > m_size_hints.max_height)
699 return false;
700
701 if ((width - m_size_hints.base_width) % m_size_hints.width_inc != 0)
702 return false;
703
704 if ((height - m_size_hints.base_height) % m_size_hints.height_inc != 0)
705 return false;
706
707 double ratio = (double)width / (double)height;
708
709 if (m_size_hints.min_aspect_y > 0 && (double)m_size_hints.min_aspect_x / (double)m_size_hints.min_aspect_y > ratio)
710 return false;
711
712 if (m_size_hints.max_aspect_y > 0 && (double)m_size_hints.max_aspect_x / (double)m_size_hints.max_aspect_y < ratio)
713 return false;
714
715 return true;
716}
717
718void WinClient::removeTransientFromWaitingList() { 693void WinClient::removeTransientFromWaitingList() {
719 694
720 // holds the windows that dont have empty 695 // holds the windows that dont have empty
diff --git a/src/WinClient.hh b/src/WinClient.hh
index 9c6dc9e..54c431d 100644
--- a/src/WinClient.hh
+++ b/src/WinClient.hh
@@ -81,8 +81,6 @@ public:
81 void setAttentionState(bool value); 81 void setAttentionState(bool value);
82 const std::string &title() const { return m_title; } 82 const std::string &title() const { return m_title; }
83 83
84 bool checkSizeHints(unsigned int width, unsigned int height);
85
86 void setGroupLeftWindow(Window win); 84 void setGroupLeftWindow(Window win);
87 85
88 void saveBlackboxAttribs(FluxboxWindow::BlackboxAttributes &blackbox_attribs, int nelements); 86 void saveBlackboxAttribs(FluxboxWindow::BlackboxAttributes &blackbox_attribs, int nelements);
diff --git a/src/Window.cc b/src/Window.cc
index 45c1e9d..2a2dbd9 100644
--- a/src/Window.cc
+++ b/src/Window.cc
@@ -550,9 +550,9 @@ void FluxboxWindow::init() {
550 } 550 }
551#endif // DEBUG 551#endif // DEBUG
552 552
553 int real_width = frame().width(); 553 unsigned int real_width = frame().width();
554 int real_height = frame().height() - frame().titlebarHeight() - frame().handleHeight(); 554 unsigned int real_height = frame().height() - frame().titlebarHeight() - frame().handleHeight();
555 frame().applySizeHints(real_width, real_height); 555 frame().sizeHints().apply(real_width, real_height);
556 real_height += frame().titlebarHeight() + frame().handleHeight(); 556 real_height += frame().titlebarHeight() + frame().handleHeight();
557 557
558 if (m_placed) 558 if (m_placed)
@@ -2483,12 +2483,12 @@ void FluxboxWindow::configureRequestEvent(XConfigureRequestEvent &cr) {
2483 // make sure the new width/height would be ok with all clients, or else they 2483 // make sure the new width/height would be ok with all clients, or else they
2484 // could try to resize the window back and forth 2484 // could try to resize the window back and forth
2485 if (cr.value_mask & CWWidth || cr.value_mask & CWHeight) { 2485 if (cr.value_mask & CWWidth || cr.value_mask & CWHeight) {
2486 int new_w = (cr.value_mask & CWWidth) ? cr.width : cw; 2486 unsigned int new_w = (cr.value_mask & CWWidth) ? cr.width : cw;
2487 int new_h = (cr.value_mask & CWHeight) ? cr.height : ch; 2487 unsigned int new_h = (cr.value_mask & CWHeight) ? cr.height : ch;
2488 ClientList::iterator it = clientList().begin(); 2488 ClientList::iterator it = clientList().begin();
2489 ClientList::iterator it_end = clientList().end(); 2489 ClientList::iterator it_end = clientList().end();
2490 for (; it != it_end; ++it) { 2490 for (; it != it_end; ++it) {
2491 if (*it != client && !(*it)->checkSizeHints(new_w, new_h)) 2491 if (*it != client && !(*it)->sizeHints().valid(new_w, new_h))
2492 cr.value_mask = cr.value_mask & ~(CWWidth | CWHeight); 2492 cr.value_mask = cr.value_mask & ~(CWWidth | CWHeight);
2493 } 2493 }
2494 } 2494 }
@@ -3725,12 +3725,14 @@ void FluxboxWindow::fixsize(int *user_w, int *user_h, bool maximizing) {
3725 3725
3726 // dx is new width = current width + difference between new and old x values 3726 // dx is new width = current width + difference between new and old x values
3727 //int dx = frame().width() + frame().x() - m_last_resize_x; 3727 //int dx = frame().width() + frame().x() - m_last_resize_x;
3728 int dw = m_last_resize_w; 3728 unsigned int dw = m_last_resize_w;
3729 3729
3730 // dy = new height (w/o decorations), similarly 3730 // dy = new height (w/o decorations), similarly
3731 int dh = m_last_resize_h - decoration_height; 3731 unsigned int dh = m_last_resize_h - decoration_height;
3732 3732
3733 frame().applySizeHints(dw, dh, user_w, user_h, maximizing); 3733 frame().sizeHints().apply(dw, dh, maximizing);
3734 if (user_w && user_h)
3735 frame().sizeHints().displaySize(*user_w, *user_h, dw, dh);
3734 3736
3735 // update last resize 3737 // update last resize
3736 m_last_resize_w = dw; 3738 m_last_resize_w = dw;