Create a window for the X11 proxy

This commit is contained in:
Robbert van der Helm
2021-07-10 16:43:23 +02:00
parent a8b7dc8764
commit 3372f4424e
2 changed files with 77 additions and 12 deletions
+36 -10
View File
@@ -57,9 +57,43 @@ void CALLBACK dnd_winevent_callback(HWINEVENTHOOK hWinEventHook,
DWORD idEventThread, DWORD idEventThread,
DWORD dwmsEventTime); DWORD dwmsEventTime);
ProxyWindow::ProxyWindow(std::shared_ptr<xcb_connection_t> x11_connection)
: x11_connection(x11_connection),
window(xcb_generate_id(x11_connection.get())) {
const xcb_screen_t* screen =
xcb_setup_roots_iterator(xcb_get_setup(x11_connection.get())).data;
xcb_create_window(x11_connection.get(), XCB_COPY_FROM_PARENT, window,
screen->root, 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
XCB_COPY_FROM_PARENT, 0, nullptr);
xcb_flush(x11_connection.get());
}
ProxyWindow::~ProxyWindow() noexcept {
if (!is_moved) {
xcb_destroy_window(x11_connection.get(), window);
xcb_flush(x11_connection.get());
}
}
ProxyWindow::ProxyWindow(ProxyWindow&& o) noexcept
: x11_connection(std::move(o.x11_connection)), window(std::move(o.window)) {
o.is_moved = true;
}
ProxyWindow& ProxyWindow::operator=(ProxyWindow&& o) noexcept {
if (&o != this) {
x11_connection = std::move(o.x11_connection);
window = std::move(o.window);
o.is_moved = true;
}
return *this;
}
WineXdndProxy::WineXdndProxy() WineXdndProxy::WineXdndProxy()
: x11_connection(xcb_connect(nullptr, nullptr), xcb_disconnect), : x11_connection(xcb_connect(nullptr, nullptr), xcb_disconnect),
proxy_window(xcb_generate_id(x11_connection.get())), proxy_window(x11_connection),
hook_handle( hook_handle(
SetWinEventHook(EVENT_OBJECT_CREATE, SetWinEventHook(EVENT_OBJECT_CREATE,
EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE,
@@ -68,15 +102,7 @@ WineXdndProxy::WineXdndProxy()
0, 0,
0, 0,
WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS), WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS),
UnhookWinEvent) { UnhookWinEvent) {}
//
}
WineXdndProxy::~WineXdndProxy() noexcept {
// TODO: Move this to a RAII wrapper
xcb_destroy_window(x11_connection.get(), proxy_window);
xcb_flush(x11_connection.get());
}
WineXdndProxy::Handle::Handle(WineXdndProxy* proxy) : proxy(proxy) {} WineXdndProxy::Handle::Handle(WineXdndProxy* proxy) : proxy(proxy) {}
+41 -2
View File
@@ -26,6 +26,35 @@
#include <windows.h> #include <windows.h>
/**
* A simple, unmapped 1x1 proxy window we'll use for our Wine->X11 drag-and-drop
* proxy so we can send and receive client messages.
*/
class ProxyWindow {
public:
/**
* Create the proxy window.
*/
ProxyWindow(std::shared_ptr<xcb_connection_t> x11_connection);
/**
* Destroy the window again when this object gets dropped.
*/
~ProxyWindow() noexcept;
ProxyWindow(const ProxyWindow&) noexcept = delete;
ProxyWindow& operator=(const ProxyWindow&) noexcept = delete;
ProxyWindow(ProxyWindow&&) noexcept;
ProxyWindow& operator=(ProxyWindow&&) noexcept;
private:
std::shared_ptr<xcb_connection_t> x11_connection;
xcb_window_t window;
bool is_moved = false;
};
/** /**
* A simple wrapper that registers a WinEvents hook to listen for new windows * A simple wrapper that registers a WinEvents hook to listen for new windows
* being created, and handles XDND client messages to achieve the behaviour * being created, and handles XDND client messages to achieve the behaviour
@@ -33,6 +62,9 @@
*/ */
class WineXdndProxy { class WineXdndProxy {
protected: protected:
/**
* Initialize the proxy and register all hooks.
*/
WineXdndProxy(); WineXdndProxy();
public: public:
@@ -106,13 +138,20 @@ class WineXdndProxy {
void handle_x11_events() const noexcept; void handle_x11_events() const noexcept;
private: private:
std::unique_ptr<xcb_connection_t, decltype(&xcb_disconnect)> x11_connection; /**
* We need a dedicated X11 connection for our proxy because we can have
* multiple open editors in a single process (e.g. when using VST3 plugins
* or plugin groups), and client messages are sent to the X11 connection
* that created the window. So we cannot just reuse the connection from the
* editor.
*/
std::shared_ptr<xcb_connection_t> x11_connection;
/** /**
* We need an unmapped proxy window to send and receive client messages for * We need an unmapped proxy window to send and receive client messages for
* the XDND protocol. * the XDND protocol.
*/ */
xcb_window_t proxy_window; ProxyWindow proxy_window;
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wignored-attributes" #pragma GCC diagnostic ignored "-Wignored-attributes"