From e75378d0e6d5891536e24389fcbeabeb7a9d579a Mon Sep 17 00:00:00 2001 From: rathnor Date: Sun, 20 Apr 2003 02:47:15 +0000 Subject: Add window snapping (Simon) --- ChangeLog | 4 ++ RoadMap | 2 +- src/Window.cc | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ src/Window.hh | 5 +- 4 files changed, 138 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index b468ac3..3b8f479 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ (Format: Year/Month/Day) +Changes for 0.9.2: +*03/04/20: + * Snap to Windows (and toolbar, slit + screen edge) (Simon) + Window.hh/cc Changes for 0.9.1: *03/04/16: * Fixed resize bug (Henrik) diff --git a/RoadMap b/RoadMap index e3764f5..aea3c79 100644 --- a/RoadMap +++ b/RoadMap @@ -105,7 +105,7 @@ Minor Features: - more keybinding actions (Both) - directional focus movement (?) - fix up focus issues (Simon) - = snap to windows (Simon) + * snap to windows (Simon) - improved command-line help option (Henrik) - pixmap buttons (Henrik) = Shaped menu/slit/toolbar (Henrik) diff --git a/src/Window.cc b/src/Window.cc index cbd5b84..890a4e0 100644 --- a/src/Window.cc +++ b/src/Window.cc @@ -22,7 +22,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: Window.cc,v 1.143 2003/04/16 22:17:46 fluxgen Exp $ +// $Id: Window.cc,v 1.144 2003/04/20 02:47:14 rathnor Exp $ #include "Window.hh" @@ -2303,18 +2303,19 @@ void FluxboxWindow::motionNotifyEvent(XMotionEvent &me) { dx += me.x_root - button_grab_x; } } - + // dx = current left side, dy = current top + doSnapping(dx, dy); if (! screen.doOpaqueMove()) { XDrawRectangle(display, screen.getRootWindow(), screen.getOpGC(), last_move_x, last_move_y, - m_frame.width() + 2*frame().window().borderWidth(), - m_frame.height() + 2*frame().window().borderWidth()); + m_frame.width() + 2*frame().window().borderWidth()-1, + m_frame.height() + 2*frame().window().borderWidth()-1); XDrawRectangle(display, screen.getRootWindow(), screen.getOpGC(), dx, dy, - m_frame.width() + 2*frame().window().borderWidth(), - m_frame.height() + 2*frame().window().borderWidth()); + m_frame.width() + 2*frame().window().borderWidth()-1, + m_frame.height() + 2*frame().window().borderWidth()-1); last_move_x = dx; last_move_y = dy; } else { @@ -2577,8 +2578,8 @@ void FluxboxWindow::startMoving(Window win) { fluxbox->grab(); XDrawRectangle(display, screen.getRootWindow(), screen.getOpGC(), frame().x(), frame().y(), - frame().width() + 2*frame().window().borderWidth(), - frame().height() + 2*frame().window().borderWidth()); + frame().width() + 2*frame().window().borderWidth()-1, + frame().height() + 2*frame().window().borderWidth()-1); screen.showPosition(frame().x(), frame().y()); } } @@ -2593,8 +2594,8 @@ void FluxboxWindow::stopMoving() { if (! screen.doOpaqueMove()) { XDrawRectangle(FbTk::App::instance()->display(), screen.getRootWindow(), screen.getOpGC(), last_move_x, last_move_y, - frame().width() + 2*frame().window().borderWidth(), - frame().height() + 2*frame().window().borderWidth()); + frame().width() + 2*frame().window().borderWidth()-1, + frame().height() + 2*frame().window().borderWidth()-1); moveResize(last_move_x, last_move_y, m_frame.width(), m_frame.height()); if (workspace_number != getScreen().getCurrentWorkspaceID()) { screen.reassociateWindow(this, getScreen().getCurrentWorkspaceID(), true); @@ -2617,8 +2618,8 @@ void FluxboxWindow::pauseMoving() { XDrawRectangle(display, getScreen().getRootWindow(), getScreen().getOpGC(), last_move_x, last_move_y, - m_frame.width() + 2*frame().window().borderWidth(), - m_frame.height() + 2*frame().window().borderWidth()); + m_frame.width() + 2*frame().window().borderWidth()-1, + m_frame.height() + 2*frame().window().borderWidth()-1); } @@ -2634,8 +2635,122 @@ void FluxboxWindow::resumeMoving() { XSync(display,false); XDrawRectangle(display, screen.getRootWindow(), screen.getOpGC(), last_move_x, last_move_y, - m_frame.width() + 2*frame().window().borderWidth(), - m_frame.height() + 2*frame().window().borderWidth()); + m_frame.width() + 2*frame().window().borderWidth()-1, + m_frame.height() + 2*frame().window().borderWidth()-1); + +} + +/** + * Helper function that snaps a window to another window + * We snap if we're closer than the x/ylimits. + */ +inline void snapToWindow(int &xlimit, int &ylimit, + int left, int right, int top, int bottom, + int oleft, int oright, int otop, int obottom) { + // Only snap if we're adjacent to the edge we're looking at + + // for left + right, need to be in the right y range + if (top <= obottom && bottom >= otop) { + // left + if (abs(left-oleft) < abs(xlimit)) xlimit = -(left-oleft); + if (abs(right-oleft) < abs(xlimit)) xlimit = -(right-oleft); + + // right + if (abs(left-oright) < abs(xlimit)) xlimit = -(left-oright); + if (abs(right-oright) < abs(xlimit)) xlimit = -(right-oright); + } + + // for top + bottom, need to be in the right x range + if (left <= oright && right >= oleft) { + // top + if (abs(top-otop) < abs(ylimit)) ylimit = -(top-otop); + if (abs(bottom-otop) < abs(ylimit)) ylimit = -(bottom-otop); + + // bottom + if (abs(top-obottom) < abs(ylimit)) ylimit = -(top-obottom); + if (abs(bottom-obottom) < abs(ylimit)) ylimit = -(bottom-obottom); + } + +} + +/* + * Do Whatever snapping magic is necessary, and return using the left and top variables + * to indicate the new x,y position + */ +void FluxboxWindow::doSnapping(int &orig_left, int &orig_top) { + /* + * Snap to screen edge + * Snap to windows + * Snap to toolbar + * Snap to slit + * TODO: + * Xinerama screen edge? + */ + + if (screen.getEdgeSnapThreshold() == 0) return; + + // Keep track of our best offsets so far + // We need to find things less than or equal to the threshold + int dx = screen.getEdgeSnapThreshold() + 1; + int dy = screen.getEdgeSnapThreshold() + 1; + + // we only care about the left/top etc that includes borders + int borderW = m_frame.window().borderWidth(); + + int top = orig_top; // orig include the borders + int left = orig_left; + int right = orig_left + getWidth() + 2*borderW; + int bottom = orig_top + getHeight() + 2*borderW; + + ///////////////////////////////////// + // begin by checking the screen edges + + snapToWindow(dx, dy, left, right, top, bottom, 0, screen.getWidth(), 0, screen.getHeight()); + + ///////////////////////////////////// + // now check window edges + + Workspace::Windows &wins = + screen.getCurrentWorkspace()->getWindowList(); + + Workspace::Windows::iterator it = wins.begin(); + Workspace::Windows::iterator it_end = wins.end(); + + for (; it != it_end; it++) { + if ((*it) == this) continue; // skip myself + + snapToWindow(dx, dy, left, right, top, bottom, + (*it)->getXFrame(), + (*it)->getXFrame() + (*it)->getWidth() + 2*borderW, + (*it)->getYFrame(), + (*it)->getYFrame() + (*it)->getHeight() + 2*borderW); + } + + ///////////////////////////////////// + // now the toolbar + + Toolbar *tbar = screen.getToolbar(); + if (tbar) + snapToWindow(dx, dy, left, right, top, bottom, + tbar->x(), tbar->x() + tbar->width() + 2*borderW, + tbar->y(), tbar->y() + tbar->height() + 2*borderW); + + ///////////////////////////////////// + // and the slit + +#ifdef SLIT + Slit *slit = screen.getSlit(); + if (slit) + snapToWindow(dx, dy, left, right, top, bottom, + slit->x(), slit->x() + slit->width() + 2*borderW, + slit->y(), slit->y() + slit->height() + 2*borderW); +#endif // SLIT + + // commit + if (dx <= screen.getEdgeSnapThreshold()) + orig_left += dx; + if (dy <= screen.getEdgeSnapThreshold()) + orig_top += dy; } diff --git a/src/Window.hh b/src/Window.hh index ba1413b..31be752 100644 --- a/src/Window.hh +++ b/src/Window.hh @@ -22,7 +22,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: Window.hh,v 1.58 2003/04/16 12:28:39 fluxgen Exp $ +// $Id: Window.hh,v 1.59 2003/04/20 02:47:15 rathnor Exp $ #ifndef WINDOW_HH #define WINDOW_HH @@ -348,6 +348,9 @@ private: void setState(unsigned long stateval); void upsize(); void downsize(); + + // modifies left and top if snap is necessary + void doSnapping(int &left, int &top); void right_fixsize(int *x = 0, int *y = 0); void left_fixsize(int *x = 0, int *y = 0); void resizeClient(WinClient &client, unsigned int width, unsigned int height); -- cgit v0.11.2