diff options
author | Mark Tiefenbruck <mark@fluxbox.org> | 2008-08-15 11:04:56 (GMT) |
---|---|---|
committer | Mark Tiefenbruck <mark@fluxbox.org> | 2008-08-15 11:04:56 (GMT) |
commit | 4fa3773267362f8ca9f653bb8ee7c98baa09d5fd (patch) | |
tree | d77ee1cde06ab0b5d4a403f236aff4a51d418c89 /src/FbWinFrame.cc | |
parent | 80059c6dae8de4962b14f08bd75f1c773e37a78d (diff) | |
download | fluxbox_pavel-4fa3773267362f8ca9f653bb8ee7c98baa09d5fd.zip fluxbox_pavel-4fa3773267362f8ca9f653bb8ee7c98baa09d5fd.tar.bz2 |
move size hint code to FbWinFrame
Diffstat (limited to 'src/FbWinFrame.cc')
-rw-r--r-- | src/FbWinFrame.cc | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/src/FbWinFrame.cc b/src/FbWinFrame.cc index afd5fb5..4734b2b 100644 --- a/src/FbWinFrame.cc +++ b/src/FbWinFrame.cc | |||
@@ -1459,6 +1459,138 @@ 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 | |||
1473 | void 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 | */ | ||
1493 | void 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 | |||
1462 | bool FbWinFrame::setBorderWidth(bool do_move) { | 1594 | bool FbWinFrame::setBorderWidth(bool do_move) { |
1463 | unsigned int border_width = theme()->border().width(); | 1595 | unsigned int border_width = theme()->border().width(); |
1464 | unsigned int win_bw = m_decoration_mask & DECORM_BORDER ? border_width : 0; | 1596 | unsigned int win_bw = m_decoration_mask & DECORM_BORDER ? border_width : 0; |