diff options
| author | Berke Güzel <wenekar1@gmail.com> | 2026-10-13 13:44:13 +0300 |
|---|---|---|
| committer | Berke Güzel <wenekar1@gmail.com> | 2026-10-13 13:44:13 +0300 |
| commit | c059e3aa7f93da470f052a5cd8ee0d8dc969e679 (patch) | |
| tree | 63ffa378287ed2c606eda2e940501b9edc3d2b8b /src/wayland/surface.c | |
| parent | 87d0bc50d53dc216efb2b04495f090616318bc5c (diff) | |
rename and simplification
Diffstat (limited to 'src/wayland/surface.c')
| -rw-r--r-- | src/wayland/surface.c | 507 |
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, ®istry_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; -} |
