mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-10 04:30:12 +02:00
Create a window for the X11 proxy
This commit is contained in:
@@ -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) {}
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user