summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-12 00:09:38 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-12 00:09:38 +0300
commit624d1371304a5ae4b3429ad5e4267aac7cd03dfd (patch)
tree32de069f6eec83686521fc4bf39cc9874b123e93 /include
parente813252e685d761235ad45e170d97c9375f51958 (diff)
missing impls and hardening
Diffstat (limited to 'include')
-rw-r--r--include/yasl/timing.h10
-rw-r--r--include/yasl/yasl.h64
2 files changed, 69 insertions, 5 deletions
diff --git a/include/yasl/timing.h b/include/yasl/timing.h
index 7c66967..85f305d 100644
--- a/include/yasl/timing.h
+++ b/include/yasl/timing.h
@@ -15,11 +15,20 @@ struct yasl_resize_stats {
long minflt;
};
+/* Describes last_present_ns, not merely availability of an extension. */
+enum yasl_timing_source {
+ YASL_TIMING_UNKNOWN = 0,
+ YASL_TIMING_SUBMISSION, /* CPU submission time; not scanout confirmation */
+ YASL_TIMING_FRAME_CALLBACK, /* compositor pacing callback, not scanout */
+ YASL_TIMING_PRESENTATION, /* compositor-confirmed presentation */
+};
+
struct yasl_timing {
double refresh_ns;
uint64_t last_present_ns;
uint64_t next_present_ns;
uint64_t frames_skipped;
+ enum yasl_timing_source source;
struct yasl_resize_stats resize;
};
@@ -33,6 +42,7 @@ struct yasl_frame_clock {
long resize_minflt;
uint64_t frame_time_ns;
double refresh_ns;
+ enum yasl_timing_source source;
};
uint64_t yasl_clock_extend_ms(uint32_t ms, uint64_t now_ns);
diff --git a/include/yasl/yasl.h b/include/yasl/yasl.h
index 6fea487..2852112 100644
--- a/include/yasl/yasl.h
+++ b/include/yasl/yasl.h
@@ -4,6 +4,8 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
+#include <limits.h>
+#include <float.h>
#include "yasl/timing.h"
@@ -45,14 +47,25 @@ struct yasl_rect2i {
#define YASL_SCALE_UNIT 120
#define YASL_MIN_LOGICAL_PX 64
+/* Nearest integer, ties away from zero. Zero scale returns zero; finite
+ * out-of-range results saturate. Non-finite logical coordinates return zero. */
static inline int yasl_scale_to_device(double logical, uint32_t scale_120)
{
- return (int)((logical * (double)scale_120 + YASL_SCALE_UNIT / 2) / YASL_SCALE_UNIT);
+ if (!scale_120 || !(logical >= -DBL_MAX && logical <= DBL_MAX)) return 0;
+ double px = logical * ((double)scale_120 / YASL_SCALE_UNIT);
+ if (px >= INT_MAX) return INT_MAX;
+ if (px <= INT_MIN) return INT_MIN;
+ return (int)(px < 0 ? px - 0.5 : px + 0.5);
}
static inline int yasl_scale_to_logical(int device, uint32_t scale_120)
{
- return (int)(((int64_t)device * YASL_SCALE_UNIT + scale_120 / 2) / scale_120);
+ if (!scale_120) return 0;
+ int64_t px = (int64_t)device * YASL_SCALE_UNIT;
+ px = (px + (px < 0 ? -(int64_t)(scale_120 / 2) : scale_120 / 2)) / scale_120;
+ if (px > INT_MAX) return INT_MAX;
+ if (px < INT_MIN) return INT_MIN;
+ return (int)px;
}
/* Capabilities */
@@ -63,6 +76,8 @@ enum yasl_display_cap : uint32_t {
YASL_CAP_PLACE_WINDOW = 1 << 3,
YASL_CAP_PRIMARY_SELECTION = 1 << 4,
YASL_CAP_CSD = 1 << 5,
+ YASL_CAP_NATIVE_GRAPHICS = 1 << 6,
+ YASL_CAP_FRAME_PACING = 1 << 7, /* compositor/display-driven draws */
};
enum yasl_selection : uint8_t {
@@ -103,7 +118,12 @@ enum yasl_resize_edge : uint32_t {
YASL_EDGE_BOTTOM_RIGHT = 10,
};
-/* Damage & Framebuffer */
+/* Damage & Framebuffer
+ * CPU pixels are tightly packed premultiplied ARGB8888 (0xAARRGGBB).
+ * Size, pointer positions, IME caret and damage use device pixels; surface
+ * creation sizes use logical pixels. Damage is a hint: backends may upload
+ * the whole frame. Every pixel must contain valid content on each draw.
+ */
#define YASL_DAMAGE_MAX 64
struct yasl_damage_list {
@@ -113,6 +133,7 @@ struct yasl_damage_list {
};
struct yasl_framebuffer {
+ uint64_t generation; /* Opaque draw identity; preserve when copying target. */
uint32_t *pixels;
struct yasl_vector2i size;
int buffer;
@@ -224,6 +245,9 @@ enum yasl_input_kind {
YASL_INPUT_PASTE,
YASL_INPUT_DROP_FILES,
YASL_INPUT_TEXT,
+ /* Allocation failure broke the input stream. Clear all held keys/buttons
+ * and composition state before processing subsequent events. */
+ YASL_INPUT_RESET,
};
struct yasl_input_event {
@@ -240,6 +264,17 @@ struct yasl_input_event {
};
};
+/* Ownership and threading
+ * All calls and callbacks run on the display's opening thread (main thread on
+ * Cocoa). Displays borrow supplied loops; destroy surfaces before displays,
+ * popups before parents, and displays before their supplied loop.
+ * Specs, strings, callback tables and drag listeners are copied during calls.
+ * Userdata is borrowed until callbacks are removed or the object/drag ends.
+ * Native handles are borrowed and expire when their owning object is destroyed.
+ * Surface destruction is allowed from its callbacks; display/loop destruction
+ * during dispatch or callbacks is not supported.
+ */
+
/* Callbacks */
struct yasl_display_cbs {
void (*quit)(void *ud);
@@ -284,9 +319,12 @@ YASL_API void yasl_display_dispatch(struct yasl_display *d);
YASL_API int yasl_display_dispatch_timeout(struct yasl_display *d, int timeout_ms);
YASL_API void yasl_display_flush(struct yasl_display *d);
YASL_API int yasl_display_modifiers(const struct yasl_display *d);
+/* Unsupported/invalid selections are no-ops, never clipboard aliases. */
YASL_API void yasl_display_copy(struct yasl_display *d, enum yasl_selection sel, const char *text);
YASL_API void yasl_display_paste(struct yasl_display *d, enum yasl_selection sel, struct yasl_surface *target);
+/* A successful drag invokes the copied listener's non-NULL end once, including
+ * cancel and display close. Failed starts do not invoke it. */
YASL_API bool yasl_display_drag_start(struct yasl_display *d, struct yasl_surface *origin,
const struct yasl_drag_image *image,
const struct yasl_drag_listener *l, void *ud);
@@ -298,7 +336,9 @@ struct yasl_surface_spec {
struct yasl_vector2i size;
bool fullscreen;
bool tearing;
- /* Optional native graphics device. NULL selects CPU pixel presentation. */
+ /* Optional native graphics device (retained on Cocoa). Requires
+ * YASL_CAP_NATIVE_GRAPHICS; other backends reject it with ENOTSUP.
+ * NULL selects CPU pixel presentation. */
void *graphics_device;
};
@@ -323,19 +363,33 @@ YASL_API void yasl_surface_set_callbacks(struct yasl_surface *s,
const struct yasl_surface_cbs *cbs, void *ud);
YASL_API void yasl_surface_set_title(struct yasl_surface *s, const char *title);
YASL_API void yasl_surface_schedule_redraw(struct yasl_surface *s);
+/* Present exactly the target supplied to the current draw callback, at most
+ * once. Targets and native drawables expire when that callback returns or
+ * the surface is destroyed.
+ * damage is required: n must be -1 or 0..YASL_DAMAGE_MAX. Rectangles must have
+ * nonnegative extents; they are clipped to the target. Invalid input returns
+ * false without consuming the frame. Native renderers submit/present their
+ * drawable themselves, then call this function to record the submission. */
YASL_API bool yasl_surface_present(struct yasl_surface *s, const struct yasl_framebuffer *fb,
const struct yasl_damage_list *damage);
+/* Event payload strings are library-owned, NUL-terminated, and valid until
+ * the next SUCCESSFUL poll on this surface or surface destruction. Dispatch,
+ * flush and unsuccessful polls do not invalidate them. Copy to keep longer. */
YASL_API bool yasl_surface_input_poll(struct yasl_surface *s, struct yasl_input_event *ev);
YASL_API struct yasl_vector2i yasl_surface_size(const struct yasl_surface *s);
YASL_API uint32_t yasl_surface_scale_120(const struct yasl_surface *s);
YASL_API uint32_t yasl_surface_state(const struct yasl_surface *s);
+/* Timing uses monotonic nanoseconds. Check source before treating timestamps
+ * as presentation confirmation. refresh/next_present are estimates. Without
+ * YASL_CAP_FRAME_PACING, redraws run on flush without display synchronization.
+ * Tearing may bypass pacing even when the capability is present. */
YASL_API struct yasl_timing yasl_surface_timing(const struct yasl_surface *s);
YASL_API uint64_t yasl_surface_frame_time_ns(struct yasl_surface *s, uint64_t now);
YASL_API void yasl_surface_set_cursor(struct yasl_surface *s, enum yasl_cursor cursor);
YASL_API void yasl_surface_set_background_color(struct yasl_surface *s, uint32_t bg);
-/* IME Support */
+/* IME Support: preedit is borrowed until the next dispatch or destruction. */
YASL_API const char *yasl_surface_ime_preedit(const struct yasl_surface *s);
YASL_API bool yasl_surface_ime_preedit_cursor(const struct yasl_surface *s, int *begin, int *end);
YASL_API void yasl_surface_set_ime_caret(struct yasl_surface *s, struct yasl_rect2i caret);