# Getting started YASL gives a C application desktop windows with CPU pixel targets, scale-aware geometry, queued input, clipboard text, and optional frame pacing. It fits software-rendered tools such as editors, terminals, drawing applications, and custom interfaces that already have their own renderer. A window needs neither an OpenGL context nor a graphics device supplied by the application. The core headers expose no window system types. Native handles and Metal drawing are separate opt-in extensions. YASL currently supports Linux (Wayland and X11) and macOS (Cocoa); it does not provide widgets, font shaping, audio, an OpenGL context API, or a Vulkan surface API. It is pre-release software; see the [API policy](api-policy.md) before distributing a library that depends on its ABI. ## Build and run Use a C23 compiler, Meson 1.6 or newer, and Ninja. GCC and Clang can build the library. On Linux install either backend's development dependencies: | Backend | pkg-config dependencies | | --- | --- | | Wayland | `wayland-client`, `wayland-cursor`, `xkbcommon` | | X11 | `x11`, `xi`, `xkbcommon`, `xext`; optional `xrandr` | | Cocoa | macOS 14+ SDK with AppKit, Metal, and QuartzCore; Metal-capable device | ```sh meson setup build meson compile -C build ./build/yasl-hello meson test -C build --print-errorlogs ``` Each Linux backend defaults to `auto`, meaning build it when its dependencies are available. Require one with `-Dwayland=enabled` or `-Dx11=enabled`; omit one with `-Dwayland=disabled` or `-Dx11=disabled`. At least one backend is required. Cocoa is selected on macOS and requires no extra third-party dependencies. Its minimum deployment target is macOS 14. Set `MACOSX_DEPLOYMENT_TARGET=14.0` (or newer) before configuring if your toolchain defaults to an older target. CPU pixel targets are presented through the system's Metal device; applications do not need to create or manage that device themselves. The complete beginner example is [hello.c](../examples/hello.c). It checks construction failures, fills every pixel, presents inside `draw`, drains input, responds to quit/close/lost, and destroys resources in order. The [interactive window](../examples/simple_window.c) adds pointer input; the [tablet example](../examples/tablet.c) demonstrates retained application content, pressure, erasers, resizing, and scale changes. ## Link an application Install the library and public headers into your chosen prefix: ```sh meson setup build --prefix=/usr/local meson compile -C build meson install -C build cc -std=c23 examples/hello.c -o hello $(pkg-config --cflags --libs yasl) ./hello ``` The prefix must be writable, and your compiler, pkg-config, and runtime loader must search it. For a custom prefix, set `PKG_CONFIG_PATH` to its pkg-config directory and configure the loader for its library directory. Static linking uses `pkg-config --static --libs yasl` to include backend dependencies. A Meson consumer uses the installed dependency: ```meson project('my-app', 'c', default_options: ['c_std=c23']) yasl = dependency('yasl', version: '>=0.1.0') executable('my-app', 'main.c', dependencies: yasl) ``` YASL also declares `meson.override_dependency('yasl', ...)`, so the same consumer can use a vendored Meson subproject through a fallback dependency. Public headers can be included from C++11 or newer; the library itself builds as C23. ## The application cycle 1. Open a display with `yasl_display_open(NULL, &spec)`. NULL creates a loop owned by the display. Supply your own loop only when you need shared loop ownership. 2. Create a toplevel with a positive **logical-pixel** size and install callbacks. Zero-initialize every option and callback struct. Callback tables are copied; userdata must remain alive. Registration can call back synchronously. 3. Schedule the initial redraw. `draw` receives a borrowed target. Fill every pixel with premultiplied `0xAARRGGBB`, then present that exact target, once. 4. Dispatch, drain input for every live surface queue, update application state, and flush. Flush runs scheduled drawing and sends native requests. Dispatch may also invoke callbacks, including drawing during native live resize. 5. Destroy popups before parents, surfaces before displays, and displays before any supplied loop. NULL destroy/close calls do nothing; freed pointers are invalid for every operation. ```c while (running) { if (yasl_display_dispatch(display, -1) < 0) { perror("yasl_display_dispatch"); break; } struct yasl_input_event event; while (yasl_surface_input_poll(surface, &event)) { /* Read the union member selected by event.kind. */ } yasl_display_flush(display); } ``` Zero timeout polls, positive timeout bounds the wait in milliseconds, and a negative timeout waits for work. Undrained input makes dispatch return without waiting. Use the return value only to detect failure, not to count input events. If callbacks destroy surfaces, update your application registry immediately and only poll surfaces that are still alive. Arrange display/loop cleanup after the cycle ends; destroying them inside a callback is unsupported. See the [application guide](guide.md) for drawing, input, popups, timers, and platform limits, or the comments in the [public header](../include/yasl/yasl.h) for each function's contract. To build the searchable HTML reference, install Doxygen and run `doxygen Doxyfile` from the repository root. Open `build-docs/html/index.html`; Doxygen is not needed to build the library.