千家信息网

如何进行spice agent 剪贴板共享机制的分析

发表于:2025-12-03 作者:千家信息网编辑
千家信息网最后更新 2025年12月03日,本篇文章给大家分享的是有关如何进行spice agent 剪贴板共享机制的分析,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。spice
千家信息网最后更新 2025年12月03日如何进行spice agent 剪贴板共享机制的分析

本篇文章给大家分享的是有关如何进行spice agent 剪贴板共享机制的分析,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

spice 协议定义了一组用于spice客户端和spice agent之间通信的双向通信通道。spice只提供了一个通信通道,具体的传输数据内容对协议而言是不透明的。此通道可用于各种用途,如客户端和客户机之间剪贴板共享,分辨率设置等。

spice 中的剪贴板数据共享的数据传输流程是一样的,以win32-vd_agent源码为例:当一方比如客户端进行复制的操作时,就会向spice agent发送GRAB数据,spice agent收到客户端的GRAB数据时,就会调用该函数:

bool VDAgent::handle_clipboard_grab(VDAgentClipboardGrab* clipboard_grab, uint32_t size){    std::set grab_formats;    _grab_types.clear();    for (uint32_t i = 0; i < size / sizeof(clipboard_grab->types[0]); i++) {        vd_printf("grab type %u", clipboard_grab->types[i]);        uint32_t format = get_clipboard_format(clipboard_grab->types[i]);        //On first supported type, open and empty the clipboard        if (format && grab_formats.empty()) {            if (!OpenClipboard(_hwnd)) {                return false;            }            EmptyClipboard();        }        //For all supported type set delayed rendering        if (format) {            _grab_types.insert(clipboard_grab->types[i]);            if (grab_formats.insert(format).second) {                SetClipboardData(format, NULL);            }        }    }    if (grab_formats.empty()) {        vd_printf("No supported clipboard types in client grab");        return true;    }    CloseClipboard();    set_clipboard_owner(owner_client);    return true;}

该函数将guest的剪贴板清空,并通过set_clipboard_owner(owner_client);设置剪贴板的拥有者为client。

当客户机(guest)端进行粘贴操作时,spice agent就会调用on_clipboard_request(UINT format)函数向客户端发送REQUEST数据。

client端收到REQUEST数据时,就会向客户机上的agent发送CLIPBOARD数据,即把剪贴板数据封装进VDAgentClipboard中。spice agent收到数据后调用handle_clipboard()函数将数据解析出来并写入到客户机的剪贴板。

bool VDAgent::handle_clipboard(VDAgentClipboard* clipboard, uint32_t size){    HANDLE clip_data;    UINT format;    bool ret = false;    if (_clipboard_owner != owner_client) {        vd_printf("Received clipboard data from client while clipboard is not owned by client");        goto fin;    }    if (clipboard->type == VD_AGENT_CLIPBOARD_NONE) {        goto fin;    }    switch (clipboard->type) {    case VD_AGENT_CLIPBOARD_UTF8_TEXT:        clip_data = utf8_alloc((LPCSTR)clipboard->data, size);        break;    case VD_AGENT_CLIPBOARD_IMAGE_PNG:    case VD_AGENT_CLIPBOARD_IMAGE_BMP: {        DWORD cximage_format = get_cximage_format(clipboard->type);        ASSERT(cximage_format);        CxImage image(clipboard->data, size, cximage_format);        clip_data = image.CopyToHandle();        break;    }    default:        vd_printf("Unsupported clipboard type %u", clipboard->type);        goto fin;    }    format = get_clipboard_format(clipboard->type);    if (format == 0) {        vd_printf("Unknown clipboard format, type %u", clipboard->type);        goto fin;    }    ret = !!SetClipboardData(format, clip_data);    if (!ret) {        DWORD err = GetLastError();        if (err == ERROR_NOT_ENOUGH_MEMORY) {            vd_printf("Not enough memory to set clipboard data, size %u bytes", size);        } else {            vd_printf("SetClipboardData failed: %lu", err);        }    }fin:    set_control_event(CONTROL_CLIPBOARD);    return ret;}

剪贴板数据共享流程如图1.1所示。客户机上的agent和客户端关于剪贴板数据的处理流程是对称的。所以当Guest机进行复制操作时也同理,先设置剪贴板拥有者为guest,并向客户端发送GRAB数据。收到客户端的REQUEST数据请求时,将CLIPBOARD数据发给客户端。

图1.1 client-guest 剪贴板数据传输

以上就是如何进行spice agent 剪贴板共享机制的分析,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注行业资讯频道。

0