Add support for nearest corner or edge resizing

This commit is contained in:
Michael Abbott 2012-09-29 08:10:48 +01:00 committed by Mathias Gumz
parent 7b6ab828c7
commit 391712b980
5 changed files with 96 additions and 33 deletions

View file

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

View file

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

View file

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

View file

@ -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 {
int cx = frame().width() / 2;
int cy = frame().height() / 2;
if (model == CENTERRESIZE)
return CENTER;
if (model == NEARESTEDGERESIZE) {
FluxboxWindow::ReferenceCorner FluxboxWindow::getResizeDirection(int x, int y,
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;
}
/* 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;
else
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;
return RIGHTBOTTOM;
}

View file

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