The following code was scrounged up on the Internet years ago and works quite well in python2. It supplies the current idle time on the X server.
import ctypes, os, subprocess
class XScreenSaverInfo( ctypes.Structure ):
_fields_ = [("window", ctypes.c_ulong), ("state", ctypes.c_int), ("kind", ctypes.c_int), ("since", ctypes.c_ulong), ("idle", ctypes.c_ulong), ("event_mask", ctypes.c_ulong)]
xlib = ctypes.cdll.LoadLibrary("libX11.so.6")
xss = ctypes.cdll.LoadLibrary("libXss.so.1")
display = xlib.XOpenDisplay(os.environ["DISPLAY"])
xss.XScreenSaverAllocInfo.restype = ctypes.POINTER(XScreenSaverInfo)
xssinfo = xss.XScreenSaverAllocInfo()
xss.XScreenSaverQueryInfo(display, xlib.XDefaultRootWindow(display), xssinfo)
xssinfo.contents.idle
I can throw this into a python2.7.10 shell and get what I want. However, doing the same on a python3.4.3 shell kicks me out with a segmentation fault in this line
xss.XScreenSaverQueryInfo(display, xlib.XDefaultRootWindow(display), xssinfo)
Is my py3 environment broken? Does py3 do something differently?
There was no significant change in Python 3's ctypes
module. However in Python3 os.environ
values are unicode strings, contrary to the byte strings of python2 and this causes the segmentation fault. So changing:
display = xlib.XOpenDisplay(os.environ["DISPLAY"])
To:
display = xlib.XOpenDisplay(bytes(os.environ["DISPLAY"], 'ascii'))
Fixes the segmentation fault.
If you want to have code that works both in python 2 and 3 you want to use the encode
method:
display = xlib.XOpenDisplay(os.environ["DISPLAY"].encode('ascii'))