diff --git a/src/wine-host/xdnd-proxy.cpp b/src/wine-host/xdnd-proxy.cpp index e34769d6..b18b9997 100644 --- a/src/wine-host/xdnd-proxy.cpp +++ b/src/wine-host/xdnd-proxy.cpp @@ -89,30 +89,18 @@ void CALLBACK dnd_winevent_callback(HWINEVENTHOOK hWinEventHook, std::optional find_escape_keycode( xcb_connection_t& x11_connection); -ProxyWindow::ProxyWindow(std::shared_ptr 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 { +X11Window::~X11Window() noexcept { if (!is_moved) { xcb_destroy_window(x11_connection.get(), window); xcb_flush(x11_connection.get()); } } -ProxyWindow::ProxyWindow(ProxyWindow&& o) noexcept +X11Window::X11Window(X11Window&& o) noexcept : x11_connection(std::move(o.x11_connection)), window(std::move(o.window)) { o.is_moved = true; } -ProxyWindow& ProxyWindow::operator=(ProxyWindow&& o) noexcept { +X11Window& X11Window::operator=(X11Window&& o) noexcept { if (&o != this) { x11_connection = std::move(o.x11_connection); window = std::move(o.window); @@ -125,7 +113,19 @@ ProxyWindow& ProxyWindow::operator=(ProxyWindow&& o) noexcept { WineXdndProxy::WineXdndProxy() : x11_connection(xcb_connect(nullptr, nullptr), xcb_disconnect), - proxy_window(x11_connection), + proxy_window( + x11_connection, + [](std::shared_ptr x11_connection, + xcb_window_t window) { + 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); + }), hook_handle( SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, diff --git a/src/wine-host/xdnd-proxy.h b/src/wine-host/xdnd-proxy.h index 9e01d922..9173ac48 100644 --- a/src/wine-host/xdnd-proxy.h +++ b/src/wine-host/xdnd-proxy.h @@ -32,26 +32,38 @@ #include "utils.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. + * A RAII wrapper for creating an X11 window. */ -class ProxyWindow { +class X11Window { public: /** - * Create the proxy window. + * Create the window. + * + * @param x11_connection The X11 connection to use for creating this window. + * Events sent to the window will be received here. + * @param create_window_fn A function receiving the X11 connection and the + * window ID that should call `xcb_create_window()`. The function doesn't + * need to call `xcb_flush()`. */ - ProxyWindow(std::shared_ptr x11_connection); + template , xcb_window_t> F> + X11Window(std::shared_ptr x11_connection, + F&& create_window_fn) + : x11_connection(x11_connection), + window(xcb_generate_id(x11_connection.get())) { + create_window_fn(x11_connection, window); + xcb_flush(x11_connection.get()); + } /** * Destroy the window again when this object gets dropped. */ - ~ProxyWindow() noexcept; + ~X11Window() noexcept; - ProxyWindow(const ProxyWindow&) noexcept = delete; - ProxyWindow& operator=(const ProxyWindow&) noexcept = delete; + X11Window(const X11Window&) noexcept = delete; + X11Window& operator=(const X11Window&) noexcept = delete; - ProxyWindow(ProxyWindow&&) noexcept; - ProxyWindow& operator=(ProxyWindow&&) noexcept; + X11Window(X11Window&&) noexcept; + X11Window& operator=(X11Window&&) noexcept; private: std::shared_ptr x11_connection; @@ -222,10 +234,10 @@ class WineXdndProxy { std::shared_ptr x11_connection; /** - * We need an unmapped proxy window to send and receive client messages for - * the XDND protocol. + * We need an unmapped 1x1 proxy window to send and receive client messages + * for the XDND protocol. */ - ProxyWindow proxy_window; + X11Window proxy_window; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wignored-attributes"