Key press stolen in FL / Studio One
-
- KVRian
- Topic Starter
- 876 posts since 24 Jun, 2002 from Berlin
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
thanks
- KVRAF
- 7891 posts since 12 Feb, 2006 from Helsinki, Finland
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.
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.
- KVRAF
- 7891 posts since 12 Feb, 2006 from Helsinki, Finland
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...
-
- KVRian
- 1256 posts since 15 Mar, 2007 from Yorkshire, England
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.
-
- KVRian
- Topic Starter
- 876 posts since 24 Jun, 2002 from Berlin
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.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...
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);
}
oli
- KVRAF
- 7891 posts since 12 Feb, 2006 from Helsinki, Finland
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.
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.
- KVRAF
- 7891 posts since 12 Feb, 2006 from Helsinki, Finland
- KVRAF
- 7891 posts since 12 Feb, 2006 from Helsinki, Finland
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).
- KVRAF
- 7891 posts since 12 Feb, 2006 from Helsinki, Finland
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..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.
- KVRAF
- 7891 posts since 12 Feb, 2006 from Helsinki, Finland
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...
-
- KVRian
- 1256 posts since 15 Mar, 2007 from Yorkshire, England
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.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...
- KVRian
- 519 posts since 12 Apr, 2010 from The Netherlands
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.
-
- KVRian
- Topic Starter
- 876 posts since 24 Jun, 2002 from Berlin
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.
- KVRAF
- 7891 posts since 12 Feb, 2006 from Helsinki, Finland
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.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.
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);
- KVRian
- 519 posts since 12 Apr, 2010 from The Netherlands
Well, all hosts... REAPER doesn't seem to support it. But indeed FL Studio and VSTHost do, so thanks for the info.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);