Pause X screen blanking while an inhibit is active
Browsers don't pause X blanking themselves, so the screen still went black after 10 minutes even with xautolock disabled. Use XScreenSaverSuspend (MIT-SCREEN-SAVER) instead of xset: no global setting is changed, and the X server ends the pause on its own if the daemon exits or crashes. The suspend also holds off DPMS. Add libx11 and libxss to depends.
This commit is contained in:
+60
-9
@@ -1,7 +1,11 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Own org.freedesktop.ScreenSaver and turn inhibit requests into xautolock -disable/-enable."""
|
||||
"""Own org.freedesktop.ScreenSaver and turn inhibit requests into xautolock -disable/-enable.
|
||||
|
||||
While an inhibit is active, X screen blanking is also paused (like mpv does).
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import ctypes
|
||||
import itertools
|
||||
import signal
|
||||
import subprocess
|
||||
@@ -62,9 +66,49 @@ def xautolock(arg):
|
||||
log(f"xautolock {arg} failed: {e}")
|
||||
|
||||
|
||||
class XBlanking:
|
||||
"""Pause X screen blanking with XScreenSaverSuspend (MIT-SCREEN-SAVER extension).
|
||||
|
||||
Unlike `xset s off -dpms` this changes no global setting: the X server ends the
|
||||
pause by itself when this client releases it or its connection closes (exit, crash).
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.dpy = None
|
||||
try:
|
||||
self.x11 = ctypes.CDLL("libX11.so.6")
|
||||
self.xss = ctypes.CDLL("libXss.so.1")
|
||||
except OSError as e:
|
||||
log(f"Cannot load X11 libraries ({e}); X blanking will not be paused")
|
||||
return
|
||||
self.x11.XOpenDisplay.argtypes = [ctypes.c_char_p]
|
||||
self.x11.XOpenDisplay.restype = ctypes.c_void_p
|
||||
self.x11.XFlush.argtypes = [ctypes.c_void_p]
|
||||
self.xss.XScreenSaverQueryExtension.argtypes = [
|
||||
ctypes.c_void_p, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int)]
|
||||
self.xss.XScreenSaverSuspend.argtypes = [ctypes.c_void_p, ctypes.c_int]
|
||||
|
||||
dpy = self.x11.XOpenDisplay(None)
|
||||
if not dpy:
|
||||
log("Cannot open the X display; X blanking will not be paused")
|
||||
return
|
||||
event_base, error_base = ctypes.c_int(), ctypes.c_int()
|
||||
if not self.xss.XScreenSaverQueryExtension(dpy, ctypes.byref(event_base), ctypes.byref(error_base)):
|
||||
log("X server lacks the MIT-SCREEN-SAVER extension; X blanking will not be paused")
|
||||
return
|
||||
self.dpy = dpy
|
||||
|
||||
def suspend(self, on):
|
||||
if self.dpy:
|
||||
self.xss.XScreenSaverSuspend(self.dpy, int(on))
|
||||
self.x11.XFlush(self.dpy)
|
||||
log(f"X blanking {'paused' if on else 'resumed'}")
|
||||
|
||||
|
||||
class Inhibitor:
|
||||
def __init__(self, ignored_reasons, release_delay):
|
||||
def __init__(self, ignored_reasons, release_delay, blanking):
|
||||
self.ignored_reasons = ignored_reasons
|
||||
self.blanking = blanking
|
||||
self.release_delay = release_delay
|
||||
self.cookies = {} # cookie -> (sender, application_name, reason, counts)
|
||||
self.next_cookie = itertools.count(1)
|
||||
@@ -85,8 +129,7 @@ class Inhibitor:
|
||||
GLib.source_remove(self.release_timer)
|
||||
self.release_timer = 0
|
||||
if active and not self.disabled:
|
||||
xautolock("-disable")
|
||||
self.disabled = True
|
||||
self.block()
|
||||
elif not active and self.disabled and not self.release_timer:
|
||||
# Browsers send quick Inhibit/UnInhibit bursts when a video starts.
|
||||
self.release_timer = GLib.timeout_add_seconds(self.release_delay, self.on_release_timeout)
|
||||
@@ -94,17 +137,25 @@ class Inhibitor:
|
||||
def on_release_timeout(self):
|
||||
self.release_timer = 0
|
||||
if not self.active_count() and self.disabled:
|
||||
xautolock("-enable")
|
||||
self.disabled = False
|
||||
self.unblock()
|
||||
return GLib.SOURCE_REMOVE
|
||||
|
||||
def block(self):
|
||||
xautolock("-disable")
|
||||
self.blanking.suspend(True)
|
||||
self.disabled = True
|
||||
|
||||
def unblock(self):
|
||||
xautolock("-enable")
|
||||
self.blanking.suspend(False)
|
||||
self.disabled = False
|
||||
|
||||
def shutdown(self):
|
||||
if self.release_timer:
|
||||
GLib.source_remove(self.release_timer)
|
||||
self.release_timer = 0
|
||||
if self.disabled:
|
||||
xautolock("-enable")
|
||||
self.disabled = False
|
||||
self.unblock()
|
||||
|
||||
# --- D-Bus ------------------------------------------------------------
|
||||
|
||||
@@ -205,7 +256,7 @@ def main():
|
||||
ignored = set()
|
||||
else:
|
||||
ignored = set(args.ignore_reason or ["Playing audio"])
|
||||
inhibitor = Inhibitor(ignored, max(args.release_delay, 0))
|
||||
inhibitor = Inhibitor(ignored, max(args.release_delay, 0), XBlanking())
|
||||
loop = GLib.MainLoop()
|
||||
exit_code = 0
|
||||
acquired = False
|
||||
|
||||
Reference in New Issue
Block a user