# Surface and input guide ## Lifetime, threads, and errors The first successful `yasl_surface_create` or `yasl_gl_surface_create` initializes shared native state. Subsequent surfaces share one backend. Optional `yasl_set_app_id` and `yasl_set_backend` configure the next initialization; they fail after initialization. Destroying the final surface preserves shared state. `yasl_shutdown` destroys remaining surfaces, releases the backend, and restores defaults. Release application-owned GPU objects before their surface or shutdown. Parent destruction destroys popup descendants. Creation, window operations, event pumping, and shutdown use the first creation's thread, which must be the main thread on Cocoa. GL context binding/drawing/swapping may use a rendering thread; detach its context before destroying the window. The application synchronizes renderer state/geometry and joins workers before shutdown. `yasl_wake` is thread-safe and does nothing before initialization or after shutdown. Constructors return NULL on failure; fallible mutations return bool. Event reads return 1 for an event, 0 for empty/timeout/wake, -1 for failure. `yasl_get_error` returns a stable per-thread error and static description; `yasl_get_native_error` returns supplementary native diagnostics. Success does not clear a preceding error. Valid-object size/scale/userdata getters return ordinary values. Destroyed pointers are invalid. Strings passed to creation and setters are copied; userdata is borrowed. ## Events and coordinates `yasl_poll_event` and `yasl_wait_event` process native events and consume one shared FIFO. No manual dispatch/flush cycle. A failed/empty read leaves output unchanged. Wait timeout zero polls, negative waits for work, positive milliseconds bound waiting. A wake can return zero. Polling before initialization returns zero; waiting reports NOT_INITIALIZED. Close and quit are requests; the application decides how to respond. Display loss is a terminal native failure; destroy resources and shut down. Read the union member selected by type. Events own their text through `yasl_event_release`, independently of later polls and source destruction. Release every successful event exactly once; numeric events need no allocation to release. Do not duplicate event ownership by shallow copying. Event surface pointers remain borrowed and become invalid when their surface is destroyed. Undelivered events for a destroyed surface are canceled. Sequence orders capture by YASL, not OS causality. Timestamps use monotonic nanoseconds; native_time states whether normalized native sample timing was available or capture time was used. Creation dimensions, pointer/pen coordinates, popup placement, caret, and CSD actions use logical content units. Fractional positions use doubles. Image dimensions, byte stride, framebuffer size, and damage use device pixels. Query actual framebuffer extent for swapchain/viewport sizing; scale alone need not determine integer rounding. Request functions report acceptance, while geometry/state events report actual results. There is no portable absolute window-position promise. State's known mask distinguishes reported false from unavailable state fields. ## Rendering GPU creation (flags zero) does not create a device, context, or software framebuffer. One presenter attaches to each surface. Incompatible second attachments fail. - Vulkan: inject vkGetInstanceProcAddr, query instance extensions and flags through the live GPU surface, create the instance, then `yasl_vulkan_create_surface`. The application owns VkInstance/VkDevice/queues/swapchains/VkSurfaceKHR, handles image acquisition, synchronization and recreation, and presents with Vulkan. - Metal: `yasl_metal_layer` returns a borrowed CAMetalLayer on Cocoa. YASL owns the native view/layer and updates its dimensions. The app sets device/pixel format, obtains drawables, and submits/presents commands. No additional YASL present call. - GL: `yasl_gl_surface_create` accepts title, dimensions, flags, a per-call int key/value attribute list terminated by YASL_GL_END, and an optional sharing surface. NULL attributes default to GL3.2 core, RGBA8, depth24/stencil8. The surface owns its context. Bind, load procedures, set swap interval, and swap explicitly. Available on Linux with EGL; GL API support depends on the native driver. Cocoa reports UNSUPPORTED for GL creation; use Metal or MoltenVK. - CPU: create with YASL_SURFACE_CPU and call `yasl_cpu_present` with premultiplied numeric 0xAARRGGBB, width/height, byte stride, and optional damage rows containing x/y/width/height. Extent must match current framebuffer. NULL/zero damage means full; explicit lists must be nonempty. Initial submission and changed extent require full images. Later patches update the retained submitted image. Source bytes are copied before return, so the app may reuse/free them. Native uploads may copy the entire retained image, but never unsubmitted source changes. `yasl_cpu_read_pixels` reads that submitted CPU image, not the composited screen. GPU creation/presentation uses native requests directly; YASL acknowledges Wayland configuration before external GPU submission. Native refresh events can be handled in the ordinary loop. An optional refresh callback permits drawing while the native window system remains in a modal resize path. It runs only during pumping and never recursively; it may query geometry and render, but must not pump, create/destroy surfaces, or shut down. Geometry events may not yet have been consumed, so query current geometry there. Without a hook, CPU exposes reuse committed pixels and GPU redraw waits for the application's loop to resume. ## Keyboard, pen, and scrolling Physical YASL_KEY names identify US keyboard positions independent of layout. Layout labels support shortcuts; committed UTF-8 TEXT is for document insertion. Keys and text need not correspond one-to-one. Input RESET/focus loss cancels held application input. Keep pointer and pen streams separate to avoid duplicate strokes. PEN events carry connection-local device/tool IDs, tool type, proximity/contact, button transitions, coherent position and axes. Pressure is 0..1; zero does not end contact. Tilt uses degrees -90..90; rotation uses clockwise degrees; distance is normalized, not a physical unit. Axis validity distinguishes unavailable from zero. Changed masks indicate native updates. Tools/axes depend on hardware and backend; IDs do not guarantee persistent hardware serials. Pen-generated mouse duplicates are suppressed where recognized; do not treat tool class as a multi-contact API. SCROLL preserves wheel-line and precise-pixel values with validity, source, phase, and momentum metadata where supplied. Applications choose layout pixels per wheel line. X11 supplies native wheel/smooth valuator data where available. Missing native metadata stays explicitly unavailable instead of being inferred. ## Text input, clipboard, popups, and drags Activate text input for a text control with `yasl_surface_set_text_input`. Set purpose, caret, and copied UTF-8 surrounding text/selection/revision through direct setters. Snapshot offsets and TEXT_EDIT replacement ranges are UTF-8 bytes; COMPOSITION is uncommitted preedit. Apply a matching-revision edit once, update your snapshot, and ignore/rebase stale edits. Activation generation distinguishes controls. Ordinary key text remains TEXT. Never insert preedit as committed document text. Wayland requires text-input-v3 for native IME; absence is reported as unsupported. Cocoa translates native UTF-16 replacement/deletion to snapshot UTF-8 ranges. X11 XIM supplies ordinary text/preedit but cannot promise surrounding-text replacement support. Clipboard set copies UTF-8; read returns a nonzero request ID and later CLIPBOARD completion with OK, UNAVAILABLE, or FAILED. Empty successful text is distinct from failure. Destroying the target cancels transfer and delivery. Primary selection stays independent and reports unsupported where unavailable. Linux external transfers time out after 30 seconds; X11 currently lacks INCR for large transfers. File drops carry URI-list text; `yasl_drop_next_path` decodes supported local paths into caller buffers. Popup arguments use logical parent anchor coordinates, anchor/gravity directions, and flip/slide/resize constraint bits. Popup size includes its content. Destroying a parent retires descendants too. Native grabs, CSD moves/resizes, menus, and surface drags require a live triggering press event; unsupported/expired input fails explicitly. Surface drags support application tab/window carry; they are not an arbitrary MIME source API. Check operation results even when feature bits advertise support. ## Backend limits Wayland support varies by compositor protocols; no portable absolute placement or minimized-state query is assumed. X11 currently reports unit scale and lacks an implemented relative-pointer lock. Cocoa requires macOS 14+; native Metal/GL and Objective-C paths require validation on macOS. EGL/wayland-egl and Vulkan SDK support are independently optional at build time. Feature bits describe implementation/ server support, not guaranteed permission or attached hardware. The current work was compiled and tested on Linux; macOS validation remains a separate required check.