【问题标题】:How do I detect when the contents of an X11 window have changed?如何检测 X11 窗口的内容何时发生变化?
【发布时间】:2013-02-12 08:10:24
【问题描述】:

我正在尝试编写一个 Xvfb-to-HTML5-canvas 工具,它需要知道 X11 窗口何时发生变化,以便向客户端发送屏幕更新。可以将其想象为基于 Web 的 VNC 或 RDP,但只是用于 X11 窗口(为什么要发送整个桌面?=)。

认为有一种直接的方法可以通过 Xlib 或 xcb (xpyb) 做到这一点,但在我的实验中,我能做的最好的事情是检测窗口何时被创建、销毁,或移动。这很好,但我还需要知道窗口的内容何时发生变化(想象一下向 xterm 发送击键并让它在您移动窗口之前显示为冻结状态)。

如果有人知道如何判断 X11 窗口的内容何时发生变化,我很想听听!我对创造性的解决方案持开放态度。例如,我尝试使用 ffmpeg 通过 fifo 流式传输 x11grab,并定期检查以查看是否有任何变化,但结果证明它在 CPU 利用率方面效率极低(即使没有发生任何事情,它似乎也会减慢整个系统的速度)。

我还尝试在循环中抓取 15fps 的屏幕截图,同时以最有效的方式检查更改(例如,此 cStringIO 缓冲区是否与最后一个缓冲区匹配?)。这也是 CPU 密集型的。

理想的解决方案是让我能够观察套接字的文件描述符并在 X11 窗口发生变化时调用处理程序。我愿意满足于检测整个 X11 屏幕何时发生变化......这仍然比我所拥有的要好。

对此的任何和所有帮助表示赞赏!

【问题讨论】:

    标签: python html x11


    【解决方案1】:

    首先,您实际上可以使用 vnc 来跟踪一个窗口中的更改,而不是整个桌面。来自x11vnc documentation

    -id windowid           Show the X window corresponding to "windowid" not
                           the entire display.  New windows like popup menus,
                           transient toplevels, etc, may not be seen or may be
                           clipped.  Disabling SaveUnders or BackingStore in the
                           X server may help show them.  x11vnc may crash if the
                           window is initially partially obscured, changes size,
                           is iconified, etc.  Some steps are taken to avoid this
                           and the -xrandr mechanism is used to track resizes.  Use
                           xwininfo(1) to get the window id, or use "-id pick"
                           to have x11vnc run xwininfo(1) for you and extract
                           the id.  The -id option is useful for exporting very
                           simple applications (e.g. the current view on a webcam).
    -sid windowid          As -id, but instead of using the window directly it
                           shifts a root view to it: this shows SaveUnders menus,
                           etc, although they will be clipped if they extend beyond
                           the window.
    
    
    -appshare              Simple application sharing based on the -id/-sid
                           mechanism.  Every new toplevel window that the
                           application creates induces a new viewer window via
                           a reverse connection.  The -id/-sid and -connect
                           options are required.  Run 'x11vnc -appshare -help'
                           for more info.
    

    如果你想手动编写类似的功能,你需要使用damage extension

    这是使用 node-x11 的 javascript 中的简单示例(抱歉,我不确定 python 中是否支持损坏扩展)

    var x11 = require('x11');
    
    var X = x11.createClient(function(err, display) {
        X.require('damage', function(Damage) {
            var damage = X.AllocID();
            Damage.Create(damage, parseInt(process.argv[2]), Damage.ReportLevel.NonEmpty);
            X.on('event', function(ev) {
              Damage.Subtract(damage, 0, 0);
              console.log("window content changed!");
            });
        });
    });
    

    以窗口 id 作为命令行参数启动它,每当窗口内容发生更改时,您都会收到通知。

    【讨论】:

    • 我将此答案标记为正确,因为损坏扩展程序可以满足我的需要。我最终将 Python 的 XCB 绑定 (xpyb) 与 SHM 扩展结合使用,以非常有效的方式抓取窗口部分的屏幕截图,我希望尽快发布我的工具!
    • 虽然损坏似乎是最专业和最直接的方式,但还有其他一些选择。一种简单的方法是使用 vnc 服务器(无需打开查看器)并安装 vncsnapshot (vncsnapshot.sourceforge.net) 以拍摄屏幕截图,然后在您喜欢的软/脚本语言上进行比较。
    猜你喜欢
    • 2019-07-19
    • 2016-12-28
    • 1970-01-01
    • 2022-07-20
    • 2011-03-17
    • 1970-01-01
    • 1970-01-01
    • 2018-08-29
    • 2016-11-04
    相关资源
    最近更新 更多