[RFC,spice-vdagent,4/8] build: make GTK+ mandatory

Submitted by =?UTF-8?q?Jakub=20Jank=C5=AF?= on May 31, 2018, 8:52 p.m.

Details

Message ID 20180531205225.4266-5-jjanku@redhat.com
State New
Headers show
Series "Clipboard - using MIME types" ( rev: 1 ) in Spice

Not browsing as part of any series.

Commit Message

=?UTF-8?q?Jakub=20Jank=C5=AF?= May 31, 2018, 8:52 p.m.
Use GTK+ instead of Xlib where possible,
remove Xlib code that handles clipboard.
---
 configure.ac            |   13 +-
 src/vdagent/clipboard.c |   49 +-
 src/vdagent/clipboard.h |    4 +-
 src/vdagent/vdagent.c   |   14 +-
 src/vdagent/x11-priv.h  |   94 ----
 src/vdagent/x11.c       | 1177 +--------------------------------------
 src/vdagent/x11.h       |   18 +-
 7 files changed, 21 insertions(+), 1348 deletions(-)

Patch hide | download patch | download mbox

diff --git a/configure.ac b/configure.ac
index 89f617c..1eb17a9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -75,16 +75,6 @@  if test "x$init_systemd" = "xyes"; then
   fi
 fi
 
-AC_ARG_WITH([gtk],
-            [AS_HELP_STRING([--with-gtk], [Use GTK+ instead of Xlib])],
-            [],
-            [with_gtk="auto"])
-if test "x$with_gtk" != "xno"; then
-  PKG_CHECK_MODULES([GTK], [gtk+-3.0 >= 3.10],
-                    [AC_DEFINE([WITH_GTK], [1], [If defined, vdagent will favor GTK+ over Xlib])],
-                    [AS_IF([test "x$with_gtk" = "xyes"], [AC_MSG_ERROR([GTK+ requested but not found])])])
-fi
-
 AC_ARG_ENABLE([pciaccess],
               [AS_HELP_STRING([--enable-pciaccess], [Enable libpciaccess use for auto generation of Xinerama xorg.conf (default: yes)])],
               [enable_pciaccess="$enableval"],
@@ -96,6 +86,7 @@  AC_ARG_ENABLE([static-uinput],
               [enable_static_uinput="no"])
 
 PKG_CHECK_MODULES([GLIB2], [glib-2.0 >= 2.34])
+PKG_CHECK_MODULES([GTK], [gtk+-3.0 >= 3.10])
 PKG_CHECK_MODULES(X, [xfixes xrandr >= 1.3 xinerama x11])
 PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.12.13])
 PKG_CHECK_MODULES(ALSA, [alsa >= 1.0.22])
@@ -219,8 +210,6 @@  AC_MSG_NOTICE([
         install systemd service:  ${init_systemd}
         udevdir:                  ${udevdir}
 
-        use GTK+:                 ${with_gtk}
-
         Now type 'make' to build $PACKAGE
 
 ])
diff --git a/src/vdagent/clipboard.c b/src/vdagent/clipboard.c
index 667c168..101e535 100644
--- a/src/vdagent/clipboard.c
+++ b/src/vdagent/clipboard.c
@@ -20,17 +20,14 @@ 
 # include <config.h>
 #endif
 
-#ifdef WITH_GTK
-# include <gtk/gtk.h>
-# include <syslog.h>
+#include <gtk/gtk.h>
+#include <syslog.h>
 
-# include "vdagentd-proto.h"
-# include "spice/vd_agent.h"
-#endif
+#include "vdagentd-proto.h"
+#include "spice/vd_agent.h"
 
 #include "clipboard.h"
 
-#ifdef WITH_GTK
 /* 2 selections supported - _SELECTION_CLIPBOARD = 0, _SELECTION_PRIMARY = 1 */
 #define SELECTION_COUNT (VD_AGENT_CLIPBOARD_SELECTION_PRIMARY + 1)
 #define TYPE_COUNT      (VD_AGENT_CLIPBOARD_IMAGE_JPG + 1)
@@ -59,18 +56,12 @@  typedef struct {
 
     GdkAtom       targets[TYPE_COUNT];
 } Selection;
-#endif
 
 struct VDAgentClipboards {
-#ifdef WITH_GTK
     struct udscs_connection *conn;
     Selection                selections[SELECTION_COUNT];
-#else
-    struct vdagent_x11 *x11;
-#endif
 };
 
-#ifdef WITH_GTK
 static const struct {
     guint         type;
     const gchar  *atom_name;
@@ -298,14 +289,10 @@  static void clipboard_clear_cb(GtkClipboard *clipboard, gpointer user_data)
     VDAgentClipboards *c = user_data;
     clipboard_new_owner(c, sel_id_from_clip(clipboard), OWNER_NONE);
 }
-#endif
 
 void vdagent_clipboard_grab(VDAgentClipboards *c, guint sel_id,
                             guint32 *types, guint n_types)
 {
-#ifndef WITH_GTK
-    vdagent_x11_clipboard_grab(c->x11, sel_id, types, n_types);
-#else
     GtkTargetEntry targets[G_N_ELEMENTS(atom2agent)];
     guint n_targets, i, t;
 
@@ -333,15 +320,11 @@  void vdagent_clipboard_grab(VDAgentClipboards *c, guint sel_id,
         syslog(LOG_ERR, "%s: sel_id=%u: clipboard grab failed", __func__, sel_id);
         clipboard_new_owner(c, sel_id, OWNER_NONE);
     }
-#endif
 }
 
 void vdagent_clipboard_data(VDAgentClipboards *c, guint sel_id,
                             guint type, guchar *data, guint size)
 {
-#ifndef WITH_GTK
-    vdagent_x11_clipboard_data(c->x11, sel_id, type, data, size);
-#else
     g_return_if_fail(sel_id < SELECTION_COUNT);
     Selection *sel = &c->selections[sel_id];
     AppRequest *req;
@@ -364,28 +347,20 @@  void vdagent_clipboard_data(VDAgentClipboards *c, guint sel_id,
                            8, data, size);
 
     g_main_loop_quit(req->loop);
-#endif
 }
 
 void vdagent_clipboard_release(VDAgentClipboards *c, guint sel_id)
 {
-#ifndef WITH_GTK
-    vdagent_x11_clipboard_release(c->x11, sel_id);
-#else
     g_return_if_fail(sel_id < SELECTION_COUNT);
     if (c->selections[sel_id].owner != OWNER_CLIENT)
         return;
 
     clipboard_new_owner(c, sel_id, OWNER_NONE);
     gtk_clipboard_clear(c->selections[sel_id].clipboard);
-#endif
 }
 
 void vdagent_clipboards_release_all(VDAgentClipboards *c)
 {
-#ifndef WITH_GTK
-    vdagent_x11_client_disconnected(c->x11);
-#else
     guint sel_id, owner;
 
     for (sel_id = 0; sel_id < SELECTION_COUNT; sel_id++) {
@@ -396,14 +371,10 @@  void vdagent_clipboards_release_all(VDAgentClipboards *c)
         else if (owner == OWNER_GUEST && c->conn)
             udscs_write(c->conn, VDAGENTD_CLIPBOARD_RELEASE, sel_id, 0, NULL, 0);
     }
-#endif
 }
 
 void vdagent_clipboard_request(VDAgentClipboards *c, guint sel_id, guint type)
 {
-#ifndef WITH_GTK
-    vdagent_x11_clipboard_request(c->x11, sel_id, type);
-#else
     Selection *sel;
 
     if (sel_id >= SELECTION_COUNT)
@@ -428,25 +399,18 @@  void vdagent_clipboard_request(VDAgentClipboards *c, guint sel_id, guint type)
 err:
     udscs_write(c->conn, VDAGENTD_CLIPBOARD_DATA, sel_id,
                 VD_AGENT_CLIPBOARD_NONE, NULL, 0);
-#endif
 }
 
-VDAgentClipboards *vdagent_clipboards_init(struct vdagent_x11      *x11,
-                                           struct udscs_connection *conn)
+VDAgentClipboards *vdagent_clipboards_init(struct udscs_connection *conn)
 {
-#ifdef WITH_GTK
     guint sel_id;
     const GdkAtom sel_atom[SELECTION_COUNT] = {
         GDK_SELECTION_CLIPBOARD, /* VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD */
         GDK_SELECTION_PRIMARY,   /* VD_AGENT_CLIPBOARD_SELECTION_PRIMARY */
     };
-#endif
 
     VDAgentClipboards *c;
     c = g_new0(VDAgentClipboards, 1);
-#ifndef WITH_GTK
-    c->x11 = x11;
-#else
     c->conn = conn;
 
     for (sel_id = 0; sel_id < SELECTION_COUNT; sel_id++) {
@@ -458,14 +422,12 @@  VDAgentClipboards *vdagent_clipboards_init(struct vdagent_x11      *x11,
         g_signal_connect(G_OBJECT(clipboard), "owner-change",
                          G_CALLBACK(clipboard_owner_change_cb), c);
     }
-#endif
 
     return c;
 }
 
 void vdagent_clipboards_finalize(VDAgentClipboards *c, gboolean conn_alive)
 {
-#ifdef WITH_GTK
     guint sel_id;
     for (sel_id = 0; sel_id < SELECTION_COUNT; sel_id++)
         g_signal_handlers_disconnect_by_func(c->selections[sel_id].clipboard,
@@ -474,7 +436,6 @@  void vdagent_clipboards_finalize(VDAgentClipboards *c, gboolean conn_alive)
     if (conn_alive == FALSE)
         c->conn = NULL;
     vdagent_clipboards_release_all(c);
-#endif
 
     g_free(c);
 }
diff --git a/src/vdagent/clipboard.h b/src/vdagent/clipboard.h
index f819b49..e007a37 100644
--- a/src/vdagent/clipboard.h
+++ b/src/vdagent/clipboard.h
@@ -21,13 +21,11 @@ 
 
 #include <glib.h>
 
-#include "x11.h"
 #include "udscs.h"
 
 typedef struct VDAgentClipboards VDAgentClipboards;
 
-VDAgentClipboards *vdagent_clipboards_init(struct vdagent_x11      *x11,
-                                           struct udscs_connection *conn);
+VDAgentClipboards *vdagent_clipboards_init(struct udscs_connection *conn);
 void vdagent_clipboards_finalize(VDAgentClipboards *c, gboolean conn_alive);
 
 void vdagent_clipboard_request(VDAgentClipboards *c, guint sel_id, guint type);
diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c
index 3f8ef31..711e4f8 100644
--- a/src/vdagent/vdagent.c
+++ b/src/vdagent/vdagent.c
@@ -36,9 +36,7 @@ 
 #include <spice/vd_agent.h>
 #include <poll.h>
 #include <glib-unix.h>
-#ifdef WITH_GTK
-# include <gtk/gtk.h>
-#endif
+#include <gtk/gtk.h>
 
 #include "udscs.h"
 #include "vdagentd-proto.h"
@@ -113,7 +111,7 @@  static const gchar *xfer_get_download_directory(VDAgent *agent)
         return fx_dir;
     }
 
-    return g_get_user_special_dir(vdagent_x11_has_icons_on_desktop(agent->x11) ?
+    return g_get_user_special_dir(vdagent_x11_has_icons_on_desktop() ?
                                   G_USER_DIRECTORY_DESKTOP :
                                   G_USER_DIRECTORY_DOWNLOAD);
 }
@@ -143,7 +141,7 @@  static gboolean vdagent_init_file_xfer(VDAgent *agent)
     }
 
     open_dir = fx_open_dir == -1 ?
