summaryrefslogtreecommitdiff
path: root/docs/getting-started.md
blob: 73af4ab6b5dc08c2ac547748b9abe995f9a23630 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# 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 lets
`yasl_run()` create its window from `yasl_app_desc.window`, fills every pixel
with an RGB gradient, and presents inside a frame callback.
`yasl_run()` handles input delivery, display notifications, and cleanup. 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 shared and static libraries into your chosen prefix. Headers,
examples, documentation, and pkg-config metadata remain in the source tree:

```sh
meson setup build --prefix=/usr/local --libdir=lib
meson compile -C build
meson install -C build
cc -std=c23 -Iinclude examples/hello.c -o hello -L/usr/local/lib -Wl,-rpath,/usr/local/lib -lyasl
./hello
```

The prefix must be writable. Use matching headers from `include/`, and adjust
the library search path and runtime path for your chosen prefix and `libdir`.
Static consumers must also link the enabled backends' dependencies.

A Meson application can instead vendor the source under `subprojects/yasl`:

```meson
project('my-app', 'c', default_options: ['c_std=c23'])
yasl = subproject('yasl').get_variable('yasl_dep')
executable('my-app', 'main.c', dependencies: yasl)
```

The subproject dependency includes headers and backend link dependencies.
Public headers can be included from C++11 or newer; the library itself builds
as C23. Only the library artifacts are installed by `meson install`.

## The application cycle

1. Include `<yasl/app.h>` and initialize a `yasl_app_desc` with your userdata and
   `init`, `event`, and `frame` callbacks. Call `yasl_run(&desc)`.
2. In `init`, create a toplevel with a positive **logical-pixel** size and call
   `yasl_surface_request_frame(surface)` for the first redraw.
3. In `event`, handle the union member selected by `event->type`. Return
   `YASL_APP_QUIT` for a close request; otherwise return `YASL_APP_CONTINUE`.
4. In `frame`, fill every pixel in `frame->cpu.pixels` with premultiplied
   `0xAARRGGBB` and present once with `yasl_frame_present_cpu(frame, NULL, 0)`.
5. Let the runner close remaining surfaces and the display. Release your own
   resources in the optional `quit` callback or after `yasl_run()` returns.

```c
struct yasl_app_desc desc = {
    .app_id = "org.example.app",
    .userdata = &app,
    .init = init,
    .event = event,
    .frame = draw,
};
return yasl_run(&desc);
```

The default pacing mode sleeps until input, resize, or a requested redraw.
Use `YASL_PACING_CONTINUOUS` for an animation or game. The core API still supports
manual dispatch/poll/flush when an application owns its event loop; see the guide.

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.