summaryrefslogtreecommitdiff
path: root/src/wayland/surface.c
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-13 13:44:13 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-13 13:44:13 +0300
commitc059e3aa7f93da470f052a5cd8ee0d8dc969e679 (patch)
tree63ffa378287ed2c606eda2e940501b9edc3d2b8b /src/wayland/surface.c
parent87d0bc50d53dc216efb2b04495f090616318bc5c (diff)
rename and simplification
Diffstat (limited to 'src/wayland/surface.c')
-rw-r--r--src/wayland/surface.c507
1 files changed, 0 insertions, 507 deletions
diff --git a/src/wayland/surface.c b/src/wayland/surface.c
deleted file mode 100644
index ca9db72..0000000
--- a/src/wayland/surface.c
+++ /dev/null
@@ -1,507 +0,0 @@
-#include "internal.h"
-#include <assert.h>
-
-static void display_free(struct wayland_display *c);
-
-static void display_cancel_read(struct wayland_display *c)
-{
- if (!c->reading)
- return;
- wl_display_cancel_read(c->wl);
- c->reading = false;
-}
-
-static void report_display_error(struct wayland_display *c)
-{
- int err = wl_display_get_error(c->wl);
- if (!err)
- return;
- uint32_t object_id = 0;
- const struct wl_interface *iface = NULL;
- uint32_t protocol_err = wl_display_get_protocol_error(c->wl, &iface, &object_id);
- if (protocol_err)
- fprintf(stderr, "[yasl] protocol error %u on %s (object %u)\n",
- protocol_err, iface ? iface->name : "?", object_id);
- else
- fprintf(stderr, "[yasl] display error %d\n", err);
-}
-
-void display_enter(struct wayland_display *c)
-{
- c->depth++;
-}
-
-void display_leave(struct wayland_display *c)
-{
- if (--c->depth > 0)
- return;
- keyboard_settle_focus(c);
- while (c->dead) {
- struct wayland_surface *w = c->dead;
- c->dead = w->dead_next;
- free(w);
- }
-}
-
-static void display_lose(struct wayland_display *c)
-{
- if (c->lost)
- return;
- c->lost = true;
- report_display_error(c);
- display_cancel_read(c);
- display_enter(c);
- for (struct wayland_surface *w = c->surfaces, *next; w; w = next) {
- next = w->conn_next;
- surface_fail(w);
- }
- display_leave(c);
- if (c->cbs && c->cbs->lost)
- c->cbs->lost(c->ud);
-}
-
-void surface_fail(struct wayland_surface *w)
-{
- if (w->closed)
- return;
- w->closed = true;
- if (w->cbs->close)
- w->cbs->close(&w->base, w->ud);
-}
-
-static int display_ready(int fd, short revents, void *ud)
-{
- (void)fd;
- struct wayland_display *c = ud;
- if (c->lost)
- return 0;
- display_enter(c);
- if (c->reading) {
- c->reading = false;
- if (!(revents & POLLIN))
- wl_display_cancel_read(c->wl);
- else if (wl_display_read_events(c->wl) < 0)
- revents |= POLLERR;
- }
- if (revents & POLLOUT) {
- if (wl_display_flush(c->wl) >= 0) {
- if (c->loop && c->watch > 0)
- yasl_loop_set_fd_events(c->loop, c->watch, POLLIN);
- } else if (errno != EAGAIN) {
- display_lose(c);
- }
- }
- if (wl_display_dispatch_pending(c->wl) < 0 ||
- (revents & (POLLERR | POLLHUP | POLLNVAL)))
- display_lose(c);
- display_leave(c);
- return 0;
-}
-
-static bool display_arm(struct wayland_display *c)
-{
- bool had_pending = false;
- while (!c->reading && wl_display_prepare_read(c->wl) != 0) {
- had_pending = true;
- if (wl_display_dispatch_pending(c->wl) < 0) {
- display_lose(c);
- return false;
- }
- }
- c->reading = true;
- short events = POLLIN;
- if (wl_display_flush(c->wl) < 0) {
- if (errno != EAGAIN) {
- display_cancel_read(c);
- display_lose(c);
- return false;
- }
- events |= POLLOUT;
- }
- if (c->loop && c->watch > 0)
- yasl_loop_set_fd_events(c->loop, c->watch, events);
- return had_pending;
-}
-
-static inline bool display_has_immediate_work(const struct wayland_display *c)
-{
- if (unlikely(!c || c->lost)) return false;
- for (struct wayland_surface *w = c->surfaces; w; w = w->conn_next) {
- bool ready_draw = w->want_draw & (w->frame_cb == NULL) & w->configured;
- bool has_input = (w->input.count > 0 || w->input.reset_pending);
- if (unlikely((ready_draw | has_input) & !w->closed))
- return true;
- }
- return false;
-}
-
-int wayland_display_dispatch_timeout(struct wayland_display *c, int timeout_ms)
-{
- if (!c || c->lost)
- return -1;
-
- display_enter(c);
-
- if (wl_display_dispatch_pending(c->wl) < 0) {
- display_lose(c);
- display_leave(c);
- return -1;
- }
-
- display_arm(c);
- if (c->lost) {
- display_leave(c);
- return -1;
- }
-
- if (timeout_ms != 0 && display_has_immediate_work(c)) {
- timeout_ms = 0;
- }
-
- int n = 0;
- if (c->loop) {
- n = yasl_loop_step(c->loop, timeout_ms);
- }
-
- if (c->reading) {
- display_cancel_read(c);
- }
-
- if (wl_display_dispatch_pending(c->wl) < 0) {
- display_lose(c);
- display_leave(c);
- return -1;
- }
-
- display_leave(c);
- return n;
-}
-
-void wayland_display_flush(struct wayland_display *c)
-{
- if (!c || c->lost)
- return;
- display_enter(c);
- for (struct wayland_surface *w = c->surfaces, *next; w; w = next) {
- next = w->conn_next;
- surface_draw_frame(w);
- }
- if (!c->lost && c->wl) {
- if (wl_display_flush(c->wl) < 0 && errno != EAGAIN)
- display_lose(c);
- }
- display_leave(c);
-}
-
-static void display_free(struct wayland_display *c)
-{
- conn_drag_end(c);
- if (c->loop && c->watch > 0) yasl_loop_del_fd(c->loop, c->watch);
- if (c->wl) display_cancel_read(c);
- while (c->seats)
- seat_destroy(c->seats);
- if (c->toplevel_drag_mgr) xdg_toplevel_drag_manager_v1_destroy(c->toplevel_drag_mgr);
- if (c->primary_selection_mgr) zwp_primary_selection_device_manager_v1_destroy(c->primary_selection_mgr);
- if (c->data_manager) wl_data_device_manager_destroy(c->data_manager);
- if (c->cursor_shape_mgr) wp_cursor_shape_manager_v1_destroy(c->cursor_shape_mgr);
- if (c->cursor_theme) wl_cursor_theme_destroy(c->cursor_theme);
- if (c->tablet_mgr) zwp_tablet_manager_v2_destroy(c->tablet_mgr);
- if (c->text_input_mgr) zwp_text_input_manager_v3_destroy(c->text_input_mgr);
- if (c->tearing_mgr) wp_tearing_control_manager_v1_destroy(c->tearing_mgr);
- if (c->fifo_mgr) wp_fifo_manager_v1_destroy(c->fifo_mgr);
- if (c->commit_timing_mgr) wp_commit_timing_manager_v1_destroy(c->commit_timing_mgr);
- if (c->presentation) wp_presentation_destroy(c->presentation);
- if (c->xkb_ctx) xkb_context_unref(c->xkb_ctx);
- if (c->scale_mgr) wp_fractional_scale_manager_v1_destroy(c->scale_mgr);
- if (c->viewporter) wp_viewporter_destroy(c->viewporter);
- if (c->decor_mgr) zxdg_decoration_manager_v1_destroy(c->decor_mgr);
- conn_destroy_outputs(c);
- if (c->wm_base) xdg_wm_base_destroy(c->wm_base);
- if (c->shm) wl_shm_destroy(c->shm);
- if (c->compositor) wl_compositor_destroy(c->compositor);
- if (c->registry) wl_registry_destroy(c->registry);
- if (c->wl) wl_display_disconnect(c->wl);
- if (c->owns_loop && c->loop) {
- yasl_loop_destroy(c->loop);
- c->loop = NULL;
- c->base.loop = NULL;
- }
- free(c->app_id);
- free(c);
-}
-
-struct wayland_display *wayland_display_open(struct yasl_loop *loop, const struct yasl_display_spec *spec)
-{
- struct wayland_display *c = calloc(1, sizeof(*c));
- if (!c) return NULL;
- c->base.ops = &yasl_wayland_backend;
- if (!loop) {
- c->loop = yasl_loop_create();
- c->owns_loop = true;
- } else {
- c->loop = loop;
- }
- c->base.loop = c->loop;
- if (!c->loop) goto err;
- if (spec) {
- c->base.callbacks = spec->cbs ? *spec->cbs : (struct yasl_display_cbs){0};
- c->cbs = &c->base.callbacks;
- c->ud = spec->ud;
- if (spec->app_id) c->app_id = strdup(spec->app_id);
- }
- c->xkb_ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
- c->wl = c->xkb_ctx ? wl_display_connect(NULL) : NULL;
- if (!c->wl) goto err;
- c->base.native_handle = c->wl;
-
- c->registry = wl_display_get_registry(c->wl);
- if (!c->registry) goto err;
- wl_registry_add_listener(c->registry, &registry_listener, c);
- if (wl_display_roundtrip(c->wl) < 0 || !c->compositor || !c->shm || !c->wm_base)
- goto err;
-
- surface_init_cursor(c);
- if (c->loop) {
- c->watch = yasl_loop_add_fd(c->loop, wl_display_get_fd(c->wl), POLLIN, display_ready, c);
- if (c->watch <= 0) { c->watch = 0; goto err; }
- }
- if (display_input_init(c) < 0)
- goto err;
- return c;
-
-err:
- display_free(c);
- return NULL;
-}
-
-void wayland_display_close(struct wayland_display *c)
-{
- if (!c) return;
- assert(!c->surfaces && "destroy every surface before its display");
- display_free(c);
-}
-
-uint32_t wayland_display_caps(const struct wayland_display *c)
-{
- if (!c) return 0;
- uint32_t caps = YASL_CAP_POPUPS | YASL_CAP_CSD | YASL_CAP_FRAME_PACING;
- if (c->tablet_mgr) caps |= YASL_CAP_TABLET;
- struct seat *s = conn_active_seat(c);
- const struct wl_data_device *device = s ? clipboard_data_device(s->clipboard) : NULL;
- if (device && wl_data_device_get_version((struct wl_data_device *)device) >= 3)
- caps |= YASL_CAP_DRAG;
- if (c->toplevel_drag_mgr)
- caps |= YASL_CAP_DRAG_CARRY;
- if (c->primary_selection_mgr)
- caps |= YASL_CAP_PRIMARY_SELECTION;
- return caps;
-}
-
-static void conn_link(struct wayland_display *c, struct wayland_surface *w)
-{
- w->base.display = &c->base;
- w->conn = c;
- w->conn_next = c->surfaces;
- c->surfaces = w;
-}
-
-static void conn_unlink(struct wayland_surface *w)
-{
- struct wayland_display *c = w->conn;
- if (!c) return;
- for (struct wayland_surface **p = &c->surfaces; *p; p = &(*p)->conn_next) {
- if (*p == w) {
- *p = w->conn_next;
- break;
- }
- }
- for (struct seat *s = c->seats; s; s = s->next)
- seat_forget_surface(s, w);
- w->conn = NULL;
-}
-
-
-static bool spec_valid(const struct yasl_surface_spec *spec)
-{
- size_t bytes;
- return spec && spec->size.x > 0 && spec->size.y > 0 &&
- buffer_size(spec->size.x, spec->size.y, &bytes);
-}
-
-struct wayland_surface *wayland_surface_create_toplevel(struct wayland_display *c,
- const struct yasl_surface_spec *spec, void *graphics_device)
-{
- (void)graphics_device;
- if (!c || c->lost || !spec_valid(spec))
- return NULL;
- int width = spec->size.x, height = spec->size.y;
- display_cancel_read(c);
- struct wayland_surface *w = calloc(1, sizeof(*w));
- if (!w) return NULL;
- display_enter(c);
- conn_link(c, w);
- wayland_surface_set_callbacks(w, NULL, NULL);
- w->cursor = YASL_CURSOR_TEXT;
- w->req_width = width;
- w->req_height = height;
- w->logical_width = width;
- w->logical_height = height;
- w->scale_120 = YASL_SCALE_UNIT;
- w->pending_scale_120 = YASL_SCALE_UNIT;
- w->scale_factor = 1.0;
- w->size_pending = true;
- w->clock.refresh_ns = c->outputs && c->outputs->refresh_ns
- ? c->outputs->refresh_ns : YASL_REFRESH_DEFAULT_NS;
-
- w->surface = wl_compositor_create_surface(c->compositor);
- if (!w->surface) goto err;
- w->base.native_handle = w->surface;
- w->base.size = (struct yasl_vector2i){width, height};
- w->base.scale_120 = YASL_SCALE_UNIT;
- wl_surface_set_user_data(w->surface, w);
- if (surface_init_scaling(w) < 0) goto err;
- if (surface_init_shell(w, spec->title) < 0) goto err;
- w->opaque = spec->fullscreen;
- if (spec->fullscreen)
- xdg_toplevel_set_fullscreen(w->toplevel, NULL);
- if (spec->tearing && c->tearing_mgr) {
- w->tearing_control = wp_tearing_control_manager_v1_get_tearing_control(
- c->tearing_mgr, w->surface);
- if (w->tearing_control)
- wp_tearing_control_v1_set_presentation_hint(w->tearing_control,
- WP_TEARING_CONTROL_V1_PRESENTATION_HINT_ASYNC);
- }
-
- wl_surface_commit(w->surface);
- if (wl_display_roundtrip(c->wl) < 0) {
- display_lose(c);
- goto err;
- }
- if (apply_pending_geometry(w) < 0) goto err;
- if (w->closed) goto err;
- display_leave(c);
- return w;
-
-err:
- wayland_surface_destroy(w);
- display_leave(c);
- return NULL;
-}
-
-void wayland_surface_set_callbacks(struct wayland_surface *w, const struct yasl_surface_cbs *cbs, void *ud)
-{
- if (w && !w->closed) {
- w->base.callbacks = cbs ? *cbs : (struct yasl_surface_cbs){0};
- w->cbs = &w->base.callbacks;
- w->ud = ud;
- }
-}
-
-void wayland_surface_destroy(struct wayland_surface *w)
-{
- if (!w || w->destroyed) return;
- for (struct wayland_surface *o = w->conn ? w->conn->surfaces : NULL; o; o = o->conn_next)
- assert(o->parent != w && "destroy a popup before its parent");
- input_queue_clear(&w->input);
- free(w->ime_preedit);
- free(w->ime_commit);
- free(w->ime_shown);
- if (w->tearing_control) wp_tearing_control_v1_destroy(w->tearing_control);
- if (w->fifo) wp_fifo_v1_destroy(w->fifo);
- if (w->commit_timer) wp_commit_timer_v1_destroy(w->commit_timer);
- surface_feedback_destroy(w);
- if (w->frame_cb) wl_callback_destroy(w->frame_cb);
- for (int i = 0; i < NBUF; i++) buffer_destroy(&w->buffers[i]);
- if (w->frac_scale) wp_fractional_scale_v1_destroy(w->frac_scale);
- if (w->viewport) wp_viewport_destroy(w->viewport);
- if (w->toplevel_decor) zxdg_toplevel_decoration_v1_destroy(w->toplevel_decor);
- if (w->toplevel) xdg_toplevel_destroy(w->toplevel);
- if (w->popup) xdg_popup_destroy(w->popup);
- if (w->xdg_surface) xdg_surface_destroy(w->xdg_surface);
- if (w->surface) {
- wl_surface_set_user_data(w->surface, NULL);
- wl_surface_destroy(w->surface);
- }
- struct wayland_display *c = w->conn;
- conn_unlink(w);
- static const struct yasl_surface_cbs no_callbacks = {0};
- *w = (struct wayland_surface){
- .base = w->base,
- .conn_next = w->conn_next,
- .cbs = &no_callbacks,
- .closed = true,
- .destroyed = true,
- };
- if (c && c->depth > 0) {
- w->dead_next = c->dead;
- c->dead = w;
- } else {
- free(w);
- }
-}
-
-struct wayland_display *wayland_surface_display(const struct wayland_surface *w)
-{
- return w ? w->conn : NULL;
-}
-
-void wayland_surface_schedule_redraw(struct wayland_surface *w)
-{
- if (!w || w->closed) return;
- w->want_draw = true;
- if (w->conn && w->conn->loop)
- yasl_loop_kick(w->conn->loop);
-}
-
-struct yasl_geometry wayland_surface_geometry(const struct wayland_surface *w)
-{
- return (struct yasl_geometry){
- .size = w ? (struct yasl_vector2i){w->width, w->height} : (struct yasl_vector2i){0},
- .scale_120 = w ? w->scale_120 : YASL_SCALE_UNIT,
- };
-}
-
-void wayland_surface_set_background_color(struct wayland_surface *w, uint32_t bg)
-{
- (void)w; (void)bg;
-}
-
-bool wayland_surface_start_interactive_move(struct wayland_surface *s)
-{
- if (!s || !s->toplevel || !s->conn) return false;
- struct seat *seat = conn_active_seat(s->conn);
- if (!seat || !seat->proxy || !seat->press_serial) return false;
- xdg_toplevel_move(s->toplevel, seat->proxy, seat->press_serial);
- return true;
-}
-
-bool wayland_surface_start_interactive_resize(struct wayland_surface *s, enum yasl_resize_edge edge)
-{
- if (!s || !s->toplevel || !s->conn || edge == YASL_EDGE_NONE) return false;
- struct seat *seat = conn_active_seat(s->conn);
- if (!seat || !seat->proxy || !seat->press_serial) return false;
- xdg_toplevel_resize(s->toplevel, seat->proxy, seat->press_serial, (uint32_t)edge);
- return true;
-}
-
-bool wayland_surface_show_window_menu(struct wayland_surface *s, struct yasl_vector2i pos)
-{
- if (!s || !s->toplevel || !s->conn) return false;
- struct seat *seat = conn_active_seat(s->conn);
- if (!seat || !seat->proxy || !seat->press_serial) return false;
- uint32_t scale = s->scale_120 ? s->scale_120 : YASL_SCALE_UNIT;
- xdg_toplevel_show_window_menu(s->toplevel, seat->proxy, seat->press_serial,
- yasl_scale_to_logical(pos.x, scale),
- yasl_scale_to_logical(pos.y, scale));
- return true;
-}
-
-void *wayland_display_get_native_handle(struct wayland_display *d)
-{
- return d ? d->wl : NULL;
-}
-
-void *wayland_surface_get_native_handle(struct wayland_surface *s)
-{
- return s ? s->surface : NULL;
-}