2013-02-08 86 views
0

我正試圖編寫一個Xvfb-to-HTML5-canvas工具,它需要知道X11窗口何時更改,以便它可以向客戶端發送屏幕更新。把它想象成一個基於網絡的VNC或RDP,但是對於X11窗口,只是(爲什麼發送整個桌面?=)。如何檢測X11窗口的內容何時更改?

想法通過Xlib或xcb(xpyb)可以直接做到這一點,但在我的實驗中,我已經能夠做的最好的事情是檢測窗口的創建,銷燬或移動。這很好,除了我需要知道什麼時候窗口的內容也會改變(想象一下,向xterm發送一個擊鍵,並在窗口移動之前凍結它)。

如果有人知道如何判斷X11窗口內容何時發生變化,我很樂意聽到它!我願意提供創造性的解決方案。例如,我嘗試使用ffmpeg通過fifo傳輸x11grab,並定期檢查以確定是否有任何更改,但在CPU利用率方面效率極低(即使沒有任何事情發生,它也似乎減慢了整個系統的速度)。

我也嘗試在循環中抓取15fps的屏幕截圖,同時以最有效的方式檢查更改(例如,這個cStringIO緩衝區是否匹配最後一個?)。這也是CPU密集型的。

對於我來說,理想的解決方案是能夠監視套接字的文件描述符,並在X11窗口發生變化時調用處理程序。我願意爲檢測整個X11屏幕發生什麼變化而做出決定......這仍然比我得到的更好。

任何和所有這方面的幫助表示讚賞!

回答

3

首先,你實際上可以使用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作爲命令行參數啓動它,你會被告知,只要窗口內容被改變。

+0

我標記爲正確的答案,因爲損害擴展做我需要的。我最終將Python的XCB綁定(xpyb)與SHM擴展結合使用,以便以非常高效的方式獲取窗口部分的屏幕截圖,我希望儘快發佈我的工具! –

+0

雖然損傷似乎是最專業和直接的方式,但還有其他一些選擇。一個簡單的方法是使用vnc服務器(不需要打開查看器)並安裝vncsnapshot(vncsnapshot.sourceforge.net)來獲取屏幕截圖,然後使用您喜歡的軟/腳本lang進行比較。 – erm3nda