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*)×tamp, 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@xxxxxxxxxxxxxxxxxxxxx > > https://lists.freedesktop.org/mailman/listinfo/spice-devel > _______________________________________________ > Spice-devel mailing list > Spice-devel@xxxxxxxxxxxxxxxxxxxxx > https://lists.freedesktop.org/mailman/listinfo/spice-devel
Attachment:
signature.asc
Description: PGP signature
_______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel