Xlib XSelectionRequest - 向请求者发送图像

问题描述


我希望我的 C++ 程序像剪贴板一样存储 png 图像并将该图像发送到请求当前剪贴板选择的 X11 客户端。图像数据以字节数组的形式存储在 const std::string clipboardContent 变量中。阅读 this 后,我正在尝试在我的程序中实现它:

#include <iostream>
#include <string>
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>

int main()
{
    //...
    Display* display = XOpenDisplay(NULL);
    int screen = XDefaultScreen(display);
    Window rootWindow = XRootWindow(display,screen);
    Atom selection = XInternAtom(display,"CLIPBOARD",false);
    Atom image = XInternAtom(display,"image/png",false);
    Atom targets = XInternAtom(display,"TARGETS",false);
    Window newOwnerWindow = XCreateSimpleWindow(display,rootWindow,-10,1,0);
    XSetSelectionOwner(display,selection,newOwnerWindow,CurrentTime);
    XEvent event;
    while (true)
    {
        XNextEvent(display,&event);
        if (event.type == SelectionRequest)
        {
            Atom targetRequsted = event.xselectionrequest.target;
            std::cout << "Requested target: \"" <<
                XGetAtomName(display,targetRequsted) << "\"" << '\n';
            if (targetRequsted == targets)
            {
                XChangeProperty(display,event.xselectionrequest.requestor,event.xselectionrequest.property,XA_ATOM,32,PropModeReplace,reinterpret_cast<unsigned char*>(&image),sizeof(image));
                XEvent selectionRespond;
                selectionRespond.type = SelectionNotify;
                selectionRespond.xselection.requestor =
                    event.xselectionrequest.requestor;
                selectionRespond.xselection.property =
                    event.xselectionrequest.property;
                selectionRespond.xselection.display =
                    event.xselectionrequest.display;
                selectionRespond.xselection.selection =
                    event.xselectionrequest.selection;
                selectionRespond.xselection.target =
                    event.xselectionrequest.target;
                selectionRespond.xselection.time =
                    event.xselectionrequest.time;
                XSendEvent(display,true,NoEventMask,&selectionRespond);
            }
            else if (targetRequsted == image)
            {
                // clipboardContent is a const std::string variable storing a
                // png image
                XChangeProperty(display,image,8,reinterpret_cast<const unsigned char*>(&clipboardContent[0]),clipboardContent.size());
                XEvent selectionRespond;
                selectionRespond.type = SelectionNotify;
                selectionRespond.xselection.requestor =
                    event.xselectionrequest.requestor;
                selectionRespond.xselection.property =
                    event.xselectionrequest.property;
                selectionRespond.xselection.display =
                    event.xselectionrequest.display;
                selectionRespond.xselection.selection =
                    event.xselectionrequest.selection;
                selectionRespond.xselection.target =
                    event.xselectionrequest.target;
                selectionRespond.xselection.time =
                    event.xselectionrequest.time;
                XSendEvent(display,&selectionRespond);
                break;
            }
            else
            {
                //...
            }
        }
    }
    //...
    return 0;
}

因此,const std::string clipboardContent 变量中存储了一些 png 图像数据。该程序创建一个新的简单窗口,将该窗口声明为新的剪贴板选择所有者并等待选择请求。如果某些客户端请求可用的选择目标,程序会以 image Atom 响应,它引用“image/png”字符串,如果请求者对“image/png”数据类型感兴趣,它可以请求并获取这些数据。

总的来说,这段代码可以工作并完成预期的工作,但是它有一个小问题。例如,当我将一些图像粘贴到 Firefox 窗口时,程序输出为:

REQUESTED TARGET "TARGETS"
REQUESTED TARGET "TARGETS"
REQUESTED TARGET "TARGETS"
REQUESTED TARGET "TARGETS"
REQUESTED TARGET "TARGETS"
REQUESTED TARGET "TARGETS"
REQUESTED TARGET "TARGETS"
REQUESTED TARGET "TARGETS"
REQUESTED TARGET "TARGETS"
REQUESTED TARGET "TARGETS"
REQUESTED TARGET "TARGETS"
REQUESTED TARGET "TARGETS"
REQUESTED TARGET "TARGETS"
REQUESTED TARGET "TARGETS"
REQUESTED TARGET "TARGETS"
REQUESTED TARGET "TARGETS"
REQUESTED TARGET "application/x-moz-nativehtml"
REQUESTED TARGET "text/html"
REQUESTED TARGET "application/x-moz-file"
REQUESTED TARGET "image/png"
REQUESTED TARGET "TARGETS"

如您所见,请求者在实际请求图像之前执行了大量冗余(或不?)请求,这会导致按下“Ctrl+V”和粘贴图像之间出现明显的(1-2 秒)延迟.另一方面,当我将相同的图像粘贴到同一个窗口而不运行我的程序(使用 X 原生剪贴板机制)时,没有任何滞后。
为什么客户端在请求目标后不立即请求图像,而是请求不可用的数据类型,例如“text/html”?为什么有这么多相同的目标请求?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...