Skip to content
Haiku OSDeep Dive Published Updated 8 min readViews unavailable

Haiku's Kit-Based API: Application, Interface, Storage, and Media Kits

How Haiku's native API is divided into cooperating Kits, with shared conventions for messages, ownership, status codes, linking, and threads.

Haiku organizes its public native API into Kits: logical groups for application messaging, interface construction, storage, media, networking, translation, localization, devices, support utilities, and other domains. The grouping is conceptual and documentary. It does not imply that every Kit is a separate shared library; many central classes are delivered together in libbe.so, while specialized Kits have their own libraries.

The benefit is a navigable contract. A developer can start with the domain that owns a task, then follow explicit types into another Kit where responsibilities meet. A BWindow from the Interface Kit is also a BLooper from the Application Kit; a Translation Kit decoder consumes a BPositionIO abstraction rooted in Support/Storage facilities; a media application presents controls through Interface Kit without moving codec policy into BView.

Application Kit: messages and lifecycle

The Application Kit supplies BApplication, BLooper, BHandler, BMessage, BMessenger, roster facilities, clipboard access, resources, and related application services. Its message model connects threads and teams through typed fields rather than exposing internal object pointers.

BLooper owns a message loop and dispatches messages to handlers. BApplication and BWindow are major looper subclasses. BMessenger identifies a target and can deliver asynchronous or synchronous requests across local or remote contexts. A synchronous request must not create a circular wait between loopers.

Messages are extensible containers, not self-validating schemas. Each public what code needs documented fields, types, optional values, and reply behavior. Receivers validate every field and return status rather than assuming that IPC from a local team is trusted.

Application lifecycle also belongs here: signatures, launching, references, quit requests, and interapplication communication. A CLI that only uses storage may not need BApplication; a graphical app normally creates one because system messaging and window integration depend on it.

Interface Kit: windows, views, and layout

The Interface Kit provides BWindow, BView, native controls, menus, lists, fonts, drawing primitives, bitmaps, and the Layout API. It builds on Application Kit messaging: BWindow dispatches messages and BView is a handler that draws and receives input.

Views form a hierarchy with parent-relative frames and local bounds. Once attached to a window, their drawing state and geometry are represented to app_server. Applications invalidate changed regions and reconstruct pixels in Draw() rather than treating the screen as permanent memory.

The Layout API uses constraints and preferred sizes to place controls. That matters for translated text, font preferences, and resizable windows. Fixed coordinates are valid for genuinely fixed custom content, not a shortcut for dialog layout that must survive another locale.

Window objects follow looper locking rules. Expensive file, network, or media work belongs on workers, with results posted back as messages. The Kit enables responsive UI but cannot rescue a window thread blocked by application code.

Storage Kit: nodes, entries, attributes, and queries

The Storage Kit wraps file-system operations in classes such as BEntry, BFile, BDirectory, BNode, BPath, BVolume, BQuery, and node-monitoring facilities. It distinguishes a directory entry—the name/link in a directory—from the underlying node and the open file stream.

BNode exposes typed attributes; BQuery uses BFS indexes and predicates on a selected volume; BVolumeRoster enumerates volumes. These APIs let native applications participate in Haiku’s MIME, attribute, query, and Tracker ecosystem without parsing BFS structures.

Storage operations can race. A path validated earlier may name another entry later, and a query result may disappear before opening. Code checks every status_t, prefers object references appropriate to the task, and revalidates security-sensitive conditions at use time.

The Kit also works with non-BFS file systems, but features differ. An application must not assume that arbitrary mounted volumes support BFS attributes, indexes, or live queries. Capability and error handling are part of portable Haiku software.

Support Kit: shared building blocks

The Support Kit supplies widely used utility types including BString, BList, BLocker, reference and archiving helpers, data I/O abstractions, memory I/O, and byte-order or type facilities. Because these classes appear across other Kits, their ownership and error contracts shape the entire API.

BPositionIO abstracts a seekable stream and is used by files, memory buffers, and translators. BArchivable defines object flattening patterns for classes that support archival. BLocker provides userland locking, but placing a lock around a data structure does not define a complete thread lifecycle or prevent deadlocks.

Use modern C++ facilities where they fit and Haiku types where they participate in a system contract. A BString returned by a Kit or a BMessage field is not an argument against std::unique_ptr in private code. The boundary should be explicit, with ownership converted once rather than mixed ambiguously.

