# YASL (Yet Another Surface Library) YASL is a minimal, modern, and high-performance desktop window surface library written in C. It provides window creation, frame pacing, high-DPI scaling, and input routing without bundling audio, physics, or game engine components. ## Features - **Lean Core**: No audio, no font rendering, and no widget toolkit overhead. - **Wayland Protocol Coverage**: - `xdg-shell` toplevels and hierarchical popups (`xdg_popup` + `xdg_positioner`). - Fractional scaling via `wp_fractional_scale_v1` and `wp_viewporter`. - Presentation feedback and refresh rate timing via `wp_presentation` and `wp_fifo_v1`. - Cursor shapes via `wp_cursor_shape_device_v1`. - Graphics tablets and stylus input via `zwp_tablet_v2` (pressure, tilt, eraser). - Text Input Method (IME) composition via `zwp_text_input_v3`. - Primary selection and clipboard transfers via `wl_data_device` and `zwp_primary_selection_v1`. - Interactive client-side window move and resize triggers (`xdg_toplevel_move`, `xdg_toplevel_resize`). - **macOS Cocoa & Metal**: - Native `NSWindow` and `CAMetalLayer` presentation. - Vsync pacing via `CADisplayLink`. - **Zero Framework Leaks**: - Self-contained UTF-8 validation. - Self-contained event queue. - No terminal-specific telemetry or hardcoded application names. ## Backend selection YASL selects the native window backend at runtime. Leave `yasl_display_spec.backend` at zero to use this mode. `YASL_BACKEND_AUTO` has the same effect. You can also pass NULL as the display spec. On Linux, YASL tries Wayland first in a Wayland session. It uses `WAYLAND_DISPLAY`, `WAYLAND_SOCKET`, and `XDG_SESSION_TYPE` to detect that session. In other sessions, it tries X11 first. If the first backend cannot open, it tries the other built backend. On macOS, it uses Cocoa. Set `backend` to request one backend: ```c struct yasl_display_spec spec = { .app_id = "org.example.app", .backend = YASL_BACKEND_X11, }; struct yasl_display *display = yasl_display_open(loop, &spec); ``` Use `YASL_BACKEND_WAYLAND` to request Wayland. Use `YASL_BACKEND_COCOA` to request Cocoa. An explicit request never falls back to another backend. Open returns NULL if the requested backend cannot open. It sets `errno` to `ENOSYS` for a backend that was not built. It sets `errno` to `EINVAL` for an invalid backend value. Call `yasl_display_backend(display)` to read the selected backend. All surfaces on a display use that backend. Open separate displays to use Wayland and X11 in one process. The public API needs no window system headers. Use `yasl_display_caps()` to check optional features. X11 supports CPU pixel buffers, keyboard and pointer input, and clipboard transfer. It supports the primary selection and window placement. It does not yet support YASL popups, drag operations, or IME preedit text. Those features return their normal unsupported result. The surface spec needs no native graphics device for CPU drawing. On Cocoa, YASL creates its own Metal device for this mode. An app that renders with Metal can supply its device through `graphics_device`. That app submits and presents the native drawable. The native display handle is a `wl_display *` on Wayland. It is a `Display *` on X11. The native surface handle is a `wl_surface *` on Wayland. On X11, convert it to `Window` through `uintptr_t`. On Cocoa, the native surface handle is the content `NSView *`. ## Building Use a C23 compiler and Meson 1.6 or later. Build with Meson and Ninja: ```sh meson setup build ninja -C build ninja -C build test ``` Linux builds include each backend whose dependencies are installed. Wayland needs `wayland-client`, `wayland-cursor`, and `xkbcommon`. X11 needs `x11` and `xkbcommon`. Use `-Dwayland=enabled` or `-Dx11=enabled` to require a backend. Use `-Dwayland=disabled` or `-Dx11=disabled` to omit a backend. At least one backend must be built. To run the Linux window tests, install Weston and Xwayland. Then run: ```sh meson setup build-test -Dintegration_tests=true meson test -C build-test --print-errorlogs ``` The tests start isolated display servers. They test explicit requests, automatic selection, and fallback. They also test both backends in one process. On macOS, the same option runs native Cocoa window tests. These tests need a desktop session. ## Quick Example ```c #include static void on_draw(struct yasl_surface *s, struct yasl_frame *frame, void *ud) { /* Present frame target */ struct yasl_damage_list dmg = { .n = -1 }; yasl_surface_present(s, &frame->target, &dmg); } int main(void) { struct yasl_loop *loop = yasl_loop_create(); struct yasl_display_spec dspec = { .app_id = "org.example.app" }; struct yasl_display *d = yasl_display_open(loop, &dspec); struct yasl_surface_spec sspec = { .title = "YASL Application", .size = { .x = 800, .y = 600 }, }; struct yasl_surface *s = yasl_surface_create_toplevel(d, &sspec); struct yasl_surface_cbs cbs = { .draw = on_draw }; yasl_surface_set_callbacks(s, &cbs, NULL); yasl_surface_schedule_redraw(s); while (true) { yasl_display_dispatch(d); struct yasl_input_event ev; while (yasl_surface_input_poll(s, &ev)) { /* Handle input */ } yasl_display_flush(d); } } ``` ## License MIT License.