RustAudio / baseview

low-level window system interface for audio plugin UIs
Apache License 2.0
267 stars 57 forks source link

Reparented X11 windows don't receive keyboard events when not hovering over them #116

Open robbert-vdh opened 2 years ago

robbert-vdh commented 2 years ago

An X11 window created using Windows::open_parented() will not receive keyboard input, and as a consequence of that, keyboard input for modifiers, when not hovering over the window. This makes sense as the window is not requesting input focus, but it does mean that weird things happen when you combine this with dragging gestures. When you start a dragging gesture, hold down shift, move your mouse cursor outside of the window, release shift, and then WIndowHandler won't notice shift being released, and every subsequent interaction would behave as if shift was still pressed. You can cry this out with this example using the patched baseview from #115 and Carla:

NOTE: This example has been updated with the patches from #117, so the issue no longer exists on the latest version.

git clone git@github.com:robbert-vdh/nih-plug.git
cd nih-plug
cargo xtask bundle gain_gui --bundle-vst3 && carla-single vst3 target/gain_gui.vst3

Note that this won't happen in Bitwig, as in Bitwig the host's parent window grabs focus itself and then forwards most keyboard events (except for Space and a couple other keys) to the child window.

Also, because modifiers are not sent as part of the mouse move/click events, the modifiers will be ignored when you Shift+click on a plugin GUI directly after opening the window in Bitwig because the click event arrives before the keyboard even (of it doesn't get sent at all, I'd need to check).

The potential ways to fix this would be to always grab keyboard focus, or to add modifiers to mouse move and click events. The last one is the least invasive, and I think this information is part of those events on every platform.

robbert-vdh commented 2 years ago

To add to this, I feel like the simplest way around this would be to add grab_focus() and release_focus() methods to WindowHandle, and to also add FocusIn/FocusGrabbed and FocusOut/FocusReleased events that lets the window know if received or lost focus so it can keep track if its focus state.