all repos — fluxbox @ 6053ecc1b573e437dd0d1752670748c5c3679669

custom fork of the fluxbox windowmanager

move size hint code to methods in size hint struct, restructure them a little
Mark Tiefenbruck mark@fluxbox.org
commit

6053ecc1b573e437dd0d1752670748c5c3679669

parent

4fa3773267362f8ca9f653bb8ee7c98baa09d5fd

5 files changed, 138 insertions(+), 178 deletions(-)

jump to
M src/FbWinFrame.ccsrc/FbWinFrame.cc

@@ -1459,138 +1459,6 @@ if (client_move)

frameExtentSig().notify(); } -/* 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 - * that conforms to it's size hints. - * - * display_* give the values that would be displayed - * to the user when resizing. - * We use pointers for display_* since they are optional. - * - * See ICCCM section 4.1.2.3 - */ -void FbWinFrame::applySizeHints(int &width, int &height, - int *display_width, int *display_height, - bool maximizing) { - - int i = width, j = height; - - // Check minimum size - if (width < 0 || width < static_cast<signed>(m_size_hints.min_width)) - width = m_size_hints.min_width; - - if (height < 0 || height < static_cast<signed>(m_size_hints.min_height)) - height = m_size_hints.min_height; - - // Check maximum size - if (m_size_hints.max_width > 0 && width > static_cast<signed>(m_size_hints.max_width)) - width = m_size_hints.max_width; - - if (m_size_hints.max_height > 0 && height > static_cast<signed>(m_size_hints.max_height)) - height = m_size_hints.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 m_size_hints.base_width - * - * m_size_hints.min_aspect_x width m_size_hints.max_aspect_x - * ------------ < ------- < ------------ - * m_size_hints.min_aspect_y height m_size_hints.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! - * - * When maximizing, we must not increase any of the sizes, because we - * would end up with the window partly off a screen, so a simpler formula - * is used in that case. - */ - - if (m_size_hints.min_aspect_y > 0 && m_size_hints.max_aspect_y > 0 && - (height - m_size_hints.base_height) > 0) { - double widthd = static_cast<double>(width - m_size_hints.base_width); - double heightd = static_cast<double>(height - m_size_hints.base_height); - - double min = static_cast<double>(m_size_hints.min_aspect_x) / - static_cast<double>(m_size_hints.min_aspect_y); - - double max = static_cast<double>(m_size_hints.max_aspect_x) / - static_cast<double>(m_size_hints.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; - if (maximizing) - heightd = widthd / min; - else - closestPointToLine(widthd, heightd, widthd, heightd, min); - } else if (actual > max) { - changed = true; - if (maximizing) - widthd = heightd * max; - else - closestPointToLine(widthd, heightd, widthd, heightd, max); - } - - if (changed) { - width = static_cast<int>(widthd) + m_size_hints.base_width; - height = static_cast<int>(heightd) + m_size_hints.base_height; - } - } - } - - // enforce incremental size limits, wrt base size - // only calculate this if we really need to - i = (width - static_cast<signed>(m_size_hints.base_width)) / - static_cast<signed>(m_size_hints.width_inc); - width = i*static_cast<signed>(m_size_hints.width_inc) + - static_cast<signed>(m_size_hints.base_width); - - j = (height - static_cast<signed>(m_size_hints.base_height)) / - static_cast<signed>(m_size_hints.height_inc); - height = j*static_cast<signed>(m_size_hints.height_inc) + - static_cast<signed>(m_size_hints.base_height); - - if (display_width) - *display_width = i; - - if (display_height) - *display_height = j; -} - bool FbWinFrame::setBorderWidth(bool do_move) { unsigned int border_width = theme()->border().width(); unsigned int win_bw = m_decoration_mask & DECORM_BORDER ? border_width : 0;

@@ -1800,3 +1668,124 @@ }

