diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/FbWinFrame.cc | 132 | ||||
-rw-r--r-- | src/FbWinFrame.hh | 28 | ||||
-rw-r--r-- | src/WinClient.cc | 132 | ||||
-rw-r--r-- | src/WinClient.hh | 29 | ||||
-rw-r--r-- | src/Window.cc | 6 |
5 files changed, 167 insertions, 160 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; |
diff --git a/src/FbWinFrame.hh b/src/FbWinFrame.hh index e24612e..d2a27c9 100644 --- a/src/FbWinFrame.hh +++ b/src/FbWinFrame.hh | |||
@@ -95,6 +95,21 @@ public: | |||
95 | DECOR_TAB = DECORM_BORDER|DECORM_MENU|DECORM_TAB | 95 | DECOR_TAB = DECORM_BORDER|DECORM_MENU|DECORM_TAB |
96 | }; | 96 | }; |
97 | 97 | ||
98 | typedef struct SizeHints { | ||
99 | unsigned int min_width; | ||
100 | unsigned int max_width; | ||
101 | unsigned int min_height; | ||
102 | unsigned int max_height; | ||
103 | unsigned int width_inc; | ||
104 | unsigned int height_inc; | ||
105 | unsigned int min_aspect_x; | ||
106 | unsigned int max_aspect_x; | ||
107 | unsigned int min_aspect_y; | ||
108 | unsigned int max_aspect_y; | ||
109 | unsigned int base_width; | ||
110 | unsigned int base_height; | ||
111 | } SizeHints; | ||
112 | |||
98 | /// create a top level window | 113 | /// create a top level window |
99 | FbWinFrame(BScreen &screen, FocusableTheme<FbWinFrameTheme> &theme, | 114 | FbWinFrame(BScreen &screen, FocusableTheme<FbWinFrameTheme> &theme, |
100 | FbTk::ImageControl &imgctrl, | 115 | FbTk::ImageControl &imgctrl, |
@@ -185,6 +200,18 @@ public: | |||
185 | /// remove any handler for the windows | 200 | /// remove any handler for the windows |
186 | void removeEventHandler(); | 201 | void removeEventHandler(); |
187 | 202 | ||
203 | /** | ||
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; } | ||
214 | |||
188 | void setDecorationMask(unsigned int mask) { m_decoration_mask = mask; } | 215 | void setDecorationMask(unsigned int mask) { m_decoration_mask = mask; } |
189 | void applyDecorations(); | 216 | void applyDecorations(); |
190 | 217 | ||
@@ -392,6 +419,7 @@ private: | |||
392 | // last gravity that this window was *actively* placed with | 419 | // last gravity that this window was *actively* placed with |
393 | int m_active_gravity; | 420 | int m_active_gravity; |
394 | unsigned int m_active_orig_client_bw; | 421 | unsigned int m_active_orig_client_bw; |
422 | SizeHints m_size_hints; | ||
395 | 423 | ||
396 | bool m_need_render; | 424 | bool m_need_render; |
397 | int m_button_size; ///< size for all titlebar buttons | 425 | int m_button_size; ///< size for all titlebar buttons |
diff --git a/src/WinClient.cc b/src/WinClient.cc index 9aac38d..b9602ec 100644 --- a/src/WinClient.cc +++ b/src/WinClient.cc | |||
@@ -690,138 +690,6 @@ void WinClient::updateWMProtocols() { | |||
690 | 690 | ||
691 | } | 691 | } |
692 | 692 | ||
693 | /* For aspect ratios | ||
694 | Note that its slightly simplified in that only the | ||
695 | line gradient is given - this is because for aspect | ||
696 | ratios, we always have the line going through the origin | ||
697 | |||
698 | * Based on this formula: | ||
699 | http://astronomy.swin.edu.au/~pbourke/geometry/pointline/ | ||
700 | |||
701 | Note that a gradient from origin goes through ( grad , 1 ) | ||
702 | */ | ||
703 | |||
704 | void closestPointToLine(double &ret_x, double &ret_y, | ||
705 | double point_x, double point_y, | ||
706 | double gradient) { | ||
707 | double u = (point_x * gradient + point_y) / | ||
708 | (gradient*gradient + 1); | ||
709 | |||
710 | ret_x = u*gradient; | ||
711 | ret_y = u; | ||
712 | } | ||
713 | |||
714 | /** | ||
715 | * Changes width and height to the nearest (lower) value | ||
716 | * that conforms to it's size hints. | ||
717 | * | ||
718 | * display_* give the values that would be displayed | ||
719 | * to the user when resizing. | ||
720 | * We use pointers for display_* since they are optional. | ||
721 | * | ||
722 | * See ICCCM section 4.1.2.3 | ||
723 | */ | ||
724 | void WinClient::applySizeHints(int &width, int &height, | ||
725 | int *display_width, int *display_height, | ||
726 | bool maximizing) { | ||
727 | |||
728 | int i = width, j = height; | ||
729 | |||
730 | // Check minimum size | ||
731 | if (width < 0 || width < static_cast<signed>(m_size_hints.min_width)) | ||
732 | width = m_size_hints.min_width; | ||
733 | |||
734 | if (height < 0 || height < static_cast<signed>(m_size_hints.min_height)) | ||
735 | height = m_size_hints.min_height; | ||
736 | |||
737 | // Check maximum size | ||
738 | if (m_size_hints.max_width > 0 && width > static_cast<signed>(m_size_hints.max_width)) | ||
739 | width = m_size_hints.max_width; | ||
740 | |||
741 | if (m_size_hints.max_height > 0 && height > static_cast<signed>(m_size_hints.max_height)) | ||
742 | height = m_size_hints.max_height; | ||
743 | |||
744 | // we apply aspect ratios before incrementals | ||
745 | // Too difficult to exactly satisfy both incremental+aspect | ||
746 | // in most situations | ||
747 | // (they really shouldn't happen at the same time anyway). | ||
748 | |||
749 | /* aspect ratios are applied exclusive to the m_size_hints.base_width | ||
750 | * | ||
751 | * m_size_hints.min_aspect_x width m_size_hints.max_aspect_x | ||
752 | * ------------ < ------- < ------------ | ||
753 | * m_size_hints.min_aspect_y height m_size_hints.max_aspect_y | ||
754 | * | ||
755 | * beware of integer maximum (so I'll use doubles instead and divide) | ||
756 | * | ||
757 | * The trick is how to get back to the aspect ratio with minimal | ||
758 | * change - do we modify x, y or both? | ||
759 | * A: we minimise the distance between the current point, and | ||
760 | * the target aspect ratio (consider them as x,y coordinates) | ||
761 | * Consider that the aspect ratio is a line, and the current | ||
762 | * w/h is a point, so we're just using the formula for | ||
763 | * shortest distance from a point to a line! | ||
764 | * | ||
765 | * When maximizing, we must not increase any of the sizes, because we | ||
766 | * would end up with the window partly off a screen, so a simpler formula | ||
767 | * is used in that case. | ||
768 | */ | ||
769 | |||
770 | if (m_size_hints.min_aspect_y > 0 && m_size_hints.max_aspect_y > 0 && | ||
771 | (height - m_size_hints.base_height) > 0) { | ||
772 | double widthd = static_cast<double>(width - m_size_hints.base_width); | ||
773 | double heightd = static_cast<double>(height - m_size_hints.base_height); | ||
774 | |||
775 | double min = static_cast<double>(m_size_hints.min_aspect_x) / | ||
776 | static_cast<double>(m_size_hints.min_aspect_y); | ||
777 | |||
778 | double max = static_cast<double>(m_size_hints.max_aspect_x) / | ||
779 | static_cast<double>(m_size_hints.max_aspect_y); | ||
780 | |||
781 | double actual = widthd / heightd; | ||
782 | |||
783 | if (max > 0 && min > 0 && actual > 0) { // don't even try otherwise | ||
784 | bool changed = false; | ||
785 | if (actual < min) { | ||
786 | changed = true; | ||
787 | if (maximizing) | ||
788 | heightd = widthd / min; | ||
789 | else | ||
790 | closestPointToLine(widthd, heightd, widthd, heightd, min); | ||
791 | } else if (actual > max) { | ||
792 | changed = true; | ||
793 | if (maximizing) | ||
794 | widthd = heightd * max; | ||
795 | else | ||
796 | closestPointToLine(widthd, heightd, widthd, heightd, max); | ||
797 | } | ||
798 | |||
799 | if (changed) { | ||
800 | width = static_cast<int>(widthd) + m_size_hints.base_width; | ||
801 | height = static_cast<int>(heightd) + m_size_hints.base_height; | ||
802 | } | ||
803 | } | ||
804 | } | ||
805 | |||
806 | // enforce incremental size limits, wrt base size | ||
807 | // only calculate this if we really need to | ||
808 | i = (width - static_cast<signed>(m_size_hints.base_width)) / | ||
809 | static_cast<signed>(m_size_hints.width_inc); | ||
810 | width = i*static_cast<signed>(m_size_hints.width_inc) + | ||
811 | static_cast<signed>(m_size_hints.base_width); | ||
812 | |||
813 | j = (height - static_cast<signed>(m_size_hints.base_height)) / | ||
814 | static_cast<signed>(m_size_hints.height_inc); | ||
815 | height = j*static_cast<signed>(m_size_hints.height_inc) + | ||
816 | static_cast<signed>(m_size_hints.base_height); | ||
817 | |||
818 | if (display_width) | ||
819 | *display_width = i; | ||
820 | |||
821 | if (display_height) | ||
822 | *display_height = j; | ||
823 | } | ||
824 | |||
825 | // check if the given width and height satisfy the size hints | 693 | // check if the given width and height satisfy the size hints |
826 | bool WinClient::checkSizeHints(unsigned int width, unsigned int height) { | 694 | bool WinClient::checkSizeHints(unsigned int width, unsigned int height) { |
827 | if (width < m_size_hints.min_width || height < m_size_hints.min_height) | 695 | if (width < m_size_hints.min_width || height < m_size_hints.min_height) |
diff --git a/src/WinClient.hh b/src/WinClient.hh index 51d3b3e..9c6dc9e 100644 --- a/src/WinClient.hh +++ b/src/WinClient.hh | |||
@@ -22,6 +22,7 @@ | |||
22 | #ifndef WINCLIENT_HH | 22 | #ifndef WINCLIENT_HH |
23 | #define WINCLIENT_HH | 23 | #define WINCLIENT_HH |
24 | 24 | ||
25 | #include "FbWinFrame.hh" | ||
25 | #include "Window.hh" | 26 | #include "Window.hh" |
26 | #include "FbTk/FbWindow.hh" | 27 | #include "FbTk/FbWindow.hh" |
27 | #include "FbTk/FbString.hh" | 28 | #include "FbTk/FbString.hh" |
@@ -43,21 +44,6 @@ public: | |||
43 | unsigned long decorations; // Motif wm decorations | 44 | unsigned long decorations; // Motif wm decorations |
44 | } MwmHints; | 45 | } MwmHints; |
45 | 46 | ||
46 | typedef struct SizeHints { | ||
47 | unsigned int min_width; | ||
48 | unsigned int max_width; | ||
49 | unsigned int min_height; | ||
50 | unsigned int max_height; | ||
51 | unsigned int width_inc; | ||
52 | unsigned int height_inc; | ||
53 | unsigned int min_aspect_x; | ||
54 | unsigned int max_aspect_x; | ||
55 | unsigned int min_aspect_y; | ||
56 | unsigned int max_aspect_y; | ||
57 | unsigned int base_width; | ||
58 | unsigned int base_height; | ||
59 | } SizeHints; | ||
60 | |||
61 | WinClient(Window win, BScreen &screen, FluxboxWindow *fbwin = 0); | 47 | WinClient(Window win, BScreen &screen, FluxboxWindow *fbwin = 0); |
62 | 48 | ||
63 | ~WinClient(); | 49 | ~WinClient(); |
@@ -95,16 +81,6 @@ public: | |||
95 | void setAttentionState(bool value); | 81 | void setAttentionState(bool value); |
96 | const std::string &title() const { return m_title; } | 82 | const std::string &title() const { return m_title; } |
97 | 83 | ||
98 | /** | ||
99 | * Changes width and height to the nearest (lower) value | ||
100 | * that conforms to it's size hints. | ||
101 | * | ||
102 | * display_* give the values that would be displayed | ||
103 | * to the user when resizing. | ||
104 | * We use pointers for display_* since they are optional. | ||
105 | */ | ||
106 | void applySizeHints(int &width, int &height, int *display_width = 0, | ||
107 | int *display_height = 0, bool maximizing = false); | ||
108 | bool checkSizeHints(unsigned int width, unsigned int height); | 84 | bool checkSizeHints(unsigned int width, unsigned int height); |
109 | 85 | ||
110 | void setGroupLeftWindow(Window win); | 86 | void setGroupLeftWindow(Window win); |
@@ -143,6 +119,7 @@ public: | |||
143 | Window getGroupLeftWindow() const; | 119 | Window getGroupLeftWindow() const; |
144 | 120 | ||
145 | const MwmHints *getMwmHint() const { return m_mwm_hint; } | 121 | const MwmHints *getMwmHint() const { return m_mwm_hint; } |
122 | const FbWinFrame::SizeHints &sizeHints() const { return m_size_hints; } | ||
146 | 123 | ||
147 | unsigned int minWidth() const { return m_size_hints.min_width; } | 124 | unsigned int minWidth() const { return m_size_hints.min_width; } |
148 | unsigned int minHeight() const { return m_size_hints.min_height; } | 125 | unsigned int minHeight() const { return m_size_hints.min_height; } |
@@ -187,7 +164,7 @@ private: | |||
187 | 164 | ||
188 | Focusable::WindowType m_window_type; | 165 | Focusable::WindowType m_window_type; |
189 | MwmHints *m_mwm_hint; | 166 | MwmHints *m_mwm_hint; |
190 | SizeHints m_size_hints; | 167 | FbWinFrame::SizeHints m_size_hints; |
191 | 168 | ||
192 | Strut *m_strut; | 169 | Strut *m_strut; |
193 | // map transient_for X window to winclient transient | 170 | // map transient_for X window to winclient transient |
diff --git a/src/Window.cc b/src/Window.cc index 651b995..45c1e9d 100644 --- a/src/Window.cc +++ b/src/Window.cc | |||
@@ -552,7 +552,7 @@ void FluxboxWindow::init() { | |||
552 | 552 | ||
553 | int real_width = frame().width(); | 553 | int real_width = frame().width(); |
554 | int real_height = frame().height() - frame().titlebarHeight() - frame().handleHeight(); | 554 | int real_height = frame().height() - frame().titlebarHeight() - frame().handleHeight(); |
555 | m_client->applySizeHints(real_width, real_height); | 555 | frame().applySizeHints(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) |
@@ -1066,6 +1066,7 @@ bool FluxboxWindow::setCurrentClient(WinClient &client, bool setinput) { | |||
1066 | // frame focused doesn't necessarily mean input focused | 1066 | // frame focused doesn't necessarily mean input focused |
1067 | frame().setLabelButtonFocus(*button); | 1067 | frame().setLabelButtonFocus(*button); |
1068 | frame().setShapingClient(&client, false); | 1068 | frame().setShapingClient(&client, false); |
1069 | frame().setSizeHints(client.sizeHints()); | ||
1069 | return ret; | 1070 | return ret; |
1070 | } | 1071 | } |
1071 | 1072 | ||
@@ -1090,6 +1091,7 @@ void FluxboxWindow::associateClientWindow(bool use_attrs, | |||
1090 | frame().resizeForClient(m_client->width(), m_client->height()); | 1091 | frame().resizeForClient(m_client->width(), m_client->height()); |
1091 | 1092 | ||
1092 | frame().setActiveGravity(m_client->gravity(), m_client->old_bw); | 1093 | frame().setActiveGravity(m_client->gravity(), m_client->old_bw); |
1094 | frame().setSizeHints(m_client->sizeHints()); | ||
1093 | frame().setClientWindow(*m_client); | 1095 | frame().setClientWindow(*m_client); |
1094 | } | 1096 | } |
1095 | 1097 | ||
@@ -3728,7 +3730,7 @@ void FluxboxWindow::fixsize(int *user_w, int *user_h, bool maximizing) { | |||
3728 | // dy = new height (w/o decorations), similarly | 3730 | // dy = new height (w/o decorations), similarly |
3729 | int dh = m_last_resize_h - decoration_height; | 3731 | int dh = m_last_resize_h - decoration_height; |
3730 | 3732 | ||
3731 | m_client->applySizeHints(dw, dh, user_w, user_h, maximizing); | 3733 | frame().applySizeHints(dw, dh, user_w, user_h, maximizing); |
3732 | 3734 | ||
3733 | // update last resize | 3735 | // update last resize |
3734 | m_last_resize_w = dw; | 3736 | m_last_resize_w = dw; |