Key press stolen in FL / Studio One

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

I've noticed that some plugins steal keyboard focus in FL and Studio One on windows once you have clicked in the UI, you have to click back in a host window to use host shortcuts again. It seems to happen with VSTGUI and IPlug. Does anyone know what is different about these hosts and how to pass the key press back to the host?

thanks

Post

Those hosts where this happens just follow the standard way of handling keyboard focus in Windows; I would argue that any host that is immune does something "different" instead.

FL actually has a wrapper option for preventing plugins from taking the keyboard focus, but IIRC at least in FL it should be enough to pass keyboard messages (WM_KEYUP, WM_KEYDOWN and WM_CHAR.. that's probably enough I guess) to DefWindowProc when you want to "pass-through" the keys; that way all the messages should get delivered to the parent window. It should also be possible to look at the messages and handle some of them while passing through others.

Now, since this generally happens with plugins using "toolkits" I'd imagine the toolkits have some simplistic keyboard dispatch method, that always consumes every keypress they receive. Assuming the toolkit in question has a sane "event bubbling" logic, it should be relatively simple to modify the low-level code to check whether the event floated back to the top unconsumed, and pass it through to DefWindowProc. I won't promise this is enough, but IIRC it should be.

Post

If you're willing to wait a day or two, I can give you more definite answers about what exactly is and isn't required; I need to add some keyboard handling into one my plugin projects, and I intend to only capture those keys that I actually use...

Post

I had a nightmare handling key presses and passing to host etc. and so in the end I don't trap any key messages with my wndproc but instead use effEditKeyUp and effEditKeyDown messages. That seems to work much better.

Post

mystran wrote:If you're willing to wait a day or two, I can give you more definite answers about what exactly is and isn't required; I need to add some keyboard handling into one my plugin projects, and I intend to only capture those keys that I actually use...
thanks for the info, i'm interested in your findings. I've actually managed to get it working using some code that I was using for RTAS.

Code: Select all

if (!handle) // if we didn't handle the message
{
//#ifdef RTAS_API
  HWND rootHWnd = GetAncestor( hWnd, GA_ROOT);
  SendMessage(rootHWnd, WM_KEYDOWN, wParam, lParam);
  //#endif
  return DefWindowProc(hWnd, msg, wParam, lParam);
 }
So far it seems to do the trick. I need to read up on this stuff though to make sure it's not going to cause more problems in other hosts (seems ok on initial testing).

oli

Post

Ah, indeed you're right. DefWindowProc is not enough.. hmmh..

edit: I'm not convinced the GetAncestor/GA_ROOT approach is ideal though, since there's no reason to believe that it's necessarily the root window that host wants to use for it's keyboard handling...

edit2: one alternative would be to never take focus, but simply hook the keys you want (assuming you want any; if you don't just never take focus).. but hooking isn't totally trivial either..

edit3: rather than use GetAncestor, one could take the return value of SetFocus(), which is specified to be the previous window that had the keyboard focus; I tried this and it works fine at least in FL.. specifically, when ever you activate a plugin window with mouse, FL will reset the keyboard focus, so if you then SetFocus in WM_LBUTTONDOWN the return value of SetFocus will still point to the right place.. which makes sense. I'm still not convinced it's ideal, though.

Post

rant mode: why exactly doesn't Windows bubble events properly?!?

Post

Anyway, the obvious solution is to never to take focus in the first place, unless you really plan to redirect the keyboard; mouse messages get the modifiers in any case (ctrl, shift, alt), so it's only really a problem if you want some keys but not others (say, want arrow keys, but not main keyboard.. or something).

Post

Keith99 wrote:I had a nightmare handling key presses and passing to host etc. and so in the end I don't trap any key messages with my wndproc but instead use effEditKeyUp and effEditKeyDown messages. That seems to work much better.
Are these actually supported by hosts on Windows too? I always thought they were supposed to be legacy pre-OSX Mac work-around or something similar.. :o

Post

Also regarding effEditKeyDown/effEditKeyUp: this seems rather under-specified, an quite lacking in functionality as well, if you plan on making a proper text-edit field or something...

Post

mystran wrote:Also regarding effEditKeyDown/effEditKeyUp: this seems rather under-specified, an quite lacking in functionality as well, if you plan on making a proper text-edit field or something...
Well I came across them by accident after just started programming VSTs so did not know their history. Nobody using my Sound Rider plugin has had any issues with key presses though so they seem to work OK. If you return true from them the host does not handle them otherwise it does.

Post

I don't really need keyboard input in the plug-in window. However, AFAIK on Windows you also need keyboard focus if you want to receive mouse wheel messages. So while not setting focus will fix the keyboard stealing issue in FL Studio, it will also disables mouse wheel support in the plug-in's GUI.

Post

Tale - even if you don't use the keyboard shortcut your plugs still block the space bar, and probably other keys in FL/Studio One, after the gui is clicked.

Post

Tale wrote:I don't really need keyboard input in the plug-in window. However, AFAIK on Windows you also need keyboard focus if you want to receive mouse wheel messages. So while not setting focus will fix the keyboard stealing issue in FL Studio, it will also disables mouse wheel support in the plug-in's GUI.
There's a "vendorSpecific" (not really, it's common to all hosts) in VST to handle mouse wheel: check for index == 0x73744341 && value == 0x57686565, then "opt" parameter will be -1 or 1 depending on direction.

edit:
Since I'm not sure if I've change the parameter names, here's the prototype

VstIntPtr MyPlug::vendorSpecific(VstInt32 index, VstIntPtr value, void* ptr, float opt);

Post

mystran wrote:There's a "vendorSpecific" (not really, it's common to all hosts) in VST to handle mouse wheel: check for index == 0x73744341 && value == 0x57686565, then "opt" parameter will be -1 or 1 depending on direction.

edit:
Since I'm not sure if I've change the parameter names, here's the prototype

VstIntPtr MyPlug::vendorSpecific(VstInt32 index, VstIntPtr value, void* ptr, float opt);
Well, all hosts... REAPER doesn't seem to support it. But indeed FL Studio and VSTHost do, so thanks for the info. :)

Post Reply

Return to “DSP and Plugin Development”