18

我想知道自从用户最后一次按键或移动鼠标以来已经过了多长时间 - 不仅在我的应用程序中,而且在整个“计算机”(即显示器)上,以便猜测他们是否仍然在计算机并能够观察屏幕上弹出的通知。

我想纯粹从 (Py)GTK+ 来做这件事,但我愿意调用特定于平台的函数。理想情况下,我想调用已经从 Python 包装的函数,但如果这不可能,我不会超过一点 C 或ctypes代码,只要我知道我真正在寻找什么。

在 Windows 上,我认为我想要的功能是GetLastInputInfo,但这似乎没有被 pywin32 包装;我希望我错过了什么。

4

3 回答 3

12

Gajim在 Windows、OS X 和 GNU/Linux(以及其他 *nixes)上这样做:

  1. Python 包装器模块(还包括 Windows 空闲时间检测代码,使用GetTickCountwith ctypes);
  2. 基于 Ctypes 的模块来获取 X11 空闲时间(使用XScreenSaverQueryInfo, 是旧 Gajim 版本中的 C 模块);
  3. C 模块获取 OS X 空闲时间(使用HIDIdleTime系统属性)。

这些链接指向相当过时的 0.12 版本,因此您可能需要检查当前来源以了解可能的进一步改进和更改。

于 2009-07-17T21:07:04.147 回答
7

如果你在 Linux 上使用 PyGTK 和 X11,你可以这样做,这是基于 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

上面的例子通过 ctypes 使用 gdk 来访问特定的 X11。Xscreensaver API 也需要通过 ctypes 访问。

移植它以使用 PyGI 和自省应该很容易。

于 2013-05-27T17:06:43.560 回答
2

我得到了关于建议使用pyHook的鼠标点击的答案:

使用python检测Windows中的鼠标点击

这是我通过 ctypes 检测鼠标位置的一些其他代码:http: //monkut.webfactional.com/blog/archive/2008/10/2/python-win-mouse-position

实现这一点的一种更迂回的方法是通过屏幕捕获并使用 PIL 比较图像中的任何变化。

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

于 2008-10-20T01:27:38.613 回答