From fc61658ada98cbceff996e01b28f14c362dcac55 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Fri, 9 Jul 2021 18:47:27 +0200 Subject: [PATCH] Add the start for a Wine->X11 DnD wrapper --- src/wine-host/editor.cpp | 7 +++++ src/wine-host/meson.build | 2 +- src/wine-host/xdnd-proxy.cpp | 52 ++++++++++++++++++++++++++++++++++++ src/wine-host/xdnd-proxy.h | 51 +++++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 src/wine-host/xdnd-proxy.cpp create mode 100644 src/wine-host/xdnd-proxy.h diff --git a/src/wine-host/editor.cpp b/src/wine-host/editor.cpp index b8fb57c2..e7c9fdf8 100644 --- a/src/wine-host/editor.cpp +++ b/src/wine-host/editor.cpp @@ -20,6 +20,8 @@ #include +#include "xdnd-proxy.h" + using namespace std::literals::chrono_literals; // A catchable alternative to `assert()`. Normally all of our `assert(!error)` @@ -360,6 +362,11 @@ Editor::Editor(MainContext& main_context, 0); xcb_flush(x11_connection.get()); } + + // Set up our proxy for translating Wine drag-and-drop events into XDND + // events + // TODO: We're going to need to store this somewhere to pass the events + WineXdndProxy::init_proxy(); } void Editor::handle_x11_events() const noexcept { diff --git a/src/wine-host/meson.build b/src/wine-host/meson.build index 0450038f..c62c431d 100644 --- a/src/wine-host/meson.build +++ b/src/wine-host/meson.build @@ -62,8 +62,8 @@ host_common_sources = files( 'bridges/common.cpp', 'bridges/vst2.cpp', 'editor.cpp', - 'editor.cpp', 'utils.cpp', + 'xdnd-proxy.cpp', ) if with_vst3 diff --git a/src/wine-host/xdnd-proxy.cpp b/src/wine-host/xdnd-proxy.cpp new file mode 100644 index 00000000..725a5d03 --- /dev/null +++ b/src/wine-host/xdnd-proxy.cpp @@ -0,0 +1,52 @@ +// yabridge: a Wine VST bridge +// Copyright (C) 2020-2021 Robbert van der Helm +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "xdnd-proxy.h" + +void CALLBACK dnd_winevent_callback(HWINEVENTHOOK hWinEventHook, + DWORD event, + HWND hwnd, + LONG idObject, + LONG idChild, + DWORD idEventThread, + DWORD dwmsEventTime) { + // TODO: `EVENT_OBJECT_DESTROY` doesn't seem to be implemented by Wine, so + // we can't rely on that. + if (event == EVENT_OBJECT_CREATE && idObject == OBJID_WINDOW) { + // TODO + } +} + +WineXdndProxy::WineXdndProxy() + : hook_handle( + SetWinEventHook(EVENT_OBJECT_CREATE, + EVENT_OBJECT_CREATE, + nullptr, + dnd_winevent_callback, + 0, + 0, + WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS), + UnhookWinEvent) {} + +WineXdndProxy& WineXdndProxy::init_proxy() { + static std::unique_ptr instance; + if (!instance) { + // Protected constructors, hooray! + instance.reset(new WineXdndProxy{}); + } + + return *instance; +} diff --git a/src/wine-host/xdnd-proxy.h b/src/wine-host/xdnd-proxy.h new file mode 100644 index 00000000..db822a68 --- /dev/null +++ b/src/wine-host/xdnd-proxy.h @@ -0,0 +1,51 @@ +// yabridge: a Wine VST bridge +// Copyright (C) 2020-2021 Robbert van der Helm +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include + +#include + +/** + * A simple wrapper that registers a WinEvents hook to listen for new windows + * being created, and handles XDND client messages to achieve the behaviour + * described in `WineXdndProxy::init_proxy()`. + */ +class WineXdndProxy { + protected: + WineXdndProxy(); + + public: + /** + * Initialize the Wine->X11 drag-and-drop proxy. Calling this will hook into + * Wine's OLE drag and drop system by listening for the creation of special + * proxy windows created by the Wine server. When a drag and drop operation + * is started, we will initiate the XDND protocol with the same file. This + * will allow us to drag files from Wine windows to X11 applications, + * something that's normally not possible. Calling this function more than + * once doesn't have any effect, but this will still be called from every + * plugin host instance. Because of that we'll use a global Win32 mutex to + * ensure that this is done from only one thread at a time. + */ + static WineXdndProxy& init_proxy(); + + private: +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wignored-attributes" + std::unique_ptr, + std::decay_t> + hook_handle; +#pragma GCC diagnostic pop +};