summaryrefslogtreecommitdiff
path: root/src/common/backend.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/backend.c')
-rw-r--r--src/common/backend.c321
1 files changed, 321 insertions, 0 deletions
diff --git a/src/common/backend.c b/src/common/backend.c
new file mode 100644
index 0000000..a6fa6f2
--- /dev/null
+++ b/src/common/backend.c
@@ -0,0 +1,321 @@
+#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);
+}
+
+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);
+}