diff --git a/src/Backends/OpenVRBackend.cpp b/src/Backends/OpenVRBackend.cpp index 8c80edd981..519dea9a73 100644 --- a/src/Backends/OpenVRBackend.cpp +++ b/src/Backends/OpenVRBackend.cpp @@ -1713,7 +1713,7 @@ namespace gamescope UpdateEdid(); m_pBackend->HackUpdatePatchedEdid(); - if ( g_bForceRelativeMouse ) + if ( g_forceRelativeMouse == ForceRelativeMouseMode::FORCE_ON ) this->SetRelativeMouseMode( true ); if ( m_pBackend->m_oulCurrentSceneVirtualConnectorKey && diff --git a/src/Backends/SDLBackend.cpp b/src/Backends/SDLBackend.cpp index 87bde7e2f1..b76a1a5f21 100644 --- a/src/Backends/SDLBackend.cpp +++ b/src/Backends/SDLBackend.cpp @@ -34,6 +34,9 @@ extern bool steamMode; extern bool g_bFirstFrame; extern int g_nPreferredOutputWidth; extern int g_nPreferredOutputHeight; +extern ForceRelativeMouseMode g_forceRelativeMouse; +static ForceRelativeMouseMode g_preForceRelativeMouse; +static int isSaved = 0; namespace gamescope { @@ -625,7 +628,10 @@ namespace gamescope g_nOutputHeight = height; } - if ( g_bForceRelativeMouse ) + /** + * If --force-grab-cursor is given, g_forceRelativeMouse will be ForceRelativeMouseMode::FORCE_ON + */ + if ( g_forceRelativeMouse == ForceRelativeMouseMode::FORCE_ON ) { SDL_SetRelativeMouseMode( SDL_TRUE ); m_bApplicationGrabbed = true; @@ -758,6 +764,19 @@ namespace gamescope g_bFullscreen = !g_bFullscreen; SDL_SetWindowFullscreen( m_Connector.GetSDLWindow(), g_bFullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0 ); break; + case KEY_M: + if (!isSaved) { + g_preForceRelativeMouse = g_forceRelativeMouse; + isSaved = 1; + } + g_forceRelativeMouse = g_forceRelativeMouse == g_preForceRelativeMouse ? ForceRelativeMouseMode::FORCE_OFF : g_preForceRelativeMouse; + SDL_SetRelativeMouseMode( SDL_GetRelativeMouseMode() ? SDL_FALSE : SDL_TRUE ); + if (g_forceRelativeMouse != ForceRelativeMouseMode::FORCE_OFF) + isSaved = 0; + SDL_Event event_m; + event_m.type = GetUserEventIndex( GAMESCOPE_SDL_EVENT_TITLE ); + SDL_PushEvent( &event_m ); + break; case KEY_N: g_wantedUpscaleFilter = GamescopeUpscaleFilter::PIXEL; break; @@ -782,6 +801,15 @@ namespace gamescope gamescope::CScreenshotManager::Get().TakeScreenshot( true ); break; case KEY_G: + if (g_forceRelativeMouse != ForceRelativeMouseMode::FORCE_ON) + g_forceRelativeMouse = ForceRelativeMouseMode::FORCE_ON; + else if (isSaved) + g_forceRelativeMouse = g_preForceRelativeMouse; + else + g_forceRelativeMouse = ForceRelativeMouseMode::OFF; + if (!g_bGrabbed) + SDL_SetRelativeMouseMode( SDL_TRUE ); + g_bGrabbed = !g_bGrabbed; SDL_SetWindowKeyboardGrab( m_Connector.GetSDLWindow(), g_bGrabbed ? SDL_TRUE : SDL_FALSE ); @@ -892,6 +920,8 @@ namespace gamescope std::string szTitle = pAppTitle ? *pAppTitle : "gamescope"; if ( g_bGrabbed ) szTitle += " (grabbed)"; + if ( g_forceRelativeMouse == ForceRelativeMouseMode::FORCE_OFF) + szTitle += " (mouse-off)"; SDL_SetWindowTitle( m_Connector.GetSDLWindow(), szTitle.c_str() ); szTitle = "Title: " + szTitle; diff --git a/src/Backends/WaylandBackend.cpp b/src/Backends/WaylandBackend.cpp index ab6d30c397..0712899be9 100644 --- a/src/Backends/WaylandBackend.cpp +++ b/src/Backends/WaylandBackend.cpp @@ -1013,7 +1013,7 @@ namespace gamescope UpdateEdid(); m_pBackend->HackUpdatePatchedEdid(); - if ( g_bForceRelativeMouse ) + if ( g_forceRelativeMouse == ForceRelativeMouseMode::FORCE_ON ) this->SetRelativeMouseMode( true ); return true; diff --git a/src/main.cpp b/src/main.cpp index 1397028e7f..68ce11c090 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -84,6 +84,7 @@ const struct option *gamescope_options = (struct option[]){ { "grab", no_argument, nullptr, 'g' }, { "force-grab-cursor", no_argument, nullptr, 0 }, { "display-index", required_argument, nullptr, 0 }, + { "never-grab-cursor", no_argument, nullptr, 0 }, // embedded mode options { "disable-layers", no_argument, nullptr, 0 }, @@ -224,6 +225,7 @@ const char usage[] = " --force-grab-cursor always use relative mouse mode instead of flipping dependent on cursor visibility.\n" " --display-index forces gamescope to use a specific display in nested mode." "\n" + " --never-grab-cursor never use relative mouse mode instead of flipping dependent on cursor visibility.\n" "Embedded mode options:\n" " -O, --prefer-output list of connectors in order of preference (ex: DP-1,DP-2,DP-3,HDMI-A-1)\n" " --default-touch-mode 0: hover, 1: left, 2: right, 3: middle, 4: passthrough\n" @@ -284,6 +286,7 @@ const char usage[] = " Super + O decrease FSR sharpness by 1\n" " Super + S take a screenshot\n" " Super + G toggle keyboard grab\n" + " Super + M toggle never grab mouse\n" ""; std::atomic< bool > g_bRun{true}; @@ -300,7 +303,7 @@ int g_nOutputRefresh = 0; bool g_bOutputHDREnabled = false; bool g_bFullscreen = false; -bool g_bForceRelativeMouse = false; +ForceRelativeMouseMode g_forceRelativeMouse = ForceRelativeMouseMode::OFF; bool g_bGrabbed = false; @@ -807,7 +810,9 @@ int main(int argc, char **argv) } else if (strcmp(opt_name, "immediate-flips") == 0) { cv_tearing_enabled = true; } else if (strcmp(opt_name, "force-grab-cursor") == 0) { - g_bForceRelativeMouse = true; + g_forceRelativeMouse = ForceRelativeMouseMode::FORCE_ON; + } else if (strcmp(opt_name, "never-grab-cursor") == 0) { + g_forceRelativeMouse = ForceRelativeMouseMode::FORCE_OFF; } else if (strcmp(opt_name, "display-index") == 0) { g_nNestedDisplayIndex = parse_integer( optarg, opt_name ); } else if (strcmp(opt_name, "adaptive-sync") == 0) { diff --git a/src/main.hpp b/src/main.hpp index 2e6fb833af..26363b63bd 100644 --- a/src/main.hpp +++ b/src/main.hpp @@ -4,6 +4,13 @@ #include +enum class ForceRelativeMouseMode : uint32_t +{ + OFF, + FORCE_OFF, + FORCE_ON, +}; + extern const char *gamescope_optstring; extern const struct option *gamescope_options; @@ -17,7 +24,7 @@ extern int g_nNestedDisplayIndex; extern uint32_t g_nOutputWidth; extern uint32_t g_nOutputHeight; -extern bool g_bForceRelativeMouse; +extern ForceRelativeMouseMode g_forceRelativeMouse; extern int g_nOutputRefresh; // mHz extern bool g_bOutputHDREnabled; extern bool g_bForceInternal; diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 7ccf4a32da..3626a495e0 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -800,7 +800,7 @@ constexpr const T& clamp( const T& x, const T& min, const T& max ) return x < min ? min : max < x ? max : x; } -extern bool g_bForceRelativeMouse; +extern ForceRelativeMouseMode g_forceRelativeMouse; CommitDoneList_t g_steamcompmgr_xdg_done_commits; @@ -2427,7 +2427,10 @@ bool ShouldDrawCursor() if ( cv_cursor_composite == 0 ) return false; - if ( g_bForceRelativeMouse ) + /** + * Should composite cursor when RelativeMouse is not default value ForceRelativeMouseMode::OFF + */ + if ( g_forceRelativeMouse != ForceRelativeMouseMode::OFF ) return true; global_focus_t *pFocus = GetCurrentFocus(); @@ -8790,7 +8793,10 @@ steamcompmgr_main(int argc, char **argv) pPaintFocus->cursor->UpdatePosition(); } - if ( pPaintFocus->GetNestedHints() && !g_bForceRelativeMouse ) + /** + * Update after key input. This should be g_forceRelativeMouse != ForceRelativeMouseMode::FORCE_ON + */ + if ( pPaintFocus->GetNestedHints() && g_forceRelativeMouse != ForceRelativeMouseMode::FORCE_ON ) { const bool bImageEmpty = ( pPaintFocus->cursor && pPaintFocus->cursor->imageEmpty() ) &&