[Spice-devel] [PATCH vdagent 1/2] vdagent-x11: remove clipboard handling

Jakub Janku jjanku at redhat.com
Sun Feb 18 22:51:41 UTC 2018


Hi,

On Mon, Feb 12, 2018 at 10:40 AM, Victor Toso <victortoso at redhat.com> wrote:
> Hi,
>
> Follow up after the comment in the cover letter.
>
> On Sun, Jan 21, 2018 at 09:03:13PM +0100, Jakub Janků wrote:
>> From: Jakub Janků <jjanku at redhat.com>
>>
>> The code will be replaced by GTK+ in the following patch.
>> ---
>>  src/vdagent/vdagent.c  |    7 -
>>  src/vdagent/x11-priv.h |   91 ----
>>  src/vdagent/x11.c      | 1074 +-----------------------------------------------
>>  src/vdagent/x11.h      |   10 -
>>  4 files changed, 1 insertion(+), 1181 deletions(-)
>>
>> diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c
>> index d86ee25..92ffcf3 100644
>> --- a/src/vdagent/vdagent.c
>> +++ b/src/vdagent/vdagent.c
>> @@ -164,18 +164,12 @@ static void daemon_read_complete(struct udscs_connection **connp,
>>          vdagent_x11_set_monitor_config(agent->x11, (VDAgentMonitorsConfig *)data, 0);
>>          break;
>>      case VDAGENTD_CLIPBOARD_REQUEST:
>> -        vdagent_x11_clipboard_request(agent->x11, header->arg1, header->arg2);
>>          break;
>>      case VDAGENTD_CLIPBOARD_GRAB:
>> -        vdagent_x11_clipboard_grab(agent->x11, header->arg1, (uint32_t *)data,
>> -                                   header->size / sizeof(uint32_t));
>>          break;
>>      case VDAGENTD_CLIPBOARD_DATA:
>> -        vdagent_x11_clipboard_data(agent->x11, header->arg1, header->arg2,
>> -                                   data, header->size);
>>          break;
>>      case VDAGENTD_CLIPBOARD_RELEASE:
>> -        vdagent_x11_clipboard_release(agent->x11, header->arg1);
>>          break;
>>      case VDAGENTD_VERSION:
>>          if (strcmp((char *)data, VERSION) != 0) {
>> @@ -228,7 +222,6 @@ static void daemon_read_complete(struct udscs_connection **connp,
>>          }
>>          break;
>>      case VDAGENTD_CLIENT_DISCONNECTED:
>> -        vdagent_x11_client_disconnected(agent->x11);
>
> So, instead of removing the vdagent_x11 calls, you could
> introduce the clipboard.[ch] and use the renamed calls here that
> will call the x11 code for now.

Seems reasonable (including the proposal in cover letter comment),
I'll change it with v2.

  Jakub
>
> Reviewed-by: Victor Toso <victortoso at redhat.com>
>
>         toso
>
>>          if (vdagent_finalize_file_xfer(agent)) {
>>              vdagent_init_file_xfer(agent);
>>          }
>> diff --git a/src/vdagent/x11-priv.h b/src/vdagent/x11-priv.h
>> index 3776098..627e0ed 100644
>> --- a/src/vdagent/x11-priv.h
>> +++ b/src/vdagent/x11-priv.h
>> @@ -1,118 +1,27 @@
>>  #ifndef VDAGENT_X11_PRIV
>>  #define VDAGENT_X11_PRIV
>>
>> -#include <stdint.h>
>> -#include <stdio.h>
>> -
>> -#include <spice/vd_agent.h>
>> -
>>  #include <X11/extensions/Xrandr.h>
>>
>> -/* Macros to print a message to the logfile prefixed by the selection */
>> -#define SELPRINTF(format, ...) \
>> -    syslog(LOG_ERR, "%s: " format, \
>> -            vdagent_x11_sel_to_str(selection), ##__VA_ARGS__)
>> -
>> -#define VSELPRINTF(format, ...) \
>> -    do { \
>> -        if (x11->debug) { \
>> -            syslog(LOG_DEBUG, "%s: " format, \
>> -                    vdagent_x11_sel_to_str(selection), ##__VA_ARGS__); \
>> -        } \
>> -    } while (0)
>> -
>>  #define MAX_SCREENS 16
>>  /* Same as qxl_dev.h client_monitors_config.heads count */
>>  #define MONITOR_SIZE_COUNT 64
>>
>> -enum { owner_none, owner_guest, owner_client };
>> -
>> -/* X11 terminology is confusing a selection request is a request from an
>> -   app to get clipboard data from us, so iow from the spice client through
>> -   the vdagent channel. We handle these one at a time and queue any which
>> -   come in while we are still handling the current one. */
>> -struct vdagent_x11_selection_request {
>> -    XEvent event;
>> -    uint8_t selection;
>> -    struct vdagent_x11_selection_request *next;
>> -};
>> -
>> -/* A conversion request is X11 speak for asking another app to give its
>> -   clipboard data to us, we do these on behalf of the spice client to copy
>> -   data from the guest to the client. Like selection requests we process
>> -   these one at a time. */
>> -struct vdagent_x11_conversion_request {
>> -    Atom target;
>> -    uint8_t selection;
>> -    struct vdagent_x11_conversion_request *next;
>> -};
>> -
>> -struct clipboard_format_tmpl {
>> -    uint32_t type;
>> -    const char *atom_names[16];
>> -};
>> -
>> -struct clipboard_format_info {
>> -    uint32_t type;
>> -    Atom atoms[16];
>> -    int atom_count;
>> -};
>> -
>>  struct monitor_size {
>>      int width;
>>      int height;
>>  };
>>
>> -static const struct clipboard_format_tmpl clipboard_format_templates[] = {
>> -    { VD_AGENT_CLIPBOARD_UTF8_TEXT, { "UTF8_STRING", "text/plain;charset=UTF-8",
>> -      "text/plain;charset=utf-8", "STRING", NULL }, },
>> -    { VD_AGENT_CLIPBOARD_IMAGE_PNG, { "image/png", NULL }, },
>> -    { VD_AGENT_CLIPBOARD_IMAGE_BMP, { "image/bmp", "image/x-bmp",
>> -      "image/x-MS-bmp", "image/x-win-bitmap", NULL }, },
>> -    { VD_AGENT_CLIPBOARD_IMAGE_TIFF, { "image/tiff", NULL }, },
>> -    { VD_AGENT_CLIPBOARD_IMAGE_JPG, { "image/jpeg", NULL }, },
>> -};
>> -
>> -#define clipboard_format_count (sizeof(clipboard_format_templates)/sizeof(clipboard_format_templates[0]))
>> -
>>  struct vdagent_x11 {
>> -    struct clipboard_format_info clipboard_formats[clipboard_format_count];
>>      Display *display;
>> -    Atom clipboard_atom;
>> -    Atom clipboard_primary_atom;
>> -    Atom targets_atom;
>> -    Atom incr_atom;
>> -    Atom multiple_atom;
>> -    Atom timestamp_atom;
>>      Window root_window[MAX_SCREENS];
>> -    Window selection_window;
>>      struct udscs_connection *vdagentd;
>>      int debug;
>>      int fd;
>>      int screen_count;
>>      int width[MAX_SCREENS];
>>      int height[MAX_SCREENS];
>> -    int has_xfixes;
>> -    int xfixes_event_base;
>>      int xrandr_event_base;
>> -    int max_prop_size;
>> -    int expected_targets_notifies[256];
>> -    int clipboard_owner[256];
>> -    int clipboard_type_count[256];
>> -    uint32_t clipboard_agent_types[256][256];
>> -    Atom clipboard_x11_targets[256][256];
>> -    /* Data for conversion_req which is currently being processed */
>> -    struct vdagent_x11_conversion_request *conversion_req;
>> -    int expect_property_notify;
>> -    uint8_t *clipboard_data;
>> -    uint32_t clipboard_data_size;
>> -    uint32_t clipboard_data_space;
>> -    /* Data for selection_req which is currently being processed */
>> -    struct vdagent_x11_selection_request *selection_req;
>> -    uint8_t *selection_req_data;
>> -    uint32_t selection_req_data_pos;
>> -    uint32_t selection_req_data_size;
>> -    Atom selection_req_atom;
>>      /* resolution change state */
>>      struct {
>>          XRRScreenResources *res;
>> diff --git a/src/vdagent/x11.c b/src/vdagent/x11.c
>> index 9700847..738eaa4 100644
>> --- a/src/vdagent/x11.c
>> +++ b/src/vdagent/x11.c
>> @@ -31,21 +31,14 @@
>>     Calling XPending when-ever we return to the mainloop also ensures any
>>     pending writes are flushed. */
>>
>> -#include <glib.h>
>>  #include <gdk/gdk.h>
>>  #ifdef GDK_WINDOWING_X11
>>  #include <gdk/gdkx.h>
>>  #endif
>>  #include <stdlib.h>
>> -#include <limits.h>
>>  #include <string.h>
>>  #include <syslog.h>
>> -#include <assert.h>
>> -#include <unistd.h>
>> -#include <X11/Xatom.h>
>>  #include <X11/Xlib.h>
>> -#include <X11/extensions/Xfixes.h>
>> -#include "vdagentd-proto.h"
>>  #include "x11.h"
>>  #include "x11-priv.h"
>>
>> @@ -53,48 +46,12 @@
>>  int (*vdagent_x11_prev_error_handler)(Display *, XErrorEvent *);
>>  int vdagent_x11_caught_error;
>>
>> -static void vdagent_x11_handle_selection_notify(struct vdagent_x11 *x11,
>> -                                                XEvent *event, int incr);
>> -static void vdagent_x11_handle_selection_request(struct vdagent_x11 *x11);
>> -static void vdagent_x11_handle_targets_notify(struct vdagent_x11 *x11,
>> -                                              XEvent *event);
>> -static void vdagent_x11_handle_property_delete_notify(struct vdagent_x11 *x11,
>> -                                                      XEvent *del_event);
>> -static void vdagent_x11_send_selection_notify(struct vdagent_x11 *x11,
>> -                Atom prop, struct vdagent_x11_selection_request *request);
>> -static void vdagent_x11_set_clipboard_owner(struct vdagent_x11 *x11,
>> -                                            uint8_t selection, int new_owner);
>> -
>> -static const char *vdagent_x11_sel_to_str(uint8_t selection) {
>> -    switch (selection) {
>> -    case VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD:
>> -        return "clipboard";
>> -    case VD_AGENT_CLIPBOARD_SELECTION_PRIMARY:
>> -        return "primary";
>> -    case VD_AGENT_CLIPBOARD_SELECTION_SECONDARY:
>> -        return "secondary";
>> -    default:
>> -        return "unknown";
>> -    }
>> -}
>> -
>>  static int vdagent_x11_debug_error_handler(
>>      Display *display, XErrorEvent *error)
>>  {
>>      abort();
>>  }
>>
>> -/* With the clipboard we're sometimes dealing with Properties on another apps
>> -   Window. which can go away at any time. */
>> -static int vdagent_x11_ignore_bad_window_handler(
>> -    Display *display, XErrorEvent *error)
>> -{
>> -    if (error->error_code == BadWindow)
>> -        return 0;
>> -
>> -    return vdagent_x11_prev_error_handler(display, error);
>> -}
>> -
>>  void vdagent_x11_set_error_handler(struct vdagent_x11 *x11,
>>      int (*handler)(Display *, XErrorEvent *))
>>  {
>> @@ -131,7 +88,7 @@ struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
>>  {
>>      struct vdagent_x11 *x11;
>>      XWindowAttributes attrib;
>> -    int i, j, major, minor;
>> +    int i;
>>      const gchar *net_wm_name;
>>
>>      x11 = calloc(1, sizeof(*x11));
>> @@ -167,57 +124,9 @@ struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
>>      for (i = 0; i < x11->screen_count; i++)
>>          x11->root_window[i] = RootWindow(x11->display, i);
>>      x11->fd = ConnectionNumber(x11->display);
>> -    x11->clipboard_atom = XInternAtom(x11->display, "CLIPBOARD", False);
>> -    x11->clipboard_primary_atom = XInternAtom(x11->display, "PRIMARY", False);
>> -    x11->targets_atom = XInternAtom(x11->display, "TARGETS", False);
>> -    x11->incr_atom = XInternAtom(x11->display, "INCR", False);
>> -    x11->multiple_atom = XInternAtom(x11->display, "MULTIPLE", False);
>> -    x11->timestamp_atom = XInternAtom(x11->display, "TIMESTAMP", False);
>> -    for(i = 0; i < clipboard_format_count; i++) {
>> -        x11->clipboard_formats[i].type = clipboard_format_templates[i].type;
>> -        for(j = 0; clipboard_format_templates[i].atom_names[j]; j++) {
>> -            x11->clipboard_formats[i].atoms[j] =
>> -                XInternAtom(x11->display,
>> -                            clipboard_format_templates[i].atom_names[j],
>> -                            False);
>> -        }
>> -        x11->clipboard_formats[i].atom_count = j;
>> -    }
>> -
>> -    /* We should not store properties (for selections) on the root window */
>> -    x11->selection_window = XCreateSimpleWindow(x11->display, x11->root_window[0],
>> -                                                0, 0, 1, 1, 0, 0, 0);
>> -    if (x11->debug)
>> -        syslog(LOG_DEBUG, "Selection window: %u", (int)x11->selection_window);
>>
>>      vdagent_x11_randr_init(x11);
>>
>> -    if (XFixesQueryExtension(x11->display, &x11->xfixes_event_base, &i) &&
>> -        XFixesQueryVersion(x11->display, &major, &minor) && major >= 1) {
>> -        x11->has_xfixes = 1;
>> -        XFixesSelectSelectionInput(x11->display, x11->root_window[0],
>> -                                   x11->clipboard_atom,
>> -                                   XFixesSetSelectionOwnerNotifyMask|
>> -                                   XFixesSelectionWindowDestroyNotifyMask|
>> -                                   XFixesSelectionClientCloseNotifyMask);
>> -        XFixesSelectSelectionInput(x11->display, x11->root_window[0],
>> -                                   x11->clipboard_primary_atom,
>> -                                   XFixesSetSelectionOwnerNotifyMask|
>> -                                   XFixesSelectionWindowDestroyNotifyMask|
>> -                                   XFixesSelectionClientCloseNotifyMask);
>> -    } else
>> -        syslog(LOG_ERR, "no xfixes, no guest -> client copy paste support");
>> -
>> -    x11->max_prop_size = XExtendedMaxRequestSize(x11->display);
>> -    if (x11->max_prop_size) {
>> -        x11->max_prop_size -= 100;
>> -    } else {
>> -        x11->max_prop_size = XMaxRequestSize(x11->display) - 100;
>> -    }
>> -    /* Be a good X11 citizen and maximize the amount of data we send at once */
>> -    if (x11->max_prop_size > 262144)
>> -        x11->max_prop_size = 262144;
>> -
>>      for (i = 0; i < x11->screen_count; i++) {
>>          /* Catch resolution changes */
>>          XSelectInput(x11->display, x11->root_window[i], StructureNotifyMask);
>> @@ -249,18 +158,12 @@ struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
>>
>>  void vdagent_x11_destroy(struct vdagent_x11 *x11, int vdagentd_disconnected)
>>  {
>> -    uint8_t sel;
>> -
>>      if (!x11)
>>          return;
>>
>>      if (vdagentd_disconnected)
>>          x11->vdagentd = NULL;
>>
>> -    for (sel = 0; sel < VD_AGENT_CLIPBOARD_SELECTION_SECONDARY; ++sel) {
>> -        vdagent_x11_set_clipboard_owner(x11, sel, owner_none);
>> -    }
>> -
>>      XCloseDisplay(x11->display);
>>      free(x11->randr.failed_conf);
>>      free(x11);
>> @@ -271,190 +174,9 @@ int vdagent_x11_get_fd(struct vdagent_x11 *x11)
>>      return x11->fd;
>>  }
>>
>> -static void vdagent_x11_next_selection_request(struct vdagent_x11 *x11)
>> -{
>> -    struct vdagent_x11_selection_request *selection_request;
>> -    selection_request = x11->selection_req;
>> -    x11->selection_req = selection_request->next;
>> -    free(selection_request);
>> -}
>> -
>> -static void vdagent_x11_next_conversion_request(struct vdagent_x11 *x11)
>> -{
>> -    struct vdagent_x11_conversion_request *conversion_req;
>> -    conversion_req = x11->conversion_req;
>> -    x11->conversion_req = conversion_req->next;
>> -    free(conversion_req);
>> -}
>> -
>> -static void vdagent_x11_set_clipboard_owner(struct vdagent_x11 *x11,
>> -    uint8_t selection, int new_owner)
>> -{
>> -    struct vdagent_x11_selection_request *prev_sel, *curr_sel, *next_sel;
>> -    struct vdagent_x11_conversion_request *prev_conv, *curr_conv, *next_conv;
>> -    int once;
>> -
>> -    /* Clear pending requests and clipboard data */
>> -    once = 1;
>> -    prev_sel = NULL;
>> -    next_sel = x11->selection_req;
>> -    while (next_sel) {
>> -        curr_sel = next_sel;
>> -        next_sel = curr_sel->next;
>> -        if (curr_sel->selection == selection) {
>> -            if (once) {
>> -                SELPRINTF("selection requests pending on clipboard ownership "
>> -                          "change, clearing");
>> -                once = 0;
>> -            }
>> -            vdagent_x11_send_selection_notify(x11, None, curr_sel);
>> -            if (curr_sel == x11->selection_req) {
>> -                x11->selection_req = next_sel;
>> -                free(x11->selection_req_data);
>> -                x11->selection_req_data = NULL;
>> -                x11->selection_req_data_pos = 0;
>> -                x11->selection_req_data_size = 0;
>> -                x11->selection_req_atom = None;
>> -            } else {
>> -                prev_sel->next = next_sel;
>> -            }
>> -            free(curr_sel);
>> -        } else {
>> -            prev_sel = curr_sel;
>> -        }
>> -    }
>> -
>> -    once = 1;
>> -    prev_conv = NULL;
>> -    next_conv = x11->conversion_req;
>> -    while (next_conv) {
>> -        curr_conv = next_conv;
>> -        next_conv = curr_conv->next;
>> -        if (curr_conv->selection == selection) {
>> -            if (once) {
>> -                SELPRINTF("client clipboard request pending on clipboard "
>> -                          "ownership change, clearing");
>> -                once = 0;
>> -            }
>> -            if (x11->vdagentd)
>> -                udscs_write(x11->vdagentd, VDAGENTD_CLIPBOARD_DATA, selection,
>> -                            VD_AGENT_CLIPBOARD_NONE, NULL, 0);
>> -            if (curr_conv == x11->conversion_req) {
>> -                x11->conversion_req = next_conv;
>> -                x11->clipboard_data_size = 0;
>> -                x11->expect_property_notify = 0;
>> -            } else {
>> -                prev_conv->next = next_conv;
>> -            }
>> -            free(curr_conv);
>> -        } else {
>> -            prev_conv = curr_conv;
>> -        }
>> -    }
>> -
>> -    if (new_owner == owner_none) {
>> -        /* When going from owner_guest to owner_none we need to send a
>> -           clipboard release message to the client */
>> -        if (x11->clipboard_owner[selection] == owner_guest && x11->vdagentd) {
>> -            udscs_write(x11->vdagentd, VDAGENTD_CLIPBOARD_RELEASE, selection,
>> -                        0, NULL, 0);
>> -        }
>> -        x11->clipboard_type_count[selection] = 0;
>> -    }
>> -    x11->clipboard_owner[selection] = new_owner;
>> -}
>> -
>> -static int vdagent_x11_get_clipboard_atom(struct vdagent_x11 *x11, uint8_t selection, Atom* clipboard)
>> -{
>> -    if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) {
>> -        *clipboard = x11->clipboard_atom;
>> -    } else if (selection == VD_AGENT_CLIPBOARD_SELECTION_PRIMARY) {
>> -        *clipboard = x11->clipboard_primary_atom;
>> -    } else {
>> -        syslog(LOG_ERR, "get_clipboard_atom: unknown selection");
>> -        return -1;
>> -    }
>> -
>> -    return 0;
>> -}
>> -
>> -static int vdagent_x11_get_clipboard_selection(struct vdagent_x11 *x11,
>> -    XEvent *event, uint8_t *selection)
>> -{
>> -    Atom atom;
>> -
>> -    if (event->type == x11->xfixes_event_base) {
>> -        XFixesSelectionNotifyEvent *xfev = (XFixesSelectionNotifyEvent *)event;
>> -        atom = xfev->selection;
>> -    } else if (event->type == SelectionNotify) {
>> -        atom = event->xselection.selection;
>> -    } else if (event->type == SelectionRequest) {
>> -        atom = event->xselectionrequest.selection;
>> -    } else {
>> -        syslog(LOG_ERR, "get_clipboard_selection: unknown event type");
>> -        return -1;
>> -    }
>> -
>> -    if (atom == x11->clipboard_atom) {
>> -        *selection = VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD;
>> -    } else if (atom == x11->clipboard_primary_atom) {
>> -        *selection = VD_AGENT_CLIPBOARD_SELECTION_PRIMARY;
>> -    } else {
>> -        syslog(LOG_ERR, "get_clipboard_selection: unknown selection");
>> -        return -1;
>> -    }
>> -
>> -    return 0;
>> -}
>> -
>>  static void vdagent_x11_handle_event(struct vdagent_x11 *x11, XEvent event)
>>  {
>>      int i, handled = 0;
>> -    uint8_t selection;
>> -
>> -    if (event.type == x11->xfixes_event_base) {
>> -        union {
>> -            XEvent ev;
>> -            XFixesSelectionNotifyEvent xfev;
>> -        } ev;
>> -
>> -        if (vdagent_x11_get_clipboard_selection(x11, &event, &selection)) {
>> -            return;
>> -        }
>> -
>> -        ev.ev = event;
>> -        switch (ev.xfev.subtype) {
>> -        case XFixesSetSelectionOwnerNotify:
>> -            break;
>> -        /* Treat ... as a SelectionOwnerNotify None */
>> -        case XFixesSelectionWindowDestroyNotify:
>> -        case XFixesSelectionClientCloseNotify:
>> -            ev.xfev.owner = None;
>> -            break;
>> -        default:
>> -            VSELPRINTF("unexpected xfix event subtype %d window %d",
>> -                       (int)ev.xfev.subtype, (int)event.xany.window);
>> -            return;
>> -        }
>> -        VSELPRINTF("New selection owner: %u", (unsigned int)ev.xfev.owner);
>> -
>> -        /* Ignore becoming the owner ourselves */
>> -        if (ev.xfev.owner == x11->selection_window)
>> -            return;
>> -
>> -        /* If the clipboard owner is changed we no longer own it */
>> -        vdagent_x11_set_clipboard_owner(x11, selection, owner_none);
>> -
>> -        if (ev.xfev.owner == None)
>> -            return;
>> -
>> -        /* Request the supported targets from the new owner */
>> -        XConvertSelection(x11->display, ev.xfev.selection, x11->targets_atom,
>> -                          x11->targets_atom, x11->selection_window,
>> -                          CurrentTime);
>> -        x11->expected_targets_notifies[selection]++;
>> -        return;
>> -    }
>>
>>      if (vdagent_x11_randr_handle_event(x11, event))
>>          return;
>> @@ -475,65 +197,6 @@ static void vdagent_x11_handle_event(struct vdagent_x11 *x11, XEvent event)
>>          /* These are uninteresting */
>>          handled = 1;
>>          break;
>> -    case SelectionNotify:
>> -        if (event.xselection.target == x11->targets_atom)
>> -            vdagent_x11_handle_targets_notify(x11, &event);
>> -        else
>> -            vdagent_x11_handle_selection_notify(x11, &event, 0);
>> -
>> -        handled = 1;
>> -        break;
>> -    case PropertyNotify:
>> -        if (x11->expect_property_notify &&
>> -                                event.xproperty.state == PropertyNewValue) {
>> -            vdagent_x11_handle_selection_notify(x11, &event, 1);
>> -        }
>> -        if (x11->selection_req_data &&
>> -                                 event.xproperty.state == PropertyDelete) {
>> -            vdagent_x11_handle_property_delete_notify(x11, &event);
>> -        }
>> -        /* Always mark as handled, since we cannot unselect input for property
>> -           notifications once we are done with handling the incr transfer. */
>> -        handled = 1;
>> -        break;
>> -    case SelectionClear:
>> -        /* Do nothing the clipboard ownership will get updated through
>> -           the XFixesSetSelectionOwnerNotify event */
>> -        handled = 1;
>> -        break;
>> -    case SelectionRequest: {
>> -        struct vdagent_x11_selection_request *req, *new_req;
>> -
>> -        if (vdagent_x11_get_clipboard_selection(x11, &event, &selection)) {
>> -            return;
>> -        }
>> -
>> -        new_req = malloc(sizeof(*new_req));
>> -        if (!new_req) {
>> -            SELPRINTF("out of memory on SelectionRequest, ignoring.");
>> -            break;
>> -        }
>> -
>> -        handled = 1;
>> -
>> -        new_req->event = event;
>> -        new_req->selection = selection;
>> -        new_req->next = NULL;
>> -
>> -        if (!x11->selection_req) {
>> -            x11->selection_req = new_req;
>> -            vdagent_x11_handle_selection_request(x11);
>> -            break;
>> -        }
>> -
>> -        /* maybe we should limit the selection_request stack depth ? */
>> -        req = x11->selection_req;
>> -        while (req->next)
>> -            req = req->next;
>> -
>> -        req->next = new_req;
>> -        break;
>> -    }
>>      }
>>      if (!handled && x11->debug)
>>          syslog(LOG_DEBUG, "unhandled x11 event, type %d, window %d",
>> @@ -550,741 +213,6 @@ void vdagent_x11_do_read(struct vdagent_x11 *x11)
>>      }
>>  }
>>
>> -static const char *vdagent_x11_get_atom_name(struct vdagent_x11 *x11, Atom a)
>> -{
>> -    if (a == None)
>> -        return "None";
>> -
>> -    return XGetAtomName(x11->display, a);
>> -}
>> -
>> -static int vdagent_x11_get_selection(struct vdagent_x11 *x11, XEvent *event,
>> -    uint8_t selection, Atom type, Atom prop, int format,
>> -    unsigned char **data_ret, int incr)
>> -{
>> -    Bool del = incr ? True: False;
>> -    Atom type_ret;
>> -    int format_ret, ret_val = -1;
>> -    unsigned long len, remain;
>> -    unsigned char *data = NULL;
>> -
>> -    *data_ret = NULL;
>> -
>> -    if (!incr) {
>> -        if (event->xselection.property == None) {
>> -            VSELPRINTF("XConvertSelection refused by clipboard owner");
>> -            goto exit;
>> -        }
>> -
>> -        if (event->xselection.requestor != x11->selection_window ||
>> -            event->xselection.property != prop) {
>> -            SELPRINTF("SelectionNotify parameters mismatch");
>> -            goto exit;
>> -        }
>> -    }
>> -
>> -    if (XGetWindowProperty(x11->display, x11->selection_window, prop, 0,
>> -                           LONG_MAX, del, type, &type_ret, &format_ret, &len,
>> -                           &remain, &data) != Success) {
>> -        SELPRINTF("XGetWindowProperty failed");
>> -        goto exit;
>> -    }
>> -
>> -    if (!incr && prop != x11->targets_atom) {
>> -        if (type_ret == x11->incr_atom) {
>> -            int prop_min_size = *(uint32_t*)data;
>> -
>> -            if (x11->expect_property_notify) {
>> -                SELPRINTF("received an incr SelectionNotify while "
>> -                          "still reading another incr property");
>> -                goto exit;
>> -            }
>> -
>> -            if (x11->clipboard_data_space < prop_min_size) {
>> -                free(x11->clipboard_data);
>> -                x11->clipboard_data = malloc(prop_min_size);
>> -                if (!x11->clipboard_data) {
>> -                    SELPRINTF("out of memory allocating clipboard buffer");
>> -                    x11->clipboard_data_space = 0;
>> -                    goto exit;
>> -                }
>> -                x11->clipboard_data_space = prop_min_size;
>> -            }
>> -            x11->expect_property_notify = 1;
>> -            XSelectInput(x11->display, x11->selection_window,
>> -                         PropertyChangeMask);
>> -            XDeleteProperty(x11->display, x11->selection_window, prop);
>> -            XFree(data);
>> -            return 0; /* Wait for more data */
>> -        }
>> -        XDeleteProperty(x11->display, x11->selection_window, prop);
>> -    }
>> -
>> -    if (type_ret != type) {
>> -        SELPRINTF("expected property type: %s, got: %s",
>> -                  vdagent_x11_get_atom_name(x11, type),
>> -                  vdagent_x11_get_atom_name(x11, type_ret));
>> -        goto exit;
>> -    }
>> -
>> -    if (format_ret != format) {
>> -        SELPRINTF("expected %d bit format, got %d bits", format, format_ret);
>> -        goto exit;
>> -    }
>> -
>> -    /* Convert len to bytes */
>> -    switch(format) {
>> -    case 8:
>> -        break;
>> -    case 16:
>> -        len *= sizeof(short);
>> -        break;
>> -    case 32:
>> -        len *= sizeof(long);
>> -        break;
>> -    }
>> -
>> -    if (incr) {
>> -        if (len) {
>> -            if (x11->clipboard_data_size + len > x11->clipboard_data_space) {
>> -                void *old_clipboard_data = x11->clipboard_data;
>> -
>> -                x11->clipboard_data_space = x11->clipboard_data_size + len;
>> -                x11->clipboard_data = realloc(x11->clipboard_data,
>> -                                              x11->clipboard_data_space);
>> -                if (!x11->clipboard_data) {
>> -                    SELPRINTF("out of memory allocating clipboard buffer");
>> -                    x11->clipboard_data_space = 0;
>> -                    free(old_clipboard_data);
>> -                    goto exit;
>> -                }
>> -            }
>> -            memcpy(x11->clipboard_data + x11->clipboard_data_size, data, len);
>> -            x11->clipboard_data_size += len;
>> -            VSELPRINTF("Appended %ld bytes to buffer", len);
>> -            XFree(data);
>> -            return 0; /* Wait for more data */
>> -        }
>> -        len = x11->clipboard_data_size;
>> -        *data_ret = x11->clipboard_data;
>> -    } else
>> -        *data_ret = data;
>> -
>> -    if (len > 0) {
>> -        ret_val = len;
>> -    } else {
>> -        SELPRINTF("property contains no data (zero length)");
>> -        *data_ret = NULL;
>> -    }
>> -
>> -exit:
>> -    if ((incr || ret_val == -1) && data)
>> -        XFree(data);
>> -
>> -    if (incr) {
>> -        x11->clipboard_data_size = 0;
>> -        x11->expect_property_notify = 0;
>> -    }
>> -
>> -    return ret_val;
>> -}
>> -
>> -static void vdagent_x11_get_selection_free(struct vdagent_x11 *x11,
>> -    unsigned char *data, int incr)
>> -{
>> -    if (incr) {
>> -        /* If the clipboard has grown large return the memory to the system */
>> -        if (x11->clipboard_data_space > 512 * 1024) {
>> -            free(x11->clipboard_data);
>> -            x11->clipboard_data = NULL;
>> -            x11->clipboard_data_space = 0;
>> -        }
>> -    } else if (data)
>> -        XFree(data);
>> -}
>> -
>> -static uint32_t vdagent_x11_target_to_type(struct vdagent_x11 *x11,
>> -    uint8_t selection, Atom target)
>> -{
>> -    int i, j;
>> -
>> -    for (i = 0; i < clipboard_format_count; i++) {
>> -        for (j = 0; j < x11->clipboard_formats[i].atom_count; j++) {
>> -            if (x11->clipboard_formats[i].atoms[j] == target) {
>> -                return x11->clipboard_formats[i].type;
>> -            }
>> -        }
>> -    }
>> -
>> -    VSELPRINTF("unexpected selection type %s",
>> -               vdagent_x11_get_atom_name(x11, target));
>> -    return VD_AGENT_CLIPBOARD_NONE;
>> -}
>> -
>> -static Atom vdagent_x11_type_to_target(struct vdagent_x11 *x11,
>> -                                       uint8_t selection, uint32_t type)
>> -{
>> -    int i;
>> -
>> -    for (i = 0; i < x11->clipboard_type_count[selection]; i++) {
>> -        if (x11->clipboard_agent_types[selection][i] == type) {
>> -            return x11->clipboard_x11_targets[selection][i];
>> -        }
>> -    }
>> -    SELPRINTF("client requested unavailable type %u", type);
>> -    return None;
>> -}
>> -
>> -static void vdagent_x11_handle_conversion_request(struct vdagent_x11 *x11)
>> -{
>> -    Atom clip = None;
>> -
>> -    if (!x11->conversion_req) {
>> -        return;
>> -    }
>> -
>> -    vdagent_x11_get_clipboard_atom(x11, x11->conversion_req->selection, &clip);
>> -    XConvertSelection(x11->display, clip, x11->conversion_req->target,
>> -                      clip, x11->selection_window, CurrentTime);
>> -}
>> -
>> -static void vdagent_x11_handle_selection_notify(struct vdagent_x11 *x11,
>> -                                                XEvent *event, int incr)
>> -{
>> -    int len = 0;
>> -    unsigned char *data = NULL;
>> -    uint32_t type;
>> -    uint8_t selection = -1;
>> -    Atom clip = None;
>> -
>> -    if (!x11->conversion_req) {
>> -        syslog(LOG_ERR, "SelectionNotify received without a target");
>> -        return;
>> -    }
>> -    vdagent_x11_get_clipboard_atom(x11, x11->conversion_req->selection, &clip);
>> -
>> -    if (incr) {
>> -        if (event->xproperty.atom != clip ||
>> -                event->xproperty.window != x11->selection_window) {
>> -            return;
>> -        }
>> -    } else {
>> -        if (vdagent_x11_get_clipboard_selection(x11, event, &selection)) {
>> -            len = -1;
>> -        } else if (selection != x11->conversion_req->selection) {
>> -            SELPRINTF("Requested data for selection %d got %d",
>> -                      (int)x11->conversion_req->selection, (int)selection);
>> -            len = -1;
>> -        }
>> -        if (event->xselection.target != x11->conversion_req->target &&
>> -                event->xselection.target != x11->incr_atom) {
>> -            SELPRINTF("Requested %s target got %s",
>> -                vdagent_x11_get_atom_name(x11, x11->conversion_req->target),
>> -                vdagent_x11_get_atom_name(x11, event->xselection.target));
>> -            len = -1;
>> -        }
>> -    }
>> -
>> -    selection = x11->conversion_req->selection;
>> -    type = vdagent_x11_target_to_type(x11, selection,
>> -                                      x11->conversion_req->target);
>> -    if (type == VD_AGENT_CLIPBOARD_NONE)
>> -        SELPRINTF("internal error conversion_req has bad target %s",
>> -                  vdagent_x11_get_atom_name(x11, x11->conversion_req->target));
>> -    if (len == 0) { /* No errors so far */
>> -        len = vdagent_x11_get_selection(x11, event, selection,
>> -                                        x11->conversion_req->target,
>> -                                        clip, 8, &data, incr);
>> -        if (len == 0) { /* waiting for more data? */
>> -            return;
>> -        }
>> -    }
>> -    if (len == -1) {
>> -        type = VD_AGENT_CLIPBOARD_NONE;
>> -        len = 0;
>> -    }
>> -
>> -    udscs_write(x11->vdagentd, VDAGENTD_CLIPBOARD_DATA, selection, type,
>> -                data, len);
>> -    vdagent_x11_get_selection_free(x11, data, incr);
>> -
>> -    vdagent_x11_next_conversion_request(x11);
>> -    vdagent_x11_handle_conversion_request(x11);
>> -}
>> -
>> -static Atom atom_lists_overlap(Atom *atoms1, Atom *atoms2, int l1, int l2)
>> -{
>> -    int i, j;
>> -
>> -    for (i = 0; i < l1; i++)
>> -        for (j = 0; j < l2; j++)
>> -            if (atoms1[i] == atoms2[j])
>> -                return atoms1[i];
>> -
>> -    return 0;
>> -}
>> -
>> -static void vdagent_x11_print_targets(struct vdagent_x11 *x11,
>> -    uint8_t selection, const char *action, Atom *atoms, int c)
>> -{
>> -    int i;
>> -    VSELPRINTF("%s %d targets:", action, c);
>> -    for (i = 0; i < c; i++)
>> -        VSELPRINTF("%s", vdagent_x11_get_atom_name(x11, atoms[i]));
>> -}
>> -
>> -static void vdagent_x11_handle_targets_notify(struct vdagent_x11 *x11,
>> -                                              XEvent *event)
>> -{
>> -    int i, len;
>> -    Atom atom, *atoms = NULL;
>> -    uint8_t selection;
>> -    int *type_count;
>> -
>> -    if (vdagent_x11_get_clipboard_selection(x11, event, &selection)) {
>> -        return;
>> -    }
>> -
>> -    if (!x11->expected_targets_notifies[selection]) {
>> -        SELPRINTF("unexpected selection notify TARGETS");
>> -        return;
>> -    }
>> -
>> -    x11->expected_targets_notifies[selection]--;
>> -
>> -    /* If we have more targets_notifies pending, ignore this one, we
>> -       are only interested in the targets list of the current owner
>> -       (which is the last one we've requested a targets list from) */
>> -    if (x11->expected_targets_notifies[selection]) {
>> -        return;
>> -    }
>> -
>> -    len = vdagent_x11_get_selection(x11, event, selection,
>> -                                    XA_ATOM, x11->targets_atom, 32,
>> -                                    (unsigned char **)&atoms, 0);
>> -    if (len == 0 || len == -1) /* waiting for more data or error? */
>> -        return;
>> -
>> -    /* bytes -> atoms */
>> -    len /= sizeof(Atom);
>> -    vdagent_x11_print_targets(x11, selection, "received", atoms, len);
>> -
>> -    type_count = &x11->clipboard_type_count[selection];
>> -    *type_count = 0;
>> -    for (i = 0; i < clipboard_format_count; i++) {
>> -        atom = atom_lists_overlap(x11->clipboard_formats[i].atoms, atoms,
>> -                                  x11->clipboard_formats[i].atom_count, len);
>> -        if (atom) {
>> -            x11->clipboard_agent_types[selection][*type_count] =
>> -                x11->clipboard_formats[i].type;
>> -            x11->clipboard_x11_targets[selection][*type_count] = atom;
>> -            (*type_count)++;
>> -            if (*type_count ==
>> -                    sizeof(x11->clipboard_agent_types[0])/sizeof(uint32_t)) {
>> -                SELPRINTF("handle_targets_notify: too many types");
>> -                break;
>> -            }
>> -        }
>> -    }
>> -
>> -    if (*type_count) {
>> -        udscs_write(x11->vdagentd, VDAGENTD_CLIPBOARD_GRAB, selection, 0,
>> -                    (uint8_t *)x11->clipboard_agent_types[selection],
>> -                    *type_count * sizeof(uint32_t));
>> -        vdagent_x11_set_clipboard_owner(x11, selection, owner_guest);
>> -    }
>> -
>> -    vdagent_x11_get_selection_free(x11, (unsigned char *)atoms, 0);
>> -}
>> -
>> -static void vdagent_x11_send_selection_notify(struct vdagent_x11 *x11,
>> -    Atom prop, struct vdagent_x11_selection_request *request)
>> -{
>> -    XEvent res, *event;
>> -
>> -    if (request) {
>> -        event = &request->event;
>> -    } else {
>> -        event = &x11->selection_req->event;
>> -    }
>> -
>> -    res.xselection.property = prop;
>> -    res.xselection.type = SelectionNotify;
>> -    res.xselection.display = event->xselectionrequest.display;
>> -    res.xselection.requestor = event->xselectionrequest.requestor;
>> -    res.xselection.selection = event->xselectionrequest.selection;
>> -    res.xselection.target = event->xselectionrequest.target;
>> -    res.xselection.time = event->xselectionrequest.time;
>> -
>> -    vdagent_x11_set_error_handler(x11, vdagent_x11_ignore_bad_window_handler);
>> -    XSendEvent(x11->display, event->xselectionrequest.requestor, 0, 0, &res);
>> -    vdagent_x11_restore_error_handler(x11);
>> -
>> -    if (!request) {
>> -        vdagent_x11_next_selection_request(x11);
>> -        vdagent_x11_handle_selection_request(x11);
>> -    }
>> -}
>> -
>> -static void vdagent_x11_send_targets(struct vdagent_x11 *x11,
>> -    uint8_t selection, XEvent *event)
>> -{
>> -    Atom prop, targets[256] = { x11->targets_atom, };
>> -    int i, j, k, target_count = 1;
>> -
>> -    for (i = 0; i < x11->clipboard_type_count[selection]; i++) {
>> -        for (j = 0; j < clipboard_format_count; j++) {
>> -            if (x11->clipboard_formats[j].type !=
>> -                    x11->clipboard_agent_types[selection][i])
>> -                continue;
>> -
>> -            for (k = 0; k < x11->clipboard_formats[j].atom_count; k++) {
>> -                targets[target_count] = x11->clipboard_formats[j].atoms[k];
>> -                target_count++;
>> -                if (target_count == sizeof(targets)/sizeof(Atom)) {
>> -                    SELPRINTF("send_targets: too many targets");
>> -                    goto exit_loop;
>> -                }
>> -            }
>> -        }
>> -    }
>> -exit_loop:
>> -
>> -    prop = event->xselectionrequest.property;
>> -    if (prop == None)
>> -        prop = event->xselectionrequest.target;
>> -
>> -    vdagent_x11_set_error_handler(x11, vdagent_x11_ignore_bad_window_handler);
>> -    XChangeProperty(x11->display, event->xselectionrequest.requestor, prop,
>> -                    XA_ATOM, 32, PropModeReplace, (unsigned char *)&targets,
>> -                    target_count);
>> -    if (vdagent_x11_restore_error_handler(x11) == 0) {
>> -        vdagent_x11_print_targets(x11, selection, "sent",
>> -                                  targets, target_count);
>> -        vdagent_x11_send_selection_notify(x11, prop, NULL);
>> -    } else
>> -        SELPRINTF("send_targets: Failed to sent, requestor window gone");
>> -}
>> -
>> -static void vdagent_x11_handle_selection_request(struct vdagent_x11 *x11)
>> -{
>> -    XEvent *event;
>> -    uint32_t type = VD_AGENT_CLIPBOARD_NONE;
>> -    uint8_t selection;
>> -
>> -    if (!x11->selection_req)
>> -        return;
>> -
>> -    event = &x11->selection_req->event;
>> -    selection = x11->selection_req->selection;
>> -
>> -    if (x11->clipboard_owner[selection] != owner_client) {
>> -        SELPRINTF("received selection request event for target %s, "
>> -                  "while not owning client clipboard",
>> -            vdagent_x11_get_atom_name(x11, event->xselectionrequest.target));
>> -        vdagent_x11_send_selection_notify(x11, None, NULL);
>> -        return;
>> -    }
>> -
>> -    if (event->xselectionrequest.target == x11->multiple_atom) {
>> -        SELPRINTF("multiple target not supported");
>> -        vdagent_x11_send_selection_notify(x11, None, NULL);
>> -        return;
>> -    }
>> -
>> -    if (event->xselectionrequest.target == x11->timestamp_atom) {
>> -        /* TODO: use more accurate selection time */
>> -        guint32 timestamp = event->xselectionrequest.time;
>> -
>> -        XChangeProperty(x11->display, event->xselectionrequest.requestor,
>> -                       event->xselectionrequest.property,
>> -                        event->xselectionrequest.target, 32, PropModeReplace,
>> -                        (guint8*)&timestamp, 1);
>> -        vdagent_x11_send_selection_notify(x11,
>> -                       event->xselectionrequest.property, NULL);
>> -       return;
>> -    }
>> -
>> -
>> -    if (event->xselectionrequest.target == x11->targets_atom) {
>> -        vdagent_x11_send_targets(x11, selection, event);
>> -        return;
>> -    }
>> -
>> -    type = vdagent_x11_target_to_type(x11, selection,
>> -                                      event->xselectionrequest.target);
>> -    if (type == VD_AGENT_CLIPBOARD_NONE) {
>> -        VSELPRINTF("guest app requested a non-advertised target");
>> -        vdagent_x11_send_selection_notify(x11, None, NULL);
>> -        return;
>> -    }
>> -
>> -    udscs_write(x11->vdagentd, VDAGENTD_CLIPBOARD_REQUEST, selection, type,
>> -                NULL, 0);
>> -}
>> -
>> -static void vdagent_x11_handle_property_delete_notify(struct vdagent_x11 *x11,
>> -                                                      XEvent *del_event)
>> -{
>> -    XEvent *sel_event;
>> -    int len;
>> -    uint8_t selection;
>> -
>> -    assert(x11->selection_req);
>> -    sel_event = &x11->selection_req->event;
>> -    selection = x11->selection_req->selection;
>> -    if (del_event->xproperty.window != sel_event->xselectionrequest.requestor
>> -            || del_event->xproperty.atom != x11->selection_req_atom) {
>> -        return;
>> -    }
>> -
>> -    len = x11->selection_req_data_size - x11->selection_req_data_pos;
>> -    if (len > x11->max_prop_size) {
>> -        len = x11->max_prop_size;
>> -    }
>> -
>> -    if (len) {
>> -        VSELPRINTF("Sending %d-%d/%d bytes of clipboard data",
>> -                x11->selection_req_data_pos,
>> -                x11->selection_req_data_pos + len - 1,
>> -                x11->selection_req_data_size);
>> -    } else {
>> -        VSELPRINTF("Ending incr send of clipboard data");
>> -    }
>> -    vdagent_x11_set_error_handler(x11, vdagent_x11_ignore_bad_window_handler);
>> -    XChangeProperty(x11->display, sel_event->xselectionrequest.requestor,
>> -                    x11->selection_req_atom,
>> -                    sel_event->xselectionrequest.target, 8, PropModeReplace,
>> -                    x11->selection_req_data + x11->selection_req_data_pos,
>> -                    len);
>> -    if (vdagent_x11_restore_error_handler(x11)) {
>> -        SELPRINTF("incr sent failed, requestor window gone");
>> -        len = 0;
>> -    }
>> -
>> -    x11->selection_req_data_pos += len;
>> -
>> -    /* Note we must explicitly send a 0 sized XChangeProperty to signal the
>> -       incr transfer is done. Hence we do not check if we've send all data
>> -       but instead check we've send the final 0 sized XChangeProperty. */
>> -    if (len == 0) {
>> -        free(x11->selection_req_data);
>> -        x11->selection_req_data = NULL;
>> -        x11->selection_req_data_pos = 0;
>> -        x11->selection_req_data_size = 0;
>> -        x11->selection_req_atom = None;
>> -        vdagent_x11_next_selection_request(x11);
>> -        vdagent_x11_handle_selection_request(x11);
>> -    }
>> -}
>> -
>> -void vdagent_x11_clipboard_request(struct vdagent_x11 *x11,
>> -        uint8_t selection, uint32_t type)
>> -{
>> -    Atom target, clip;
>> -    struct vdagent_x11_conversion_request *req, *new_req;
>> -
>> -    /* We don't use clip here, but we call get_clipboard_atom to verify
>> -       selection is valid */
>> -    if (vdagent_x11_get_clipboard_atom(x11, selection, &clip)) {
>> -        goto none;
>> -    }
>> -
>> -    if (x11->clipboard_owner[selection] != owner_guest) {
>> -        SELPRINTF("received clipboard req while not owning guest clipboard");
>> -        goto none;
>> -    }
>> -
>> -    target = vdagent_x11_type_to_target(x11, selection, type);
>> -    if (target == None) {
>> -        goto none;
>> -    }
>> -
>> -    new_req = malloc(sizeof(*new_req));
>> -    if (!new_req) {
>> -        SELPRINTF("out of memory on client clipboard request, ignoring.");
>> -        return;
>> -    }
>> -
>> -    new_req->target = target;
>> -    new_req->selection = selection;
>> -    new_req->next = NULL;
>> -
>> -    if (!x11->conversion_req) {
>> -        x11->conversion_req = new_req;
>> -        vdagent_x11_handle_conversion_request(x11);
>> -        /* Flush output buffers and consume any pending events */
>> -        vdagent_x11_do_read(x11);
>> -        return;
>> -    }
>> -
>> -    /* maybe we should limit the conversion_request stack depth ? */
>> -    req = x11->conversion_req;
>> -    while (req->next)
>> -        req = req->next;
>> -
>> -    req->next = new_req;
>> -    return;
>> -
>> -none:
>> -    udscs_write(x11->vdagentd, VDAGENTD_CLIPBOARD_DATA,
>> -                selection, VD_AGENT_CLIPBOARD_NONE, NULL, 0);
>> -}
>> -
>> -void vdagent_x11_clipboard_grab(struct vdagent_x11 *x11, uint8_t selection,
>> -    uint32_t *types, uint32_t type_count)
>> -{
>> -    Atom clip = None;
>> -
>> -    if (vdagent_x11_get_clipboard_atom(x11, selection, &clip)) {
>> -        return;
>> -    }
>> -
>> -    if (type_count > sizeof(x11->clipboard_agent_types[0])/sizeof(uint32_t)) {
>> -        SELPRINTF("x11_clipboard_grab: too many types");
>> -        type_count = sizeof(x11->clipboard_agent_types[0])/sizeof(uint32_t);
>> -    }
>> -
>> -    memcpy(x11->clipboard_agent_types[selection], types,
>> -           type_count * sizeof(uint32_t));
>> -    x11->clipboard_type_count[selection] = type_count;
>> -
>> -    XSetSelectionOwner(x11->display, clip,
>> -                       x11->selection_window, CurrentTime);
>> -    vdagent_x11_set_clipboard_owner(x11, selection, owner_client);
>> -
>> -    /* Flush output buffers and consume any pending events */
>> -    vdagent_x11_do_read(x11);
>> -}
>> -
>> -void vdagent_x11_clipboard_data(struct vdagent_x11 *x11, uint8_t selection,
>> -    uint32_t type, uint8_t *data, uint32_t size)
>> -{
>> -    Atom prop;
>> -    XEvent *event;
>> -    uint32_t type_from_event;
>> -
>> -    if (x11->selection_req_data) {
>> -        if (type || size) {
>> -            SELPRINTF("received clipboard data while still sending"
>> -                      " data from previous request, ignoring");
>> -        }
>> -        return;
>> -    }
>> -
>> -    if (!x11->selection_req) {
>> -        if (type || size) {
>> -            SELPRINTF("received clipboard data without an "
>> -                      "outstanding selection request, ignoring");
>> -        }
>> -        return;
>> -    }
>> -
>> -    event = &x11->selection_req->event;
>> -    type_from_event = vdagent_x11_target_to_type(x11,
>> -                                             x11->selection_req->selection,
>> -                                             event->xselectionrequest.target);
>> -    if (type_from_event != type ||
>> -            selection != x11->selection_req->selection) {
>> -        if (selection != x11->selection_req->selection) {
>> -            SELPRINTF("expecting data for selection %d got %d",
>> -                      (int)x11->selection_req->selection, (int)selection);
>> -        }
>> -        if (type_from_event != type) {
>> -            SELPRINTF("expecting type %u clipboard data got %u",
>> -                      type_from_event, type);
>> -        }
>> -        vdagent_x11_send_selection_notify(x11, None, NULL);
>> -
>> -        /* Flush output buffers and consume any pending events */
>> -        vdagent_x11_do_read(x11);
>> -        return;
>> -    }
>> -
>> -    prop = event->xselectionrequest.property;
>> -    if (prop == None)
>> -        prop = event->xselectionrequest.target;
>> -
>> -    if (size > x11->max_prop_size) {
>> -        unsigned long len = size;
>> -        VSELPRINTF("Starting incr send of clipboard data");
>> -
>> -        vdagent_x11_set_error_handler(x11, vdagent_x11_ignore_bad_window_handler);
>> -        XSelectInput(x11->display, event->xselectionrequest.requestor,
>> -                     PropertyChangeMask);
>> -        XChangeProperty(x11->display, event->xselectionrequest.requestor, prop,
>> -                        x11->incr_atom, 32, PropModeReplace,
>> -                        (unsigned char*)&len, 1);
>> -        if (vdagent_x11_restore_error_handler(x11) == 0) {
>> -            /* duplicate data */
>> -            x11->selection_req_data = malloc(size);
>> -            if (x11->selection_req_data != NULL) {
>> -                memcpy(x11->selection_req_data, data, size);
>> -                x11->selection_req_data_pos = 0;
>> -                x11->selection_req_data_size = size;
>> -                x11->selection_req_atom = prop;
>> -                vdagent_x11_send_selection_notify(x11, prop, x11->selection_req);
>> -            } else {
>> -                SELPRINTF("out of memory allocating selection buffer");
>> -            }
>> -        } else {
>> -            SELPRINTF("clipboard data sent failed, requestor window gone");
>> -        }
>> -    } else {
>> -        vdagent_x11_set_error_handler(x11, vdagent_x11_ignore_bad_window_handler);
>> -        XChangeProperty(x11->display, event->xselectionrequest.requestor, prop,
>> -                        event->xselectionrequest.target, 8, PropModeReplace,
>> -                        data, size);
>> -        if (vdagent_x11_restore_error_handler(x11) == 0)
>> -            vdagent_x11_send_selection_notify(x11, prop, NULL);
>> -        else
>> -            SELPRINTF("clipboard data sent failed, requestor window gone");
>> -    }
>> -
>> -    /* Flush output buffers and consume any pending events */
>> -    vdagent_x11_do_read(x11);
>> -}
>> -
>> -void vdagent_x11_clipboard_release(struct vdagent_x11 *x11, uint8_t selection)
>> -{
>> -    XEvent event;
>> -    Atom clip = None;
>> -
>> -    if (vdagent_x11_get_clipboard_atom(x11, selection, &clip)) {
>> -        return;
>> -    }
>> -
>> -    if (x11->clipboard_owner[selection] != owner_client) {
>> -        VSELPRINTF("received release while not owning client clipboard");
>> -        return;
>> -    }
>> -
>> -    XSetSelectionOwner(x11->display, clip, None, CurrentTime);
>> -    /* Make sure we process the XFixesSetSelectionOwnerNotify event caused
>> -       by this, so we don't end up changing the clipboard owner to none, after
>> -       it has already been re-owned because this event is still pending. */
>> -    XSync(x11->display, False);
>> -    while (XCheckTypedEvent(x11->display, x11->xfixes_event_base,
>> -                            &event))
>> -        vdagent_x11_handle_event(x11, event);
>> -
>> -    /* Note no need to do a set_clipboard_owner(owner_none) here, as that is
>> -       already done by processing the XFixesSetSelectionOwnerNotify event. */
>> -
>> -    /* Flush output buffers and consume any pending events */
>> -    vdagent_x11_do_read(x11);
>> -}
>> -
>> -void vdagent_x11_client_disconnected(struct vdagent_x11 *x11)
>> -{
>> -    int sel;
>> -
>> -    for (sel = 0; sel < VD_AGENT_CLIPBOARD_SELECTION_SECONDARY; sel++) {
>> -        if (x11->clipboard_owner[sel] == owner_client)
>> -            vdagent_x11_clipboard_release(x11, sel);
>> -    }
>> -}
>> -
>>  /* Function used to determine the default location to save file-xfers,
>>     xdg desktop dir or xdg download dir. We err on the safe side and use a
>>     whitelist approach, so any unknown desktop will end up with saving
>> diff --git a/src/vdagent/x11.h b/src/vdagent/x11.h
>> index a8ceb08..6ad09c2 100644
>> --- a/src/vdagent/x11.h
>> +++ b/src/vdagent/x11.h
>> @@ -38,16 +38,6 @@ void vdagent_x11_do_read(struct vdagent_x11 *x11);
>>  void vdagent_x11_set_monitor_config(struct vdagent_x11 *x11,
>>      VDAgentMonitorsConfig *mon_config, int fallback);
>>
>> -void vdagent_x11_clipboard_grab(struct vdagent_x11 *x11, uint8_t selection,
>> -    uint32_t *types, uint32_t type_count);
>> -void vdagent_x11_clipboard_request(struct vdagent_x11 *x11,
>> -    uint8_t selection, uint32_t type);
>> -void vdagent_x11_clipboard_data(struct vdagent_x11 *x11, uint8_t selection,
>> -    uint32_t type, uint8_t *data, uint32_t size);
>> -void vdagent_x11_clipboard_release(struct vdagent_x11 *x11, uint8_t selection);
>> -
>> -void vdagent_x11_client_disconnected(struct vdagent_x11 *x11);
>> -
>>  int vdagent_x11_has_icons_on_desktop();
>>
>>  #endif
>> --
>> 2.14.3
>>
>> _______________________________________________
>> Spice-devel mailing list
>> Spice-devel at lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/spice-devel
>
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/spice-devel
>


More information about the Spice-devel mailing list