-               !vdagent_x11_has_icons_on_desktop(agent->x11) :
+               !vdagent_x11_has_icons_on_desktop() :
                fx_open_dir;
 
     agent->xfers = vdagent_file_xfers_create(agent->conn, xfer_dir,
@@ -391,7 +389,7 @@  static gboolean vdagent_init_async_cb(gpointer user_data)
     if (!vdagent_init_file_xfer(agent))
         syslog(LOG_WARNING, "File transfer is disabled");
 
-    agent->clipboards = vdagent_clipboards_init(agent->x11, agent->conn);
+    agent->clipboards = vdagent_clipboards_init(agent->conn);
 
     if (parent_socket != -1) {
         if (write(parent_socket, "OK", 2) != 2)
@@ -419,9 +417,7 @@  int main(int argc, char *argv[])
     g_option_context_set_summary(context,
                                  "\tSpice session guest agent: X11\n"
                                  "\tVersion: " VERSION);
-#ifdef WITH_GTK
     g_option_context_add_group(context, gtk_get_option_group(FALSE));
-#endif
     g_option_context_parse(context, &argc, &argv, &error);
     g_option_context_free(context);
 
@@ -449,10 +445,8 @@  int main(int argc, char *argv[])
     if (do_daemonize)
         parent_socket = daemonize();
 
-#ifdef WITH_GTK
     gdk_set_allowed_backends("x11");
     gtk_init(NULL, NULL);
-#endif
 
 reconnect:
     if (version_mismatch) {
diff --git a/src/vdagent/x11-priv.h b/src/vdagent/x11-priv.h
index e7c64bd..f341048 100644
--- a/src/vdagent/x11-priv.h
+++ b/src/vdagent/x11-priv.h
@@ -1,10 +1,6 @@ 
 #ifndef VDAGENT_X11_PRIV
 #define VDAGENT_X11_PRIV
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include <stdint.h>
 #include <stdio.h>
 
@@ -12,66 +8,6 @@ 
 
 #include <X11/extensions/Xrandr.h>
 
-#ifndef WITH_GTK
-/* 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)
-
-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;
-};
-
-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]))
-#endif
-
 #define MAX_SCREENS 16
 /* Same as qxl_dev.h client_monitors_config.heads count */
 #define MONITOR_SIZE_COUNT 64
@@ -83,36 +19,6 @@  struct monitor_size {
 
 struct vdagent_x11 {
     Display *display;
-#ifndef WITH_GTK
-    struct clipboard_format_info clipboard_formats[clipboard_format_count];
-    Atom clipboard_atom;
-    Atom clipboard_primary_atom;
-    Atom targets_atom;
-    Atom incr_atom;
-    Atom multiple_atom;
-    Atom timestamp_atom;
-    Window selection_window;
-    int has_xfixes;
-    int xfixes_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;
-#endif
     Window root_window[MAX_SCREENS];
     struct udscs_connection *vdagentd;
     int debug;
diff --git a/src/vdagent/x11.c b/src/vdagent/x11.c
index 0ea5668..a9ab699 100644
--- a/src/vdagent/x11.c
+++ b/src/vdagent/x11.c
@@ -36,12 +36,10 @@ 
 #endif
 
 #include <glib.h>
-#ifdef WITH_GTK
 #include <gdk/gdk.h>
 #ifdef GDK_WINDOWING_X11
 #include <gdk/gdkx.h>
 #endif
-#endif
 #include <stdlib.h>
 #include <limits.h>
 #include <string.h>
@@ -50,7 +48,6 @@ 
 #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"
@@ -59,52 +56,12 @@ 
 int (*vdagent_x11_prev_error_handler)(Display *, XErrorEvent *);
 int vdagent_x11_caught_error;
 
-#ifndef WITH_GTK
-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";
-    }
-}
-#endif
-
 static int vdagent_x11_debug_error_handler(
     Display *display, XErrorEvent *error)
 {
     abort();
 }
 
-#ifndef WITH_GTK
-/* 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);
-}
-#endif
-
 void vdagent_x11_set_error_handler(struct vdagent_x11 *x11,
     int (*handler)(Display *, XErrorEvent *))
 {
@@ -125,77 +82,15 @@  int vdagent_x11_restore_error_handler(struct vdagent_x11 *x11)
     return error;
 }
 
-static gchar *vdagent_x11_get_wm_name(struct vdagent_x11 *x11)
+static const gchar *vdagent_x11_get_wm_name()
 {
 #ifdef GDK_WINDOWING_X11
     GdkDisplay *display = gdk_display_get_default();
     if (GDK_IS_X11_DISPLAY(display))
-        return g_strdup(gdk_x11_screen_get_window_manager_name(
-            gdk_display_get_default_screen(display)));
-    return g_strdup("unsupported");
-#else
-    Atom type_ret;
-    int format_ret;
-    unsigned long len, remain;
-    unsigned char *data = NULL;
-    Window sup_window = None;
-    gchar *net_wm_name = NULL;
-
-    /* XGetWindowProperty can throw a BadWindow error. One way we can trigger
-       this is when the display-manager (ie gdm) has set, and not cleared the
-       _NET_SUPPORTING_WM_CHECK property, and the window manager running in
-       the user session has not yet updated it to point to its window, so its
-       pointing to a nonexistent window. */
-    vdagent_x11_set_error_handler(x11, vdagent_x11_ignore_bad_window_handler);
-
-    /* Get the window manager SUPPORTING_WM_CHECK window */
-    if (XGetWindowProperty(x11->display, x11->root_window[0],
-            XInternAtom(x11->display, "_NET_SUPPORTING_WM_CHECK", False), 0,
-            LONG_MAX, False, XA_WINDOW, &type_ret, &format_ret, &len,
-            &remain, &data) == Success) {
-        if (type_ret == XA_WINDOW)
-            sup_window = *((Window *)data);
-        XFree(data);
-    }
-    if (sup_window == None &&
-        XGetWindowProperty(x11->display, x11->root_window[0],
-            XInternAtom(x11->display, "_WIN_SUPPORTING_WM_CHECK", False), 0,
-            LONG_MAX, False, XA_CARDINAL, &type_ret, &format_ret, &len,
-            &remain, &data) == Success) {
-        if (type_ret == XA_CARDINAL)
-            sup_window = *((Window *)data);
-        XFree(data);
-    }
-    /* So that we can get the net_wm_name */
-    if (sup_window != None) {
-        Atom utf8 = XInternAtom(x11->display, "UTF8_STRING", False);
-        if (XGetWindowProperty(x11->display, sup_window,
-                XInternAtom(x11->display, "_NET_WM_NAME", False), 0,
-                LONG_MAX, False, utf8, &type_ret, &format_ret, &len,
-                &remain, &data) == Success) {
-            if (type_ret == utf8) {
-                net_wm_name = g_strndup((char *)data, (format_ret / 8) * len);
-            }
-            XFree(data);
-        }
-        if (net_wm_name == NULL &&
-            XGetWindowProperty(x11->display, sup_window,
-                XInternAtom(x11->display, "_NET_WM_NAME", False), 0,
-                LONG_MAX, False, XA_STRING, &type_ret, &format_ret, &len,
-                &remain, &data) == Success) {
-            if (type_ret == XA_STRING) {
-                net_wm_name = g_strndup((char *)data, (format_ret / 8) * len);
-            }
-            XFree(data);
-        }
-    }
-
-    vdagent_x11_restore_error_handler(x11);
-
-    if (net_wm_name == NULL)
-        return g_strdup("unknown");
-    return net_wm_name;
+        return gdk_x11_screen_get_window_manager_name(
+            gdk_display_get_default_screen(display));
 #endif
+    return "unsupported";
 }
 
 struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
@@ -203,12 +98,8 @@  struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
 {
     struct vdagent_x11 *x11;
     XWindowAttributes attrib;
-#ifdef WITH_GTK
     int i;
-#else
-    int i, j, major, minor;
-#endif
-    gchar *net_wm_name = NULL;
+    const gchar *net_wm_name;
 
     x11 = calloc(1, sizeof(*x11));
     if (!x11) {
@@ -243,61 +134,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);
-#ifndef WITH_GTK
-    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);
-#endif
 
     vdagent_x11_randr_init(x11);
 
-#ifndef WITH_GTK
-    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;
-#endif
-
     for (i = 0; i < x11->screen_count; i++) {
         /* Catch resolution changes */
         XSelectInput(x11->display, x11->root_window[i], StructureNotifyMask);
@@ -312,8 +151,7 @@  struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
     /* Since we are started at the same time as the wm,
        sometimes we need to wait a bit for the _NET_WM_NAME to show up. */
     for (i = 0; i < 9; i++) {
-        g_free(net_wm_name);
-        net_wm_name = vdagent_x11_get_wm_name(x11);
+        net_wm_name = vdagent_x11_get_wm_name();
         if (strcmp(net_wm_name, "unknown"))
             break;
         usleep(100000);
@@ -321,7 +159,6 @@  struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
     if (x11->debug)
         syslog(LOG_DEBUG, "%s: net_wm_name=\"%s\", has icons=%d",
                __func__, net_wm_name, vdagent_x11_has_icons_on_desktop(x11));
-    g_free(net_wm_name);
 
     /* Flush output buffers and consume any pending events */
     vdagent_x11_do_read(x11);
@@ -334,16 +171,6 @@  void vdagent_x11_destroy(struct vdagent_x11 *x11, int vdagentd_disconnected)
     if (!x11)
         return;
 
-#ifndef WITH_GTK
-    if (vdagentd_disconnected)
-        x11->vdagentd = NULL;
-
-    uint8_t sel;
-    for (sel = 0; sel < VD_AGENT_CLIPBOARD_SELECTION_SECONDARY; ++sel) {
-        vdagent_x11_set_clipboard_owner(x11, sel, owner_none);
-    }
-#endif
-
     XCloseDisplay(x11->display);
     free(x11->randr.failed_conf);
     free(x11);
@@ -354,194 +181,9 @@  int vdagent_x11_get_fd(struct vdagent_x11 *x11)
     return x11->fd;
 }
 
-#ifndef WITH_GTK
-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;
-}
-#endif
-
 static void vdagent_x11_handle_event(struct vdagent_x11 *x11, XEvent event)
 {
     int i, handled = 0;
-#ifndef WITH_GTK
-    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;
-    }
-#endif
 
     if (vdagent_x11_randr_handle_event(x11, event))
         return;
@@ -562,67 +204,6 @@  static void vdagent_x11_handle_event(struct vdagent_x11 *x11, XEvent event)
         /* These are uninteresting */
         handled = 1;
         break;
-#ifndef WITH_GTK
-    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;
-    }
-#endif
     }
     if (!handled && x11->debug)
         syslog(LOG_DEBUG, "unhandled x11 event, type %d, window %d",
@@ -639,749 +220,12 @@  void vdagent_x11_do_read(struct vdagent_x11 *x11)
     }
 }
 