Media and Translation Kits: shared extensibility

The Media Kit models audio/video processing through media nodes, buffers, formats, connections, and system services. Its graph and timing contracts separate producers, consumers, mixers, and devices. Real-time callbacks perform bounded work; file decoding and UI updates occur elsewhere.

The Translation Kit discovers translator add-ons through BTranslatorRoster and converts BPositionIO streams between advertised formats. One translator can extend multiple applications. Identification parses untrusted data, so a shared add-on needs strict size and format validation.

The Kits can cooperate without collapsing into one another. A media editor may use Translation Kit for image assets, Media Kit for timed playback, Storage Kit for project files and attributes, and Interface Kit for windows. Each boundary preserves a testable responsibility.

Availability is dynamic. Installed media add-ons and translators determine runtime capabilities. Query rosters and declared formats rather than showing a hardcoded list based on the developer’s system.

Network, Locale, and other domains

The Network Kit contains address, interface, URL, socket-related, and network-management facilities, while POSIX/BSD sockets are also available through system libraries. Network I/O can block and all received data is untrusted; GUI code uses workers or asynchronous messaging.

The Locale Kit separates catalog translation from locale-aware formatting and collation. BCatalog looks up strings, while number and date formatters present values according to conventions. Interface layouts must tolerate the output rather than measuring English labels.

Device and Kernel Kit APIs expose hardware and low-level objects where appropriate. Kernel Kit is primarily C functions and structures for teams, threads, ports, semaphores, and areas, demonstrating that the B-class convention is common but not universal.

Additional public domains include Package, Mail, Game, MIDI, and OpenGL-related facilities. Consult the generated Haiku Book for the current supported surface. Historical Be Book material is valuable context but may document APIs changed or absent in Haiku.

Shared conventions across Kits

Most operations report status_t values such as B_OK or a specific error. Constructors that cannot return status commonly provide InitCheck(). Check the result before using the object; a non-null C++ instance can represent a failed file open or uninitialized service connection.

Ownership varies by API. Some methods transfer an allocated list to the caller, some return borrowed pointers valid only while an owner exists, and some increment references. Read the exact class reference and encode ownership with RAII locally. Guessing from a pointer type is not sufficient.

Class names commonly begin with B, constants with B_, and public headers are grouped by Kit. That naming makes native types recognizable, but namespace appearance does not grant thread safety. Unless documentation says otherwise, mutate a looper-owned object on its thread or under its lock.

Archiving and flattening are versioned data contracts. Do not unflatten arbitrary input without type and size checks, and do not persist undocumented private fields. Messages and archives can cross processes or outlive the code version that created them.

Libraries and build integration

A Jamfile or other build system must link the library that implements the used Kit. Core Application, Interface, Storage, and Support functionality is commonly provided by libbe; Media, Translation, Network, Locale, and other specialized APIs may require their documented libraries. Header inclusion alone proves only compilation, not linking or runtime availability.

Use pkg-config or Haiku’s documented build conventions where provided, and inspect the class reference’s library annotation. Avoid linking every system library preemptively: it hides dependencies and can make optional functionality mandatory.

Public headers live under headers/os in the source tree, while implementations live under src/kits and system servers. Private headers are not stable application APIs. If a needed feature exists only under headers/private, treat it as experimental/internal and isolate the dependency with a clear compatibility plan.

Application API compatibility is a goal, but Haiku documents differences from BeOS. Porting code should consult the current compatibility page and compile against current headers instead of assuming every undocumented BeOS symbol exists.

Designing an application along Kit boundaries

Let the Application Kit own message routing and lifecycle, Interface Kit own presentation, Storage Kit own file-system interactions, and domain Kits own media, translation, network, or locale behavior. Application-specific model code can sit between them without inheriting from every system class.

Keep blocking work off looper threads. Return results in messages that contain stable data rather than raw pointers to worker-owned objects. Convert external errors into status_t plus useful context at boundaries, and preserve the original status for diagnostics.

Test each boundary independently: malformed BMessage fields, missing attributes or indexes, unavailable translator, media format rejection, locale expansion, network timeout, and service restart. A Kit provides an abstraction, not immunity from partial failure.

The Kit organization has lasted because it expresses durable domains while sharing a consistent native vocabulary. Its value is not that applications use fewer libraries; it is that responsibilities, threading, ownership, and error contracts remain visible as software combines system capabilities.

Related:

Sources:

Comments