为什么这个程序在 X11 复制到剪贴板功能 returns 后冻结?

Why does this program freeze after the X11 copy to clipboard function returns?

基本上,我在搞乱 X11 函数,我正在尝试 this。当我发现它冻结并且无法继续时,我正在检查我是否可以使用该代码。为什么会结冰?这就是代码。

#include <string.h> // strlen
#include <X11/Xlib.h>

Display * display;
Window window;
Atom targets_atom, text_atom, UTF8, XA_ATOM = 4, XA_STRING = 31;

static void XCopy(Atom selection, unsigned char * text, int size) {
    XEvent event;
    Window owner;
    XSetSelectionOwner (display, selection, window, 0);
    if (XGetSelectionOwner (display, selection) != window) return;
    while (1) {
        XNextEvent (display, &event);
        switch (event.type) {
            case SelectionRequest:
              if (event.xselectionrequest.selection != selection) break;
              XSelectionRequestEvent * xsr = &event.xselectionrequest;
              XSelectionEvent ev = {0};
              int R = 0;
              ev.type = SelectionNotify, ev.display = xsr->display, ev.requestor = xsr->requestor,
              ev.selection = xsr->selection, ev.time = xsr->time, ev.target = xsr->target, ev.property = xsr->property;
              if (ev.target == targets_atom) R = XChangeProperty (ev.display, ev.requestor, ev.property, XA_ATOM, 32,
                    PropModeReplace, (unsigned char*)&UTF8, 1);
              else if (ev.target == XA_STRING || ev.target == text_atom) 
                R = XChangeProperty(ev.display, ev.requestor, ev.property, XA_STRING, 8, PropModeReplace, text, size);
              else if (ev.target == UTF8)
                R = XChangeProperty(ev.display, ev.requestor, ev.property, UTF8, 8, PropModeReplace, text, size);
              else ev.property = None;
              if ((R & 2) == 0) XSendEvent (display, ev.requestor, 0, 0, (XEvent *)&ev);
             break;
            case SelectionClear:
             return;
        }
    }
}

int main(int argc, char *argv[]) {
    display = XOpenDisplay(0);
    int N = DefaultScreen(display);
    window = XCreateSimpleWindow(display, RootWindow(display, N), 0, 0, 1, 1, 0,
        BlackPixel(display, N), WhitePixel(display, N));    
    targets_atom = XInternAtom(display, "TARGETS", 0);
    text_atom = XInternAtom(display, "TEXT", 0);
    UTF8 = XInternAtom(display, "UTF8_STRING", 1);
    if (UTF8 == None) UTF8 = XA_STRING;
    Atom selection = XInternAtom(display, "CLIPBOARD", 0);
    XCopy(selection, (unsigned char*) argv[1], strlen(argv[1]));
    printf("TEST");
    return 0;
}

我没有用 gcc 以外的编译器测试过。

“冻结”到底是什么意思?

那个printf("TEST");不叫?

如果您使用某些文本编辑器(例如 gnome 编辑器),select 一些文本并在文本编辑器中执行“复制到剪贴板”操作,您的程序应该继续并执行 printf("TEST");.

为什么程序会有这种行为?

X11 下的剪贴板与 MS 下的剪贴板工作方式不同 Windows:

在Windows下,你实际上是将数据复制到剪贴板。然后数据在剪贴板中,想要“粘贴”数据的程序从剪贴板中获取数据。

在 X11 下,window(因此也是一个程序)只是将自己注册为“selection 所有者”。这意味着想要“粘贴”某些数据的程序不会从剪贴板中获取数据,而是从“复制”数据的程序中获取数据。

每当您在某些程序中执行“粘贴”(例如在文本编辑器中)时,都会执行 case SelectionRequest: 中的代码。然后您的程序会将数据发送到想要“粘贴”数据的程序。

您可以通过在 case SelectionRequest: 之后添加 printf("paste\n"); 来进行尝试。每当您在另一个程序(例如文本编辑器)中“粘贴”数据时,您都会看到您的程序打印 "paste".

当然,函数XCopy()一定不能return,只要任何程序都可以“粘贴”你复制的数据。因此,一旦另一个程序将数据“复制”到剪贴板,XCopy() 将 return。