0

I am trying to build up an XClient that monitors clipboard selections, namely the PRIMARY Selection. With the attached code, the selections from running xterm windows are being retrieved satisfactorily. However retrieving the selections from other applications is never working. I do not understand why. Can anybody offer any advise?

(to compile use gcc -L/usr/X11R6/lib -lX11 [filename.cpp])

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char chr_title[] = { "COM Clipboard XClient" };

int main(int argc, char *argv[]) {

    /*declarations */
    Display *ads_display;
    Window ds_window;
    GC ds_gc;
    XEvent ds_event;
    XSizeHints ds_size_hints;
    XWMHints ds_wm_hints;
    int iml_screen;
    unsigned long ull_foreground, ull_background;
    int iml_i;
    char chr_text[10];
    int iml_done;
    Atom ds_property;

    /*initialisation*/

    ads_display = XOpenDisplay(NULL);

    assert(ads_display); //NULL pointer check

    iml_screen = DefaultScreen(ads_display);

    /* default pixel values */
    ull_background = WhitePixel(ads_display, iml_screen);
    ull_foreground = BlackPixel(ads_display, iml_screen);

    /* default program-specified window position and size */
    ds_size_hints.x = 200;
    ds_size_hints.y = 300;

    ds_size_hints.width = 350;
    ds_size_hints.height = 250;

    ds_size_hints.flags = PPosition | PSize;

    ds_wm_hints.flags = InputHint;
    ds_wm_hints.input = True;

    fprintf(stderr, "\nCreating Simple Window");
    ds_window = XCreateSimpleWindow(ads_display,
        DefaultRootWindow(ads_display), ds_size_hints.x, ds_size_hints.y,
        ds_size_hints.width, ds_size_hints.height, 5, ull_foreground,
        ull_background);

    XSetStandardProperties(ads_display, ds_window, chr_title, chr_title, None,
        argv, argc, &ds_size_hints);

    XSetWMHints(ads_display, ds_window, &ds_wm_hints);

    /* GC creation and initialisation */
    ds_gc = XCreateGC(ads_display, ds_window, 0, 0);
    XSetBackground(ads_display, ds_gc, ull_background);
    XSetForeground(ads_display, ds_gc, ull_foreground);

    /* input event selection */
    XSelectInput(ads_display, ds_window, ButtonPressMask | KeyPressMask
        | ExposureMask | PropertyChangeMask);

    /* window mapping */
    XMapRaised(ads_display, ds_window);

    /*main event-reading loop */
    iml_done = 0;

    while (iml_done == 0) {
        /* read the next event */
        XNextEvent(ads_display, &ds_event);
        switch (ds_event.type) {

        /* repaint window on expose events */
        case Expose:
        if (ds_event.xexpose.count == 0) {
            XDrawImageString(ds_event.xexpose.display,
                ds_event.xexpose.window, ds_gc, 50, 50, chr_title,
                strlen(chr_title));
        }
        break;

        /* process mouse-button presses */
        case ButtonPress:
            fprintf(stderr, "\nCalling XConvertSelection()...");
        XConvertSelection(ads_display, XA_PRIMARY, XA_STRING, None,
        ds_window, ds_event.xbutton.time);

        XFlush(ads_display);
        break;

        case SelectionNotify:

        fprintf(stderr, "\nSelection Notify Event:");

        Atom type;
        int format, result;
        unsigned long len, bytes_left, dummy;
        unsigned char *data;

        result = XGetWindowProperty(ads_display, ds_window, XA_STRING, 0, 0, //off, len
                0, // Delete 0==FALSE
                AnyPropertyType, //flag
                &type, // return type
                &format, // return format
                &len, &bytes_left, //that
                &data);
        fprintf(stderr, "\nReturn from XGetWindowProperty(): %d.", result);

        fprintf(stderr, "\nType:%i Len:%lu Format:%i Byte_left:%lu",
                (int) type, len, format, bytes_left);

        // DATA is There
        if (bytes_left > 0) {
            result = XGetWindowProperty(ads_display, ds_window, XA_STRING,
                0, bytes_left, 0, AnyPropertyType, &type, &format,
                &len, &dummy, &data);
            if (result == Success)
                fprintf(stderr, "\nDATA:\n%s\n", data);
            else
                fprintf(stderr, "\nFAIL\n");

            XFree(data);

        } //end if (bytes_left > 0)
        break;
        }// end switch (ds_event.type)

    } /* while (done == 0) */

    /* termination */
    XFreeGC(ads_display, ds_gc);
    XDestroyWindow(ads_display, ds_window);
    XCloseDisplay(ads_display);
    exit(0);
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Jumik
  • 1
  • 1

1 Answers1

0

Try printing out your SelectionNotify event fields, maybe the property in there is None because the selection doesn't exist or isn't in the STRING format? Maybe clicking on your window causes focus out and some apps drop PRIMARY then?

How does X11 clipboard handle multiple data formats? may be a useful snippet of Python to inspect available selections.

Community
  • 1
  • 1
Havoc P
  • 8,365
  • 1
  • 31
  • 46