diff options
| author | Berke Güzel <wenekar1@gmail.com> | 2026-10-11 23:51:43 +0300 |
|---|---|---|
| committer | Berke Güzel <wenekar1@gmail.com> | 2026-10-11 23:51:43 +0300 |
| commit | e813252e685d761235ad45e170d97c9375f51958 (patch) | |
| tree | e57bae545c0eb22aac4119a890b8344ee7cd09d2 /src/common/backend.c | |
| parent | 608b49052178ea74f593c925cdeedf352aa1c357 (diff) | |
| parent | 6eac0a5f2c552728efca420b1129fae7d4fea773 (diff) | |
Merge branch 'backend-selection' into main
- Implement runtime backend selection (Wayland, X11, Cocoa)
- Add native X11 backend with clipboard, keyboard, mouse, and placement
- Integrate multi-backend integration tests running under Weston and Xwayland
- Retain zero-hole struct packing, branchless ALU/LUT primitives, and paced event loop
Diffstat (limited to 'src/common/backend.c')
| -rw-r--r-- | src/common/backend.c | 333 |
1 files changed, 333 insertions, 0 deletions
diff --git a/src/common/backend.c b/src/common/backend.c new file mode 100644 index 0000000..2220f1f --- /dev/null +++ b/src/common/backend.c @@ -0,0 +1,333 @@ +#include "backend.h" + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +static const struct yasl_backend_ops *backend_ops(enum yasl_backend backend) +{ + switch (backend) { +#if YASL_HAS_WAYLAND + case YASL_BACKEND_WAYLAND: return &yasl_wayland_backend; +#endif +#if YASL_HAS_X11 + case YASL_BACKEND_X11: return &yasl_x11_backend; +#endif +#if YASL_HAS_COCOA + case YASL_BACKEND_COCOA: return &yasl_cocoa_backend; +#endif + default: return NULL; + } +} + +static struct yasl_display *open_backend(enum yasl_backend backend, + struct yasl_loop *loop, const struct yasl_display_spec *spec) +{ + const struct yasl_backend_ops *ops = backend_ops(backend); + if (!ops) { + errno = ENOSYS; + return NULL; + } + errno = 0; + struct yasl_display *d = ops->display_open(loop, spec); + if (!d && !errno) errno = ENODEV; + return d; +} + +struct yasl_display *yasl_display_open(struct yasl_loop *loop, + const struct yasl_display_spec *spec) +{ + enum yasl_backend backend = spec ? spec->backend : YASL_BACKEND_AUTO; + if (backend < YASL_BACKEND_AUTO || backend > YASL_BACKEND_COCOA) { + errno = EINVAL; + return NULL; + } + if (backend != YASL_BACKEND_AUTO) + return open_backend(backend, loop, spec); +#if YASL_HAS_COCOA + return open_backend(YASL_BACKEND_COCOA, loop, spec); +#else + const char *session = getenv("XDG_SESSION_TYPE"); + bool wayland = getenv("WAYLAND_DISPLAY") || getenv("WAYLAND_SOCKET") || + (session && strcmp(session, "wayland") == 0); + enum yasl_backend first = wayland ? YASL_BACKEND_WAYLAND : YASL_BACKEND_X11; + enum yasl_backend second = wayland ? YASL_BACKEND_X11 : YASL_BACKEND_WAYLAND; + struct yasl_display *d = NULL; + if (backend_ops(first)) d = open_backend(first, loop, spec); + if (!d && backend_ops(second)) d = open_backend(second, loop, spec); + return d; +#endif +} + +enum yasl_backend yasl_display_backend(const struct yasl_display *d) +{ + return d ? d->ops->type : YASL_BACKEND_AUTO; +} + +void yasl_display_close(struct yasl_display *d) +{ + if (!d || !d->ops->display_close) + return; + d->ops->display_close(d); +} + +uint32_t yasl_display_caps(const struct yasl_display *d) +{ + if (!d || !d->ops->display_caps) + return 0; + return d->ops->display_caps(d); +} + +void yasl_display_dispatch(struct yasl_display *d) +{ + if (!d || !d->ops->display_dispatch) + return; + d->ops->display_dispatch(d); +} + +int yasl_display_dispatch_timeout(struct yasl_display *d, int timeout_ms) +{ + if (!d) return -1; + if (d->ops->display_dispatch_timeout) + return d->ops->display_dispatch_timeout(d, timeout_ms); + if (d->ops->display_dispatch) { + d->ops->display_dispatch(d); + return 0; + } + return -1; +} + +void yasl_display_flush(struct yasl_display *d) +{ + if (!d || !d->ops->display_flush) + return; + d->ops->display_flush(d); +} + +int yasl_display_modifiers(const struct yasl_display *d) +{ + if (!d || !d->ops->display_modifiers) + return 0; + return d->ops->display_modifiers(d); +} + +void yasl_display_copy(struct yasl_display *d, enum yasl_selection sel, const char *text) +{ + if (!d || !d->ops->display_copy) + return; + d->ops->display_copy(d, sel, text); +} + +void yasl_display_paste(struct yasl_display *d, enum yasl_selection sel, struct yasl_surface *target) +{ + if (!d || !d->ops->display_paste) + return; + if (!target || target->display != d) + return; + d->ops->display_paste(d, sel, target); +} + +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) +{ + if (!d || !d->ops->display_drag_start) + return 0; + if (!origin || origin->display != d) + return false; + return d->ops->display_drag_start(d, origin, image, l, ud); +} + +void yasl_display_drag_cancel(struct yasl_display *d) +{ + if (!d || !d->ops->display_drag_cancel) + return; + d->ops->display_drag_cancel(d); +} + +struct yasl_surface *yasl_surface_create_toplevel(struct yasl_display *d, const struct yasl_surface_spec *spec) +{ + if (!d || !d->ops->surface_create_toplevel) + return 0; + return d->ops->surface_create_toplevel(d, spec); +} + +struct yasl_surface *yasl_surface_create_popup(struct yasl_surface *parent, const struct yasl_popup_spec *spec) +{ + if (!parent || !parent->display->ops->surface_create_popup) + return 0; + return parent->display->ops->surface_create_popup(parent, spec); +} + +bool yasl_surface_popup_reposition(struct yasl_surface *popup, const struct yasl_popup_spec *spec) +{ + if (!popup || !popup->display->ops->surface_popup_reposition) + return 0; + return popup->display->ops->surface_popup_reposition(popup, spec); +} + +void yasl_surface_destroy(struct yasl_surface *s) +{ + if (!s || !s->display->ops->surface_destroy) + return; + s->display->ops->surface_destroy(s); +} + +struct yasl_display *yasl_surface_display(const struct yasl_surface *s) +{ + if (!s || !s->display->ops->surface_display) + return 0; + return s->display->ops->surface_display(s); +} + +void yasl_surface_set_callbacks(struct yasl_surface *s, const struct yasl_surface_cbs *cbs, void *ud) +{ + if (!s || !s->display->ops->surface_set_callbacks) + return; + s->display->ops->surface_set_callbacks(s, cbs, ud); +} + +void yasl_surface_set_title(struct yasl_surface *s, const char *title) +{ + if (!s || !s->display->ops->surface_set_title) + return; + s->display->ops->surface_set_title(s, title); +} + +void yasl_surface_schedule_redraw(struct yasl_surface *s) +{ + if (!s || !s->display->ops->surface_schedule_redraw) + return; + s->display->ops->surface_schedule_redraw(s); +} + +bool yasl_surface_present(struct yasl_surface *s, const struct yasl_framebuffer *fb, const struct yasl_damage_list *damage) +{ + if (!s || !s->display->ops->surface_present) + return 0; + return s->display->ops->surface_present(s, fb, damage); +} + +bool yasl_surface_input_poll(struct yasl_surface *s, struct yasl_input_event *ev) +{ + if (!s || !s->display->ops->surface_input_poll) + return 0; + return s->display->ops->surface_input_poll(s, ev); +} + +struct yasl_vector2i yasl_surface_size(const struct yasl_surface *s) +{ + if (!s || !s->display->ops->surface_size) + return (struct yasl_vector2i){0}; + return s->display->ops->surface_size(s); +} + +uint32_t yasl_surface_scale_120(const struct yasl_surface *s) +{ + if (!s || !s->display->ops->surface_scale_120) + return YASL_SCALE_UNIT; + return s->display->ops->surface_scale_120(s); +} + +uint32_t yasl_surface_state(const struct yasl_surface *s) +{ + if (!s || !s->display->ops->surface_state) + return 0; + return s->display->ops->surface_state(s); +} + +struct yasl_timing yasl_surface_timing(const struct yasl_surface *s) +{ + if (!s || !s->display->ops->surface_timing) + return (struct yasl_timing){0}; + return s->display->ops->surface_timing(s); +} + +uint64_t yasl_surface_frame_time_ns(struct yasl_surface *s, uint64_t now) +{ + if (!s || !s->display->ops->surface_frame_time_ns) + return 0; + return s->display->ops->surface_frame_time_ns(s, now); +} + +void yasl_surface_set_cursor(struct yasl_surface *s, enum yasl_cursor cursor) +{ + if (!s || !s->display->ops->surface_set_cursor) + return; + s->display->ops->surface_set_cursor(s, cursor); +} + +void yasl_surface_set_background_color(struct yasl_surface *s, uint32_t bg) +{ + if (!s || !s->display->ops->surface_set_background_color) + return; + s->display->ops->surface_set_background_color(s, bg); +} + +const char *yasl_surface_ime_preedit(const struct yasl_surface *s) +{ + if (!s || !s->display->ops->surface_ime_preedit) + return 0; + return s->display->ops->surface_ime_preedit(s); +} + +bool yasl_surface_ime_preedit_cursor(const struct yasl_surface *s, int *begin, int *end) +{ + if (!s || !s->display->ops->surface_ime_preedit_cursor) + return 0; + return s->display->ops->surface_ime_preedit_cursor(s, begin, end); +} + +void yasl_surface_set_ime_caret(struct yasl_surface *s, struct yasl_rect2i caret) +{ + if (!s || !s->display->ops->surface_set_ime_caret) + return; + s->display->ops->surface_set_ime_caret(s, caret); +} + +bool yasl_surface_start_interactive_move(struct yasl_surface *s) +{ + if (!s || !s->display->ops->surface_start_interactive_move) + return 0; + return s->display->ops->surface_start_interactive_move(s); +} + +bool yasl_surface_start_interactive_resize(struct yasl_surface *s, enum yasl_resize_edge edge) +{ + if (!s || !s->display->ops->surface_start_interactive_resize) + return 0; + return s->display->ops->surface_start_interactive_resize(s, edge); +} + +bool yasl_surface_show_window_menu(struct yasl_surface *s, struct yasl_vector2i pos) +{ + if (!s || !s->display->ops->surface_show_window_menu) + return 0; + return s->display->ops->surface_show_window_menu(s, pos); +} + +bool yasl_surface_drag_carry(struct yasl_surface *s, struct yasl_vector2i offset) +{ + if (!s || !s->display->ops->surface_drag_carry) + return 0; + return s->display->ops->surface_drag_carry(s, offset); +} + +bool yasl_surface_place_under_pointer(struct yasl_surface *s, struct yasl_vector2i at) +{ + if (!s || !s->display->ops->surface_place_under_pointer) + return 0; + return s->display->ops->surface_place_under_pointer(s, at); +} + +void *yasl_display_get_native_handle(struct yasl_display *d) +{ + if (!d || !d->ops->display_get_native_handle) + return 0; + return d->ops->display_get_native_handle(d); +} + +void *yasl_surface_get_native_handle(struct yasl_surface *s) +{ + if (!s || !s->display->ops->surface_get_native_handle) + return 0; + return s->display->ops->surface_get_native_handle(s); +} |
