Skip to content

feat(options): Implement user option to toggle Right Mouse Scroll with Alternate Mouse#2798

Merged
xezon merged 2 commits into
TheSuperHackers:mainfrom
xezon:xezon/add-rmb-scroll-alternate-mouse-option
Jun 16, 2026
Merged

feat(options): Implement user option to toggle Right Mouse Scroll with Alternate Mouse#2798
xezon merged 2 commits into
TheSuperHackers:mainfrom
xezon:xezon/add-rmb-scroll-alternate-mouse-option

Conversation

@xezon

@xezon xezon commented Jun 15, 2026

Copy link
Copy Markdown

This change adds a user option to enable or disable Right Mouse Scroll with Alternate Mouse. It can be toggled with UseRightMouseScrollWithAlternateMouse=yes/no in the Options.ini

The reason for this option is that before merge #2794 the RMB scroll was disabled in Generals, but enabled in Zero Hour. It is now default disabled in Generals and default enabled in Zero Hour, but both games can toggle it. This avoids potential irritations for legacy Generals players with Alternate Mouse setup.

TODO

  • Replicate in Generals

… with Alternate Mouse

Toggle with UseRightMouseScrollWithAlternateMouse=yes/no in Options.ini
@xezon xezon added Enhancement Is new feature or request Minor Severity: Minor < Major < Critical < Blocker Gen Relates to Generals ZH Relates to Zero Hour Input labels Jun 15, 2026
@greptile-apps

greptile-apps Bot commented Jun 15, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds a user-configurable option (UseRightMouseScrollWithAlternateMouse=yes/no in Options.ini) to control whether right-mouse-button scrolling is active when Alternate Mouse mode is enabled, following up on #2794 which changed the default behaviour per-game.

  • Adds m_useRightMouseScrollWithAlternateMouse to GlobalData for both Generals and Zero Hour, defaulting to FALSE in Generals and TRUE in Zero Hour; the Core OptionPreferences getter falls back to the GlobalData default when the key is absent from the INI.
  • Gates setScrolling(SCROLL_RMB) in LookAtXlat.cpp (both targets) behind a userWantsRMBScroll boolean that respects the new flag.
  • Preserves the INI value in saveOptions() on both targets so it is not silently discarded when the user saves other options from the menu; no UI widget exists yet (marked @todo).

Confidence Score: 5/5

The change is safe to merge — all three sites (preference loading, runtime gating, and options persistence) are updated consistently in both Generals and Zero Hour.

The logic for userWantsRMBScroll is correct, the OptionPreferences fallback path is consistent with existing getters, and the previously missing m_useRightMouseScrollWithAlternateMouse field in Generals/Code/GameEngine/Include/Common/GlobalData.h has been added. The only outstanding items are the deferred dead-code cleanup in GeneralsMD's #if RTS_GENERALS block and the future UI checkbox, both acknowledged by the author.

