Views, layers, input, and accessibility
0.57.0-dev · beta source documentation. Native, Blueprint, Editor and rendering examples are source-reviewed, not executed in Unreal during this scan. See validation and limits.
UQuartzUISubsystem is the GameInstance owner. UQuartzUIView is a logical document and its player identity, contract, providers, bridge access, and lifecycle. A presentation target displays that view. Keep these lifetimes distinct: hiding a presentation is not closing the logical view.
A shell or an embedded view
For the standard shell, use the HUD/component or FQuartzUI::StartShell. Repeated starts return the same player shell. Ready, Failed, Action, and Stopped convenience events are observers; destroying the observing HUD/component does not stop the shell.
For an advanced embedded view, get the GameInstance subsystem, call CreateAppView(AppAsset, Player), then AttachToView(View) on a UQuartzUIWidget in your UMG tree. Keep the returned view owned through the subsystem and close it with CloseView when your document owner ends. A logical view permits one presentation target; it cannot simultaneously occupy a HUD widget and a direct world surface.
CreateConfiguredView accepts an explicit definition for advanced uses. App assets carry registered project contracts/providers. ConfigureStandaloneApp on a widget must run before browser construction and attachment; standalone definitions do not supply an app asset's project contract closure. SQuartzUIBrowser is the equivalent native Slate embedding seam. Its delegates distinguish load completion from aggregate Ready. Never use raw HTML loading or JavaScript execution as the ordinary Blueprint gameplay API.
Layer multiple documents
Use GetOrCreateLayerStack(Player) and the built-in quartzui.hud, quartzui.menu, and quartzui.modal layers. Subsystem PushAppView / PushConfiguredView create and push views. The native player host mounts and clips them to the exact viewport. A project UMG composition may use UQuartzUILayerHost::AttachToLayerStack instead.
Minimal policy example, with Stack obtained from that subsystem:
FQuartzUILayerDefinition Layer;
Layer.LayerId = TEXT("game.overlay");
Layer.ZOrder = 200;
Layer.bReceivesInput = true;
Layer.bDismissTopOnBack = true;
Layer.InputConfig.InputMode = EQuartzUIInputMode::GameAndUI;
const bool bRegistered = Stack->RegisterLayer(Layer);
Use PushView, PopView, and RemoveView only with the correct player's views. Pop/remove close by default; opt out only when another owner will close or reuse the view. FQuartzUILayerTransitionDefinition configures bounded native enter/exit durations and scales. Exit transitions may defer close; reduced motion completes/suppresses transitions. The host retains covered browser presentations and suspends their runtime work. Do not implement a second competing visibility/input stack.
Input belongs to the exact player
FQuartzUIInputConfig chooses Game Only, UI Only, or Game and UI plus cursor/capture policy. The default HUD layer is passive Game Only; menu/modal layers use UI Only. Native pointer, keyboard, text, and IME input follow Chromium. Gamepad navigation arrives as semantic actions; the consuming page must implement focus, editing, and activation behavior.
UQuartzUIInputAdapter is the shipped customization seam. Create a subclass, register it on the layer host with RegisterInputAdapter, publish modality/connection/glyphs/navigation/logical actions, and unregister when its feature ends. Up to eight adapters are supported. OnActivated, OnInputContextChanged, and OnDeactivated own device subscriptions across travel and reassignment. A UQuartzUIInputGlyphProfile maps logical actions to resolved labels or same-origin compiled images. The web page renders quartzui.input; it should not guess controller vendors or use unscoped browser gamepads as the production player identity.
For mixed game/editor UI, native SetPointerInputRegions accepts up to 256 normalized finite rectangles. Empty means pointer-passive. Publish actual interactive rectangles after layout/viewport changes; a transparent full-screen DOM wrapper is not a hit-test mask. Gate Enhanced Input/direct polling in your game while IsUIKeyboardFocused is true.
Acknowledge Back before changing native context
Back offers the page a bounded chance to handle it, then falls back to native dismissal. Copy back-navigation.mjs; it does not install listeners or choose navigation hierarchy.
import { resolveBackBeforeTransition } from './back-navigation.mjs';
const stopBack = client.subscribeEvent('quartzui.back', event => {
void resolveBackBeforeTransition(event.requestId, defer => {
if (!submenuOpen()) return false;
defer(() => closeSubmenuAndChangeNativeContext());
return true;
}, payload => client.request('quartzui.back.resolve', payload))
.catch(showBackError);
});
The three named UI callbacks belong to your project. Rejected acknowledgments do not run deferred transitions. Unsubscribe on document owner teardown. Closing the native context first can invalidate the pending Back request.
Platform, culture, and accessible presentation
FQuartzUIPlatformContext holds an Unreal-owned platform ID and bounded traits. Set it through UQuartzUILayerHost::SetPlatformContext; render its quartzui.platform snapshot. FQuartzUIPresentationContext carries culture, locale, text direction, text scale, reduced motion, high contrast, and screen-reader status. Host SetPresentationPreferences supplies per-player choices; culture changes refresh native state without reloading the document. The standalone transport does not itself apply HTML lang, dir, or CSS attributes: subscribe and apply the generated fields in your frontend.
Use semantic HTML/ARIA and visible focus. For a native status announcement, call the actual shipped transport:
const result = await client.request('quartzui.accessibility.announce', { message: 'Settings saved' });
Announcements require 1–512 trimmed UTF-16 characters and at least 500 ms between admitted announcements; inspect inactive/unavailable/rate-limited outcomes. This is a narrow status path. Epic's public browser does not expose full DOM-to-Slate OS screen-reader traversal. IME composition, physical controllers, trusted multitouch, HDR/stereo, and split-screen rendering require their own runtime gates.
Recover honestly
IsQuartzUIReady requires document load and contract ping. Load recovery uses a native fallback, with explicit Retry and bounded attempts (default 3; maximum 8). A new navigation resets the sequence. Do not count the synthetic browser error page as Ready or reload forever. Mount failures can retain one logical shell for later remount; inspect failure state instead of creating duplicates.
API guide (source: Documentation/API.md), layer stack (source: Source/QuartzUIRuntime/Public/QuartzUILayerStack.h), Back helper (source: Resources/Client/back-navigation.mjs). Native and composed input examples remain unexecuted in this scan.