Как я могу определить время простоя дисплея из Python в Windows, Linux и MacOS?

Я хотел бы знать, сколько времени прошло с тех пор, как пользователь последний раз нажал клавишу или переместил мышь - не только в моем приложении, но и на всем «компьютере» (то есть на дисплее), чтобы угадать, находятся ли они все еще в компьютер и может наблюдать за всплывающими на экране уведомлениями.

Я хотел бы сделать это исключительно из (Py) GTK +, но я могу вызывать функции, специфичные для платформы. В идеале я хотел бы вызывать функции, которые уже были обернуты из Python, но если это невозможно, я не выше немного кода C или ctypes, если я знаю, что на самом деле ищу.

В Windows я думаю, что мне нужна функция GetLastInputInfo, но это не так. t кажется обернутым pywin32; Надеюсь, я что-то упускаю.


person Glyph    schedule 19.10.2008    source источник


Ответы (3)



Если вы используете PyGTK и X11 в Linux, вы можете сделать что-то вроде этого, в зависимости от того, что делает 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

В приведенном выше примере используется gdk через ctypes для доступа к специфическим для X11. API-интерфейсы Xscreensaver также должны быть доступны через ctypes.

Его должно быть довольно легко перенести для использования PyGI и самоанализа.

person Johan Dahlin    schedule 27.05.2013
comment
Было бы интересно вместо этого перенести эти ctypes интерфейсы на pypi.python.org/pypi/cffi . - person Glyph; 28.05.2013
comment
да, наверное, хорошая идея. Этот комментарий был основан на моей собственной программе, и я не хотел добавлять туда зависимость cffi. Надеюсь, cffi когда-нибудь войдет в CPython. - person Johan Dahlin; 29.05.2013
comment
Я очень на это надеюсь. Откровенно говоря, они должны выпустить отладочную версию 2.7, которая включает его. - person Glyph; 30.05.2013
comment
Для работы код должен быть запущен в python2. Для тестирования попробуйте: time.sleep(2.1); print IdleXScreenSaver().get_idle() - person SurpriseDog; 14.03.2021

Я получил ответ относительно щелчков мышью, предлагающих использовать pyHook:

Обнаружение щелчков мыши в Windows с помощью Python

Вот еще один код, который я сделал для определения положения мыши с помощью 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

person monkut    schedule 20.10.2008