No files require special attention; the known deferred items (#if RTS_GENERALS dead code in GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp and the missing UI checkbox) are tracked TODOs acknowledged by the author.

Important Files Changed

Filename Overview
Core/GameEngine/Include/Common/OptionPreferences.h Adds getRightMouseScrollWithAlternateMouseEnabled() const declaration; correctly mirrors the pattern of surrounding methods.
Core/GameEngine/Source/Common/OptionPreferences.cpp Implements the new preference getter; falls back to TheGlobalData->m_useRightMouseScrollWithAlternateMouse when key is absent, consistent with neighbouring getters.
Generals/Code/GameEngine/Include/Common/GlobalData.h Adds m_useRightMouseScrollWithAlternateMouse field, addressing the missing-field compilation issue noted in a prior review thread.
Generals/Code/GameEngine/Source/Common/GlobalData.cpp Initialises the new field in the constructor (default FALSE via #if RTS_GENERALS); the historical attribution comment carries a pre-2026 date in newly added code.
Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp Persists the INI value on every options-save so it isn't clobbered; no UI widget yet (gated with @todo).
Generals/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp Adds userWantsRMBScroll guard before setScrolling(SCROLL_RMB); logic correctly allows RMB scroll when not in alternate-mouse mode or when the new flag permits it.
GeneralsMD/Code/GameEngine/Include/Common/GlobalData.h Mirrors the Generals header change; adds m_useRightMouseScrollWithAlternateMouse in the correct position.
GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp Same constructor block as the Generals copy (including the pre-2026 attribution comment); the #if RTS_GENERALS dead-code issue was noted in a prior thread and is deferred.
GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp Identical pattern to the Generals OptionsMenu change; correctly preserves the setting on save.
GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp Mirrors the Generals LookAtXlat.cpp change; RMB scroll guard logic is identical and correct.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant INI as Options.ini
    participant OP as OptionPreferences
    participant GD as GlobalData
    participant LX as LookAtXlat
    participant OM as OptionsMenu (saveOptions)

    Note over GD: Constructor sets default<br/>Generals: FALSE<br/>ZeroHour: TRUE
    GD->>OP: parseGameDataDefinition calls getRightMouseScrollWithAlternateMouseEnabled()
    OP->>INI: find("UseRightMouseScrollWithAlternateMouse")
    alt key present
        INI-->>OP: "yes"/"no"
        OP-->>GD: TRUE / FALSE
    else key absent
        OP-->>GD: m_useRightMouseScrollWithAlternateMouse (default)
    end
    Note over GD: m_useRightMouseScrollWithAlternateMouse set

    LX->>GD: read m_useAlternateMouse + m_useRightMouseScrollWithAlternateMouse
    LX->>LX: "userWantsRMBScroll = !useAlt || useRMBWithAlt"
    alt "userWantsRMBScroll && !isSelecting && !isScrolling"
        LX->>LX: setScrolling(SCROLL_RMB)
    end

    OM->>OP: getRightMouseScrollWithAlternateMouseEnabled()
    OP-->>OM: current value
    OM->>INI: write "UseRightMouseScrollWithAlternateMouse"
    OM->>GD: update m_useRightMouseScrollWithAlternateMouse
Loading
%%{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 INI as Options.ini
    participant OP as OptionPreferences
    participant GD as GlobalData
    participant LX as LookAtXlat
    participant OM as OptionsMenu (saveOptions)

    Note over GD: Constructor sets default<br/>Generals: FALSE<br/>ZeroHour: TRUE
    GD->>OP: parseGameDataDefinition calls getRightMouseScrollWithAlternateMouseEnabled()
    OP->>INI: find("UseRightMouseScrollWithAlternateMouse")
    alt key present
        INI-->>OP: "yes"/"no"
        OP-->>GD: TRUE / FALSE
    else key absent
        OP-->>GD: m_useRightMouseScrollWithAlternateMouse (default)
    end
    Note over GD: m_useRightMouseScrollWithAlternateMouse set

    LX->>GD: read m_useAlternateMouse + m_useRightMouseScrollWithAlternateMouse
    LX->>LX: "userWantsRMBScroll = !useAlt || useRMBWithAlt"
    alt "userWantsRMBScroll && !isSelecting && !isScrolling"
        LX->>LX: setScrolling(SCROLL_RMB)
    end

    OM->>OP: getRightMouseScrollWithAlternateMouseEnabled()
    OP-->>OM: current value
    OM->>INI: write "UseRightMouseScrollWithAlternateMouse"
    OM->>GD: update m_useRightMouseScrollWithAlternateMouse
Loading

Reviews (2): Last reviewed commit: "Replicate in Generals" | Re-trigger Greptile

Comment thread Core/GameEngine/Source/Common/OptionPreferences.cpp
Comment thread GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp
Comment thread Core/GameEngine/Source/Common/OptionPreferences.cpp
Comment thread GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp
@xezon

xezon commented Jun 16, 2026

Copy link
Copy Markdown
Author

Replicated in Generals with conflicts

D:\Projects\TheSuperHackers\GeneralsGameCode>FOR /F "delims=" %b IN ('git merge-base --fork-point main') DO git diff %b  1>changes.patch

D:\Projects\TheSuperHackers\GeneralsGameCode>git diff 2339194dd13d99a1ea1b49de90e25fd82ae2c7e4  1>changes.patch

D:\Projects\TheSuperHackers\GeneralsGameCode>git apply -p2 --directory=Generals --reject --whitespace=fix changes.patch
Checking patch Generals/GameEngine/Include/Common/OptionPreferences.h...
error: Generals/GameEngine/Include/Common/OptionPreferences.h: No such file or directory
Checking patch Generals/GameEngine/Source/Common/OptionPreferences.cpp...
error: Generals/GameEngine/Source/Common/OptionPreferences.cpp: No such file or directory
Checking patch Generals/Code/GameEngine/Include/Common/GlobalData.h...
Hunk #1 succeeded at 139 (offset -1 lines).
Checking patch Generals/Code/GameEngine/Source/Common/GlobalData.cpp...
error: while searching for:
        //-allAdvice feature
        //m_allAdvice = FALSE;

        m_clientRetaliationModeEnabled = TRUE; //On by default.

}


error: patch failed: Generals/Code/GameEngine/Source/Common/GlobalData.cpp:1053
Hunk #2 succeeded at 1187 (offset -15 lines).
Checking patch Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp...
error: while searching for:
        TheWritableGlobalData->m_useAlternateMouse = GadgetCheckBoxIsChecked(checkAlternateMouse);
        (*pref)["UseAlternateMouse"] = TheWritableGlobalData->m_useAlternateMouse ? "yes" : "no";

        TheWritableGlobalData->m_clientRetaliationModeEnabled = GadgetCheckBoxIsChecked(checkRetaliation);
        (*pref)["Retaliation"] = TheWritableGlobalData->m_clientRetaliationModeEnabled? "yes" : "no";


error: patch failed: Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp:598
Checking patch Generals/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp...
Applied patch Generals/Code/GameEngine/Include/Common/GlobalData.h cleanly.
Applying patch Generals/Code/GameEngine/Source/Common/GlobalData.cpp with 1 reject...
Rejected hunk #1.
Hunk #2 applied cleanly.
Applying patch Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp with 1 reject...
Rejected hunk #1.
Applied patch Generals/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp cleanly.

@xezon xezon changed the title feat(option): Add user option to enable or disable Right Mouse Scroll with Alternate Mouse feat(options): Implement user option to enable or disable Right Mouse Scroll with Alternate Mouse Jun 16, 2026
@xezon xezon changed the title feat(options): Implement user option to enable or disable Right Mouse Scroll with Alternate Mouse feat(options): Implement user option to toggle Right Mouse Scroll with Alternate Mouse Jun 16, 2026
@xezon xezon merged commit 59d4c29 into TheSuperHackers:main Jun 16, 2026
17 checks passed
@xezon xezon deleted the xezon/add-rmb-scroll-alternate-mouse-option branch June 16, 2026 20:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Enhancement Is new feature or request Gen Relates to Generals Input Minor Severity: Minor < Major < Critical < Blocker ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants