Library / SDK
emoon/rust_minifb avatar
emoon/rust_minifb

minifb gives a Rust program a window and a 32-bit pixel buffer in one crate

Cross platform window and framebuffer crate for Rust

1,220 stars121 forksRustMIT

At a glance

What is it?
minifb is a cross-platform Rust crate that opens a window, blits a 32-bit pixel buffer into it and reads keyboard and mouse input, with backends for X11, Wayland, Windows and macOS. It fits a prototype or a small game where a full windowing stack is overkill, and it does not fit a production application that needs a real widget toolkit.
Who is it for?
minifb fits a Rust developer building a prototype, a small game, a plotter or a demo that needs a window and raw pixel output in one dependency, and it does not fit an application that needs resizable layouts, widgets or a mature event system, since the README states it is primarily designed for prototyping.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One crate gives you a window, a framebuffer and raw input

minifb is a cross-platform library written in Rust that makes it easy to set up a window and to, optionally, display a 32-bit pixel buffer, and it also makes it easy to get input from keyboard and mouse.

The API surface is deliberately small. You create a Window with a title, a width, a height and a WindowOptions value, then in a loop you check whether the window is still open, fill a Vec<u32> buffer, and hand it to the window. There is no scene graph, no retained widget tree and no layout system, because the crate is not trying to be a UI framework.

The README is direct about the scope. Note that minifb is primarily designed for prototyping and may not include all the features found in full window handling libraries. That sentence is the contract, and it is worth reading as the main limitation rather than a footnote.

What the crate does give you is a very short path from nothing to a visible window with pixels in it. The dependencies are correspondingly light: raw-window-handle 0.6 for the platform window handle and web-time 1.1 for timing. On Windows it pulls in winapi 0.3.9 with the winuser, wingdi, libloaderapi, errhandlingapi and fileapi features, which is the classic Win32 API path rather than a modern windowing framework.

The example loop is the whole programming model

The example in the README is the shortest complete program, and it is worth reading line by line because every part of it is a pattern you will repeat.

rust
use minifb::{Key, Window, WindowOptions};

const WIDTH: usize = 640;
const HEIGHT: usize = 360;

fn main() {
    let mut buffer: Vec<u32> = vec![0; WIDTH * HEIGHT];

    let mut window = Window::new(
        "Test - ESC to exit",
        WIDTH,
        HEIGHT,
        WindowOptions::default(),
    )
    .unwrap_or_else(|e| {
        panic!("{}", e);
    });

    window.set_target_fps(60);

    while window.is_open() && !window.is_key_down(Key::Escape) {
        for i in buffer.iter_mut() {
            *i = 0;
        }

        window
            .update_with_buffer(&buffer, WIDTH, HEIGHT)
            .unwrap();
    }
}

The buffer is a flat Vec<u32> of WIDTH times HEIGHT entries, which is why the update call takes the width and height again rather than inferring them. The loop condition is the input check, is_open() combined with is_key_down(Key::Escape), which is the only exit in the example.

set_target_fps(60) is the throttle, with a comment saying it limits to a maximum of about 60 fps update rate. That matters because the alternative is a loop that spins as fast as the CPU allows, and a frame limiter is a one-liner here rather than a timing problem you have to solve yourself.

The README also documents the error handling choice, noting that the code unwraps on the update because it wants to exit if it fails, and that real applications may want to handle this in a different way.

X11 and Wayland are feature flags, and both are on by default

The Cargo.toml is where the real platform story lives. The default feature set is default = ["wayland", "x11", "dlopen"], so a default build carries both a Wayland and an X11 backend, plus dlopen, which is enabled through the wayland-client crate's own dlopen feature.

The x11 feature pulls in x11-dl and libc, and the wayland feature pulls in dlib, lazy_static, libc, tempfile, wayland-client, wayland-cursor and wayland-protocols. The tempfile dependency in the Wayland set is a hint about how the Wayland backend handles shared memory buffers, and the dlib dependency is about loading the Wayland client library at runtime rather than linking it, which is the same idea as the dlopen feature.

There is a separate dependency block for targets that are not macOS, not Redox, not Windows and not wasm32, with a comment explaining that the system key selects the libwayland-backed backend rather than the wayland-rs pure Rust one. So on Linux the two backends are a compile-time choice, not a runtime guess, and the comment suggests you can select between them.

Because both are enabled by default, a Linux build has to satisfy both sets of requirements, and the build instructions say you may need to install libxkbcommon-dev, libwayland-cursor0 and libwayland-dev first. If you target only X11, turning off the wayland feature removes the Wayland system dependency entirely, which is the first thing to try when a Linux build fails on a machine without a Wayland stack.

Supported platforms are broad, and Redox is a known casualty

The status section states that current supported platforms include macOS, Linux and Windows, in both 64-bit and 32-bit. X11 support, for Linux, FreeBSD and similar, has been tested on Ubuntu x64. Linux Wayland support is also available. Bug reports for other operating systems and CPUs are welcome.

