Compositor: xdg_positioner, xdg_popup and wl_output requests no longer abort

Positioners and outputs were created without an implementation, and get_popup
created nothing. libwayland aborts on the first request to a resource with no
implementation - the compositor and the app with it. On device: a gamescope
started from the pixman desktop (droiddeck-gpu) beside labwc took the app down
(tombstone: abort in libwayland-server under wl_event_loop_dispatch). Positioner
requests are accepted and ignored, popups are dismissed at once (popup_done),
wl_output.release destroys the resource.
This commit is contained in:
The412Banner committed 2026-09-23 22:59:44 -04:00
1 parent 6192d5be2c
commit 351882f0ea
1 file changed
+55 -3
+55 -3
View File
@@ -1332,8 +1332,23 @@ static void xdg_surface_get_toplevel(struct wl_client *c, struct wl_resource *r,
s->xdg_toplevel = tl;
send_toplevel_configure(s);
}
/* A popup is dismissed as soon as it is made (see the positioner below). */
static void popup_destroy(struct wl_client *c, struct wl_resource *r) { wl_resource_destroy(r); }
static void popup_grab(struct wl_client *c, struct wl_resource *r, struct wl_resource *seat, uint32_t serial) {}
static void popup_reposition(struct wl_client *c, struct wl_resource *r, struct wl_resource *positioner,
uint32_t token) {}
static const struct xdg_popup_interface popup_impl = {
.destroy = popup_destroy,
.grab = popup_grab,
.reposition = popup_reposition,
};
static void xdg_surface_get_popup(struct wl_client *c, struct wl_resource *r, uint32_t id,
struct wl_resource *parent, struct wl_resource *positioner) {}
struct wl_resource *parent, struct wl_resource *positioner) {
struct wl_resource *p = wl_resource_create(c, &xdg_popup_interface, wl_resource_get_version(r), id);
if (!p) { wl_client_post_no_memory(c); return; }
wl_resource_set_implementation(p, &popup_impl, NULL, NULL);
xdg_popup_send_popup_done(p);
}
static void xdg_surface_set_geometry(struct wl_client *c, struct wl_resource *r,
int32_t x, int32_t y, int32_t w, int32_t h) {}
static void xdg_surface_ack_configure(struct wl_client *c, struct wl_resource *r, uint32_t serial) {}
@@ -1350,9 +1365,40 @@ static void xdg_surface_resource_destroy(struct wl_resource *r) {
}
static void xdg_wm_base_destroy(struct wl_client *c, struct wl_resource *r) { wl_resource_destroy(r); }
/* Popups are not drawn here, but their requests must still land somewhere: a resource without an
* implementation makes libwayland abort on the first request to it - the whole compositor, and the
* app with it. A positioner takes every request and keeps nothing; a popup is dismissed at once
* (popup_done), which is what a client does with a popup it cannot show. Seen with a gamescope
* started from the Linux desktop beside labwc. */
static void positioner_destroy(struct wl_client *c, struct wl_resource *r) { wl_resource_destroy(r); }
static void positioner_set_size(struct wl_client *c, struct wl_resource *r, int32_t w, int32_t h) {}
static void positioner_set_anchor_rect(struct wl_client *c, struct wl_resource *r, int32_t x, int32_t y,
int32_t w, int32_t h) {}
static void positioner_set_anchor(struct wl_client *c, struct wl_resource *r, uint32_t a) {}
static void positioner_set_gravity(struct wl_client *c, struct wl_resource *r, uint32_t g) {}
static void positioner_set_constraint_adjustment(struct wl_client *c, struct wl_resource *r, uint32_t a) {}
static void positioner_set_offset(struct wl_client *c, struct wl_resource *r, int32_t x, int32_t y) {}
static void positioner_set_reactive(struct wl_client *c, struct wl_resource *r) {}
static void positioner_set_parent_size(struct wl_client *c, struct wl_resource *r, int32_t w, int32_t h) {}
static void positioner_set_parent_configure(struct wl_client *c, struct wl_resource *r, uint32_t serial) {}
static const struct xdg_positioner_interface positioner_impl = {
.destroy = positioner_destroy,
.set_size = positioner_set_size,
.set_anchor_rect = positioner_set_anchor_rect,
.set_anchor = positioner_set_anchor,
.set_gravity = positioner_set_gravity,
.set_constraint_adjustment = positioner_set_constraint_adjustment,
.set_offset = positioner_set_offset,
.set_reactive = positioner_set_reactive,
.set_parent_size = positioner_set_parent_size,
.set_parent_configure = positioner_set_parent_configure,
};
static void xdg_wm_base_create_positioner(struct wl_client *c, struct wl_resource *r, uint32_t id) {
struct wl_resource *p = wl_resource_create(c, &xdg_positioner_interface, wl_resource_get_version(r), id);
if (p) wl_resource_set_implementation(p, NULL, NULL, NULL);
if (!p) { wl_client_post_no_memory(c); return; }
wl_resource_set_implementation(p, &positioner_impl, NULL, NULL);
}
static void xdg_wm_base_get_xdg_surface(struct wl_client *c, struct wl_resource *r, uint32_t id,
struct wl_resource *surf) {
@@ -1738,9 +1784,15 @@ static void bind_dmabuf(struct wl_client *c, void *data, uint32_t ver, uint32_t
/* ------------------------------------------------------------------ wl_output */
/* wl_output v3+ has a request (release); without an implementation the first client to send it
* aborted the compositor. */
static void output_release(struct wl_client *c, struct wl_resource *r) { wl_resource_destroy(r); }
static const struct wl_output_interface output_impl = { .release = output_release };
static void bind_output(struct wl_client *c, void *data, uint32_t ver, uint32_t id) {
struct wl_resource *r = wl_resource_create(c, &wl_output_interface, ver, id);
wl_resource_set_implementation(r, NULL, NULL, NULL);
if (!r) { wl_client_post_no_memory(c); return; }
wl_resource_set_implementation(r, &output_impl, NULL, NULL);
wl_output_send_geometry(r, 0, 0, 340, 190, WL_OUTPUT_SUBPIXEL_UNKNOWN,
"Bannerlator", "Wayland", WL_OUTPUT_TRANSFORM_NORMAL);
wl_output_send_mode(r, WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED,