From 7c3e3d66d63f0dfd33902ab7541724cf2dc4cd76 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Tue, 7 Jan 2020 14:48:48 +0100 Subject: Fix drag and drop for X11 in Gtk "XDND drag-and-drop does not work with reparented external windows, since messages are exchanged with the toplevel window only" To address this, the XDND specification allows events to be proxied to child windows: https://www.freedesktop.org/wiki/Specifications/XDND/ This commit does so in suil so that drag and drop works with embedded plugin UIs. --- src/x11_in_gtk2.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'src') diff --git a/src/x11_in_gtk2.c b/src/x11_in_gtk2.c index 69fbc17..d8f9578 100644 --- a/src/x11_in_gtk2.c +++ b/src/x11_in_gtk2.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "lv2/options/options.h" #include "lv2/urid/urid.h" @@ -89,6 +90,25 @@ x_window_is_valid(SuilX11Wrapper* socket) return false; } +static Window +get_parent_window(Display* display, Window child) +{ + Window root = 0; + Window parent = 0; + Window* children = NULL; + unsigned count = 0; + + if (child) { + if (XQueryTree(display, child, &root, &parent, &children, &count)) { + if (children) { + XFree(children); + } + } + } + + return (parent == root) ? 0 : parent; +} + static gboolean on_plug_removed(GtkSocket* sock, gpointer data) { @@ -133,6 +153,25 @@ suil_x11_wrapper_realize(GtkWidget* w) gtk_widget_set_sensitive(GTK_WIDGET(wrap->plug), TRUE); gtk_widget_set_can_focus(GTK_WIDGET(wrap->plug), TRUE); gtk_widget_grab_focus(GTK_WIDGET(wrap->plug)); + + // Setup drag/drop proxy from parent/grandparent window + GdkWindow* gwindow = gtk_widget_get_window(GTK_WIDGET(wrap->plug)); + Window xwindow = GDK_WINDOW_XID(gwindow); + Atom xdnd_proxy_atom = gdk_x11_get_xatom_by_name("XdndProxy"); + Window plugin = (Window)wrap->instance->ui_widget; + + while (xwindow) { + XChangeProperty(GDK_WINDOW_XDISPLAY(gwindow), + xwindow, + xdnd_proxy_atom, + XA_WINDOW, + 32, + PropModeReplace, + (unsigned char*)&plugin, + 1); + + xwindow = get_parent_window(GDK_WINDOW_XDISPLAY(gwindow), xwindow); + } } static void -- cgit v1.2.1