feat(gamescope): a three way switch for relative mouse motion

Games that confine the cursor and warp it back to read movement never
reach the nested hints rule, so their aim stays bounded by the screen.
The convar defaults to 0 and leaves that rule alone; 1 forces relative
motion for the focused game, 2 keeps the pointer absolute even when the
rule would apply.
This commit is contained in:
kingokksa committed 2026-10-31 23:50:24 +08:00
1 parent ac132a23e2
commit db3d7555e0
1 file changed
+30
@@ -0,0 +1,30 @@
--- a/src/steamcompmgr.cpp
+++ b/src/steamcompmgr.cpp
@@ -3062,8 +3062,13 @@
#endif
gamescope::ConVar<int> cv_cursor_composite{ "cursor_composite", 1, "0 = Never composite a cursor. 1 = Composite cursor when not nested. 2 = Always composite a cursor manually" };
+static gamescope::ConVar<int> cv_relative_mouse( "relative_mouse", 0,
+"0 = Leave it to the game and the nested hints. 1 = Send host pointer motion as relative movement, for games that confine the cursor and warp it back to read movement. 2 = Never go relative." );
bool ShouldDrawCursor()
{
+ if ( cv_relative_mouse.Get() == 1 )
+ return true;
+
global_focus_t *pFocus = GetCurrentFocus();
gamescope::INestedHints *pNestedHints = pFocus ? pFocus->GetNestedHints() : nullptr;
return gamescope::CursorShouldBeComposited( cv_cursor_composite.Get(), g_bForceRelativeMouse,
@@ -10810,7 +10815,12 @@
const bool bExcludedAppId = uAppId && gamescope::Algorithm::Contains( s_uRelativeMouseFilteredAppids, uAppId );
- const bool bRelativeMouseMode = bImageEmpty && bHasPointerConstraint && !bExcludedAppId;
+ const int nRelativeMouse = cv_relative_mouse.Get();
+ const bool bForcedRelativeMouse = nRelativeMouse == 1 && !window_is_steam( pPaintFocus->inputFocusWindow );
+
+ const bool bRelativeMouseMode = nRelativeMouse == 2
+ ? false
+ : ( bForcedRelativeMouse || ( bImageEmpty && bHasPointerConstraint && !bExcludedAppId ) );
pPaintFocus->GetNestedHints()->SetRelativeMouseMode( bRelativeMouseMode );
}