Keyboard focus lost and KeyCommands stop working after instantiating an AUv3 in a JUCE-based host on iOS

Hi JUCE Team,

I’m experiencing an issue with KeyCommands on iOS. When an AUv3 plugin is instantiated in my host, the application seems to lose keyboard focus, causing the key commands to stop working. They only start working again after I tap somewhere on the screen.

I tested with the latest Audio Plugin Host (develop branch) to see if the issue was related to how I manage them but I discovered it happens there too.

Could you please run some tests to investigate the cause of this issue?
If you need anything from my side, please don’t hesitate to ask.

I look forward to your response.
Best,
Samuele

Hi, please could you provide the following information:

  • What iOS versions are you testing? Do you see the same behaviour for all iOS versions that you’ve tested?
  • What is the precise series of steps that you’re taking in the AudioPluginHost in order to test this?
  • What peripherals are you using (keyboard + mouse) and how are they connected to the device? e.g. are you using a keyboard cover, connecting bluetooth peripherals to the iOS device, using a USB hub to connect wired peripherals, or using the “Continuity” feature to transfer mouse and keyboard input from a Mac on the same network?
  • Have you tried other sets of peripherals, and do you see the same results in all cases?
  • Have you tested with AUv3 plugins from different vendors, and do they all behave in the same way?

I’ve tested with iOS 26.4 on a 9th gen iPad, using Continuity to transfer keyboard/mouse input from a MacBook Pro to the iPad. So far, I’ve seen two different behaviours depending on whether I use the touchpad built into the MacBook, or an external five-button bluetooth mouse.

Steps:

  • Add some logging in pressesBegan in juce_UIViewComponentPeer_ios.mm to print [event modifierFlags].
  • Build AudioPluginHost from JUCE develop and launch on the iPad.
  • Move the mouse cursor to the iPad.
  • Press cmd + P on the keyboard.
    • When using the touchpad, the plugin list window is shown.
    • When using a bluetooth mouse, the plugin list window is not shown.
    • Log messages are printed in both cases, indicating that key events are being sent by the system to the JUCE app.
  • Close the plugin list window, then add a plugin to the graph and double-click on the node to open the plugin’s editor. I tested with Loopy Pro (non-JUCE) and the AUv3SynthDemo from the JUCE repo.
  • Immediately after opening the editor, press cmd+P again on the keyboard.
    • I observe the same behaviour as before: the plugin list window gets shown when using the internal touchpad, but not when using the external mouse. Log messages are printed in both cases.

Based on this, it looks like the external bluetooth mouse prevents keyboard shortcuts from working as expected. Interestingly, it looks like [event modifierFlags] returns zero when pressing cmd + p with the external bluetooth mouse connected. This is why the plugin window doesn’t show up - the app doesn’t know that the command key is pressed, so shortcuts that rely on the command key don’t get triggered. I need to investigate more in order to work out exactly why the keyboard modifier keys aren’t reported correctly in this case.

The issue described above sounds different to the issue you’re seeing. Although the keyboard shortcuts don’t always work as expected, the logging shows that keyboard input is reaching the app, even when an AUv3 editor is opened. Therefore, I suspect that some aspect of my test setup is different to yours. Please could you provide the information requested at the top of this post, so that we can continue investigating? Thanks!

Quick update: I tested out some keyboard shortcuts like cmd+w, cmd+q in other built-in apps (Settings, App Store) and these also seem to be broken when using my external bluetooth mouse. So, I think the issue I’m seeing is probably caused by this particular mouse and/or iOS itself, rather than something that JUCE is doing incorrectly.

Hi Reuk,

Thanks for getting back to me.

The steps to reproduce the issue are quite straightforward. I connect a Bluetooth keyboard or pedal (which sends key command messages) to the iPad, then open AudioPluginHost and load an AUv3 plugin without opening its GUI (without double‑clicking it). Without interacting with the screen, I press Cmd + P to open the plugin list, but nothing happens.

As soon as I touch the screen, even in an empty area, the keyboard input starts working again. It seems that opening an AUv3 plugin causes the host to lose focus, and any touch interaction restores it.

Is this behavior the same for you?

When testing with Camelot Pro, the issue affects all key commands, not just those that use modifier combinations. In my case, even simple inputs such as the right arrow key or a single letter fail to work until the screen is touched.

I’ve tested this across multiple iPads running iOS 26, using different Bluetooth keyboards, pedals, and keyboard covers. As far as I can tell, the issue occurs with all AUv3 plugins. I specifically tested with Numa Player, SWAM instruments, Korg Module, Synth Pro, and Animoog Z.

Following your suggestion, I also tested on an older iPad running iOS 17, where everything works as expected. This leads me to believe the issue may be related to changes in iOS. I’m not certain exactly when it was introduced, but based on user reports, it seems to have started with iOS 26.

How should we proceed in order to get this issue fixed? Is there anything you can do on your side? In the meantime, I will also try to contact Apple directly and hope to get some feedback from them.

Looking forward to hearing from you.

Thanks!

Thanks, I’d assumed the problem arose when opening the editor, not when merely instantiating the plugin.

I’m able to reproduce the problem on the iOS 26.3.1 simulator, but not on 18.6 or 15.5. So, this definitely seems to be specific to iOS 26.

I tried overriding didUpdateFocusInContext:withAnimationCoordinator: on the JUCE UIView, but this never seems to get hit.

However, if I register an object as an observer of UIFocusDidUpdateNotification on the default notification centre, then I see that the focus does get changed on iOS 26, but not on iOS 18.

[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector (focusDidChange:) name: UIFocusDidUpdateNotification object: nil];

...

- (void) focusDidChange: (NSNotification*) notification
{
    auto* userInfo = notification.userInfo;
    auto* context = (UIFocusUpdateContext*) userInfo[UIFocusUpdateContextKey];
    auto* prev = context.previouslyFocusedItem;
    auto* next = context.nextFocusedItem;
    auto heading = context.focusHeading;
    DBG ((uint64_t) prev << ' ' << (uint64_t) next << ' ' << heading);
}

In the focus change callback, I see that both the ‘next’ and ‘prev’ focus items are nil, and the focus heading is ‘none’. This is the same behaviour I see when e.g. dragging from the bottom of the screen to show the dock, or tapping on another app when in windowing mode.

On both iOS 18 and 26, I only see focusDidChange: being called when focus is lost from the app window. It doesn’t seem to be called when focus is gained, so we can’t see if/when the system is attempting to move focus back to the host app.

My current interpretation of the situation is that on iOS 26, the system is (incorrectly?) moving focus away from the host application when loading an AUv3 plugin, as though another app had been moved to the foreground. I would need to spend more time on this issue to look for potential workarounds.

Many thanks again for your time and support. I really appreciate it.
In the meantime, we are trying to get in touch with Apple, and I will come back to you as soon as I have any updates.
If you happen to find a workaround in the meantime, please let me know.

Thanks again for your help and have a great weekend.