BR: Mouse-wheel messages are discarded for other plugins

DAW: Cubase 12 on Windows

If you open a JUCE plugin first (NEXUS in our case) and then open another plugin while the NEXUS UI is still open, the other plugin will not receive mouse-wheel messages anymore. Once you close NEXUS, the mouse-wheel messages arrive again.

If you open the other plugin first, and then open NEXUS, then all mouse-wheel messages arrive just fine.

This suggests, once processed, mouse-wheel messages are not calling CallNextHookEx.

juce_WindowsHooks_windows.cpp at line 71 it reads:

return PostMessage (target, WM_MOUSEWHEEL,
                                  hs.mouseData & 0xffff0000, MAKELPARAM (hs.pt.x, hs.pt.y));

If I comment out the return (but leave the PostMessage intact), then everything works as expected.

1 Like

+1 have noticed this occurring today.

My test environment is Windows 11, Cubase 13.0.40, Cubase 12.0.70, REAPER 7.20.

When I load JUCE’s AudioPluginDemo VST3 in either host, moving the mouse wheel over a dial causes the dial to move. If I then open NI Supercharger VST3, the dials in that plugin update as expected when the mouse wheel is moved over them. Dials in Steinberg’s AmpSimulator plugin and Serum_x64 also continue to respond to the mouse wheel.

My guess is that either the issue is only present with specific third-party plugins.

In order for me to continue investigating, please provide the following information:

  • With which third-party plugin have you observed the buggy behaviour?
  • Do you see the same problem with Steinberg AmpSimulator?
  • Do you see this issue in other DAWs such as REAPER?
  • Do you see the same problem when testing with JUCE’s AudioPluginDemo instead of Nexus?

I’ve analyzed it further. The problem is not that it doesn’t get forwarded; it gets sent to the wrong window.

If you make sure that your plugin windows overlap, the first plugin you open will get the mouse wheel even for windows that overlap it. You will accidentally modify parameters in the wrong plugin.

Let’s say you open AudioPluginDemo first, then open Serum_x64, and then position the Serum window on top of the AudioPluginDemo window. Make sure you have two dials on top of each other. When you use the mouse wheel to change a parameter in Serum_x64, it won’t affect Serum_x64, but the parameter in the window underneath will be changed.

The problem is that the Desktop hit-test function checks only the rectangle of the window, even if another window overlaps it. It then sends a PostMessage to that first window.

The check to find the correct windows needs to be a bit more sophisticated than simply checking its rect.

Thanks, I was able to repro the issue with the additional details.

It looks like Windows 10 changed the way that WM_MOUSEWHEEL messages work, so that they always go to the window under the mouse, even if that window doesn’t have focus. I think this means we can remove the mousewheel hook completely, and also avoid some event redirection we were doing in the ComponentPeer.

I’ll aim to push that change soon. In the meantime, you could try rmoving the mousewheel hook and see whether that resolves the problem.

I’ve commented out the body of the mousewheel hook callback, only leaving the CallNextCallback call, and now it works perfectly. No more problems with overlaps and even windows that don’t have focus receive the messages without problems.

I’ve tried in FL Studio and Cubase 12 Pro.

New problem I just discovered in Cubase 12 Pro with NEXUS UI. The titlebar has the name centered instead of left (like other plugins) and the maximise button was not disabled. So by double clicking the titlebar or clicking on the maximize button, but NEXUS UI was suddenly full screen, which had the wrong aspect ratio, so a chunk of the window is just black. For Serum, the maximise button is disabled and the name of the plugin is on the left hand side.

I suspect you’ve changed the always-on-top option for this plugin to be disabled. By default, the always-on-top option is enabled, but the window style changes to have full-size caption buttons and centred titled text when the always-on-top option is disabled.

I haven’t tried to reverse engineer this, but I suspect Cubase 12 just checks the result of IPlugView::canResize to work out whether the maximise button should be enabled. When I checked Kontakt 7, it looks like that plugin returns 1 (kResultFalse) from canResize, despite having an internal corner resizer. This also means that host-initiated resize by dragging on the window borders is disabled.

If I change the first argument of setResizable from true to false in the constructor of the AudioPluginDemo’s editor, then I see similar behaviour. The maximise button and host-initiated resize are disabled, but the internal corner resizer still works. Maybe you could check whether the host is Cubase and disable host-initiated resize in this case.

This behaviour is arguably a bug in Cubase 12. According to the VST3 docs, IPlugView::checkSizeConstraint should be used to check whether the plugin actually supports a given size before performing a resize, but Cubase 12 doesn’t seem to check whether the fullscreen bounds are supported before entering the maximised state.

Is it disabled, or completely invisible? If you toggle always-on-top, what happens?

For Serum_x64 the always-on-top flag doesn’t matter. The text stays always on the left hand side and with always-on-top enabled, there is only a close button and with always-on-top disabled, the maximize button is visible, but disabled (greyed out, not clickable)

With NEXUS, it’s broken when “always-on-top” is disabled. Text is centered, and the maximize button is clickable.

If NEXUS is using “always-on-top” then it’s equal to Serum_x64, so the text is left aligned and there are no window buttons except the close button.

I consider the JUCE behavior a bug here. The text moving back and forth between centered and left-aligned is not a good look, and the maximize button should not be clickable.

Sounds like you’re seeing different behaviour to me. Windows 11, Cubase 12.0.70:


Serum’s caption buttons change depending on the always-on-top setting, but the title text is always left-aligned. I see exactly the same behaviour for Kontakt 7.

For the stock AudioPluginDemo, the results are slightly different:


When the maximise button is enabled, the title text seems to get centred too.
However, if I make the tweak I suggested earlier (disabling host-initiated resize in the AudioPluginDemo editor’s constructor), then I get this:


I disagree. The behaviour you’re referring to is host behaviour based on the result of canResize. It’d be wrong for JUCE to internally override the result of canResize based on the host, because some plugins might be fine with running in full-screen and/or want edge-resizing.

JUCE has no control over what the host decides to do with its title bars.

As I mentioned earlier, you can control this by changing the first argument to setResizable in your editor. However, in Cubase 12 this single bool controls all forms of host-initiated resize, so if you disable it you’ll miss out on edge-resizing (like Serum and Kontakt). Some plugins may be infinitely resizable, so it’d be wrong for JUCE to attempt to detect Cubase 12 and disable host-initiated resize in that case.

I want to reiterate that there exists in the VST3 API a function for the host to check whether the plugin supports a particular editor size, and JUCE implements this function using the plugin editor’s constrainer. Cubase 12 doesn’t seem to use this API when it decides whether or not to enable the maximise button.

We’ve pushed some changes to develop that should resolve the issues with mouse wheel messages:

1 Like

I can confirm that it works as expected, and the resizing issue is also fixed when changing the first argument of setResizeable.