2

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

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

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

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

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

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

4

1 回答 1

4

First of all, you can actually use vnc to track changes in just one window, not whole desktop. From 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.

If you want to code similar functionality manually you need to use damage extension.

Here is simple example in javascript using node-x11 (sorry, I'm not sure about damage extension support in 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!");
        });
    });
});

start it with window id as command line argument and you'll be notified whenever window content is changed.

于 2013-02-12T00:10:24.220 回答