From 38d64422e4c893150227d203ad3199ae9faca48b Mon Sep 17 00:00:00 2001 From: Ahmet Fatih Cengiz <37782582+afc-afc0@users.noreply.github.com> Date: Sun, 12 Apr 2026 02:37:10 -0400 Subject: [PATCH 1/3] bugfix(input): Fix touchpad upward scrolling in UI list boxes Preserve wheel delta sign when normalizing for touchpad scroll direction detection. Touchpad devices send small continuous deltas that were truncated to 0 by integer division with MOUSE_WHEEL_DELTA, causing upward scroll to be misidentified as downward scroll. Clamp the normalized value to at least 1 or -1 based on the original sign. --- Core/GameEngine/Source/GameClient/Input/Mouse.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Core/GameEngine/Source/GameClient/Input/Mouse.cpp b/Core/GameEngine/Source/GameClient/Input/Mouse.cpp index 67ceb096461..4abb1d44297 100644 --- a/Core/GameEngine/Source/GameClient/Input/Mouse.cpp +++ b/Core/GameEngine/Source/GameClient/Input/Mouse.cpp @@ -824,7 +824,9 @@ void Mouse::createStreamMessages() { msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_WHEEL ); msg->appendPixelArgument( m_currMouse.pos ); - msg->appendIntegerArgument( m_currMouse.wheelPos / 120 ); // wheel delta + // TheSuperHackers @bugfix Preserve wheel delta sign for touchpad scroll direction detection + const Int wheelTicks = m_currMouse.wheelPos / MOUSE_WHEEL_DELTA; + msg->appendIntegerArgument( m_currMouse.wheelPos > 0 ? max( 1, wheelTicks ) : min( -1, wheelTicks ) ); msg->appendIntegerArgument( TheKeyboard->getModifierFlags() ); } From a87807f22638ac95beec4a4fe944abf45f3bb41d Mon Sep 17 00:00:00 2001 From: Ahmet Fatih Cengiz <37782582+afc-afc0@users.noreply.github.com> Date: Mon, 13 Apr 2026 20:57:36 -0400 Subject: [PATCH 2/3] bugfix(input): cleanup --- Core/GameEngine/Source/GameClient/Input/Mouse.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Core/GameEngine/Source/GameClient/Input/Mouse.cpp b/Core/GameEngine/Source/GameClient/Input/Mouse.cpp index 4abb1d44297..90c7d5a819a 100644 --- a/Core/GameEngine/Source/GameClient/Input/Mouse.cpp +++ b/Core/GameEngine/Source/GameClient/Input/Mouse.cpp @@ -824,9 +824,10 @@ void Mouse::createStreamMessages() { msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_WHEEL ); msg->appendPixelArgument( m_currMouse.pos ); - // TheSuperHackers @bugfix Preserve wheel delta sign for touchpad scroll direction detection - const Int wheelTicks = m_currMouse.wheelPos / MOUSE_WHEEL_DELTA; - msg->appendIntegerArgument( m_currMouse.wheelPos > 0 ? max( 1, wheelTicks ) : min( -1, wheelTicks ) ); + // TheSuperHackers @bugfix Guarantee non-zero wheel delta to preserve scroll direction for touchpad input + Int wheelTicks = m_currMouse.wheelPos / MOUSE_WHEEL_DELTA; + wheelTicks = m_currMouse.wheelPos > 0 ? max( 1, wheelTicks ) : min( -1, wheelTicks ); + msg->appendIntegerArgument( wheelTicks ); msg->appendIntegerArgument( TheKeyboard->getModifierFlags() ); } From d2e3c49043b15d5e7f5198338d6d9be669b8ae75 Mon Sep 17 00:00:00 2001 From: Ahmet Fatih Cengiz <37782582+afc-afc0@users.noreply.github.com> Date: Tue, 14 Apr 2026 21:35:36 -0400 Subject: [PATCH 3/3] Apply float based fix --- Core/GameEngine/Source/GameClient/Input/Mouse.cpp | 6 ++---- Generals/Code/GameEngine/Include/Common/MessageStream.h | 2 +- .../Source/GameClient/MessageStream/LookAtXlat.cpp | 2 +- .../Source/GameClient/MessageStream/WindowXlat.cpp | 4 ++-- GeneralsMD/Code/GameEngine/Include/Common/MessageStream.h | 2 +- .../Source/GameClient/MessageStream/LookAtXlat.cpp | 2 +- .../Source/GameClient/MessageStream/WindowXlat.cpp | 4 ++-- 7 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Core/GameEngine/Source/GameClient/Input/Mouse.cpp b/Core/GameEngine/Source/GameClient/Input/Mouse.cpp index 90c7d5a819a..a1c2cb97a4e 100644 --- a/Core/GameEngine/Source/GameClient/Input/Mouse.cpp +++ b/Core/GameEngine/Source/GameClient/Input/Mouse.cpp @@ -824,10 +824,8 @@ void Mouse::createStreamMessages() { msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_WHEEL ); msg->appendPixelArgument( m_currMouse.pos ); - // TheSuperHackers @bugfix Guarantee non-zero wheel delta to preserve scroll direction for touchpad input - Int wheelTicks = m_currMouse.wheelPos / MOUSE_WHEEL_DELTA; - wheelTicks = m_currMouse.wheelPos > 0 ? max( 1, wheelTicks ) : min( -1, wheelTicks ); - msg->appendIntegerArgument( wheelTicks ); + // TheSuperHackers @bugfix Use float wheel delta to preserve fractional values from touchpad input + msg->appendRealArgument( m_currMouse.wheelPos / (Real)MOUSE_WHEEL_DELTA ); msg->appendIntegerArgument( TheKeyboard->getModifierFlags() ); } diff --git a/Generals/Code/GameEngine/Include/Common/MessageStream.h b/Generals/Code/GameEngine/Include/Common/MessageStream.h index 408c66aa3dd..103e67fa3a4 100644 --- a/Generals/Code/GameEngine/Include/Common/MessageStream.h +++ b/Generals/Code/GameEngine/Include/Common/MessageStream.h @@ -131,7 +131,7 @@ class GameMessage : public MemoryPoolObject MSG_RAW_MOUSE_RIGHT_DOUBLE_CLICK, ///< (pixel, modifiers, time) MSG_RAW_MOUSE_RIGHT_BUTTON_UP, ///< (pixel, modifiers, time) MSG_RAW_MOUSE_RIGHT_DRAG, ///< drag of the mouse with a button held down - MSG_RAW_MOUSE_WHEEL, ///< (Int spin, + is away, - is toward user) + MSG_RAW_MOUSE_WHEEL, ///< (Real spin, + is away, - is toward user) MSG_RAW_MOUSE_END, MSG_RAW_KEY_DOWN, ///< (KeyDefType) the given key was pressed (uses Microsoft VK_ codes) diff --git a/Generals/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp b/Generals/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp index 484f7df7c54..0174dd5fce5 100644 --- a/Generals/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp @@ -406,7 +406,7 @@ GameMessageDisposition LookAtTranslator::translateGameMessage(const GameMessage { m_lastMouseMoveTimeMsec = timeGetTime(); - const Int spin = msg->getArgument( 1 )->integer; + const Real spin = msg->getArgument( 1 )->real; const Real zoom = -spin * View::ZoomHeightPerSecond; TheTacticalView->userZoom(zoom); diff --git a/Generals/Code/GameEngine/Source/GameClient/MessageStream/WindowXlat.cpp b/Generals/Code/GameEngine/Source/GameClient/MessageStream/WindowXlat.cpp index 6612ae56ab1..6f6bf5d9e39 100644 --- a/Generals/Code/GameEngine/Source/GameClient/MessageStream/WindowXlat.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/MessageStream/WindowXlat.cpp @@ -135,7 +135,7 @@ static GameWindowMessage rawMouseToWindowMessage( const GameMessage *msg ) // ------------------------------------------------------------------------ case GameMessage::MSG_RAW_MOUSE_WHEEL: - if( msg->getArgument( 1 )->integer > 0 ) + if( msg->getArgument( 1 )->real > 0 ) gwm = GWM_WHEEL_UP; else gwm = GWM_WHEEL_DOWN; @@ -266,7 +266,7 @@ GameMessageDisposition WindowTranslator::translateGameMessage(const GameMessage ICoord2D mousePos = msg->getArgument( 0 )->pixel; // get wheel position - Int wheelPos = msg->getArgument( 1 )->integer; + Real wheelPos = msg->getArgument( 1 )->real; // process wheel event GameWindowMessage gwm = rawMouseToWindowMessage( msg ); diff --git a/GeneralsMD/Code/GameEngine/Include/Common/MessageStream.h b/GeneralsMD/Code/GameEngine/Include/Common/MessageStream.h index 3f54a01b5aa..3c53bcd0235 100644 --- a/GeneralsMD/Code/GameEngine/Include/Common/MessageStream.h +++ b/GeneralsMD/Code/GameEngine/Include/Common/MessageStream.h @@ -131,7 +131,7 @@ class GameMessage : public MemoryPoolObject MSG_RAW_MOUSE_RIGHT_DOUBLE_CLICK, ///< (pixel, modifiers, time) MSG_RAW_MOUSE_RIGHT_BUTTON_UP, ///< (pixel, modifiers, time) MSG_RAW_MOUSE_RIGHT_DRAG, ///< drag of the mouse with a button held down - MSG_RAW_MOUSE_WHEEL, ///< (Int spin, + is away, - is toward user) + MSG_RAW_MOUSE_WHEEL, ///< (Real spin, + is away, - is toward user) MSG_RAW_MOUSE_END, MSG_RAW_KEY_DOWN, ///< (KeyDefType) the given key was pressed (uses Microsoft VK_ codes) diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp index 133903eae5e..b0fced4d69e 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp @@ -405,7 +405,7 @@ GameMessageDisposition LookAtTranslator::translateGameMessage(const GameMessage { m_lastMouseMoveTimeMsec = timeGetTime(); - const Int spin = msg->getArgument( 1 )->integer; + const Real spin = msg->getArgument( 1 )->real; const Real zoom = -spin * View::ZoomHeightPerSecond; TheTacticalView->userZoom(zoom); diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/WindowXlat.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/WindowXlat.cpp index d97380aff95..8345f051a1c 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/WindowXlat.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/WindowXlat.cpp @@ -135,7 +135,7 @@ static GameWindowMessage rawMouseToWindowMessage( const GameMessage *msg ) // ------------------------------------------------------------------------ case GameMessage::MSG_RAW_MOUSE_WHEEL: - if( msg->getArgument( 1 )->integer > 0 ) + if( msg->getArgument( 1 )->real > 0 ) gwm = GWM_WHEEL_UP; else gwm = GWM_WHEEL_DOWN; @@ -284,7 +284,7 @@ GameMessageDisposition WindowTranslator::translateGameMessage(const GameMessage ICoord2D mousePos = msg->getArgument( 0 )->pixel; // get wheel position - Int wheelPos = msg->getArgument( 1 )->integer; + Real wheelPos = msg->getArgument( 1 )->real; // process wheel event GameWindowMessage gwm = rawMouseToWindowMessage( msg );