bugfix(mouse): Fix bad drag tolerances with high scroll speed factors#2823
bugfix(mouse): Fix bad drag tolerances with high scroll speed factors#2823xezon wants to merge 1 commit into
Conversation
|
| Filename | Overview |
|---|---|
| Core/GameEngine/Source/GameClient/Input/Mouse.cpp | Introduces getDragToleranceAdjustedForScrollFactor() to scale drag tolerance inversely with m_keyboardScrollFactor; the division lacks a zero-guard, which can produce +infinity if the scroll factor is ever 0. |
| Core/GameEngine/Include/GameClient/Mouse.h | Adds the getDragToleranceAdjustedForScrollFactor() public const method declaration; straightforward header addition, no issues. |
Sequence Diagram
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant User as Player
participant Input as Input Handler
participant Mouse as Mouse::isClick()
participant Adj as getDragToleranceAdjustedForScrollFactor()
participant GD as TheGlobalData
User->>Input: press + release mouse button
Input->>Mouse: isClick(anchor, dest, t0, t1)
Mouse->>Adj: getDragToleranceAdjustedForScrollFactor()
Adj->>GD: read m_keyboardDefaultScrollFactor
Adj->>GD: read m_keyboardScrollFactor
Note over Adj: dragTolerance = m_dragTolerance * (default / current)<br/>⚠ Division by zero if m_keyboardScrollFactor == 0
Adj-->>Mouse: dragTolerance (Real)
Mouse->>Mouse: "compare abs(delta.x/y) > dragTolerance"
Mouse-->>Input: TRUE (click) / FALSE (drag)
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant User as Player
participant Input as Input Handler
participant Mouse as Mouse::isClick()
participant Adj as getDragToleranceAdjustedForScrollFactor()
participant GD as TheGlobalData
User->>Input: press + release mouse button
Input->>Mouse: isClick(anchor, dest, t0, t1)
Mouse->>Adj: getDragToleranceAdjustedForScrollFactor()
Adj->>GD: read m_keyboardDefaultScrollFactor
Adj->>GD: read m_keyboardScrollFactor
Note over Adj: dragTolerance = m_dragTolerance * (default / current)<br/>⚠ Division by zero if m_keyboardScrollFactor == 0
Adj-->>Mouse: dragTolerance (Real)
Mouse->>Mouse: "compare abs(delta.x/y) > dragTolerance"
Mouse-->>Input: TRUE (click) / FALSE (drag)
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
Core/GameEngine/Source/GameClient/Input/Mouse.cpp:414
**Potential division by zero in scroll factor adjustment**
`m_keyboardScrollFactor` is written directly via `INI::parseReal` without clamping. If a game or mod INI file sets `KeyboardScrollSpeedFactor = 0`, this line produces `+infinity` (IEEE 754), making `dragTolerance` infinite. Every subsequent call to `isClick` would then return `TRUE` for any movement, breaking box selection and right-click drag detection entirely. The `OptionPreferences::getScrollFactor()` path clamps the minimum to `1` (→ `0.01f`), but that overwrite only happens after INI parsing, so a corrupt preference state or a modded INI with zero could still reach here with `m_keyboardScrollFactor == 0.0f`. Adding a guard like `if (TheGlobalData->m_keyboardScrollFactor > 0.0f)` before performing the division would prevent this.
```suggestion
if (TheGlobalData->m_keyboardScrollFactor > 0.0f)
return m_dragTolerance * (TheGlobalData->m_keyboardDefaultScrollFactor / TheGlobalData->m_keyboardScrollFactor);
return m_dragTolerance;
```
Reviews (1): Last reviewed commit: "bugfix(mouse): Fix bad drag tolerances w..." | Re-trigger Greptile
| //------------------------------------------------------------------------------------------------- | ||
| Real Mouse::getDragToleranceAdjustedForScrollFactor() const | ||
| { | ||
| return m_dragTolerance * (TheGlobalData->m_keyboardDefaultScrollFactor / TheGlobalData->m_keyboardScrollFactor); |
There was a problem hiding this comment.
Potential division by zero in scroll factor adjustment
m_keyboardScrollFactor is written directly via INI::parseReal without clamping. If a game or mod INI file sets KeyboardScrollSpeedFactor = 0, this line produces +infinity (IEEE 754), making dragTolerance infinite. Every subsequent call to isClick would then return TRUE for any movement, breaking box selection and right-click drag detection entirely. The OptionPreferences::getScrollFactor() path clamps the minimum to 1 (→ 0.01f), but that overwrite only happens after INI parsing, so a corrupt preference state or a modded INI with zero could still reach here with m_keyboardScrollFactor == 0.0f. Adding a guard like if (TheGlobalData->m_keyboardScrollFactor > 0.0f) before performing the division would prevent this.
| return m_dragTolerance * (TheGlobalData->m_keyboardDefaultScrollFactor / TheGlobalData->m_keyboardScrollFactor); | |
| if (TheGlobalData->m_keyboardScrollFactor > 0.0f) | |
| return m_dragTolerance * (TheGlobalData->m_keyboardDefaultScrollFactor / TheGlobalData->m_keyboardScrollFactor); | |
| return m_dragTolerance; |
Prompt To Fix With AI
This is a comment left during a code review.
Path: Core/GameEngine/Source/GameClient/Input/Mouse.cpp
Line: 414
Comment:
**Potential division by zero in scroll factor adjustment**
`m_keyboardScrollFactor` is written directly via `INI::parseReal` without clamping. If a game or mod INI file sets `KeyboardScrollSpeedFactor = 0`, this line produces `+infinity` (IEEE 754), making `dragTolerance` infinite. Every subsequent call to `isClick` would then return `TRUE` for any movement, breaking box selection and right-click drag detection entirely. The `OptionPreferences::getScrollFactor()` path clamps the minimum to `1` (→ `0.01f`), but that overwrite only happens after INI parsing, so a corrupt preference state or a modded INI with zero could still reach here with `m_keyboardScrollFactor == 0.0f`. Adding a guard like `if (TheGlobalData->m_keyboardScrollFactor > 0.0f)` before performing the division would prevent this.
```suggestion
if (TheGlobalData->m_keyboardScrollFactor > 0.0f)
return m_dragTolerance * (TheGlobalData->m_keyboardDefaultScrollFactor / TheGlobalData->m_keyboardScrollFactor);
return m_dragTolerance;
```
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
If it is zero then we cannot scroll and have more problems than that.
There was a problem hiding this comment.
Fair point — a scroll factor of zero means camera scrolling is already non-functional, so defending against infinite drag tolerance in that broken state adds noise without real benefit. I'll withdraw the concern.
|
#1501 Seems related. Maybe using |
In principle yes, but that would require to be a reasonable value and the arguments of the isClick function to take in world positions instead of mouse positions.
It looks related yes. |
This change fixes the bad drag tolerances with high scroll speed factors, which is a retail bug but is more pronounced in this Project because players are encouraged to set way higher scroll factors after #1026 when higher frame rates no longer increase the camera movement.