From 53de872163d61c87fa8128767ebbc218599f3835 Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Thu, 11 Feb 2016 20:35:10 +0100 Subject: Mixed relative and absolute values for apps Allow setting relative value for x and y or width and height separately in the apps configuration file. This makes these settings compatible with ones available in the keys file. Previous buggy behavior: If someone has specified, e.g. "[Dimensions] {50% 100}" it was parsed as "{50% 100%}" not as "{50% 100px}" which was inconsistent with the "keys" configuration file. From now on it is possible to write something like this: [app] [Position] (RIGHT) {50% 0} [Dimensions] {300 100%} [end] Signed-off-by: Arkadiusz Bokowy --- src/CurrentWindowCmd.cc | 33 +++----------- src/FbTk/StringUtil.hh | 35 ++++++++++++++- src/Remember.cc | 114 +++++++++++++++++++++++++----------------------- 3 files changed, 98 insertions(+), 84 deletions(-) diff --git a/src/CurrentWindowCmd.cc b/src/CurrentWindowCmd.cc index dd43d43..44556f5 100644 --- a/src/CurrentWindowCmd.cc +++ b/src/CurrentWindowCmd.cc @@ -500,27 +500,6 @@ void MoveCmd::real_execute() { fbwindow().move(fbwindow().x() + m_step_size_x, fbwindow().y() + m_step_size_y); } -namespace { - template - static void parseToken(Container &container, int &d, bool &is_relative, bool &ignore) { - if (container.size() < 1) - return; - - d = 0; - is_relative = false; - ignore = false; - if (container[0] == '*') { - ignore = true; - } else if (container[container.size() - 1] == '%') { - // its a percent - is_relative = true; - d = atoi(container.substr(0, container.size() - 1).c_str()); - } else { - d = atoi(container.c_str()); - } - } -} - FbTk::Command *ResizeCmd::parse(const string &command, const string &args, bool trusted) { @@ -536,15 +515,15 @@ FbTk::Command *ResizeCmd::parse(const string &command, const string &args, bool is_relative_x = false, is_relative_y = false, ignore_x = false, ignore_y = false; if (command == "resizehorizontal") { - parseToken(tokens[0], dx, is_relative_x, ignore_x); + dx = FbTk::StringUtil::parseSizeToken(tokens[0], is_relative_x, ignore_x); } else if (command == "resizevertical") { - parseToken(tokens[0], dy, is_relative_y, ignore_y); + dy = FbTk::StringUtil::parseSizeToken(tokens[0], is_relative_y, ignore_y); } else { if (tokens.size() < 2) { return 0; } - parseToken(tokens[0], dx, is_relative_x, ignore_x); - parseToken(tokens[1], dy, is_relative_y, ignore_y); + dx = FbTk::StringUtil::parseSizeToken(tokens[0], is_relative_x, ignore_x); + dy = FbTk::StringUtil::parseSizeToken(tokens[1], is_relative_y, ignore_y); } if (command == "resizeto") { @@ -610,8 +589,8 @@ FbTk::Command *MoveToCmd::parse(const string &cmd, const string &args, int x = 0, y = 0; bool ignore_x = false, ignore_y = false, is_relative_x = false, is_relative_y = false; - parseToken(tokens[0], x, is_relative_x, ignore_x); - parseToken(tokens[1], y, is_relative_y, ignore_y); + x = FbTk::StringUtil::parseSizeToken(tokens[0], is_relative_x, ignore_x); + y = FbTk::StringUtil::parseSizeToken(tokens[1], is_relative_y, ignore_y); if (tokens.size() >= 3) { refc = FluxboxWindow::getCorner(tokens[2]); diff --git a/src/FbTk/StringUtil.hh b/src/FbTk/StringUtil.hh index 2f7c6fc..bfa3a5c 100644 --- a/src/FbTk/StringUtil.hh +++ b/src/FbTk/StringUtil.hh @@ -24,6 +24,12 @@ #include +#ifdef HAVE_CSTDLIB +#include +#else +#include +#endif + namespace FbTk { namespace StringUtil { @@ -61,12 +67,12 @@ std::string findExtension(const std::string &filename); /// @param found - position of found char in alphabet (optional) /// @return position of trigger if found /// @return std::string::npos if nothing found -std::string::size_type findCharFromAlphabetAfterTrigger(const std::string& in, +std::string::size_type findCharFromAlphabetAfterTrigger(const std::string& in, char trigger, const char alphabet[], size_t len_alphabet, size_t* found); /// @return copy of original with find_string replaced with "replace" -std::string replaceString(const std::string &original, +std::string replaceString(const std::string &original, const char *find_string, const char *replace); @@ -143,6 +149,31 @@ stringtok (Container &container, std::string const &in, } } +/// Parse token, which might be in formats as follows: , % or *. +/// @param relative - parsed relative value (percentage suffix) +/// @param ignore - this token should be ignored (asterisk) +/// @return parsed integer value or 0 if not applicable +template +static int +parseSizeToken(Container &container, bool &relative, bool &ignore) { + + if (container.empty()) + return 0; + + relative = false; + ignore = false; + + if (container[0] == '*') { + ignore = true; + return 0; + } + + if (container[container.size() - 1] == '%') + relative = true; + + return atoi(container.c_str()); +} + } // end namespace StringUtil } // end namespace FbTk diff --git a/src/Remember.cc b/src/Remember.cc index 7163dec..6dcd378 100644 --- a/src/Remember.cc +++ b/src/Remember.cc @@ -110,9 +110,10 @@ public: { workspace = ws; workspace_remember = true; } void rememberHead(int h) { head = h; head_remember = true; } - void rememberDimensions(int width, int height, bool is_relative) + void rememberDimensions(int width, int height, bool is_w_relative, bool is_h_relative) { - dimension_is_relative = is_relative; + dimension_is_w_relative = is_w_relative; + dimension_is_h_relative = is_h_relative; w = width; h = height; dimensions_remember = true; } @@ -120,10 +121,11 @@ public: { focushiddenstate= state; focushiddenstate_remember= true; } void rememberIconHiddenstate(bool state) { iconhiddenstate= state; iconhiddenstate_remember= true; } - void rememberPosition(int posx, int posy, bool is_relative, + void rememberPosition(int posx, int posy, bool is_x_relative, bool is_y_relative, FluxboxWindow::ReferenceCorner rfc = FluxboxWindow::LEFTTOP) { - position_is_relative = is_relative; + position_is_x_relative = is_x_relative; + position_is_y_relative = is_y_relative; x = posx; y = posy; refc = rfc; position_remember = true; @@ -161,11 +163,13 @@ public: bool dimensions_remember; int w,h; // width, height - bool dimension_is_relative; + bool dimension_is_w_relative; + bool dimension_is_h_relative; bool position_remember; int x,y; - bool position_is_relative; + bool position_is_x_relative; + bool position_is_y_relative; FluxboxWindow::ReferenceCorner refc; bool alpha_remember; @@ -481,32 +485,34 @@ int parseApp(ifstream &file, Application &app, string *first_line = 0) { if (!had_error) app.rememberLayer(l); } else if (str_key == "dimensions") { - unsigned int h, w; - if (sscanf(str_label.c_str(), "%u %u", &w, &h) == 2) { - app.rememberDimensions(w, h, false); - } else if(sscanf(str_label.c_str(), "%u%% %u%%", &w, &h) == 2) { - app.rememberDimensions(w, h, true); - } else { + std::vector tokens; + FbTk::StringUtil::stringtok >(tokens, str_label); + if (tokens.size() == 2) { + unsigned int h, w; + bool h_relative, w_relative, ignore; + w = FbTk::StringUtil::parseSizeToken(tokens[0], w_relative, ignore); + h = FbTk::StringUtil::parseSizeToken(tokens[1], h_relative, ignore); + app.rememberDimensions(w, h, w_relative, h_relative); + } else had_error = true; - } } else if (str_key == "position") { FluxboxWindow::ReferenceCorner r = FluxboxWindow::LEFTTOP; - int x = 0, y = 0; // more info about the parameter // in ::rememberPosition if (str_option.length()) r = FluxboxWindow::getCorner(str_option); - had_error = (r == FluxboxWindow::ERROR); - - if (!had_error){ - if(sscanf(str_label.c_str(), "%d %d", &x, &y) == 2) { - app.rememberPosition(x, y, false, r); - } else if (sscanf(str_label.c_str(), "%d%% %d%%", &x, &y) == 2){ - app.rememberPosition(x, y, true, r); - } - } else { - had_error = true; + if (!(had_error = (r == FluxboxWindow::ERROR))) { + std::vector tokens; + FbTk::StringUtil::stringtok >(tokens, str_label); + if (tokens.size() == 2) { + int x, y; + bool x_relative, y_relative, ignore; + x = FbTk::StringUtil::parseSizeToken(tokens[0], x_relative, ignore); + y = FbTk::StringUtil::parseSizeToken(tokens[1], y_relative, ignore); + app.rememberPosition(x, y, x_relative, y_relative, r); + } else + had_error = true; } } else if (str_key == "shaded") { app.rememberShadedstate(str_label == "yes"); @@ -916,11 +922,9 @@ void Remember::save() { apps_file << " [Head]\t{" << a.head << "}" << endl; } if (a.dimensions_remember) { - if(a.dimension_is_relative) { - apps_file << " [Dimensions]\t{" << a.w << "% " << a.h << "%}" << endl; - } else { - apps_file << " [Dimensions]\t{" << a.w << " " << a.h << "}" << endl; - } + apps_file << " [Dimensions]\t{" << + a.w << (a.dimension_is_w_relative ? "% " : " ") << + a.h << (a.dimension_is_h_relative ? "%}" : "}") << endl; } if (a.position_remember) { apps_file << " [Position]\t("; @@ -952,11 +956,9 @@ void Remember::save() { default: apps_file << "UPPERLEFT"; } - if(a.position_is_relative) { - apps_file << ")\t{" << a.x << "% " << a.y << "%}" << endl; - } else { - apps_file << ")\t{" << a.x << " " << a.y << "}" << endl; - } + apps_file << ")\t{" << + a.x << (a.position_is_x_relative ? "% " : " ") << + a.y << (a.position_is_y_relative ? "%}" : "}") << endl; } if (a.shadedstate_remember) { apps_file << " [Shaded]\t{" << ((a.shadedstate)?"yes":"no") << "}" << endl; @@ -1136,14 +1138,14 @@ void Remember::rememberAttrib(WinClient &winclient, Attribute attrib) { head = win->screen().getHead(win->fbWindow()); percx = win->screen().calRelativeDimensionWidth(head, win->normalWidth()); percy = win->screen().calRelativeDimensionHeight(head, win->normalHeight()); - app->rememberDimensions(percx, percy, true); + app->rememberDimensions(percx, percy, true, true); break; } case REM_POSITION: { head = win->screen().getHead(win->fbWindow()); percx = win->screen().calRelativePositionWidth(head, win->normalX()); percy = win->screen().calRelativePositionHeight(head, win->normalY()); - app->rememberPosition(percx, percy, true); + app->rememberPosition(percx, percy, true, true); break; } case REM_FOCUSHIDDENSTATE: @@ -1307,28 +1309,30 @@ void Remember::setupFrame(FluxboxWindow &win) { if (app->dimensions_remember) { - int win_w, win_h; - if(app->dimension_is_relative) { - int head = screen.getHead(win.fbWindow()); - win_w = screen.calRelativeWidth(head, app->w); - win_h = screen.calRelativeHeight(head, app->h); - } else { - win_w = app->w; - win_h = app->h; - } - win.resize(win_w, win_h); + int win_w = app->w; + int win_h = app->h; + int head = screen.getHead(win.fbWindow()); + int border_w = win.frame().window().borderWidth(); + + if (app->dimension_is_w_relative) + win_w = screen.calRelativeWidth(head, win_w); + if (app->dimension_is_h_relative) + win_h = screen.calRelativeHeight(head, win_h); + + win.resize(win_w - 2 * border_w, win_h - 2 * border_w); } if (app->position_remember) { - int newx, newy; - if(app->position_is_relative) { - int head = screen.getHead(win.fbWindow()); - newx = screen.calRelativeWidth(head, app->x); - newy = screen.calRelativeHeight(head, app->y); - } else { - newx = app->x; - newy = app->y; - } + + int newx = app->x; + int newy = app->y; + int head = screen.getHead(win.fbWindow()); + + if (app->position_is_x_relative) + newx = screen.calRelativeWidth(head, newx); + if (app->position_is_y_relative) + newy = screen.calRelativeHeight(head, newy); + win.translateCoords(newx, newy, app->refc); win.move(newx, newy); } -- cgit v0.11.2