From 391712b9805eda9d56a100f49d69b38863910565 Mon Sep 17 00:00:00 2001 From: Michael Abbott <michael@araneidae.co.uk> Date: Sat, 29 Sep 2012 08:10:48 +0100 Subject: Add support for nearest corner or edge resizing --- doc/asciidoc/fluxbox-keys.txt | 12 ++++++-- src/CurrentWindowCmd.cc | 41 ++++++++++++++++++++++----- src/CurrentWindowCmd.hh | 5 +++- src/Window.cc | 66 ++++++++++++++++++++++++++++++------------- src/Window.hh | 5 ++-- 5 files changed, 96 insertions(+), 33 deletions(-) diff --git a/doc/asciidoc/fluxbox-keys.txt b/doc/asciidoc/fluxbox-keys.txt index 0d0b52e..96b1141 100644 --- a/doc/asciidoc/fluxbox-keys.txt +++ b/doc/asciidoc/fluxbox-keys.txt @@ -178,8 +178,16 @@ Start dragging to resize the window as if you had grabbed the window at the specified 'corner'. + By default 'corner' is *BottomRight*, but may be overridden with one of:;; -*NearestCorner NearestEdge Center TopLeft Top TopRight Left Right BottomLeft -Bottom BottomRight* +*NearestCorner NearestEdge NearestCornerOrEdge Center TopLeft Top TopRight +Left Right BottomLeft Bottom BottomRight* + ++ +If *NearestCornerOrEdge* is specified the size of the corner can also be +specified to be the larger of one or two following numbers: ['pixel-size' +['percent-size']] or 'percent-size'%, where 'percent-size' is the +percentage of half the window width or height. If no size is given, it +defaults to 50 pixels and 30%. + *StartTabbing*:: Start dragging to add this window to another's tabgroup. diff --git a/src/CurrentWindowCmd.cc b/src/CurrentWindowCmd.cc index 4363d0d..6138e64 100644 --- a/src/CurrentWindowCmd.cc +++ b/src/CurrentWindowCmd.cc @@ -20,6 +20,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +#include <string.h> #include "CurrentWindowCmd.hh" #include "fluxbox.hh" @@ -369,15 +370,13 @@ void StartMovingCmd::real_execute() { FbTk::Command<void> *StartResizingCmd::parse(const string &cmd, const string &args, bool trusted) { FluxboxWindow::ResizeModel mode = FluxboxWindow::DEFAULTRESIZE; + int corner_size_px = 0; + int corner_size_pc = 0; std::vector<string> tokens; FbTk::StringUtil::stringtok<std::vector<string> >(tokens, args); if (!tokens.empty()) { string arg = FbTk::StringUtil::toLower(tokens[0]); - if (arg == "nearestcorner") - mode = FluxboxWindow::QUADRANTRESIZE; - else if (arg == "nearestedge") - mode = FluxboxWindow::NEARESTEDGERESIZE; - else if (arg == "center") + if (arg == "center") mode = FluxboxWindow::CENTERRESIZE; else if (arg == "topleft") mode = FluxboxWindow::TOPLEFTRESIZE; @@ -395,8 +394,35 @@ FbTk::Command<void> *StartResizingCmd::parse(const string &cmd, const string &ar mode = FluxboxWindow::BOTTOMRESIZE; else if (arg == "bottomright") mode = FluxboxWindow::BOTTOMRIGHTRESIZE; + else if (arg == "nearestcorner") { + mode = FluxboxWindow::EDGEORCORNERRESIZE; + corner_size_pc = 100; + } else if (arg == "nearestedge") { + mode = FluxboxWindow::EDGEORCORNERRESIZE; + } else if (arg == "nearestcorneroredge") { + mode = FluxboxWindow::EDGEORCORNERRESIZE; + /* The NearestCornerOrEdge can be followed by a corner size in + * one of three forms: + * <size in pixels> + * <size in pixels> <size in percent> + * <size in percent>% + * If no corner size is given then it defaults to 50 pixels, 30%. */ + if (tokens.size() > 1) { + const char * size1 = tokens[1].c_str(); + if (size1[strlen(size1)-1] == '%') + corner_size_pc = atoi(size1); + else { + corner_size_px = atoi(size1); + if (tokens.size() > 2) + corner_size_pc = atoi(tokens[2].c_str()); + } + } else { + corner_size_px = 50; + corner_size_pc = 30; + } + } } - return new StartResizingCmd(mode); + return new StartResizingCmd(mode, corner_size_px, corner_size_pc); } REGISTER_COMMAND_PARSER(startresizing, StartResizingCmd::parse, void); @@ -422,7 +448,8 @@ void StartResizingCmd::real_execute() { x -= fbwindow().x() - fbwindow().frame().window().borderWidth(); y -= fbwindow().y() - fbwindow().frame().window().borderWidth(); - fbwindow().startResizing(x, y, fbwindow().getResizeDirection(x, y, m_mode)); + fbwindow().startResizing(x, y, fbwindow().getResizeDirection( + x, y, m_mode, m_corner_size_px, m_corner_size_pc)); } REGISTER_COMMAND(starttabbing, StartTabbingCmd, void); diff --git a/src/CurrentWindowCmd.hh b/src/CurrentWindowCmd.hh index f406796..95175f2 100644 --- a/src/CurrentWindowCmd.hh +++ b/src/CurrentWindowCmd.hh @@ -124,13 +124,16 @@ protected: // begin resizing with mouse class StartResizingCmd: public WindowHelperCmd { public: - explicit StartResizingCmd(FluxboxWindow::ResizeModel mode):m_mode(mode) { } + explicit StartResizingCmd(FluxboxWindow::ResizeModel mode, int corner_size_px, int corner_size_pc): + m_mode(mode), m_corner_size_px(corner_size_px), m_corner_size_pc(corner_size_pc) { } static FbTk::Command<void> *parse(const std::string &command, const std::string &args, bool trusted); protected: void real_execute(); private: const FluxboxWindow::ResizeModel m_mode; + const int m_corner_size_px; // Corner size in pixels + const int m_corner_size_pc; // and in percent of half window width/height }; // begin tabbing with mouse diff --git a/src/Window.cc b/src/Window.cc index 33a4c9e..0b8d1e5 100644 --- a/src/Window.cc +++ b/src/Window.cc @@ -251,6 +251,18 @@ private: int m_mode; }; + +// Helper class for getResizeDirection below +// Tests whether a point is on an edge or the corner. +struct TestEdgeHelper { + int corner_size_px, corner_size_pc; + inline bool operator()(int xy, int wh) + { + /* The % checking must be right: 0% must fail, 100% must succeed. */ + return xy < corner_size_px || 100 * xy < corner_size_pc * wh; + } +}; + } @@ -3004,30 +3016,44 @@ void FluxboxWindow::doSnapping(int &orig_left, int &orig_top) { } + FluxboxWindow::ReferenceCorner FluxboxWindow::getResizeDirection(int x, int y, - ResizeModel model) const { + ResizeModel model, int corner_size_px, int corner_size_pc) const +{ + if (model == TOPLEFTRESIZE) return LEFTTOP; + if (model == TOPRESIZE) return TOP; + if (model == TOPRIGHTRESIZE) return RIGHTTOP; + if (model == LEFTRESIZE) return LEFT; + if (model == RIGHTRESIZE) return RIGHT; + if (model == BOTTOMLEFTRESIZE) return LEFTBOTTOM; + if (model == BOTTOMRESIZE) return BOTTOM; + if (model == CENTERRESIZE) return CENTER; + + if (model == EDGEORCORNERRESIZE) + { + int w = frame().width(); + int h = frame().height(); + int cx = w / 2; + int cy = h / 2; + TestEdgeHelper test_edge = { corner_size_px, corner_size_pc }; + if (x < cx && test_edge(x, cx)) { + if (y < cy && test_edge(y, cy)) + return LEFTTOP; + else if (test_edge(h - y - 1, h - cy)) + return LEFTBOTTOM; + } else if (test_edge(w - x - 1, w - cx)) { + if (y < cy && test_edge(y, cy)) + return RIGHTTOP; + else if (test_edge(h - y - 1, h - cy)) + return RIGHTBOTTOM; + } - int cx = frame().width() / 2; - int cy = frame().height() / 2; - if (model == CENTERRESIZE) - return CENTER; - if (model == NEARESTEDGERESIZE) { + /* Nope, not a corner; find the nearest edge instead. */ if (cy - abs(y - cy) < cx - abs(x - cx)) // y is nearest return (y > cy) ? BOTTOM : TOP; - return (x > cx) ? RIGHT : LEFT; - } - if (model == QUADRANTRESIZE) { - if (x < cx) - return (y < cy) ? LEFTTOP : LEFTBOTTOM; - return (y < cy) ? RIGHTTOP : RIGHTBOTTOM; - } - if (model == TOPLEFTRESIZE) return LEFTTOP; - if (model == TOPRESIZE) return TOP; - if (model == TOPRIGHTRESIZE) return RIGHTTOP; - if (model == LEFTRESIZE) return LEFT; - if (model == RIGHTRESIZE) return RIGHT; - if (model == BOTTOMLEFTRESIZE) return LEFTBOTTOM; - if (model == BOTTOMRESIZE) return BOTTOM; + else + return (x > cx) ? RIGHT : LEFT; + } return RIGHTBOTTOM; } diff --git a/src/Window.hh b/src/Window.hh index 09374af..b7975f5 100644 --- a/src/Window.hh +++ b/src/Window.hh @@ -89,9 +89,7 @@ public: /// Different resize modes when resizing a window enum ResizeModel { - QUADRANTRESIZE, ///< resizes from one quadrant CENTERRESIZE, ///< resizes from center - NEARESTEDGERESIZE, ///< resizes the nearest edge TOPLEFTRESIZE, ///< resizes top left corner TOPRESIZE, ///< resizes top edge TOPRIGHTRESIZE, ///< resizes top right corner @@ -100,6 +98,7 @@ public: BOTTOMLEFTRESIZE, ///< resizes bottom left corner BOTTOMRESIZE, ///< resizes bottom edge BOTTOMRIGHTRESIZE, ///< resizes bottom right corner + EDGEORCORNERRESIZE, ///< resizes nearest edge or corner DEFAULTRESIZE = BOTTOMRIGHTRESIZE ///< default resize mode }; @@ -341,7 +340,7 @@ public: */ void startResizing(int x, int y, ReferenceCorner dir); /// determine which edge or corner to resize - ReferenceCorner getResizeDirection(int x, int y, ResizeModel model) const; + ReferenceCorner getResizeDirection(int x, int y, ResizeModel model, int corner_size_px, int corner_size_pc) const; /// stops the resizing void stopResizing(bool interrupted = false); /// starts tabbing -- cgit v0.11.2