From 1e7e81ac3dadab1bf0d3526207fe1cc8a1b6333c Mon Sep 17 00:00:00 2001 From: Kamil Jarosz Date: Sat, 14 Sep 2024 13:13:29 +0200 Subject: [PATCH] desktop: Add GameModeSession for managing gamemode --- desktop/src/dbus.rs | 56 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/desktop/src/dbus.rs b/desktop/src/dbus.rs index 7280d3be3778..34267378ee7a 100644 --- a/desktop/src/dbus.rs +++ b/desktop/src/dbus.rs @@ -1,6 +1,9 @@ #![cfg(target_os = "linux")] //! Types and methods utilized for communicating with D-Bus +use std::mem; +use std::sync::{Arc, Mutex}; + use futures::StreamExt; use zbus::export::futures_core::Stream; use zbus::zvariant::{OwnedValue, Value}; @@ -80,3 +83,56 @@ impl<'p> FreedesktopSettings<'p> { } } } + +pub struct GameModeSession { + _guard: Arc>>, +} + +impl GameModeSession { + pub fn new(enabled: bool) -> Self { + let guard = Arc::new(Mutex::new(None)); + let guard2 = guard.clone(); + tokio::spawn(async move { + let game_mode_guard = GameModeGuard::new(enabled).await; + *guard2.lock().expect("Non-poisoned gamemode guard") = Some(game_mode_guard); + }); + Self { _guard: guard } + } +} + +struct GameModeGuard { + gamemode: Option>, +} + +impl GameModeGuard { + async fn new(enabled: bool) -> Self { + if !enabled { + return Self { gamemode: None }; + } + + let gamemode = ashpd::desktop::game_mode::GameMode::new() + .await + .inspect_err(|err| tracing::warn!("Failed to initialize gamemode controller: {}", err)) + .ok(); + + if let Some(gamemode) = &gamemode { + if let Err(err) = gamemode.register(std::process::id()).await { + tracing::warn!("Failed to register a game with gamemode: {}", err) + } + } + + Self { gamemode } + } +} + +impl Drop for GameModeGuard { + fn drop(&mut self) { + if let Some(gamemode) = mem::take(&mut self.gamemode) { + tokio::spawn(async move { + if let Err(err) = gamemode.unregister(std::process::id()).await { + tracing::warn!("Failed to unregister a game with gamemode: {}", err) + } + }); + } + } +}