spice客戶機到主機的拖拽特性開發(linux)

前言
衆所周知,spice的拖拽特性只支持從主機到客戶機,不支持從客戶機到主機,即便是最新版本也無該功能支持。我針對公司的桌面雲開發了該功能,注意我的大部分涉及產品的博客都只講原理不放代碼,望理解。

客戶機 – 虛擬機。
主機 – 運行spice-gtk的終端設備。
spice-gtk: 運行在主機端。
spice-vdagent: 運行在客戶機端。

1)從主機到客戶機的拖拽原理:
主機到客戶機拖拽相對好實現,因爲spice-gtk直接利用gtk2.0/3.0的特性,獲取拖入widget文件的路徑,之後首先在client端通過socket將文件數據發送到qemu端,qemu通過libspice-server將數據發送到客戶機端,而客戶機通過/dev/virtio-ports/下的設備來和qemu通信。

2)從客戶機到主機的拖拽思路:
理解了從主機到客戶機的拖拽思路後,客戶機到主機的拖拽思路也與此類似,唯一的難點在於文件路徑的獲取。

3)如何獲取客戶機中希望拖拽到主機的文件路徑?
我的想法是在鼠標左鍵按下時,在spice-gtk端通過調用gdk_display_warp_pointer激活鼠標陷入,並在鼠標移動到spice widget邊緣時觸發信號禁止鼠標移動,此時spice-gtk發送VD_AGENT_FILE_XREAD_DND_WINDOW信號到spice-vdagent端,之後客戶機通過XCreateWindow在鼠標所在位置創建一個100x100的透明window,並通過XPending等待信號,當等待到第一個XdndEnter信號時,發送VD_AGENT_DND_WINDOW_REPLY到spice-gtk端,spice-gtk獲取到信號後開始發送釋放鼠標的信號,之後spice-vdagent端就能獲取到該文件路徑,並且摧毀window。

4)調用流程圖如下:
注:vdagentd是一個daemon,不含x11相關的對象,所以window的創建必須在vdagent中完成。

Created with Raphaël 2.1.2SPICE_GTKSPICE_GTKvdagentdvdagentdvdagentvdagentpress & edge mouse detectionVD_AGENT_FILE_XREAD_DND_WINDOWVDAGENT_FILE_XREAD_DND_WINDOWprepare drop target window okrecv XdndEnter signalVDAGENT_DND_WINDOW_REPLYVDAGENT_DND_WINDOW_REPLYrelease mouse(send event)recv dropfile pathVDAGENT_DND_PATH_REPLYVD_AGENT_DND_PATH_REPLYdrag file out-side spice-widgetdrop file in hostVDAGEND_FILE_XREAD_REQUESTVD_AGEND_FILE_XREAD_REQUESTcheck file exist...etc

基本時序圖如上,後面就是文件拷貝的細節不例舉了。

5)結論
可能會有不同的實現方式,不過這套流程實際測試和後續使用中還是驗證過了,其中重點在於vdagent一定要收到了xwindow的XdndEnter信號後纔回發VDAGENT_DND_PATH_REPLY,而非在prepare drop target window完成後即回發。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章