MCPcopy Index your code
hub / github.com/emoon/minifb

github.com/emoon/minifb @v0.10.1

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.10.1 ↗ · + Follow
667 symbols 1,577 edges 65 files 419 documented · 63%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

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

  1. First the application creates a window calling mfb_open or mfb_open_ex.
  2. Next, it's the application's responsibility to allocate a buffer to work with.
  3. 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.
  4. 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);
void                mfb_set_title(struct mfb_window *window, const char *title);

// 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 == 0 or height == 0 - viewport bounds exceed the current window drawable size

mfb_open() and mfb_open_ex() return NULL if: - width == 0 or height == 0 - width * 4 would 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 == NULL - width == 0 or height == 0 - width * 4 would 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_OK without presenting when ANativeWindow is 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 ANativeWindow is 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_buffer(struct mfb_window *window); // 1=pressed, 0=released (8 buttons)
const uint8_t *     mfb_get_key_buffer(struct mfb_window *window);          // 1=pressed, 0=released

On Android/iOS touch paths, mfb_get_mouse_x() and mfb_get_mouse_y() include an encoded touch pointer id in the upper bits. Use mfb_decode_touch() to decode both at once, or mfb_decode_touch_pos() / mfb_decode_touch_id() individually. On desktop/Web/DOS, id is always 0. For touch callbacks, the pointer id is also exposed as button in mfb_mouse_button_func (MFB_MOUSE_BTN_0..MFB_MOUSE_BTN_7). On Android/iOS touch move callbacks, mfb_mouse_move_func receives packed x/y values (same encoding as getters). On Android, external HOVER_MOVE also uses packed x/y; if Android does not provide a valid pointer id, MiniFB uses fallback id 15. mfb_get_mouse_scroll_x/y() are pump-local values: MiniFB resets them to 0.0f before each backend event pump, then writes the delta if a scroll event is received during that pump.

Per-Window Data

Attach and retrieve custom data per window:

void                mfb_set_user_data(struct mfb_window *window, void *user_data);
void *              mfb_get_user_data(struct mfb_window *window);

Timers

Create and manage timers independently:

struct mfb_timer *  mfb_timer_create(void);
void                mfb_timer_destroy(struct mfb_timer *tmr);
void                mfb_timer_reset(struct mfb_timer *tmr);
void                mfb_timer_compensated_reset(struct mfb_timer *tmr);
double              mfb_timer_now(struct mfb_timer *tmr);
double              mfb_timer_delta(struct mfb_timer *tmr);
double              mfb_timer_get_frequency(void);
double              mfb_timer_get_resolution(void);

Frame Rate Control

Control target FPS and frame synchronization:

void                mfb_set_target_fps(uint32_t fps);         // Default: 60 fps
unsigned            mfb_get_target_fps(void);

bool                mfb_wait_sync(struct mfb_window *window); // Frame sync point

Note: Hardware-accelerated syncing (OpenGL / Metal, where supported) will use vertical sync. Other platforms use software pacing.

Logging

MiniFB ships with a simple logger that you can redirect or disable:

// Set a custom logger; pass NULL to restore the built-in logger
void mfb_set_logger(mfb_log_func user_logger);

// Control verbosity threshold (inclusive)
void mfb_set_log_level(mfb_log_level level);
  • Levels (low → high): MFB_LOG_TRACE, MFB_LOG_DEBUG, MFB_LOG_INFO, MFB_LOG_WARNING, MFB_LOG_ERROR.
  • Defaults: in _DEBUG builds the threshold is MFB_LOG_DEBUG; in release builds MFB_LOG_INFO.
  • Messages with a level below the threshold are discarded; equal or higher are emitted.
  • Custom loggers receive the message already formatted (level + message).
  • The built-in logger writes TRACE/DEBUG/INFO to stdout and WARNING/ERROR to stderr as [MiniFB (LEVEL)] message.

Cursor Control

void                mfb_show_cursor(struct mfb_window *window, bool show);

Note: Cursor hiding is supported on Windows, macOS, X11, and Wayland only.

Monitor Information

void                mfb_get_monitor_scale(struct mfb_window *window, float *scale_x, float *scale_y);
void                mfb_get_monitor_dpi(struct mfb_window *window, float *dpi_x, float *dpi_y); // [Deprecated]

mfb_get_monitor_scale():

  • Returns scale multipliers (1.0 = 100%).
  • If window == NULL, outputs still receive a safe fallback (1.0) when their pointers are non-NULL.
  • Some backends provide real scale values (for example Retina/HiDPI); others currently return fixed 1.0.
  • On X11, scale detection is implemented (Xresources/XRandR/fallbacks), but in many desktop setups the value is effectively startup-time and may not update dynamically after changing global scale whi

Core symbols most depended-on inside this repo

Shape

Function 454
Class 170
Method 25
Enum 18

Languages

C60%
C++39%
Java1%

Modules by API surface

src/wayland/WaylandMiniFB.c90 symbols
src/wayland/generated/xdg-shell-client-protocol.h85 symbols
src/web/WebMiniFB.c46 symbols
src/MiniFB_common.c42 symbols
src/x11/X11MiniFB.c29 symbols
src/wayland/WindowData_Way.h27 symbols
src/android/AndroidMiniFB.c27 symbols
src/MiniFB_cpp.cpp25 symbols
src/windows/WinMiniFB.c24 symbols
examples/dos/gdbstub.h24 symbols
src/dos/DOSMiniFB.c23 symbols
src/wayland/generated/xdg-decoration-client-protocol.h21 symbols

For agents

$ claude mcp add minifb \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page