summaryrefslogtreecommitdiff
path: root/src/platform/wayland/surface.c
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-13 23:41:31 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-13 23:41:31 +0300
commit76073fe5fad8799e5850805f2f090af2cb62c741 (patch)
tree9658019babe4760a3634bdab4da0731a10e42e68 /src/platform/wayland/surface.c
parentdd1775a9927922c14f8679ccbc4d3ca8d5917e20 (diff)
Simplify the public event and CPU API
Applications now need far less ceremony: hello.c is a 20-line loop that handles REFRESH, CLOSE and QUIT and draws into the surface's own pixels. - Fold GEOMETRY, STATE and FOCUS into one WINDOW event carrying size, scale and state; unchanged values send nothing. - Guarantee REFRESH once a window has a size and after every resize, never at size zero. - Merge DROP_HOVER into DROP with over/leave/data actions and give drag and drop actions enums. - Keep event strings valid until the next wait and drop yasl_event_release; empty or failed waits report NONE. - Replace copy-in presentation with a lent pixel buffer: yasl_cpu_pixels and yasl_cpu_present. - Remove yasl_poll_event, yasl_cpu_read_pixels, unused event fields and comments that restated names. - Wayland: resize floating windows in request_size instead of reporting it unsupported, and stop marking new GPU surfaces as Vulkan so yasl_vulkan_create_surface no longer fails with NATIVE_WINDOW_IN_USE. Also includes the in-progress public API refactor that was uncommitted in the tree (removal of the app/loop layer, new surface, GL and Vulkan entry points). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'src/platform/wayland/surface.c')
-rw-r--r--src/platform/wayland/surface.c119
1 files changed, 77 insertions, 42 deletions
diff --git a/src/platform/wayland/surface.c b/src/platform/wayland/surface.c
index 2e85e2b..31096f4 100644
--- a/src/platform/wayland/surface.c
+++ b/src/platform/wayland/surface.c
@@ -52,7 +52,7 @@ static void display_lose(struct wayland_display *c)
surface_fail(w);
}
display_leave(c);
- yasl_display_notify_event(&c->base, YASL_EVENT_DISPLAY_LOST);
+ yasl_private_display_notify_event(&c->base, YASL_PRIVATE_EVENT_DISPLAY_LOST);
}
void surface_fail(struct wayland_surface *w)
@@ -60,7 +60,7 @@ void surface_fail(struct wayland_surface *w)
if (w->closed)
return;
w->closed = true;
- yasl_surface_notify_close(&w->base);
+ yasl_private_surface_notify_close(&w->base);
}
static int display_ready(int fd, short revents, void *ud)
@@ -80,7 +80,7 @@ static int display_ready(int fd, short revents, void *ud)
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);
+ yasl_private_loop_set_fd_events(c->loop, c->watch, POLLIN);
} else if (errno != EAGAIN) {
display_lose(c);
}
@@ -113,7 +113,7 @@ static bool display_arm(struct wayland_display *c)
events |= POLLOUT;
}
if (c->loop && c->watch > 0)
- yasl_loop_set_fd_events(c->loop, c->watch, events);
+ yasl_private_loop_set_fd_events(c->loop, c->watch, events);
return had_pending;
}
@@ -154,7 +154,7 @@ int wayland_display_dispatch_timeout(struct wayland_display *c, int timeout_ms)
int n = 0;
if (c->loop) {
- n = yasl_loop_step(c->loop, timeout_ms);
+ n = yasl_private_loop_step(c->loop, timeout_ms);
}
if (c->reading) {
@@ -190,7 +190,7 @@ void wayland_display_flush(struct wayland_display *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->loop && c->watch > 0) yasl_private_loop_del_fd(c->loop, c->watch);
if (c->wl) display_cancel_read(c);
while (c->seats)
seat_destroy(c->seats);
@@ -217,9 +217,12 @@ static void display_free(struct wayland_display *c)
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 YASL_HAS_EGL
+ if (c->egl_initialized) eglTerminate(c->egl_display);
+#endif
if (c->wl) wl_display_disconnect(c->wl);
if (c->owns_loop && c->loop) {
- yasl_loop_destroy(c->loop);
+ yasl_private_loop_destroy(c->loop);
c->loop = NULL;
c->base.loop = NULL;
}
@@ -227,13 +230,13 @@ static void display_free(struct wayland_display *c)
free(c);
}
-struct wayland_display *wayland_display_open(struct yasl_loop *loop, const struct yasl_display_spec *spec)
+struct wayland_display *wayland_display_open(struct yasl_private_loop *loop, const struct yasl_private_display_spec *spec)
{
struct wayland_display *c = calloc(1, sizeof(*c));
if (!c) return NULL;
- c->base.ops = &yasl_wayland_backend;
+ c->base.ops = &yasl_private_wayland_backend;
if (!loop) {
- c->loop = yasl_loop_create();
+ c->loop = yasl_private_loop_create();
c->owns_loop = true;
} else {
c->loop = loop;
@@ -241,7 +244,7 @@ struct wayland_display *wayland_display_open(struct yasl_loop *loop, const struc
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->base.callbacks = spec->cbs ? *spec->cbs : (struct yasl_private_display_cbs){0};
c->cbs = &c->base.callbacks;
c->ud = spec->ud;
if (spec->app_id) c->app_id = strdup(spec->app_id);
@@ -251,6 +254,13 @@ struct wayland_display *wayland_display_open(struct yasl_loop *loop, const struc
c->wl = c->xkb_ctx ? wl_display_connect(NULL) : NULL;
if (!c->wl) goto err;
c->base.native_handle = c->wl;
+#if YASL_HAS_EGL
+ c->egl_display = eglGetDisplay((EGLNativeDisplayType)c->wl);
+ if (c->egl_display != EGL_NO_DISPLAY) {
+ EGLint major = 0, minor = 0;
+ c->egl_initialized = eglInitialize(c->egl_display, &major, &minor) == EGL_TRUE;
+ }
+#endif
c->registry = wl_display_get_registry(c->wl);
if (!c->registry) goto err;
@@ -260,7 +270,7 @@ struct wayland_display *wayland_display_open(struct yasl_loop *loop, const struc
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);
+ c->watch = yasl_private_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)
@@ -282,16 +292,18 @@ void wayland_display_close(struct wayland_display *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;
+ uint32_t caps = YASL_PRIVATE_CAP_POPUPS | YASL_PRIVATE_CAP_CSD |
+ YASL_PRIVATE_CAP_FRAME_PACING | YASL_PRIVATE_CAP_NATIVE_GRAPHICS;
+ if (c->tablet_mgr) caps |= YASL_PRIVATE_CAP_TABLET;
+ if (c->text_input_mgr) caps |= YASL_PRIVATE_CAP_TEXT_INPUT;
struct seat *s = c->active_seat ? c->active_seat : c->seats;
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;
+ caps |= YASL_PRIVATE_CAP_DRAG;
if (c->toplevel_drag_mgr)
- caps |= YASL_CAP_DRAG_CARRY;
+ caps |= YASL_PRIVATE_CAP_DRAG_CARRY;
if (c->primary_selection_mgr)
- caps |= YASL_CAP_PRIMARY_SELECTION;
+ caps |= YASL_PRIVATE_CAP_PRIMARY_SELECTION;
return caps;
}
@@ -321,15 +333,18 @@ static void conn_unlink(struct wayland_surface *w)
}
-static bool spec_valid(const struct yasl_window_spec *spec)
+static bool spec_valid(const struct yasl_private_window_spec *spec)
{
size_t bytes;
- return spec && spec->size.x > 0 && spec->size.y > 0 &&
- buffer_size(spec->size.x, spec->size.y, &bytes);
+ if (!spec || spec->size.x <= 0 || spec->size.y <= 0)
+ return false;
+ return spec->external_gpu && !(spec->flags & YASL_PRIVATE_SURFACE_CPU)
+ ? spec->size.x <= INT32_MAX && spec->size.y <= INT32_MAX
+ : buffer_size(spec->size.x, spec->size.y, &bytes);
}
struct wayland_surface *wayland_surface_create_toplevel(struct wayland_display *c,
- const struct yasl_window_spec *spec, void *graphics_device)
+ const struct yasl_private_window_spec *spec, void *graphics_device)
{
(void)graphics_device;
if (!c || c->lost || !spec_valid(spec))
@@ -340,28 +355,35 @@ struct wayland_surface *wayland_surface_create_toplevel(struct wayland_display *
if (!w) return NULL;
c->depth++;
conn_link(c, w);
- w->base.state = YASL_STATE_CSD;
+ w->base.state = YASL_PRIVATE_STATE_CSD;
+ w->base.creation_flags = spec->flags;
+ w->base.presenter = (spec->external_gpu && !(spec->flags & YASL_PRIVATE_SURFACE_CPU))
+ ? YASL_PRIVATE_PRESENTER_NONE : YASL_PRIVATE_PRESENTER_CPU;
wayland_surface_set_callbacks(w, NULL, NULL);
- w->cursor = YASL_CURSOR_TEXT;
+ w->cursor = YASL_PRIVATE_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_120 = YASL_PRIVATE_SCALE_UNIT;
+ w->pending_scale_120 = YASL_PRIVATE_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;
+ ? c->outputs->refresh_ns : YASL_PRIVATE_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;
+ w->base.size = (struct yasl_private_vector2i){width, height};
+ w->base.scale_120 = YASL_PRIVATE_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;
+ if (spec->flags & YASL_PRIVATE_SURFACE_FIXED_SIZE) {
+ xdg_toplevel_set_min_size(w->toplevel, width, height);
+ xdg_toplevel_set_max_size(w->toplevel, width, height);
+ }
w->opaque = spec->fullscreen;
if (spec->fullscreen)
xdg_toplevel_set_fullscreen(w->toplevel, NULL);
@@ -389,10 +411,10 @@ err:
return NULL;
}
-void wayland_surface_set_callbacks(struct wayland_surface *w, const struct yasl_window_cbs *cbs, void *ud)
+void wayland_surface_set_callbacks(struct wayland_surface *w, const struct yasl_private_window_cbs *cbs, void *ud)
{
if (w && !w->closed) {
- w->base.callbacks = cbs ? *cbs : (struct yasl_window_cbs){0};
+ w->base.callbacks = cbs ? *cbs : (struct yasl_private_window_cbs){0};
w->base.ud = ud;
w->cbs = &w->base.callbacks;
w->ud = ud;
@@ -410,6 +432,15 @@ void wayland_surface_destroy(struct wayland_surface *w)
free(w->ime_commit);
free(w->ime_shown);
if (w->tearing_control) wp_tearing_control_v1_destroy(w->tearing_control);
+#if YASL_HAS_EGL
+ if (w->egl_context) {
+ if (eglGetCurrentContext() == w->egl_context)
+ eglMakeCurrent(w->conn->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroyContext(w->conn->egl_display, w->egl_context);
+ }
+ if (w->egl_surface) eglDestroySurface(w->conn->egl_display, w->egl_surface);
+ if (w->egl_window) wl_egl_window_destroy(w->egl_window);
+#endif
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);
@@ -427,7 +458,7 @@ void wayland_surface_destroy(struct wayland_surface *w)
}
struct wayland_display *c = w->conn;
conn_unlink(w);
- static const struct yasl_window_cbs no_callbacks = {0};
+ static const struct yasl_private_window_cbs no_callbacks = {0};
*w = (struct wayland_surface){
.base = w->base,
.conn_next = w->conn_next,
@@ -446,16 +477,20 @@ void wayland_surface_destroy(struct wayland_surface *w)
void wayland_surface_schedule_redraw(struct wayland_surface *w)
{
if (!w || w->closed) return;
+ if (w->base.presenter != YASL_PRIVATE_PRESENTER_CPU) {
+ yasl_private_surface_notify_refresh(&w->base);
+ return;
+ }
w->want_draw = true;
if (w->conn && w->conn->loop)
- yasl_loop_kick(w->conn->loop);
+ yasl_private_loop_kick(w->conn->loop);
}
-struct yasl_geometry wayland_surface_geometry(const struct wayland_surface *w)
+struct yasl_private_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,
+ return (struct yasl_private_geometry){
+ .size = w ? (struct yasl_private_vector2i){w->width, w->height} : (struct yasl_private_vector2i){0},
+ .scale_120 = w ? w->scale_120 : YASL_PRIVATE_SCALE_UNIT,
};
}
@@ -473,23 +508,23 @@ bool wayland_surface_start_interactive_move(struct wayland_surface *s)
return true;
}
-bool wayland_surface_start_interactive_resize(struct wayland_surface *s, enum yasl_resize_edge edge)
+bool wayland_surface_start_interactive_resize(struct wayland_surface *s, enum yasl_private_resize_edge edge)
{
- if (!s || !s->toplevel || !s->conn || edge == YASL_EDGE_NONE) return false;
+ if (!s || !s->toplevel || !s->conn || edge == YASL_PRIVATE_EDGE_NONE) return false;
struct seat *seat = s->conn->active_seat ? s->conn->active_seat : s->conn->seats;
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)
+bool wayland_surface_show_window_menu(struct wayland_surface *s, struct yasl_private_vector2i pos)
{
if (!s || !s->toplevel || !s->conn) return false;
struct seat *seat = s->conn->active_seat ? s->conn->active_seat : s->conn->seats;
if (!seat || !seat->proxy || !seat->press_serial) return false;
- uint32_t scale = s->scale_120 ? s->scale_120 : YASL_SCALE_UNIT;
+ uint32_t scale = s->scale_120 ? s->scale_120 : YASL_PRIVATE_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));
+ yasl_private_scale_to_logical(pos.x, scale),
+ yasl_private_scale_to_logical(pos.y, scale));
return true;
}