我正在尝试创建一个将图形化地重复鼠标指针的应用程序,因此我最终可以为Ubuntu 18.04制作一个鼠标跟踪程序-看来,做到这一点的方法是通过X11 / Xlib-尽管这些我什至不知道的日子,就像我的机器也说wayland
:
$ loginctl | while IFS= read line; do echo "$line"; if [[ $line == *"tty"* ]]; then sessnum=$(echo "$line" | awk '{print $1;}'); echo sessnum: $sessnum\; $(loginctl show-session $sessnum -p Type); fi; done
SESSION UID USER SEAT TTY
c1 121 gdm seat0 tty1
sessnum: c1; Type=wayland
2 1000 administrator seat0 tty2
sessnum: 2; Type=x11
2 sessions listed.
无论如何,我设法将以下内容组合在一起:
....加上大量其他代码片段(大部分来自SO),这些都是我想要的(即使我没有真正完全理解其中的所有层和组合)。我将其发布为gist: xosd_track_cursor.c,因为它有700多行(但可以在需要的地方发布)。
这是应用程序的行为方式(另请参见完整分辨率imgur .mp4 video)
基本上,一开始就设置了“ OSD”最上面的窗口,它比桌面窗口小得多-这有助于我们查看周围的窗口边框装饰(最终,我将使该窗口的大小与桌面)。
开始时,此窗口位置处的桌面像素似乎已被复制为窗口背景。
一旦鼠标指针进入OSD窗口,就会画出一个圆圈,该圆圈成为OSD窗口的遮罩(再次可以通过窗口边框装饰看到)-该圆形窗口跟随鼠标。然后,在其中绘制一个XFillRectangle来绘制一个石灰矩形,然后绘制XPutImage来绘制从最新鼠标指针捕获的像素(视频不显示它,但是复制的光标在正常显示时也发生了变化,例如从left_ptr
到bottom_side
或xterm
光标位图)。
到目前为止还不错-但这是问题和疑问:
XGetImage
捕获桌面,也许是(?)-然后显示该窗口;但是show总是发送Expose事件,否则将运行{ {1}}函数可以进行重绘,因此我得到了一堆递归调用,从而拖延了应用程序的运行时间还有一个奖励问题(这里只是很好奇-显然我宁愿不要剩菜剩饭):
答案 0 :(得分:0)
好吧,我想我到达了某个地方-结果出在同一要点上,只是版本不同:gist: xosd_track_cursor.c (a31e9dff5);看起来像这样:
因此,回答我的问题:
每次呈现新状态时,如何擦除这些先前的图纸?
不能-与以前代码的设置方式不同。它被设置为override_redirect
,这意味着它将不受任何窗口管理器的管理。此外,默认位深度为24,这意味着不支持透明性,这意味着要“隐藏”桌面(用作“清晰”背景),我们必须先隐藏然后显示窗口,由于对公开事件的反应而导致递归。
但是,我在How to make an OpenGL rendering context with transparent background?中看到使用glXCreateContext
可能会有所帮助-确实如此。但是,事实证明,没有必要-一旦XMatchVisualInfo
成功为OSD窗口返回了32位深度的匹配项(支持alpha透明性),便可以定义“完全透明”的颜色,通过XSetForeground
设置为0x00000000(据我所知,它是0xAARRGGBB格式)-并使用它直接在XFillRectangle
->窗口上绘制,从而可以透明地清除整个OSD窗口。
鼠标指针副本呈现黑色背景-如何使鼠标指针副本的图形透明(现在为黑色)?
结果证明,使用XCreateWindow
使用XMatchVisualInfo
中的设置为32位深度的窗口创建窗口后,此操作也开始起作用。就是说,我的意思是XPutImage
的结果是如此,以至于光标图像中的透明点现在是“透明的” /透明的-而以前的XPutImage
的结果显示为黑色像素这些位置。
但是,当OSD窗口完全显示时,剩余的部分似乎使绿色像素被绘制在鼠标光标复制像素的顶部。为什么会这样呢?
显然,我不正确地记得绘制像素的顺序。进行演示捕获时,确实首先复制了鼠标光标像素,然后在顶部复制了绿色像素。 (这现在改变了问题-鼠标光标为什么在该捕获中是可见的?!但是现在解决了整个问题,我并不那么好奇:))
否则,关于gist: xosd_track_cursor.c (a31e9dff5)的更多注意事项:由于X11具有客户端/服务器体系结构,这意味着用户程序只能将请求排队到服务器,因此所有绘图调用都是异步的/非阻塞的-因此,当我们运行XFillRectangle
并退出时,不是并不意味着像素绘制已完成-只是请求已发送到队列,最终被发送到服务器。此外,尽管使用了XFlush
,XSync
之类的命令,也无法保证我们可以等待完成的绘制操作。并且也不保证服务器将满足任何给定的请求。
但是,您尝试做的越少,X Server兑现请求的可能性就越大。因此,此版本的代码实际上创建了一个较小的窗口(60x60像素),然后对其进行设置,使其被鼠标指针的运动拖动(中心对齐)。然后,只需将(主)鼠标指针复制到此窗口中的相同相对位置即可。
最后,有一种原始的尝试来进行鼠标跟踪,方法是渲染鼠标指针的两个“幽灵”副本,并让它们被鼠标运动增量矢量的历史记录所取代-效果在鼠标上可见gif并不是真的很棒,但是至少它可以作为一种“概念证明”存在。另外,该窗口在开始时使用XShapeCombineRectangles
设置为“点击”-表示OSD窗口不直接拾取/处理任何鼠标事件(单击),而是将所有内容自动传递给窗口在它下面,因此交互保持不变,就好像该程序根本没有运行。
(请注意,要获得gif中显示的gist: xosd_track_cursor.c (a31e9dff5)的行为,您应该查找定义DEBUGPRINT
和MOUSE_TRAIL
,并在构建时取消注释)