summaryrefslogtreecommitdiff
path: root/docs/api-redesign.md
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-13 21:23:03 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-13 21:23:03 +0300
commitdd1775a9927922c14f8679ccbc4d3ca8d5917e20 (patch)
tree3acc442bb4a3470364b74aa82ff67cb84d555c45 /docs/api-redesign.md
parentecb81aeea4c0c880b3a60a0dc8418c4bf2a7cf85 (diff)
public api refactor
Diffstat (limited to 'docs/api-redesign.md')
-rw-r--r--docs/api-redesign.md147
1 files changed, 147 insertions, 0 deletions
diff --git a/docs/api-redesign.md b/docs/api-redesign.md
new file mode 100644
index 0000000..a111a92
--- /dev/null
+++ b/docs/api-redesign.md
@@ -0,0 +1,147 @@
+# Public API redesign
+
+This is the implementation contract for the pre-release API revision. The
+portable layer owns event ordering, queued payloads, surface identities, and
+frame validation. Backends translate native behavior into that contract.
+
+## One event stream
+
+`yasl_display_poll_event(display, &event)` consumes one display-wide FIFO. Input,
+window resize/close/state, drag hover/drop, composition, clipboard results, and
+display quit/reopen/loss use the same `yasl_event`. Events have an increasing
+`sequence` assigned when YASL queues them, and a monotonic `time_ns`. Sequence
+orders capture by YASL, not unknowable ordering between OS threads or devices.
+The runner consumes this same queue; it does not drain separate queues by window.
+
+Event strings are copied on enqueue and borrowed until the next successful
+display poll or display close, even if the recipient is destroyed. Destroying a
+surface removes its undelivered events. A callback may destroy its recipient;
+it must stop using that surface. Draws remain synchronous to satisfy native
+live-resize rules; the runner drains queued events before invoking a frame.
+
+Legacy surface polling consumes input from the same queue and discards pending
+non-input notifications, which were already delivered through legacy callbacks.
+Applications must choose one polling style; discarding prevents idle spin and
+unbounded retention in old manual loops. Legacy window
+callbacks remain for migration, but applications should choose queue delivery
+and a draw callback. Backend notifications must queue before calling a legacy
+callback, and must not access a surface after a callback that can destroy it.
+
+## One frame contract
+
+Both manual drawing and `yasl_app_desc.frame` receive `struct yasl_frame`.
+Its `target` describes CPU pixels (NULL for native rendering), device-pixel size,
+and row stride. The frame also carries frame index, scale, and an estimated
+animation timestamp. Native drawables are queried through `<yasl/native.h>`;
+there is no untyped GPU layer or public internal pointer in the portable frame.
+
+`yasl_frame_present(frame, rects, count)` submits the exact active frame once.
+NULL with zero count means full damage; a non-NULL array with zero count means
+no damage. NULL with nonzero count and negative extents fail with EINVAL.
+More than the backend rectangle limit falls back to full damage after validating
+every rectangle; damage must never be silently lost. Targets expire at callback
+return. Pixels must always describe a complete frame.
+
+`yasl_surface_request_frame` is the normal coalescing redraw operation.
+`yasl_surface_set_pacing` returns success/failure and works with either loop
+style. Continuous drawing uses native pacing where available and a refresh-based
+timer otherwise. On-demand surfaces require explicit invalidation.
+
+## Identities, posting, and shutdown
+
+`yasl_surface_id(surface)` returns a nonzero identity unique within its display.
+`yasl_display_post(display, &message)` is thread-safe; messages target an identity
+(zero means display-wide), never a borrowed surface pointer. The display must
+remain alive during posting, and producer threads must stop before display close.
+After a successful post the optional release callback runs exactly once on the
+display thread, after consumption or cancellation (including surface destruction
+and shutdown). A failed post leaves payload ownership with the caller. Posting
+to a retired identity fails. The display queue owns only its copy of the message;
+the release callback defines payload cleanup. Release may post, but must not
+poll, dispatch, or destroy YASL objects. Legacy `yasl_post_event` adapts to
+this mechanism, with the caller responsible for its borrowed target lifetime.
+
+Application callbacks may return CONTINUE, QUIT, or ERROR. ERROR makes
+`yasl_run` return failure after cleanup. `yasl_app_exit(display, result)` permits
+timers, fd callbacks, and frames to request the same orderly termination.
+The optional initial window is available through `yasl_app_window(display)`.
+Surface userdata is independent of legacy callback userdata and accessible
+through `yasl_surface_set_userdata` / `yasl_surface_userdata`.
+
+## Window requests and units
+
+New code spells toplevel creation size `size_logical`; `size` remains an alias
+for migration. Framebuffer geometry, pointer coordinates, popup placement,
+damage, IME carets, and drag-image coordinates are device pixels as documented
+on their structures. Conversion helpers remain explicit.
+
+`yasl_surface_set_size(surface, logical_size)`,
+`yasl_surface_set_fullscreen(surface, enabled)`,
+`yasl_surface_set_maximized(surface, enabled)`, and
+`yasl_surface_minimize(surface)` return whether the native request was issued.
+They set errno on failure: EINVAL for invalid input/non-toplevel surfaces,
+ENOTSUP for unsupported requests, or an OS error. Success is acceptance of a
+request, not a promise that the window manager honored it. Resulting size/state
+is reported through events. No portable absolute window-position setter exists.
+
+## Clipboard and composition
+
+`yasl_clipboard_set(display, selection, text)` returns whether a copied UTF-8
+offer was issued, with errno on failure. `yasl_clipboard_request(surface,
+selection)` returns a nonzero request ID, or zero with errno on failure.
+The backend operation `display_request_paste(d, selection, surface, id)` returns
+true only after accepting responsibility for one completion. It completes via
+`yasl_surface_complete_paste(surface, id, status, text, len)`; status is
+YASL_TRANSFER_OK, UNAVAILABLE, or FAILED. Results use YASL_EVENT_PASTE and its
+`.paste` payload (data/len/request_id/status); legacy `.text` aliases data/len.
+Surface destruction cancels delivery and native transfers. A backend must
+complete errors as well as success, including empty text. Request IDs are
+monotonic per display. Legacy paste uses ID zero. External Linux transfers time out after 30 seconds.
+
+YASL_EVENT_COMPOSITION carries copied UTF-8 preedit text, byte selection offsets
+(both -1 if unavailable), and an active flag. Each native change queues a
+snapshot, including composition ending; committed text remains YASL_EVENT_TEXT.
+The query functions remain migration helpers.
+
+## Backend boundary
+
+Common helpers declared in `common/backend.h`:
+
+* `yasl_surface_notify_configure(s, geometry)`
+* `yasl_surface_notify_close(s)`
+* `yasl_surface_notify_state(s, state)`
+* `yasl_surface_notify_drag(s, event, position_px)`
+* `yasl_surface_notify_drop(s, event, position_px)`
+* `yasl_surface_notify_composition(s, text, begin, end)` (NULL/empty ends it)
+* `yasl_surface_draw(s, frame)` (fills frame metadata and invokes draw)
+* `yasl_display_notify_event(d, YASL_EVENT_DISPLAY_QUIT/REOPEN/LOST)`
+* `yasl_surface_complete_paste(s, request_id, status, text, length)`
+
+Backends keep using their existing input_queue; a new `surface_input_queue`
+operation exposes that queue to common code for attaching its event publisher.
+Backends must replace direct lifecycle/draw/drag callbacks with these helpers,
+without weakening their native destruction guards. They implement optional
+surface_set_size/fullscreen/maximized/minimize and display_copy_text /
+display_request_paste operations. Common wrappers validate arguments and
+report unsupported operations uniformly.
+
+Linux backends are compiled and tested independently and together. Cocoa changes
+can be inspected here but require macOS compilation/runtime verification.
+
+## Validation
+
+The combined Linux configuration passes all 26 Meson tests, including isolated
+Weston/Xwayland integration, runner error/cleanup paths, event ordering,
+clipboard outcomes, composition, and destruction during callbacks. Separate
+Wayland-only and X11-only builds pass their unit suites and the final public
+export, C++11, and event-contract checks.
+
+AddressSanitizer and UndefinedBehaviorSanitizer pass the common contract tests
+and the isolated backend integration suite. Leak detection was disabled because
+LeakSanitizer is unavailable in this execution environment. Doxygen builds with
+warnings treated as errors. A staged install links both shared and static
+consumers using only the installed headers and pkg-config metadata.
+
+Cocoa code and native regression tests were updated and reviewed, but were not
+compiled or executed: macOS validation remains required. Existing X11 INCR and
+Wayland arbitrary-size limitations are reported explicitly rather than hidden.