-#ifndef WITH_GTK
-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);
-    }
-}
-#endif
-
 /* 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
    file-xfers to the xdg download dir, and opening the xdg download dir with
    xdg-open when the file-xfer completes. */
-int vdagent_x11_has_icons_on_desktop(struct vdagent_x11 *x11)
+int vdagent_x11_has_icons_on_desktop()
 {
     const char * const wms_with_icons_on_desktop[] = {
         "Metacity", /* GNOME-2 or GNOME-3 fallback */
@@ -1390,15 +234,12 @@  int vdagent_x11_has_icons_on_desktop(struct vdagent_x11 *x11)
         "Metacity (Marco)", /* Mate, newer */
         NULL
     };
-    gchar *net_wm_name = vdagent_x11_get_wm_name(x11);
+    const gchar *net_wm_name = vdagent_x11_get_wm_name();
     int i;
 
     for (i = 0; wms_with_icons_on_desktop[i]; i++)
-        if (!strcmp(net_wm_name, wms_with_icons_on_desktop[i])) {
-            g_free(net_wm_name);
+        if (!strcmp(net_wm_name, wms_with_icons_on_desktop[i]))
             return 1;
-        }
 
-    g_free(net_wm_name);
     return 0;
 }
diff --git a/src/vdagent/x11.h b/src/vdagent/x11.h
index 1505f58..6ad09c2 100644
--- a/src/vdagent/x11.h
+++ b/src/vdagent/x11.h
@@ -22,10 +22,6 @@ 
 #ifndef __VDAGENT_X11_H
 #define __VDAGENT_X11_H
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include <stdio.h>
 #include <spice/vd_agent.h>
 #include "udscs.h"
@@ -42,18 +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);
 
-#ifndef WITH_GTK
-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);
-#endif
-
-int vdagent_x11_has_icons_on_desktop(struct vdagent_x11 *x11);
+int vdagent_x11_has_icons_on_desktop();
 
 #endif

Comments

Hi,

On Thu, May 31, 2018 at 10:52:21PM +0200, Jakub Janků wrote:
> Use GTK+ instead of Xlib where possible,
> remove Xlib code that handles clipboard.

@teuf, double checking here if you think requiring gtk and
dropping xlib would be a problem.

With possible problems in mind I asked gtk to be optional at
build time for the 0.18.0 release but I don't see much point in
working in features in gtk and x11 so I'd say this is fine.

Cheers,
Victor

