Skip to content

Commit

Permalink
src/wayland: fix multiseat sessions crashing wl-mirror
Browse files Browse the repository at this point in the history
  • Loading branch information
Ferdi265 committed Jun 5, 2024
1 parent 23bff92 commit 502fdc9
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 57 deletions.
10 changes: 8 additions & 2 deletions include/wayland.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,25 @@ typedef struct output_list_node {
enum wl_output_transform transform;
} output_list_node_t;

typedef struct seat_list_node {
struct seat_list_node * next;
struct ctx * ctx;
struct wl_seat * seat;
uint32_t seat_id;
} seat_list_node_t;

typedef struct ctx_wl {
struct wl_display * display;
struct wl_registry * registry;

// registry objects
struct wl_compositor * compositor;
struct wl_seat * seat;
struct wp_viewporter * viewporter;
struct wp_fractional_scale_manager_v1 * fractional_scale_manager;
struct xdg_wm_base * wm_base;
struct zxdg_output_manager_v1 * output_manager;
// registry ids
uint32_t compositor_id;
uint32_t seat_id;
uint32_t viewporter_id;
uint32_t fractional_scale_manager_id;
uint32_t wm_base_id;
Expand All @@ -59,6 +64,7 @@ typedef struct ctx_wl {

// output list
output_list_node_t * outputs;
seat_list_node_t * seats;

// surface objects
struct wl_surface * surface;
Expand Down
162 changes: 107 additions & 55 deletions src/wayland.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,16 +221,6 @@ static void on_registry_add(
registry, id, &wl_compositor_interface, 4
);
ctx->wl.compositor_id = id;
} else if (strcmp(interface, wl_seat_interface.name) == 0) {
if (ctx->wl.seat != NULL) {
log_error("wayland::on_registry_add(): duplicate wl_seat\n");
exit_fail(ctx);
}

// bind wl_seat object
ctx->wl.seat = (struct wl_seat *)wl_registry_bind(
registry, id, &wl_seat_interface, 1
);
} else if (strcmp(interface, wp_viewporter_interface.name) == 0) {
if (ctx->wl.viewporter != NULL) {
log_error("wayland::on_registry_add(): duplicate wp_viewporter\n");
Expand Down Expand Up @@ -365,6 +355,26 @@ static void on_registry_add(
// - for logical_size event
// - for name event
zxdg_output_v1_add_listener(node->xdg_output, &xdg_output_listener, (void *)node);
} else if (strcmp(interface, wl_seat_interface.name) == 0) {
// allocate seat node
seat_list_node_t * node = malloc(sizeof (seat_list_node_t));
if (node == NULL) {
log_error("wayland::on_registry_add(): failed to allocate seat node\n");
exit_fail(ctx);
}

// initialize seat node
node->ctx = ctx;

// prepend seat node to seat list
node->next = ctx->wl.seats;
ctx->wl.seats = node;

// bind wl_seat
node->seat = (struct wl_seat *)wl_registry_bind(
registry, id, &wl_seat_interface, 1
);
node->seat_id = id;
}

(void)version;
Expand All @@ -381,9 +391,6 @@ static void on_registry_remove(
if (id == ctx->wl.compositor_id) {
log_error("wayland::on_registry_remove(): compositor disappeared\n");
exit_fail(ctx);
} else if (id == ctx->wl.seat_id) {
log_error("wayland::on_registry_remove(): seat disappeared\n");
exit_fail(ctx);
} else if (id == ctx->wl.viewporter_id) {
log_error("wayland::on_registry_remove(): viewporter disappeared\n");
exit_fail(ctx);
Expand All @@ -400,33 +407,63 @@ static void on_registry_remove(
log_error("wayland::on_registry_remove(): dmabuf_manager disappeared\n");
exit_fail(ctx);
} else {
output_list_node_t ** link = &ctx->wl.outputs;
output_list_node_t * cur = ctx->wl.outputs;
output_list_node_t * prev = NULL;
while (cur != NULL) {
if (id == cur->output_id) {
log_debug(ctx, "wayland::on_registry_remove(): output %s removed (id = %d)\n", cur->name, id);

// notify mirror code of removed outputs
// - triggers exit if the target output disappears
output_removed(ctx, cur);

// remove output node from linked list
*link = cur->next;
prev = cur;
cur = cur->next;

// deallocate output node
zxdg_output_v1_destroy(prev->xdg_output);
wl_output_destroy(prev->output);
free(prev->name);
free(prev);

// break when the removed output was found
break;
} else {
link = &cur->next;
cur = cur->next;
{
output_list_node_t ** link = &ctx->wl.outputs;
output_list_node_t * cur = ctx->wl.outputs;
output_list_node_t * prev = NULL;
while (cur != NULL) {
if (id == cur->output_id) {
log_debug(ctx, "wayland::on_registry_remove(): output %s removed (id = %d)\n", cur->name, id);

// notify mirror code of removed outputs
// - triggers exit if the target output disappears
output_removed(ctx, cur);

// remove output node from linked list
*link = cur->next;
prev = cur;
cur = cur->next;

// deallocate output node
zxdg_output_v1_destroy(prev->xdg_output);
wl_output_destroy(prev->output);
free(prev->name);
free(prev);

// return because the removed object was found
return;
} else {
link = &cur->next;
cur = cur->next;
}
}
}

// output not found
// id must have been a seat
{
seat_list_node_t ** link = &ctx->wl.seats;
seat_list_node_t * cur = ctx->wl.seats;
seat_list_node_t * prev = NULL;
while (cur != NULL) {
if (id == cur->seat_id) {
log_debug(ctx, "wayland::on_registry_remove(): seat removed (id = %d)\n", id);

// remove seat node from linked list
*link = cur->next;
prev = cur;
cur = cur->next;

// deallocate seat node
wl_seat_destroy(prev->seat);
free(prev);

// return because the removed object was found
return;
} else {
link = &cur->next;
cur = cur->next;
}
}
}
}
Expand Down Expand Up @@ -672,8 +709,6 @@ void init_wl(ctx_t * ctx) {

ctx->wl.compositor = NULL;
ctx->wl.compositor_id = 0;
ctx->wl.seat = NULL;
ctx->wl.seat_id = 0;
ctx->wl.viewporter = NULL;
ctx->wl.viewporter_id = 0;
ctx->wl.fractional_scale_manager = NULL;
Expand All @@ -691,6 +726,7 @@ void init_wl(ctx_t * ctx) {
ctx->wl.screencopy_manager_id = 0;

ctx->wl.outputs = NULL;
ctx->wl.seats = NULL;

ctx->wl.surface = NULL;
ctx->wl.viewport = NULL;
Expand Down Expand Up @@ -889,20 +925,37 @@ void cleanup_wl(ctx_t *ctx) {
// deregister event handler
event_remove_fd(ctx, &ctx->wl.event_handler);

// free every output in output list
output_list_node_t * cur = ctx->wl.outputs;
output_list_node_t * prev = NULL;
while (cur != NULL) {
prev = cur;
cur = cur->next;
{
// free every output in output list
output_list_node_t * cur = ctx->wl.outputs;
output_list_node_t * prev = NULL;
while (cur != NULL) {
prev = cur;
cur = cur->next;

// deallocate output node
zxdg_output_v1_destroy(prev->xdg_output);
wl_output_destroy(prev->output);
free(prev->name);
free(prev);
}
ctx->wl.outputs = NULL;
}

// deallocate output node
zxdg_output_v1_destroy(prev->xdg_output);
wl_output_destroy(prev->output);
free(prev->name);
free(prev);
{
// free every seat in seat list
seat_list_node_t * cur = ctx->wl.seats;
seat_list_node_t * prev = NULL;
while (cur != NULL) {
prev = cur;
cur = cur->next;

// deallocate seat node
wl_seat_destroy(prev->seat);
free(prev);
}
ctx->wl.seats = NULL;
}
ctx->wl.outputs = NULL;

if (ctx->wl.dmabuf_manager != NULL) zwlr_export_dmabuf_manager_v1_destroy(ctx->wl.dmabuf_manager);
if (ctx->wl.screencopy_manager != NULL) zwlr_screencopy_manager_v1_destroy(ctx->wl.screencopy_manager);
Expand All @@ -916,7 +969,6 @@ void cleanup_wl(ctx_t *ctx) {
if (ctx->wl.wm_base != NULL) xdg_wm_base_destroy(ctx->wl.wm_base);
if (ctx->wl.fractional_scale_manager != NULL) wp_fractional_scale_manager_v1_destroy(ctx->wl.fractional_scale_manager);
if (ctx->wl.viewporter != NULL) wp_viewporter_destroy(ctx->wl.viewporter);
if (ctx->wl.seat != NULL) wl_seat_destroy(ctx->wl.seat);
if (ctx->wl.compositor != NULL) wl_compositor_destroy(ctx->wl.compositor);
if (ctx->wl.registry != NULL) wl_registry_destroy(ctx->wl.registry);
if (ctx->wl.display != NULL) wl_display_disconnect(ctx->wl.display);
Expand Down

0 comments on commit 502fdc9

Please sign in to comment.