How to Write a Simple Native GUI Application on Haiku
A complete walkthrough building a minimal windowed application using Haiku's Interface Kit and BApplication/BWindow classes — the actual starting point for any native Haiku app, GUI or not.
Every native Haiku GUI application is built around the same small set of core classes from the Interface Kit — this walks through the minimal skeleton every Haiku app, however complex, ultimately extends.
Step 1: set up a development environment first
Before writing any code, a working Haiku development environment with the necessary headers and build tools needs to be in place — either building on Haiku itself or cross-compiling, depending on your setup.
Step 2: understand the two mandatory base classes
Every Haiku GUI application needs exactly one BApplication subclass (the application object itself, handling app-level events) and at least one BWindow subclass (an actual window) — this pairing is the mandatory minimum, analogous to similar app/window pairings in other GUI frameworks.
Step 3: write the BApplication subclass
#include <Application.h>
class MyApp : public BApplication {
public:
MyApp() : BApplication("application/x-vnd.MyCompany-MyApp") {}
};
int main() {
MyApp app;
app.Run();
return 0;
}
The string passed to BApplication’s constructor is a MIME-style application signature — Haiku uses this for identifying the running application system-wide, including in ProcessController’s team list.
Step 4: write a BWindow subclass
#include <Window.h>
class MyWindow : public BWindow {
public:
MyWindow()
: BWindow(BRect(100, 100, 400, 300), "My App",
B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE) {
Show();
}
};
B_QUIT_ON_WINDOW_CLOSE tells the window to signal application quit when closed — without it, closing the window wouldn’t automatically end the application’s run loop.
Step 5: instantiate the window from your application
class MyApp : public BApplication {
public:
MyApp() : BApplication("application/x-vnd.MyCompany-MyApp") {
MyWindow* window = new MyWindow();
}
};
Step 6: add a view and a control
#include <Button.h>
#include <View.h>
BButton* button = new BButton("my_button", "Click Me",
new BMessage('CLIK'));
AddChild(button);
Controls like BButton communicate back to your application via BMessage objects rather than direct function calls — this message-passing model is the same Looper/Handler pattern that underlies all of Haiku’s inter-thread and inter-application communication, not a GUI-specific special case.
Step 7: handle the button’s message
void MyWindow::MessageReceived(BMessage* message) {
switch (message->what) {
case 'CLIK':
// handle the click
break;
default:
BWindow::MessageReceived(message);
}
}
Overriding MessageReceived and falling through to the base class implementation for anything you don’t explicitly handle is the standard pattern — forgetting the default case’s call to the parent class breaks handling of system messages your window still needs to respond to.
Step 8: compile and run
g++ -o myapp main.cpp -lbe
./myapp
The -lbe flag links Haiku’s core Be API library (libbe), which provides the Interface Kit, Application Kit, and most of the rest of the native API surface a typical app needs.
Why this small skeleton scales to genuinely complex applications
The BApplication/BWindow/BView/BMessage pattern shown here is exactly the same structure underlying Haiku’s own bundled applications, not a simplified teaching example distinct from “real” app architecture — a complex native Haiku application is, structurally, this same skeleton with substantially more views, message types, and handler logic layered on top of it.