如何在 Linux 下跟踪 python 中的光标图像
How to track cursor images in python under Linux
我想做的是跟踪屏幕上显示的光标图像,特别是当它因我移入和移出活动区域而发生变化时。跟踪光标位置的模块很多,但是光标图像的信息比较少
我发现一个 post 提到 windows 使用 win32gui:
但是是否还有一种方法可以使用 Xlib 在 linux 下获取它?我进一步发现 XFixes 显然有一个名为 XFixesGetCursorImage 的方法并且它没有直接暴露给 python,但它也是几年老的。有谁知道这是否已经改变或我如何使用 python 中的 C 库来使用该功能(到目前为止没有关于如何做到这一点的经验)?
我能为您提供的最好的是下面的代码,来自我的一个项目 Xwintrack
。
Xlib
下的 Fixes
模块仅提供 show_cursor
和 hide_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()
如果您确实想出了解决方案,请务必在此处 post。
已经有一段时间了,但是对于那些感兴趣的人,我最近遇到了类似问题中提到的这个存储库:
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 属性 这是描述光标的字符串。
我想做的是跟踪屏幕上显示的光标图像,特别是当它因我移入和移出活动区域而发生变化时。跟踪光标位置的模块很多,但是光标图像的信息比较少
我发现一个 post 提到 windows 使用 win32gui:
但是是否还有一种方法可以使用 Xlib 在 linux 下获取它?我进一步发现 XFixes 显然有一个名为 XFixesGetCursorImage 的方法并且它没有直接暴露给 python,但它也是几年老的。有谁知道这是否已经改变或我如何使用 python 中的 C 库来使用该功能(到目前为止没有关于如何做到这一点的经验)?
我能为您提供的最好的是下面的代码,来自我的一个项目 Xwintrack
。
Xlib
下的 Fixes
模块仅提供 show_cursor
和 hide_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()
如果您确实想出了解决方案,请务必在此处 post。
已经有一段时间了,但是对于那些感兴趣的人,我最近遇到了类似问题中提到的这个存储库:
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 属性 这是描述光标的字符串。