Mouse should now stick to borders when resize is clamped.

This commit is contained in:
Scott Duensing 2026-03-18 00:20:04 -05:00
parent 83860ac13d
commit fddd97ad91

View file

@ -1900,10 +1900,9 @@ int32_t wmReallocContentBuf(WindowT *win, const DisplayT *d) {
//
// Initiates a window resize. Unlike drag (which stores mouse-to-origin
// offset), resize stores the absolute mouse position. wmResizeMove computes
// delta from this position each frame, then resets it — this incremental
// approach avoids accumulating floating-point-like drift and handles the
// case where the resize is clamped (min/max size) without the window
// "catching up" when the mouse returns to range.
// delta from this position each frame, then conditionally resets it only
// on axes where the resize was applied. When clamped, the delta accumulates
// so the border sticks to the mouse when the user reverses direction.
void wmResizeBegin(WindowStackT *stack, int32_t idx, int32_t edge, int32_t mouseX, int32_t mouseY) {
stack->resizeWindow = idx;
@ -1975,9 +1974,11 @@ void wmResizeEnd(WindowStackT *stack) {
//
// After resizing, the content buffer is reallocated and the app is notified
// via onResize + onPaint. dragOffX/Y are reset to the current mouse position
// so the next frame's delta is incremental. This incremental approach means
// that if the resize is clamped (window at minimum size, user still dragging),
// the window stays put and doesn't snap when the mouse re-enters range.
// only on axes where the resize was actually applied. If clamped (window at
// min/max size), dragOff is NOT updated on that axis, so the accumulated
// delta tracks how far the mouse moved past the border. When the user
// reverses direction, the border immediately follows — it "sticks" to
// the mouse pointer instead of creating a dead zone.
//
// If the user resizes while maximized, the maximized flag is cleared.
// This prevents wmRestore from snapping back to the pre-maximize geometry,
@ -2005,6 +2006,13 @@ void wmResizeMove(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, int32_
// Mark old position dirty
dirtyListAdd(dl, win->x, win->y, win->w, win->h);
// Track whether each axis actually changed, so we only update
// dragOff on axes where the resize was applied. If clamped, leaving
// dragOff unchanged makes the border "stick" to the mouse when the
// user reverses direction, instead of creating a dead zone.
bool appliedX = false;
bool appliedY = false;
if (stack->resizeEdge & RESIZE_LEFT) {
int32_t newX = win->x + dx;
int32_t newW = win->w - dx;
@ -2017,6 +2025,7 @@ void wmResizeMove(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, int32_
if (newW >= minW) {
win->x = newX;
win->w = newW;
appliedX = true;
}
}
@ -2029,6 +2038,7 @@ void wmResizeMove(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, int32_
if (newW >= minW) {
win->w = newW;
appliedX = true;
}
}
@ -2044,6 +2054,7 @@ void wmResizeMove(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, int32_
if (newH >= minH) {
win->y = newY;
win->h = newH;
appliedY = true;
}
}
@ -2056,6 +2067,7 @@ void wmResizeMove(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, int32_
if (newH >= minH) {
win->h = newH;
appliedY = true;
}
}
@ -2078,8 +2090,13 @@ void wmResizeMove(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, int32_
win->contentDirty = true;
}
if (appliedX) {
stack->dragOffX = mouseX;
}
if (appliedY) {
stack->dragOffY = mouseY;
}
// Mark new position dirty
dirtyListAdd(dl, win->x, win->y, win->w, win->h);