Capturing key presses of plugins


#1

I wonder how to properly capture the keys from a plugin window, so the plugin host application receives them as if they were pressed in there (For instance, when I press CTRL+Z when the plugin window is focused, this should still provoke the ApplicationCommand “Undo” in the plugin host app).

So far, what I found out is:

  1. It is possible to receive KeyPresses via ThePluginWindow::keyPressed(), but funnily enough this only works after opening the plugin window, then clicking the host app so it gets focused, then clicking back on the plugin window so it gets focused back again.
  2. I forward the KeyPress to the app’s MainComponent, but then I don’t know what to do. I would like the KeyPress handling to be as if the key was pressed in the app, but calling Component::getPeer()->handleKeyPress() results in a stack overflow. I don’t know what’s the proper way to do this.

Any help appreciated!


#2

This is a whole can of worms, because all the hosts have different and strange behaviours… Some intercept all the keypresses, others don’t, and each platform is also very different. There are lots of other threads bemoaning this kind of thing, but there are as many problems and hacky workarounds as there are hosts.


#3

(please note that I’m writing a host, not a plugin!)
So, how would you suggest my JUCE-based host app to do it? I’m asking, because in the PluginHost demo, you don’t intercept keys from the plugins either.


#4

Oh sorry, misread your post…! Not sure about that, it’s a long time since I looked at that bit of code… I’m going to be revisiting the plugin hosting stuff in the next few weeks for a project of my own, so will probably hit this problem myself; in the meantime, any info from other hosters would be welcome…


#5

But in general, how do you route KeyPresses from one JUCE DocumentWindow (that is currently focused), to another non-focused JUCE DoumentWindow so the second DocumentWindow actually treats the KeyPresses as if they’d happened in itself, although it is not focused?


#6

Really, the only safe way to do it would be to register a key listener and get the events that way. Don’t try to redeliver events manually, it’ll end in tears - the mechanisms involved in getting events to the right place are surprisingly complicated.


#7

Ok, will try! Thanks!


#8

OK, I checked and the KeyPresses are well received - but now where should I route this KeyPresses to? What I want is that the host app behaves as if the key was pressed in itself (and it should react to combinations such as CTRL+Z). My MainController class inherits from ApplicationCommandManager - and I still want the keyboard shortcuts (at least CTRL+Z and CTRL-Y, SPACE to stop/start) to work via the ApplicationCommandManager.

I tried:

bool MainComponent::keyPressed (const KeyPress &key, Component *originatingComponent) { return getPeer()->handleKeyPress(key.getKeyCode(), key.getTextCharacter()); }

which results in a stack overflow, as the function seems to route the KeyPress back to the Plugin window.

This seems to work, but it’s kinda lame & hacky:

bool MainComponent::keyPressed (const KeyPress &key, Component *originatingComponent) { grabKeyboardFocus(); return getPeer()->handleKeyPress(key.getKeyCode(), key.getTextCharacter()); }

The problem with the second approach seems to be that, after the MainComponent gained the keyboard focus (after first key press in Plugin window) and then clicking on the Plugin window again, the mechanism does not work anymore, as if the Plugin window stopped to receive the keys?!


#9

If you want the ApplicationCommandManager to receive the keypresses, then just register its KeyPressMappingSet directly with the window you’re interested in. You don’t need to forward the events yourself.


#10

Doesn’t work. I give up.