BUG REPORT - JUCE & TRACKTION: Third party plugin don't pass keyboard events to JUCE correctly

This bug seems to exhibit itself only on Windows, with Tracktion Waveform and also on my own JUCE application which hosts VST3 plugins. I’ve tested Mac and Windows platforms so far.

How to reproduce:

  1. Load a VST3 plugin into a Windows application/DAW which has been made with JUCE and which hosts VST3 plugins. Tracktion Waveform can be used for this.
  2. Tweak the VST3 plugin’s knobs/sliders with your mouse.
  3. Now hit Spacebar to start playback of the DAW.
  4. Nothing happens.

Many VST3 plugins on Windows seem to steal all keyboard events as long as the VST3 plugin window has keyboard focus. This bug doesn’t happen on Ableton Live 11. Ableton Live works correctly, while Tracktion Waveform and applications made with JUCE exhibit this bug.

VST3 plugins made with JUCE seem to behave correctly, while third party plugins probably not made with JUCE have this issue I described above.

List of plugins I’ve tested so far, which all exhibit this buggy behavior:

  • Native Instruments FM8
  • Native Instruments Massive
  • Native Instruments Battery
  • Reveal Sound Spire
  • U-he Zebra2
  • U-he Zebralette

Those are almost all the VST3 plugins I have installed on my Windows and they all exhibited this same issue.

This behavior doesn’t seem to exhibit itself with Arturia MiniFreak V. (Was it made with JUCE?)

Here’s is the thread where I noticed this bug. You can read more details about tests I’ve performed regarding this buggy keyboard behavior:

1 Like

I think what’s going on is that in a JUCE host, we rely on the system to send keyboard events to the currently focused HWND, including plugin editors that have focus. JUCE plugins (and presumably other plugins with working keyboard input, like Melodyne and BlueCat PlugNScript) will then post this message back to the parent window to handle, in the event that the plugin itself doesn’t handle the event.

Some plugins, like Zebralette and Kontakt, seem not to post unhandled messages back up to the host, which is why these messages don’t reach JUCE hosts.

Comparing the behaviour of JUCE hosts to REAPER, it looks like REAPER is doing something (potentially using its own keyboard hook, or redirecting keyboard messages in some other way) to ensure that it receives keyboard messages first. That is, it seems to prevent the system from sending keyboard messages directly to the focused editor, and instead sends each message to the plugin’s IPlugView::onKeyDown. Then, if onKeyDown reports that the keypress wasn’t used, REAPER attempts to use the key itself. Finally, if REAPER didn’t use the key, it sends the keypress back to the plugin editor’s wndProc as a normal WM_KEYDOWN. (I might have some details wrong, I don’t have the REAPER source so I’m basing this on debugger output.)

I’ll think carefully about whether we can do something similar in JUCE. I’ll need to do some more investigation to work out whether such a change could be made (and made safely).

In the meantime, you might consider reporting the keyboard handling issues in NI/U-he products to their respective support teams - I believe the issue could be fixed on their side by making sure that unused keyboard events are posted back to the DAW for further processing. Certainly, there exist non-JUCE plugins that are capable of handling keyboard events in a way that works in JUCE hosts, so it should be possible to get the desired behaviour from the plugin side rather than the host side.


I reported the issue to NI and U-he.