From 7b6dc2ad72a4c4ecd20eddbfb6f1b4c3bd2a7024 Mon Sep 17 00:00:00 2001 From: Lajos Koszti Date: Fri, 6 Apr 2012 14:10:24 +0200 Subject: Allow percentage values for some Window commands --- .gitignore | 8 +++ doc/asciidoc/fluxbox-apps.txt | 9 ++- doc/asciidoc/fluxbox-keys.txt | 27 +++++--- src/CurrentWindowCmd.cc | 151 ++++++++++++++++++++++++++++++++---------- src/CurrentWindowCmd.hh | 20 +++--- src/FbTk/FbWindow.hh | 7 ++ src/FbTk/Makefile.am | 1 + src/FbTk/RelCalcHelper.cc | 38 +++++++++++ src/FbTk/RelCalcHelper.hh | 43 ++++++++++++ src/Remember.cc | 104 +++++++++++++++++++++-------- src/Screen.cc | 49 ++++++++++++++ src/Screen.hh | 17 +++++ src/Window.cc | 16 ++++- src/Window.hh | 2 + src/tests/StringUtiltest.cc | 26 ++++---- 15 files changed, 416 insertions(+), 102 deletions(-) create mode 100644 src/FbTk/RelCalcHelper.cc create mode 100644 src/FbTk/RelCalcHelper.hh diff --git a/.gitignore b/.gitignore index cf884c9..197941f 100644 --- a/.gitignore +++ b/.gitignore @@ -51,5 +51,13 @@ util/startfluxbox version.h install-sh missing +src/tests/testFont +src/tests/testFullscreen +src/tests/testDemandAttention +src/tests/testKeys +src/tests/testRectangleUtil +src/tests/testSignals +src/tests/testStringUtil +src/tests/testTexture *~ .*.swp diff --git a/doc/asciidoc/fluxbox-apps.txt b/doc/asciidoc/fluxbox-apps.txt index 26f560b..07bac0e 100644 --- a/doc/asciidoc/fluxbox-apps.txt +++ b/doc/asciidoc/fluxbox-apps.txt @@ -114,14 +114,17 @@ respectively. number. The named ones are: 2-AboveDock, 4-Dock, 6-Top, 8-Normal, 10-Bottom, 12-Desktop. -*[Dimensions]* {'width' 'height'}:: +*[Dimensions]* {'width[%]' 'height[%]'}:: Opens the application with the specified 'width' and 'height', in pixels. + If the value is given in percent, then the window size will be based on + the current screen's size. -*[Position]* ('anchor') {'X' 'Y'}:: +*[Position]* ('anchor') {'X[%]' 'Y[%]'}:: Position the application at a particular spot. By default the upper-left corner is placed at screen coordinates ('X','Y'). If you specify an 'anchor', say BottomRight, then the lower-right corner of the window is positioned ('X','Y') -pixels from the lower-right corner of the screen. +pixels from the lower-right corner of the screen. If the value is given in +percent, then the coordinates will be based on the current screen's size. + 'anchor' may be set to one of:;; *TopLeft Left BottomLeft Top Center Bottom TopRight Right BottomRight* diff --git a/doc/asciidoc/fluxbox-keys.txt b/doc/asciidoc/fluxbox-keys.txt index 2679bc0..0d0b52e 100644 --- a/doc/asciidoc/fluxbox-keys.txt +++ b/doc/asciidoc/fluxbox-keys.txt @@ -259,17 +259,22 @@ These commands ordinarily affect only the currently focused window. The *DetachClient*:: Remove the current tab from the tab group, placing it in its own window. -*ResizeTo* 'width' 'height':: - Resizes the window to the given width and height. - -*Resize* 'delta-width' 'delta-height':: - Resizes the window relative to the current width and height. - -*ResizeHorizontal* 'delta-width' / *ResizeVertical* 'delta-height':: - Resizes the window in one dimension only - -*MoveTo* 'x' 'y' ['anchor']:: -Moves the window to the given coordinates, given in pixels. +*ResizeTo* 'width[%]' 'height[%]':: + Resizes the window to the given width and height. If the value is given in + percent, then the window size will be based on the current screen's size. + +*Resize* 'delta-width[%]' 'delta-height[%]':: + Resizes the window relative to the current width and height. If the value + is given in percent, then the window size will be based on the current + window's size. + +*ResizeHorizontal* 'delta-width[%]' / *ResizeVertical* 'delta-height[%]':: + Resizes the window in one dimension only. If the value is given in + percent, then the window size will be based on the current window's size. + +*MoveTo* 'x[%]' 'y[%]' ['anchor']:: +Moves the window to the given coordinates, given in pixels or relatively to +the current screen size if % is specified after the value. + If either 'x' or 'y' is set to *\**, that coordinate will be ignored, and the movement will only take place in one dimension. diff --git a/src/CurrentWindowCmd.cc b/src/CurrentWindowCmd.cc index 8d27a3a..4363d0d 100644 --- a/src/CurrentWindowCmd.cc +++ b/src/CurrentWindowCmd.cc @@ -36,6 +36,7 @@ #include "FbTk/stringstream.hh" #include "FbTk/StringUtil.hh" #include "FbTk/Util.hh" +#include "FbTk/RelCalcHelper.hh" #ifdef HAVE_CONFIG_H #include "config.h" @@ -47,7 +48,6 @@ #include #endif - using FbTk::Command; namespace { @@ -477,21 +477,59 @@ 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) { - FbTk_istringstream is(args.c_str()); - int dx = 0, dy = 0; - is >> dx >> dy; - if (command == "resizehorizontal") + + typedef std::vector StringTokens; + StringTokens tokens; + FbTk::StringUtil::stringtok(tokens, args); + + if (tokens.size() < 1) { + return 0; + } + + int dx, dy; + 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); dy = 0; - else if (command == "resizevertical") { - dy = dx; + } else if (command == "resizevertical") { + parseToken(tokens[0], dy, is_relative_y, ignore_y); dx = 0; + } 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); } - if (command == "resizeto") - return new ResizeToCmd(dx, dy); - return new ResizeCmd(dx, dy); + if (command == "resizeto") { + return new ResizeToCmd(dx, dy, is_relative_x, is_relative_y); + } + return new ResizeCmd(dx, dy, is_relative_x, is_relative_y); } REGISTER_COMMAND_PARSER(resize, ResizeCmd::parse, void); @@ -499,8 +537,8 @@ REGISTER_COMMAND_PARSER(resizeto, ResizeCmd::parse, void); REGISTER_COMMAND_PARSER(resizehorizontal, ResizeCmd::parse, void); REGISTER_COMMAND_PARSER(resizevertical, ResizeCmd::parse, void); -ResizeCmd::ResizeCmd(const int step_size_x, const int step_size_y) : - m_step_size_x(step_size_x), m_step_size_y(step_size_y) { } +ResizeCmd::ResizeCmd(const int step_size_x, const int step_size_y, bool is_relative_x, bool is_relative_y) : + m_step_size_x(step_size_x), m_step_size_y(step_size_y), m_is_relative_x(is_relative_x), m_is_relative_y(is_relative_y) { } void ResizeCmd::real_execute() { @@ -512,11 +550,27 @@ void ResizeCmd::real_execute() { disableMaximizationIfNeeded(fbwindow()); - int w = std::max(static_cast(fbwindow().width() + - m_step_size_x * fbwindow().winClient().widthInc()), + int dx = m_step_size_x, dy = m_step_size_y; + int windowWidth = fbwindow().width(), windowHeight = fbwindow().height(); + + unsigned int widthInc = fbwindow().winClient().widthInc(), + heightInc = fbwindow().winClient().heightInc(); + + if (m_is_relative_x) { + // dx = floor(windowWidth * m_step_size_x / 100 / widthInc + 0.5); + dx = static_cast(FbTk::RelCalcHelper::calPercentageValueOf(windowWidth, m_step_size_x) / widthInc); + } + + if (m_is_relative_y) { + // dy = floor(windowHeight * m_step_size_y / 100 / heightInc + 0.5); + dy = static_cast(FbTk::RelCalcHelper::calPercentageValueOf(windowHeight, m_step_size_y) / heightInc); + } + + int w = std::max(static_cast(windowWidth + + dx * widthInc), fbwindow().frame().titlebarHeight() * 2 + 10); - int h = std::max(static_cast(fbwindow().height() + - m_step_size_y * fbwindow().winClient().heightInc()), + int h = std::max(static_cast(windowHeight + + dy * heightInc), fbwindow().frame().titlebarHeight() + 10); fbwindow().resize(w, h); @@ -533,17 +587,10 @@ FbTk::Command *MoveToCmd::parse(const string &cmd, const string &args, FluxboxWindow::ReferenceCorner refc = FluxboxWindow::LEFTTOP; int x = 0, y = 0; - bool ignore_x = false, ignore_y = false; - - if (tokens[0][0] == '*') - ignore_x = true; - else - x = atoi(tokens[0].c_str()); + bool ignore_x = false, ignore_y = false, is_relative_x = false, is_relative_y = false; - if (tokens[1][0] == '*' && !ignore_x) - ignore_y = true; - else - y = atoi(tokens[1].c_str()); + parseToken(tokens[0], x, is_relative_x, ignore_x); + parseToken(tokens[1], y, is_relative_y, ignore_y); if (tokens.size() >= 3) { refc = FluxboxWindow::getCorner(tokens[2]); @@ -551,7 +598,7 @@ FbTk::Command *MoveToCmd::parse(const string &cmd, const string &args, refc = FluxboxWindow::LEFTTOP; } - return new MoveToCmd(x, y, ignore_x, ignore_y, refc); + return new MoveToCmd(x, y, ignore_x, ignore_y, is_relative_x, is_relative_y, refc); } REGISTER_COMMAND_PARSER(moveto, MoveToCmd::parse, void); @@ -568,19 +615,31 @@ void MoveToCmd::real_execute() { int x = m_pos_x, y = m_pos_y; + int head = fbwindow().getOnHead(); - fbwindow().translateCoords(x, y, m_corner); - if (m_ignore_x) + if (m_ignore_x) { x = fbwindow().x(); - if (m_ignore_y) + } else { + if (m_is_relative_x) { + x = fbwindow().screen().calRelativeWidth(head, x); + } + fbwindow().translateXCoords(x, m_corner); + } + if (m_ignore_y) { y = fbwindow().y(); + } else { + if (m_is_relative_y) { + y = fbwindow().screen().calRelativeHeight(head, y); + } + fbwindow().translateYCoords(y, m_corner); + } fbwindow().move(x, y); } -ResizeToCmd::ResizeToCmd(const int step_size_x, const int step_size_y) : - m_step_size_x(step_size_x), m_step_size_y(step_size_y) { } +ResizeToCmd::ResizeToCmd(const int step_size_x, const int step_size_y, const bool is_relative_x, const bool is_relative_y) : + m_step_size_x(step_size_x), m_step_size_y(step_size_y), m_is_relative_x(is_relative_x), m_is_relative_y(is_relative_y) { } void ResizeToCmd::real_execute() { @@ -592,9 +651,31 @@ void ResizeToCmd::real_execute() { disableMaximizationIfNeeded(fbwindow()); + int dx = m_step_size_x, dy = m_step_size_y; + int head = fbwindow().getOnHead(); + + if (m_is_relative_x) { + dx = fbwindow().screen().calRelativeWidth(head, dx); + if(dx <= 0) { + dx = fbwindow().width(); + } + } + + if (m_is_relative_y) { + dy = fbwindow().screen().calRelativeHeight(head, dy); + if(dy <= 0) { + dy = fbwindow().height(); + } + } + + if (dx == 0) { + dx = fbwindow().width(); + } + if (dy == 0) { + dy = fbwindow().height(); + } - if (m_step_size_x > 0 && m_step_size_y > 0) - fbwindow().resize(m_step_size_x, m_step_size_y); + fbwindow().resize(dx, dy); } REGISTER_COMMAND(fullscreen, FullscreenCmd, void); @@ -720,7 +801,7 @@ void SetAlphaCmd::real_execute() { return; } - fbwindow().setFocusedAlpha(m_relative + fbwindow().setFocusedAlpha(m_relative ? FbTk::Util::clamp(fbwindow().getFocusedAlpha() + m_focus, 0, 255) : m_focus); diff --git a/src/CurrentWindowCmd.hh b/src/CurrentWindowCmd.hh index edf00fa..f406796 100644 --- a/src/CurrentWindowCmd.hh +++ b/src/CurrentWindowCmd.hh @@ -158,24 +158,26 @@ private: // resize cmd, relative size class ResizeCmd: public WindowHelperCmd{ public: - explicit ResizeCmd(int step_size_x, int step_size_y); + explicit ResizeCmd(int step_size_x, int step_size_y, bool is_relative_x, bool is_relative_y); static FbTk::Command *parse(const std::string &command, const std::string &args, bool trusted); protected: - void real_execute(); + void real_execute(); private: - - const int m_step_size_x; - const int m_step_size_y; + const int m_step_size_x; + const int m_step_size_y; + const bool m_is_relative_x; + const bool m_is_relative_y; }; class MoveToCmd: public WindowHelperCmd { public: - explicit MoveToCmd(int pos_x, int pos_y, bool ignore_x, bool ignore_y, + explicit MoveToCmd(int pos_x, int pos_y, bool ignore_x, bool ignore_y, bool is_relative_x, bool is_relative_y, FluxboxWindow::ReferenceCorner refc): m_pos_x(pos_x), m_pos_y(pos_y), m_ignore_x(ignore_x), m_ignore_y(ignore_y), + m_is_relative_x(is_relative_x), m_is_relative_y(is_relative_y), m_corner(refc) { } static FbTk::Command *parse(const std::string &command, @@ -185,19 +187,21 @@ protected: private: int m_pos_x, m_pos_y; - bool m_ignore_x, m_ignore_y; + bool m_ignore_x, m_ignore_y, m_is_relative_x, m_is_relative_y; FluxboxWindow::ReferenceCorner m_corner; }; // resize cmd class ResizeToCmd: public WindowHelperCmd{ public: - explicit ResizeToCmd(int step_size_x, int step_size_y); + explicit ResizeToCmd(int step_size_x, int step_size_y, bool is_relative_x, bool is_relative_y); protected: void real_execute(); private: const int m_step_size_x; const int m_step_size_y; + const bool m_is_relative_x; + const bool m_is_relative_y; }; class FullscreenCmd: public WindowHelperCmd{ diff --git a/src/FbTk/FbWindow.hh b/src/FbTk/FbWindow.hh index e03083c..9d335fa 100644 --- a/src/FbTk/FbWindow.hh +++ b/src/FbTk/FbWindow.hh @@ -28,6 +28,12 @@ #include #include +#ifdef HAVE_CMATH + #include +#else + #include +#endif + namespace FbTk { class Color; @@ -259,6 +265,7 @@ public: }; + } // end namespace FbTk #endif // FBTK_FBWINDOW_HH diff --git a/src/FbTk/Makefile.am b/src/FbTk/Makefile.am index 4c38f84..171f27d 100644 --- a/src/FbTk/Makefile.am +++ b/src/FbTk/Makefile.am @@ -64,6 +64,7 @@ libFbTk_a_SOURCES = App.hh App.cc Color.cc Color.hh Command.hh \ CachedPixmap.hh CachedPixmap.cc \ Slot.hh Signal.hh MemFun.hh SelectArg.hh \ Util.hh \ + RelCalcHelper.hh RelCalcHelper.cc \ ${xpm_SOURCE} \ ${xft_SOURCE} \ ${xmb_SOURCE} \ diff --git a/src/FbTk/RelCalcHelper.cc b/src/FbTk/RelCalcHelper.cc new file mode 100644 index 0000000..a537de4 --- /dev/null +++ b/src/FbTk/RelCalcHelper.cc @@ -0,0 +1,38 @@ +// RelCalcHelper.hh for Fluxbox - an X11 Window manager +// Copyright (c) 2012 Lajos Koszti (ajnasz at ajnasz.hu) +// +// 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 "RelCalcHelper.hh" + +namespace FbTk { + + namespace RelCalcHelper { + + int calPercentageValueOf(int i, int j) { + return floor(i * j / 100 + 0.5); + } + + int calPercentageOf(int i, int j) { + return floor((float) i / (float) j * 100 + 0.5); + } + + } + +} diff --git a/src/FbTk/RelCalcHelper.hh b/src/FbTk/RelCalcHelper.hh new file mode 100644 index 0000000..67d85e9 --- /dev/null +++ b/src/FbTk/RelCalcHelper.hh @@ -0,0 +1,43 @@ +// RelCalcHelper.cc for Fluxbox - an X11 Window manager +// Copyright (c) 2012 Lajos Koszti (ajnasz at ajnasz.hu) +// +// 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 FBTK_RELCALCHELPER_HH +#define FBTK_RELCALCHELPER_HH + +#ifdef HAVE_CMATH + #include +#else + #include +#endif + +namespace FbTk { + +namespace RelCalcHelper { + + int calPercentageOf(int i, int j); + + int calPercentageValueOf(int i, int j); + +} + +} + +#endif // FBTK_RELCALCHELPER_HH diff --git a/src/Remember.cc b/src/Remember.cc index c4eeb25..626522c 100644 --- a/src/Remember.cc +++ b/src/Remember.cc @@ -54,7 +54,6 @@ #define _GNU_SOURCE #endif // _GNU_SOURCE -#include #include @@ -99,15 +98,24 @@ public: { workspace = ws; workspace_remember = true; } void rememberHead(int h) { head = h; head_remember = true; } - void rememberDimensions(int width, int height) - { w = width; h = height; dimensions_remember = true; } + void rememberDimensions(int width, int height, bool is_relative) + { + dimension_is_relative = is_relative; + w = width; h = height; + dimensions_remember = true; + } void rememberFocusHiddenstate(bool state) { focushiddenstate= state; focushiddenstate_remember= true; } void rememberIconHiddenstate(bool state) { iconhiddenstate= state; iconhiddenstate_remember= true; } - void rememberPosition(int posx, int posy, + void rememberPosition(int posx, int posy, bool is_relative, FluxboxWindow::ReferenceCorner rfc = FluxboxWindow::LEFTTOP) - { x = posx; y = posy; refc = rfc; position_remember = true; } + { + position_is_relative = is_relative; + x = posx; y = posy; + refc = rfc; + position_remember = true; + } void rememberShadedstate(bool state) { shadedstate = state; shadedstate_remember = true; } void rememberTabstate(bool state) @@ -120,7 +128,7 @@ public: { focusnewwindow = state; focusnewwindow_remember = true; } void rememberJumpworkspace(bool state) { jumpworkspace = state; jumpworkspace_remember = true; } - void rememberLayer(int layernum) + void rememberLayer(int layernum) { layer = layernum; layer_remember = true; } void rememberSaveOnClose(bool state) { save_on_close = state; save_on_close_remember = true; } @@ -141,9 +149,11 @@ public: bool dimensions_remember; int w,h; // width, height + bool dimension_is_relative; bool position_remember; int x,y; + bool position_is_relative; FluxboxWindow::ReferenceCorner refc; bool alpha_remember; @@ -483,10 +493,13 @@ int parseApp(ifstream &file, Application &app, string *first_line = 0) { 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); - else + 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 { had_error = true; + } } else if (str_key == "position") { FluxboxWindow::ReferenceCorner r = FluxboxWindow::LEFTTOP; int x = 0, y = 0; @@ -497,10 +510,15 @@ int parseApp(ifstream &file, Application &app, string *first_line = 0) { r = FluxboxWindow::getCorner(str_option); had_error = (r == FluxboxWindow::ERROR); - if (!had_error && sscanf(str_label.c_str(), "%d %d", &x, &y) == 2) - app.rememberPosition(x, y, r); - else + 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; + } } else if (str_key == "shaded") { app.rememberShadedstate((strcasecmp(str_label.c_str(), "yes") == 0)); } else if (str_key == "tab") { @@ -910,7 +928,11 @@ void Remember::save() { apps_file << " [Head]\t{" << a.head << "}" << endl; } if (a.dimensions_remember) { - apps_file << " [Dimensions]\t{" << a.w << " " << a.h << "}" << endl; + if(a.dimension_is_relative) { + apps_file << " [Dimensions]\t{" << a.w << "% " << a.h << "%}" << endl; + } else { + apps_file << " [Dimensions]\t{" << a.w << " " << a.h << "}" << endl; + } } if (a.position_remember) { apps_file << " [Position]\t("; @@ -942,7 +964,11 @@ void Remember::save() { default: apps_file << "UPPERLEFT"; } - apps_file << ")\t{" << a.x << " " << a.y << "}" << endl; + if(a.position_is_relative) { + apps_file << ")\t{" << a.x << "% " << a.y << "%}" << endl; + } else { + apps_file << ")\t{" << a.x << " " << a.y << "}" << endl; + } } if (a.shadedstate_remember) { apps_file << " [Shaded]\t{" << ((a.shadedstate)?"yes":"no") << "}" << endl; @@ -1029,7 +1055,7 @@ void Remember::save() { if (a.alpha_remember) { if (a.focused_alpha == a.unfocused_alpha) apps_file << " [Alpha]\t{" << a.focused_alpha << "}" << endl; - else + else apps_file << " [Alpha]\t{" << a.focused_alpha << " " << a.unfocused_alpha << "}" << endl; } apps_file << "[end]" << endl; @@ -1110,6 +1136,7 @@ void Remember::rememberAttrib(WinClient &winclient, Attribute attrib) { app = add(winclient); if (!app) return; } + int head, head_x, head_y, win_w, win_h, percx, percy; switch (attrib) { case REM_WORKSPACE: app->rememberWorkspace(win->workspaceNumber()); @@ -1117,16 +1144,18 @@ void Remember::rememberAttrib(WinClient &winclient, Attribute attrib) { case REM_HEAD: app->rememberHead(win->screen().getHead(win->fbWindow())); break; - case REM_DIMENSIONS: - app->rememberDimensions(win->normalWidth(), - win->normalHeight()); + case REM_DIMENSIONS: { + head = win->screen().getHead(win->fbWindow()); + int percx = win->screen().calRelativeDimensionWidth(head, win->normalWidth()); + int percy = win->screen().calRelativeDimensionHeight(head, win->normalHeight()); + app->rememberDimensions(percx, percy, true); break; + } case REM_POSITION: { - int head = win->screen().getHead(win->fbWindow()); - int head_x = win->screen().maxLeft(head); - int head_y = win->screen().maxTop(head); - app->rememberPosition(win->normalX() - head_x, - win->normalY() - head_y); + head = win->screen().getHead(win->fbWindow()); + int percx = win->screen().calRelativePositionWidth(head, win->normalX()); + int percy = win->screen().calRelativePositionHeight(head, win->normalY()); + app->rememberPosition(percx, percy, true); break; } case REM_FOCUSHIDDENSTATE: @@ -1288,13 +1317,32 @@ void Remember::setupFrame(FluxboxWindow &win) { win.setOnHead(app->head); } - if (app->dimensions_remember) - win.resize(app->w, app->h); + if (app->dimensions_remember) { + + int win_w, win_h; + if(app->dimension_is_relative) { + int head = screen.getHead(win.fbWindow()); + int screen_y = screen.maxBottom(head) - screen.maxTop(head); + 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); + } if (app->position_remember) { - int newx = app->x, newy = app->y; - win.translateCoords(newx, newy, app->refc); - win.move(newx, newy); + 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; + } + win.translateCoords(newx, newy, app->refc); + win.move(newx, newy); } if (app->shadedstate_remember) diff --git a/src/Screen.cc b/src/Screen.cc index 4ea7afb..6757af0 100644 --- a/src/Screen.cc +++ b/src/Screen.cc @@ -1485,6 +1485,55 @@ void BScreen::addManagedResource(FbTk::Resource_base *resource) { m_managed_resources.push_back(resource); } +int BScreen::getGap(int head, const char type) { + return type == 'w' ? getXGap(head) : getYGap(head); +} + +int BScreen::calRelativeSize(int head, int i, char type) { + // return floor(i * getGap(head, type) / 100 + 0.5); + return FbTk::RelCalcHelper::calPercentageValueOf(i, getGap(head, type)); +} +int BScreen::calRelativeWidth(int head, int i) { + return calRelativeSize(head, i, 'w'); +} +int BScreen::calRelativeHeight(int head, int i) { + return calRelativeSize(head, i, 'h'); +} + +int BScreen::calRelativePosition(int head, int i, char type) { + int max = type == 'w' ? maxLeft(head) : maxTop(head); + // return floor((i - min) / getGap(head, type) * 100 + 0.5); + return FbTk::RelCalcHelper::calPercentageOf((i - max), getGap(head, type)); +} +// returns a pixel, which is relative to the width of the screen +// screen starts from 0, 1000 px width, if i is 10 then it should return 100 +int BScreen::calRelativePositionWidth(int head, int i) { + return calRelativePosition(head, i, 'w'); +} +// returns a pixel, which is relative to the height of th escreen +// screen starts from 0, 1000 px height, if i is 10 then it should return 100 +int BScreen::calRelativePositionHeight(int head, int i) { + return calRelativePosition(head, i, 'h'); +} + +int BScreen::calRelativeDimension(int head, int i, char type) { + // return floor(i / getGap(head, type) * 100 + 0.5); + return FbTk::RelCalcHelper::calPercentageOf(i, getGap(head, type)); + } +int BScreen::calRelativeDimensionWidth(int head, int i) { + return calRelativeDimension(head, i, 'w'); +} +int BScreen::calRelativeDimensionHeight(int head, int i) { + return calRelativeDimension(head, i, 'h'); +} + +float BScreen::getXGap(int head) { + return maxRight(head) - maxLeft(head); +} +float BScreen::getYGap(int head) { + return maxBottom(head) - maxTop(head); +} + void BScreen::setupConfigmenu(FbTk::Menu &menu) { _FB_USES_NLS; diff --git a/src/Screen.hh b/src/Screen.hh index de3a5a1..fe8d127 100644 --- a/src/Screen.hh +++ b/src/Screen.hh @@ -38,6 +38,7 @@ #include "FbTk/MultLayers.hh" #include "FbTk/NotCopyable.hh" #include "FbTk/Signal.hh" +#include "FbTk/RelCalcHelper.hh" #include "FocusControl.hh" @@ -453,12 +454,28 @@ public: /// when screen dies void addManagedResource(FbTk::Resource_base *resource); + int calRelativeSize(int head, int i, char type); + int calRelativeWidth(int head, int i); + int calRelativeHeight(int head, int i); + + int calRelativePosition(int head, int i, char type); + int calRelativePositionWidth(int head, int i); + int calRelativePositionHeight(int head, int i); + + int calRelativeDimension(int head, int i, char type); + int calRelativeDimensionWidth(int head, int i); + int calRelativeDimensionHeight(int head, int i); + private: void setupConfigmenu(FbTk::Menu &menu); void renderGeomWindow(); void renderPosWindow(); void focusedWinFrameThemeReconfigured(); + int getGap(int head, const char type); + float getXGap(int head); + float getYGap(int head); + const Strut* availableWorkspaceArea(int head) const; FbTk::SignalTracker m_tracker; diff --git a/src/Window.cc b/src/Window.cc index a4eef44..f5a2fe2 100644 --- a/src/Window.cc +++ b/src/Window.cc @@ -3714,10 +3714,9 @@ FluxboxWindow::ReferenceCorner FluxboxWindow::getCorner(string str) { return ERROR; } -void FluxboxWindow::translateCoords(int &x, int &y, ReferenceCorner dir) const { +void FluxboxWindow::translateXCoords(int &x, ReferenceCorner dir) const { int head = getOnHead(), bw = 2 * frame().window().borderWidth(), - left = screen().maxLeft(head), right = screen().maxRight(head), - top = screen().maxTop(head), bottom = screen().maxBottom(head); + left = screen().maxLeft(head), right = screen().maxRight(head); if (dir == LEFTTOP || dir == LEFT || dir == LEFTBOTTOM) x += left; @@ -3725,6 +3724,12 @@ void FluxboxWindow::translateCoords(int &x, int &y, ReferenceCorner dir) const { x = right - width() - bw - x; if (dir == TOP || dir == CENTER || dir == BOTTOM) x += (left + right - width() - bw)/2; +} + +void FluxboxWindow::translateYCoords(int &y, ReferenceCorner dir) const { + int head = getOnHead(), bw = 2 * frame().window().borderWidth(), + top = screen().maxTop(head), bottom = screen().maxBottom(head); + if (dir == LEFTTOP || dir == TOP || dir == RIGHTTOP) y += top; if (dir == LEFTBOTTOM || dir == BOTTOM || dir == RIGHTBOTTOM) @@ -3733,6 +3738,11 @@ void FluxboxWindow::translateCoords(int &x, int &y, ReferenceCorner dir) const { y += (top + bottom - height() - bw)/2; } +void FluxboxWindow::translateCoords(int &x, int &y, ReferenceCorner dir) const { + translateXCoords(x, dir); + translateYCoords(y, dir); +} + int FluxboxWindow::getOnHead() const { return screen().getHead(fbWindow()); } diff --git a/src/Window.hh b/src/Window.hh index a5bcb66..0d2cadd 100644 --- a/src/Window.hh +++ b/src/Window.hh @@ -350,6 +350,8 @@ public: /// determine the reference corner from a string static ReferenceCorner getCorner(std::string str); /// convert to coordinates on the root window + void translateXCoords(int &x, ReferenceCorner dir = LEFTTOP) const; + void translateYCoords(int &y, ReferenceCorner dir = LEFTTOP) const; void translateCoords(int &x, int &y, ReferenceCorner dir = LEFTTOP) const; /** diff --git a/src/tests/StringUtiltest.cc b/src/tests/StringUtiltest.cc index b723eef..e5e8419 100644 --- a/src/tests/StringUtiltest.cc +++ b/src/tests/StringUtiltest.cc @@ -33,9 +33,9 @@ using namespace std; using namespace FbTk; -void testStringtok() { +void testStringtok() { vector ls; - StringUtil::stringtok(ls, " arg1 arg2 \targ3\n arg4 arg5\t\t\t\targ6\n\n \n\n \t\t\narg7"); + StringUtil::stringtok(ls, " arg1 arg2 \targ3\n arg4 arg5\t\t\t\targ6\n\n \n\n \t\t\narg7"); cerr<<"Size: "<::const_iterator i = ls.begin(); i != ls.end(); ++i) { @@ -66,7 +66,7 @@ void testStrcasestr() { cerr<<"ok."<