'X11 Copy is returning only returning GDK_SELECTION, for CLIPBOARD Selection

I am writing a component which has to monitor changes in CLIPBOARD for a X11 window.

auto display = XOpenDisplay(NULL);
auto screen = DefaultScreen(mdisplay);
auto root_window = RootWindow(display, screen);
clipboard = XInternAtom(display, "CLIPBOARD", 0);
window = XCreateSimpleWindow(mdisplay, root_window, 0, 0, 1, 1, 0, 0, 0);
while(true) {
    XEvent event = {0};
    XNextEvent(display, &event);
    switch(event.type) {
        case SelectionNotify: {
            // do something
        }
        break;
        case SelectionRequest: { // triggered after performing copy
            auto target_name = XGetAtomName(display, event.xselectionrequest.target);
            auto selection_name = XGetAtomName(display, event.xselectionrequest.selection);
            auto property_name = XGetAtomName(display, event.xselectionrequest.property);
            Log("Event SelectionRequest: owner: %ld, requestor: %ld, selection: %s, target: %s(%d), property: %s",
                    event.xselectionrequest.owner, 
                    event.xselectionrequest.requestor,
                    selection_name,
                    target_name,
                    event.xselectionrequest.target,
                    property_name);

            if(x_event.xselectionrequest.selection != clipboard) {
                Log("%s: Warning: event selection not matching\n", __func__);
                break;
            }
        }
        break;
    }
}

Problem is that when I try to check event SelectionRequest all I see is

Event SelectionRequest: owner: 33554433, requestor: 18874649, selection: CLIPBOARD, target: TARGETS(344), property: GDK_SELECTION

The action I am performing is copying some text from Chrome browser. Can anyone tell me why I am not seeing this text, unicode, string types, but rather GDK_SELECTION?

PS: It happens to be I just saw those formats only once (text, unicode, string types), but never again.



Solution 1:[1]

For reading data in clipboard you need:

  • call XConvertSelection with TARGETS as target atom
  • wait for SelectionNotify event and read available targets using XGetWindowProperty
  • call XConvertSelection with preferred target
  • wait for SelectionNotify event and read available data using XGetWindowProperty

For more info check this answer

Posting hear naive implementation only for describe main idea.

// gcc -o xclipget xclipget.c -lX11
#include <stdio.h>
#include <limits.h>
#include <X11/Xlib.h>

Bool PrintSelection(Display *display, Window window, const char *bufname, const char *fmtname)
{
  char *result;
  unsigned long ressize, restail;
  int resbits;
  Atom bufid = XInternAtom(display, bufname, False),
       fmtid = XInternAtom(display, fmtname, False),
       propid = XInternAtom(display, "XSEL_DATA", False),
       incrid = XInternAtom(display, "INCR", False);
  XEvent event;

  XConvertSelection(display, bufid, fmtid, propid, window, CurrentTime);
  do {
    XNextEvent(display, &event);
  } while (event.type != SelectionNotify || event.xselection.selection != bufid);

  if (event.xselection.property)
  {
    XGetWindowProperty(display, window, propid, 0, LONG_MAX/4, False, AnyPropertyType,
      &fmtid, &resbits, &ressize, &restail, (unsigned char**)&result);

    if (fmtid == incrid)
      printf("Buffer is too large and INCR reading is not implemented yet.\n");
    else
      printf("%.*s", (int)ressize, result);

    XFree(result);
    return True;
  }
  else // request failed, e.g. owner can't convert to the target format
    return False;
}

int main()
{
  Display *display = XOpenDisplay(NULL);
  unsigned long color = BlackPixel(display, DefaultScreen(display));
  Window window = XCreateSimpleWindow(display, DefaultRootWindow(display), 0,0, 1,1, 0, color, color);
  Bool result = PrintSelection(display, window, "CLIPBOARD", "UTF8_STRING") ||
                PrintSelection(display, window, "CLIPBOARD", "STRING");
  XDestroyWindow(display, window);
  XCloseDisplay(display);
  return !result;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 marc_s