Module gui::gui
GUI: cross-platform windows + software framebuffer.
The std/gui stack, bottom to top (include only what you use):
gui.h windows, events, clipboard, cursors, the pixel buffer
gui_draw.h the original integer primitives + 8x8 bitmap font
gui_canvas.h anti-aliased 2D vector canvas (paths, gradients, images,
transforms, clipping, blend modes, TrueType text)
gui_text.h TrueType/OpenType fonts and text layout
gui_widget.h retained widget toolkit (layout, theming, ~35 widgets)
gui_app.h application object: many windows, one event loop,
timers, animation frames
gui_backend.h the interface a windowing backend implements
gui_headless.h an in-memory backend (tests, CI, offscreen rendering)
gui_gpu.h GPU presentation (OpenGL ES/EGL, Metal, Direct3D 11, WebGL)
gui_wayland.h the Wayland backend (Linux)
gui_web.h the WebAssembly <canvas> backend
Exactly one platform backend is linked — safeguard picks it by the file's suffix for the target (see gui_backend.h for the contract):
std/gui/gui_cocoa.sc macOS, via the Objective-C runtime + Core Graphics
std/gui/gui_win32.sc Windows, via the Win32 API
std/gui/gui_x11.sc Linux/BSD/Unix, via Xlib — and on Linux the
Wayland backend next to it, chosen at run time
when there is a compositor (gui_wayland.h)
std/gui/gui_web_wasm.sc WebAssembly: <canvas> elements of a web page
(gui_web.h, with std/gui/gui_web.js)
std/gui/gui_fb.sc bare metal, via a linear framebuffer (see gui_fb.h)
A program can also install another backend at run time before its first window (gui_set_backend(), gui_backend.h) — gui_headless.h's in-memory one (or any program: SAFEC_GUI_BACKEND=headless). Presenting can go through the GPU instead of a software blit: gui_gpu.h.
Every backend presents the same model: a window owns a CPU-side pixel buffer, 'pixels' — RGBA8888, premultiplied alpha, top-left origin, row-major, 4 bytes per pixel, R first in memory on every platform — that the application draws into (directly, through gui_draw.h, through gui_canvas.h, or through the widget toolkit), and win.present() puts it on the screen (the backend converts to its native pixel order on the way, or hands it to a GPU presenter: see gui_backend.h's GuiPresenter). Rasterization is always on the CPU, deterministic and identical on every backend: the same frame is the same bytes on Cocoa, Win32, X11, bare metal and the headless backend.
Sizes: a window's size is given in logical units (points on macOS, device-independent pixels on Windows, pixels on X11). With GuiWindowOptions.hiDpi set, the pixel buffer is the window's size times the display's scale factor (win.scale, e.g. 2.0 on a Retina display), so drawing is sharp; otherwise scale is 1 and the OS scales the window up. Event coordinates and win.width/height are always in buffer pixels.
Structs
| GuiColor | An RGBA color, straight (not premultiplied) alpha — the canvas premultiplies when it blends. Lives here (rather than in gui_draw.h) so GuiWindow can declare its drawing methods without the core header depending on any add-on header. |
| GuiEvent | |
| GuiWindowOptions | Everything GuiWindow::create_with() can be told. Start from GuiWindowOptions::new(title, w, h) and change fields. |
| GuiWindow |
Functions
| gui_time_ms | Milliseconds on a monotonic clock (the headless backend's is virtual and only moves with gui_headless_advance()). |
| gui_clipboard_set_text | The system clipboard, as UTF-8 text. set returns 1 on success; get replaces 'out' with the clipboard's text and returns 1, or returns 0 (leaving 'out' empty) when there is no text on it. Needs a window to exist on X11 (the clipboard is owned by a window there). |
| gui_clipboard_get_text | |
| gui_primary_mod | GUI_MOD_META on macOS, GUI_MOD_CTRL elsewhere (for the backend in use). |
| gui_display_scale | The display scale factor new hiDpi windows will get (1.0, 1.25, 2.0, ...). |
Macros
| GUI_EVENT_NONE | Event/key constants are plain #defines (not enums) to match the rest of the standard library's convention for cross-namespace constant access (see e.g. std/serial/protobuf.h's PB_WIRE_* ) — a real 'enum' declared inside 'namespace std' can't be referenced from user code as 'std::SOME_CONSTANT' the way a free function or #define can. |
| GUI_EVENT_CLOSE | the user asked to close the window (title-bar close, Alt+F4, ...) |
| GUI_EVENT_RESIZE | width/height: the new buffer size (already applied to win.pixels) |
| GUI_EVENT_MOUSE_DOWN | |
| GUI_EVENT_MOUSE_UP | |
| GUI_EVENT_MOUSE_MOVE | |
| GUI_EVENT_KEY_DOWN | keycode + modifiers; codepoint = the typed character, if any |
| GUI_EVENT_KEY_UP | |
| GUI_EVENT_CHAR | a typed character with no KEY_DOWN to carry it (IME, compose) |
| GUI_EVENT_SCROLL | scrollDx/scrollDy in "lines" (+y = away from the user / up) |
| GUI_EVENT_FOCUS_IN | the window became the keyboard-focus window |
| GUI_EVENT_FOCUS_OUT | |
| GUI_EVENT_MOVE | x/y: the window's new position on screen (logical units) |
| GUI_EVENT_MOUSE_ENTER | |
| GUI_EVENT_MOUSE_LEAVE | |
| GUI_EVENT_SCALE | the scale factor changed (moved to another display); width/height = new buffer size |
| GUI_EVENT_EXPOSE | the OS lost the window's contents: present again |
| GUI_KEY_UNKNOWN | Portable key codes for GUI_EVENT_KEY_DOWN/UP's 'keycode' field — each backend translates its own native key codes into these, so application code never sees a platform-specific key code. Letter keys are their upper-case ASCII value ('A'..'Z' = 65..90) and digit keys theirs ('0'..'9' = 48..57), whatever the keyboard layout's shift state. |
| GUI_KEY_LEFT | |
| GUI_KEY_RIGHT | |
| GUI_KEY_UP | |
| GUI_KEY_DOWN | |
| GUI_KEY_ENTER | |
| GUI_KEY_ESCAPE | |
| GUI_KEY_TAB | |
| GUI_KEY_BACKSPACE | |
| GUI_KEY_SPACE | |
| GUI_KEY_DELETE | |
| GUI_KEY_HOME | |
| GUI_KEY_END | |
| GUI_KEY_PAGE_UP | |
| GUI_KEY_PAGE_DOWN | |
| GUI_KEY_INSERT | |
| GUI_KEY_F1 | F1..F12 = 16..27 |
| GUI_KEY_F12 | |
| GUI_KEY_SHIFT | |
| GUI_KEY_CONTROL | |
| GUI_KEY_ALT | |
| GUI_KEY_META | Command (macOS), Windows/Super key |
| GUI_KEY_MENU | |
| GUI_MOD_SHIFT | GuiEvent.modifiers bits (held while the event happened). |
| GUI_MOD_CTRL | |
| GUI_MOD_ALT | Option on macOS |
| GUI_MOD_META | Command on macOS, Windows/Super key elsewhere |
| GUI_BUTTON_LEFT | GuiEvent.button. |
| GUI_BUTTON_RIGHT | |
| GUI_BUTTON_MIDDLE | |
| GUI_CURSOR_ARROW | Mouse cursor shapes (GuiWindow::set_cursor). |
| GUI_CURSOR_IBEAM | |
| GUI_CURSOR_HAND | |
| GUI_CURSOR_CROSSHAIR | |
| GUI_CURSOR_RESIZE_EW | ↔ |
| GUI_CURSOR_RESIZE_NS | ↕ |
| GUI_CURSOR_RESIZE_NWSE | |
| GUI_CURSOR_RESIZE_NESW | |
| GUI_CURSOR_MOVE | |
| GUI_CURSOR_WAIT | |
| GUI_CURSOR_NOT_ALLOWED | |
| GUI_CURSOR_HIDDEN | |
| GUI_CURSOR_COUNT | |
| GUI_POS_DEFAULT | GuiWindowOptions.x/y: let the window system place the window. |
| GUI_PRESENT_DEFAULT | GuiWindowOptions.present: how win.present() gets the buffer on screen (see gui_gpu.h). Either way rendering stays on the CPU. |
| GUI_PRESENT_GPU | through the GPU (OpenGL ES/EGL, Metal, Direct3D 11); CPU if that fails |
| GUI_PRESENT_CPU | the backend's software blit, whatever the environment says |