【问题标题】:How to track cursor images in python under LinuxLinux下如何在python中跟踪光标图像
【发布时间】:2020-10-26 14:57:46
【问题描述】:

我想做的是跟踪屏幕上显示的光标图像,特别是当它因为我移入和移出活动区域而发生变化时。有很多模块可以跟踪光标的位置,但是光标图像上的信息比较少。

我发现一篇文章提到了使用 win32gui 的 windows: The way to detect the current mouse cursor type from bash or python

但是还有一种方法可以在 linux 下使用 Xlib 来实现吗?我进一步发现 XFixes 显然有一个名为 XFixesGetCursorImage 的方法,并且它没有直接暴露给 python,但它也有好几年的历史了。有谁知道这是否发生了变化,或者我如何在 python 中使用 C 库来使用该函数(到目前为止还没有关于如何做到这一点的经验)?

【问题讨论】:

  • XFixesGetCursorImage 来自 XFixes 扩展,除了 libX11 之外,您还需要 libxfixes 才能使用此功能。不确定您是否已经实现了 puthon 绑定

标签: python linux cursor xlib


【解决方案1】:

我能给你的最好的就是下面的代码,来自我的一个项目XwintrackXlib 下的 Fixes 模块仅提供 show_cursorhide_cursor,这使我们只能更改现有属性。

这也意味着,由于您无法识别现有光标或它来自的主题,如果您更改光标,您将不得不求助于标准 X 光标或创建自己的光标,例如,来自使用 PIL 的图像。另外,当然,没有退路。您将无法恢复到之前的光标,您必须从 X 库中提供猜测。

如果你开始挖掘,研究光标和主题,你会发现它是一个多么曲折的雷区。它似乎是一个由不同部分组成的系统,只是松散地结合在一起,有蜘蛛网和唾液。

以下依赖:

from Xlib import X, display, Xcursorfont
LEFT_PTR = Xcursorfont.left_ptr
SELECT = Xcursorfont.dotbox

def xcursorselect():
    ''' Change the cursor to a green dotbox to indicate a selection is required
        Beware - there is no way back to the original themed cursor - see xcursornormal()
    '''
    disp = display.Display()
    root = disp.screen().root
    font = disp.open_font('cursor')
    cursor = font.create_glyph_cursor(font, SELECT, SELECT+1, (0, 65535, 0), (0, 0, 0)) #green with black edges
    root.change_attributes(cursor=cursor)
    disp.flush()

def xcursornormal():
    ''' Change the cursor back to White left_ptr to indicate selection finished
        Sadly under python there appears to be no way to identify the existing
        cursor image, so we're left with returning to a standard X cursor, rather
        than the Themed one
    '''
    disp = display.Display()
    root = disp.screen().root
    font = disp.open_font('cursor')
    cursor = font.create_glyph_cursor(font, LEFT_PTR, LEFT_PTR+1, (65535, 65535, 65355), (0, 0, 0)) #white with black edges
    root.change_attributes(cursor=cursor)
    disp.flush()

如果您确实提出了解决方案,请务必在此处发布。

【讨论】:

    【解决方案2】:

    已经有一段时间了,但是对于那些感兴趣的人,我最近遇到了一个类似问题中提到的这个存储库:

    https://github.com/zorvios/PyXCursor/blob/master/pyxcursor/pyxcursor.py

    它更侧重于复制光标的图片,但跟踪光标状态的相关部分是:

    import os
    import ctypes
    import ctypes.util
    
    PIXEL_DATA_PTR = ctypes.POINTER(ctypes.c_ulong)
    Atom = ctypes.c_ulong
    
    class XFixesCursorImage(ctypes.Structure):
        _fields_ = [('x', ctypes.c_short),
                    ('y', ctypes.c_short),
                    ('width', ctypes.c_ushort),
                    ('height', ctypes.c_ushort),
                    ('xhot', ctypes.c_ushort),
                    ('yhot', ctypes.c_ushort),
                    ('cursor_serial', ctypes.c_ulong),
                    ('pixels', PIXEL_DATA_PTR),
                    ('atom', Atom),
                    ('name', ctypes.c_char_p)]
    
    class Display(ctypes.Structure):
        pass
    
    class Xcursor:
        display = None
    
        def __init__(self, display=None):
            if not display:
                try:
                    display = os.environ["DISPLAY"].encode("utf-8")
                except KeyError:
                    raise Exception("$DISPLAY not set.")
    
            XFixes = ctypes.util.find_library("Xfixes")
            if not XFixes:
                raise Exception("No XFixes library found.")
            self.XFixeslib = ctypes.cdll.LoadLibrary(XFixes)
    
            x11 = ctypes.util.find_library("X11")
            if not x11:
                raise Exception("No X11 library found.")
            self.xlib = ctypes.cdll.LoadLibrary(x11)
    
            XFixesGetCursorImage = self.XFixeslib.XFixesGetCursorImage
            XFixesGetCursorImage.restype = ctypes.POINTER(XFixesCursorImage)
            XFixesGetCursorImage.argtypes = [ctypes.POINTER(Display)]
            self.XFixesGetCursorImage = XFixesGetCursorImage
    
            XOpenDisplay = self.xlib.XOpenDisplay
            XOpenDisplay.restype = ctypes.POINTER(Display)
            XOpenDisplay.argtypes = [ctypes.c_char_p]
    
            if not self.display:
                self.display = self.xlib.XOpenDisplay(display)  # (display) or (None)
    
        def getCursorImageData(self):
            cursor_data = self.XFixesGetCursorImage(self.display)
            return cursor_data[0]
    

    返回的 cursor_data[0] 包含 XFixesGetCursorImage 函数返回的信息。状态变化方面的相关信息是 cursor_serial,它提供了一些图像特定的 ID,或者是 name 属性,它是一个描述光标的字符串。 p>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多