Skip to content

The host library

xpui-cpp-host is the Rust half of a C++ application that hosts xpui screens. It compiles to a staticlib that the C++ links, and it has two public functions: one wires the framework up, and one builds the screen the host starts on. The C ABI is every symbol on both sides of the boundary; the tutorial builds the same thing a step at a time.

Its screens module is public too, because it is the half a firmware would reuse. Menu, About, Controls and Example are the worked example, meant to be read as source, and have no sections here.

xpui_app_installInstalls what paints and what navigates.
xpui_app_create_menuThe root screen's factory, as cpp/xpui_app.h declares it.

Installs what paints and what navigates.

pub unsafe extern "C" fn xpui_app_install()

Two installs, not one. xpui keeps them apart because they answer to different owners, and a host that supplies only the first gets a screen that draws perfectly and whose Back does nothing:

InstallsThroughWithout it
the host: the FreeInkUI backend, which asks the C++ for input, words and device figures through xpui_host_*xpui::host::installnothing paints
the navigator: the shell that turns present and a finished screen into xpui_host_screen_present and xpui_host_screen_finishxpui::host::install_navigatorBack and present silently do nothing

Each install is skipped when one is already in place, so a second call does nothing. A firmware whose render task could run first calls it from each entry point that could, as xpui::host::install_navigator asks, provided those calls can never run at the same time as each other or as a frame. Call it before the first screen is created.

Example — starting the UI

C++
#include <stdint.h>
#include <xpui_app.h>
#include <xpui_fui.h>
// 1 bit per pixel, (width + 7) / 8 bytes per row, and a set bit is white.
static uint8_t framebuffer[(480 + 7) / 8 * 800];
void* start_the_ui(void) {
xpui_fui_attach(framebuffer, 480, 800); // where the panel is
xpui_app_install(); // what paints, and what navigates
return xpui_app_create_menu(); // only now is there a screen
}

See also: xpui_app_create_menu, its C declaration

The root screen's factory, as cpp/xpui_app.h declares it.

pub extern "C" fn xpui_app_create_menu() -> *mut c_void

register_screen!, from xpui-fui, writes the function: the source holds register_screen!(screens::Menu, xpui_app_create_menu), and the declaration above, marked #[unsafe(no_mangle)], is what that expands to.

It builds a screens::Menu with Menu::new and returns it as an opaque handle. The host calls it once, and owns the handle until it passes it to xpui_screen_destroy. Between the two it drives the screen through xpui_screen.h: xpui_screen_on_enter once, then xpui_screen_loop and xpui_screen_render every frame, then xpui_screen_on_exit. The screen handle says what the pointer is and why nothing on the C++ side looks inside it.

Only a screen the C++ opens directly needs a factory. A screen opened from another Rust screen goes out through present and needs none, which is why this crate exports exactly one.

Example — running the root screen

C++
#include <xpui_app.h>
#include <xpui_screen.h>
// After `xpui_app_install`.
void run_the_root(bool (*running)(void)) {
void* menu = xpui_app_create_menu();
xpui_screen_on_enter(menu);
while (running()) {
xpui_screen_loop(menu); // input first: a screen asks for its repaint here
xpui_screen_render(menu);
}
xpui_screen_on_exit(menu);
xpui_screen_destroy(menu); // the handle dangles from here on
}

Example — a second factory beside it

Rust
use xpui::screen::Screen;
use xpui::{NavigationScreen, Text, View};
use xpui_fui::register_screen;
pub struct Brightness;
impl Brightness {
// `register_screen!` calls `new` on the type it is handed.
pub fn new() -> Self {
Brightness
}
}
impl Screen for Brightness {
type Message = ();
fn body(&self) -> impl View<()> {
NavigationScreen::new(Text::new("Brightness")).title("Brightness")
}
fn update(&mut self, _message: ()) {}
}
register_screen!(Brightness, xpui_app_create_brightness);

The C++ then needs one declaration, void* xpui_app_create_brightness(void);, beside the menu's in cpp_host/cpp/xpui_app.h.

See also: xpui_app_install, its C declaration