A dependency-free interoperability library for passing raw window and display handles between Zig windowing and graphics libraries.
This package defines handle types and provider interfaces only. It does not create, own, retain, release, or destroy native windows.
The API is based on the released Rust
raw-window-handle 0.6.2
model and includes all 16 window-handle variants and 13 display-handle
variants from that release.
- Dependency-free Zig API
- Platform variants available on every target
- Non-null native pointer fields using
*anyopaque NonZeroU32andNonZeroIsizewrappers for non-zero native IDs- Compile-time provider dispatch with no runtime overhead
- Optional zero-allocation, type-erased providers
- OpenHarmony, Android, Apple, Linux, Windows, Web, Redox, and Haiku support
- Zig-native tagged unions with explicit lifetime and ABI documentation
| Requirement | Version |
|---|---|
| Zig | 0.16.0 or newer |
| Third-party dependencies | None |
| API compatibility baseline | Rust raw-window-handle 0.6.2 |
| Platform | Display handle | Window handle |
|---|---|---|
| UIKit | UiKitDisplayHandle |
UiKitWindowHandle |
| AppKit | AppKitDisplayHandle |
AppKitWindowHandle |
| OpenHarmony | OhosDisplayHandle |
OhosNdkWindowHandle |
| Android | AndroidDisplayHandle |
AndroidNdkWindowHandle |
| Xlib | XlibDisplayHandle |
XlibWindowHandle |
| XCB | XcbDisplayHandle |
XcbWindowHandle |
| Wayland | WaylandDisplayHandle |
WaylandWindowHandle |
| DRM/KMS | DrmDisplayHandle |
DrmWindowHandle |
| GBM | GbmDisplayHandle |
GbmWindowHandle |
| Windows | WindowsDisplayHandle |
Win32WindowHandle, WinRtWindowHandle |
| Web | WebDisplayHandle |
WebWindowHandle, WebCanvasWindowHandle, WebOffscreenCanvasWindowHandle |
| Redox Orbital | OrbitalDisplayHandle |
OrbitalWindowHandle |
| Haiku | HaikuDisplayHandle |
HaikuWindowHandle |
Add the package to build.zig.zon. For local development:
.dependencies = .{
.raw_window_handle = .{
.path = "../raw-window-handle",
},
},After the repository is published, it can also be added with:
zig fetch --save git+https://github.com/OWNER/raw-window-handle.git#COMMITThen expose the module to your target in build.zig:
const raw_window_handle = b.dependency("raw_window_handle", .{
.target = target,
.optimize = optimize,
});
your_module.addImport(
"raw-window-handle",
raw_window_handle.module("raw-window-handle"),
);A window type participates in compile-time provider dispatch by declaring
windowHandle and, when applicable, displayHandle:
const rwh = @import("raw-window-handle");
const OhosWindow = struct {
native_window: *anyopaque,
pub fn windowHandle(self: *const @This()) rwh.HandleError!rwh.WindowHandle {
return .borrowRaw(.{
.ohos_ndk = rwh.OhosNdkWindowHandle.init(self.native_window),
});
}
pub fn displayHandle(_: *const @This()) rwh.HandleError!rwh.DisplayHandle {
return .ohos();
}
};Required pointer fields use *anyopaque, which cannot be null. Non-zero
integer handles use the provided wrappers:
const hwnd = rwh.NonZeroIsize.init(raw_hwnd) orelse
return error.Unavailable;
const handle = rwh.Win32WindowHandle.init(hwnd);Generic consumers use getWindowHandle or getDisplayHandle:
fn createSurface(window: anytype) !void {
const handle = try rwh.getWindowHandle(window);
switch (handle.asRaw()) {
.ohos_ndk => |ohos| {
// Pass ohos.native_window to the graphics API.
},
else => return error.NotSupported,
}
}Use WindowHandleProvider or DisplayHandleProvider when a concrete provider
type must be erased:
const provider = rwh.WindowHandleProvider.init(&window);
const handle = try provider.windowHandle();These providers do not allocate. The concrete object passed to init must
outlive the type-erased provider.
| Type | Purpose |
|---|---|
RawWindowHandle |
Tagged union containing a platform window payload |
RawDisplayHandle |
Tagged union containing a platform display payload |
WindowHandle |
Borrowed, non-owning window-handle wrapper |
DisplayHandle |
Borrowed, non-owning display-handle wrapper |
HandleError |
Error set returned while acquiring a handle |
WindowHandleProvider |
Type-erased window provider |
DisplayHandleProvider |
Type-erased display provider |
The complete public API is exported from src/root.zig.
Handle providers return HandleError:
| Error | Meaning |
|---|---|
error.NotSupported |
The underlying platform handle cannot be represented by this package |
error.Unavailable |
The handle is temporarily unavailable, such as during Android surface replacement |
WindowHandle and DisplayHandle are borrowed, non-owning values. Zig cannot
encode Rust-style lifetimes, so providers must guarantee that:
- Every non-null pointer remains valid while a consumer uses the handle.
- The underlying window or display is not destroyed or replaced during use.
- Repeated acquisitions remain consistent unless a platform event invalidates or replaces the handle.
- Main-thread-only objects such as UIKit and AppKit handles are used only from an allowed thread.
- Platform-specific synchronization requirements are respected.
Integer identifiers such as X11 XIDs are not covered by pointer-lifetime guarantees and may be invalidated by the current process, another process, or a remote X11 client.
RawWindowHandle and RawDisplayHandle use Zig-native tagged-union layout and
do not provide a stable C ABI. For FFI, pass an explicit tag and the matching
platform payload instead of passing either union directly.
Most Rust variants map directly to lowercase Zig tags. Variants with compound
names use Zig snake_case:
| Rust variant | Zig tag |
|---|---|
UiKit |
.ui_kit |
AppKit |
.app_kit |
OhosNdk |
.ohos_ndk |
Win32 |
.win32 |
WinRt |
.win_rt |
WebCanvas |
.web_canvas |
WebOffscreenCanvas |
.web_offscreen_canvas |
AndroidNdk |
.android_ndk |
Run the unit tests:
zig build test
zig build test -Doptimize=ReleaseSafeRun the OpenHarmony example:
zig build exampleCompile the portability probe for representative targets:
zig build check -Dtarget=aarch64-linux-ohos
zig build check -Dtarget=aarch64-linux-android
zig build check -Dtarget=x86_64-windows-gnu
zig build check -Dtarget=wasm32-freestandingCheck formatting:
zig fmt --check build.zig src tests examplesSee examples/ohos.zig for an end-to-end provider example.
This package currently follows semantic versioning from version 0.1.0.
Breaking Zig API changes require a minor version bump while the package remains
below 1.0.0.
The Rust raw-window-handle compatibility baseline is documented explicitly
and is not updated implicitly from unreleased upstream branches.
Licensed under the MIT License.
The API model is based on the independently licensed Rust
raw-window-handle
project.