diff --git a/dvx/dvxWm.c b/dvx/dvxWm.c index 332228a..2320046 100644 --- a/dvx/dvxWm.c +++ b/dvx/dvxWm.c @@ -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; @@ -2015,8 +2023,9 @@ void wmResizeMove(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, int32_ } if (newW >= minW) { - win->x = newX; - win->w = newW; + win->x = newX; + win->w = newW; + appliedX = true; } } @@ -2028,7 +2037,8 @@ void wmResizeMove(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, int32_ } if (newW >= minW) { - win->w = newW; + win->w = newW; + appliedX = true; } } @@ -2042,8 +2052,9 @@ void wmResizeMove(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, int32_ } if (newH >= minH) { - win->y = newY; - win->h = newH; + win->y = newY; + win->h = newH; + appliedY = true; } } @@ -2055,7 +2066,8 @@ void wmResizeMove(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, int32_ } if (newH >= minH) { - win->h = newH; + win->h = newH; + appliedY = true; } } @@ -2078,8 +2090,13 @@ void wmResizeMove(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, int32_ win->contentDirty = true; } - stack->dragOffX = mouseX; - stack->dragOffY = mouseY; + if (appliedX) { + stack->dragOffX = mouseX; + } + + if (appliedY) { + stack->dragOffY = mouseY; + } // Mark new position dirty dirtyListAdd(dl, win->x, win->y, win->w, win->h);