aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/config/ConfigDescriptions.hpp6
-rw-r--r--src/config/ConfigManager.cpp1
-rw-r--r--src/layout/IHyprLayout.cpp163
3 files changed, 90 insertions, 80 deletions
diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp
index 0177f92b..07034e71 100644
--- a/src/config/ConfigDescriptions.hpp
+++ b/src/config/ConfigDescriptions.hpp
@@ -122,6 +122,12 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
.type = CONFIG_OPTION_INT,
.data = SConfigOptionDescription::SRangeData{10, 0, 100},
},
+ SConfigOptionDescription{
+ .value = "general:snap:border_overlap",
+ .description = "if true, windows snap such that only one border's worth of space is between them",
+ .type = CONFIG_OPTION_BOOL,
+ .data = SConfigOptionDescription::SBoolData{false},
+ },
/*
* decoration:
diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp
index 909dfc63..f1ba8d7f 100644
--- a/src/config/ConfigManager.cpp
+++ b/src/config/ConfigManager.cpp
@@ -344,6 +344,7 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("general:snap:enabled", Hyprlang::INT{0});
m_pConfig->addConfigValue("general:snap:window_gap", Hyprlang::INT{10});
m_pConfig->addConfigValue("general:snap:monitor_gap", Hyprlang::INT{10});
+ m_pConfig->addConfigValue("general:snap:border_overlap", Hyprlang::INT{0});
m_pConfig->addConfigValue("misc:disable_hyprland_logo", Hyprlang::INT{0});
m_pConfig->addConfigValue("misc:disable_splash_rendering", Hyprlang::INT{0});
diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp
index 73e7a125..980311d6 100644
--- a/src/layout/IHyprLayout.cpp
+++ b/src/layout/IHyprLayout.cpp
@@ -389,91 +389,93 @@ void IHyprLayout::onEndDragWindow() {
g_pInputManager->m_bWasDraggingWindow = false;
}
-static inline bool canSnap(const double sideA, const double sideB, const double gap) {
- return std::abs(sideA - sideB) < gap;
+static inline bool canSnap(const double SIDEA, const double SIDEB, const double GAP) {
+ return std::abs(SIDEA - SIDEB) < GAP;
}
-static void snapMoveLeft(double& pos, double& len, const double p) {
- pos = p;
+static void snapMove(double& start, double& end, const double P) {
+ end = P + (end - start);
+ start = P;
}
-static void snapMoveRight(double& pos, double& len, const double p) {
- pos = p - len;
-}
-
-static void snapResizeLeft(double& pos, double& len, const double p) {
- len += pos - p;
- pos = p;
-}
-
-static void snapResizeRight(double& pos, double& len, const double p) {
- len = p - pos;
+static void snapResize(double& start, double& end, const double P) {
+ start = P;
}
typedef std::function<void(double&, double&, const double)> SnapFn;
-static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRAGGINGWINDOW, const eMouseBindMode mode, const int corner, const Vector2D& beginSize) {
- static auto SNAPWINDOWGAP = CConfigValue<Hyprlang::INT>("general:snap:window_gap");
- static auto SNAPMONITORGAP = CConfigValue<Hyprlang::INT>("general:snap:monitor_gap");
+static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRAGGINGWINDOW, const eMouseBindMode MODE, const int CORNER, const Vector2D& BEGINSIZE) {
+ static auto SNAPWINDOWGAP = CConfigValue<Hyprlang::INT>("general:snap:window_gap");
+ static auto SNAPMONITORGAP = CConfigValue<Hyprlang::INT>("general:snap:monitor_gap");
+ static auto SNAPBORDEROVERLAP = CConfigValue<Hyprlang::INT>("general:snap:border_overlap");
- const SnapFn snapRight = (mode == MBIND_MOVE) ? snapMoveRight : snapResizeRight;
- const SnapFn snapLeft = (mode == MBIND_MOVE) ? snapMoveLeft : snapResizeLeft;
- const SnapFn snapDown = snapRight;
- const SnapFn snapUp = snapLeft;
- int snaps = 0;
+ const SnapFn SNAP = (MODE == MBIND_MOVE) ? snapMove : snapResize;
+ int snaps = 0;
+ const bool OVERLAP = *SNAPBORDEROVERLAP;
const int DRAGGINGBORDERSIZE = DRAGGINGWINDOW->getRealBorderSize();
- CBox sourceBox = CBox{sourcePos, sourceSize}.expand(DRAGGINGBORDERSIZE);
+
+ struct SRange {
+ double start = 0;
+ double end = 0;
+ };
+ SRange sourceX = {sourcePos.x, sourcePos.x + sourceSize.x};
+ SRange sourceY = {sourcePos.y, sourcePos.y + sourceSize.y};
if (*SNAPWINDOWGAP) {
- const auto WSID = DRAGGINGWINDOW->workspaceID();
+ const double GAPSIZE = *SNAPWINDOWGAP;
+ const auto WSID = DRAGGINGWINDOW->workspaceID();
for (auto& other : g_pCompositor->m_vWindows) {
if (other == DRAGGINGWINDOW || other->workspaceID() != WSID || !other->m_bIsMapped || other->m_bFadingOut || other->isX11OverrideRedirect())
continue;
- const int BORDERSIZE = other->getRealBorderSize();
- const double GAPSIZE = *SNAPWINDOWGAP + BORDERSIZE;
+ const int OTHERBORDERSIZE = other->getRealBorderSize();
+ const double BORDERSIZE = OVERLAP ? std::max(DRAGGINGBORDERSIZE, OTHERBORDERSIZE) : (DRAGGINGBORDERSIZE + OTHERBORDERSIZE);
- const CBox SURFBB = other->getWindowMainSurfaceBox().expand(BORDERSIZE);
- const Vector2D end = sourceBox.pos() + sourceBox.size();
+ const CBox SURF = other->getWindowMainSurfaceBox();
+ const SRange SURFBX = {SURF.x - BORDERSIZE, SURF.x + SURF.w + BORDERSIZE};
+ const SRange SURFBY = {SURF.y - BORDERSIZE, SURF.y + SURF.h + BORDERSIZE};
- // only snap windows if their ranges intersect in the opposite axis
- if (sourceBox.y <= SURFBB.y + SURFBB.h && SURFBB.y <= end.y) {
- if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(sourceBox.x, SURFBB.x + SURFBB.w, GAPSIZE)) {
- snapLeft(sourceBox.x, sourceBox.w, SURFBB.x + SURFBB.w);
+ // only snap windows if their ranges overlap in the opposite axis
+ if (sourceY.start <= SURFBY.end && SURFBY.start <= sourceY.end) {
+ if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(sourceX.start, SURFBX.end, GAPSIZE)) {
+ SNAP(sourceX.start, sourceX.end, SURFBX.end);
snaps |= SNAP_LEFT;
- } else if (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(end.x, SURFBB.x, GAPSIZE)) {
- snapRight(sourceBox.x, sourceBox.w, SURFBB.x);
+ } else if (CORNER & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(sourceX.end, SURFBX.start, GAPSIZE)) {
+ SNAP(sourceX.end, sourceX.start, SURFBX.start);
snaps |= SNAP_RIGHT;
}
}
- if (sourceBox.x <= SURFBB.x + SURFBB.w && SURFBB.x <= end.x) {
- if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(sourceBox.y, SURFBB.y + SURFBB.h, GAPSIZE)) {
- snapUp(sourceBox.y, sourceBox.h, SURFBB.y + SURFBB.h);
+ if (sourceX.start <= SURFBX.end && SURFBX.start <= sourceX.end) {
+ if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(sourceY.start, SURFBY.end, GAPSIZE)) {
+ SNAP(sourceY.start, sourceY.end, SURFBY.end);
snaps |= SNAP_UP;
- } else if (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(end.y, SURFBB.y, GAPSIZE)) {
- snapDown(sourceBox.y, sourceBox.h, SURFBB.y);
+ } else if (CORNER & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(sourceY.end, SURFBY.start, GAPSIZE)) {
+ SNAP(sourceY.end, sourceY.start, SURFBY.start);
snaps |= SNAP_DOWN;
}
}
// corner snapping
- if (sourceBox.x == SURFBB.x + SURFBB.w || SURFBB.x == sourceBox.x + sourceBox.w) {
- if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(sourceBox.y, SURFBB.y, GAPSIZE)) {
- snapUp(sourceBox.y, sourceBox.h, SURFBB.y);
+ const double BORDERDIFF = OTHERBORDERSIZE - DRAGGINGBORDERSIZE;
+ if (sourceX.start == SURFBX.end || SURFBX.start == sourceX.end) {
+ const SRange SURFY = {SURF.y - BORDERDIFF, SURF.y + SURF.h + BORDERDIFF};
+ if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(sourceY.start, SURFY.start, GAPSIZE)) {
+ SNAP(sourceY.start, sourceY.end, SURFY.start);
snaps |= SNAP_UP;
- } else if (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(end.y, SURFBB.y + SURFBB.h, GAPSIZE)) {
- snapDown(sourceBox.y, sourceBox.h, SURFBB.y + SURFBB.h);
+ } else if (CORNER & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(sourceY.end, SURFY.end, GAPSIZE)) {
+ SNAP(sourceY.end, sourceY.start, SURFY.end);
snaps |= SNAP_DOWN;
}
}
- if (sourceBox.y == SURFBB.y + SURFBB.h || SURFBB.y == sourceBox.y + sourceBox.h) {
- if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(sourceBox.x, SURFBB.x, GAPSIZE)) {
- snapLeft(sourceBox.x, sourceBox.w, SURFBB.x);
+ if (sourceY.start == SURFBY.end || SURFBY.start == sourceY.end) {
+ const SRange SURFX = {SURF.x - BORDERDIFF, SURF.x + SURF.w + BORDERDIFF};
+ if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(sourceX.start, SURFX.start, GAPSIZE)) {
+ SNAP(sourceX.start, sourceX.end, SURFX.start);
snaps |= SNAP_LEFT;
- } else if (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(end.x, SURFBB.x + SURFBB.w, GAPSIZE)) {
- snapRight(sourceBox.x, sourceBox.w, SURFBB.x + SURFBB.w);
+ } else if (CORNER & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(sourceX.end, SURFX.end, GAPSIZE)) {
+ SNAP(sourceX.end, sourceX.start, SURFX.end);
snaps |= SNAP_RIGHT;
}
}
@@ -481,49 +483,50 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA
}
if (*SNAPMONITORGAP) {
- const auto MON = DRAGGINGWINDOW->m_pMonitor.lock();
- const CBox mon =
- CBox{MON->vecPosition.x + MON->vecReservedTopLeft.x, MON->vecPosition.y + MON->vecReservedTopLeft.y,
- MON->vecSize.x - MON->vecReservedTopLeft.x - MON->vecReservedBottomRight.x, MON->vecSize.y - MON->vecReservedBottomRight.y - MON->vecReservedTopLeft.y};
- const double gap = *SNAPMONITORGAP;
-
- if (canSnap(sourceBox.x, mon.x, gap)) {
- snapLeft(sourceBox.x, sourceBox.w, mon.x);
+ const double GAPSIZE = *SNAPMONITORGAP;
+ const double BORDERSIZE = OVERLAP ? 0 : DRAGGINGBORDERSIZE;
+ const double BORDERDIFF = DRAGGINGBORDERSIZE - BORDERSIZE;
+ const auto MON = DRAGGINGWINDOW->m_pMonitor.lock();
+
+ SRange monX = {MON->vecPosition.x + BORDERSIZE, MON->vecSize.x - BORDERSIZE};
+ SRange monY = {MON->vecPosition.y + BORDERSIZE, MON->vecSize.y - BORDERSIZE};
+
+ if (canSnap(sourceX.start, monX.start, GAPSIZE) || canSnap(sourceX.start, (monX.start += MON->vecReservedTopLeft.x + BORDERDIFF), GAPSIZE)) {
+ SNAP(sourceX.start, sourceX.end, monX.start);
snaps |= SNAP_LEFT;
}
- if (canSnap(sourceBox.x + sourceBox.w, mon.x + mon.w, gap)) {
- snapRight(sourceBox.x, sourceBox.w, mon.w + mon.x);
+ if (canSnap(sourceX.end, monX.end, GAPSIZE) || canSnap(sourceX.end, (monX.end -= MON->vecReservedBottomRight.x + BORDERDIFF), GAPSIZE)) {
+ SNAP(sourceX.end, sourceX.start, monX.end);
snaps |= SNAP_RIGHT;
}
- if (canSnap(sourceBox.y, mon.y, gap)) {
- snapUp(sourceBox.y, sourceBox.h, mon.y);
+ if (canSnap(sourceY.start, monY.start, GAPSIZE) || canSnap(sourceY.start, (monY.start += MON->vecReservedTopLeft.y + BORDERDIFF), GAPSIZE)) {
+ SNAP(sourceY.start, sourceY.end, monY.start);
snaps |= SNAP_UP;
}
- if (canSnap(sourceBox.y + sourceBox.h, mon.y + mon.h, gap)) {
- snapDown(sourceBox.y, sourceBox.h, mon.h + mon.y);
+ if (canSnap(sourceY.end, monY.end, GAPSIZE) || canSnap(sourceY.end, (monY.end -= MON->vecReservedBottomRight.y + BORDERDIFF), GAPSIZE)) {
+ SNAP(sourceY.end, sourceY.start, monY.end);
snaps |= SNAP_DOWN;
}
}
- if (mode == MBIND_RESIZE_FORCE_RATIO) {
- const double RATIO = beginSize.y / beginSize.x;
-
- if ((corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && snaps & SNAP_LEFT) || (corner & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && snaps & SNAP_RIGHT)) {
- const double sizeY = sourceBox.w * RATIO;
- if (corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT))
- sourceBox.y += sourceBox.h - sizeY;
- sourceBox.h = sizeY;
- } else if ((corner & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && snaps & SNAP_UP) || (corner & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && snaps & SNAP_DOWN)) {
- const double sizeX = sourceBox.h / RATIO;
- if (corner & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT))
- sourceBox.x += sourceBox.w - sizeX;
- sourceBox.w = sizeX;
+ if (MODE == MBIND_RESIZE_FORCE_RATIO) {
+ if ((CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && snaps & SNAP_LEFT) || (CORNER & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && snaps & SNAP_RIGHT)) {
+ const double SIZEY = (sourceX.end - sourceX.start) * (BEGINSIZE.y / BEGINSIZE.x);
+ if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT))
+ sourceY.start = sourceY.end - SIZEY;
+ else
+ sourceY.end = sourceY.start + SIZEY;
+ } else if ((CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && snaps & SNAP_UP) || (CORNER & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && snaps & SNAP_DOWN)) {
+ const double SIZEX = (sourceY.end - sourceY.start) * (BEGINSIZE.x / BEGINSIZE.y);
+ if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT))
+ sourceX.start = sourceX.end - SIZEX;
+ else
+ sourceX.end = sourceX.start + SIZEX;
}
}
- sourceBox.expand(-DRAGGINGBORDERSIZE).round();
- sourcePos = sourceBox.pos();
- sourceSize = sourceBox.size();
+ sourcePos = {sourceX.start, sourceY.start};
+ sourceSize = {sourceX.end - sourceX.start, sourceY.end - sourceY.start};
}
void IHyprLayout::onMouseMove(const Vector2D& mousePos) {