2008-10-19 98 views
15

我想知道從用戶上次敲一個鍵或移動鼠標開始,不僅僅是在我的應用程序中,而是在整個「計算機」(即顯示器)上,以便猜測它們是否仍然存在在電腦上並能夠觀察屏幕上彈出的通知。如何在Windows,Linux和MacOS中確定Python的顯示空閒時間?

我想純粹從(Py)GTK +這樣做,但我可以調用平臺特定的功能。理想情況下,我想調用已經被Python封裝的函數,但如果這不可能,我不會超過C或​​的代碼,只要我知道我實際上在尋找什麼。

在Windows上,我認爲我想要的函數是GetLastInputInfo,但似乎沒有被pywin32包裝;我希望我錯過了一些東西。

回答

11

Gajim做它在Windows,OS X和GNU/Linux(和其他* nixes)這樣說:

  1. Python wrapper module(也包含了Windows空閒時間檢測代碼,使用GetTickCount與​​);
  2. Ctypes-based module to get X11 idle time(使用XScreenSaverQueryInfo,是舊版Gajim版本中的C模塊);
  3. C module to get OS X idle time(使用HIDIdleTime系統屬性)。

這些鏈接是相當過時的0.12版本,所以你可能想檢查當前的來源,可能的進一步改進和改變。

5

如果您使用的PyGTK和X11在Linux上,你可以做這樣的事情,這是基於什麼洋涇浜的作用:

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 

上面的例子使用通過ctypes的GDK能夠訪問X11專用。 Xscreensaver API也需要通過ctypes來訪問。

它應該很容易移植到使用PyGI和內省。

+0

將這些`ctypes`接口替換爲https://pypi.python.org/pypi/cffi可能會很有趣。 – Glyph 2013-05-28 04:38:53