rust-windowing/winit
Window handling library in pure Rust
Healthy across the board
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 3w ago
- ✓40+ active contributors
- ✓Distributed ownership (top contributor 28% of recent commits)
Show all 6 evidence items →Show less
- ✓Apache-2.0 licensed
- ✓CI configured
- ✓Tests present
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/rust-windowing/winit)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/rust-windowing/winit on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: rust-windowing/winit
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/rust-windowing/winit shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit 3w ago
- 40+ active contributors
- Distributed ownership (top contributor 28% of recent commits)
- Apache-2.0 licensed
- CI configured
- Tests present
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live rust-windowing/winit
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/rust-windowing/winit.
What it runs against: a local clone of rust-windowing/winit — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in rust-windowing/winit | Confirms the artifact applies here, not a fork |
| 2 | License is still Apache-2.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 54 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of rust-windowing/winit. If you don't
# have one yet, run these first:
#
# git clone https://github.com/rust-windowing/winit.git
# cd winit
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of rust-windowing/winit and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "rust-windowing/winit(\\.git)?\\b" \\
&& ok "origin remote is rust-windowing/winit" \\
|| miss "origin remote is not rust-windowing/winit (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is Apache-2.0" \\
|| miss "license drift — was Apache-2.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "winit-core/src/lib.rs" \\
&& ok "winit-core/src/lib.rs" \\
|| miss "missing critical file: winit-core/src/lib.rs"
test -f "winit-core/src/event_loop/mod.rs" \\
&& ok "winit-core/src/event_loop/mod.rs" \\
|| miss "missing critical file: winit-core/src/event_loop/mod.rs"
test -f "winit-core/src/window.rs" \\
&& ok "winit-core/src/window.rs" \\
|| miss "missing critical file: winit-core/src/window.rs"
test -f "winit-appkit/src/event_loop.rs" \\
&& ok "winit-appkit/src/event_loop.rs" \\
|| miss "missing critical file: winit-appkit/src/event_loop.rs"
test -f "winit-android/src/event_loop.rs" \\
&& ok "winit-android/src/event_loop.rs" \\
|| miss "missing critical file: winit-android/src/event_loop.rs"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 54 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~24d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/rust-windowing/winit"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Winit is a pure-Rust cross-platform window creation and event handling library that abstracts over platform-specific APIs (Win32, X11, Wayland, AppKit, UIKit, Web, Android). It provides a unified interface for creating windows and receiving input events (keyboard, mouse, touch, resize, etc.) without shipping graphics rendering itself—consumers use platform getters or external graphics libraries like softbuffer or wgpu. Monorepo workspace structure: winit/ is the main crate, with platform-specific crates (winit-android/, winit-appkit/, winit-win32/, etc.) in separate directories, a shared dpi/ crate for DPI calculations, and winit-common/, winit-core/ for shared abstractions. Each platform backend in winit-*/src/ implements the same event loop and window trait.
👥Who it's for
Rust game developers and graphics programmers building cross-platform desktop and mobile applications who need low-level window management and event loops without GUI framework overhead. Also used by graphics library authors (e.g., Bevy, iced, egui) who need a solid windowing foundation.
🌱Maturity & risk
Actively developed and approaching production-ready status (currently at v0.31.0-beta.2 with MSRV 1.85). The project has established CI/CD (.github/workflows/ci.yml, docs.yml), consistent versioning policy, CHANGELOG.md tracking, and weekly maintainer meetings. However, the -beta version suffix indicates the API is not yet stable and breaking changes may occur before v1.0.
Moderate risk: the codebase spans 11 platform-specific implementations (winit-android, winit-appkit, winit-uikit, winit-wayland, winit-win32, winit-x11, winit-web, winit-orbital, etc.) increasing test surface area and maintenance burden. Being pre-1.0, API breakage is expected; consumers should pin minor versions. Dependency complexity is moderate (objc2, android-activity, smithay-client-toolkit for Wayland) but managed via workspace-level pinning in Cargo.toml.
Active areas of work
The project is in active development toward stabilization: the -beta.2 tag suggests recent API refinements, CI is passing (visible in workflow badges), and maintainers meet weekly (noted in README). Breaking changes are being staged before v1.0; check CHANGELOG.md and FEATURES.md for recent feature additions. The workspace dependency versioning shows coordinated releases across platform backends.
🚀Get running
Clone and explore the main crate:
git clone https://github.com/rust-windowing/winit.git
cd winit
cargo build --release
cargo test
Or run platform-specific examples (in examples/ directory, specify platform via --features if needed):
cargo run --example <example-name>
Daily commands: No server to start—winit is a library, not an application. To test locally:
cargo build
cargo test --all
cargo test --doc
To run a specific example:
cargo run --example window --all-features
🗺️Map of the codebase
winit-core/src/lib.rs— Root library entry point for winit-core; defines the primary public API including EventLoop, Window, and MonitorHandle traits that all platform backends must implement.winit-core/src/event_loop/mod.rs— Core event loop abstraction; defines the EventLoop trait and run/pump semantics that govern how all backends process and deliver window events.winit-core/src/window.rs— Window trait definition; all platform-specific implementations (appkit, android, wayland, etc.) must satisfy this interface for window creation and manipulation.winit-appkit/src/event_loop.rs— macOS/iOS event loop implementation; heaviest platform-specific code path for Apple platforms, bridging to Cocoa/UIKit run loops.winit-android/src/event_loop.rs— Android event loop implementation; manages NativeActivity lifecycle and Android looper integration for Android platform support.Cargo.toml— Workspace configuration defining all platform-specific crates (winit-appkit, winit-android, winit-orbital, etc.) and unified versioning.winit-core/src/event.rs— Event type definitions (WindowEvent, DeviceEvent, StartCause, etc.); the contract for all events delivered to user event handlers across all platforms.
🛠️How to make changes
Add a new WindowEvent variant for platform-specific input
- Define the new event type in the WindowEvent enum (
winit-core/src/event.rs) - Update the platform backend event loop to emit the new event (e.g., for macOS/iOS in event_loop.rs) (
winit-appkit/src/event_loop.rs) - Update other platform backends to emit the same event or an equivalent fallback to maintain parity (
winit-android/src/event_loop.rs) - Add tests/examples demonstrating the new event (
examples)
Add support for a new platform backend (e.g., new OS or windowing system)
- Create a new crate directory (e.g., winit-newplatform/) with Cargo.toml (
Cargo.toml) - Implement the EventLoop trait from winit-core (
winit-core/src/event_loop/mod.rs) - Implement the Window trait from winit-core (
winit-core/src/window.rs) - Add the new crate to the workspace members list (
Cargo.toml)
Add keyboard layout or IME support for a new language
- Extend XKB keymap or compose table handling in winit-common (
winit-common/src/xkb/keymap.rs) - Update the keyboard module to handle the new layout variants (
winit-core/src/keyboard.rs) - Emit KeyEvent with the correct Key and text variants in the platform event loop (
winit-appkit/src/event.rs)
🔧Why these technologies
- Rust (pure, no FFI wrappers in core trait definitions) — Safe, zero-cost abstractions for cross-platform window management; memory safety prevents common windowing bugs (use-after-free, thread safety violations).
- Trait-based architecture (EventLoop, Window traits in winit-core) — Enables compile-time polymorphism across platforms without runtime dispatch penalty; each platform provides optimized impl, consumers use common trait.
- Platform-specific crates (winit-appkit, winit-android, winit-orbital) — Isolates FFI and OS-specific code; allows selective compilation and reduces binary bloat for single-platform deployments.
- XKB (X Keyboard Extension) for keyboard handling — Standard Linux keyboard layout and composition engine; provides consistent key mapping across X11 and Wayland without reimplementing keyboard logic.
⚖️Trade-offs already made
-
Traits (EventLoop, Window) defined in winit-core instead of concrete struct in main winit crate
- Why: Allows multiple backends to coexist without vtable overhead; enables zero-cost abstractions at compile time.
- Consequence: Users see trait types, not concrete structs; less ergonomic than if a single concrete 'Window' struct existed, but better performance and modularity.
-
Separate workspace members (winit-appkit, winit-android, etc.) instead of feature-gated single crate
- Why: Reduces coupling; each platform's dependencies (e.g., Cocoa) only pulled if that crate is used; clearer architecture.
- Consequence: More crates to maintain; coordination across versions; but better dependency management for minimal deployments.
-
EventLoop::run() consumes self and never returns (or ControlFlow::ExitWithCode)
- Why: Enforces single event loop per application; aligns with native OS event models (NSApplication.run on macOS, Looper on Android).
- Consequence: Cannot re-run event loop or interleave with other control flow; users must refactor code to use callbacks or run_on_demand for advanced patterns.
-
DPI conversions separated into standalone dpi crate
- Why: Decouples physical/logical coordinate math from windowing; allows use in other UI frameworks without pulling full winit.
- Consequence: DPI types are not deeply integrated into Window; users must manually convert coordinates when needed.
🚫Non-goals (don't propose these)
- Does not provide rendering (no GPU context management; rendering handled by wgpu, gfx, or raw graphics APIs).
- Does not handle GUI layout, theming, or widget libraries (scope is window/event management only).
- Does not provide networking, file I/O, or async runtime (orthogonal concerns).
- Does not guarantee frame-rate or timing guarantees (event delivery latency is platform-dependent).
- Does not support headless/offscreen rendering (windows are always tied to a display).
🪤Traps & gotchas
Multi-platform testing complexity: CI tests multiple backends (Win32, X11, Wayland, AppKit, Android, Web); local development usually targets one platform. To test Wayland on Linux, Wayland libraries must be installed (libwayland-dev on Ubuntu). Android requires ndk: Android builds need Android NDK and Java toolchain (not just Rust). MSRV splits by platform: Android may require a newer rustc than the stated 1.85 MSRV (see README exception clause). Beta API stability: this is pre-1.0, so depending on unreleased branches means accepting breaking changes between commits. Raw window handle interop: winit uses raw-window-handle (rwh_06) for FFI; mismatches with dependent crates' versions can cause subtle unsoundness.
🏗️Architecture
💡Concepts to learn
- Event Loop Abstraction — Winit unifies wildly different platform event models (Win32 message pumps, X11 event queues, Wayland event listeners, iOS app lifecycle) under a single event loop trait—understanding how this abstraction works is key to debugging platform-specific event delivery issues
- DPI Awareness and Logical vs Physical Coordinates — Modern UIs must handle HiDPI displays and multi-monitor setups with different pixel densities; winit's LogicalSize/PhysicalSize distinction prevents mouse coordinate bugs and blurry text—critical for any windowed app
- Raw Window Handle FFI — Winit outputs opaque platform handles (HWND on Windows, Window on X11, NSWindow* on macOS) via raw-window-handle; graphics libraries and other unsafe code consume these—understanding the safety invariants is essential when integrating multiple backends
- Platform-Specific Event Delivery Semantics — Each OS has different event ordering, coalescing, and timing behavior (e.g., macOS sends MouseMoved before MouseInput, X11 may deliver multiple resize events); winit normalizes but doesn't hide these—knowing the per-platform quirks prevents subtle bugs in multi-platform code
- Monorepo Workspace Organization with Platform Backends — Winit's 11 platform-specific crates (winit-win32, winit-x11, winit-wayland, etc.) are coordinated in a single Cargo workspace with unified versioning; this pattern scales for managing N divergent implementations while keeping them in sync—useful to study for similar multi-backend projects
- Wayland Protocol Interaction — Winit's Wayland backend (winit-wayland/) must handle the Wayland compositor protocol, which is event-driven and asynchronous unlike X11's synchronous model; understanding Wayland's surface role negotiation and output events is crucial for debugging Wayland-specific issues
- Cursor Icon Abstraction — Winit re-exports the
cursor-iconcrate's icon enum, translating semantic cursor types (Grab, ResizeEast, etc.) to platform-specific cursors; this avoids hardcoding platform IDs and enables smooth cross-platform UX
🔗Related repos
rust-windowing/raw-window-handle— Defines theraw-window-handle(rwh_06) crate that winit uses for FFI interop; co-maintained by the same community to ensure compatibilitybevyengine/bevy— Major downstream consumer of winit; Bevy's windowing system relies on winit and drives many feature requests and testinghecrj/iced— GUI framework built on top of winit for immediate-mode UI; demonstrates idiomatic use of winit's event loop and window APIslinebender/druid— Data-first GUI framework that uses winit as its windowing backend; another reference for application-level integration patternsgfx-rs/wgpu— GPU graphics library frequently paired with winit in graphics apps; winit provides the window surface, wgpu renders to it
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add platform-specific integration tests for event loop across all backends
The repo has platform-specific backend crates (winit-android, winit-appkit, winit-wayland, winit-win32, winit-x11, winit-web, winit-uikit, winit-orbital) but lacks comprehensive integration tests verifying event loop behavior consistency across platforms. This would catch regressions early and ensure API contracts are maintained uniformly across all backends.
- [ ] Create tests/ directory structure mirroring backend structure (tests/android/, tests/appkit/, tests/wayland/, etc.)
- [ ] Add basic event loop initialization and window creation tests in each backend test module
- [ ] Add tests verifying WindowEvent and DeviceEvent propagation for each platform in .github/workflows/ci.yml
- [ ] Document platform-specific test requirements in CONTRIBUTING.md
Implement missing DPI conversion tests and benchmarks in dpi/src/lib.rs
The dpi crate is a standalone workspace member but lacks comprehensive test coverage for DPI conversions between physical and logical pixels. Given this is a critical calculation used across all platforms, adding unit tests and benchmarks would improve reliability and help catch precision issues early.
- [ ] Add unit tests in dpi/src/lib.rs covering edge cases (0 scale factor, very large/small values, rounding)
- [ ] Add benchmarks using criterion for common conversion operations in dpi/benches/
- [ ] Add property-based tests using proptest to verify bidirectional conversions maintain invariants
- [ ] Update dpi/README.md with examples of common DPI conversion patterns
Add feature matrix documentation and validation in FEATURES.md with CI check
The repo references FEATURES.md but lacks automated validation that all conditional compilation features are properly documented and tested. With 10+ platform backends and Cargo features, contributors often miss documenting which features apply to which platforms. Adding a CI job to validate this prevents documentation drift.
- [ ] Extend FEATURES.md with a comprehensive table mapping each Cargo feature to supported platforms (Android, macOS, iOS, Linux/Wayland, Linux/X11, Windows, Web, Orbital)
- [ ] Create a script (e.g., scripts/validate_features.sh) that parses Cargo.toml feature definitions and cross-references FEATURES.md
- [ ] Add CI workflow step in .github/workflows/ci.yml to run feature validation on every PR
- [ ] Document the feature validation process in CONTRIBUTING.md
🌿Good first issues
- Add integration tests for the DPI module (
dpi/src/lib.rs): currently no dedicated test file despite being critical for multi-monitor scaling. Createdpi/src/tests.rswith tests for LogicalSize↔PhysicalSize conversions at various DPI factors. - Document platform-specific event quirks in
winit-core/src/event.rsdoc comments: many events have subtle platform-specific behaviors (e.g., key repeat on different OSes, mouse wheel direction inversion on macOS) that should be called out inline rather than discovered via bug reports. - Implement missing platform feature parity: compare
winit-win32/src/window.rsmethod count vs.winit-x11/src/window.rs—identify missing Xlib equivalents (e.g., blur/transparency features) and add with fallback stubs for unsupported platforms.
⭐Top contributors
Click to expand
Top contributors
- @madsmtm — 28 commits
- @kchibisov — 16 commits
- @dcz-self — 8 commits
- @dependabot[bot] — 5 commits
- @Random-Scientist — 3 commits
📝Recent commits
Click to expand
Recent commits
c4afadb— winit-wayland: useext-background-effectif available (kchibisov)b5252f1— chore: bump actions/configure-pages (#4550) (dependabot[bot])f93a223— Clean up cargo-deny (madsmtm)d75a0da— chore: bump actions/deploy-pages from 4 to 5 (#4545) (dependabot[bot])9bf46af— AppKit: Use fn_addr_eq now that it's in MSRV (#4532) (madsmtm)464c37a— Remove leftover apple/appkit/mod.rs (#4533) (madsmtm)557d285— Remove symlinking between winit-appkit and winit-uikit (#4530) (madsmtm)ba856e1— Fix CI (#4546) (madsmtm)0ffd303— fix(typo): dependant -> dependent (#4540) (c-tonneslan)5a74bf0— Android: Add further scancode conversions (#4023) (madsmtm)
🔒Security observations
The winit codebase demonstrates generally good security practices with a well-structured workspace, proper dependency management, and clear separation of platform concerns. However, the use of a beta release version introduces some risk. The primary security consideration is the complexity of supporting multiple platforms (Windows, macOS, Linux, Web, Android, iOS) with FFI bindings, which requires careful handling of unsafe code and platform-specific security concerns. No hardcoded secrets, obvious injection vulnerabilities, or exposed credentials were detected in the file structure. Recommendation: upgrade to stable release version once available, and maintain ongoing security audits of platform-specific FFI implementations.
- Medium · Beta Version in Production Dependencies —
Cargo.toml (workspace.package.version). The workspace is using version 0.31.0-beta.2, which is a beta release. Beta versions may contain unpatched security vulnerabilities and stability issues that are typically resolved in stable releases. Using pre-release versions in production environments increases security risk. Fix: Upgrade to a stable release version (1.0.0 or later) once available. If beta versions must be used, implement additional security testing and monitoring. - Low · Incomplete Dependency Specification —
Cargo.toml (workspace.dependencies section). The dependency list in Cargo.toml appears to be truncated at the 'objc2' crate specification. This incomplete configuration could lead to unintended dependency resolution or build failures. While visible in the provided snippet, this suggests the actual file may have formatting or parsing issues. Fix: Verify the Cargo.toml file is complete and properly formatted. Run 'cargo check' and 'cargo build' to validate dependency resolution. - Low · Relaxed Dependency Version Constraints —
Cargo.toml (workspace.dependencies section - multiple entries). Several dependencies use broad version specifications (e.g., 'bitflags = "2"', 'serde = { version = "1"...}') without upper bounds. This could allow minor/patch version updates that introduce unexpected changes or security patches for indirect dependencies. Fix: Consider using more specific version constraints (e.g., '2.x' or '^2.0.0') for critical dependencies to have better control over transitive dependency updates. - Low · Multiple FFI/Platform-Specific Modules —
Multiple crates: winit-appkit/src/ffi.rs, winit-win32, winit-x11, winit-wayland, etc.. The codebase includes multiple platform-specific implementations (winit-appkit, winit-win32, winit-x11, winit-wayland, winit-web, etc.) with FFI bindings and native code. Each platform variant represents an additional attack surface for platform-specific vulnerabilities. Fix: Implement thorough security testing for each platform backend. Conduct regular security audits of FFI code, particularly unsafe blocks that interact with native APIs. Consider using automated tools like miri for runtime safety checking.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.