This document tracks NXKit against the portable, application-facing core of Apple's UIKit. It is both a compatibility audit and an implementation roadmap.
- Last audited: 2026-08-06
- NXKit revision: working tree after
158ed66 - UIKit-cross-platform reference:
ed2c290
Any patch that changes a UIKit-facing public API or its behavior must update this document in the same patch. Follow the maintenance contract in AGENTS.md.
Statuses describe behavior, not declarations:
- Usable — the listed core behavior is available and has no known application-blocking defect; this does not imply every Apple overload or convenience API exists.
- Partial — a meaningful subset works, but important behavior, fidelity, or verification is missing.
- Stub/unsafe — the public surface exists but is empty, misleading, or has a known correctness/lifetime blocker.
- Missing — no equivalent implementation exists.
- Alternative — NXKit intentionally solves the need with a different, non-source-compatible API.
- Out of scope — intentionally excluded from the current portable-core target.
Priorities:
- P0 — required for a dependable small application.
- P1 — required by most production applications.
- P2 — common advanced application functionality.
- P3 — valuable breadth after the core is dependable.
Apple's views and controls, view controllers, UIScrollView, UITextView, and CALayer documentation define the target. UIKit-cross-platform is a secondary behavioral and test reference, not the specification.
| UIKit API or capability | Status | NXKit evidence and remaining work |
|---|---|---|
CGFloat, CGPoint, CGSize, CGRect |
Partial | NXFloat, NXPoint, NXSize, and NXRect provide common geometry and transforms. Names and portions of Core Graphics behavior differ; add edge-case tests for null/empty/infinite geometry, standardization, intersection, containment, and pixel alignment. |
UIEdgeInsets |
Partial | Basic value type and arithmetic exist. Verify equality, inset operations, direction-aware edges, and UIKit-compatible defaults. |
CGAffineTransform, CATransform3D |
Partial | NXAffineTransform and NXTransform3D support common transforms and animation. Expand conversion, concatenation, inversion, decomposition, and numerical tests. |
| Safe object ownership | Stub/unsafe | UIKit-style objects depend on the custom new_shared ownership path. Stack allocation or std::make_shared can create competing owners. Replace SharedBase.hpp with standard ownership before declaring the object model dependable. |
| Main-thread UI confinement | Partial | A main DispatchQueue exists, but UI objects have no enforcement or assertions comparable to @MainActor. Add a UI-thread contract and debug checks. |
UIApplicationMain, UIApplication, UIApplicationDelegate |
Partial | Launch, quit, foreground/background callbacks, SDL event handling, and one global application exist. The build exports SK_RELEASE to match the checked-in release Skia archives, preventing incompatible inline SkRefCnt disposal semantics at shutdown. Apple and Switch teardown snap and synchronously finish pending recorder work, then let the recorder abandon tracked devices and destroy its promoted-image provider before the Graphite context. Switch additionally keeps its Dawn surface configured through that sequence, then restores nxlink-redirected descriptors and terminates EGL for same-process homebrew-launcher handoff. Switch hardware verification of the corrected shutdown order is pending. Complete lifecycle ordering, activation semantics, error handling, and reproducible tests. |
UIWindow and root controller |
Partial | Root-controller installation, key visibility, event dispatch, safe area, traits, and focus exist. Clarify key-window semantics, multiple-window support without adopting UIScene, resizing, and teardown. |
UIResponder and responder chain |
Partial | Touch and press forwarding exists, hardware presses start at the focused responder or the active presentation root when focus is empty, and responders can register semantic, input-grouped executable actions with enabled state, input matchers, dynamic canPerform availability, same-responder priority, and explicit repeat policy through their UIAction. Repeated input skips automatic/non-repeatable actions and may fall through to a lower-priority or later-responder repeatable action; regular unavailable matches likewise fall through, while an available disabled regular match still consumes the press so parent fallbacks cannot run accidentally. Ancestor responders can temporarily gate action dispatch for their subtree without changing the responders' own enabled state; NXNavigationController uses this during transitions, and NXResponderAction supplies typed console-button registration and collection without placing console button types in UIKitCore. UIViewController::show also propagates primary-context presentation requests through parent containers before falling back to modal presentation. Add UIKit-compatible target/action discovery where portable, first-responder management, loop protection, detail-context presentation, and broader chain tests. |
UIAction and menu-leaf repeat policy |
Partial | Closure-backed actions provide title mutation and execution. UIMenuElementRepeatBehavior mirrors UIKit's automatic, repeatable, and nonRepeatable values; the current menu-less subset exposes repeatBehavior directly on UIAction, and automatic is conservatively non-repeatable for hardware input. Add identifiers, images, attributes/state, sender-aware handlers, the UIMenuElement / UIMenuLeaf hierarchy, and menu integration. |
UIEvent, UITouch, presses and keys |
Partial | Touch and gamepad/press events exist. Held keyboard and gamepad presses use Borealis's 250 ms initial threshold and 100 ms repeat interval; repeat deliveries carry UIPress::isRepeat(), directional focus always accepts them, and actions must explicitly opt in. SDL's platform keyboard repeats are ignored so supported backends share one cadence. Physical key and gamepad-button downs are idempotent, thumbstick direction changes and direct returns to neutral balance their press lifecycle, and held presses are cancelled on controller removal, backgrounding, or window focus loss so a missed release cannot leave a repeating command behind. UIPressPhase::cancelled now reaches the responder chain without performing release actions. Keyboard and gamepad dispatch no longer depends on renderer geometry that is only needed for pointer translation. SDL finger-cancel events now carry a distinct cancelled phase through recognizers and the hit view instead of being treated as successful touch endings. The SDL3 Switch backend preserves finger identity across polls and emits balanced down/motion/up events; the full Switch Demo .nro build verifies backend integration, but repeat cadence and touch behavior still need manual hardware confirmation. Complete timestamps, multi-touch identity, modifier/key semantics, mouse input, broader cancellation cases, and deterministic tests. |
UIView geometry and hierarchy |
Partial | Frame/bounds/center, subviews, superview, hit testing, conversion, alpha, hidden state, backgrounds, alpha masks, tint and content modes exist. Newly attached views now inherit their superview's trait collection before receiving trait-change callbacks, including subtrees created dynamically after the window is visible; mask views participate in display/layout and trait/tint propagation, descendant traversal correctly advances through each ancestor, and removal now detaches the Yoga node immediately so reparenting before the next layout is safe. Fix index validation, remaining hierarchy-cycle checks, invalidation, conversion through transforms, and insertion parity. |
UIView display and invalidation |
Stub/unsafe | Drawing exists, and CALayer::setNeedsDisplay() now marks an attached layer tree dirty, which lets runtime backdrop-effect changes schedule a frame. Several other layer/view setters still do not mark the global tree dirty; make every visual mutation schedule the required display/render pass before treating this as usable. |
UIView layout lifecycle |
Partial | setNeedsLayout, layoutIfNeeded, invalidateIntrinsicContentSize, margins, safe areas, sizing, and controller layout callbacks exist. Intrinsic invalidation dirties Yoga's cached measurement for measured leaf views. Verify callback ordering, propagation, hidden views, re-entrant layout, and broader intrinsic-sizing behavior. |
Auto Layout (NSLayoutConstraint, anchors, guides) |
Alternative | Yoga flex layout is the current portable layout system. Document the intentional incompatibility. Add UILayoutGuide-like safe/readable guides only if they improve portable layout; do not claim Auto Layout compatibility. |
CALayer geometry, hierarchy, and visual properties |
Partial | Bounds, position, anchor point, affine/3D transform, z-order, opacity, background, rounded corners, borders, shadows, contents, hierarchy, alpha masks, and presentation copies exist. Fix incomplete insertion, invalidation, contents rectangles/centers, coordinate conversion, and remaining safe-hierarchy mutation gaps. |
| Core Animation actions and transactions | Partial | CAAction, CABasicAnimation, spring animation, timing functions, model/presentation layers, implicit actions, and basic transactions exist. Add robust begin/commit nesting, completion semantics, repeat/autoreverse, fill behavior, additive/keyframe/group animation where useful, interruption, and tests. |
UIView animation APIs |
Partial | Duration, delay, options, spring parameters, completion, and without-animation blocks exist. beginFromCurrentState samples the currently visible presentation-layer value when replacing an in-flight property animation, replacement installs the new animation before invoking the old completion, and a multi-property animation now reports finished == false if any property was interrupted. Touch hit testing and responder actions share the same per-view allowUserInteraction gate, so hardware actions do not bypass a running animation's interaction policy. Verify nested blocks, broader interruption/removal completion delivery, inherited options, and overlapping-animation interaction semantics. |
CADisplayLink |
Partial | A callback is registered with the main dispatch loop and can be invalidated. Add timestamp/duration, preferred rate/range, pause, safe lifetime/thread behavior, frame-drop behavior, and tests. |
UIViewController view loading and lifecycle |
Partial | Lazy view loading, appearance callbacks, title, safe-area callbacks, traits, responder participation, adaptive primary-context show forwarding, modal relationship accessors, and being-presented/dismissed state exist. View insertion no longer synthesizes duplicate appearance callbacks; modal completions follow the final appearance callback; a built-in presentation reversed before viewDidAppear now proceeds through viewWillDisappear / viewDidDisappear without synthesizing viewDidAppear, while a full-screen presenter's pending disappearance is balanced by viewWillAppear / viewDidAppear; and NX containers explicitly forward transitions only to visible children. Add stricter callback-mutation, broader canceled-transition cases, repeated-presentation, memory/unload, detail-context, and interactive appearance-coordination tests. |
| View-controller containment | Partial | addChild rejects null children, existing parents, self-containment, and ancestor cycles; removal completes the move callback without incorrectly synthesizing disappearance. NXTabBarController and NXNavigationController keep every configured controller contained while mounting only selected/top content, and regression coverage verifies attachment, removal, nested show routing, stack changes, and selection without containment churn. Add broader ordering, reparenting, callback-mutation, and animated-transition tests. |
Modal present / dismiss, UIPresentationController, and custom transitions |
Partial | Modal relationships resolve through containment to the actual presenter; every presentation-root controller supplies a low-priority default Menu/B Dismiss action, including when its focus hierarchy is empty, while higher-priority local and container actions can intercept first. Full-screen, over-full-screen, and custom presentation styles retain a presentation controller through dismissal; full-screen transitions remove and restore the presenting view; custom presentation controllers control the final frame, chrome lifecycle, and relayout, including for Yoga-backed presented roots whose container-owned origin must remain stable; and focus follows the top presentation as soon as it is installed, before its animation completes. UIPresentationController participates in the focus-environment chain, and the top presentation is a hard focus boundary: directional and explicit focus updates cannot reach its presenter, while a presentation with no eligible item leaves focus empty. UIModalTransitionStyle provides cover-vertical, horizontal-flip, cross-dissolve, and a portable 2D partial-curl approximation that folds the presented view without reordering the live presenter. Partial curl requires full-screen presentation style but uses the presentation container's bounds instead of rejecting transient or container-managed presenter geometry. Built-in modal animators request the 120 fps frame limit used by navigation transitions, opt into interaction so early dismissal input stays in the incoming hierarchy, and use beginFromCurrentState. Dismissal during an in-flight built-in presentation cancels that presentation and immediately animates back from the current presentation-layer transform/opacity while retaining relationships, focus ownership, and balanced appearance callbacks until dismissal completes. Other overlapping operations remain serialized per presentation stack; repeated presentation input while a controller is already presented and queued requests that no longer apply are ignored without corrupting relationships or throwing. Custom transition actions are consumed without executing when their animated view omits allowUserInteraction; custom transitions remain serialized until an interruptible property-animator contract exists. UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning, and a non-interactive UIViewControllerContextTransitioning subset support separate presentation/dismissal animators with correct completion timing. Dismissing a lower controller removes its whole presented stack while animating the top controller. The navigation regression harness covers built-in full-screen/overlay/partial-curl hierarchy behavior plus custom framing across Yoga layout, animator/context use, relationships, lifecycle hooks, completion, focus trapping, 120 fps scheduling, transition-time input ownership and allowed/blocked action routing, immediate presentation reversal from an intermediate visual state, overlapping-operation serialization, repeated-action safety, and modal-aware visibility; the scrollable Demo playground exercises all built-in styles, over-full-screen behavior, and a safe-area-centered glass alert whose height is measured from its Yoga content and whose card transform uses ease-in-out timing without spring overshoot. Add interactive/custom transition interruption, transition coordinators, adaptive presentation/delegate behavior, current-context and sheet/popover styles, dismissal-prevention policy, broader cancellation/order tests, and a true renderer-backed page curl before treating the full UIKit surface as usable. |
UIColor and dynamic colors |
Partial | RGBA colors, many semantic colors, alpha changes, tint and dark/light dynamic providers exist. View drawing now establishes a non-null view trait context for dynamic-color resolution and restores the surrounding context after each subtree. Add color-space-independent semantics, explicit resolution APIs, more system colors, and broader tests. Pattern colors are not core priority. |
Trait environment and UITraitCollection |
Partial | Interface style and display scale propagate through ordinary view/controller containment, newly attached views, window-owned presentation chrome, and active presented-controller chains; draw/layout traversal scopes the current trait collection instead of leaking a child or replacing it with null. Add thread-local current traits, performAsCurrent-style scoping, layout direction, preferred content size, accessibility contrast, interface idiom where portable, and explicit trait-change registration/ordering. |
UIImage / CGImage |
Partial | Images load from path, resources, and data; scale and template rendering exist, and raster images are promoted through a bounded Graphite image-provider cache on every supported backend. Add orientation-independent image metadata, resizing/cropping, cap insets or a portable equivalent, decoding errors, and cache/lifetime tests. |
UIImageView |
Partial | Basic image display, tint/template mode, content mode, and fitting exist. Add highlighted/animated images only after core invalidation and state behavior are dependable. |
UIFont and font descriptors |
Missing | Labels accept only numeric size and weight. Add a portable UIFont facade for family, size, weight, traits, metrics, fallback, and custom font registration. |
UILabel |
Partial | SkParagraph/ICU shaping, text, color, size, weight, alignment, measurement, and rendering exist; default-family resolution also supports platform custom-data font managers. Text and font mutations invalidate Yoga's cached intrinsic measurement, allowing live labels such as the navigation clock to grow without wrapping, and the old text-setter debug logging is removed. Expose and implement line count, wrapping, truncation, attributed text, baseline behavior, font objects, fuller intrinsic-size parity, and accessibility text. |
UIControl target/action and state |
Stub/unsafe | Enabled/selected/highlighted bits and one primaryAction exist; primary-action execution respects ancestor responder action gates, and a primary action marked repeatable receives held-button clicks without prematurely clearing the control's hold highlight. Automatic and non-repeatable primary actions receive only the regular release click, while a cancelled Select press clears its hold highlight without firing. The focused highlight feedback animation allows the gamepad press that created it to finish dispatching. A scroll-view pan cancels touch tracking and suppresses the pending primary action, tapping the visibly focused control still completes its action while touch input removes the focus appearance, and a touch action may remove its own control without post-dispatch focus access. Implement combinable UIKit-like states, target/action or event-scoped actions, event dispatch, disabled behavior, complete tracking events, and state-change invalidation. |
UIButton |
Partial | A title label, image view, four visual styles, Yoga layout, focus and primary action exist; inherited control tracking is cancelled when an overlapping scroll pan succeeds. Add per-state title/image/color, content alignment/insets, configuration/state updates, disabled behavior, complete touch-event delivery, and intrinsic sizing. |
UIGestureRecognizer base |
Partial | Touches now enter the internal tracking path before subclass callbacks; successful continuous and discrete recognition prevents overlapping recognizers by default through overridable canPrevent / canBePreventedBy hooks; either delegate can opt a pair into simultaneous recognition; prevention distinguishes failed from cancelled; terminal attempts invoke the protected subclass reset() hook; recognized aliases ended; and cancelsTouchesInView defaults to true. A focused regression test covers a scroll pan cancelling a tracked control without firing its action. Complete dependency/failure relationships, delayed-touch policies, touch filtering, multi-touch reset timing, press arbitration, and remaining delegate coverage. |
UITapGestureRecognizer |
Partial | Single-touch tap/press recognition exists. Add tap count, touch count, movement/duration thresholds, cancellation behavior, and tests. |
UIPanGestureRecognizer |
Partial | Translation and velocity exist. Add min/max touch counts, robust multi-touch centroid behavior, coordinate-conversion tests, and deterministic velocity sampling. |
UIScrollView basic scrolling |
Partial | Offset, explicit validated contentSize, adjustedContentInset, insets, axis-specific bouncing, safe-area adjustment, pan, deceleration, spring-back, isDecelerating, and isScrollEnabled exist. Scroll views are focusable when scrolling is enabled and expose the portable UIScrollViewFocusTrackingMode extension: natural mode exhausts fully visible descendants before scrolling at a constant rate and transfers focus as incoming items become fully visible; centered mode animates each focused descendant toward the inset-adjusted viewport center without exceeding scroll limits; focused mode scrolls only the minimum distance required for full visibility. All focus modes keep their visibility viewport outside physical safe-area occlusion even when contentInsetAdjustmentBehavior is never. Programmatic focus requests targeting a scroll view or a controller whose preferred root is a scroll view resolve through to its visible preferred descendant when one exists; childless subclasses still resolve to the scroll view itself. Natural scrolling uses a separate internal exact-item request when it must temporarily hold focus on the scroll view. It reads the focus system's authoritative physical-direction state instead of depending on a particular descendant responder to forward begin/end events, so controls that consume a press and controls removed before release cannot reject or strand scrolling. When no descendant exists in the held direction, focus remains on the scroll view instead of jumping backward to the first visible item. Both axes are supported, and focusable childless subclasses such as long UITextView content consume repeated directional scrolling until an edge. A scrollable axis retains release momentum even when bouncing is disabled; the bounce flags control rubber-banding and the boundary spring only. Disabling scrolling gates the pan recognizer and active deceleration while preserving programmatic offsets. Existing callers that do not set contentSize retain the historical first-subview inference as a compatibility fallback; migrate them to explicit sizes, then remove that divergence. |
UIScrollView indicators |
Partial | UIKit-shaped UIScrollViewIndicatorStyle, showsVerticalScrollIndicator, showsHorizontalScrollIndicator, axis-specific indicator insets, the deprecated combined-inset convenience, flashScrollIndicators(), and a std::function-based withScrollIndicatorsShownForContentOffsetChanges() are implemented with UIKit defaults; the block convenience reveals only axes whose offset changed. Private overlay layers stay out of subviews() and therefore out of content-size inference, track both axes and explicit content insets, reserve their shared corner, compress during overscroll, support default/dark/light styling, remain fixed to the moving viewport, appear for touch/controller scrolling, and fade after tracking, deceleration, bounce, or a flash. Indicator tracks use the greater of each physical safe-area edge and its explicit axis-specific inset, keeping both thumbs wholly inside visible bounds without discarding larger caller-supplied insets. Focused regression coverage verifies defaults, geometry, normalized movement, per-axis visibility/insets, asymmetric safe-area containment, styling, flash state, block-driven axis selection, overscroll compression, non-scrollable axes, and public validation. Add layout-direction-aware placement, exact platform-metric/visual verification, automatic controller-driven indicator-inset adjustment, and animation-completion-aware block fading before treating the broader current UIKit surface as complete. The C++ enum uses defaultStyle because default is a language keyword. |
UIScrollView delegate |
Stub/unsafe | Begin-dragging is delivered repeatedly and end-dragging is not delivered. Correct callback state transitions and ordering before exposing more delegate surface. |
Editable text: UITextInput, UITextField, UITextView editing |
Missing | A display-only UITextView now exists, but forms, search, login, and settings still require a portable text-input client, SDL IME bridge, selection/caret model, clipboard integration, composition/marked text, secure entry, and keyboard navigation. |
| Core accessibility element semantics | Missing | Add accessible flag, label, value, hint, traits/role, enabled/selected state, frame, hidden state, grouping, ordering, actions, focus, and a platform bridge. Accessibility is part of the core definition of done, not optional polish. See Apple's Accessibility for UIKit. |
| Automated core tests | Partial | The opt-in NXKit tests cover Borealis-timed keyboard repeat generation, suppression of native SDL repeats, duplicate physical-down suppression, repeat flags, repeated directional focus, thumbstick reversal/neutral release, controller-disconnect cancellation, action opt-in/fallthrough, all 26 normalized SDL gamepad buttons plus both analog triggers routing to distinct responder actions, repeatable control highlighting, direct scroll-view and scroll-root controller focus resolution to a visible child, natural scroll-view temporary self-focus and constant-speed handoff through a press-consuming child, release after responder removal, centered edge clamping, minimal focused-mode visibility scrolling, and repeated focusable long-text directional scrolling; tab selection/delegation/configuration, remaining-width layout for intrinsically wide tab content, responder-routed A/B focus transfer with child B interception, unavailable-action fallthrough versus disabled interception, nested-navigation-to-tab fallback, window-owned top-level Exit, and touch-selected tab focus restoration when controller input resumes; touch-to-controller focus loss/regain animation callbacks, focused-control touch execution without visible focus reactivation, trait propagation into a focus-triggered action-legend rebuild, Yoga-enabled view reparenting, live label intrinsic-width invalidation, scroll-pan cancellation of a highlighted control and its pending action, non-bouncing release deceleration on a scrollable axis, scroll-disabled gesture gating with preserved programmatic offsets, scroll-indicator defaults/geometry/movement/insets/styles/visibility/flash/overscroll compression and validation, UITextView defaults, multiline storage, and horizontal-scroll/wrapping mode, safe self-removal during touch action dispatch, plus navigation stack mutation, containment, visible push/pop lifecycle, 120 fps transition scheduling, serialized overlapping programmatic push/pop requests, destination focus transfer with action gating during presentation, delegates, validation, nested show routing, overlay safe areas, movable status/action widgets, responder-derived and presentation-layer-isolated action legends, controller-icon resolution for every action and explicit generic/Xbox/PlayStation/Nintendo family, a Switch-only direct-provider harness that rejects silent fallback for every mapped NintendoExt glyph, invalid icon-size rejection, touch execution and non-focusability of non-A legend commands, latest-handler replacement, nearest-action precedence, SDL execution of custom and container Back commands, default modal Dismiss with focused and empty-focus presentations, immediate animated-presentation focus ownership, transition-time B routing with and without allowUserInteraction, presented-navigation Back-before-Dismiss priority, non-animated custom modal presentation/dismissal relationships, frames, lifecycle hooks, contexts, completions, navigation visibility, nested presentation-stack dismissal resolution, top-presentation focus trapping for directional and explicit requests, immediate built-in presentation-to-dismissal reversal with presentation-layer continuity and balanced lifecycle, dismissal-to-presentation serialization, and built-in full-screen versus over-full-screen hierarchy/appearance behavior. Expand into a fast core suite covering ownership, geometry, view/layer hierarchy, conversion, layout, lifecycle, controls, gestures, scrolling, traits, and animation; port applicable behavioral tests from UIKit-cross-platform. |
| UIKit API or capability | Status | NXKit evidence and remaining work |
|---|---|---|
UINavigationController |
Missing | The Switch-style NXNavigationController extension now has a validated mutable stack, push/pop/pop-to/pop-to-root operations, top/visible access, delegate notifications, appearance and containment handling, 120 fps-limited slide transitions, controller-driven show routing, modal-aware visibleViewController, and regression coverage. Explicit pushes and pops requested during an animated transition are serialized in call order: queued operations do not prematurely alter the public stack, and queued pops reserve and return their eventual removal result, matching observed UIKit behavior instead of throwing on re-entry. Controller focus moves into the incoming screen when its transition begins, while actions from that screen are temporarily gated and shown disabled until presentation completes; this prevents a repeated confirm press from accidentally enqueueing another push. Its restored console chrome uses blurred overlay bars, left-aligned title/icon presentation, live battery/time status, and per-controller NXNavigationItem placement/replacement of the default widgets. Its action legend is no longer navigation-item metadata: it continuously resolves the first available registered controller-button action from focused responders in its own presentation layer, falls back to its own visible content when focus belongs to a controller presented above it, supplies Back only while its stack can pop, then falls through to its own presentation, enclosing-container, or window actions, and retains the mandatory disabled-A placeholder. NXControllerIconResolver renders those commands as template images: Apple uses each connected GCControllerElement.sfSymbolsName for remapping-aware Xbox, PlayStation, or Nintendo artwork and uses filled SF Symbol names for its fallback mappings; Switch loads both the standard and Nintendo-extended shared fonts, preserves the standard face for ordinary text, and explicitly selects the extended typeface containing Nintendo's private-use button glyphs; other platforms and missing native symbols use portable vector-drawn prompts. The resolver treats SDL's controller database as authoritative when it identifies a family, while Apple refines only generic SDL results from the connected controller's identity and unmapped physical face-button SF Symbol metadata, covering third-party PlayStation-layout devices such as Backbone. Every live legend refreshes its cached icon images in place when that resolved family changes, including legends whose actions and titles remain unchanged. Enabled non-A legend entries are touch targets that re-resolve the latest available responder callback before execution without participating in controller focus; A remains display-only. The Demo navigation playground uses scrollable menus to exercise nested show pushes, default/header widget placements, all modal transition styles, and a custom card presentation. It intentionally remains outside UIKitCore; implement separate UINavigationController, navigation-item/bar APIs, interactive transitions, and full UIKit customization behavior. |
UINavigationBar, UINavigationItem, bar-button items |
Missing | Build data-driven navigation items, title/back behavior, left/right actions, safe-area layout, appearance, and focus/touch input. |
UITabBarController, UITabBar, tab items |
Missing | NXTabBarController provides validated mutable content, flat and sectioned selection, a selected controller, delegate veto/notification, configurable sidebar width, focus-selection policy, centered scroll tracking for focused sidebar items, and responder-routed console actions: a tab item's A action enters its presented controller, while its controller-level B action returns to the selected tab item only when focus is outside the tab bar and otherwise falls through to presentation or window handling. Its selected item is also the sidebar's preferred focus destination, keeping touch selection and later controller focus restoration aligned. It remains Switch-specific and has no UITabBarItem model, UIKit bar presentation, customization, or adaptive bottom/sidebar mode. Implement the UIKit types separately in UIKitCore. |
UIScreen-like display information |
Missing | Expose logical bounds, pixel scale, refresh rate/range, and display identity through a portable facade rather than requiring application code to access SkiaCtx. |
IndexPath |
Partial | A two-component section/item value now has const access and equality and is exercised by tab-controller tests. Add ordering/hash, arbitrary components if needed, negative-component policy, and focused value tests before using it as the stable public list index type. |
UITableView, cells, data source and delegate |
Missing | High-value foundation for settings, lists, menus, and feeds. Start with vertical reusable cells, headers/footers, selection, scrolling, insert/delete/reload, stable reuse, focus, accessibility, and keyboard/gamepad navigation. |
UICollectionView, cells and basic layouts |
Missing | Implement after table/reuse primitives. Begin with a flow/grid layout, reusable cells/supplementaries, selection, batch updates, and accessibility. |
| Reuse and diffable data model | Missing | Define stable identifiers and snapshot/diff behavior shared by table and collection views. A simpler C++ API is acceptable if lifecycle and update semantics are documented. |
UIStackView |
Alternative | Yoga covers most stack-layout needs, but there is no UIKit-compatible arranged-subview API. Add only if UIKit familiarity materially improves common layout code. |
UITextView display/editing subset |
Partial | UITextView subclasses UIScrollView and provides UTF-8 multiline text, viewport-constrained wrapping by default, opt-in unwrapped horizontal scrolling through horizontalScrollEnabled, explicit measured content sizing, dynamic color, numeric size/weight, paragraph alignment, UIKit's default (8, 0, 8, 0) text-container inset, measurement, safe-area-adjusted scrolling, XML construction, and a long-text Demo. SkParagraph shapes and lays out the document once per width/style change; only visible 1024-point retained drawing tiles plus one-tile overdraw are mounted, offscreen tiles are released, and each tile paints its clipped paragraph slice directly into the platform canvas without an intermediate bitmap upload. Add attributed runs, incremental/viewport text layout, selection, caret/editing/IME, links/data detection, scroll-to-range behavior, accessibility, and visual/performance regression coverage. |
UISwitch |
Missing | Implement value state, action events, disabled/highlighted behavior, animation, focus, and accessibility. |
UISlider |
Missing | Implement range/value, continuous events, touch/gamepad/keyboard interaction, visuals, and accessibility increment/decrement. |
UISegmentedControl |
Missing | Implement items, selection, momentary mode if needed, control events, intrinsic sizing, focus, and accessibility. |
UIActivityIndicatorView and UIProgressView |
Missing | Provide determinate/indeterminate progress primitives with reduced-motion-aware animation and accessibility values. |
UIAlertController / actions |
Missing | Implement portable alert and action-sheet semantics, focus trapping, keyboard/gamepad selection, cancellation, safe-area sizing, and accessibility. Avoid platform-specific iOS presentation chrome. |
UISearchBar or search-field composition |
Missing | Implement after UITextField; a composed control is sufficient if behavior, clear/cancel actions, focus, and accessibility are familiar. |
UIVisualEffectView / blur and backdrop effects |
Partial | UIBlurView and CABlurLayer retain the existing Skia background blur and tint behavior. UIGlassEffect provides UIKit-shaped Style::regular and Style::clear initialization while remaining hosted by NXKit's BackdropEffectView: clear glass keeps size-invariant translucent defaults, while regular glass smoothly increases backdrop frost and a light/dark systemBackground tint with the view's shortest dimension. Alert-sized light glass caps its tint below 30% and adds up to a 0.12 luminosity lift, retaining the blurred backdrop while separating the material from dimmed content; dark glass keeps the stronger 36% black tint without that lift. Active presented-controller trait changes reinstall the resolved material. Partially opaque animation groups now initialize their offscreen surface from the existing canvas, so nested glass keeps sampling and filtering live backdrop pixels throughout presentation and dismissal instead of snapping on at opacity one. Every optical input—sample and frost radii, refraction strength/depth, saturation/contrast/luminosity processing, tint hue/opacity, directional specular lighting, rim width, reflection sampling, and bright-backdrop shading—has a validated optional override; unset inputs continue following the style. The view resolves those values into its shader on effect installation, bounds-size changes, and trait changes, and same-shader updates reuse the compiled runtime effect. The NXKit-specific BackdropEffectView also accepts validated custom SkSL runtime effects without exposing Skia types, supplies the live backdrop plus view geometry uniforms, preserves ordinary subviews above the effect, and includes an attributed Apache-2.0 port of Cloudy's tested liquid-glass shader with rounded-SDF refraction, chromatic dispersion, blur, and tint. The default curved-depth field spans most of a capsule instead of collapsing into a thin edge band; on larger rounded rectangles it is capped by the corner radius so displacement fades out before the SDF's diagonal medial axes. Raster regressions cover both strong capsule refraction and the absence of large-lens diagonal seams. Its former static white edge highlight is now an MIT-attributed, Fresnel-style specular reflection colored from a three-tap backdrop sample beyond the lens boundary. NXKit supplies the effect's declared sample radius as an automatic uniform; the built-in glass skips zero-contribution body reflection reads and clamps every backdrop coordinate to that radius, including after callers retune displacement uniforms. A raster regression forces an oversized reflection offset and verifies the bounded sample. Achromatic fallback lighting uses directional key/kick lobes rather than a uniform border: pure black samples receive neutral white highlights without darkening the unlit sides, while near-white samples produce a contrasting grey reflection and a subtle adaptive body shade keeps white-on-white glass visible. Its immutable runtime image-filter graph is cached across draws and position-only movement, then rebuilt when the effect, bounds size, corner radius, content scale, or resolved glass parameters change; regression coverage verifies reuse, invalidation, style size adaptation, manual shader propagation, public validation, shape-safe interior refraction, colored exterior reflections, partial black-sample highlights, white-background separation, and backdrop preservation through group opacity. The Test VC uses regular glass, and the dedicated artwork screen presents draggable clear/regular lenses plus a demo-only bottom slider that continuously resizes regular glass across its adaptive material range. The shader compiles with the bundled Skia RuntimeEffect compiler; canonical UIVisualEffect inheritance and UIVisualEffectView/contentView, interactive and container glass behavior, materialization animation, continuous presentation-layer size adaptation, and end-to-end Graphite visual/performance verification on Metal and Dawn remain. |
CAGradientLayer |
Missing | Add linear gradients first using Skia, including colors, locations, start/end points, scale, animation, and mask compatibility. |
CAShapeLayer, CGPath, UIBezierPath core |
Missing | Needed for icons, progress rings, clipping, custom controls, and vector drawing. Start with move/line/curve/close, fill/stroke, line styles, bounds, hit testing, and animation-safe ownership. |
| Layer masking | Partial | CALayer::mask uses destination-in alpha compositing, honors mask geometry and presentation state, preserves the backdrop required by blur layers, and invalidates with its masked hierarchy. Its content-isolation and destination-in offscreen passes are now bounded to the masked layer's local rectangle instead of implicitly allocating against the full canvas; a recording-canvas regression test verifies both bounds and backdrop initialization. Add focused pixel tests for partial alpha, transforms, animated masks, nested masks, nonzero bounds origins, shadows or descendants extending outside masked bounds, and transparent backbuffers; evaluate luminance masks only as an explicit extension because UIKit's contract is alpha-based. |
| Focus engine | Partial | Directional focus, focus environments, coordination, gamepad input, and explicit environment-targeted focus requests exist. Focus-update validation now visits the previous and proposed items followed by each unique ancestor focus environment, allowing containers such as UIScrollView to accept or defer descendant transitions without bypassing leaf vetoes. Explicit view requests use the view's focus search behavior: ordinary focusable views resolve to themselves, while focusable containers such as UIScrollView may resolve to a preferred descendant; a private exact-item path supports temporary container focus without changing public environment semantics. The top modal presentation defines the active focus branch as soon as installation begins, so traversal, programmatic requests, control actions, and presses cannot remain in or move into a retained presenting hierarchy; an empty presentation clears focus until it is dismissed. Touch input hides the focus appearance without preventing the same tap from reaching the focused control; focus requests made by touch-driven actions retarget the retained item without reactivating controller-style focus. Switching back to controller input models reactivation as none -> retained item, so the control repeats its gain-focus animation instead of treating the update as a failed same-item move. Replace hierarchy-order-only movement with geometric candidate scoring, disabled filtering, focus guides or overrides, and accessibility integration. |
| Keyboard navigation and shortcuts | Partial | Low-level key/press types and standard select/menu mapping exist. NX responder actions map Return/Escape/X/Y/equal/hyphen and the corresponding gamepad inputs to A/B/X/Y/plus/minus commands; Start/plus is no longer intercepted as an application quit shortcut. Focused-responder routing, unavailable fallthrough, disabled interception, navigation Back, tab focus fallback, modal Dismiss, and application-window B/menu Exit have regression coverage. Tab navigation, richer shortcuts, localization-aware confirm/cancel policy, and broader standard-control behavior remain incomplete. |
| Layout direction and localization support | Missing | Add left-to-right/right-to-left traits, leading/trailing layout concepts, natural alignment correctness, string/resource localization hooks, and mirrored control behavior. |
| Dynamic type / scalable metrics | Missing | Add preferred content-size categories or a platform-neutral scale trait, font metrics, relayout, and accessibility-size support. |
Clipboard / UIPasteboard-like service |
Missing | Provide portable text and image copy/paste through SDL/platform backends, required by editable text and common application workflows. |
| Application resources / bundles | Partial | NXData, image resource loading, and libromfs exist. Define a stable bundle/resource abstraction, errors, locale variants, scale variants, and testable lookup rules. |
UINib / declarative view loading |
Alternative | A custom TinyXML2 view registry and XML inflater exist. It is not compatible with Apple nibs, storyboards, outlets, actions, or archives. Keep the dialect portable and document its schema; do not imply Interface Builder compatibility. |
| Notifications / observation utility | Missing | A small safe notification/observer primitive is useful for UIKit-like lifecycle and app state. Prefer typed C++ callbacks/tokens and deterministic removal over copying Objective-C selector APIs. |
| UIKit API or capability | Status | NXKit evidence and remaining work |
|---|---|---|
| Pinch, long-press, swipe and rotation gestures | Missing | Implement shared recognizer timing/state infrastructure first, then individual recognizers with touch-count and cancellation tests. |
| Scroll-view zooming | Missing | Add zoom scale/range, content centering, delegate hooks, gesture arbitration, and accessibility after basic scrolling is dependable. |
UIPickerView and a portable date-picker model |
Missing | Prioritize general picker mechanics; keep platform-specific calendar appearance separate from the data/control contract. |
UIPageControl |
Missing | Add page count/current page, value events, focus/touch input, intrinsic sizing, and accessibility. |
UIToolbar and general bar items |
Missing | Reuse navigation item/action and appearance primitives; avoid iOS-only placement assumptions. |
UISplitViewController |
Missing | Implement adaptive two/three-column containment only after navigation and trait systems are stable. |
UIPageViewController |
Missing | Implement after container lifecycle and scroll/gesture arbitration are tested. |
| Menus and contextual actions | Missing | Provide portable action models, nested menus, enabled/selected state, mouse/touch/gamepad presentation, keyboard shortcuts, and accessibility. |
| Pointer, hover and mouse interaction | Missing | SDL mouse input exists at a low level. Add hover events, cursor/interaction state, control highlighting, and consistent hit testing. |
| Drag and drop inside the application | Missing | Start with local typed payloads and reordering. Native inter-application drag and drop can remain platform optional. |
| Multiple windows | Missing | Support multiple UIWindow roots and event routing without requiring Apple's UIScene API. |
| Custom modal transitions and presentations | Missing | Add transition contexts, cancellation, presentation containers, dimming, and interactive progress after standard modal behavior is stable. |
| Interruptible view animation / property animator | Missing | Current animations cover common implicit/basic/spring cases. Add pause, continue, reverse, fraction-complete, interruption, and completion-position semantics. |
| Advanced attributed text and text attachments | Missing | Build on UIFont, path/drawing, and editable text. Include paragraph styles, runs, links, attachments, selection, and accessibility. |
| Image animation and resizable images | Missing | Add only after image lifetime, caching, and invalidation are well tested. |
| State restoration | Missing | Use portable identifiers and serializable controller/view state; exclude Apple's process- and scene-specific mechanics. |
| UIKit API or capability | Status | Notes |
|---|---|---|
Advanced layer types (CAReplicatorLayer, tiled rendering, emitter-like effects) |
Missing | Add based on demonstrated application demand and Skia feasibility. |
| Appearance proxies and broad theming | Missing | Prefer explicit theme/trait propagation first; add appearance-style defaults only with deterministic scope and invalidation. |
| Content configuration APIs | Missing | Useful once reusable list cells and control state configuration exist. |
| Rich text layout manager compatibility | Missing | Consider a smaller portable API unless source familiarity justifies UIKit/TextKit-shaped types. |
| Native inter-application drag/drop and platform services | Missing | Platform capability, not a requirement for the portable core. |
These are not silently “complete.” They must remain documented until a deliberate compatibility decision changes them.
| Area | Current divergence |
|---|---|
| Language/API shape | C++ setters/getters, callbacks, smart pointers, and value types replace Objective-C/Swift properties, selectors, ARC, and protocols. Until the menu model lands, UIKit's UIMenuLeaf::repeatBehavior policy is exposed directly on UIAction. |
| Geometry names | NXKit currently uses NXPoint, NXSize, NXRect, NXAffineTransform, and NXTransform3D rather than Core Graphics names. |
| Layout | Yoga flex layout replaces Auto Layout constraints and anchors. |
| Interface files | NXKit's TinyXML2 format is a custom declarative layout dialect, not an Apple nib/storyboard parser. |
| Rendering | Views are custom-rendered through Skia rather than native platform widgets. Native platform look, accessibility, text input, and system integration must therefore be implemented explicitly. |
| Backdrop effects | UIGlassEffect now mirrors Apple's regular/clear style names and initializer but is installed on the portable NXKit extension BackdropEffectView; it does not yet inherit UIVisualEffect or use a source-compatible UIVisualEffectView. Custom BackdropEffect values use SkSL, one named backdrop child, optional conventional geometry uniforms, and an explicit maximum sample radius. |
| Scroll-view focus tracking | UIScrollViewFocusTrackingMode is an NXKit extension inspired by Borealis controller navigation. UIKit does not expose the same natural/centered/focused three-mode API. |
| Partial-curl transition | Skia currently has no page-curl primitive in NXKit. UIModalTransitionStyle::partialCurl preserves the full-screen restriction with a safe 2D affine fold of the presented view; it does not reorder or curl the live presenting hierarchy and is not visually identical to UIKit's page curl. |
| Extension components | NXNavigationController, NXNavigationItem, NXTabBarController, NXResponderAction, NXControllerIconResolver, and NXControl are opinionated console components and do not count as UIKit API coverage. NXNavigationController borrows UIKit's stack operations, top/visible concepts, serialized transition requests, delegate timing, appearance/containment model, per-screen item configuration, and show handling while retaining Switch-style blurred header/footer chrome, movable status/action widgets, and a responder-derived console legend. NXResponderAction models commands for all normalized SDL gamepad buttons and both triggers, including enabled state, dynamic availability, semantic identifier, priority, and UIAction; nearest-responder precedence differs from UIKit command discovery. NXControllerIconResolver follows the last active controller family and deliberately uses native Apple SF Symbols, Nintendo's Switch font glyphs, or portable vector fallback artwork instead of prescribing one cross-platform asset set. The Demo Controller tab provides a manual regression screen for every normalized button icon, both stick axes, analog trigger pressure, icon aging, and the hold-to-exit interaction. NXTabBarController keeps grouped sidebar, focus-following selection, tab-item A-to-content behavior, conditionally available B-to-selected-tab fallback, selected-item focus restoration across touch/controller input changes, and a content column constrained to the width remaining beside its fixed sidebar while borrowing UIKit's mutable controller list, selected controller/index, delegate veto/notification, and containment ordering. |
Do not add these to the active completeness tables unless the project scope changes:
UIScene, scene sessions, iOS process restoration, and iOS-specific application-shell lifecycle- status-bar, home-indicator, device-orientation, and iPhone/iPad idiom policy APIs
- Apple Pencil, 3D Touch, and device-specific sensor interactions
- UIKit wrappers for camera, photo library, contacts, mail, messages, telephony, StoreKit, or authentication services
- printing, AirPrint, document browser/picker, and iOS share-sheet controllers
- CarPlay, watchOS, visionOS-only, or extension-host APIs
- WebKit, MapKit, AVKit, SpriteKit, and other separate Apple frameworks
- haptic APIs until a portable feedback abstraction becomes a project goal
Safe areas, keyboard/gamepad focus, mouse input, multiple windows, accessibility, localization, and clipboard remain in scope because they are broadly useful across supported and future platforms.
- Replace unsafe shared ownership and add the initial automated test target.
- Make view/layer invalidation, masking, hierarchy operations, and lifecycle ordering dependable.
- Finish
UIControl,UIButton,UILabel/UIFont, editable text/IME, andUIScrollViewcore behavior. - Add accessibility semantics and a first platform bridge.
- Implement standard navigation/tab containers and reusable table/list infrastructure.
- Add gradients, paths/shapes, common controls, alerts, and localization/dynamic type.
- Add Android, Windows, or Linux backends only with shared conformance tests so platform expansion does not fork behavior.