summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2020-01-07 14:48:48 +0100
committerDavid Robillard <d@drobilla.net>2020-02-12 20:12:27 +0100
commit7c3e3d66d63f0dfd33902ab7541724cf2dc4cd76 (patch)
tree3b83b4e1dd45bde5c3aded090cdabe300a32ceb4 /src
parent87532252e2aa0ea15f6a97df76c51a93c1378b20 (diff)
downloadsuil-7c3e3d66d63f0dfd33902ab7541724cf2dc4cd76.tar.gz
suil-7c3e3d66d63f0dfd33902ab7541724cf2dc4cd76.tar.bz2
suil-7c3e3d66d63f0dfd33902ab7541724cf2dc4cd76.zip
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" <https://specifications.freedesktop.org/xembed-spec/xembed-spec-latest.html#idm46049203496608> 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.
Diffstat (limited to 'src')
-rw-r--r--src/x11_in_gtk2.c39
1 files changed, 39 insertions, 0 deletions
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 <gdk/gdkx.h>
#include <gtk/gtk.h>
#include <string.h>
+#include <X11/Xatom.h>
#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