move FbWinFrame::State class to a new file

This commit is contained in:
Mark Tiefenbruck 2008-08-27 13:05:49 -04:00
parent 08c8c6431f
commit 55fd49614b
10 changed files with 486 additions and 459 deletions

View file

@ -503,7 +503,7 @@ void SetTitleCmd::real_execute() {
REGISTER_COMMAND_WITH_ARGS(setdecor, SetDecorCmd, void); REGISTER_COMMAND_WITH_ARGS(setdecor, SetDecorCmd, void);
SetDecorCmd::SetDecorCmd(const std::string &args): SetDecorCmd::SetDecorCmd(const std::string &args):
m_mask(FbWinFrame::getDecoMaskFromString(args)) { } m_mask(WindowState::getDecoMaskFromString(args)) { }
void SetDecorCmd::real_execute() { void SetDecorCmd::real_execute() {
fbwindow().setDecorationMask(m_mask); fbwindow().setDecorationMask(m_mask);

View file

@ -28,7 +28,6 @@
#include "FbTk/Compose.hh" #include "FbTk/Compose.hh"
#include "FbTk/Transparent.hh" #include "FbTk/Transparent.hh"
#include "FbTk/CompareEqual.hh" #include "FbTk/CompareEqual.hh"
#include "FbTk/StringUtil.hh"
#include "FbTk/TextUtils.hh" #include "FbTk/TextUtils.hh"
#include "FbWinFrameTheme.hh" #include "FbWinFrameTheme.hh"
@ -194,7 +193,7 @@ void FbWinFrame::show() {
Toggle shade state, and resize window Toggle shade state, and resize window
*/ */
void FbWinFrame::shade() { void FbWinFrame::shade() {
if (!(m_state.deco_mask & DECORM_TITLEBAR)) if (!(m_state.deco_mask & WindowState::DECORM_TITLEBAR))
return; return;
// toggle shade // toggle shade
@ -254,7 +253,8 @@ void FbWinFrame::moveResize(int x, int y, unsigned int width, unsigned int heigh
m_window.resize(width, height); m_window.resize(width, height);
} }
saveGeometry(); m_state.saveGeometry(window().x(), window().y(),
window().width(), window().height());
if (move || (resize && m_screen.getTabPlacement() != TOPLEFT && if (move || (resize && m_screen.getTabPlacement() != TOPLEFT &&
m_screen.getTabPlacement() != LEFTTOP)) 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, void FbWinFrame::quietMoveResize(int x, int y,
unsigned int width, unsigned int height) { unsigned int width, unsigned int height) {
m_window.moveResize(x, y, width, height); m_window.moveResize(x, y, width, height);
saveGeometry(); m_state.saveGeometry(window().x(), window().y(),
window().width(), window().height());
if (m_tabmode == EXTERNAL) { if (m_tabmode == EXTERNAL) {
switch(m_screen.getTabPlacement()) { switch(m_screen.getTabPlacement()) {
@ -534,21 +535,6 @@ void FbWinFrame::setMaximized(int value) {
applyState(); 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() { void FbWinFrame::applyState() {
applyDecorations(); applyDecorations();
@ -556,7 +542,7 @@ void FbWinFrame::applyState() {
int new_x = m_state.x, new_y = m_state.y; int new_x = m_state.x, new_y = m_state.y;
unsigned int new_w = m_state.width, new_h = m_state.height; 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_y = m_screen.maxTop(head);
new_h = m_screen.maxBottom(head) - new_y - 2*window().borderWidth(); new_h = m_screen.maxBottom(head) - new_y - 2*window().borderWidth();
if (!m_screen.getMaxOverTabs()) { if (!m_screen.getMaxOverTabs()) {
@ -564,7 +550,7 @@ void FbWinFrame::applyState() {
new_h -= heightOffset(); new_h -= heightOffset();
} }
} }
if (m_state.maximized & MAX_HORZ) { if (m_state.maximized & WindowState::MAX_HORZ) {
new_x = m_screen.maxLeft(head); new_x = m_screen.maxLeft(head);
new_w = m_screen.maxRight(head) - new_x - 2*window().borderWidth(); new_w = m_screen.maxRight(head) - new_x - 2*window().borderWidth();
if (!m_screen.getMaxOverTabs()) { 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 FbWinFrame::getShape() const {
int shape = theme()->shapePlace(); int shape = theme()->shapePlace();
if (!useTitlebar()) if (!m_state.useTitlebar())
shape &= ~(FbTk::Shape::TOPRIGHT|FbTk::Shape::TOPLEFT); shape &= ~(FbTk::Shape::TOPRIGHT|FbTk::Shape::TOPLEFT);
if (!useHandle()) if (!m_state.useHandle())
shape &= ~(FbTk::Shape::BOTTOMRIGHT|FbTk::Shape::BOTTOMLEFT); shape &= ~(FbTk::Shape::BOTTOMRIGHT|FbTk::Shape::BOTTOMLEFT);
return shape; return shape;
} }
@ -1541,13 +1488,13 @@ void FbWinFrame::applyDecorations() {
// tab deocration only affects if we're external // tab deocration only affects if we're external
// must do before the setTabMode in case it goes // must do before the setTabMode in case it goes
// to external and is meant to be hidden // to external and is meant to be hidden
if (useTabs()) if (m_state.useTabs())
client_move |= showTabs(); client_move |= showTabs();
else else
client_move |= hideTabs(); client_move |= hideTabs();
// we rely on frame not doing anything if it is already shown/hidden // we rely on frame not doing anything if it is already shown/hidden
if (useTitlebar()) { if (m_state.useTitlebar()) {
client_move |= showTitlebar(); client_move |= showTitlebar();
if (m_screen.getDefaultInternalTabs()) if (m_screen.getDefaultInternalTabs())
client_move |= setTabMode(INTERNAL); client_move |= setTabMode(INTERNAL);
@ -1555,11 +1502,11 @@ void FbWinFrame::applyDecorations() {
client_move |= setTabMode(EXTERNAL); client_move |= setTabMode(EXTERNAL);
} else { } else {
client_move |= hideTitlebar(); client_move |= hideTitlebar();
if (useTabs()) if (m_state.useTabs())
client_move |= setTabMode(EXTERNAL); client_move |= setTabMode(EXTERNAL);
} }
if (useHandle()) if (m_state.useHandle())
client_move |= showHandle(); client_move |= showHandle();
else else
client_move |= hideHandle(); client_move |= hideHandle();
@ -1581,7 +1528,7 @@ void FbWinFrame::applyDecorations() {
bool FbWinFrame::setBorderWidth(bool do_move) { bool FbWinFrame::setBorderWidth(bool do_move) {
unsigned int border_width = theme()->border().width(); 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 && if (border_width &&
theme()->border().color().pixel() != window().borderColor()) { 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 { int FbWinFrame::widthOffset() const {
if (m_tabmode != EXTERNAL || !m_use_tabs) if (m_tabmode != EXTERNAL || !m_use_tabs)
return 0; return 0;
@ -1825,201 +1748,3 @@ void FbWinFrame::displaySize(unsigned int width, unsigned int height) const {
width, height - titlebarHeight() - handleHeight()); width, height - titlebarHeight() - handleHeight());
m_screen.showGeometry(i, j); 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;
}

View file

@ -33,6 +33,8 @@
#include "FbTk/Container.hh" #include "FbTk/Container.hh"
#include "FbTk/Shape.hh" #include "FbTk/Shape.hh"
#include "WindowState.hh"
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <vector> #include <vector>
@ -68,85 +70,6 @@ public:
RIGHTBOTTOM, RIGHT, RIGHTTOP 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 /// create a top level window
FbWinFrame(BScreen &screen, FocusableTheme<FbWinFrameTheme> &theme, FbWinFrame(BScreen &screen, FocusableTheme<FbWinFrameTheme> &theme,
FbTk::ImageControl &imgctrl, FbTk::ImageControl &imgctrl,
@ -247,18 +170,9 @@ public:
bool maximizing = false) const; bool maximizing = false) const;
void displaySize(unsigned int width, unsigned int height) 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 setDecorationMask(unsigned int mask) { m_state.deco_mask = mask; }
void applyDecorations(); void applyDecorations();
void applyState(); 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 // this function translates its arguments according to win_gravity
// if win_gravity is negative, it does an inverse translation // 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 width() const { return m_window.width(); }
unsigned int height() const { return m_window.height(); } unsigned int height() const { return m_window.height(); }
int normalX() const; int normalX() const { return m_state.x; }
int normalY() const; int normalY() const { return m_state.y; }
unsigned int normalWidth() const; unsigned int normalWidth() const { return m_state.width; }
unsigned int normalHeight() const; unsigned int normalHeight() const { return m_state.height; }
// extra bits for tabs // extra bits for tabs
int xOffset() const; int xOffset() const;
@ -368,6 +282,9 @@ private:
bool showHandle(); bool showHandle();
bool setBorderWidth(bool do_move = true); bool setBorderWidth(bool do_move = true);
// check which corners should be rounded
int getShape() const;
/** /**
@name apply pixmaps depending on focus @name apply pixmaps depending on focus
*/ */
@ -463,7 +380,7 @@ private:
TabMode m_tabmode; TabMode m_tabmode;
unsigned int m_active_orig_client_bw; unsigned int m_active_orig_client_bw;
State m_state; WindowState m_state;
bool m_need_render; bool m_need_render;
int m_button_size; ///< size for all titlebar buttons int m_button_size; ///< size for all titlebar buttons

View file

@ -113,7 +113,7 @@ fluxbox_SOURCES = AtomHandler.hh ArrowButton.hh ArrowButton.cc \
Slit.cc Slit.hh SlitTheme.hh SlitTheme.cc SlitClient.hh SlitClient.cc \ Slit.cc Slit.hh SlitTheme.hh SlitTheme.cc SlitClient.hh SlitClient.cc \
WinButton.hh WinButton.cc \ WinButton.hh WinButton.cc \
WinButtonTheme.hh WinButtonTheme.cc \ WinButtonTheme.hh WinButtonTheme.cc \
Window.cc Window.hh \ Window.cc Window.hh WindowState.cc WindowState.hh\
Workspace.cc Workspace.hh \ Workspace.cc Workspace.hh \
FbCommands.hh FbCommands.cc LayerMenu.hh LayerMenu.cc \ FbCommands.hh FbCommands.cc LayerMenu.hh LayerMenu.cc \
Layer.hh \ Layer.hh \

View file

@ -500,7 +500,7 @@ int parseApp(ifstream &file, Application &app, string *first_line = 0) {
app.rememberIconHiddenstate((strcasecmp(str_label.c_str(), "yes") == 0)); app.rememberIconHiddenstate((strcasecmp(str_label.c_str(), "yes") == 0));
app.rememberFocusHiddenstate((strcasecmp(str_label.c_str(), "yes") == 0)); app.rememberFocusHiddenstate((strcasecmp(str_label.c_str(), "yes") == 0));
} else if (str_key == "deco") { } else if (str_key == "deco") {
int deco = FbWinFrame::getDecoMaskFromString(str_label); int deco = WindowState::getDecoMaskFromString(str_label);
if (deco == -1) if (deco == -1)
had_error = 1; had_error = 1;
else else
@ -535,13 +535,13 @@ int parseApp(ifstream &file, Application &app, string *first_line = 0) {
app.rememberMinimizedstate((strcasecmp(str_label.c_str(), "yes") == 0)); app.rememberMinimizedstate((strcasecmp(str_label.c_str(), "yes") == 0));
} else if (str_key == "maximized") { } else if (str_key == "maximized") {
if (strcasecmp(str_label.c_str(), "yes") == 0) 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) 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) else if (strcasecmp(str_label.c_str(), "vert") == 0)
app.rememberMaximizedstate(FbWinFrame::MAX_VERT); app.rememberMaximizedstate(WindowState::MAX_VERT);
else else
app.rememberMaximizedstate(FbWinFrame::MAX_NONE); app.rememberMaximizedstate(WindowState::MAX_NONE);
} else if (str_key == "fullscreen") { } else if (str_key == "fullscreen") {
app.rememberFullscreenstate((strcasecmp(str_label.c_str(), "yes") == 0)); app.rememberFullscreenstate((strcasecmp(str_label.c_str(), "yes") == 0));
} else if (str_key == "jump") { } else if (str_key == "jump") {
@ -953,25 +953,25 @@ void Remember::save() {
apps_file << " [Deco]\t{NONE}" << endl; apps_file << " [Deco]\t{NONE}" << endl;
break; break;
case (0xffffffff): case (0xffffffff):
case (FbWinFrame::DECORM_LAST - 1): case (WindowState::DECORM_LAST - 1):
apps_file << " [Deco]\t{NORMAL}" << endl; apps_file << " [Deco]\t{NORMAL}" << endl;
break; break;
case (FbWinFrame::DECORM_TITLEBAR case (WindowState::DECORM_TITLEBAR
| FbWinFrame::DECORM_ICONIFY | WindowState::DECORM_ICONIFY
| FbWinFrame::DECORM_MENU): | WindowState::DECORM_MENU):
apps_file << " [Deco]\t{TOOL}" << endl; apps_file << " [Deco]\t{TOOL}" << endl;
break; break;
case (FbWinFrame::DECORM_TITLEBAR case (WindowState::DECORM_TITLEBAR
| FbWinFrame::DECORM_MENU): | WindowState::DECORM_MENU):
apps_file << " [Deco]\t{TINY}" << endl; apps_file << " [Deco]\t{TINY}" << endl;
break; break;
case (FbWinFrame::DECORM_BORDER case (WindowState::DECORM_BORDER
| FbWinFrame::DECORM_MENU): | WindowState::DECORM_MENU):
apps_file << " [Deco]\t{BORDER}" << endl; apps_file << " [Deco]\t{BORDER}" << endl;
break; break;
case (FbWinFrame::DECORM_BORDER case (WindowState::DECORM_BORDER
| FbWinFrame::DECORM_MENU | WindowState::DECORM_MENU
| FbWinFrame::DECORM_TAB): | WindowState::DECORM_TAB):
apps_file << " [Deco]\t{TAB}" << endl; apps_file << " [Deco]\t{TAB}" << endl;
break; break;
default: default:
@ -999,16 +999,16 @@ void Remember::save() {
if (a.maximizedstate_remember) { if (a.maximizedstate_remember) {
apps_file << " [Maximized]\t{"; apps_file << " [Maximized]\t{";
switch (a.maximizedstate) { switch (a.maximizedstate) {
case FbWinFrame::MAX_FULL: case WindowState::MAX_FULL:
apps_file << "yes" << "}" << endl; apps_file << "yes" << "}" << endl;
break; break;
case FbWinFrame::MAX_HORZ: case WindowState::MAX_HORZ:
apps_file << "horz" << "}" << endl; apps_file << "horz" << "}" << endl;
break; break;
case FbWinFrame::MAX_VERT: case WindowState::MAX_VERT:
apps_file << "vert" << "}" << endl; apps_file << "vert" << "}" << endl;
break; break;
case FbWinFrame::MAX_NONE: case WindowState::MAX_NONE:
default: default:
apps_file << "no" << "}" << endl; apps_file << "no" << "}" << endl;
break; break;

View file

@ -22,8 +22,9 @@
#ifndef WINCLIENT_HH #ifndef WINCLIENT_HH
#define WINCLIENT_HH #define WINCLIENT_HH
#include "FbWinFrame.hh"
#include "Window.hh" #include "Window.hh"
#include "WindowState.hh"
#include "FbTk/FbWindow.hh" #include "FbTk/FbWindow.hh"
#include "FbTk/FbString.hh" #include "FbTk/FbString.hh"
@ -114,7 +115,7 @@ public:
Window getGroupLeftWindow() const; Window getGroupLeftWindow() const;
const MwmHints *getMwmHint() const { return m_mwm_hint; } 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 minWidth() const { return m_size_hints.min_width; }
unsigned int minHeight() const { return m_size_hints.min_height; } unsigned int minHeight() const { return m_size_hints.min_height; }
@ -157,7 +158,7 @@ private:
Focusable::WindowType m_window_type; Focusable::WindowType m_window_type;
MwmHints *m_mwm_hint; MwmHints *m_mwm_hint;
FbWinFrame::SizeHints m_size_hints; SizeHints m_size_hints;
Strut *m_strut; Strut *m_strut;
// map transient_for X window to winclient transient // map transient_for X window to winclient transient

View file

@ -271,7 +271,7 @@ FluxboxWindow::FluxboxWindow(WinClient &client, FbTk::XLayer &layer):
m_creation_time(0), m_creation_time(0),
moving(false), resizing(false), shaded(false), iconic(false), moving(false), resizing(false), shaded(false), iconic(false),
stuck(false), m_initialized(false), fullscreen(false), stuck(false), m_initialized(false), fullscreen(false),
maximized(FbWinFrame::MAX_NONE), maximized(WindowState::MAX_NONE),
m_attaching_tab(0), m_attaching_tab(0),
display(FbTk::App::instance()->display()), display(FbTk::App::instance()->display()),
m_button_grab_x(0), m_button_grab_y(0), m_button_grab_x(0), m_button_grab_y(0),
@ -423,7 +423,7 @@ void FluxboxWindow::init() {
m_workspace_number = m_screen.currentWorkspaceID(); m_workspace_number = m_screen.currentWorkspaceID();
// set default decorations but don't apply them // set default decorations but don't apply them
setDecorationMask(FbWinFrame::getDecoMaskFromString(screen().defaultDeco()), setDecorationMask(WindowState::getDecoMaskFromString(screen().defaultDeco()),
false); false);
functions.resize = functions.move = functions.iconify = functions.maximize functions.resize = functions.move = functions.iconify = functions.maximize
@ -559,7 +559,7 @@ void FluxboxWindow::init() {
if (maximized) { if (maximized) {
int tmp = maximized; int tmp = maximized;
maximized = FbWinFrame::MAX_NONE; maximized = WindowState::MAX_NONE;
setMaximizedState(tmp); setMaximizedState(tmp);
} }
@ -1045,7 +1045,7 @@ void FluxboxWindow::updateSizeHints() {
if ((*it) == m_client) if ((*it) == m_client)
continue; continue;
const FbWinFrame::SizeHints &hint = (*it)->sizeHints(); const SizeHints &hint = (*it)->sizeHints();
if (m_size_hint.min_width < hint.min_width) if (m_size_hint.min_width < hint.min_width)
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) if (m_size_hint.max_width > hint.max_width)
@ -1144,7 +1144,7 @@ void FluxboxWindow::updateMWMHintsFromClient(WinClient &client) {
} }
unsigned int mask = decorationMask(); unsigned int mask = decorationMask();
mask &= FbWinFrame::getDecoMaskFromString(screen().defaultDeco()); mask &= WindowState::getDecoMaskFromString(screen().defaultDeco());
setDecorationMask(mask, false); setDecorationMask(mask, false);
// functions.tabable is ours, not special one // functions.tabable is ours, not special one
@ -1503,7 +1503,7 @@ void FluxboxWindow::setFullscreenLayer() {
void FluxboxWindow::maximize(int type) { void FluxboxWindow::maximize(int type) {
// nothing to do // nothing to do
if (type == FbWinFrame::MAX_NONE) if (type == WindowState::MAX_NONE)
return; return;
int new_max = maximized; int new_max = maximized;
@ -1512,14 +1512,14 @@ void FluxboxWindow::maximize(int type) {
// when _don't_ we want to toggle? // when _don't_ we want to toggle?
// - type is horizontal maximise, or // - type is horizontal maximise, or
// - type is full and we are not maximised horz but already vertically // - type is full and we are not maximised horz but already vertically
if (type != FbWinFrame::MAX_HORZ && if (type != WindowState::MAX_HORZ &&
(type != FbWinFrame::MAX_FULL || maximized != FbWinFrame::MAX_VERT)) (type != WindowState::MAX_FULL || maximized != WindowState::MAX_VERT))
new_max ^= FbWinFrame::MAX_VERT; new_max ^= WindowState::MAX_VERT;
// maximize horizontally? // maximize horizontally?
if (type != FbWinFrame::MAX_VERT && if (type != WindowState::MAX_VERT &&
(type != FbWinFrame::MAX_FULL || maximized != FbWinFrame::MAX_HORZ)) (type != WindowState::MAX_FULL || maximized != WindowState::MAX_HORZ))
new_max ^= FbWinFrame::MAX_HORZ; new_max ^= WindowState::MAX_HORZ;
setMaximizedState(new_max); setMaximizedState(new_max);
} }
@ -1552,21 +1552,21 @@ void FluxboxWindow::setMaximizedState(int type) {
* Maximize window horizontal * Maximize window horizontal
*/ */
void FluxboxWindow::maximizeHorizontal() { void FluxboxWindow::maximizeHorizontal() {
maximize(FbWinFrame::MAX_HORZ); maximize(WindowState::MAX_HORZ);
} }
/** /**
* Maximize window vertical * Maximize window vertical
*/ */
void FluxboxWindow::maximizeVertical() { void FluxboxWindow::maximizeVertical() {
maximize(FbWinFrame::MAX_VERT); maximize(WindowState::MAX_VERT);
} }
/** /**
* Maximize window fully * Maximize window fully
*/ */
void FluxboxWindow::maximizeFull() { void FluxboxWindow::maximizeFull() {
maximize(FbWinFrame::MAX_FULL); maximize(WindowState::MAX_FULL);
} }
void FluxboxWindow::setWorkspace(int n) { void FluxboxWindow::setWorkspace(int n) {
@ -2807,9 +2807,9 @@ void FluxboxWindow::toggleDecoration() {
if (m_toggled_decos) { if (m_toggled_decos) {
m_old_decoration_mask = decorationMask(); m_old_decoration_mask = decorationMask();
if (decorations.titlebar | decorations.tab) if (decorations.titlebar | decorations.tab)
setDecorationMask(FbWinFrame::DECOR_NONE); setDecorationMask(WindowState::DECOR_NONE);
else else
setDecorationMask(FbWinFrame::DECOR_NORMAL); setDecorationMask(WindowState::DECOR_NORMAL);
} else //revert back to old decoration } else //revert back to old decoration
setDecorationMask(m_old_decoration_mask); setDecorationMask(m_old_decoration_mask);
@ -2818,42 +2818,42 @@ void FluxboxWindow::toggleDecoration() {
unsigned int FluxboxWindow::decorationMask() const { unsigned int FluxboxWindow::decorationMask() const {
unsigned int ret = 0; unsigned int ret = 0;
if (decorations.titlebar) if (decorations.titlebar)
ret |= FbWinFrame::DECORM_TITLEBAR; ret |= WindowState::DECORM_TITLEBAR;
if (decorations.handle) if (decorations.handle)
ret |= FbWinFrame::DECORM_HANDLE; ret |= WindowState::DECORM_HANDLE;
if (decorations.border) if (decorations.border)
ret |= FbWinFrame::DECORM_BORDER; ret |= WindowState::DECORM_BORDER;
if (decorations.iconify) if (decorations.iconify)
ret |= FbWinFrame::DECORM_ICONIFY; ret |= WindowState::DECORM_ICONIFY;
if (decorations.maximize) if (decorations.maximize)
ret |= FbWinFrame::DECORM_MAXIMIZE; ret |= WindowState::DECORM_MAXIMIZE;
if (decorations.close) if (decorations.close)
ret |= FbWinFrame::DECORM_CLOSE; ret |= WindowState::DECORM_CLOSE;
if (decorations.menu) if (decorations.menu)
ret |= FbWinFrame::DECORM_MENU; ret |= WindowState::DECORM_MENU;
if (decorations.sticky) if (decorations.sticky)
ret |= FbWinFrame::DECORM_STICKY; ret |= WindowState::DECORM_STICKY;
if (decorations.shade) if (decorations.shade)
ret |= FbWinFrame::DECORM_SHADE; ret |= WindowState::DECORM_SHADE;
if (decorations.tab) if (decorations.tab)
ret |= FbWinFrame::DECORM_TAB; ret |= WindowState::DECORM_TAB;
if (decorations.enabled) if (decorations.enabled)
ret |= FbWinFrame::DECORM_ENABLED; ret |= WindowState::DECORM_ENABLED;
return ret; return ret;
} }
void FluxboxWindow::setDecorationMask(unsigned int mask, bool apply) { void FluxboxWindow::setDecorationMask(unsigned int mask, bool apply) {
decorations.titlebar = mask & FbWinFrame::DECORM_TITLEBAR; decorations.titlebar = mask & WindowState::DECORM_TITLEBAR;
decorations.handle = mask & FbWinFrame::DECORM_HANDLE; decorations.handle = mask & WindowState::DECORM_HANDLE;
decorations.border = mask & FbWinFrame::DECORM_BORDER; decorations.border = mask & WindowState::DECORM_BORDER;
decorations.iconify = mask & FbWinFrame::DECORM_ICONIFY; decorations.iconify = mask & WindowState::DECORM_ICONIFY;
decorations.maximize = mask & FbWinFrame::DECORM_MAXIMIZE; decorations.maximize = mask & WindowState::DECORM_MAXIMIZE;
decorations.close = mask & FbWinFrame::DECORM_CLOSE; decorations.close = mask & WindowState::DECORM_CLOSE;
decorations.menu = mask & FbWinFrame::DECORM_MENU; decorations.menu = mask & WindowState::DECORM_MENU;
decorations.sticky = mask & FbWinFrame::DECORM_STICKY; decorations.sticky = mask & WindowState::DECORM_STICKY;
decorations.shade = mask & FbWinFrame::DECORM_SHADE; decorations.shade = mask & WindowState::DECORM_SHADE;
decorations.tab = mask & FbWinFrame::DECORM_TAB; decorations.tab = mask & WindowState::DECORM_TAB;
decorations.enabled = mask & FbWinFrame::DECORM_ENABLED; decorations.enabled = mask & WindowState::DECORM_ENABLED;
// we don't want to do this during initialization // we don't want to do this during initialization
if (apply) if (apply)
applyDecorations(); 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 // we only care about the left/top etc that includes borders
int borderW = 0; int borderW = 0;
if (decorationMask() & (FbWinFrame::DECORM_BORDER|FbWinFrame::DECORM_HANDLE)) if (decorationMask() & (WindowState::DECORM_BORDER|WindowState::DECORM_HANDLE))
borderW = frame().window().borderWidth(); borderW = frame().window().borderWidth();
int top = orig_top; // orig include the borders int top = orig_top; // orig include the borders
@ -3096,7 +3096,7 @@ void FluxboxWindow::doSnapping(int &orig_left, int &orig_top) {
if ((*it) == this) if ((*it) == this)
continue; // skip myself 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; (*it)->frame().window().borderWidth() : 0;
snapToWindow(dx, dy, left, right, top, bottom, snapToWindow(dx, dy, left, right, top, bottom,
@ -3175,7 +3175,7 @@ void FluxboxWindow::startResizing(int x, int y, ReferenceCorner dir) {
m_resize_corner = dir; m_resize_corner = dir;
resizing = true; resizing = true;
maximized = FbWinFrame::MAX_NONE; maximized = WindowState::MAX_NONE;
frame().setMaximized(maximized); frame().setMaximized(maximized);
const Cursor& cursor = (m_resize_corner == LEFTTOP) ? frame().theme()->upperLeftAngleCursor() : const Cursor& cursor = (m_resize_corner == LEFTTOP) ? frame().theme()->upperLeftAngleCursor() :
@ -3862,7 +3862,7 @@ void FluxboxWindow::setWindowType(Focusable::WindowType type) {
setFocusNew(false); setFocusNew(false);
setMouseFocus(false); setMouseFocus(false);
setClickFocus(false); setClickFocus(false);
setDecorationMask(FbWinFrame::DECOR_NONE); setDecorationMask(WindowState::DECOR_NONE);
moveToLayer(::Layer::DOCK); moveToLayer(::Layer::DOCK);
break; break;
case Focusable::TYPE_DESKTOP: case Focusable::TYPE_DESKTOP:
@ -3877,7 +3877,7 @@ void FluxboxWindow::setWindowType(Focusable::WindowType type) {
setFocusNew(false); setFocusNew(false);
setMouseFocus(false); setMouseFocus(false);
moveToLayer(::Layer::DESKTOP); moveToLayer(::Layer::DESKTOP);
setDecorationMask(FbWinFrame::DECOR_NONE); setDecorationMask(WindowState::DECOR_NONE);
setTabable(false); setTabable(false);
setMovable(false); setMovable(false);
setResizable(false); setResizable(false);
@ -3889,7 +3889,7 @@ void FluxboxWindow::setWindowType(Focusable::WindowType type) {
* window is a splash screen displayed as an application * window is a splash screen displayed as an application
* is starting up. * is starting up.
*/ */
setDecorationMask(FbWinFrame::DECOR_NONE); setDecorationMask(WindowState::DECOR_NONE);
setFocusHidden(true); setFocusHidden(true);
setIconHidden(true); setIconHidden(true);
setFocusNew(false); setFocusNew(false);
@ -3909,7 +3909,7 @@ void FluxboxWindow::setWindowType(Focusable::WindowType type) {
* application). Windows of this type may set the * application). Windows of this type may set the
* WM_TRANSIENT_FOR hint indicating the main application window. * WM_TRANSIENT_FOR hint indicating the main application window.
*/ */
setDecorationMask(FbWinFrame::DECOR_TOOL); setDecorationMask(WindowState::DECOR_TOOL);
setIconHidden(true); setIconHidden(true);
moveToLayer(::Layer::ABOVE_DOCK); moveToLayer(::Layer::ABOVE_DOCK);
break; break;

View file

@ -31,6 +31,7 @@
#include "FbTk/Observer.hh" #include "FbTk/Observer.hh"
#include "FbTk/EventHandler.hh" #include "FbTk/EventHandler.hh"
#include "FbTk/XLayerItem.hh" #include "FbTk/XLayerItem.hh"
#include "FbWinFrame.hh" #include "FbWinFrame.hh"
#include "Focusable.hh" #include "Focusable.hh"
#include "FocusableTheme.hh" #include "FocusableTheme.hh"
@ -45,7 +46,6 @@
class WinClient; class WinClient;
class FbWinFrameTheme; class FbWinFrameTheme;
class BScreen; class BScreen;
class FbWinFrame;
class FocusControl; class FocusControl;
class FbMenu; class FbMenu;
@ -212,7 +212,7 @@ public:
/// set fullscreen /// set fullscreen
void setFullscreen(bool flag); void setFullscreen(bool flag);
/// toggle maximize /// toggle maximize
void maximize(int type = FbWinFrame::MAX_FULL); void maximize(int type = WindowState::MAX_FULL);
/// sets the maximized state /// sets the maximized state
void setMaximizedState(int type); void setMaximizedState(int type);
/// maximizes the window horizontal /// maximizes the window horizontal
@ -373,9 +373,9 @@ public:
bool isIconic() const { return iconic; } bool isIconic() const { return iconic; }
bool isShaded() const { return shaded; } bool isShaded() const { return shaded; }
bool isFullscreen() const { return fullscreen; } bool isFullscreen() const { return fullscreen; }
bool isMaximized() const { return maximized == FbWinFrame::MAX_FULL; } bool isMaximized() const { return maximized == WindowState::MAX_FULL; }
bool isMaximizedVert() const { return (bool)(maximized & FbWinFrame::MAX_VERT); } bool isMaximizedVert() const { return (bool)(maximized & WindowState::MAX_VERT); }
bool isMaximizedHorz() const { return (bool)(maximized & FbWinFrame::MAX_HORZ); } bool isMaximizedHorz() const { return (bool)(maximized & WindowState::MAX_HORZ); }
int maximizedState() const { return maximized; } int maximizedState() const { return maximized; }
bool isIconifiable() const { return functions.iconify; } bool isIconifiable() const { return functions.iconify; }
bool isMaximizable() const { return functions.maximize; } bool isMaximizable() const { return functions.maximize; }
@ -553,7 +553,7 @@ private:
typedef std::map<WinClient *, IconButton *> Client2ButtonMap; typedef std::map<WinClient *, IconButton *> Client2ButtonMap;
Client2ButtonMap m_labelbuttons; Client2ButtonMap m_labelbuttons;
FbWinFrame::SizeHints m_size_hint; SizeHints m_size_hint;
struct _decorations { struct _decorations {
bool titlebar, handle, border, iconify, bool titlebar, handle, border, iconify,
maximize, close, menu, sticky, shade, tab, enabled; maximize, close, menu, sticky, shade, tab, enabled;

266
src/WindowState.cc Normal file
View file

@ -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;
}

118
src/WindowState.hh Normal file
View file

@ -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