#!/usr/bin/env python3 import os import sys import gi gi.require_version("Gio", "2.0") from gi.repository import Gio, GLib DISPLAY_BUS = "org.gnome.Mutter.DisplayConfig" DISPLAY_PATH = "/org/gnome/Mutter/DisplayConfig" IDLE_BUS = "org.gnome.Mutter.IdleMonitor" IDLE_PATH = "/org/gnome/Mutter/IdleMonitor/Core" POLL_MS = 2000 WAKE_MS = 1500 def name_has_owner(bus, name): try: res = bus.call_sync( "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "NameHasOwner", GLib.Variant("(s)", (name,)), None, Gio.DBusCallFlags.NONE, 2000, None, ) return bool(res.unpack()[0]) except GLib.Error: return False def main(): if "GNOME" not in os.environ.get("XDG_CURRENT_DESKTOP", ""): return 0 try: bus = Gio.bus_get_sync(Gio.BusType.SESSION, None) except GLib.Error: return 0 if name_has_owner(bus, "org.gnome.Shell.ScreenShield"): return 0 settings = Gio.Settings.new("org.gnome.desktop.session") state = {"off": False} def set_power(mode): bus.call_sync( DISPLAY_BUS, DISPLAY_PATH, "org.freedesktop.DBus.Properties", "Set", GLib.Variant( "(ssv)", (DISPLAY_BUS, "PowerSaveMode", GLib.Variant("i", mode)), ), None, Gio.DBusCallFlags.NONE, 2000, None, ) def get_idle_ms(): res = bus.call_sync( IDLE_BUS, IDLE_PATH, IDLE_BUS, "GetIdletime", None, None, Gio.DBusCallFlags.NONE, 2000, None, ) return int(res.unpack()[0]) def tick(): try: delay = settings.get_uint("idle-delay") idle = get_idle_ms() if delay > 0 and idle >= delay * 1000 and not state["off"]: set_power(3) state["off"] = True elif state["off"] and idle < WAKE_MS: set_power(0) state["off"] = False except GLib.Error: pass return True GLib.timeout_add(POLL_MS, tick) GLib.MainLoop().run() return 0 if __name__ == "__main__": sys.exit(main())