> ---
>  configure.ac            |   13 +-
>  src/vdagent/clipboard.c |   49 +-
>  src/vdagent/clipboard.h |    4 +-
>  src/vdagent/vdagent.c   |   14 +-
>  src/vdagent/x11-priv.h  |   94 ----
>  src/vdagent/x11.c       | 1177 +--------------------------------------
>  src/vdagent/x11.h       |   18 +-
>  7 files changed, 21 insertions(+), 1348 deletions(-)
> 
> diff --git a/configure.ac b/configure.ac
> index 89f617c..1eb17a9 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -75,16 +75,6 @@ if test "x$init_systemd" = "xyes"; then
>    fi
>  fi
>  
> -AC_ARG_WITH([gtk],
> -            [AS_HELP_STRING([--with-gtk], [Use GTK+ instead of Xlib])],
> -            [],
> -            [with_gtk="auto"])
> -if test "x$with_gtk" != "xno"; then
> -  PKG_CHECK_MODULES([GTK], [gtk+-3.0 >= 3.10],
> -                    [AC_DEFINE([WITH_GTK], [1], [If defined, vdagent will favor GTK+ over Xlib])],
> -                    [AS_IF([test "x$with_gtk" = "xyes"], [AC_MSG_ERROR([GTK+ requested but not found])])])
> -fi
> -
>  AC_ARG_ENABLE([pciaccess],
>                [AS_HELP_STRING([--enable-pciaccess], [Enable libpciaccess use for auto generation of Xinerama xorg.conf (default: yes)])],
>                [enable_pciaccess="$enableval"],
> @@ -96,6 +86,7 @@ AC_ARG_ENABLE([static-uinput],
>                [enable_static_uinput="no"])
>  
>  PKG_CHECK_MODULES([GLIB2], [glib-2.0 >= 2.34])
> +PKG_CHECK_MODULES([GTK], [gtk+-3.0 >= 3.10])
>  PKG_CHECK_MODULES(X, [xfixes xrandr >= 1.3 xinerama x11])
>  PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.12.13])
>  PKG_CHECK_MODULES(ALSA, [alsa >= 1.0.22])
> @@ -219,8 +210,6 @@ AC_MSG_NOTICE([
>          install systemd service:  ${init_systemd}
>          udevdir:                  ${udevdir}
>  
> -        use GTK+:                 ${with_gtk}
> -
>          Now type 'make' to build $PACKAGE
>  
>  ])
> diff --git a/src/vdagent/clipboard.c b/src/vdagent/clipboard.c
> index 667c168..101e535 100644
> --- a/src/vdagent/clipboard.c
> +++ b/src/vdagent/clipboard.c
> @@ -20,17 +20,14 @@
>  # include <config.h>
>  #endif
>  
> -#ifdef WITH_GTK
> -# include <gtk/gtk.h>
> -# include <syslog.h>
> +#include <gtk/gtk.h>
> +#include <syslog.h>
>  
> -# include "vdagentd-proto.h"
> -# include "spice/vd_agent.h"
> -#endif
> +#include "vdagentd-proto.h"
> +#include "spice/vd_agent.h"
>  
>  #include "clipboard.h"
>  
> -#ifdef WITH_GTK
>  /* 2 selections supported - _SELECTION_CLIPBOARD = 0, _SELECTION_PRIMARY = 1 */
>  #define SELECTION_COUNT (VD_AGENT_CLIPBOARD_SELECTION_PRIMARY + 1)
>  #define TYPE_COUNT      (VD_AGENT_CLIPBOARD_IMAGE_JPG + 1)
> @@ -59,18 +56,12 @@ typedef struct {
>  
>      GdkAtom       targets[TYPE_COUNT];
>  } Selection;
> -#endif
>  
>  struct VDAgentClipboards {
> -#ifdef WITH_GTK
>      struct udscs_connection *conn;
>      Selection                selections[SELECTION_COUNT];
> -#else
> -    struct vdagent_x11 *x11;
> -#endif
>  };
>  
> -#ifdef WITH_GTK
>  static const struct {
>      guint         type;
>      const gchar  *atom_name;
> @@ -298,14 +289,10 @@ static void clipboard_clear_cb(GtkClipboard *clipboard, gpointer user_data)
>      VDAgentClipboards *c = user_data;
>      clipboard_new_owner(c, sel_id_from_clip(clipboard), OWNER_NONE);
>  }
> -#endif
>  
>  void vdagent_clipboard_grab(VDAgentClipboards *c, guint sel_id,
>                              guint32 *types, guint n_types)
>  {
> -#ifndef WITH_GTK
> -    vdagent_x11_clipboard_grab(c->x11, sel_id, types, n_types);
> -#else
>      GtkTargetEntry targets[G_N_ELEMENTS(atom2agent)];
>      guint n_targets, i, t;
>  
> @@ -333,15 +320,11 @@ void vdagent_clipboard_grab(VDAgentClipboards *c, guint sel_id,
>          syslog(LOG_ERR, "%s: sel_id=%u: clipboard grab failed", __func__, sel_id);
>          clipboard_new_owner(c, sel_id, OWNER_NONE);
>      }
> -#endif
>  }
>  
>  void vdagent_clipboard_data(VDAgentClipboards *c, guint sel_id,
>                              guint type, guchar *data, guint size)
>  {
> -#ifndef WITH_GTK
> -    vdagent_x11_clipboard_data(c->x11, sel_id, type, data, size);
> -#else
>      g_return_if_fail(sel_id < SELECTION_COUNT);
>      Selection *sel = &c->selections[sel_id];
>      AppRequest *req;
> @@ -364,28 +347,20 @@ void vdagent_clipboard_data(VDAgentClipboards *c, guint sel_id,
>                             8, data, size);
>  
>      g_main_loop_quit(req->loop);
> -#endif
>  }
>  
>  void vdagent_clipboard_release(VDAgentClipboards *c, guint sel_id)
>  {
> -#ifndef WITH_GTK
> -    vdagent_x11_clipboard_release(c->x11, sel_id);
> -#else
>      g_return_if_fail(sel_id < SELECTION_COUNT);
>      if (c->selections[sel_id].owner != OWNER_CLIENT)
>          return;
>  
>      clipboard_new_owner(c, sel_id, OWNER_NONE);
>      gtk_clipboard_clear(c->selections[sel_id].clipboard);
> -#endif
>  }
>  
>  void vdagent_clipboards_release_all(VDAgentClipboards *c)
>  {
> -#ifndef WITH_GTK
> -    vdagent_x11_client_disconnected(c->x11);
> -#else
>      guint sel_id, owner;
>  
>      for (sel_id = 0; sel_id < SELECTION_COUNT; sel_id++) {
> @@ -396,14 +371,10 @@ void vdagent_clipboards_release_all(VDAgentClipboards *c)
>          else if (owner == OWNER_GUEST && c->conn)
>              udscs_write(c->conn, VDAGENTD_CLIPBOARD_RELEASE, sel_id, 0, NULL, 0);
>      }
> -#endif
>  }
>  
>  void vdagent_clipboard_request(VDAgentClipboards *c, guint sel_id, guint type)
>  {
> -#ifndef WITH_GTK
> -    vdagent_x11_clipboard_request(c->x11, sel_id, type);
> -#else
>      Selection *sel;
>  
>      if (sel_id >= SELECTION_COUNT)
> @@ -428,25 +399,18 @@ void vdagent_clipboard_request(VDAgentClipboards *c, guint sel_id, guint type)
>  err:
>      udscs_write(c->conn, VDAGENTD_CLIPBOARD_DATA, sel_id,
>                  VD_AGENT_CLIPBOARD_NONE, NULL, 0);
> -#endif
>  }
>  
> -VDAgentClipboards *vdagent_clipboards_init(struct vdagent_x11      *x11,
> -                                           struct udscs_connection *conn)
> +VDAgentClipboards *vdagent_clipboards_init(struct udscs_connection *conn)
>  {
> -#ifdef WITH_GTK
>      guint sel_id;
>      const GdkAtom sel_atom[SELECTION_COUNT] = {
>          GDK_SELECTION_CLIPBOARD, /* VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD */
>          GDK_SELECTION_PRIMARY,   /* VD_AGENT_CLIPBOARD_SELECTION_PRIMARY */
>      };
> -#endif
>  
>      VDAgentClipboards *c;
>      c = g_new0(VDAgentClipboards, 1);
> -#ifndef WITH_GTK
> -    c->x11 = x11;
> -#else
>      c->conn = conn;
>  
>      for (sel_id = 0; sel_id < SELECTION_COUNT; sel_id++) {
> @@ -458,14 +422,12 @@ VDAgentClipboards *vdagent_clipboards_init(struct vdagent_x11      *x11,
>          g_signal_connect(G_OBJECT(clipboard), "owner-change",
>                           G_CALLBACK(clipboard_owner_change_cb), c);
>      }
> -#endif
>  
>      return c;
>  }
>  
>  void vdagent_clipboards_finalize(VDAgentClipboards *c, gboolean conn_alive)
>  {
> -#ifdef WITH_GTK
>      guint sel_id;
>      for (sel_id = 0; sel_id < SELECTION_COUNT; sel_id++)
>          g_signal_handlers_disconnect_by_func(c->selections[sel_id].clipboard,
> @@ -474,7 +436,6 @@ void vdagent_clipboards_finalize(VDAgentClipboards *c, gboolean conn_alive)
>      if (conn_alive == FALSE)
>          c->conn = NULL;
>      vdagent_clipboards_release_all(c);
> -#endif
>  
>      g_free(c);
>  }
> diff --git a/src/vdagent/clipboard.h b/src/vdagent/clipboard.h
> index f819b49..e007a37 100644
> --- a/src/vdagent/clipboard.h
> +++ b/src/vdagent/clipboard.h
> @@ -21,13 +21,11 @@
>  
>  #include <glib.h>
>  
> -#include "x11.h"
>  #include "udscs.h"
>  
>  typedef struct VDAgentClipboards VDAgentClipboards;
>  
> -VDAgentClipboards *vdagent_clipboards_init(struct vdagent_x11      *x11,
> -                                           struct udscs_connection *conn);
> +VDAgentClipboards *vdagent_clipboards_init(struct udscs_connection *conn);
>  void vdagent_clipboards_finalize(VDAgentClipboards *c, gboolean conn_alive);
>  
>  void vdagent_clipboard_request(VDAgentClipboards *c, guint sel_id, guint type);
> diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c
> index 3f8ef31..711e4f8 100644
> --- a/src/vdagent/vdagent.c
> +++ b/src/vdagent/vdagent.c
> @@ -36,9 +36,7 @@
>  #include <spice/vd_agent.h>
>  #include <poll.h>
>  #include <glib-unix.h>
> -#ifdef WITH_GTK
> -# include <gtk/gtk.h>
> -#endif
> +#include <gtk/gtk.h>
>  
>  #include "udscs.h"
>  #include "vdagentd-proto.h"
> @@ -113,7 +111,7 @@ static const gchar *xfer_get_download_directory(VDAgent *agent)
>          return fx_dir;
>      }
>  
> -    return g_get_user_special_dir(vdagent_x11_has_icons_on_desktop(agent->x11) ?
> +    return g_get_user_special_dir(vdagent_x11_has_icons_on_desktop() ?
>                                    G_USER_DIRECTORY_DESKTOP :
>                                    G_USER_DIRECTORY_DOWNLOAD);
>  }
> @@ -143,7 +141,7 @@ static gboolean vdagent_init_file_xfer(VDAgent *agent)
>      }
>  
>      open_dir = fx_open_dir == -1 ?
> -               !vdagent_x11_has_icons_on_desktop(agent->x11) :
> +               !vdagent_x11_has_icons_on_desktop() :
>                 fx_open_dir;
>  
>      agent->xfers = vdagent_file_xfers_create(agent->conn, xfer_dir,
> @@ -391,7 +389,7 @@ static gboolean vdagent_init_async_cb(gpointer user_data)
>      if (!vdagent_init_file_xfer(agent))
>          syslog(LOG_WARNING, "File transfer is disabled");
>  
> -    agent->clipboards = vdagent_clipboards_init(agent->x11, agent->conn);
> +    agent->clipboards = vdagent_clipboards_init(agent->conn);
>  
>      if (parent_socket != -1) {
>          if (write(parent_socket, "OK", 2) != 2)
> @@ -419,9 +417,7 @@ int main(int argc, char *argv[])
>      g_option_context_set_summary(context,
>                                   "\tSpice session guest agent: X11\n"
>                                   "\tVersion: " VERSION);
> -#ifdef WITH_GTK
>      g_option_context_add_group(context, gtk_get_option_group(FALSE));
> -#endif
>      g_option_context_parse(context, &argc, &argv, &error);
>      g_option_context_free(context);
>  
> @@ -449,10 +445,8 @@ int main(int argc, char *argv[])
>      if (do_daemonize)
>          parent_socket = daemonize();
>  
> -#ifdef WITH_GTK
>      gdk_set_allowed_backends("x11");
>      gtk_init(NULL, NULL);
> -#endif
>  
>  reconnect:
>      if (version_mismatch) {
> diff --git a/src/vdagent/x11-priv.h b/src/vdagent/x11-priv.h
> index e7c64bd..f341048 100644
> --- a/src/vdagent/x11-priv.h
> +++ b/src/vdagent/x11-priv.h
> @@ -1,10 +1,6 @@
>  #ifndef VDAGENT_X11_PRIV
>  #define VDAGENT_X11_PRIV
>  
> -#ifdef HAVE_CONFIG_H
> -# include <config.h>
> -#endif
> -
>  #include <stdint.h>
>  #include <stdio.h>
>  
> @@ -12,66 +8,6 @@
>  
>  #include <X11/extensions/Xrandr.h>
>  
> -#ifndef WITH_GTK
> -/* 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)
> -
> -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;
> -};
> -
> -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]))
> -#endif
> -
>  #define MAX_SCREENS 16
>  /* Same as qxl_dev.h client_monitors_config.heads count */
>  #define MONITOR_SIZE_COUNT 64
> @@ -83,36 +19,6 @@ struct monitor_size {
>  
>  struct vdagent_x11 {
>      Display *display;
> -#ifndef WITH_GTK
> -    struct clipboard_format_info clipboard_formats[clipboard_format_count];
> -    Atom clipboard_atom;
> -    Atom clipboard_primary_atom;
> -    Atom targets_atom;
> -    Atom incr_atom;
> -    Atom multiple_atom;
> -    Atom timestamp_atom;
> -    Window selection_window;
> -    int has_xfixes;
> -    int xfixes_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;
> -#endif
>      Window root_window[MAX_SCREENS];
>      struct udscs_connection *vdagentd;
>      int debug;
> diff --git a/src/vdagent/x11.c b/src/vdagent/x11.c
> index 0ea5668..a9ab699 100644
> --- a/src/vdagent/x11.c
> +++ b/src/vdagent/x11.c
> @@ -36,12 +36,10 @@
>  #endif
>  
>  #include <glib.h>
> -#ifdef WITH_GTK
>  #include <gdk/gdk.h>
>  #ifdef GDK_WINDOWING_X11
>  #include <gdk/gdkx.h>
>  #endif
> -#endif
>  #include <stdlib.h>
>  #include <limits.h>
>  #include <string.h>
> @@ -50,7 +48,6 @@
>  #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"
> @@ -59,52 +56,12 @@
>  int (*vdagent_x11_prev_error_handler)(Display *, XErrorEvent *);
>  int vdagent_x11_caught_error;
>  
> -#ifndef WITH_GTK
> -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";
> -    }
> -}
> -#endif
> -
>  static int vdagent_x11_debug_error_handler(
>      Display *display, XErrorEvent *error)
>  {
>      abort();
>  }
>  
> -#ifndef WITH_GTK
> -/* 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);
> -}
> -#endif
> -
>  void vdagent_x11_set_error_handler(struct vdagent_x11 *x11,
>      int (*handler)(Display *, XErrorEvent *))
>  {
> @@ -125,77 +82,15 @@ int vdagent_x11_restore_error_handler(struct vdagent_x11 *x11)
>      return error;
>  }
>  
> -static gchar *vdagent_x11_get_wm_name(struct vdagent_x11 *x11)
> +static const gchar *vdagent_x11_get_wm_name()
>  {
>  #ifdef GDK_WINDOWING_X11
>      GdkDisplay *display = gdk_display_get_default();
>      if (GDK_IS_X11_DISPLAY(display))
> -        return g_strdup(gdk_x11_screen_get_window_manager_name(
> -            gdk_display_get_default_screen(display)));
> -    return g_strdup("unsupported");
> -#else
> -    Atom type_ret;
> -    int format_ret;
> -    unsigned long len, remain;
> -    unsigned char *data = NULL;
> -    Window sup_window = None;
> -    gchar *net_wm_name = NULL;
> -
> -    /* XGetWindowProperty can throw a BadWindow error. One way we can trigger
> -       this is when the display-manager (ie gdm) has set, and not cleared the
> -       _NET_SUPPORTING_WM_CHECK property, and the window manager running in
> -       the user session has not yet updated it to point to its window, so its
> -       pointing to a nonexistent window. */
> -    vdagent_x11_set_error_handler(x11, vdagent_x11_ignore_bad_window_handler);
> -
> -    /* Get the window manager SUPPORTING_WM_CHECK window */
> -    if (XGetWindowProperty(x11->display, x11->root_window[0],
> -            XInternAtom(x11->display, "_NET_SUPPORTING_WM_CHECK", False), 0,
> -            LONG_MAX, False, XA_WINDOW, &type_ret, &format_ret, &len,
> -            &remain, &data) == Success) {
> -        if (type_ret == XA_WINDOW)
> -            sup_window = *((Window *)data);
> -        XFree(data);
> -    }
> -    if (sup_window == None &&
> -        XGetWindowProperty(x11->display, x11->root_window[0],
> -            XInternAtom(x11->display, "_WIN_SUPPORTING_WM_CHECK", False), 0,
> -            LONG_MAX, False, XA_CARDINAL, &type_ret, &format_ret, &len,
> -            &remain, &data) == Success) {
> -        if (type_ret == XA_CARDINAL)
> -            sup_window = *((Window *)data);
> -        XFree(data);
> -    }
> -    /* So that we can get the net_wm_name */
> -    if (sup_window != None) {
> -        Atom utf8 = XInternAtom(x11->display, "UTF8_STRING", False);
> -        if (XGetWindowProperty(x11->display, sup_window,
> -                XInternAtom(x11->display, "_NET_WM_NAME", False), 0,
> -                LONG_MAX, False, utf8, &type_ret, &format_ret, &len,
> -                &remain, &data) == Success) {
> -            if (type_ret == utf8) {
> -                net_wm_name = g_strndup((char *)data, (format_ret / 8) * len);
> -            }
> -            XFree(data);
> -        }
> -        if (net_wm_name == NULL &&
> -            XGetWindowProperty(x11->display, sup_window,
> -                XInternAtom(x11->display, "_NET_WM_NAME", False), 0,
> -                LONG_MAX, False, XA_STRING, &type_ret, &format_ret, &len,
> -                &remain, &data) == Success) {
> -            if (type_ret == XA_STRING) {
> -                net_wm_name = g_strndup((char *)data, (format_ret / 8) * len);
> -            }
> -            XFree(data);
> -        }
> -    }
> -
> -    vdagent_x11_restore_error_handler(x11);
> -
> -    if (net_wm_name == NULL)
> -        return g_strdup("unknown");
> -    return net_wm_name;
> +        return gdk_x11_screen_get_window_manager_name(
> +            gdk_display_get_default_screen(display));
>  #endif
> +    return "unsupported";
>  }
>  
>  struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
> @@ -203,12 +98,8 @@ struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
>  {
>      struct vdagent_x11 *x11;
>      XWindowAttributes attrib;
> -#ifdef WITH_GTK
>      int i;
> -#else
> -    int i, j, major, minor;
> -#endif
> -    gchar *net_wm_name = NULL;
> +    const gchar *net_wm_name;
>  
>      x11 = calloc(1, sizeof(*x11));
>      if (!x11) {
> @@ -243,61 +134,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);
> -#ifndef WITH_GTK
> -    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);
> -#endif
>  
>      vdagent_x11_randr_init(x11);
>  
> -#ifndef WITH_GTK
> -    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;
> -#endif
> -
>      for (i = 0; i < x11->screen_count; i++) {
>          /* Catch resolution changes */
>          XSelectInput(x11->display, x11->root_window[i], StructureNotifyMask);
> @@ -312,8 +151,7 @@ struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
>      /* Since we are started at the same time as the wm,
>         sometimes we need to wait a bit for the _NET_WM_NAME to show up. */
>      for (i = 0; i < 9; i++) {
> -        g_free(net_wm_name);
> -        net_wm_name = vdagent_x11_get_wm_name(x11);
> +        net_wm_name = vdagent_x11_get_wm_name();
>          if (strcmp(net_wm_name, "unknown"))
>              break;
>          usleep(100000);
> @@ -321,7 +159,6 @@ struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
>      if (x11->debug)
>          syslog(LOG_DEBUG, "%s: net_wm_name=\"%s\", has icons=%d",
>                 __func__, net_wm_name, vdagent_x11_has_icons_on_desktop(x11));
> -    g_free(net_wm_name);
>  
>      /* Flush output buffers and consume any pending events */
>      vdagent_x11_do_read(x11);
> @@ -334,16 +171,6 @@ void vdagent_x11_destroy(struct vdagent_x11 *x11, int vdagentd_disconnected)
>      if (!x11)
>          return;
>  
> -#ifndef WITH_GTK
> -    if (vdagentd_disconnected)
> -        x11->vdagentd = NULL;
> -
> -    uint8_t sel;
> -    for (sel = 0; sel < VD_AGENT_CLIPBOARD_SELECTION_SECONDARY; ++sel) {
> -        vdagent_x11_set_clipboard_owner(x11, sel, owner_none);
> -    }
> -#endif
> -
>      XCloseDisplay(x11->display);
>      free(x11->randr.failed_conf);
>      free(x11);
> @@ -354,194 +181,9 @@ int vdagent_x11_get_fd(struct vdagent_x11 *x11)
>      return x11->fd;
>  }
>  
> -#ifndef WITH_GTK
> -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;
> -}
> -#endif
> -
>  static void vdagent_x11_handle_event(struct vdagent_x11 *x11, XEvent event)
>  {
>      int i, handled = 0;
> -#ifndef WITH_GTK
> -    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;
> -    }
> -#endif
>  
>      if (vdagent_x11_randr_handle_event(x11, event))
>          return;
> @@ -562,67 +204,6 @@ static void vdagent_x11_handle_event(struct vdagent_x11 *x11, XEvent event)
>          /* These are uninteresting */
>          handled = 1;
>          break;
> -#ifndef WITH_GTK
> -    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;
> -    }
> -#endif
>      }
>      if (!handled && x11->debug)
>          syslog(LOG_DEBUG, "unhandled x11 event, type %d, window %d",
> @@ -639,749 +220,12 @@ void vdagent_x11_do_read(struct vdagent_x11 *x11)
>      }
>  }
>  
> -#ifndef WITH_GTK
> -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);
> -    }
> -}
> -#endif
> -
>  /* 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
>     file-xfers to the xdg download dir, and opening the xdg download dir with
>     xdg-open when the file-xfer completes. */
> -int vdagent_x11_has_icons_on_desktop(struct vdagent_x11 *x11)
> +int vdagent_x11_has_icons_on_desktop()
>  {
>      const char * const wms_with_icons_on_desktop[] = {
>          "Metacity", /* GNOME-2 or GNOME-3 fallback */
> @@ -1390,15 +234,12 @@ int vdagent_x11_has_icons_on_desktop(struct vdagent_x11 *x11)
>          "Metacity (Marco)", /* Mate, newer */
>          NULL
>      };
> -    gchar *net_wm_name = vdagent_x11_get_wm_name(x11);
> +    const gchar *net_wm_name = vdagent_x11_get_wm_name();
>      int i;
>  
>      for (i = 0; wms_with_icons_on_desktop[i]; i++)
> -        if (!strcmp(net_wm_name, wms_with_icons_on_desktop[i])) {
> -            g_free(net_wm_name);
> +        if (!strcmp(net_wm_name, wms_with_icons_on_desktop[i]))
>              return 1;
> -        }
>  
> -    g_free(net_wm_name);
>      return 0;
>  }
> diff --git a/src/vdagent/x11.h b/src/vdagent/x11.h
> index 1505f58..6ad09c2 100644
> --- a/src/vdagent/x11.h
> +++ b/src/vdagent/x11.h
> @@ -22,10 +22,6 @@
>  #ifndef __VDAGENT_X11_H
>  #define __VDAGENT_X11_H
>  
> -#ifdef HAVE_CONFIG_H
> -# include <config.h>
> -#endif
> -
>  #include <stdio.h>
>  #include <spice/vd_agent.h>
>  #include "udscs.h"
> @@ -42,18 +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);
>  
> -#ifndef WITH_GTK
> -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);
> -#endif
> -
> -int vdagent_x11_has_icons_on_desktop(struct vdagent_x11 *x11);
> +int vdagent_x11_has_icons_on_desktop();
>  
>  #endif
> -- 
> 2.17.0
> 
> _______________________________________________
> Spice-devel mailing list
> Spice-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/spice-devel
On Thu, Aug 09, 2018 at 03:35:52PM +0200, Victor Toso wrote:
> Hi,
> 
> On Thu, May 31, 2018 at 10:52:21PM +0200, Jakub Janků wrote:
> > Use GTK+ instead of Xlib where possible,
> > remove Xlib code that handles clipboard.
> 
> @teuf, double checking here if you think requiring gtk and
> dropping xlib would be a problem.
> 
> With possible problems in mind I asked gtk to be optional at
> build time for the 0.18.0 release but I don't see much point in
> working in features in gtk and x11 so I'd say this is fine.

