Comment déterminer le temps d'inactivité d'affichage à partir de Python sous Windows, Linux et MacOS?
Question
Je voudrais savoir combien de temps s'est écoulé depuis que l'utilisateur a appuyé sur une touche ou déplacé la souris - pas seulement dans mon application, mais dans l'ensemble "ordinateur". (i.e. display), afin de deviner s’ils sont toujours sur l’ordinateur et capables d’observer les notifications qui apparaissent à l’écran.
J'aimerais faire cela uniquement à partir de (Py) GTK +, mais je suis disposé à appeler des fonctions spécifiques à la plate-forme. Dans l’idéal, j’aimerais appeler des fonctions qui ont déjà été intégrées à Python, mais si cela n’est pas possible, je ne suis pas au-dessus d’un peu de code C ou ctypes
, à condition que je sache ce que je sais. cherche réellement.
Sous Windows, je pense que la fonction que je veux utiliser est GetLastInputInfo
, mais cela ne semble pas être enveloppé par pywin32; J'espère que je manque quelque chose.
La solution
Gajim le fait de cette façon sous Windows, OS X et GNU / Linux (et autres * nixes) :
- Python En savoir plus inclut le code de détection du temps d’inactivité de Windows, en utilisant
GetTickCount
avecctypes
); - défenderesse (en utilisant
XScreenSaverQueryInfo
, était un module C dans les anciennes versions de Gajim); - c heure (utilisation de la propriété système
HIDIdleTime
).
Ces liens sont datés de la version 0.12, vous pouvez donc vérifier la source actuelle pour d’autres améliorations et modifications éventuelles.
Autres conseils
Si vous utilisez PyGTK et X11 sous Linux, vous pouvez faire quelque chose comme ceci, basé sur ce que fait Pidgin:
import ctypes
import ctypes.util
import platform
class XScreenSaverInfo(ctypes.Structure):
_fields_ = [('window', ctypes.c_long),
('state', ctypes.c_int),
('kind', ctypes.c_int),
('til_or_since', ctypes.c_ulong),
('idle', ctypes.c_ulong),
('eventMask', ctypes.c_ulong)]
class IdleXScreenSaver(object):
def __init__(self):
self.xss = self._get_library('Xss')
self.gdk = self._get_library('gdk-x11-2.0')
self.gdk.gdk_display_get_default.restype = ctypes.c_void_p
# GDK_DISPLAY_XDISPLAY expands to gdk_x11_display_get_xdisplay
self.gdk.gdk_x11_display_get_xdisplay.restype = ctypes.c_void_p
self.gdk.gdk_x11_display_get_xdisplay.argtypes = [ctypes.c_void_p]
# GDK_ROOT_WINDOW expands to gdk_x11_get_default_root_xwindow
self.gdk.gdk_x11_get_default_root_xwindow.restype = ctypes.c_void_p
self.xss.XScreenSaverAllocInfo.restype = ctypes.POINTER(XScreenSaverInfo)
self.xss.XScreenSaverQueryExtension.restype = ctypes.c_int
self.xss.XScreenSaverQueryExtension.argtypes = [ctypes.c_void_p,
ctypes.POINTER(ctypes.c_int),
ctypes.POINTER(ctypes.c_int)]
self.xss.XScreenSaverQueryInfo.restype = ctypes.c_int
self.xss.XScreenSaverQueryInfo.argtypes = [ctypes.c_void_p,
ctypes.c_void_p,
ctypes.POINTER(XScreenSaverInfo)]
# gtk_init() must have been called for this to work
import gtk
gtk # pyflakes
# has_extension = XScreenSaverQueryExtension(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()),
# &event_base, &error_base);
event_base = ctypes.c_int()
error_base = ctypes.c_int()
gtk_display = self.gdk.gdk_display_get_default()
self.dpy = self.gdk.gdk_x11_display_get_xdisplay(gtk_display)
available = self.xss.XScreenSaverQueryExtension(self.dpy,
ctypes.byref(event_base),
ctypes.byref(error_base))
if available == 1:
self.xss_info = self.xss.XScreenSaverAllocInfo()
else:
self.xss_info = None
def _get_library(self, libname):
path = ctypes.util.find_library(libname)
if not path:
raise ImportError('Could not find library "%s"' % (libname, ))
lib = ctypes.cdll.LoadLibrary(path)
assert lib
return lib
def get_idle(self):
if not self.xss_info:
return 0
# XScreenSaverQueryInfo(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()),
# GDK_ROOT_WINDOW(), mit_info);
drawable = self.gdk.gdk_x11_get_default_root_xwindow()
self.xss.XScreenSaverQueryInfo(self.dpy, drawable, self.xss_info)
# return (mit_info->idle) / 1000;
return self.xss_info.contents.idle / 1000
L'exemple ci-dessus utilise gdk via ctypes pour pouvoir accéder au spécifique X11. Les API Xscreensaver doivent également être accessibles via ctypes.
Il devrait être assez facile de le porter pour utiliser PyGI et l’introspection.
J'ai obtenu une réponse concernant les clics de souris suggérant d'utiliser pyHook :
Détection de clics de souris dans des fenêtres à l'aide de python
Voici un autre code que j'ai créé pour détecter la position de la souris via des ctypes: http://monkut.webfactional.com/ blog / archive / 2008/10/2 / python-win-mouse-position
Une méthode plus souple pour ce faire consisterait à effectuer une capture d’écran et à comparer tout changement dans les images à l’aide de PIL.
http: / /www.wellho.net/forum/Programming-in-Python-and-Ruby/Python-Imaging-Library-PIL.html