diff --git a/data/com.github.tkashkin.gamehub.gschema.xml.in b/data/com.github.tkashkin.gamehub.gschema.xml.in index 6b3b1256..64e9827d 100644 --- a/data/com.github.tkashkin.gamehub.gschema.xml.in +++ b/data/com.github.tkashkin.gamehub.gschema.xml.in @@ -132,6 +132,10 @@ true Import tags + + true + Inhibit screensaver while game is running + diff --git a/src/data/runnables/traits/HasExecutableFile.vala b/src/data/runnables/traits/HasExecutableFile.vala index 5f888d9d..aa9a6b56 100644 --- a/src/data/runnables/traits/HasExecutableFile.vala +++ b/src/data/runnables/traits/HasExecutableFile.vala @@ -119,6 +119,7 @@ namespace GameHub.Data.Runnables.Traits if(!can_be_launched(true)) return; Runnable.IsAnyRunnableRunning = is_running = true; + Inhibitor.inhibit(_("%s is running").printf(name)); update_status(); yield pre_run(); @@ -129,6 +130,7 @@ namespace GameHub.Data.Runnables.Traits Timeout.add_seconds(1, () => { Runnable.IsAnyRunnableRunning = is_running = false; + Inhibitor.uninhibit(); update_status(); return Source.REMOVE; }); diff --git a/src/meson.build b/src/meson.build index 52ecb790..4bb399bb 100644 --- a/src/meson.build +++ b/src/meson.build @@ -221,6 +221,7 @@ sources = [ 'utils/Parser.vala', 'utils/BinaryVDF.vala', 'utils/SignalRateLimiter.vala', + 'utils/Inhibitor.vala', 'settings/Settings.vala', 'settings/UI.vala', diff --git a/src/settings/UI.vala b/src/settings/UI.vala index 9bdb56e1..2ffbde41 100644 --- a/src/settings/UI.vala +++ b/src/settings/UI.vala @@ -202,6 +202,7 @@ namespace GameHub.Settings.UI public bool grid_doubleclick { get; set; } public bool merge_games { get; set; } public bool import_tags { get; set; } + public bool inhibit_screensaver { get; set; } public Behavior() { diff --git a/src/ui/dialogs/SettingsDialog/pages/ui/Behavior.vala b/src/ui/dialogs/SettingsDialog/pages/ui/Behavior.vala index ddc6001e..25faa0b8 100644 --- a/src/ui/dialogs/SettingsDialog/pages/ui/Behavior.vala +++ b/src/ui/dialogs/SettingsDialog/pages/ui/Behavior.vala @@ -47,6 +47,10 @@ namespace GameHub.UI.Dialogs.SettingsDialog.Pages.UI var sgrp_tags = new SettingsGroup(_("Tags")); sgrp_tags.add_setting(new SwitchSetting.bind(_("Import tags from sources"), null, settings, "import-tags")); add_widget(sgrp_tags); + + var sgrp_system = new SettingsGroup(_("System")); + sgrp_system.add_setting(new SwitchSetting.bind(_("Inhibit screensaver while game is running"), _("Request session manager to prevent suspending while game is running"), settings, "inhibit-screensaver")); + add_widget(sgrp_system); } } } diff --git a/src/utils/Inhibitor.vala b/src/utils/Inhibitor.vala new file mode 100644 index 00000000..71b97e00 --- /dev/null +++ b/src/utils/Inhibitor.vala @@ -0,0 +1,100 @@ +/* +This file is part of GameHub. +Copyright (C) 2018-2019 Anatoliy Kashkin + +GameHub is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +GameHub is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GameHub. If not, see . +*/ + +using Gtk; + +namespace GameHub.Utils +{ + public class Inhibitor + { + private static DBusFreeDesktopScreenSaver? fd_screensaver = null; + + private static uint32? fd_screensaver_inhibit_id = null; + private static uint? gtk_inhibit_id = null; + + private static void dbus_connect() + { + if(fd_screensaver != null) return; + try + { + fd_screensaver = Bus.get_proxy_sync(BusType.SESSION, "org.freedesktop.ScreenSaver", "/ScreenSaver", DBusProxyFlags.NONE); + } + catch(Error e) + { + warning("[ScreenSaver.dbus_connect] Failed to connect to DBus: %s", e.message); + } + } + + public static void inhibit(string? reason = null) + { + if(!GameHub.Settings.UI.Behavior.instance.inhibit_screensaver) return; + reason = reason ?? _("Game is running"); + if(fd_screensaver_inhibit_id == null) + { + dbus_connect(); + if(fd_screensaver != null) + { + try + { + fd_screensaver_inhibit_id = fd_screensaver.inhibit("GameHub", reason); + } + catch(Error e) + { + warning("[ScreenSaver.inhibit] Failed to inhibit screensaver via DBus: %s", e.message); + } + } + } + if(gtk_inhibit_id == null) + { + gtk_inhibit_id = GameHub.Application.instance.inhibit(GameHub.Application.instance.active_window, ApplicationInhibitFlags.IDLE | ApplicationInhibitFlags.SUSPEND, reason); + } + } + + public static void uninhibit() + { + if(fd_screensaver_inhibit_id != null) + { + dbus_connect(); + if(fd_screensaver != null) + { + try + { + fd_screensaver.un_inhibit(fd_screensaver_inhibit_id); + fd_screensaver_inhibit_id = null; + } + catch(Error e) + { + warning("[ScreenSaver.uninhibit] Failed to uninhibit screensaver via DBus: %s", e.message); + } + } + } + if(gtk_inhibit_id != null) + { + GameHub.Application.instance.uninhibit(gtk_inhibit_id); + gtk_inhibit_id = null; + } + } + + [DBus(name = "org.freedesktop.ScreenSaver")] + private interface DBusFreeDesktopScreenSaver: Object + { + public abstract uint32 inhibit(string app_name, string reason) throws Error; + public abstract void un_inhibit(uint32 cookie) throws Error; + } + } +}