Minifb
MiniFB is a small cross platform library to create a frame buffer that you can draw pixels in
Install / Use
/learn @emoon/MinifbREADME
MiniFB
MiniFB (Mini FrameBuffer) is a small cross-platform library that makes it easy to render (32-bit) pixels in a window.
Quick Start
An example is the best way to show how it works:
int main() {
struct mfb_window *window = mfb_open_ex("my display", 800, 600, MFB_WF_RESIZABLE);
if (window == NULL)
return 0;
uint32_t *buffer = malloc(800 * 600 * 4);
mfb_update_state state;
do {
// TODO: add some fancy rendering to the buffer of size 800 * 600
state = mfb_update_ex(window, buffer, 800, 600);
if (state != MFB_STATE_OK)
break;
} while(mfb_wait_sync(window));
free(buffer);
buffer = NULL;
window = NULL;
return 0;
}
How it works
- First the application creates a window calling mfb_open or mfb_open_ex.
- Next, it's the application's responsibility to allocate a buffer to work with.
- Next, call mfb_update or mfb_update_ex to copy the buffer to the window and display it. If this function returns a value lower than 0, the window has been destroyed internally and cannot be used anymore.
- Last the code waits to synchronize with the monitor calling mfb_wait_sync.
Note: By default, if ESC key is pressed, mfb_update / mfb_update_ex will return -1 (and the window will have been destroyed internally).
See https://github.com/emoon/minifb/blob/master/examples/noise.c for a complete example.
Supported Platforms
| Platform | Backends | Status | |----------|----------|--------| | Windows | GDI, OpenGL | Fully supported | | macOS | Cocoa, Metal | Fully supported | | Linux/Unix | X11, Wayland | Fully supported (X11, Wayland) | | iOS | Metal | Beta | | Android | Native | Beta | | Web | WASM | Beta | | DOS | DJGPP | Beta |
MiniFB has been tested on Windows, macOS, Linux, iOS, Android, web, and DOSBox-x. Compatibility may vary depending on your setup. Currently, the library does not perform any data conversion if a proper 32-bit display cannot be created.
Features
- Window creation and management
- Event callbacks (keyboard, mouse, window lifecycle)
- Direct window state queries
- Per-window custom data
- Built-in timers and FPS control
- C and C++ interfaces
- Cursor control
API Reference
Window Management
// Create and manage windows
struct mfb_window * mfb_open(const char *title, unsigned width, unsigned height);
struct mfb_window * mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags);
void mfb_close(struct mfb_window *window);
// Update and synchronization
mfb_update_state mfb_update(struct mfb_window *window, void *buffer);
mfb_update_state mfb_update_ex(struct mfb_window *window, void *buffer, unsigned width, unsigned height);
mfb_update_state mfb_update_events(struct mfb_window *window);
bool mfb_wait_sync(struct mfb_window *window);
// Viewport control
// Coordinates/sizes are in drawable coordinates (same units as mfb_get_window_width/height and resize callback).
bool mfb_set_viewport(struct mfb_window *window, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height);
bool mfb_set_viewport_best_fit(struct mfb_window *window, unsigned old_width, unsigned old_height);
mfb_set_viewport() returns false if:
width == 0orheight == 0- viewport bounds exceed the current window drawable size
mfb_open() and mfb_open_ex() return NULL if:
width == 0orheight == 0width * 4would overflow the internal framebuffer stride
If title is NULL or empty, MiniFB uses "minifb" as the effective window/canvas title.
If both MFB_WF_FULLSCREEN and MFB_WF_FULLSCREEN_DESKTOP are provided, MFB_WF_FULLSCREEN takes precedence.
mfb_update_ex() returns MFB_STATE_INVALID_BUFFER if:
buffer == NULLwidth == 0orheight == 0width * 4would overflow internal stride calculations
mfb_update_ex() runtime behavior is backend-specific:
- Wayland waits for compositor frame callback inside
mfb_update_ex()(can block). - Android may return
MFB_STATE_OKwithout presenting whenANativeWindowis temporarily unavailable during lifecycle transitions.
Open-time readiness is backend-specific:
- Wayland waits for the initial configure handshake before returning from
mfb_open_ex(). - Android may return a window handle before
ANativeWindowis ready (rendering starts once the native window becomes available).
mfb_open_ex() flag support by backend:
| Backend | RESIZABLE | BORDERLESS | ALWAYS_ON_TOP | FULLSCREEN | FULLSCREEN_DESKTOP | |---------|-----------|------------|---------------|------------|--------------------| | Windows | Yes | Yes | Yes | Yes | Yes | | X11 | Yes | Yes* | Yes* | Yes* | Yes* | | Wayland | Yes | Yes | No (ignored, warning) | Yes | Yes (maximized) | | macOS | Yes | Yes | Yes | Yes | Yes (zoom/maximize) | | Web | No (ignored, warning) | No (ignored, warning) | No (ignored, warning) | Yes** | Yes** | | DOS | No (ignored, warning) | No (ignored, warning) | No (ignored, warning) | No (ignored, warning) | No (ignored, warning) | | Android | No (ignored, warning) | No (ignored, warning) | No (ignored, warning) | No (ignored, warning) | No (ignored, warning) | | iOS | No (ignored, warning) | No (ignored, warning) | No (ignored, warning) | No (ignored, warning) | No (ignored, warning) |
* Best effort via window-manager hints/properties; behavior depends on compositor/WM support.
** Browser-managed fullscreen; typically requires a user gesture before entering fullscreen.
Event Callbacks
Register callbacks to handle window events:
// Callback types
void mfb_set_active_callback(struct mfb_window *window, mfb_active_func callback);
void mfb_set_resize_callback(struct mfb_window *window, mfb_resize_func callback);
void mfb_set_close_callback(struct mfb_window *window, mfb_close_func callback);
void mfb_set_keyboard_callback(struct mfb_window *window, mfb_keyboard_func callback);
void mfb_set_char_input_callback(struct mfb_window *window, mfb_char_input_func callback);
void mfb_set_mouse_button_callback(struct mfb_window *window, mfb_mouse_button_func callback);
void mfb_set_mouse_move_callback(struct mfb_window *window, mfb_mouse_move_func callback);
void mfb_set_mouse_scroll_callback(struct mfb_window *window, mfb_mouse_scroll_func callback);
Callback Signature Examples
void active(struct mfb_window *window, bool is_active) {
// Called when window gains/loses focus
}
void resize(struct mfb_window *window, int width, int height) {
// Called when window is resized (width/height use the same drawable units as mfb_set_viewport)
// Optionally adjust viewport:
// mfb_set_viewport(window, x, y, width, height);
}
bool close(struct mfb_window *window) {
// Called when close is requested
return true; // true => confirm close, false => cancel
}
void keyboard(struct mfb_window *window, mfb_key key, mfb_key_mod mod, bool is_pressed) {
if (key == KB_KEY_ESCAPE) {
mfb_close(window);
}
}
void char_input(struct mfb_window *window, unsigned int char_code) {
// Unicode character input
}
void mouse_btn(struct mfb_window *window, mfb_mouse_button button, mfb_key_mod mod, bool is_pressed) {
// Mouse button events
}
void mouse_move(struct mfb_window *window, int x, int y) {
// Mouse movement (note: fired frequently)
}
void mouse_scroll(struct mfb_window *window, mfb_key_mod mod, float delta_x, float delta_y) {
// Mouse wheel/scroll events
}
C++ Callback Interface
If you are using C++, you can set callbacks to class methods or lambda expressions:
// Using object and pointer to member
mfb_set_active_callback(window, &myObject, &MyClass::onActive);
// Using std::bind
mfb_set_active_callback(std::bind(&MyClass::onActive, &myObject, _1, _2), window);
// Using lambda
mfb_set_active_callback([](struct mfb_window *window, bool is_active) {
// Handle event
}, window);
Window State Queries
Query window and input state directly (alternative to callbacks):
// Window state
bool mfb_is_window_active(struct mfb_window *window);
unsigned mfb_get_window_width(struct mfb_window *window);
unsigned mfb_get_window_height(struct mfb_window *window);
void mfb_get_window_size(struct mfb_window *window, unsigned *width, unsigned *height);
// Key utilities
const char * mfb_get_key_name(mfb_key key);
// Drawable area (considering viewport scaling/DPI)
unsigned mfb_get_drawable_offset_x(struct mfb_window *window);
unsigned mfb_get_drawable_offset_y(struct mfb_window *window);
unsigned mfb_get_drawable_width(struct mfb_window *window);
unsigned mfb_get_drawable_height(struct mfb_window *window);
void mfb_get_drawable_bounds(struct mfb_window *window, unsigned *offset_x, unsigned *offset_y, unsigned *width, unsigned *height);
// Input state
int mfb_get_mouse_x(struct mfb_window *window);
int mfb_get_mouse_y(struct mfb_window *window);
void mfb_decode_touch(int combined, int *pos, int *id); // Decode packed mobile touch pos/id
int mfb_decode_touch_pos(int combined); // Extract position from a packed touch value
int mfb_decode_touch_id(int combined); // Extract pointer id from a packed touch value
float mfb_get_mouse_scroll_x(struct mfb_window *window); // Mouse wheel delta X from the most recent event pump (0.0f if none)
float mfb_get_mouse_scroll_y(struct mfb_window *window); // Mouse wheel delta Y from the most recent event pump (0.0f if none)
const uint8_t * mfb_get_mouse_button_b
Related Skills
node-connect
343.3kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
92.1kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
343.3kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
343.3kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
