Fix fake dropdown menus in TDR plugins

These would close immediately when hovering over them with the new focus
grabbing method.
This commit is contained in:
Robbert van der Helm
2020-10-19 14:33:44 +02:00
parent e6af947fe1
commit 3facdf532a
3 changed files with 24 additions and 7 deletions
+2
View File
@@ -12,6 +12,8 @@ Versioning](https://semver.org/spec/v2.0.0.html).
- Fixed a regression where the `editor_double_embed` option would cause X11 - Fixed a regression where the `editor_double_embed` option would cause X11
errors and crash yabridge. errors and crash yabridge.
- Fixed a regression where certain fake dropdown menus such as those used in the
Tokyo Dawn Records plugins would close immediately when hovering over them.
### yabridgectl ### yabridgectl
+21 -6
View File
@@ -141,13 +141,15 @@ Editor::Editor(const Configuration& config,
<< std::endl; << std::endl;
} }
// Because we're not using XEmbed Wine will interpret any local coordinates // Because we're not using XEmbed, Wine will interpret any local coordinates
// as global coordinates. To work around this we'll tell the Wine window // as global coordinates. To work around this we'll tell the Wine window
// it's located at its actual coordinates on screen rather than somewhere // it's located at its actual coordinates on screen rather than somewhere
// within. For robustness's sake this should be done both when the actual // within. For robustness's sake this should be done both when the actual
// window the Wine window is embedded in (which may not be the parent // window the Wine window is embedded in (which may not be the parent
// window) is moved or resized, and when the user moves his mouse over the // window) is moved or resized, and when the user moves his mouse over the
// window because this is sometimes needed for plugin groups. // window because this is sometimes needed for plugin groups. We also listen
// for EnterNotify and LeaveNotify events on the Wine window so we can grab
// and release input focus as necessary.
const uint32_t topmost_event_mask = XCB_EVENT_MASK_STRUCTURE_NOTIFY; const uint32_t topmost_event_mask = XCB_EVENT_MASK_STRUCTURE_NOTIFY;
xcb_change_window_attributes(x11_connection.get(), topmost_window, xcb_change_window_attributes(x11_connection.get(), topmost_window,
XCB_CW_EVENT_MASK, &topmost_event_mask); XCB_CW_EVENT_MASK, &topmost_event_mask);
@@ -211,7 +213,7 @@ Editor::~Editor() {
win32_handle.reset(); win32_handle.reset();
} }
HWND Editor::get_win32_handle() { HWND Editor::get_win32_handle() const {
if (win32_child_handle) { if (win32_child_handle) {
return win32_child_handle->get(); return win32_child_handle->get();
} else { } else {
@@ -296,11 +298,24 @@ void Editor::handle_x11_events() const {
// FX window. This distinction is important, because we do not want // FX window. This distinction is important, because we do not want
// to mess with keyboard focus when hovering over the window while // to mess with keyboard focus when hovering over the window while
// for instance a dialog is open. // for instance a dialog is open.
case XCB_LEAVE_NOTIFY: case XCB_LEAVE_NOTIFY: {
if (supports_ewmh_active_window() && is_wine_window_active()) { const auto event =
reinterpret_cast<xcb_leave_notify_event_t*>(generic_event);
// This extra check for the `NonlinearVirtual` detail is
// important (see
// https://www.x.org/releases/X11R7.5/doc/x11proto/proto.html
// for more information on what this actually means). I've only
// seen this issue with the Tokyo Dawn Records plugins, but a
// plugin may create a popup window that acts as a dropdown
// without actually activating that window (unlike with an
// actual Win32 dropdown menu). Without this check these fake
// dropdowns would immediately close when hovering over them.
if (event->detail != XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL &&
supports_ewmh_active_window() && is_wine_window_active()) {
set_input_focus(false); set_input_focus(false);
} }
break; } break;
} }
free(generic_event); free(generic_event);
+1 -1
View File
@@ -115,7 +115,7 @@ class Editor {
* call. This will return the child window's handle if double editor * call. This will return the child window's handle if double editor
* embedding is enabled. * embedding is enabled.
*/ */
HWND get_win32_handle(); HWND get_win32_handle() const;
/** /**
* Returns `true` if the window manager supports the EWMH active window * Returns `true` if the window manager supports the EWMH active window