Discussion
TL; DR; There is no way to cross-DE to block screensaver with pure Python. However, the question also asked about this with Linux (presumably from the shell). To be clear, on Linux there are no particularly good ways to cross-DE, but at least there is potential. You probably want to use the hacker shell xdg-screensaver
script.
This is a topic that I spent some time on. I was not happy with any of the solutions there, so after playing with some homemade tools, I ended up changing the caffeine design to fit my needs and have been using it happily ever since. I will summarize some of what I learned in the process.
If you are not familiar with this, I would recommend checking out caffeine (Launchpad PPA @ https://launchpad.net/~caffeine-developers/+archive/ubuntu/ppa ).
The caffeine project mainly consists of the following scenarios: caffeine-screensaver
caffeine
caffeine-indicator
caffeinate
caffeine
and caffeine-indicator
are written in Python 3, while caffeine-screensaver
is a rebranding of xdg-screensaver
written in a shell script.
The first half of ccpizza's answer is great because it is cross-DE and is very similar to caffeine sales. I had no problems with the zombie xdg-screensaver processes, but I am sure that this could be fixed if I knew better the use case or the conditions under which it occurred. Just the FYI that runs xdg-screensaver suspend ROOT_WINDOW_ID
will close the tracking process and lower it indefinitely (until it resumes).
If you are interested in implementing a truly DE cross solution, I highly recommend exploring the above xdg-screensaver
/ caffeine-screensaver
. Many lightsOn forks have also matured.
xdg-screensaver
detects the desktop environment (KDE, Gnome, XFCE, LXDE, xscreensaver or gnome-screensaver) and acts accordingly. For the xdg-screensaver suspend
xset -dpms
, it runs xset -dpms
to disable DPMS, DE-specific commands, and then looks at the provided window identifier for its duration. If the window disappears, the resume command is launched and the xdg-screensaver splash screen is issued. The xdg-screensaver resume
command consists of xset +dpms
(only if DPMS was originally enabled), then DE related commands.
Note that xdg-screensaver will only track the specified window id if xprop is available (it is part of x11-utils, so it should be). To track the window, it displays xprop -id WINDOW_ID -spy
to control the change window. It stores the PID of the above process along with the window identifier in the lock file for reference to pause and resume. The initial state of the DPMS is referenced in a separate lock file. Blocking files must ensure that there are no duplicate processes.
The script is a complete mess, so I empathize with someone, unfortunately, to him, but I did not encounter any problems. You probably don't want to reinvent the wheel, so if you are creating something for public consumption, I would recommend that you simply co-opt it. If you are creating something for personal use, just go through it and use the commands specific to your DE.
ccpizza , suggesting to use subprocess.Popen('xwininfo -root | grep xwininfo | cut -d" " -f4', stdout=subprocess.PIPE, shell=True).stdout.read().strip()
to get the identifier of the root window desktop. Using the desktop root window id with xdg-screensaver suspend
will disable the desktop screen saver indefinitely. Using a specific window identifier will disable the desktop screen saver throughout the window.
Shell script
To determine the active window identifier , you can run the following:
xprop -root _NET_ACTIVE_WINDOW | awk -F '[ ,]' '{print $5}'
To determine the root window identifier, you can run the following:
xwininfo -root | awk '/^xwininfo: Window id: / {print $4}'
To determine the splash screen timeout , you can run the following:
xset q | awk '/^ timeout: / {print $2}'
NOTE: the result will be 0 if the screen saver is disabled.
To determine if DPMS is enabled or disabled , you can run the following:
xset q | awk '/^ DPMS is / {print tolower($3)}'
Python script
There are also clean Python options. The Xlib
module is great for this, as is ewmh
(which is a wrapper around Xlib).
To determine the active window identifier using ewmh :
active_id = hex(ewmh.EWMH().getActiveWindow().id)
To determine the root window id with ewmh :
root_id = hex(ewmh.EWMH().root.id)
To determine the active window identifier using Xlib :
from Xlib.display import Display from Xlib.X import AnyPropertyType active_id = hex(Display().screen().root.get_full_property(Display().get_atom('_NET_ACTIVE_WINDOW'), AnyPropertyType).value[0])
To determine the root window identifier with Xlib :
from Xlib.display import Display root_id = hex(Display().screen().root.id)
To determine the screen saver timeout using Xlib :
from Xlib.display import Display timeout = Display().get_screen_saver().timeout