diff --git a/backend/wayland/output.c b/backend/wayland/output.c index 18502ec9e..d8ae63a90 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -322,10 +322,8 @@ static bool output_test(struct wlr_output *wlr_output, return true; } -static void output_layer_handle_addon_destroy(struct wlr_addon *addon) { - struct wlr_wl_output_layer *layer = wl_container_of(addon, layer, addon); - - wlr_addon_finish(&layer->addon); +static void output_layer_destroy(struct wlr_wl_output_layer *layer) { + wl_list_remove(&layer->link); if (layer->viewport != NULL) { wp_viewport_destroy(layer->viewport); } @@ -334,30 +332,15 @@ static void output_layer_handle_addon_destroy(struct wlr_addon *addon) { free(layer); } -static const struct wlr_addon_interface output_layer_addon_impl = { - .name = "wlr_wl_output_layer", - .destroy = output_layer_handle_addon_destroy, -}; - -static struct wlr_wl_output_layer *get_or_create_output_layer( - struct wlr_wl_output *output, struct wlr_output_layer *wlr_layer) { +static struct wlr_wl_output_layer *output_layer_create(struct wlr_wl_output *output) { assert(output->backend->subcompositor != NULL); - struct wlr_wl_output_layer *layer; - struct wlr_addon *addon = wlr_addon_find(&wlr_layer->addons, output, - &output_layer_addon_impl); - if (addon != NULL) { - layer = wl_container_of(addon, layer, addon); - return layer; - } - - layer = calloc(1, sizeof(*layer)); + struct wlr_wl_output_layer *layer = calloc(1, sizeof(*layer)); if (layer == NULL) { return NULL; } - wlr_addon_init(&layer->addon, &wlr_layer->addons, output, - &output_layer_addon_impl); + wl_list_insert(&output->layers, &layer->link); layer->surface = wl_compositor_create_surface(output->backend->compositor); layer->subsurface = wl_subcompositor_get_subsurface( @@ -376,24 +359,6 @@ static struct wlr_wl_output_layer *get_or_create_output_layer( return layer; } -static bool has_layers_order_changed(struct wlr_wl_output *output, - struct wlr_output_layer_state *layers, size_t layers_len) { - // output_basic_check() ensures that layers_len equals the number of - // registered output layers - size_t i = 0; - struct wlr_output_layer *layer; - wl_list_for_each(layer, &output->wlr_output.layers, link) { - assert(i < layers_len); - const struct wlr_output_layer_state *layer_state = &layers[i]; - if (layer_state->layer != layer) { - return true; - } - i++; - } - assert(i == layers_len); - return false; -} - static void output_layer_unmap(struct wlr_wl_output_layer *layer) { if (!layer->mapped) { return; @@ -476,14 +441,19 @@ static bool commit_layers(struct wlr_wl_output *output, return true; } - bool reordered = has_layers_order_changed(output, layers, layers_len); + struct wl_list *current_layer = output->layers.next; - struct wlr_wl_output_layer *prev_layer = NULL; for (size_t i = 0; i < layers_len; i++) { - struct wlr_wl_output_layer *layer = - get_or_create_output_layer(output, layers[i].layer); - if (layer == NULL) { - return false; + struct wlr_wl_output_layer *layer; + + if (current_layer == &output->layers) { + layer = output_layer_create(output); + if (layer == NULL) { + return false; + } + } else { + current_layer = current_layer->next; + layer = wl_container_of(current_layer, layer, link); } if (!layers[i].accepted) { @@ -491,16 +461,19 @@ static bool commit_layers(struct wlr_wl_output *output, continue; } - if (prev_layer != NULL && reordered) { - wl_subsurface_place_above(layer->subsurface, - prev_layer->surface); - } - if (!output_layer_commit(output, layer, &layers[i])) { return false; } } + // destroy unused subsurface + while (current_layer != &output->layers) { + struct wlr_wl_output_layer *layer = + wl_container_of(current_layer, layer, link); + current_layer = current_layer->next; + output_layer_destroy(layer); + } + return true; } @@ -636,6 +609,11 @@ static void output_destroy(struct wlr_output *wlr_output) { wl_list_remove(&output->link); + struct wlr_wl_output_layer *layer, *tmp_layer; + wl_list_for_each_safe(layer, tmp_layer, &output->layers, link) { + output_layer_destroy(layer); + } + if (output->cursor.surface) { wl_surface_destroy(output->cursor.surface); } @@ -768,6 +746,7 @@ struct wlr_output *wlr_wl_output_create(struct wlr_backend *wlr_backend) { output->backend = backend; wl_list_init(&output->presentation_feedbacks); + wl_list_init(&output->layers); output->surface = wl_compositor_create_surface(backend->compositor); if (!output->surface) { diff --git a/include/backend/wayland.h b/include/backend/wayland.h index fd0564030..bcbaa66a6 100644 --- a/include/backend/wayland.h +++ b/include/backend/wayland.h @@ -68,7 +68,7 @@ struct wlr_wl_presentation_feedback { }; struct wlr_wl_output_layer { - struct wlr_addon addon; + struct wl_list link; // struct wlr_wl_output.layers struct wl_surface *surface; struct wl_subsurface *subsurface; @@ -96,6 +96,8 @@ struct wlr_wl_output { struct wl_surface *surface; int32_t hotspot_x, hotspot_y; } cursor; + + struct wl_list layers; // struct wlr_wl_output_layer.link }; struct wlr_wl_pointer {