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 <arkadiusz.bokowy@gmail.com>
This commit is contained in:
Arkadiusz Bokowy 2016-02-11 20:35:10 +01:00
parent 22866c4d30
commit 53de872163
3 changed files with 98 additions and 84 deletions

View file

@ -500,27 +500,6 @@ void MoveCmd::real_execute() {
fbwindow().move(fbwindow().x() + m_step_size_x, fbwindow().y() + m_step_size_y);
}
namespace {
template <typename Container>
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<void> *ResizeCmd::parse(const string &command, const string &args,
bool trusted) {
@ -536,15 +515,15 @@ FbTk::Command<void> *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<void> *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]);

View file

@ -24,6 +24,12 @@
#include <string>
#ifdef HAVE_CSTDLIB
#include <cstdlib>
#else
#include <stdlib.h>
#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: <int>, <int>% 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 <typename Container>
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

View file

@ -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<string> tokens;
FbTk::StringUtil::stringtok<std::vector<string> >(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<string> tokens;
FbTk::StringUtil::stringtok<std::vector<string> >(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);
}