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

Viewed 74

Basically, I was messing with X11 functions and I was trying out this. I was checking if I could use the code when I had found out it froze up and wouldn't continue. Why does it freeze? This is what the code was.

#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;
}

I haven't tested with compilers other than gcc.

1 Answers

What exactly does "freeze" mean?

That printf("TEST"); is not called?

If you go to some text editor (e.g. gnome editor), select some text and perform a "copy to clipboard" operation in the text editor, your program should continue and perform the printf("TEST");.

Why does the program have this behaviour?

The clipboard under X11 works differently than the clipboard under MS Windows:

Under Windows, you actually copy data to the clipboard. Then the data is in the clipboard and programs that wants to "paste" data get the data from the clipboard.

Under X11, a window (and therefore a program) is only registering itself as "selection owner". This means that a program that wants to "paste" some data will not get the data from the clipboard but it will get the data from the program that "copied" the data.

Whenever you perform a "paste" in some program (e.g. in the text editor), the code in case SelectionRequest: is executed. Your program will then send the data to the program that wants to "paste" data.

You may try this out by adding a printf("paste\n"); after the case SelectionRequest:. Whenever you "paste" data in another program (e.g. the text editor), you will see that your program prints "paste".

Of course, the function XCopy() must not return as long as any program may "paste" the data that you have copied. For this reason, XCopy() will return as soon as another program "copies" data to the clipboard.

Related