From b095f51035b04c3ac15b6686bc61a0f85b35d4ea Mon Sep 17 00:00:00 2001 From: Philipp Sieweck Date: Fri, 9 Dec 2022 05:46:07 +0100 Subject: [PATCH] window: Fix potential freeze during resize The loop in `Window::handleInteractiveMoveResize` "bruteforces" the value for `nextMoveResizeGeom` such that the area of `nextMoveResizeGeom` contains at least `requiredPixels`. In each loop iteration, one or more attributes (left, right, top, bottom) of `nextMoveResizeGeom` are selected to be moved +/-1.0 towards the value of `currentMoveResizeGeom`. The loop terminates if either the area of `nextMoveResizeGeom` is large enough or `nextMoveResizeGeom == currentMoveResizeGeom`. The problem is that the variables compared and adjusted here are floating point variables, and their difference may not be a whole number. Using +/-1.0 adjustments can make the loop oscillate indefinitely around the target value. This commit ensures loop termination by using `qFuzzyCompare` to compare floating point values and correctly handles the cases where adjustments smaller than 1.0 are needed to reach the target value. --- src/window.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/window.cpp b/src/window.cpp index ed14e1e4ba..bbc5f94140 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1994,10 +1994,10 @@ void Window::handleInteractiveMoveResize(int x, int y, int x_root, int y_root) // precedence. The opposing edge has no impact on visiblePixels and only one of // the adjacent can alter at a time, ie. it's enough to ignore adjacent edges // if the title edge altered - bool leftChanged = currentMoveResizeGeom.left() != currentTry.left(); - bool rightChanged = currentMoveResizeGeom.right() != currentTry.right(); - bool topChanged = currentMoveResizeGeom.top() != currentTry.top(); - bool btmChanged = currentMoveResizeGeom.bottom() != currentTry.bottom(); + bool leftChanged = !qFuzzyCompare(currentMoveResizeGeom.left(), currentTry.left()); + bool rightChanged = !qFuzzyCompare(currentMoveResizeGeom.right(), currentTry.right()); + bool topChanged = !qFuzzyCompare(currentMoveResizeGeom.top(), currentTry.top()); + bool btmChanged = !qFuzzyCompare(currentMoveResizeGeom.bottom(), currentTry.bottom()); auto fixChangedState = [titleFailed](bool &major, bool &counter, bool &ad1, bool &ad2) { counter = false; if (titleFailed) { @@ -2023,13 +2023,13 @@ void Window::handleInteractiveMoveResize(int x, int y, int x_root, int y_root) break; } if (topChanged) { - currentTry.setTop(currentTry.y() + sign(currentMoveResizeGeom.y() - currentTry.y())); + currentTry.setTop(currentTry.y() + qBound(-1.0, currentMoveResizeGeom.y() - currentTry.y(), 1.0)); } else if (leftChanged) { - currentTry.setLeft(currentTry.x() + sign(currentMoveResizeGeom.x() - currentTry.x())); + currentTry.setLeft(currentTry.x() + qBound(-1.0, currentMoveResizeGeom.x() - currentTry.x(), 1.0)); } else if (btmChanged) { - currentTry.setBottom(currentTry.bottom() + sign(currentMoveResizeGeom.bottom() - currentTry.bottom())); + currentTry.setBottom(currentTry.bottom() + qBound(-1.0, currentMoveResizeGeom.bottom() - currentTry.bottom(), 1.0)); } else if (rightChanged) { - currentTry.setRight(currentTry.right() + sign(currentMoveResizeGeom.right() - currentTry.right())); + currentTry.setRight(currentTry.right() + qBound(-1.0, currentMoveResizeGeom.right() - currentTry.right(), 1.0)); } else { break; // no position changed - that's certainly not good }