Yes, we need to carefully test the gtk+ codepaths before making a
release with this dropped. gtk+ is a 'bigger' dependency than x11 to
install on a minimal system, but on systems with x11 installed, I'd
expect gtk+ to be present too. So no strong objection here..

Christophe

> 
> Cheers,
> Victor
> 
> > ---
> >  configure.ac            |   13 +-
> >  src/vdagent/clipboard.c |   49 +-
> >  src/vdagent/clipboard.h |    4 +-
> >  src/vdagent/vdagent.c   |   14 +-
> >  src/vdagent/x11-priv.h  |   94 ----
> >  src/vdagent/x11.c       | 1177 +--------------------------------------
> >  src/vdagent/x11.h       |   18 +-
> >  7 files changed, 21 insertions(+), 1348 deletions(-)
> > 
> > diff --git a/configure.ac b/configure.ac
> > index 89f617c..1eb17a9 100644
> > --- a/configure.ac
> > +++ b/configure.ac
> > @@ -75,16 +75,6 @@ if test "x$init_systemd" = "xyes"; then
> >    fi
> >  fi
> >  
> > -AC_ARG_WITH([gtk],
> > -            [AS_HELP_STRING([--with-gtk], [Use GTK+ instead of Xlib])],
> > -            [],
> > -            [with_gtk="auto"])
> > -if test "x$with_gtk" != "xno"; then
> > -  PKG_CHECK_MODULES([GTK], [gtk+-3.0 >= 3.10],
> > -                    [AC_DEFINE([WITH_GTK], [1], [If defined, vdagent will favor GTK+ over Xlib])],
> > -                    [AS_IF([test "x$with_gtk" = "xyes"], [AC_MSG_ERROR([GTK+ requested but not found])])])
> > -fi
> > -
> >  AC_ARG_ENABLE([pciaccess],
> >                [AS_HELP_STRING([--enable-pciaccess], [Enable libpciaccess use for auto generation of Xinerama xorg.conf (default: yes)])],
> >                [enable_pciaccess="$enableval"],
> > @@ -96,6 +86,7 @@ AC_ARG_ENABLE([static-uinput],
> >                [enable_static_uinput="no"])
> >  
> >  PKG_CHECK_MODULES([GLIB2], [glib-2.0 >= 2.34])
> > +PKG_CHECK_MODULES([GTK], [gtk+-3.0 >= 3.10])
> >  PKG_CHECK_MODULES(X, [xfixes xrandr >= 1.3 xinerama x11])
> >  PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.12.13])
> >  PKG_CHECK_MODULES(ALSA, [alsa >= 1.0.22])
> > @@ -219,8 +210,6 @@ AC_MSG_NOTICE([
> >          install systemd service:  ${init_systemd}
> >          udevdir:                  ${udevdir}
> >  
> > -        use GTK+:                 ${with_gtk}
> > -
> >          Now type 'make' to build $PACKAGE
> >  
> >  ])
> > diff --git a/src/vdagent/clipboard.c b/src/vdagent/clipboard.c
> > index 667c168..101e535 100644
> > --- a/src/vdagent/clipboard.c
> > +++ b/src/vdagent/clipboard.c
> > @@ -20,17 +20,14 @@
> >  # include <config.h>
> >  #endif
> >  
> > -#ifdef WITH_GTK
> > -# include <gtk/gtk.h>
> > -# include <syslog.h>
> > +#include <gtk/gtk.h>
> > +#include <syslog.h>
> >  
> > -# include "vdagentd-proto.h"
> > -# include "spice/vd_agent.h"
> > -#endif
> > +#include "vdagentd-proto.h"
> > +#include "spice/vd_agent.h"
> >  
> >  #include "clipboard.h"
> >  
> > -#ifdef WITH_GTK
> >  /* 2 selections supported - _SELECTION_CLIPBOARD = 0, _SELECTION_PRIMARY = 1 */
> >  #define SELECTION_COUNT (VD_AGENT_CLIPBOARD_SELECTION_PRIMARY + 1)
> >  #define TYPE_COUNT      (VD_AGENT_CLIPBOARD_IMAGE_JPG + 1)
> > @@ -59,18 +56,12 @@ typedef struct {
> >  
> >      GdkAtom       targets[TYPE_COUNT];
> >  } Selection;
> > -#endif
> >  
> >  struct VDAgentClipboards {
> > -#ifdef WITH_GTK
> >      struct udscs_connection *conn;
> >      Selection                selections[SELECTION_COUNT];
> > -#else
> > -    struct vdagent_x11 *x11;
> > -#endif
> >  };
> >  
> > -#ifdef WITH_GTK
> >  static const struct {
> >      guint         type;
> >      const gchar  *atom_name;
> > @@ -298,14 +289,10 @@ static void clipboard_clear_cb(GtkClipboard *clipboard, gpointer user_data)
> >      VDAgentClipboards *c = user_data;
> >      clipboard_new_owner(c, sel_id_from_clip(clipboard), OWNER_NONE);
> >  }
> > -#endif
> >  
> >  void vdagent_clipboard_grab(VDAgentClipboards *c, guint sel_id,
> >                              guint32 *types, guint n_types)
> >  {
> > -#ifndef WITH_GTK
> > -    vdagent_x11_clipboard_grab(c->x11, sel_id, types, n_types);
> > -#else
> >      GtkTargetEntry targets[G_N_ELEMENTS(atom2agent)];
> >      guint n_targets, i, t;
> >  
> > @@ -333,15 +320,11 @@ void vdagent_clipboard_grab(VDAgentClipboards *c, guint sel_id,
> >          syslog(LOG_ERR, "%s: sel_id=%u: clipboard grab failed", __func__, sel_id);
> >          clipboard_new_owner(c, sel_id, OWNER_NONE);
> >      }
> > -#endif
> >  }
> >  
> >  void vdagent_clipboard_data(VDAgentClipboards *c, guint sel_id,
> >                              guint type, guchar *data, guint size)
> >  {
> > -#ifndef WITH_GTK
> > -    vdagent_x11_clipboard_data(c->x11, sel_id, type, data, size);
> > -#else
> >      g_return_if_fail(sel_id < SELECTION_COUNT);
> >      Selection *sel = &c->selections[sel_id];
> >      AppRequest *req;
> > @@ -364,28 +347,20 @@ void vdagent_clipboard_data(VDAgentClipboards *c, guint sel_id,
> >                             8, data, size);
> >  
> >      g_main_loop_quit(req->loop);
> > -#endif
> >  }
> >  
> >  void vdagent_clipboard_release(VDAgentClipboards *c, guint sel_id)
> >  {
> > -#ifndef WITH_GTK
> > -    vdagent_x11_clipboard_release(c->x11, sel_id);
> > -#else
> >      g_return_if_fail(sel_id < SELECTION_COUNT);
> >      if (c->selections[sel_id].owner != OWNER_CLIENT)
> >          return;
> >  
> >      clipboard_new_owner(c, sel_id, OWNER_NONE);
> >      gtk_clipboard_clear(c->selections[sel_id].clipboard);
> > -#endif
> >  }
> >  
> >  void vdagent_clipboards_release_all(VDAgentClipboards *c)
> >  {
> > -#ifndef WITH_GTK
> > -    vdagent_x11_client_disconnected(c->x11);
> > -#else
> >      guint sel_id, owner;
> >  
> >      for (sel_id = 0; sel_id < SELECTION_COUNT; sel_id++) {
> > @@ -396,14 +371,10 @@ void vdagent_clipboards_release_all(VDAgentClipboards *c)
> >          else if (owner == OWNER_GUEST && c->conn)
> >              udscs_write(c->conn, VDAGENTD_CLIPBOARD_RELEASE, sel_id, 0, NULL, 0);
> >      }
> > -#endif
> >  }
> >  
> >  void vdagent_clipboard_request(VDAgentClipboards *c, guint sel_id, guint type)
> >  {
> > -#ifndef WITH_GTK
> > -    vdagent_x11_clipboard_request(c->x11, sel_id, type);
> > -#else
> >      Selection *sel;
> >  
> >      if (sel_id >= SELECTION_COUNT)
> > @@ -428,25 +399,18 @@ void vdagent_clipboard_request(VDAgentClipboards *c, guint sel_id, guint type)
> >  err:
> >      udscs_write(c->conn, VDAGENTD_CLIPBOARD_DATA, sel_id,
> >                  VD_AGENT_CLIPBOARD_NONE, NULL, 0);
> > -#endif
> >  }
> >  
> > -VDAgentClipboards *vdagent_clipboards_init(struct vdagent_x11      *x11,
> > -                                           struct udscs_connection *conn)
> > +VDAgentClipboards *vdagent_clipboards_init(struct udscs_connection *conn)
> >  {
> > -#ifdef WITH_GTK
> >      guint sel_id;
> >      const GdkAtom sel_atom[SELECTION_COUNT] = {
> >          GDK_SELECTION_CLIPBOARD, /* VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD */
> >          GDK_SELECTION_PRIMARY,   /* VD_AGENT_CLIPBOARD_SELECTION_PRIMARY */
> >      };
> > -#endif
> >  
> >      VDAgentClipboards *c;
> >      c = g_new0(VDAgentClipboards, 1);
> > -#ifndef WITH_GTK
> > -    c->x11 = x11;
> > -#else
> >      c->conn = conn;
> >  
> >      for (sel_id = 0; sel_id < SELECTION_COUNT; sel_id++) {
> > @@ -458,14 +422,12 @@ VDAgentClipboards *vdagent_clipboards_init(struct vdagent_x11      *x11,
> >          g_signal_connect(G_OBJECT(clipboard), "owner-change",
> >                           G_CALLBACK(clipboard_owner_change_cb), c);
> >      }
> > -#endif
> >  
> >      return c;
> >  }
> >  
> >  void vdagent_clipboards_finalize(VDAgentClipboards *c, gboolean conn_alive)
> >  {
> > -#ifdef WITH_GTK
> >      guint sel_id;
> >      for (sel_id = 0; sel_id < SELECTION_COUNT; sel_id++)
> >          g_signal_handlers_disconnect_by_func(c->selections[sel_id].clipboard,
> > @@ -474,7 +436,6 @@ void vdagent_clipboards_finalize(VDAgentClipboards *c, gboolean conn_alive)
> >      if (conn_alive == FALSE)
> >          c->conn = NULL;
> >      vdagent_clipboards_release_all(c);
> > -#endif
> >  
> >      g_free(c);
> >  }
> > diff --git a/src/vdagent/clipboard.h b/src/vdagent/clipboard.h
> > index f819b49..e007a37 100644
> > --- a/src/vdagent/clipboard.h
> > +++ b/src/vdagent/clipboard.h
> > @@ -21,13 +21,11 @@
> >  
> >  #include <glib.h>
> >  
> > -#include "x11.h"
> >  #include "udscs.h"
> >  
> >  typedef struct VDAgentClipboards VDAgentClipboards;
> >  
> > -VDAgentClipboards *vdagent_clipboards_init(struct vdagent_x11      *x11,
> > -                                           struct udscs_connection *conn);
> > +VDAgentClipboards *vdagent_clipboards_init(struct udscs_connection *conn);
> >  void vdagent_clipboards_finalize(VDAgentClipboards *c, gboolean conn_alive);
> >  
> >  void vdagent_clipboard_request(VDAgentClipboards *c, guint sel_id, guint type);
> > diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c
> > index 3f8ef31..711e4f8 100644
> > --- a/src/vdagent/vdagent.c
> > +++ b/src/vdagent/vdagent.c
> > @@ -36,9 +36,7 @@
> >  #include <spice/vd_agent.h>
> >  #include <poll.h>
> >  #include <glib-unix.h>
> > -#ifdef WITH_GTK
> > -# include <gtk/gtk.h>
> > -#endif
> > +#include <gtk/gtk.h>
> >  
> >  #include "udscs.h"
> >  #include "vdagentd-proto.h"
> > @@ -113,7 +111,7 @@ static const gchar *xfer_get_download_directory(VDAgent *agent)
> >          return fx_dir;
> >      }
> >  
> > -    return g_get_user_special_dir(vdagent_x11_has_icons_on_desktop(agent->x11) ?
> > +    return g_get_user_special_dir(vdagent_x11_has_icons_on_desktop() ?
> >                                    G_USER_DIRECTORY_DESKTOP :
> >                                    G_USER_DIRECTORY_DOWNLOAD);
> >  }
> > @@ -143,7 +141,7 @@ static gboolean vdagent_init_file_xfer(VDAgent *agent)
> >      }
> >  
> >      open_dir = fx_open_dir == -1 ?
> > -               !vdagent_x11_has_icons_on_desktop(agent->x11) :
> > +               !vdagent_x11_has_icons_on_desktop() :
> >                 fx_open_dir;
> >  
> >      agent->xfers = vdagent_file_xfers_create(agent->conn, xfer_dir,
> > @@ -391,7 +389,7 @@ static gboolean vdagent_init_async_cb(gpointer user_data)
> >      if (!vdagent_init_file_xfer(agent))
> >          syslog(LOG_WARNING, "File transfer is disabled");
> >  
> > -    agent->clipboards = vdagent_clipboards_init(agent->x11, agent->conn);
> > +    agent->clipboards = vdagent_clipboards_init(agent->conn);
> >  
> >      if (parent_socket != -1) {
> >          if (write(parent_socket, "OK", 2) != 2)
> > @@ -419,9 +417,7 @@ int main(int argc, char *argv[])
> >      g_option_context_set_summary(context,
> >                                   "\tSpice session guest agent: X11\n"
> >                                   "\tVersion: " VERSION);
> > -#ifdef WITH_GTK
> >      g_option_context_add_group(context, gtk_get_option_group(FALSE));
> > -#endif
> >      g_option_context_parse(context, &argc, &argv, &error);
> >      g_option_context_free(context);
> >  
> > @@ -449,10 +445,8 @@ int main(int argc, char *argv[])
> >      if (do_daemonize)
> >          parent_socket = daemonize();
> >  
> > -#ifdef WITH_GTK
> >      gdk_set_allowed_backends("x11");
> >      gtk_init(NULL, NULL);
> > -#endif
> >  
> >  reconnect:
> >      if (version_mismatch) {
> > diff --git a/src/vdagent/x11-priv.h b/src/vdagent/x11-priv.h
> > index e7c64bd..f341048 100644
> > --- a/src/vdagent/x11-priv.h
> > +++ b/src/vdagent/x11-priv.h
> > @@ -1,10 +1,6 @@
> >  #ifndef VDAGENT_X11_PRIV
> >  #define VDAGENT_X11_PRIV
> >  
> > -#ifdef HAVE_CONFIG_H
> > -# include <config.h>
> > -#endif
> > -
> >  #include <stdint.h>
> >  #include <stdio.h>
> >  
> > @@ -12,66 +8,6 @@
> >  
> >  #include <X11/extensions/Xrandr.h>
> >  
> > -#ifndef WITH_GTK
> > -/* 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)
> > -
> > -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;
> > -};
> > -
> > -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]))
> > -#endif
> > -
> >  #define MAX_SCREENS 16
> >  /* Same as qxl_dev.h client_monitors_config.heads count */
> >  #define MONITOR_SIZE_COUNT 64
> > @@ -83,36 +19,6 @@ struct monitor_size {
> >  
> >  struct vdagent_x11 {
> >      Display *display;
> > -#ifndef WITH_GTK
> > -    struct clipboard_format_info clipboard_formats[clipboard_format_count];
> > -    Atom clipboard_atom;
> > -    Atom clipboard_primary_atom;
> > -    Atom targets_atom;
> > -    Atom incr_atom;
> > -    Atom multiple_atom;
> > -    Atom timestamp_atom;
> > -    Window selection_window;
> > -    int has_xfixes;
> > -    int xfixes_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;
> > -#endif
> >      Window root_window[MAX_SCREENS];
> >      struct udscs_connection *vdagentd;
> >      int debug;
> > diff --git a/src/vdagent/x11.c b/src/vdagent/x11.c
> > index 0ea5668..a9ab699 100644
> > --- a/src/vdagent/x11.c
> > +++ b/src/vdagent/x11.c
> > @@ -36,12 +36,10 @@
> >  #endif
> >  
> >  #include <glib.h>
> > -#ifdef WITH_GTK
> >  #include <gdk/gdk.h>
> >  #ifdef GDK_WINDOWING_X11
> >  #include <gdk/gdkx.h>
> >  #endif
> > -#endif
> >  #include <stdlib.h>
> >  #include <limits.h>
> >  #include <string.h>
> > @@ -50,7 +48,6 @@
> >  #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"
> > @@ -59,52 +56,12 @@
> >  int (*vdagent_x11_prev_error_handler)(Display *, XErrorEvent *);
> >  int vdagent_x11_caught_error;
> >  
> > -#ifndef WITH_GTK
> > -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";
> > -    }
> > -}
> > -#endif
> > -
> >  static int vdagent_x11_debug_error_handler(
> >      Display *display, XErrorEvent *error)
> >  {
> >      abort();
> >  }
> >  
> > -#ifndef WITH_GTK
> > -/* 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);
> > -}
> > -#endif
> > -
> >  void vdagent_x11_set_error_handler(struct vdagent_x11 *x11,
> >      int (*handler)(Display *, XErrorEvent *))
> >  {
> > @@ -125,77 +82,15 @@ int vdagent_x11_restore_error_handler(struct vdagent_x11 *x11)
> >      return error;
> >  }
> >  
> > -static gchar *vdagent_x11_get_wm_name(struct vdagent_x11 *x11)
> > +static const gchar *vdagent_x11_get_wm_name()
> >  {
> >  #ifdef GDK_WINDOWING_X11
> >      GdkDisplay *display = gdk_display_get_default();
> >      if (GDK_IS_X11_DISPLAY(display))
> > -        return g_strdup(gdk_x11_screen_get_window_manager_name(
> > -            gdk_display_get_default_screen(display)));
> > -    return g_strdup("unsupported");
> > -#else
> > -    Atom type_ret;
> > -    int format_ret;
> > -    unsigned long len, remain;
> > -    unsigned char *data = NULL;
> > -    Window sup_window = None;
> > -    gchar *net_wm_name = NULL;
> > -
> > -    /* XGetWindowProperty can throw a BadWindow error. One way we can trigger
> > -       this is when the display-manager (ie gdm) has set, and not cleared the
> > -       _NET_SUPPORTING_WM_CHECK property, and the window manager running in
> > -       the user session has not yet updated it to point to its window, so its
> > -       pointing to a nonexistent window. */
> > -    vdagent_x11_set_error_handler(x11, vdagent_x11_ignore_bad_window_handler);
> > -
> > -    /* Get the window manager SUPPORTING_WM_CHECK window */
> > -    if (XGetWindowProperty(x11->display, x11->root_window[0],
> > -            XInternAtom(x11->display, "_NET_SUPPORTING_WM_CHECK", False), 0,
> > -            LONG_MAX, False, XA_WINDOW, &type_ret, &format_ret, &len,
> > -            &remain, &data) == Success) {
> > -        if (type_ret == XA_WINDOW)
> > -            sup_window = *((Window *)data);
> > -        XFree(data);
> > -    }
> > -    if (sup_window == None &&
> > -        XGetWindowProperty(x11->display, x11->root_window[0],
> > -            XInternAtom(x11->display, "_WIN_SUPPORTING_WM_CHECK", False), 0,
> > -            LONG_MAX, False, XA_CARDINAL, &type_ret, &format_ret, &len,
> > -            &remain, &data) == Success) {
> > -        if (type_ret == XA_CARDINAL)
> > -            sup_window = *((Window *)data);
> > -        XFree(data);
> > -    }
> > -    /* So that we can get the net_wm_name */
> > -    if (sup_window != None) {
> > -        Atom utf8 = XInternAtom(x11->display, "UTF8_STRING", False);
> > -        if (XGetWindowProperty(x11->display, sup_window,
> > -                XInternAtom(x11->display, "_NET_WM_NAME", False), 0,
> > -                LONG_MAX, False, utf8, &type_ret, &format_ret, &len,
> > -                &remain, &data) == Success) {
> > -            if (type_ret == utf8) {
> > -                net_wm_name = g_strndup((char *)data, (format_ret / 8) * len);
> > -            }
> > -            XFree(data);
> > -        }
> > -        if (net_wm_name == NULL &&
> > -            XGetWindowProperty(x11->display, sup_window,
> > -                XInternAtom(x11->display, "_NET_WM_NAME", False), 0,
> > -                LONG_MAX, False, XA_STRING, &type_ret, &format_ret, &len,
> > -                &remain, &data) == Success) {
> > -            if (type_ret == XA_STRING) {
> > -                net_wm_name = g_strndup((char *)data, (format_ret / 8) * len);
> > -            }
> > -            XFree(data);
> > -        }
> > -    }
> > -
> > -    vdagent_x11_restore_error_handler(x11);
> > -
> > -    if (net_wm_name == NULL)
> > -        return g_strdup("unknown");
> > -    return net_wm_name;
> > +        return gdk_x11_screen_get_window_manager_name(
> > +            gdk_display_get_default_screen(display));
> >  #endif
> > +    return "unsupported";
> >  }
> >  
> >  struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
> > @@ -203,12 +98,8 @@ struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
> >  {
> >      struct vdagent_x11 *x11;
> >      XWindowAttributes attrib;
> > -#ifdef WITH_GTK
> >      int i;
> > -#else
> > -    int i, j, major, minor;
> > -#endif
> > -    gchar *net_wm_name = NULL;
> > +    const gchar *net_wm_name;
> >  
> >      x11 = calloc(1, sizeof(*x11));
> >      if (!x11) {
> > @@ -243,61 +134,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);
> > -#ifndef WITH_GTK
> > -    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);
> > -#endif
> >  
> >      vdagent_x11_randr_init(x11);
> >  
> > -#ifndef WITH_GTK
> > -    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;
> > -#endif
> > -
> >      for (i = 0; i < x11->screen_count; i++) {
> >          /* Catch resolution changes */
> >          XSelectInput(x11->display, x11->root_window[i], StructureNotifyMask);
> > @@ -312,8 +151,7 @@ struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
> >      /* Since we are started at the same time as the wm,
> >         sometimes we need to wait a bit for the _NET_WM_NAME to show up. */
> >      for (i = 0; i < 9; i++) {
> > -        g_free(net_wm_name);
> > -        net_wm_name = vdagent_x11_get_wm_name(x11);
> > +        net_wm_name = vdagent_x11_get_wm_name();
> >          if (strcmp(net_wm_name, "unknown"))
> >              break;
> >          usleep(100000);
> > @@ -321,7 +159,6 @@ struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
> >      if (x11->debug)
> >          syslog(LOG_DEBUG, "%s: net_wm_name=\"%s\", has icons=%d",
> >                 __func__, net_wm_name, vdagent_x11_has_icons_on_desktop(x11));
> > -    g_free(net_wm_name);
> >  
> >      /* Flush output buffers and consume any pending events */
> >      vdagent_x11_do_read(x11);
> > @@ -334,16 +171,6 @@ void vdagent_x11_destroy(struct vdagent_x11 *x11, int vdagentd_disconnected)
> >      if (!x11)
> >          return;
> >  
> > -#ifndef WITH_GTK
> > -    if (vdagentd_disconnected)
> > -        x11->vdagentd = NULL;
> > -
> > -    uint8_t sel;
> > -    for (sel = 0; sel < VD_AGENT_CLIPBOARD_SELECTION_SECONDARY; ++sel) {
> > -        vdagent_x11_set_clipboard_owner(x11, sel, owner_none);
> > -    }
> > -#endif
> > -
> >      XCloseDisplay(x11->display);
> >      free(x11->randr.failed_conf);
> >      free(x11);
> > @@ -354,194 +181,9 @@ int vdagent_x11_get_fd(struct vdagent_x11 *x11)
> >      return x11->fd;
> >  }
> >  
> > -#ifndef WITH_GTK
> > -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;
> > -}
> > -#endif
> > -
> >  static void vdagent_x11_handle_event(struct vdagent_x11 *x11, XEvent event)
> >  {
> >      int i, handled = 0;
> > -#ifndef WITH_GTK
> > -    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;
> > -    }
> > -#endif
> >  
> >      if (vdagent_x11_randr_handle_event(x11, event))
> >          return;
> > @@ -562,67 +204,6 @@ static void vdagent_x11_handle_event(struct vdagent_x11 *x11, XEvent event)
> >          /* These are uninteresting */
> >          handled = 1;
> >          break;
> > -#ifndef WITH_GTK
> > -    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;
> > -    }
> > -#endif
> >      }
> >      if (!handled && x11->debug)
> >          syslog(LOG_DEBUG, "unhandled x11 event, type %d, window %d",
> > @@ -639,749 +220,12 @@ void vdagent_x11_do_read(struct vdagent_x11 *x11)
> >      }
> >  }
> >  
> > -#ifndef WITH_GTK
> > -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);
> > -    }
> > -}
> > -#endif
> > -
> >  /* 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
> >     file-xfers to the xdg download dir, and opening the xdg download dir with
> >     xdg-open when the file-xfer completes. */
> > -int vdagent_x11_has_icons_on_desktop(struct vdagent_x11 *x11)
> > +int vdagent_x11_has_icons_on_desktop()
> >  {
> >      const char * const wms_with_icons_on_desktop[] = {
> >          "Metacity", /* GNOME-2 or GNOME-3 fallback */
> > @@ -1390,15 +234,12 @@ int vdagent_x11_has_icons_on_desktop(struct vdagent_x11 *x11)
> >          "Metacity (Marco)", /* Mate, newer */
> >          NULL
> >      };
> > -    gchar *net_wm_name = vdagent_x11_get_wm_name(x11);
> > +    const gchar *net_wm_name = vdagent_x11_get_wm_name();
> >      int i;
> >  
> >      for (i = 0; wms_with_icons_on_desktop[i]; i++)
> > -        if (!strcmp(net_wm_name, wms_with_icons_on_desktop[i])) {
> > -            g_free(net_wm_name);
> > +        if (!strcmp(net_wm_name, wms_with_icons_on_desktop[i]))
> >              return 1;
> > -        }
> >  
> > -    g_free(net_wm_name);
> >      return 0;
> >  }
> > diff --git a/src/vdagent/x11.h b/src/vdagent/x11.h
> > index 1505f58..6ad09c2 100644
> > --- a/src/vdagent/x11.h
> > +++ b/src/vdagent/x11.h
> > @@ -22,10 +22,6 @@
> >  #ifndef __VDAGENT_X11_H
> >  #define __VDAGENT_X11_H
> >  
> > -#ifdef HAVE_CONFIG_H
> > -# include <config.h>
> > -#endif
> > -
> >  #include <stdio.h>
> >  #include <spice/vd_agent.h>
> >  #include "udscs.h"
> > @@ -42,18 +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);
> >  
> > -#ifndef WITH_GTK
> > -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);
> > -#endif
> > -
> > -int vdagent_x11_has_icons_on_desktop(struct vdagent_x11 *x11);
> > +int vdagent_x11_has_icons_on_desktop();
> >  
> >  #endif
> > -- 
> > 2.17.0
> > 
> > _______________________________________________
> > Spice-devel mailing list
> > Spice-devel@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/spice-devel



> _______________________________________________
> Spice-devel mailing list
> Spice-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/spice-devel