From ab6e83e9356bea6006aaf524681797f0ef6cb18e Mon Sep 17 00:00:00 2001 From: rathnor <rathnor> Date: Thu, 1 Apr 2004 14:06:42 +0000 Subject: honour aspect ratio hints --- ChangeLog | 9 ++++--- src/WinClient.cc | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 83 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6d6a60a..b468e10 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,12 +1,15 @@ (Format: Year/Month/Day) Changes for 0.9.9: +*04/04/01: + * Support aspect ratio hints (Simon) + WinClient.cc *04/03/31: * Fixed _MOTIF_WM_HINTS decoration toggle bug (Henrik) Window.cc *04/03/30: - * Fixed optional decoration on transient windows (Thanks Scott Moser <ssmoser at us dot ibm dot com>) - - Screen.hh/cc, Window.cc, nls/C/Configmenu.m + * Fixed optional decoration on transient windows + (Thanks Scott Moser <ssmoser at us dot ibm dot com>) + Screen.hh/cc, Window.cc, nls/C/Configmenu.m *04/03/28: * Fixed window snaping to screen objects (Henrik) Window.cc diff --git a/src/WinClient.cc b/src/WinClient.cc index 2524106..2265f2f 100644 --- a/src/WinClient.cc +++ b/src/WinClient.cc @@ -19,7 +19,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: WinClient.cc,v 1.37 2003/12/30 20:56:41 fluxgen Exp $ +// $Id: WinClient.cc,v 1.38 2004/04/01 14:06:42 rathnor Exp $ #include "WinClient.hh" @@ -45,8 +45,8 @@ WinClient::WinClient(Window win, BScreen &screen, FluxboxWindow *fbwin):FbTk::Fb min_width(1), min_height(1), max_width(0), max_height(0), width_inc(1), height_inc(1), - min_aspect_x(1), min_aspect_y(1), - max_aspect_x(1), max_aspect_y(1), + min_aspect_x(0), min_aspect_y(0), + max_aspect_x(0), max_aspect_y(0), base_width(1), base_height(1), initial_state(0), normal_hint_flags(0), @@ -441,7 +441,7 @@ void WinClient::updateWMNormalHints() { max_width = 0; // unbounded max_height = 0; min_aspect_x = min_aspect_y = - max_aspect_x = max_aspect_y = 1; + max_aspect_x = max_aspect_y = 0; m_win_gravity = NorthWestGravity; } else { normal_hint_flags = sizehint.flags; @@ -488,7 +488,7 @@ void WinClient::updateWMNormalHints() { max_aspect_y = sizehint.max_aspect.y; } else min_aspect_x = min_aspect_y = - max_aspect_x = max_aspect_y = 1; + max_aspect_x = max_aspect_y = 0; if (sizehint.flags & PWinGravity) m_win_gravity = sizehint.win_gravity; @@ -630,6 +630,26 @@ void WinClient::updateWMProtocols() { } +/* For aspect ratios + Note that its slightly simplified in that only the + line gradient is given - this is because for aspect + ratios, we always have the line going through the origin + + * Based on this formula: + http://astronomy.swin.edu.au/~pbourke/geometry/pointline/ + + Note that a gradient from origin goes through ( grad , 1 ) + */ + +void closestPointToLine(double &ret_x, double &ret_y, + double point_x, double point_y, + double gradient) { + double u = (point_x * gradient + point_y) / + (gradient*gradient + 1); + + ret_x = u*gradient; + ret_y = u; +} /** * Changes width and height to the nearest (lower) value @@ -660,6 +680,58 @@ void WinClient::applySizeHints(int &width, int &height, if (max_height > 0 && height > static_cast<signed>(max_height)) height = max_height; + // we apply aspect ratios before incrementals + // Too difficult to exactly satisfy both incremental+aspect + // in most situations + // (they really shouldn't happen at the same time anyway). + + /* aspect ratios are applied exclusive to the base_width + * + * min_aspect_x width max_aspect_x + * ------------ < ------- < ------------ + * min_aspect_y height max_aspect_y + * + * beware of integer maximum (so I'll use doubles instead and divide) + * + * The trick is how to get back to the aspect ratio with minimal + * change - do we modify x, y or both? + * A: we minimise the distance between the current point, and + * the target aspect ratio (consider them as x,y coordinates) + * Consider that the aspect ratio is a line, and the current + * w/h is a point, so we're just using the formula for + * shortest distance from a point to a line! + */ + + if (min_aspect_y > 0 && max_aspect_y > 0 && + (height - base_height) > 0) { + double widthd = static_cast<double>(width - base_width); + double heightd = static_cast<double>(height - base_height); + + double min = static_cast<double>(min_aspect_x) / + static_cast<double>(min_aspect_y); + + double max = static_cast<double>(max_aspect_x) / + static_cast<double>(max_aspect_y); + + double actual = widthd / heightd; + + if (max > 0 && min > 0 && actual > 0) { // don't even try otherwise + bool changed = false; + if (actual < min) { + changed = true; + closestPointToLine(widthd, heightd, widthd, heightd, min); + } else if (actual > max) { + changed = true; + closestPointToLine(widthd, heightd, widthd, heightd, max); + } + + if (changed) { + width = static_cast<int>(widthd) + base_width; + height = static_cast<int>(heightd) + base_height; + } + } + } + // enforce incremental size limits, wrt base size // only calculate this if we really need to i = (width - base_width) / width_inc; -- cgit v0.11.2