#include "backend.h" #include #include #include 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); }