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完成后即回发。

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