diff options
Diffstat (limited to 'src/FbWinFrame.cc')
-rw-r--r-- | src/FbWinFrame.cc | 303 |
1 files changed, 14 insertions, 289 deletions
diff --git a/src/FbWinFrame.cc b/src/FbWinFrame.cc index 9e7f613..1a98ff5 100644 --- a/src/FbWinFrame.cc +++ b/src/FbWinFrame.cc | |||
@@ -28,7 +28,6 @@ | |||
28 | #include "FbTk/Compose.hh" | 28 | #include "FbTk/Compose.hh" |
29 | #include "FbTk/Transparent.hh" | 29 | #include "FbTk/Transparent.hh" |
30 | #include "FbTk/CompareEqual.hh" | 30 | #include "FbTk/CompareEqual.hh" |
31 | #include "FbTk/StringUtil.hh" | ||
32 | #include "FbTk/TextUtils.hh" | 31 | #include "FbTk/TextUtils.hh" |
33 | 32 | ||
34 | #include "FbWinFrameTheme.hh" | 33 | #include "FbWinFrameTheme.hh" |
@@ -194,7 +193,7 @@ void FbWinFrame::show() { | |||
194 | Toggle shade state, and resize window | 193 | Toggle shade state, and resize window |
195 | */ | 194 | */ |
196 | void FbWinFrame::shade() { | 195 | void FbWinFrame::shade() { |
197 | if (!(m_state.deco_mask & DECORM_TITLEBAR)) | 196 | if (!(m_state.deco_mask & WindowState::DECORM_TITLEBAR)) |
198 | return; | 197 | return; |
199 | 198 | ||
200 | // toggle shade | 199 | // toggle shade |
@@ -254,7 +253,8 @@ void FbWinFrame::moveResize(int x, int y, unsigned int width, unsigned int heigh | |||
254 | m_window.resize(width, height); | 253 | m_window.resize(width, height); |
255 | } | 254 | } |
256 | 255 | ||
257 | saveGeometry(); | 256 | m_state.saveGeometry(window().x(), window().y(), |
257 | window().width(), window().height()); | ||
258 | 258 | ||
259 | if (move || (resize && m_screen.getTabPlacement() != TOPLEFT && | 259 | if (move || (resize && m_screen.getTabPlacement() != TOPLEFT && |
260 | m_screen.getTabPlacement() != LEFTTOP)) | 260 | m_screen.getTabPlacement() != LEFTTOP)) |
@@ -283,7 +283,8 @@ void FbWinFrame::moveResize(int x, int y, unsigned int width, unsigned int heigh | |||
283 | void FbWinFrame::quietMoveResize(int x, int y, | 283 | void FbWinFrame::quietMoveResize(int x, int y, |
284 | unsigned int width, unsigned int height) { | 284 | unsigned int width, unsigned int height) { |
285 | m_window.moveResize(x, y, width, height); | 285 | m_window.moveResize(x, y, width, height); |
286 | saveGeometry(); | 286 | m_state.saveGeometry(window().x(), window().y(), |
287 | window().width(), window().height()); | ||
287 | if (m_tabmode == EXTERNAL) { | 288 | if (m_tabmode == EXTERNAL) { |
288 | 289 | ||
289 | switch(m_screen.getTabPlacement()) { | 290 | switch(m_screen.getTabPlacement()) { |
@@ -534,21 +535,6 @@ void FbWinFrame::setMaximized(int value) { | |||
534 | applyState(); | 535 | applyState(); |
535 | } | 536 | } |
536 | 537 | ||
537 | void FbWinFrame::saveGeometry() { | ||
538 | if (m_state.fullscreen || m_state.maximized == MAX_FULL) | ||
539 | return; | ||
540 | |||
541 | if (!(m_state.maximized & MAX_HORZ)) { | ||
542 | m_state.x = x(); | ||
543 | m_state.width = width(); | ||
544 | } | ||
545 | if (!(m_state.maximized & MAX_VERT)) { | ||
546 | m_state.y = y(); | ||
547 | if (!m_state.shaded) | ||
548 | m_state.height = height(); | ||
549 | } | ||
550 | } | ||
551 | |||
552 | void FbWinFrame::applyState() { | 538 | void FbWinFrame::applyState() { |
553 | applyDecorations(); | 539 | applyDecorations(); |
554 | 540 | ||
@@ -556,7 +542,7 @@ void FbWinFrame::applyState() { | |||
556 | int new_x = m_state.x, new_y = m_state.y; | 542 | int new_x = m_state.x, new_y = m_state.y; |
557 | unsigned int new_w = m_state.width, new_h = m_state.height; | 543 | unsigned int new_w = m_state.width, new_h = m_state.height; |
558 | 544 | ||
559 | if (m_state.maximized & MAX_VERT) { | 545 | if (m_state.maximized & WindowState::MAX_VERT) { |
560 | new_y = m_screen.maxTop(head); | 546 | new_y = m_screen.maxTop(head); |
561 | new_h = m_screen.maxBottom(head) - new_y - 2*window().borderWidth(); | 547 | new_h = m_screen.maxBottom(head) - new_y - 2*window().borderWidth(); |
562 | if (!m_screen.getMaxOverTabs()) { | 548 | if (!m_screen.getMaxOverTabs()) { |
@@ -564,7 +550,7 @@ void FbWinFrame::applyState() { | |||
564 | new_h -= heightOffset(); | 550 | new_h -= heightOffset(); |
565 | } | 551 | } |
566 | } | 552 | } |
567 | if (m_state.maximized & MAX_HORZ) { | 553 | if (m_state.maximized & WindowState::MAX_HORZ) { |
568 | new_x = m_screen.maxLeft(head); | 554 | new_x = m_screen.maxLeft(head); |
569 | new_w = m_screen.maxRight(head) - new_x - 2*window().borderWidth(); | 555 | new_w = m_screen.maxRight(head) - new_x - 2*window().borderWidth(); |
570 | if (!m_screen.getMaxOverTabs()) { | 556 | if (!m_screen.getMaxOverTabs()) { |
@@ -1482,50 +1468,11 @@ void FbWinFrame::applyTabContainer() { | |||
1482 | } | 1468 | } |
1483 | } | 1469 | } |
1484 | 1470 | ||
1485 | int FbWinFrame::getDecoMaskFromString(const string &str_label) { | ||
1486 | string label = FbTk::StringUtil::toLower(str_label); | ||
1487 | if (label == "none") | ||
1488 | return DECOR_NONE; | ||
1489 | if (label == "normal") | ||
1490 | return DECOR_NORMAL; | ||
1491 | if (label == "tiny") | ||
1492 | return DECOR_TINY; | ||
1493 | if (label == "tool") | ||
1494 | return DECOR_TOOL; | ||
1495 | if (label == "border") | ||
1496 | return DECOR_BORDER; | ||
1497 | if (label == "tab") | ||
1498 | return DECOR_TAB; | ||
1499 | int mask = -1; | ||
1500 | if ((str_label.size() > 1 && str_label[0] == '0' && str_label[1] == 'x') || | ||
1501 | (str_label.size() > 0 && isdigit(str_label[0]))) | ||
1502 | mask = strtol(str_label.c_str(), NULL, 0); | ||
1503 | return mask; | ||
1504 | } | ||
1505 | |||
1506 | bool FbWinFrame::useBorder() const { | ||
1507 | return !m_state.fullscreen && m_state.maximized != MAX_FULL && | ||
1508 | (m_state.deco_mask & DECORM_BORDER); | ||
1509 | } | ||
1510 | |||
1511 | bool FbWinFrame::useTabs() const { | ||
1512 | return !m_state.fullscreen && m_state.deco_mask & DECORM_TAB; | ||
1513 | } | ||
1514 | |||
1515 | bool FbWinFrame::useTitlebar() const { | ||
1516 | return !m_state.fullscreen && m_state.deco_mask & DECORM_TITLEBAR; | ||
1517 | } | ||
1518 | |||
1519 | bool FbWinFrame::useHandle() const { | ||
1520 | return !m_state.fullscreen && !m_state.shaded && | ||
1521 | m_state.deco_mask & DECORM_HANDLE; | ||
1522 | } | ||
1523 | |||
1524 | int FbWinFrame::getShape() const { | 1471 | int FbWinFrame::getShape() const { |
1525 | int shape = theme()->shapePlace(); | 1472 | int shape = theme()->shapePlace(); |
1526 | if (!useTitlebar()) | 1473 | if (!m_state.useTitlebar()) |
1527 | shape &= ~(FbTk::Shape::TOPRIGHT|FbTk::Shape::TOPLEFT); | 1474 | shape &= ~(FbTk::Shape::TOPRIGHT|FbTk::Shape::TOPLEFT); |
1528 | if (!useHandle()) | 1475 | if (!m_state.useHandle()) |
1529 | shape &= ~(FbTk::Shape::BOTTOMRIGHT|FbTk::Shape::BOTTOMLEFT); | 1476 | shape &= ~(FbTk::Shape::BOTTOMRIGHT|FbTk::Shape::BOTTOMLEFT); |
1530 | return shape; | 1477 | return shape; |
1531 | } | 1478 | } |
@@ -1541,13 +1488,13 @@ void FbWinFrame::applyDecorations() { | |||
1541 | // tab deocration only affects if we're external | 1488 | // tab deocration only affects if we're external |
1542 | // must do before the setTabMode in case it goes | 1489 | // must do before the setTabMode in case it goes |
1543 | // to external and is meant to be hidden | 1490 | // to external and is meant to be hidden |
1544 | if (useTabs()) | 1491 | if (m_state.useTabs()) |
1545 | client_move |= showTabs(); | 1492 | client_move |= showTabs(); |
1546 | else | 1493 | else |
1547 | client_move |= hideTabs(); | 1494 | client_move |= hideTabs(); |
1548 | 1495 | ||
1549 | // we rely on frame not doing anything if it is already shown/hidden | 1496 | // we rely on frame not doing anything if it is already shown/hidden |
1550 | if (useTitlebar()) { | 1497 | if (m_state.useTitlebar()) { |
1551 | client_move |= showTitlebar(); | 1498 | client_move |= showTitlebar(); |
1552 | if (m_screen.getDefaultInternalTabs()) | 1499 | if (m_screen.getDefaultInternalTabs()) |
1553 | client_move |= setTabMode(INTERNAL); | 1500 | client_move |= setTabMode(INTERNAL); |
@@ -1555,11 +1502,11 @@ void FbWinFrame::applyDecorations() { | |||
1555 | client_move |= setTabMode(EXTERNAL); | 1502 | client_move |= setTabMode(EXTERNAL); |
1556 | } else { | 1503 | } else { |
1557 | client_move |= hideTitlebar(); | 1504 | client_move |= hideTitlebar(); |
1558 | if (useTabs()) | 1505 | if (m_state.useTabs()) |
1559 | client_move |= setTabMode(EXTERNAL); | 1506 | client_move |= setTabMode(EXTERNAL); |
1560 | } | 1507 | } |
1561 | 1508 | ||
1562 | if (useHandle()) | 1509 | if (m_state.useHandle()) |
1563 | client_move |= showHandle(); | 1510 | client_move |= showHandle(); |
1564 | else | 1511 | else |
1565 | client_move |= hideHandle(); | 1512 | client_move |= hideHandle(); |
@@ -1581,7 +1528,7 @@ void FbWinFrame::applyDecorations() { | |||
1581 | 1528 | ||
1582 | bool FbWinFrame::setBorderWidth(bool do_move) { | 1529 | bool FbWinFrame::setBorderWidth(bool do_move) { |
1583 | unsigned int border_width = theme()->border().width(); | 1530 | unsigned int border_width = theme()->border().width(); |
1584 | unsigned int win_bw = useBorder() ? border_width : 0; | 1531 | unsigned int win_bw = m_state.useBorder() ? border_width : 0; |
1585 | 1532 | ||
1586 | if (border_width && | 1533 | if (border_width && |
1587 | theme()->border().color().pixel() != window().borderColor()) { | 1534 | theme()->border().color().pixel() != window().borderColor()) { |
@@ -1717,30 +1664,6 @@ void FbWinFrame::gravityTranslate(int &x, int &y, | |||
1717 | } | 1664 | } |
1718 | } | 1665 | } |
1719 | 1666 | ||
1720 | int FbWinFrame::normalX() const { | ||
1721 | if ((m_state.maximized & MAX_HORZ) || m_state.fullscreen) | ||
1722 | return m_state.x; | ||
1723 | return x(); | ||
1724 | } | ||
1725 | |||
1726 | int FbWinFrame::normalY() const { | ||
1727 | if ((m_state.maximized & MAX_VERT) || m_state.fullscreen) | ||
1728 | return m_state.y; | ||
1729 | return y(); | ||
1730 | } | ||
1731 | |||
1732 | unsigned int FbWinFrame::normalWidth() const { | ||
1733 | if ((m_state.maximized & MAX_HORZ) || m_state.fullscreen) | ||
1734 | return m_state.width; | ||
1735 | return width(); | ||
1736 | } | ||
1737 | |||
1738 | unsigned int FbWinFrame::normalHeight() const { | ||
1739 | if ((m_state.maximized & MAX_VERT) || m_state.fullscreen || m_state.shaded) | ||
1740 | return m_state.height; | ||
1741 | return height(); | ||
1742 | } | ||
1743 | |||
1744 | int FbWinFrame::widthOffset() const { | 1667 | int FbWinFrame::widthOffset() const { |
1745 | if (m_tabmode != EXTERNAL || !m_use_tabs) | 1668 | if (m_tabmode != EXTERNAL || !m_use_tabs) |
1746 | return 0; | 1669 | return 0; |
@@ -1825,201 +1748,3 @@ void FbWinFrame::displaySize(unsigned int width, unsigned int height) const { | |||
1825 | width, height - titlebarHeight() - handleHeight()); | 1748 | width, height - titlebarHeight() - handleHeight()); |
1826 | m_screen.showGeometry(i, j); | 1749 | m_screen.showGeometry(i, j); |
1827 | } | 1750 | } |
1828 | |||
1829 | void FbWinFrame::SizeHints::reset(const XSizeHints &sizehint) { | ||
1830 | if (sizehint.flags & PMinSize) { | ||
1831 | min_width = sizehint.min_width; | ||
1832 | min_height = sizehint.min_height; | ||
1833 | } else | ||
1834 | min_width = min_height = 1; | ||
1835 | |||
1836 | if (sizehint.flags & PBaseSize) { | ||
1837 | base_width = sizehint.base_width; | ||
1838 | base_height = sizehint.base_height; | ||
1839 | if (!(sizehint.flags & PMinSize)) { | ||
1840 | min_width = base_width; | ||
1841 | min_height = base_height; | ||
1842 | } | ||
1843 | } else | ||
1844 | base_width = base_height = 0; | ||
1845 | |||
1846 | if (sizehint.flags & PMaxSize) { | ||
1847 | max_width = sizehint.max_width; | ||
1848 | max_height = sizehint.max_height; | ||
1849 | } else | ||
1850 | max_width = max_height = 0; // unbounded | ||
1851 | |||
1852 | if (sizehint.flags & PResizeInc) { | ||
1853 | width_inc = sizehint.width_inc; | ||
1854 | height_inc = sizehint.height_inc; | ||
1855 | } else | ||
1856 | width_inc = height_inc = 1; | ||
1857 | |||
1858 | if (sizehint.flags & PAspect) { | ||
1859 | min_aspect_x = sizehint.min_aspect.x; | ||
1860 | min_aspect_y = sizehint.min_aspect.y; | ||
1861 | max_aspect_x = sizehint.max_aspect.x; | ||
1862 | max_aspect_y = sizehint.max_aspect.y; | ||
1863 | } else { | ||
1864 | min_aspect_x = max_aspect_y = 0; | ||
1865 | min_aspect_y = max_aspect_x = 1; | ||
1866 | } | ||
1867 | |||
1868 | if (sizehint.flags & PWinGravity) | ||
1869 | win_gravity = sizehint.win_gravity; | ||
1870 | else | ||
1871 | win_gravity = NorthWestGravity; | ||
1872 | |||
1873 | // some sanity checks | ||
1874 | if (width_inc == 0) | ||
1875 | width_inc = 1; | ||
1876 | if (height_inc == 0) | ||
1877 | height_inc = 1; | ||
1878 | |||
1879 | if (base_width > min_width) | ||
1880 | min_width = base_width; | ||
1881 | if (base_height > min_height) | ||
1882 | min_height = base_height; | ||
1883 | } | ||
1884 | |||
1885 | /* For aspect ratios | ||
1886 | Note that its slightly simplified in that only the | ||
1887 | line gradient is given - this is because for aspect | ||
1888 | ratios, we always have the line going through the origin | ||
1889 | |||
1890 | * Based on this formula: | ||
1891 | http://astronomy.swin.edu.au/~pbourke/geometry/pointline/ | ||
1892 | |||
1893 | Note that a gradient from origin goes through ( grad , 1 ) | ||
1894 | */ | ||
1895 | |||
1896 | void closestPointToAspect(unsigned int &ret_x, unsigned int &ret_y, | ||
1897 | unsigned int point_x, unsigned int point_y, | ||
1898 | unsigned int aspect_x, unsigned int aspect_y) { | ||
1899 | double u = static_cast<double>(point_x * aspect_x + point_y * aspect_y) / | ||
1900 | static_cast<double>(aspect_x * aspect_x + aspect_y * aspect_y); | ||
1901 | |||
1902 | ret_x = static_cast<unsigned int>(u * aspect_x); | ||
1903 | ret_y = static_cast<unsigned int>(u * aspect_y); | ||
1904 | } | ||
1905 | |||
1906 | unsigned int increaseToMultiple(unsigned int val, unsigned int inc) { | ||
1907 | return val % inc ? val + inc - (val % inc) : val; | ||
1908 | } | ||
1909 | |||
1910 | unsigned int decreaseToMultiple(unsigned int val, unsigned int inc) { | ||
1911 | return val % inc ? val - (val % inc) : val; | ||
1912 | } | ||
1913 | |||
1914 | /** | ||
1915 | * Changes width and height to the nearest (lower) value | ||
1916 | * that conforms to it's size hints. | ||
1917 | * | ||
1918 | * display_* give the values that would be displayed | ||
1919 | * to the user when resizing. | ||
1920 | * We use pointers for display_* since they are optional. | ||
1921 | * | ||
1922 | * See ICCCM section 4.1.2.3 | ||
1923 | */ | ||
1924 | void FbWinFrame::SizeHints::apply(unsigned int &width, unsigned int &height, | ||
1925 | bool make_fit) const { | ||
1926 | |||
1927 | /* aspect ratios are applied exclusive to the base size | ||
1928 | * | ||
1929 | * min_aspect_x width max_aspect_x | ||
1930 | * ------------ < ------- < ------------ | ||
1931 | * min_aspect_y height max_aspect_y | ||
1932 | * | ||
1933 | * The trick is how to get back to the aspect ratio with minimal | ||
1934 | * change - do we modify x, y or both? | ||
1935 | * A: we minimise the distance between the current point, and | ||
1936 | * the target aspect ratio (consider them as x,y coordinates) | ||
1937 | * Consider that the aspect ratio is a line, and the current | ||
1938 | * w/h is a point, so we're just using the formula for | ||
1939 | * shortest distance from a point to a line! | ||
1940 | */ | ||
1941 | |||
1942 | // make respective to base_size | ||
1943 | unsigned int w = width - base_width, h = height - base_height; | ||
1944 | |||
1945 | if (min_aspect_y > 0 && w * min_aspect_y < min_aspect_x * h) { | ||
1946 | closestPointToAspect(w, h, w, h, min_aspect_x, min_aspect_y); | ||
1947 | // new w must be > old w, new h must be < old h | ||
1948 | w = increaseToMultiple(w, width_inc); | ||
1949 | h = decreaseToMultiple(h, height_inc); | ||
1950 | } else if (max_aspect_x > 0 && w * max_aspect_y > max_aspect_x * h) { | ||
1951 | closestPointToAspect(w, h, w, h, max_aspect_x, max_aspect_y); | ||
1952 | // new w must be < old w, new h must be > old h | ||
1953 | w = decreaseToMultiple(w, width_inc); | ||
1954 | h = increaseToMultiple(h, height_inc); | ||
1955 | } | ||
1956 | |||
1957 | // Check minimum size | ||
1958 | if (w + base_width < min_width) { | ||
1959 | w = increaseToMultiple(min_width - base_width, width_inc); | ||
1960 | // need to check maximum aspect again | ||
1961 | if (max_aspect_x > 0 && w * max_aspect_y > max_aspect_x * h) | ||
1962 | h = increaseToMultiple(w * max_aspect_y / max_aspect_x, height_inc); | ||
1963 | } | ||
1964 | |||
1965 | if (h + base_height < min_height) { | ||
1966 | h = increaseToMultiple(min_height - base_height, height_inc); | ||
1967 | // need to check minimum aspect again | ||
1968 | if (min_aspect_y > 0 && w * min_aspect_y < min_aspect_x * h) | ||
1969 | w = increaseToMultiple(h * min_aspect_x / min_aspect_y, width_inc); | ||
1970 | } | ||
1971 | |||
1972 | unsigned int max_w = make_fit && (width < max_width || max_width == 0) ? | ||
1973 | width : max_width; | ||
1974 | unsigned int max_h = make_fit && (height < max_height || max_height == 0) ? | ||
1975 | height : max_height; | ||
1976 | |||
1977 | // Check maximum size | ||
1978 | if (max_w > 0 && w + base_width > max_w) | ||
1979 | w = max_w - base_width; | ||
1980 | |||
1981 | if (max_h > 0 && h + base_height > max_h) | ||
1982 | h = max_h - base_height; | ||
1983 | |||
1984 | w = decreaseToMultiple(w, width_inc); | ||
1985 | h = decreaseToMultiple(h, height_inc); | ||
1986 | |||
1987 | // need to check aspects one more time | ||
1988 | if (min_aspect_y > 0 && w * min_aspect_y < min_aspect_x * h) | ||
1989 | h = decreaseToMultiple(w * min_aspect_y / min_aspect_x, height_inc); | ||
1990 | |||
1991 | if (max_aspect_x > 0 && w * max_aspect_y > max_aspect_x * h) | ||
1992 | w = decreaseToMultiple(h * max_aspect_x / max_aspect_y, width_inc); | ||
1993 | |||
1994 | width = w + base_width; | ||
1995 | height = h + base_height; | ||
1996 | } | ||
1997 | |||
1998 | // check if the given width and height satisfy the size hints | ||
1999 | bool FbWinFrame::SizeHints::valid(unsigned int w, unsigned int h) const { | ||
2000 | if (w < min_width || h < min_height) | ||
2001 | return false; | ||
2002 | |||
2003 | if (w > max_width || h > max_height) | ||
2004 | return false; | ||
2005 | |||
2006 | if ((w - base_width) % width_inc != 0) | ||
2007 | return false; | ||
2008 | |||
2009 | if ((h - base_height) % height_inc != 0) | ||
2010 | return false; | ||
2011 | |||
2012 | if (min_aspect_x * (h - base_height) > (w - base_width) * min_aspect_y) | ||
2013 | return false; | ||
2014 | |||
2015 | if (max_aspect_x * (h - base_height) < (w - base_width) * max_aspect_y) | ||
2016 | return false; | ||
2017 | |||
2018 | return true; | ||
2019 | } | ||
2020 | |||
2021 | void FbWinFrame::SizeHints::displaySize(unsigned int &i, unsigned int &j, | ||
2022 | unsigned int width, unsigned int height) const { | ||
2023 | i = (width - base_width) / width_inc; | ||
2024 | j = (height - base_height) / height_inc; | ||
2025 | } | ||