mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-09 20:29:10 +02:00
Change editor window destruction order
The wrapper window can only be removed after we reparented the Wine window back to the root.
This commit is contained in:
+27
-27
@@ -242,6 +242,31 @@ Editor::Editor(MainContext& main_context,
|
|||||||
logger(logger),
|
logger(logger),
|
||||||
x11_connection(xcb_connect(nullptr, nullptr), xcb_disconnect),
|
x11_connection(xcb_connect(nullptr, nullptr), xcb_disconnect),
|
||||||
dnd_proxy_handle(WineXdndProxy::get_handle()),
|
dnd_proxy_handle(WineXdndProxy::get_handle()),
|
||||||
|
xcb_wm_state_property(
|
||||||
|
get_atom_by_name(*x11_connection, wm_state_property_name)),
|
||||||
|
parent_window(parent_window_handle),
|
||||||
|
host_window(find_host_window(*x11_connection,
|
||||||
|
parent_window,
|
||||||
|
xcb_wm_state_property)
|
||||||
|
.value_or(parent_window)),
|
||||||
|
wrapper_window(
|
||||||
|
x11_connection,
|
||||||
|
[parent_window = parent_window](
|
||||||
|
std::shared_ptr<xcb_connection_t> x11_connection,
|
||||||
|
xcb_window_t window) {
|
||||||
|
xcb_generic_error_t* error = nullptr;
|
||||||
|
const xcb_query_tree_cookie_t query_cookie =
|
||||||
|
xcb_query_tree(x11_connection.get(), parent_window);
|
||||||
|
const std::unique_ptr<xcb_query_tree_reply_t> query_reply(
|
||||||
|
xcb_query_tree_reply(x11_connection.get(), query_cookie,
|
||||||
|
&error));
|
||||||
|
THROW_X11_ERROR(error);
|
||||||
|
|
||||||
|
xcb_create_window(x11_connection.get(), XCB_COPY_FROM_PARENT,
|
||||||
|
window, query_reply->root, 0, 0, 128, 128, 0,
|
||||||
|
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||||
|
XCB_COPY_FROM_PARENT, 0, nullptr);
|
||||||
|
}),
|
||||||
client_area(get_maximum_screen_dimensions(*x11_connection)),
|
client_area(get_maximum_screen_dimensions(*x11_connection)),
|
||||||
// Create a window without any decoratiosn for easy embedding. The
|
// Create a window without any decoratiosn for easy embedding. The
|
||||||
// combination of `WS_EX_TOOLWINDOW` and `WS_POPUP` causes the window to
|
// combination of `WS_EX_TOOLWINDOW` and `WS_POPUP` causes the window to
|
||||||
@@ -275,6 +300,7 @@ Editor::Editor(MainContext& main_context,
|
|||||||
nullptr,
|
nullptr,
|
||||||
GetModuleHandle(nullptr),
|
GetModuleHandle(nullptr),
|
||||||
this)),
|
this)),
|
||||||
|
wine_window(get_x11_handle(win32_window.handle)),
|
||||||
// If `config.editor_double_embed` is set, then we'll also create a child
|
// If `config.editor_double_embed` is set, then we'll also create a child
|
||||||
// window in `win32_child_window`. If we do this before calling
|
// window in `win32_child_window`. If we do this before calling
|
||||||
// `ShowWindow()` on `win32_window` we'll run into X11 errors.
|
// `ShowWindow()` on `win32_window` we'll run into X11 errors.
|
||||||
@@ -288,33 +314,7 @@ Editor::Editor(MainContext& main_context,
|
|||||||
config.event_loop_interval())
|
config.event_loop_interval())
|
||||||
.count())
|
.count())
|
||||||
: Win32Timer()),
|
: Win32Timer()),
|
||||||
idle_timer_proc(std::move(timer_proc)),
|
idle_timer_proc(std::move(timer_proc)) {
|
||||||
xcb_wm_state_property(
|
|
||||||
get_atom_by_name(*x11_connection, wm_state_property_name)),
|
|
||||||
parent_window(parent_window_handle),
|
|
||||||
wrapper_window(
|
|
||||||
x11_connection,
|
|
||||||
[parent_window = parent_window](
|
|
||||||
std::shared_ptr<xcb_connection_t> x11_connection,
|
|
||||||
xcb_window_t window) {
|
|
||||||
xcb_generic_error_t* error = nullptr;
|
|
||||||
const xcb_query_tree_cookie_t query_cookie =
|
|
||||||
xcb_query_tree(x11_connection.get(), parent_window);
|
|
||||||
const std::unique_ptr<xcb_query_tree_reply_t> query_reply(
|
|
||||||
xcb_query_tree_reply(x11_connection.get(), query_cookie,
|
|
||||||
&error));
|
|
||||||
THROW_X11_ERROR(error);
|
|
||||||
|
|
||||||
xcb_create_window(x11_connection.get(), XCB_COPY_FROM_PARENT,
|
|
||||||
window, query_reply->root, 0, 0, 128, 128, 0,
|
|
||||||
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
|
||||||
XCB_COPY_FROM_PARENT, 0, nullptr);
|
|
||||||
}),
|
|
||||||
wine_window(get_x11_handle(win32_window.handle)),
|
|
||||||
host_window(find_host_window(*x11_connection,
|
|
||||||
parent_window,
|
|
||||||
xcb_wm_state_property)
|
|
||||||
.value_or(parent_window)) {
|
|
||||||
logger.log_editor_trace(
|
logger.log_editor_trace(
|
||||||
[&]() { return "DEBUG: host_window: " + std::to_string(host_window); });
|
[&]() { return "DEBUG: host_window: " + std::to_string(host_window); });
|
||||||
logger.log_editor_trace([&]() {
|
logger.log_editor_trace([&]() {
|
||||||
|
|||||||
+42
-42
@@ -306,6 +306,44 @@ class Editor {
|
|||||||
*/
|
*/
|
||||||
WineXdndProxy::Handle dnd_proxy_handle;
|
WineXdndProxy::Handle dnd_proxy_handle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The atom corresponding to `WM_STATE`.
|
||||||
|
*/
|
||||||
|
xcb_atom_t xcb_wm_state_property;
|
||||||
|
/**
|
||||||
|
* The window handle of the editor window created by the DAW.
|
||||||
|
*/
|
||||||
|
const xcb_window_t parent_window;
|
||||||
|
/**
|
||||||
|
* The toplevel X11 window `parent_window` is contained in, or
|
||||||
|
* `parent_window` if the host doesn't do any fancy window embedding. We'll
|
||||||
|
* find this by looking for the topmost ancestor window of `parent_window`
|
||||||
|
* that has `WM_STATE` set. This is similar to how `xprop` and `xwininfo`
|
||||||
|
* select windows. In most cases this is going to be the same as
|
||||||
|
* `parent_window`, but some DAWs (such as REAPER) embed `parent_window`
|
||||||
|
* into another window. We have to listen for configuration changes on this
|
||||||
|
* topmost window to know when the window is being dragged around, and when
|
||||||
|
* returning keyboard focus to the host we'll focus this window.
|
||||||
|
*
|
||||||
|
* NOTE: When reopening a REAPER FX window that has previously been closed,
|
||||||
|
* REAPER will initialize the first plugin's editor first before
|
||||||
|
* opening the window. This means that the topmost FX window doesn't
|
||||||
|
* actually exist yet at that point, so we need to redetect this
|
||||||
|
* later.
|
||||||
|
* NOTE: Taking the very topmost window is not an option, because for some
|
||||||
|
* reason REAPER will only process keyboard input for that window when
|
||||||
|
* the mouse is within the window.
|
||||||
|
*/
|
||||||
|
xcb_window_t host_window;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A window that sits between `parent_window` and `wine_window`. The entire
|
||||||
|
* purpose of this is to prevent the host from responding to the
|
||||||
|
* `ConfigureNotify` events we send to `wine_window` when the host
|
||||||
|
* subscribes to `SubStructureNotify` events on `parent_window`.
|
||||||
|
*/
|
||||||
|
X11Window wrapper_window;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Wine window's client area, or the maximum size of that window. This
|
* The Wine window's client area, or the maximum size of that window. This
|
||||||
* will be set to a size that's large enough to be able to enter full screen
|
* will be set to a size that's large enough to be able to enter full screen
|
||||||
@@ -322,6 +360,10 @@ class Editor {
|
|||||||
* embed itself in.
|
* embed itself in.
|
||||||
*/
|
*/
|
||||||
DeferredWin32Window win32_window;
|
DeferredWin32Window win32_window;
|
||||||
|
/**
|
||||||
|
* The X11 window handle of the window belonging to `win32_window`.
|
||||||
|
*/
|
||||||
|
const xcb_window_t wine_window;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A child window embedded inside of `win32_window`. This is only used if
|
* A child window embedded inside of `win32_window`. This is only used if
|
||||||
@@ -350,48 +392,6 @@ class Editor {
|
|||||||
*/
|
*/
|
||||||
std::optional<fu2::unique_function<void()>> idle_timer_proc;
|
std::optional<fu2::unique_function<void()>> idle_timer_proc;
|
||||||
|
|
||||||
/**
|
|
||||||
* The atom corresponding to `WM_STATE`.
|
|
||||||
*/
|
|
||||||
xcb_atom_t xcb_wm_state_property;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The window handle of the editor window created by the DAW.
|
|
||||||
*/
|
|
||||||
const xcb_window_t parent_window;
|
|
||||||
/**
|
|
||||||
* A window that sits between `parent_window` and `wine_window`. The entire
|
|
||||||
* purpose of this is to prevent the host from responding to the
|
|
||||||
* `ConfigureNotify` events we send to `wine_window` when the host
|
|
||||||
* subscribes to `SubStructureNotify` events on `parent_window`.
|
|
||||||
*/
|
|
||||||
X11Window wrapper_window;
|
|
||||||
/**
|
|
||||||
* The X11 window handle of the window belonging to `win32_window`.
|
|
||||||
*/
|
|
||||||
const xcb_window_t wine_window;
|
|
||||||
/**
|
|
||||||
* The toplevel X11 window `parent_window` is contained in, or
|
|
||||||
* `parent_window` if the host doesn't do any fancy window embedding. We'll
|
|
||||||
* find this by looking for the topmost ancestor window of `parent_window`
|
|
||||||
* that has `WM_STATE` set. This is similar to how `xprop` and `xwininfo`
|
|
||||||
* select windows. In most cases this is going to be the same as
|
|
||||||
* `parent_window`, but some DAWs (such as REAPER) embed `parent_window`
|
|
||||||
* into another window. We have to listen for configuration changes on this
|
|
||||||
* topmost window to know when the window is being dragged around, and when
|
|
||||||
* returning keyboard focus to the host we'll focus this window.
|
|
||||||
*
|
|
||||||
* NOTE: When reopening a REAPER FX window that has previously been closed,
|
|
||||||
* REAPER will initialize the first plugin's editor first before
|
|
||||||
* opening the window. This means that the topmost FX window doesn't
|
|
||||||
* actually exist yet at that point, so we need to redetect this
|
|
||||||
* later.
|
|
||||||
* NOTE: Taking the very topmost window is not an option, because for some
|
|
||||||
* reason REAPER will only process keyboard input for that window when
|
|
||||||
* the mouse is within the window.
|
|
||||||
*/
|
|
||||||
xcb_window_t host_window;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The atom corresponding to `_NET_ACTIVE_WINDOW`.
|
* The atom corresponding to `_NET_ACTIVE_WINDOW`.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user