Come posso determinare il tempo di inattività del display da Python in Windows, Linux e MacOS?

StackOverflow https://stackoverflow.com/questions/217157

Domanda

Vorrei sapere quanto tempo è trascorso dall'ultima volta che l'utente ha premuto un tasto o spostato il mouse, non solo nella mia applicazione, ma nel complesso "computer". (ad esempio display), per indovinare se sono ancora al computer e in grado di osservare le notifiche che compaiono sullo schermo.

Mi piacerebbe farlo esclusivamente da (Py) GTK +, ma sono in grado di chiamare funzioni specifiche della piattaforma. Idealmente mi piacerebbe chiamare funzioni che sono già state racchiuse da Python, ma se ciò non fosse possibile, non sono sopra un po 'di codice C o ctypes , purché sappia cosa sto davvero cercando.

Su Windows penso che la funzione che desidero sia GetLastInputInfo , ma questo non sembra essere avvolto da pywin32; Spero che mi manchi qualcosa.

È stato utile?

Soluzione

Gajim lo fa in questo modo su Windows, OS X e GNU / Linux (e altri * nix) :

  1. Python wrapper include il codice di rilevamento del tempo di inattività di Windows, utilizzando GetTickCount con ctypes );
  2. Modulo Ctypes id (usando XScreenSaverQueryInfo , era un modulo C nelle vecchie versioni di Gajim);
  3. modulo C per ottenere l'ID X time (utilizzando la proprietà di sistema HIDIdleTime )

Questi collegamenti sono alla versione 0.12 piuttosto datata, quindi potresti voler controllare la fonte corrente per possibili ulteriori miglioramenti e modifiche.

Altri suggerimenti

Se usi PyGTK e X11 su Linux, puoi fare qualcosa del genere, basato su ciò che fa 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'esempio sopra usa gdk via ctypes per poter accedere allo specifico X11. È inoltre necessario accedere alle API di Xscreensaver tramite i tipi.

Dovrebbe essere abbastanza facile portarlo per usare PyGI e introspezione.

Ho ricevuto una risposta relativa ai clic del mouse che suggeriscono di utilizzare pyHook :

Rilevamento dei clic del mouse in Windows usando Python

Ecco qualche altro codice che ho fatto per rilevare la posizione del mouse tramite i tipi: http://monkut.webfactional.com/ blog / archive / 2008/10/2 / python-win-topo-position

Un metodo più completo per raggiungere questo obiettivo sarebbe tramite l'acquisizione dello schermo e il confronto di qualsiasi cambiamento nelle immagini utilizzando PIL.

http: / /www.wellho.net/forum/Programming-in-Python-and-Ruby/Python-Imaging-Library-PIL.html

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top