return 0; } +/* 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 closestPointToAspect(unsigned int &ret_x, unsigned int &ret_y, + unsigned int point_x, unsigned int point_y, + unsigned int aspect_x, unsigned int aspect_y) { + double u = static_cast<double>(point_x * aspect_x + point_y * aspect_y) / + static_cast<double>(aspect_x * aspect_x + aspect_y * aspect_y); + + ret_x = static_cast<unsigned int>(u * aspect_x); + ret_y = static_cast<unsigned int>(u * aspect_y); +} + +/** + * Changes width and height to the nearest (lower) value + * that conforms to it's size hints. + * + * display_* give the values that would be displayed + * to the user when resizing. + * We use pointers for display_* since they are optional. + * + * See ICCCM section 4.1.2.3 + */ +void FbWinFrame::SizeHints::apply(unsigned int &width, unsigned int &height, + bool maximizing) const { + + // 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 size + * + * 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! + * + * When maximizing, we must not increase any of the sizes, because we + * would end up with the window partly off a screen, so a simpler formula + * is used in that case. + */ + + if (min_aspect_y > 0 && width*min_aspect_y < min_aspect_x*height) { + if (maximizing) + height = width * min_aspect_y / min_aspect_x; + else + closestPointToAspect(width, height, width, height, + min_aspect_x, min_aspect_y); + } else if (max_aspect_x > 0 && width*max_aspect_y > max_aspect_x*height) { + if (maximizing) + width = height * max_aspect_x / max_aspect_y; + else + closestPointToAspect(width, height, width, height, + max_aspect_x, max_aspect_y); + } + + // Check minimum size + if (width < min_width) + width = min_width; + + if (height < min_height) + height = min_height; + + // Check maximum size + if (max_width > 0 && width > max_width) + width = max_width; + + if (max_height > 0 && height > max_height) + height = max_height; + + // enforce incremental size limits, wrt base size + width -= (width - base_width) % width_inc; + height -= (height - base_height) % height_inc; +} + +// check if the given width and height satisfy the size hints +bool FbWinFrame::SizeHints::valid(unsigned int w, unsigned int h) const { + if (w < min_width || h < min_height) + return false; + + if (w > max_width || h > max_height) + return false; + + if ((w - base_width) % width_inc != 0) + return false; + + if ((h - base_height) % height_inc != 0) + return false; + + if (min_aspect_x * h > w * min_aspect_y) + return false; + + if (max_aspect_x * h < w * max_aspect_y) + return false; + + return true; +} + +void FbWinFrame::SizeHints::displaySize(int &i, int &j, + unsigned int width, unsigned int height) const { + i = static_cast<signed>(width - base_width) / width_inc; + j = static_cast<signed>(height - base_height) / height_inc; +}
M src/FbWinFrame.hhsrc/FbWinFrame.hh

@@ -96,6 +96,11 @@ DECOR_TAB = DECORM_BORDER|DECORM_MENU|DECORM_TAB

}; typedef struct SizeHints { + void apply(unsigned int &w, unsigned int &h, + bool maximizing = false) const; + bool valid(unsigned int width, unsigned int height) const; + void displaySize(int &i, int &j, + unsigned int width, unsigned int height) const; unsigned int min_width; unsigned int max_width; unsigned int min_height;

@@ -200,16 +205,7 @@ void setEventHandler(FbTk::EventHandler &evh);

/// remove any handler for the windows void removeEventHandler(); - /** - * Changes width and height to the nearest (lower) value - * that conforms to it's size hints. - * - * display_* give the values that would be displayed - * to the user when resizing. - * We use pointers for display_* since they are optional. - */ - void applySizeHints(int &width, int &height, int *display_width = 0, - int *display_height = 0, bool maximizing = false); + const SizeHints &sizeHints() const { return m_size_hints; } void setSizeHints(const SizeHints &hint) { m_size_hints = hint; } void setDecorationMask(unsigned int mask) { m_decoration_mask = mask; }
M src/WinClient.ccsrc/WinClient.cc

@@ -690,31 +690,6 @@ }

} -// check if the given width and height satisfy the size hints -bool WinClient::checkSizeHints(unsigned int width, unsigned int height) { - if (width < m_size_hints.min_width || height < m_size_hints.min_height) - return false; - - if (width > m_size_hints.max_width || height > m_size_hints.max_height) - return false; - - if ((width - m_size_hints.base_width) % m_size_hints.width_inc != 0) - return false; - - if ((height - m_size_hints.base_height) % m_size_hints.height_inc != 0) - return false; - - double ratio = (double)width / (double)height; - - if (m_size_hints.min_aspect_y > 0 && (double)m_size_hints.min_aspect_x / (double)m_size_hints.min_aspect_y > ratio) - return false; - - if (m_size_hints.max_aspect_y > 0 && (double)m_size_hints.max_aspect_x / (double)m_size_hints.max_aspect_y < ratio) - return false; - - return true; -} - void WinClient::removeTransientFromWaitingList() { // holds the windows that dont have empty
M src/WinClient.hhsrc/WinClient.hh

@@ -81,8 +81,6 @@ bool isFocused() const;

void setAttentionState(bool value); const std::string &title() const { return m_title; } - bool checkSizeHints(unsigned int width, unsigned int height); - void setGroupLeftWindow(Window win); void saveBlackboxAttribs(FluxboxWindow::BlackboxAttributes &blackbox_attribs, int nelements);
M src/Window.ccsrc/Window.cc

@@ -550,9 +550,9 @@ m_client->transientFor()->fbwindow()->title()<<endl;

} #endif // DEBUG - int real_width = frame().width(); - int real_height = frame().height() - frame().titlebarHeight() - frame().handleHeight(); - frame().applySizeHints(real_width, real_height); + unsigned int real_width = frame().width(); + unsigned int real_height = frame().height() - frame().titlebarHeight() - frame().handleHeight(); + frame().sizeHints().apply(real_width, real_height); real_height += frame().titlebarHeight() + frame().handleHeight(); if (m_placed)

@@ -2483,12 +2483,12 @@

// make sure the new width/height would be ok with all clients, or else they // could try to resize the window back and forth if (cr.value_mask & CWWidth || cr.value_mask & CWHeight) { - int new_w = (cr.value_mask & CWWidth) ? cr.width : cw; - int new_h = (cr.value_mask & CWHeight) ? cr.height : ch; + unsigned int new_w = (cr.value_mask & CWWidth) ? cr.width : cw; + unsigned int new_h = (cr.value_mask & CWHeight) ? cr.height : ch; ClientList::iterator it = clientList().begin(); ClientList::iterator it_end = clientList().end(); for (; it != it_end; ++it) { - if (*it != client && !(*it)->checkSizeHints(new_w, new_h)) + if (*it != client && !(*it)->sizeHints().valid(new_w, new_h)) cr.value_mask = cr.value_mask & ~(CWWidth | CWHeight); } }

@@ -3725,12 +3725,14 @@ int decoration_height = frame().titlebarHeight() + frame().handleHeight();

// dx is new width = current width + difference between new and old x values //int dx = frame().width() + frame().x() - m_last_resize_x; - int dw = m_last_resize_w; + unsigned int dw = m_last_resize_w; // dy = new height (w/o decorations), similarly - int dh = m_last_resize_h - decoration_height; + unsigned int dh = m_last_resize_h - decoration_height; - frame().applySizeHints(dw, dh, user_w, user_h, maximizing); + frame().sizeHints().apply(dw, dh, maximizing); + if (user_w && user_h) + frame().sizeHints().displaySize(*user_w, *user_h, dw, dh); // update last resize m_last_resize_w = dw;