Use WM_WINDOW_ROLE instead of WM_STATE to detect the host window

Ardour brings up the plugin UI before the host window is visible, and it
is missing some properties. Using WM_WINDOW_ROLE instead of WM_STATE
makes it work.

For reference, these are the properties that are set on the window at
the time of plugin GUI instantiation:

_NET_WM_ICON(CARDINAL) =        Icon (16 x 16):
WM_WINDOW_ROLE(STRING) = "plugin_ui"
_NET_WM_SYNC_REQUEST_COUNTER(CARDINAL) = 6294918
_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_UTILITY
_NET_WM_USER_TIME_WINDOW(WINDOW): window id # 0x600d85
WM_CLIENT_LEADER(WINDOW): window id # 0x600001
_NET_WM_PID(CARDINAL) = 1604801
WM_LOCALE_NAME(STRING) = "en_US.UTF-8"
WM_CLIENT_MACHINE(STRING) = "homura"
WM_NORMAL_HINTS(WM_SIZE_HINTS):
                program specified size: 521 by 46
WM_PROTOCOLS(ATOM): protocols  WM_DELETE_WINDOW, WM_TAKE_FOCUS, _NET_WM_PING, _NET_WM_SYNC_REQUEST
WM_CLASS(STRING) = "ardour-8.12.0", "Ardour-8.12.0"
WM_ICON_NAME(STRING) = "Audio 1: Melodyne (by Celemony) [VST3]"
_NET_WM_ICON_NAME(UTF8_STRING) = "Audio 1: Melodyne (by Celemony) [VST3]"
WM_NAME(STRING) = "Audio 1: Melodyne (by Celemony) [VST3]"
_NET_WM_NAME(UTF8_STRING) = "Audio 1: Melodyne (by Celemony) [VST3]"
This commit is contained in:
Asahi Lina
2025-05-22 11:00:41 +09:00
committed by Robbert van der Helm
parent e18d598c7e
commit 9994043306
2 changed files with 19 additions and 6 deletions
+14 -6
View File
@@ -87,13 +87,18 @@ constexpr uint32_t wrapper_event_mask =
constexpr char active_window_property_name[] = "_NET_ACTIVE_WINDOW";
/**
* We'll use this property to filter windows for `host_window_`. Like `xprop`
* and `xwininfo`, we'll only consider windows with this property set, although
* we won't filter on whether or not the window is actually visible because it
* may be minimalized when the plugin's GUI is being opened.
* We'll set this property on the Wine window to emulate the behavior of
* a minimal window manager.
*/
constexpr char icccm_wm_state_property_name[] = "WM_STATE";
/**
* We'll use this property to filter windows for `host_window_`. WM_STATE
* can end up being set too late during window initialization, so we miss
* identifying the host window.
*/
constexpr char icccm_wm_window_role_property_name[] = "WM_WINDOW_ROLE";
/**
* This `WM_STATE` property value indicates that a window is a visible top level
* window. Needs to be set on Wine's window as part of emulating the behavior of
@@ -292,6 +297,9 @@ Editor::Editor(MainContext& main_context,
}),
xcb_wm_state_property_(
get_atom_by_name(*x11_connection_, icccm_wm_state_property_name)),
xcb_wm_window_role_property_(
get_atom_by_name(*x11_connection_,
icccm_wm_window_role_property_name)),
parent_window_(parent_window_handle),
wrapper_window_(
x11_connection_,
@@ -316,7 +324,7 @@ Editor::Editor(MainContext& main_context,
wine_window_(get_x11_handle(win32_window_.handle_)),
host_window_(find_host_window(*x11_connection_,
parent_window_,
xcb_wm_state_property_)
xcb_wm_window_role_property_)
.value_or(parent_window_)) {
logger.log_editor_trace([&]() {
return "DEBUG: host_window: " + std::to_string(host_window_);
@@ -931,7 +939,7 @@ bool Editor::is_wine_window_active() const {
void Editor::redetect_host_window() noexcept {
const xcb_window_t new_host_window =
find_host_window(*x11_connection_, parent_window_,
xcb_wm_state_property_)
xcb_wm_window_role_property_)
.value_or(parent_window_);
if (new_host_window == host_window_) {
return;