The qualifier matters. Tested on Ubuntu x64 is not the same as supported everywhere, and the distinction between macOS, Linux and Windows on the one hand and the X11 and Wayland backends being tested on a specific configuration on the other is exactly the kind of detail that determines whether a project works on your machine.

There is one explicit gap. After version 0.13, Redox has not been updated and some work is required to get it working again, with pull requests welcome. That is a factual statement about a platform that no longer builds, and it is the kind of thing the README would be expected to hide if the project cared about appearances.

The WebAssembly story is separate and better supported. The Cargo.toml declares a wasm example with crate-type cdylib, the dev-dependencies include wasm-bindgen and a large set of web-sys features covering canvas, keyboard, mouse and gamepad, and the examples directory contains a wasm.rs file. So the same crate compiles for the browser, which is where the web-time dependency earns its place.

The examples directory is the closest thing to documentation

Because the crate has a small API and a large example set, the examples are effectively the reference. The directory holds char_callback.rs, drop.rs, fractal.rs, icon.rs, image.rs, menu.rs, mouse.rs, multi.rs, noise.rs, text.rs, title_cursor.rs, topmost.rs, transparent.rs and wasm.rs, along with a resources/ directory that is excluded from the published package.

The names map onto the capabilities the crate actually has. mouse.rs and char_callback.rs cover input, which is where a raw framebuffer approach differs most from a normal GUI toolkit. transparent.rs and topmost.rs cover window attributes, icon.rs covers the window icon, and menu.rs is interesting because a menu in a framebuffer crate means drawing your own menu and handling the mouse yourself. text.rs and title_cursor.rs suggest text and cursor rendering are done by the application, not the library, which is the expected consequence of a pixel buffer design.

The dev-dependencies tell you how the image example works, with png 0.18 and console_error_panic_hook 0.1.7 for the browser target. The Cargo.toml also declares a build.rs, and the build-dependencies include cc 1.0, so there is a native build step.

The README's build instructions are simply cargo build followed by cargo run --example noise, which runs the noise example. The noise example is the right starting point because it fills the buffer with noise, which proves the whole pipeline works without needing any assets.

Dual licensing and a maintenance badge that says what it means

minifb is licensed under either the Apache License, Version 2.0 or the MIT license, at your option, with both licence texts in the repository as LICENSE-APACHE and LICENSE-MIT. The Cargo.toml expresses this as license = "MIT OR Apache-2.0". That is the standard Rust dual-licensing pattern and it removes the licence question from most adoption decisions.

The contribution terms follow the same choice. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work you submit is, as defined in the Apache-2.0 license, dual licensed as above, without any additional terms or conditions.

One metadata field deserves attention. The badges block declares maintenance = { status = "actively-developed" }, which is the crates.io maintenance status flag rather than a marketing claim, and it matches the commit activity: the last push was on 2026-10-19, with the crate version at 0.29.0 in the Cargo.toml and the README's dependency snippet showing minifb = "0.29".

The project is authored by Daniel Collin, the repository is emoon/rust_minifb, and the CHANGELOG.md at the root is where version-to-version changes are recorded, since the repository publishes no GitHub releases.

Editorial conclusion

minifb fits a Rust developer building a prototype, a small game, a plotter or a demo that needs a window and raw pixel output in one dependency, and it does not fit an application that needs resizable layouts, widgets or a mature event system, since the README states it is primarily designed for prototyping. Before building on Linux, install the listed system packages with sudo apt install libxkbcommon-dev libwayland-cursor0 libwayland-dev, and check whether the Wayland or X11 feature should be disabled for your target, since both are enabled by default.

Frequently asked questions

What does minifb do?

minifb is a cross-platform Rust library that sets up a window, optionally displays a 32-bit pixel buffer in it, and reads keyboard and mouse input. The README notes it is primarily designed for prototyping and may not include all the features found in full window handling libraries.

How do I add minifb to a Cargo project?

Add minifb = "0.29" under [dependencies] in your Cargo.toml, create a Window with a title, width, height and WindowOptions::default, then call update_with_buffer with your Vec<u32> buffer in a loop that checks window.is_open() and is_key_down(Key::Escape).

What do I need to install to build minifb on Linux?

The README says you may need to install the system dependencies first with sudo apt install libxkbcommon-dev libwayland-cursor0 libwayland-dev, then build with cargo build and run an example with cargo run --example noise. The default feature set includes both wayland and x11, so disabling one removes its system requirement.

Which platforms does minifb support?

The README lists macOS, Linux and Windows in both 64-bit and 32-bit as currently supported, with X11 support tested on Ubuntu x64 and Linux Wayland support also available. Redox has not been updated since version 0.13 and needs work to build again.

What licence is minifb under?

It is licensed under either the Apache License Version 2.0 or the MIT license, at your option, and the Cargo.toml records this as license = "MIT OR Apache-2.0". Contributions are dual licensed the same way unless you state otherwise.

Official sources

  1. emoon/rust_minifb on GitHub
  2. Issues
  3. License: MIT
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/emoon-rust-minifb.svg)](https://hysenlabs.com/projects/emoon-rust-minifb)

Was this useful?