SciMath Keyboard — Developer Notes

Design decisions, platform constraints, and known limitations for developers building similar keyboard extensions.

"Keep your stick on the ice. We're all in this together." — Red Green

1. Full Access and what it actually blocks

iOS keyboard extensions run in a sandboxed process. Full Access is an elevated entitlement that allows the extension to make network requests and share data with its containing app. When a user installs a third-party keyboard, iOS presents a warning that the keyboard "may be able to access everything you type." This warning is shown for all third-party keyboards regardless of whether they actually log anything.

SciMath does not request Full Access and will not. No keystrokes are logged or transmitted. The consequence is that several iOS features are unavailable:

FeatureWhy it requires Full Access
Autocorrect / predictive textiOS passes text context to the correction engine via a mechanism that requires Full Access.
DictationAudio is routed through Apple's servers. The entitlement to make that network call requires Full Access.
TranslationSame network entitlement requirement as dictation.
Note for developers: These are hard platform limits, not implementation choices. No amount of clever engineering recovers them without requesting Full Access. If your keyboard's value proposition depends on privacy — as SciMath's does — these features are simply off the table.

The microphone button is present in SciMath's iPad toolbar as a visual placeholder only. See Section 9.

SciMath also omits an emoji key by design. Users who need emoji can hold the globe key, switch to a stock system keyboard, insert the emoji, and switch back. This is documented in the user manual as the supported workaround.

2. Key preview balloons

Stock iOS keyboards show a magnified balloon preview above a key while the user's finger is down. This is implemented in Apple's private keyboard framework and is not directly available to keyboard extensions.

Extensions can approximate the behavior by rendering a popup view within their own view hierarchy. The architectural constraint is that a keyboard extension's view cannot render outside its own bounds. This means:

Note for developers: The only workaround is to make the keyboard taller to create clearance above the top row, which wastes screen real estate and looks wrong. SciMath does not do this. Top-row balloons go downward instead to avoid clipping.

3. Key flash as an alternative feedback mechanism

SciMath implements key flash: when a key is tapped, its background briefly brightens. This is distinct from the balloon preview and serves a complementary purpose.

Implementation

Key flash is an explicit UIColor change triggered on touchesBegan, not a system animation. The key brightens immediately on first contact and restores after a short interval. It does not use gesture recognition and therefore has no recognition delay.

Advantages over balloons in field conditions

Key flash is user-toggleable. The preference is stored in App Groups shared defaults so the keyboard extension and the containing app stay in sync without Full Access.

4. iOS 26 gesture regression

In iOS 26.x (May 2026), Apple introduced a regression affecting gesture detection in keyboard extensions. UIPanGestureRecognizer no longer transitions to .began on stationary contact — it waits for the finger to move. Key preview balloons depend on detecting first contact immediately; the regression broke them entirely.

This is a confirmed Apple bug, acknowledged by an Apple engineer. Filed as FB19394663 and FB19405284.

Workaround

Subclass UIPanGestureRecognizer and override touchesBegan to force state = .began on first contact:

class ImmediatePanGestureRecognizer: UIPanGestureRecognizer {
    override func touchesBegan(_ touches: Set<UITouch>,
                                with event: UIEvent) {
        super.touchesBegan(touches, with: event)
        state = .began
    }
}

Use this subclass wherever you would have used UIPanGestureRecognizer for balloon triggering. This is a supported API call, not a hack. It will continue to work after Apple fixes the underlying bug, because forcing .began on contact is valid behavior for a pan recognizer with zero minimum distance.

If you are using SwiftUI rather than UIKit, the equivalent workaround is DragGesture(minimumDistance: 0) with .simultaneousGesture(). The UIKit subclass approach above is for UIKit keyboard extensions only.

SciMath forked at v0.400 to isolate and test this workaround before forward-porting it to the full feature set.

5. iPad vs iPhone layout differences

SciMath's ABC, 123, and #+= layers match stock Apple layouts on both platforms. The sci layer is SciMath's own, with no stock equivalent to reference.

iPhone sci layer

Three rows: 10 keys, 10 keys, 7 keys. The shorter third row reflects the narrower iPhone form factor and the space taken by the toggle and backspace keys.

iPad sci layer

