From 55fd49614bb1b9e37561147f18719b2ac277b64b Mon Sep 17 00:00:00 2001 From: Mark Tiefenbruck <mark@fluxbox.org> Date: Wed, 27 Aug 2008 13:05:49 -0400 Subject: move FbWinFrame::State class to a new file --- src/CurrentWindowCmd.cc | 2 +- src/FbWinFrame.cc | 303 +++--------------------------------------------- src/FbWinFrame.hh | 103 ++-------------- src/Makefile.am | 2 +- src/Remember.cc | 40 +++---- src/WinClient.hh | 7 +- src/Window.cc | 92 +++++++-------- src/Window.hh | 12 +- src/WindowState.cc | 266 ++++++++++++++++++++++++++++++++++++++++++ src/WindowState.hh | 118 +++++++++++++++++++ 10 files changed, 486 insertions(+), 459 deletions(-) create mode 100644 src/WindowState.cc create mode 100644 src/WindowState.hh diff --git a/src/CurrentWindowCmd.cc b/src/CurrentWindowCmd.cc index 95f2933..59b0186 100644 --- a/src/CurrentWindowCmd.cc +++ b/src/CurrentWindowCmd.cc @@ -503,7 +503,7 @@ void SetTitleCmd::real_execute() { REGISTER_COMMAND_WITH_ARGS(setdecor, SetDecorCmd, void); SetDecorCmd::SetDecorCmd(const std::string &args): - m_mask(FbWinFrame::getDecoMaskFromString(args)) { } + m_mask(WindowState::getDecoMaskFromString(args)) { } void SetDecorCmd::real_execute() { fbwindow().setDecorationMask(m_mask); 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 @@ #include "FbTk/Compose.hh" #include "FbTk/Transparent.hh" #include "FbTk/CompareEqual.hh" -#include "FbTk/StringUtil.hh" #include "FbTk/TextUtils.hh" #include "FbWinFrameTheme.hh" @@ -194,7 +193,7 @@ void FbWinFrame::show() { Toggle shade state, and resize window */ void FbWinFrame::shade() { - if (!(m_state.deco_mask & DECORM_TITLEBAR)) + if (!(m_state.deco_mask & WindowState::DECORM_TITLEBAR)) return; // toggle shade @@ -254,7 +253,8 @@ void FbWinFrame::moveResize(int x, int y, unsigned int width, unsigned int heigh m_window.resize(width, height); } - saveGeometry(); + m_state.saveGeometry(window().x(), window().y(), + window().width(), window().height()); if (move || (resize && m_screen.getTabPlacement() != TOPLEFT && m_screen.getTabPlacement() != LEFTTOP)) @@ -283,7 +283,8 @@ void FbWinFrame::moveResize(int x, int y, unsigned int width, unsigned int heigh void FbWinFrame::quietMoveResize(int x, int y, unsigned int width, unsigned int height) { m_window.moveResize(x, y, width, height); - saveGeometry(); + m_state.saveGeometry(window().x(), window().y(), + window().width(), window().height()); if (m_tabmode == EXTERNAL) { switch(m_screen.getTabPlacement()) { @@ -534,21 +535,6 @@ void FbWinFrame::setMaximized(int value) { applyState(); } -void FbWinFrame::saveGeometry() { - if (m_state.fullscreen || m_state.maximized == MAX_FULL) - return; - - if (!(m_state.maximized & MAX_HORZ)) { - m_state.x = x(); - m_state.width = width(); - } - if (!(m_state.maximized & MAX_VERT)) { - m_state.y = y(); - if (!m_state.shaded) - m_state.height = height(); - } -} - void FbWinFrame::applyState() { applyDecorations(); @@ -556,7 +542,7 @@ void FbWinFrame::applyState() { int new_x = m_state.x, new_y = m_state.y; unsigned int new_w = m_state.width, new_h = m_state.height; - if (m_state.maximized & MAX_VERT) { + if (m_state.maximized & WindowState::MAX_VERT) { new_y = m_screen.maxTop(head); new_h = m_screen.maxBottom(head) - new_y - 2*window().borderWidth(); if (!m_screen.getMaxOverTabs()) { @@ -564,7 +550,7 @@ void FbWinFrame::applyState() { new_h -= heightOffset(); } } - if (m_state.maximized & MAX_HORZ) { + if (m_state.maximized & WindowState::MAX_HORZ) { new_x = m_screen.maxLeft(head); new_w = m_screen.maxRight(head) - new_x - 2*window().borderWidth(); if (!m_screen.getMaxOverTabs()) { @@ -1482,50 +1468,11 @@ void FbWinFrame::applyTabContainer() { } } -int FbWinFrame::getDecoMaskFromString(const string &str_label) { - string label = FbTk::StringUtil::toLower(str_label); - if (label == "none") - return DECOR_NONE; - if (label == "normal") - return DECOR_NORMAL; - if (label == "tiny") - return DECOR_TINY; - if (label == "tool") - return DECOR_TOOL; - if (label == "border") - return DECOR_BORDER; - if (label == "tab") - return DECOR_TAB; - int mask = -1; - if ((str_label.size() > 1 && str_label[0] == '0' && str_label[1] == 'x') || - (str_label.size() > 0 && isdigit(str_label[0]))) - mask = strtol(str_label.c_str(), NULL, 0); - return mask; -} - -bool FbWinFrame::useBorder() const { - return !m_state.fullscreen && m_state.maximized != MAX_FULL && - (m_state.deco_mask & DECORM_BORDER); -} - -bool FbWinFrame::useTabs() const { - return !m_state.fullscreen && m_state.deco_mask & DECORM_TAB; -} - -bool FbWinFrame::useTitlebar() const { - return !m_state.fullscreen && m_state.deco_mask & DECORM_TITLEBAR; -} - -bool FbWinFrame::useHandle() const { - return !m_state.fullscreen && !m_state.shaded && - m_state.deco_mask & DECORM_HANDLE; -} - int FbWinFrame::getShape() const { int shape = theme()->shapePlace(); - if (!useTitlebar()) + if (!m_state.useTitlebar()) shape &= ~(FbTk::Shape::TOPRIGHT|FbTk::Shape::TOPLEFT); - if (!useHandle()) + if (!m_state.useHandle()) shape &= ~(FbTk::Shape::BOTTOMRIGHT|FbTk::Shape::BOTTOMLEFT); return shape; } @@ -1541,13 +1488,13 @@ void FbWinFrame::applyDecorations() { // tab deocration only affects if we're external // must do before the setTabMode in case it goes // to external and is meant to be hidden - if (useTabs()) + if (m_state.useTabs()) client_move |= showTabs(); else client_move |= hideTabs(); // we rely on frame not doing anything if it is already shown/hidden - if (useTitlebar()) { + if (m_state.useTitlebar()) { client_move |= showTitlebar(); if (m_screen.getDefaultInternalTabs()) client_move |= setTabMode(INTERNAL); @@ -1555,11 +1502,11 @@ void FbWinFrame::applyDecorations() { client_move |= setTabMode(EXTERNAL); } else { client_move |= hideTitlebar(); - if (useTabs()) + if (m_state.useTabs()) client_move |= setTabMode(EXTERNAL); } - if (useHandle()) + if (m_state.useHandle()) client_move |= showHandle(); else client_move |= hideHandle(); @@ -1581,7 +1528,7 @@ void FbWinFrame::applyDecorations() { bool FbWinFrame::setBorderWidth(bool do_move) { unsigned int border_width = theme()->border().width(); - unsigned int win_bw = useBorder() ? border_width : 0; + unsigned int win_bw = m_state.useBorder() ? border_width : 0; if (border_width && theme()->border().color().pixel() != window().borderColor()) { @@ -1717,30 +1664,6 @@ void FbWinFrame::gravityTranslate(int &x, int &y, } } -int FbWinFrame::normalX() const { - if ((m_state.maximized & MAX_HORZ) || m_state.fullscreen) - return m_state.x; - return x(); -} - -int FbWinFrame::normalY() const { - if ((m_state.maximized & MAX_VERT) || m_state.fullscreen) - return m_state.y; - return y(); -} - -unsigned int FbWinFrame::normalWidth() const { - if ((m_state.maximized & MAX_HORZ) || m_state.fullscreen) - return m_state.width; - return width(); -} - -unsigned int FbWinFrame::normalHeight() const { - if ((m_state.maximized & MAX_VERT) || m_state.fullscreen || m_state.shaded) - return m_state.height; - return height(); -} - int FbWinFrame::widthOffset() const { if (m_tabmode != EXTERNAL || !m_use_tabs) return 0; @@ -1825,201 +1748,3 @@ void FbWinFrame::displaySize(unsigned int width, unsigned int height) const { width, height - titlebarHeight() - handleHeight()); m_screen.showGeometry(i, j); } - -void FbWinFrame::SizeHints::reset(const XSizeHints &sizehint) { - if (sizehint.flags & PMinSize) { - min_width = sizehint.min_width; - min_height = sizehint.min_height; - } else - min_width = min_height = 1; - - if (sizehint.flags & PBaseSize) { - base_width = sizehint.base_width; - base_height = sizehint.base_height; - if (!(sizehint.flags & PMinSize)) { - min_width = base_width; - min_height = base_height; - } - } else - base_width = base_height = 0; - - if (sizehint.flags & PMaxSize) { - max_width = sizehint.max_width; - max_height = sizehint.max_height; - } else - max_width = max_height = 0; // unbounded - - if (sizehint.flags & PResizeInc) { - width_inc = sizehint.width_inc; - height_inc = sizehint.height_inc; - } else - width_inc = height_inc = 1; - - if (sizehint.flags & PAspect) { - min_aspect_x = sizehint.min_aspect.x; - min_aspect_y = sizehint.min_aspect.y; - max_aspect_x = sizehint.max_aspect.x; - max_aspect_y = sizehint.max_aspect.y; - } else { - min_aspect_x = max_aspect_y = 0; - min_aspect_y = max_aspect_x = 1; - } - - if (sizehint.flags & PWinGravity) - win_gravity = sizehint.win_gravity; - else - win_gravity = NorthWestGravity; - - // some sanity checks - if (width_inc == 0) - width_inc = 1; - if (height_inc == 0) - height_inc = 1; - - if (base_width > min_width) - min_width = base_width; - if (base_height > min_height) - min_height = base_height; -} - -/* 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); -} - -unsigned int increaseToMultiple(unsigned int val, unsigned int inc) { - return val % inc ? val + inc - (val % inc) : val; -} - -unsigned int decreaseToMultiple(unsigned int val, unsigned int inc) { - return val % inc ? val - (val % inc) : val; -} - -/** - * 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 make_fit) const { - - /* aspect ratios are applied exclusive to the base size - * - * min_aspect_x width max_aspect_x - * ------------ < ------- < ------------ - * min_aspect_y height max_aspect_y - * - * 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! - */ - - // make respective to base_size - unsigned int w = width - base_width, h = height - base_height; - - if (min_aspect_y > 0 && w * min_aspect_y < min_aspect_x * h) { - closestPointToAspect(w, h, w, h, min_aspect_x, min_aspect_y); - // new w must be > old w, new h must be < old h - w = increaseToMultiple(w, width_inc); - h = decreaseToMultiple(h, height_inc); - } else if (max_aspect_x > 0 && w * max_aspect_y > max_aspect_x * h) { - closestPointToAspect(w, h, w, h, max_aspect_x, max_aspect_y); - // new w must be < old w, new h must be > old h - w = decreaseToMultiple(w, width_inc); - h = increaseToMultiple(h, height_inc); - } - - // Check minimum size - if (w + base_width < min_width) { - w = increaseToMultiple(min_width - base_width, width_inc); - // need to check maximum aspect again - if (max_aspect_x > 0 && w * max_aspect_y > max_aspect_x * h) - h = increaseToMultiple(w * max_aspect_y / max_aspect_x, height_inc); - } - - if (h + base_height < min_height) { - h = increaseToMultiple(min_height - base_height, height_inc); - // need to check minimum aspect again - if (min_aspect_y > 0 && w * min_aspect_y < min_aspect_x * h) - w = increaseToMultiple(h * min_aspect_x / min_aspect_y, width_inc); - } - - unsigned int max_w = make_fit && (width < max_width || max_width == 0) ? - width : max_width; - unsigned int max_h = make_fit && (height < max_height || max_height == 0) ? - height : max_height; - - // Check maximum size - if (max_w > 0 && w + base_width > max_w) - w = max_w - base_width; - - if (max_h > 0 && h + base_height > max_h) - h = max_h - base_height; - - w = decreaseToMultiple(w, width_inc); - h = decreaseToMultiple(h, height_inc); - - // need to check aspects one more time - if (min_aspect_y > 0 && w * min_aspect_y < min_aspect_x * h) - h = decreaseToMultiple(w * min_aspect_y / min_aspect_x, height_inc); - - if (max_aspect_x > 0 && w * max_aspect_y > max_aspect_x * h) - w = decreaseToMultiple(h * max_aspect_x / max_aspect_y, width_inc); - - width = w + base_width; - height = h + base_height; -} - -// 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 - base_height) > (w - base_width) * min_aspect_y) - return false; - - if (max_aspect_x * (h - base_height) < (w - base_width) * max_aspect_y) - return false; - - return true; -} - -void FbWinFrame::SizeHints::displaySize(unsigned int &i, unsigned int &j, - unsigned int width, unsigned int height) const { - i = (width - base_width) / width_inc; - j = (height - base_height) / height_inc; -} diff --git a/src/FbWinFrame.hh b/src/FbWinFrame.hh index 55d47ed..4a33fec 100644 --- a/src/FbWinFrame.hh +++ b/src/FbWinFrame.hh @@ -33,6 +33,8 @@ #include "FbTk/Container.hh" #include "FbTk/Shape.hh" +#include "WindowState.hh" + #include <X11/Xutil.h> #include <vector> @@ -68,85 +70,6 @@ public: RIGHTBOTTOM, RIGHT, RIGHTTOP }; - /** - * Types of maximization - */ - enum MaximizeMode { - MAX_NONE = 0, ///< normal state - MAX_HORZ = 1, ///< maximize horizontal - MAX_VERT = 2, ///< maximize vertical - MAX_FULL = 3 ///< maximize full - }; - - /** - This enumeration represents individual decoration - attributes, they can be OR-d together to get a mask. - Useful for saving. - */ - enum DecorationMask { - DECORM_TITLEBAR = (1<<0), - DECORM_HANDLE = (1<<1), - DECORM_BORDER = (1<<2), - DECORM_ICONIFY = (1<<3), - DECORM_MAXIMIZE = (1<<4), - DECORM_CLOSE = (1<<5), - DECORM_MENU = (1<<6), - DECORM_STICKY = (1<<7), - DECORM_SHADE = (1<<8), - DECORM_TAB = (1<<9), - DECORM_ENABLED = (1<<10), - DECORM_LAST = (1<<11) // useful for getting "All" - }; - - enum Decoration { - DECOR_NONE = 0, - DECOR_NORMAL = DECORM_LAST - 1, - DECOR_TINY = DECORM_TITLEBAR|DECORM_ICONIFY|DECORM_MENU|DECORM_TAB, - DECOR_TOOL = DECORM_TITLEBAR|DECORM_MENU, - DECOR_BORDER = DECORM_BORDER|DECORM_MENU, - DECOR_TAB = DECORM_BORDER|DECORM_MENU|DECORM_TAB - }; - - class SizeHints { - public: - SizeHints(): - min_width(1), max_width(0), min_height(1), max_height(0), - width_inc(1), height_inc(1), base_width(0), base_height(0), - min_aspect_x(0), max_aspect_x(1), - min_aspect_y(1), max_aspect_y(0), - win_gravity(0) { } - - void reset(const XSizeHints &sizehint); - - void apply(unsigned int &w, unsigned int &h, - bool maximizing = false) const; - bool valid(unsigned int width, unsigned int height) const; - void displaySize(unsigned int &i, unsigned int &j, - unsigned int width, unsigned int height) const; - - unsigned int min_width, max_width, min_height, max_height, - width_inc, height_inc, base_width, base_height, - min_aspect_x, max_aspect_x, min_aspect_y, max_aspect_y; - int win_gravity; - }; - - class State { - public: - State(): - size_hints(), - deco_mask(DECOR_NORMAL), - focused(false), - shaded(false), fullscreen(false), maximized(0), - x(0), y(0), width(1), height(1) { } - - SizeHints size_hints; - unsigned int deco_mask; - bool focused, shaded, fullscreen; - int maximized; - int x, y; - unsigned int width, height; - }; - /// create a top level window FbWinFrame(BScreen &screen, FocusableTheme<FbWinFrameTheme> &theme, FbTk::ImageControl &imgctrl, @@ -247,18 +170,9 @@ public: bool maximizing = false) const; void displaySize(unsigned int width, unsigned int height) const; - static int getDecoMaskFromString(const std::string &str); void setDecorationMask(unsigned int mask) { m_state.deco_mask = mask; } void applyDecorations(); void applyState(); - void saveGeometry(); - - /// determine if the given decoration should be shown in current state - bool useBorder() const; - bool useTabs() const; - bool useTitlebar() const; - bool useHandle() const; - int getShape() const; // this function translates its arguments according to win_gravity // if win_gravity is negative, it does an inverse translation @@ -287,10 +201,10 @@ public: unsigned int width() const { return m_window.width(); } unsigned int height() const { return m_window.height(); } - int normalX() const; - int normalY() const; - unsigned int normalWidth() const; - unsigned int normalHeight() const; + int normalX() const { return m_state.x; } + int normalY() const { return m_state.y; } + unsigned int normalWidth() const { return m_state.width; } + unsigned int normalHeight() const { return m_state.height; } // extra bits for tabs int xOffset() const; @@ -368,6 +282,9 @@ private: bool showHandle(); bool setBorderWidth(bool do_move = true); + // check which corners should be rounded + int getShape() const; + /** @name apply pixmaps depending on focus */ @@ -463,7 +380,7 @@ private: TabMode m_tabmode; unsigned int m_active_orig_client_bw; - State m_state; + WindowState m_state; bool m_need_render; int m_button_size; ///< size for all titlebar buttons diff --git a/src/Makefile.am b/src/Makefile.am index 448a781..923b2cc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -113,7 +113,7 @@ fluxbox_SOURCES = AtomHandler.hh ArrowButton.hh ArrowButton.cc \ Slit.cc Slit.hh SlitTheme.hh SlitTheme.cc SlitClient.hh SlitClient.cc \ WinButton.hh WinButton.cc \ WinButtonTheme.hh WinButtonTheme.cc \ - Window.cc Window.hh \ + Window.cc Window.hh WindowState.cc WindowState.hh\ Workspace.cc Workspace.hh \ FbCommands.hh FbCommands.cc LayerMenu.hh LayerMenu.cc \ Layer.hh \ diff --git a/src/Remember.cc b/src/Remember.cc index 1df5045..0ea8a6c 100644 --- a/src/Remember.cc +++ b/src/Remember.cc @@ -500,7 +500,7 @@ int parseApp(ifstream &file, Application &app, string *first_line = 0) { app.rememberIconHiddenstate((strcasecmp(str_label.c_str(), "yes") == 0)); app.rememberFocusHiddenstate((strcasecmp(str_label.c_str(), "yes") == 0)); } else if (str_key == "deco") { - int deco = FbWinFrame::getDecoMaskFromString(str_label); + int deco = WindowState::getDecoMaskFromString(str_label); if (deco == -1) had_error = 1; else @@ -535,13 +535,13 @@ int parseApp(ifstream &file, Application &app, string *first_line = 0) { app.rememberMinimizedstate((strcasecmp(str_label.c_str(), "yes") == 0)); } else if (str_key == "maximized") { if (strcasecmp(str_label.c_str(), "yes") == 0) - app.rememberMaximizedstate(FbWinFrame::MAX_FULL); + app.rememberMaximizedstate(WindowState::MAX_FULL); else if (strcasecmp(str_label.c_str(), "horz") == 0) - app.rememberMaximizedstate(FbWinFrame::MAX_HORZ); + app.rememberMaximizedstate(WindowState::MAX_HORZ); else if (strcasecmp(str_label.c_str(), "vert") == 0) - app.rememberMaximizedstate(FbWinFrame::MAX_VERT); + app.rememberMaximizedstate(WindowState::MAX_VERT); else - app.rememberMaximizedstate(FbWinFrame::MAX_NONE); + app.rememberMaximizedstate(WindowState::MAX_NONE); } else if (str_key == "fullscreen") { app.rememberFullscreenstate((strcasecmp(str_label.c_str(), "yes") == 0)); } else if (str_key == "jump") { @@ -953,25 +953,25 @@ void Remember::save() { apps_file << " [Deco]\t{NONE}" << endl; break; case (0xffffffff): - case (FbWinFrame::DECORM_LAST - 1): + case (WindowState::DECORM_LAST - 1): apps_file << " [Deco]\t{NORMAL}" << endl; break; - case (FbWinFrame::DECORM_TITLEBAR - | FbWinFrame::DECORM_ICONIFY - | FbWinFrame::DECORM_MENU): + case (WindowState::DECORM_TITLEBAR + | WindowState::DECORM_ICONIFY + | WindowState::DECORM_MENU): apps_file << " [Deco]\t{TOOL}" << endl; break; - case (FbWinFrame::DECORM_TITLEBAR - | FbWinFrame::DECORM_MENU): + case (WindowState::DECORM_TITLEBAR + | WindowState::DECORM_MENU): apps_file << " [Deco]\t{TINY}" << endl; break; - case (FbWinFrame::DECORM_BORDER - | FbWinFrame::DECORM_MENU): + case (WindowState::DECORM_BORDER + | WindowState::DECORM_MENU): apps_file << " [Deco]\t{BORDER}" << endl; break; - case (FbWinFrame::DECORM_BORDER - | FbWinFrame::DECORM_MENU - | FbWinFrame::DECORM_TAB): + case (WindowState::DECORM_BORDER + | WindowState::DECORM_MENU + | WindowState::DECORM_TAB): apps_file << " [Deco]\t{TAB}" << endl; break; default: @@ -999,16 +999,16 @@ void Remember::save() { if (a.maximizedstate_remember) { apps_file << " [Maximized]\t{"; switch (a.maximizedstate) { - case FbWinFrame::MAX_FULL: + case WindowState::MAX_FULL: apps_file << "yes" << "}" << endl; break; - case FbWinFrame::MAX_HORZ: + case WindowState::MAX_HORZ: apps_file << "horz" << "}" << endl; break; - case FbWinFrame::MAX_VERT: + case WindowState::MAX_VERT: apps_file << "vert" << "}" << endl; break; - case FbWinFrame::MAX_NONE: + case WindowState::MAX_NONE: default: apps_file << "no" << "}" << endl; break; diff --git a/src/WinClient.hh b/src/WinClient.hh index 18c9b0b..1903040 100644 --- a/src/WinClient.hh +++ b/src/WinClient.hh @@ -22,8 +22,9 @@ #ifndef WINCLIENT_HH #define WINCLIENT_HH -#include "FbWinFrame.hh" #include "Window.hh" +#include "WindowState.hh" + #include "FbTk/FbWindow.hh" #include "FbTk/FbString.hh" @@ -114,7 +115,7 @@ public: Window getGroupLeftWindow() const; const MwmHints *getMwmHint() const { return m_mwm_hint; } - const FbWinFrame::SizeHints &sizeHints() const { return m_size_hints; } + const SizeHints &sizeHints() const { return m_size_hints; } unsigned int minWidth() const { return m_size_hints.min_width; } unsigned int minHeight() const { return m_size_hints.min_height; } @@ -157,7 +158,7 @@ private: Focusable::WindowType m_window_type; MwmHints *m_mwm_hint; - FbWinFrame::SizeHints m_size_hints; + SizeHints m_size_hints; Strut *m_strut; // map transient_for X window to winclient transient diff --git a/src/Window.cc b/src/Window.cc index 4b77b95..25a6baf 100644 --- a/src/Window.cc +++ b/src/Window.cc @@ -271,7 +271,7 @@ FluxboxWindow::FluxboxWindow(WinClient &client, FbTk::XLayer &layer): m_creation_time(0), moving(false), resizing(false), shaded(false), iconic(false), stuck(false), m_initialized(false), fullscreen(false), - maximized(FbWinFrame::MAX_NONE), + maximized(WindowState::MAX_NONE), m_attaching_tab(0), display(FbTk::App::instance()->display()), m_button_grab_x(0), m_button_grab_y(0), @@ -423,7 +423,7 @@ void FluxboxWindow::init() { m_workspace_number = m_screen.currentWorkspaceID(); // set default decorations but don't apply them - setDecorationMask(FbWinFrame::getDecoMaskFromString(screen().defaultDeco()), + setDecorationMask(WindowState::getDecoMaskFromString(screen().defaultDeco()), false); functions.resize = functions.move = functions.iconify = functions.maximize @@ -559,7 +559,7 @@ void FluxboxWindow::init() { if (maximized) { int tmp = maximized; - maximized = FbWinFrame::MAX_NONE; + maximized = WindowState::MAX_NONE; setMaximizedState(tmp); } @@ -1045,7 +1045,7 @@ void FluxboxWindow::updateSizeHints() { if ((*it) == m_client) continue; - const FbWinFrame::SizeHints &hint = (*it)->sizeHints(); + const SizeHints &hint = (*it)->sizeHints(); if (m_size_hint.min_width < hint.min_width) m_size_hint.min_width = hint.min_width; if (m_size_hint.max_width > hint.max_width) @@ -1144,7 +1144,7 @@ void FluxboxWindow::updateMWMHintsFromClient(WinClient &client) { } unsigned int mask = decorationMask(); - mask &= FbWinFrame::getDecoMaskFromString(screen().defaultDeco()); + mask &= WindowState::getDecoMaskFromString(screen().defaultDeco()); setDecorationMask(mask, false); // functions.tabable is ours, not special one @@ -1503,7 +1503,7 @@ void FluxboxWindow::setFullscreenLayer() { void FluxboxWindow::maximize(int type) { // nothing to do - if (type == FbWinFrame::MAX_NONE) + if (type == WindowState::MAX_NONE) return; int new_max = maximized; @@ -1512,14 +1512,14 @@ void FluxboxWindow::maximize(int type) { // when _don't_ we want to toggle? // - type is horizontal maximise, or // - type is full and we are not maximised horz but already vertically - if (type != FbWinFrame::MAX_HORZ && - (type != FbWinFrame::MAX_FULL || maximized != FbWinFrame::MAX_VERT)) - new_max ^= FbWinFrame::MAX_VERT; + if (type != WindowState::MAX_HORZ && + (type != WindowState::MAX_FULL || maximized != WindowState::MAX_VERT)) + new_max ^= WindowState::MAX_VERT; // maximize horizontally? - if (type != FbWinFrame::MAX_VERT && - (type != FbWinFrame::MAX_FULL || maximized != FbWinFrame::MAX_HORZ)) - new_max ^= FbWinFrame::MAX_HORZ; + if (type != WindowState::MAX_VERT && + (type != WindowState::MAX_FULL || maximized != WindowState::MAX_HORZ)) + new_max ^= WindowState::MAX_HORZ; setMaximizedState(new_max); } @@ -1552,21 +1552,21 @@ void FluxboxWindow::setMaximizedState(int type) { * Maximize window horizontal */ void FluxboxWindow::maximizeHorizontal() { - maximize(FbWinFrame::MAX_HORZ); + maximize(WindowState::MAX_HORZ); } /** * Maximize window vertical */ void FluxboxWindow::maximizeVertical() { - maximize(FbWinFrame::MAX_VERT); + maximize(WindowState::MAX_VERT); } /** * Maximize window fully */ void FluxboxWindow::maximizeFull() { - maximize(FbWinFrame::MAX_FULL); + maximize(WindowState::MAX_FULL); } void FluxboxWindow::setWorkspace(int n) { @@ -2807,9 +2807,9 @@ void FluxboxWindow::toggleDecoration() { if (m_toggled_decos) { m_old_decoration_mask = decorationMask(); if (decorations.titlebar | decorations.tab) - setDecorationMask(FbWinFrame::DECOR_NONE); + setDecorationMask(WindowState::DECOR_NONE); else - setDecorationMask(FbWinFrame::DECOR_NORMAL); + setDecorationMask(WindowState::DECOR_NORMAL); } else //revert back to old decoration setDecorationMask(m_old_decoration_mask); @@ -2818,42 +2818,42 @@ void FluxboxWindow::toggleDecoration() { unsigned int FluxboxWindow::decorationMask() const { unsigned int ret = 0; if (decorations.titlebar) - ret |= FbWinFrame::DECORM_TITLEBAR; + ret |= WindowState::DECORM_TITLEBAR; if (decorations.handle) - ret |= FbWinFrame::DECORM_HANDLE; + ret |= WindowState::DECORM_HANDLE; if (decorations.border) - ret |= FbWinFrame::DECORM_BORDER; + ret |= WindowState::DECORM_BORDER; if (decorations.iconify) - ret |= FbWinFrame::DECORM_ICONIFY; + ret |= WindowState::DECORM_ICONIFY; if (decorations.maximize) - ret |= FbWinFrame::DECORM_MAXIMIZE; + ret |= WindowState::DECORM_MAXIMIZE; if (decorations.close) - ret |= FbWinFrame::DECORM_CLOSE; + ret |= WindowState::DECORM_CLOSE; if (decorations.menu) - ret |= FbWinFrame::DECORM_MENU; + ret |= WindowState::DECORM_MENU; if (decorations.sticky) - ret |= FbWinFrame::DECORM_STICKY; + ret |= WindowState::DECORM_STICKY; if (decorations.shade) - ret |= FbWinFrame::DECORM_SHADE; + ret |= WindowState::DECORM_SHADE; if (decorations.tab) - ret |= FbWinFrame::DECORM_TAB; + ret |= WindowState::DECORM_TAB; if (decorations.enabled) - ret |= FbWinFrame::DECORM_ENABLED; + ret |= WindowState::DECORM_ENABLED; return ret; } void FluxboxWindow::setDecorationMask(unsigned int mask, bool apply) { - decorations.titlebar = mask & FbWinFrame::DECORM_TITLEBAR; - decorations.handle = mask & FbWinFrame::DECORM_HANDLE; - decorations.border = mask & FbWinFrame::DECORM_BORDER; - decorations.iconify = mask & FbWinFrame::DECORM_ICONIFY; - decorations.maximize = mask & FbWinFrame::DECORM_MAXIMIZE; - decorations.close = mask & FbWinFrame::DECORM_CLOSE; - decorations.menu = mask & FbWinFrame::DECORM_MENU; - decorations.sticky = mask & FbWinFrame::DECORM_STICKY; - decorations.shade = mask & FbWinFrame::DECORM_SHADE; - decorations.tab = mask & FbWinFrame::DECORM_TAB; - decorations.enabled = mask & FbWinFrame::DECORM_ENABLED; + decorations.titlebar = mask & WindowState::DECORM_TITLEBAR; + decorations.handle = mask & WindowState::DECORM_HANDLE; + decorations.border = mask & WindowState::DECORM_BORDER; + decorations.iconify = mask & WindowState::DECORM_ICONIFY; + decorations.maximize = mask & WindowState::DECORM_MAXIMIZE; + decorations.close = mask & WindowState::DECORM_CLOSE; + decorations.menu = mask & WindowState::DECORM_MENU; + decorations.sticky = mask & WindowState::DECORM_STICKY; + decorations.shade = mask & WindowState::DECORM_SHADE; + decorations.tab = mask & WindowState::DECORM_TAB; + decorations.enabled = mask & WindowState::DECORM_ENABLED; // we don't want to do this during initialization if (apply) applyDecorations(); @@ -3024,7 +3024,7 @@ void FluxboxWindow::doSnapping(int &orig_left, int &orig_top) { // we only care about the left/top etc that includes borders int borderW = 0; - if (decorationMask() & (FbWinFrame::DECORM_BORDER|FbWinFrame::DECORM_HANDLE)) + if (decorationMask() & (WindowState::DECORM_BORDER|WindowState::DECORM_HANDLE)) borderW = frame().window().borderWidth(); int top = orig_top; // orig include the borders @@ -3096,7 +3096,7 @@ void FluxboxWindow::doSnapping(int &orig_left, int &orig_top) { if ((*it) == this) continue; // skip myself - bw = (*it)->decorationMask() & (FbWinFrame::DECORM_BORDER|FbWinFrame::DECORM_HANDLE) ? + bw = (*it)->decorationMask() & (WindowState::DECORM_BORDER|WindowState::DECORM_HANDLE) ? (*it)->frame().window().borderWidth() : 0; snapToWindow(dx, dy, left, right, top, bottom, @@ -3175,7 +3175,7 @@ void FluxboxWindow::startResizing(int x, int y, ReferenceCorner dir) { m_resize_corner = dir; resizing = true; - maximized = FbWinFrame::MAX_NONE; + maximized = WindowState::MAX_NONE; frame().setMaximized(maximized); const Cursor& cursor = (m_resize_corner == LEFTTOP) ? frame().theme()->upperLeftAngleCursor() : @@ -3862,7 +3862,7 @@ void FluxboxWindow::setWindowType(Focusable::WindowType type) { setFocusNew(false); setMouseFocus(false); setClickFocus(false); - setDecorationMask(FbWinFrame::DECOR_NONE); + setDecorationMask(WindowState::DECOR_NONE); moveToLayer(::Layer::DOCK); break; case Focusable::TYPE_DESKTOP: @@ -3877,7 +3877,7 @@ void FluxboxWindow::setWindowType(Focusable::WindowType type) { setFocusNew(false); setMouseFocus(false); moveToLayer(::Layer::DESKTOP); - setDecorationMask(FbWinFrame::DECOR_NONE); + setDecorationMask(WindowState::DECOR_NONE); setTabable(false); setMovable(false); setResizable(false); @@ -3889,7 +3889,7 @@ void FluxboxWindow::setWindowType(Focusable::WindowType type) { * window is a splash screen displayed as an application * is starting up. */ - setDecorationMask(FbWinFrame::DECOR_NONE); + setDecorationMask(WindowState::DECOR_NONE); setFocusHidden(true); setIconHidden(true); setFocusNew(false); @@ -3909,7 +3909,7 @@ void FluxboxWindow::setWindowType(Focusable::WindowType type) { * application). Windows of this type may set the * WM_TRANSIENT_FOR hint indicating the main application window. */ - setDecorationMask(FbWinFrame::DECOR_TOOL); + setDecorationMask(WindowState::DECOR_TOOL); setIconHidden(true); moveToLayer(::Layer::ABOVE_DOCK); break; diff --git a/src/Window.hh b/src/Window.hh index 89cbc69..2dbb816 100644 --- a/src/Window.hh +++ b/src/Window.hh @@ -31,6 +31,7 @@ #include "FbTk/Observer.hh" #include "FbTk/EventHandler.hh" #include "FbTk/XLayerItem.hh" + #include "FbWinFrame.hh" #include "Focusable.hh" #include "FocusableTheme.hh" @@ -45,7 +46,6 @@ class WinClient; class FbWinFrameTheme; class BScreen; -class FbWinFrame; class FocusControl; class FbMenu; @@ -212,7 +212,7 @@ public: /// set fullscreen void setFullscreen(bool flag); /// toggle maximize - void maximize(int type = FbWinFrame::MAX_FULL); + void maximize(int type = WindowState::MAX_FULL); /// sets the maximized state void setMaximizedState(int type); /// maximizes the window horizontal @@ -373,9 +373,9 @@ public: bool isIconic() const { return iconic; } bool isShaded() const { return shaded; } bool isFullscreen() const { return fullscreen; } - bool isMaximized() const { return maximized == FbWinFrame::MAX_FULL; } - bool isMaximizedVert() const { return (bool)(maximized & FbWinFrame::MAX_VERT); } - bool isMaximizedHorz() const { return (bool)(maximized & FbWinFrame::MAX_HORZ); } + bool isMaximized() const { return maximized == WindowState::MAX_FULL; } + bool isMaximizedVert() const { return (bool)(maximized & WindowState::MAX_VERT); } + bool isMaximizedHorz() const { return (bool)(maximized & WindowState::MAX_HORZ); } int maximizedState() const { return maximized; } bool isIconifiable() const { return functions.iconify; } bool isMaximizable() const { return functions.maximize; } @@ -553,7 +553,7 @@ private: typedef std::map<WinClient *, IconButton *> Client2ButtonMap; Client2ButtonMap m_labelbuttons; - FbWinFrame::SizeHints m_size_hint; + SizeHints m_size_hint; struct _decorations { bool titlebar, handle, border, iconify, maximize, close, menu, sticky, shade, tab, enabled; diff --git a/src/WindowState.cc b/src/WindowState.cc new file mode 100644 index 0000000..2f8fd4e --- /dev/null +++ b/src/WindowState.cc @@ -0,0 +1,266 @@ +// WindowState.cc +// Copyright (c) 2008 Fluxbox Team (fluxgen at fluxbox dot org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#include "WindowState.hh" + +#include "FbTk/StringUtil.hh" + +#include <stdlib.h> + +bool WindowState::useBorder() const { + return !fullscreen && maximized != MAX_FULL && deco_mask & DECORM_BORDER; +} + +bool WindowState::useHandle() const { + return !fullscreen && !shaded && deco_mask & DECORM_HANDLE; +} + +bool WindowState::useTabs() const { + return !fullscreen && deco_mask & DECORM_TAB; +} + +bool WindowState::useTitlebar() const { + return !fullscreen && deco_mask & DECORM_TITLEBAR; +} + +void WindowState::saveGeometry(int new_x, int new_y, + unsigned int new_w, unsigned int new_h) { + if (fullscreen || maximized == MAX_FULL) + return; + + if (!(maximized & MAX_HORZ)) { + x = new_x; + width = new_w; + } + if (!(maximized & MAX_VERT)) { + y = new_y; + if (!shaded) + height = new_h; + } +} + +int WindowState::getDecoMaskFromString(const std::string &str_label) { + std::string label = FbTk::StringUtil::toLower(str_label); + if (label == "none") + return DECOR_NONE; + if (label == "normal") + return DECOR_NORMAL; + if (label == "tiny") + return DECOR_TINY; + if (label == "tool") + return DECOR_TOOL; + if (label == "border") + return DECOR_BORDER; + if (label == "tab") + return DECOR_TAB; + int mask = -1; + if ((str_label.size() > 1 && str_label[0] == '0' && str_label[1] == 'x') || + (str_label.size() > 0 && isdigit(str_label[0]))) + mask = strtol(str_label.c_str(), NULL, 0); + return mask; +} + +void SizeHints::reset(const XSizeHints &sizehint) { + if (sizehint.flags & PMinSize) { + min_width = sizehint.min_width; + min_height = sizehint.min_height; + } else + min_width = min_height = 1; + + if (sizehint.flags & PBaseSize) { + base_width = sizehint.base_width; + base_height = sizehint.base_height; + if (!(sizehint.flags & PMinSize)) { + min_width = base_width; + min_height = base_height; + } + } else + base_width = base_height = 0; + + if (sizehint.flags & PMaxSize) { + max_width = sizehint.max_width; + max_height = sizehint.max_height; + } else + max_width = max_height = 0; // unbounded + + if (sizehint.flags & PResizeInc) { + width_inc = sizehint.width_inc; + height_inc = sizehint.height_inc; + } else + width_inc = height_inc = 1; + + if (sizehint.flags & PAspect) { + min_aspect_x = sizehint.min_aspect.x; + min_aspect_y = sizehint.min_aspect.y; + max_aspect_x = sizehint.max_aspect.x; + max_aspect_y = sizehint.max_aspect.y; + } else { + min_aspect_x = max_aspect_y = 0; + min_aspect_y = max_aspect_x = 1; + } + + if (sizehint.flags & PWinGravity) + win_gravity = sizehint.win_gravity; + else + win_gravity = NorthWestGravity; + + // some sanity checks + if (width_inc == 0) + width_inc = 1; + if (height_inc == 0) + height_inc = 1; + + if (base_width > min_width) + min_width = base_width; + if (base_height > min_height) + min_height = base_height; +} + +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); +} + +unsigned int increaseToMultiple(unsigned int val, unsigned int inc) { + return val % inc ? val + inc - (val % inc) : val; +} + +unsigned int decreaseToMultiple(unsigned int val, unsigned int inc) { + return val % inc ? val - (val % inc) : val; +} + +/** + * 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 SizeHints::apply(unsigned int &width, unsigned int &height, + bool make_fit) const { + + /* aspect ratios are applied exclusive to the base size + * + * min_aspect_x width max_aspect_x + * ------------ < ------- < ------------ + * min_aspect_y height max_aspect_y + * + * 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! + */ + + // make respective to base_size + unsigned int w = width - base_width, h = height - base_height; + + if (min_aspect_y > 0 && w * min_aspect_y < min_aspect_x * h) { + closestPointToAspect(w, h, w, h, min_aspect_x, min_aspect_y); + // new w must be > old w, new h must be < old h + w = increaseToMultiple(w, width_inc); + h = decreaseToMultiple(h, height_inc); + } else if (max_aspect_x > 0 && w * max_aspect_y > max_aspect_x * h) { + closestPointToAspect(w, h, w, h, max_aspect_x, max_aspect_y); + // new w must be < old w, new h must be > old h + w = decreaseToMultiple(w, width_inc); + h = increaseToMultiple(h, height_inc); + } + + // Check minimum size + if (w + base_width < min_width) { + w = increaseToMultiple(min_width - base_width, width_inc); + // need to check maximum aspect again + if (max_aspect_x > 0 && w * max_aspect_y > max_aspect_x * h) + h = increaseToMultiple(w * max_aspect_y / max_aspect_x, height_inc); + } + + if (h + base_height < min_height) { + h = increaseToMultiple(min_height - base_height, height_inc); + // need to check minimum aspect again + if (min_aspect_y > 0 && w * min_aspect_y < min_aspect_x * h) + w = increaseToMultiple(h * min_aspect_x / min_aspect_y, width_inc); + } + + unsigned int max_w = make_fit && (width < max_width || max_width == 0) ? + width : max_width; + unsigned int max_h = make_fit && (height < max_height || max_height == 0) ? + height : max_height; + + // Check maximum size + if (max_w > 0 && w + base_width > max_w) + w = max_w - base_width; + + if (max_h > 0 && h + base_height > max_h) + h = max_h - base_height; + + w = decreaseToMultiple(w, width_inc); + h = decreaseToMultiple(h, height_inc); + + // need to check aspects one more time + if (min_aspect_y > 0 && w * min_aspect_y < min_aspect_x * h) + h = decreaseToMultiple(w * min_aspect_y / min_aspect_x, height_inc); + + if (max_aspect_x > 0 && w * max_aspect_y > max_aspect_x * h) + w = decreaseToMultiple(h * max_aspect_x / max_aspect_y, width_inc); + + width = w + base_width; + height = h + base_height; +} + +// check if the given width and height satisfy the size hints +bool 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 - base_height) > (w - base_width) * min_aspect_y) + return false; + + if (max_aspect_x * (h - base_height) < (w - base_width) * max_aspect_y) + return false; + + return true; +} + +void SizeHints::displaySize(unsigned int &i, unsigned int &j, + unsigned int width, unsigned int height) const { + i = (width - base_width) / width_inc; + j = (height - base_height) / height_inc; +} diff --git a/src/WindowState.hh b/src/WindowState.hh new file mode 100644 index 0000000..fa17eb6 --- /dev/null +++ b/src/WindowState.hh @@ -0,0 +1,118 @@ +// WindowState.hh +// Copyright (c) 2008 Fluxbox Team (fluxgen at fluxbox dot org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifndef WINDOWSTATE_HH +#define WINDOWSTATE_HH + +#include <X11/Xutil.h> + +#include <string> + +class SizeHints { +public: + SizeHints(): + min_width(1), max_width(0), min_height(1), max_height(0), + width_inc(1), height_inc(1), base_width(0), base_height(0), + min_aspect_x(0), max_aspect_x(1), + min_aspect_y(1), max_aspect_y(0), + win_gravity(0) { } + + void reset(const XSizeHints &sizehint); + + void apply(unsigned int &w, unsigned int &h, + bool maximizing = false) const; + bool valid(unsigned int width, unsigned int height) const; + void displaySize(unsigned int &i, unsigned int &j, + unsigned int width, unsigned int height) const; + + unsigned int min_width, max_width, min_height, max_height, + width_inc, height_inc, base_width, base_height, + min_aspect_x, max_aspect_x, min_aspect_y, max_aspect_y; + int win_gravity; +}; + +class WindowState { +public: + + /** + * Types of maximization + */ + enum MaximizeMode { + MAX_NONE = 0, ///< normal state + MAX_HORZ = 1, ///< maximize horizontal + MAX_VERT = 2, ///< maximize vertical + MAX_FULL = 3 ///< maximize full + }; + + /** + This enumeration represents individual decoration + attributes, they can be OR-d together to get a mask. + Useful for saving. + */ + enum DecorationMask { + DECORM_TITLEBAR = (1<<0), + DECORM_HANDLE = (1<<1), + DECORM_BORDER = (1<<2), + DECORM_ICONIFY = (1<<3), + DECORM_MAXIMIZE = (1<<4), + DECORM_CLOSE = (1<<5), + DECORM_MENU = (1<<6), + DECORM_STICKY = (1<<7), + DECORM_SHADE = (1<<8), + DECORM_TAB = (1<<9), + DECORM_ENABLED = (1<<10), + DECORM_LAST = (1<<11) // useful for getting "All" + }; + + enum Decoration { + DECOR_NONE = 0, + DECOR_NORMAL = DECORM_LAST - 1, + DECOR_TINY = DECORM_TITLEBAR|DECORM_ICONIFY|DECORM_MENU|DECORM_TAB, + DECOR_TOOL = DECORM_TITLEBAR|DECORM_MENU, + DECOR_BORDER = DECORM_BORDER|DECORM_MENU, + DECOR_TAB = DECORM_BORDER|DECORM_MENU|DECORM_TAB + }; + + WindowState(): + size_hints(), + deco_mask(DECOR_NORMAL), + focused(false), + shaded(false), fullscreen(false), maximized(0), + x(0), y(0), width(1), height(1) { } + + void saveGeometry(int x, int y, unsigned int width, unsigned int height); + + bool useBorder() const; + bool useHandle() const; + bool useTabs() const; + bool useTitlebar() const; + + static int getDecoMaskFromString(const std::string &str); + + SizeHints size_hints; + unsigned int deco_mask; + bool focused, shaded, fullscreen; + int maximized; + int x, y; + unsigned int width, height; +}; + +#endif // WINDOWSTATE_HH -- cgit v0.11.2