Three rows: 10 keys + backspace, 10 keys + return, 10 keys with toggles at both ends. The iPad's wider layout accommodates additional keys that cannot fit on iPhone without the keys becoming too small to tap reliably.

123 and #+= layers on iPad

These match stock iPadOS layout, which differs from stock iOS layout. In particular, the iPad 123 layer includes superscript hint characters above the letter keys on the ABC layer, which drove the decision to adopt the iPadOS layout rather than carrying the iPhone layout across both platforms. The layouts were kept separate rather than attempting a one-size-fits-both approach.

Note for developers: Do not assume the iPhone layout scales acceptably to iPad. The key counts, row structures, and action key placements are genuinely different between stock iOS and stock iPadOS. Match each platform independently.

6. Diacritical coverage

SciMath's long-press diacritical set is a strict superset of the stock iOS English keyboard. The stock keyboard covers the most common French and German variants. SciMath extends this to cover:

The extension is deliberate: SciMath targets technical and scientific users who frequently write in multiple languages or use scholarly romanization systems. The additional diacriticals are present because they could be added without cost to users who don't need them, and they address real gaps in the stock English keyboard.

The long-press popup respects shift state: with shift active, all alternates appear in uppercase.

Punctuation alternates added for the same reason

KeyAlternatesRationale
?⸮ ¿ ‽Percontation point for rhetorical questions; Spanish inverted; interrobang
!¡Spanish inverted
-– — •En dash, em dash, bullet

7. Keyboard background colors

Apple does not publish the RGB values for stock keyboard key colors. The semantic system colors available to extensions (UIColor.systemBackground and friends) do not match the keyboard's actual appearance — they are designed for app UI, not keyboard chrome.

SciMath uses explicit hardcoded RGB values tuned by hand against the stock keyboard in both light and dark mode. The values were arrived at empirically.

Note for developers: Do not use semantic system colors for keyboard key backgrounds. They will not match stock. Pixel-sample the stock keyboard on your target devices and tune manually. The values will be close but not identical across device generations — Apple adjusts display calibration.

Host app rendering variation

Some apps use custom text rendering pipelines rather than standard UIKit text input (Google Docs is a documented example). In these apps, third-party keyboard keys may appear with different contrast than in standard UIKit text fields. This is a host-app issue and cannot be corrected from within the keyboard extension.

Action key pressed state

The pressed-state background for action keys (return, backspace, shift) is also hardcoded. In dark mode, the pressed state lightens the key; in light mode, it goes to near-white. The values used in SciMath:

// Dark mode pressed
UIColor(red: 0.42, green: 0.42, blue: 0.44, alpha: 1.0)
// Light mode pressed
UIColor.white

8. Globe key

Stock Apple keyboards integrate the globe (keyboard switcher) into the bottom row using private layout code unavailable to extensions. SciMath handles the globe differently on each platform.

iPhone

SciMath does not draw a globe key on iPhone. iOS injects the globe automatically when needsInputModeSwitchKey returns true. The injected globe appears outside the main keyboard area rather than inline in the bottom row. This is visually distinct from stock but is the correct supported behavior — attempting to draw your own globe button and call advanceToNextInputMode() directly is unreliable and has caused issues in earlier versions.

iPad

SciMath draws its own globe on iPad using Apple's documented API: a native globe SF Symbol button, short-tap calls advanceToNextInputMode(), long-press calls handleInputModeList(from:with:) to show the language picker. This is the only supported path for iPad keyboard switcher integration.

Note for developers: Do not attempt to draw and wire your own globe button on iPhone. Use needsInputModeSwitchKey to check whether iOS will inject the globe, and leave the slot empty if so. On iPad, use the documented SF Symbol + API path above.

9. Microphone button

SciMath shows a dimmed, non-interactive microphone button in the iPad toolbar. It does nothing when tapped.

The rationale: stock iPad keyboards show a microphone button in this position. Users who switch to SciMath have muscle memory for the surrounding key positions. An absent mic button shifts every other key in the toolbar, causing misses on adjacent keys during the adjustment period. The visual placeholder preserves spatial layout at zero functional cost.

Dictation is not available in SciMath because it requires Full Access to route audio through Apple's servers. See Section 1.

Users who need dictation alongside SciMath content can hold the globe key, switch to a stock system keyboard, dictate, then switch back. This is documented in the user manual.