diff --git a/include/wlr/types/wlr_compositor.h b/include/wlr/types/wlr_compositor.h index 7c94123a..816ff713 100644 --- a/include/wlr/types/wlr_compositor.h +++ b/include/wlr/types/wlr_compositor.h @@ -6,7 +6,10 @@ struct wlr_surface; -// TODO: expose subcompositor +struct wlr_subcompositor { + struct wl_global *wl_global; + struct wl_list wl_resources; +}; struct wlr_compositor { struct wl_global *wl_global; @@ -14,6 +17,8 @@ struct wlr_compositor { struct wlr_renderer *renderer; struct wl_list surfaces; + struct wlr_subcompositor subcompositor; + struct wl_listener display_destroy; struct { diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c index 7e1897e3..57f3bd91 100644 --- a/types/wlr_compositor.c +++ b/types/wlr_compositor.c @@ -10,7 +10,8 @@ static const char *subsurface_role = "wl_subsurface"; bool wlr_surface_is_subsurface(struct wlr_surface *surface) { - return strcmp(surface->role, subsurface_role) == 0; + return surface->role != NULL && + strcmp(surface->role, subsurface_role) == 0; } struct wlr_subsurface *wlr_subsurface_from_surface( @@ -19,9 +20,96 @@ struct wlr_subsurface *wlr_subsurface_from_surface( return (struct wlr_subsurface *)surface->role_data; } +static void subcompositor_handle_destroy(struct wl_client *client, + struct wl_resource *resource) { + wl_resource_destroy(resource); +} + +static void subcompositor_handle_get_subsurface(struct wl_client *client, + struct wl_resource *resource, uint32_t id, + struct wl_resource *surface_resource, + struct wl_resource *parent_resource) { + struct wlr_surface *surface = wlr_surface_from_resource(surface_resource); + struct wlr_surface *parent = wlr_surface_from_resource(parent_resource); + + static const char msg[] = "get_subsurface: wl_subsurface@"; + + if (surface == parent) { + wl_resource_post_error(resource, + WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, + "%s%d: wl_surface@%d cannot be its own parent", + msg, id, wl_resource_get_id(surface_resource)); + return; + } + + if (wlr_surface_is_subsurface(surface)) { + wl_resource_post_error(resource, + WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, + "%s%d: wl_surface@%d is already a sub-surface", + msg, id, wl_resource_get_id(surface_resource)); + return; + } + + if (wlr_surface_get_root_surface(parent) == surface) { + wl_resource_post_error(resource, + WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, + "%s%d: wl_surface@%d is an ancestor of parent", + msg, id, wl_resource_get_id(surface_resource)); + return; + } + + if (wlr_surface_set_role(surface, subsurface_role, resource, + WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE) < 0) { + return; + } + + wlr_surface_make_subsurface(surface, parent, id); +} + +static const struct wl_subcompositor_interface subcompositor_interface = { + .destroy = subcompositor_handle_destroy, + .get_subsurface = subcompositor_handle_get_subsurface, +}; + +static void subcompositor_bind(struct wl_client *client, void *data, + uint32_t version, uint32_t id) { + struct wlr_subcompositor *subcompositor = data; + struct wl_resource *resource = + wl_resource_create(client, &wl_subcompositor_interface, 1, id); + if (resource == NULL) { + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(resource, &subcompositor_interface, + subcompositor, NULL); + wl_list_insert(&subcompositor->wl_resources, wl_resource_get_link(resource)); +} + +static void subcompositor_init(struct wlr_subcompositor *subcompositor, + struct wl_display *display) { + subcompositor->wl_global = wl_global_create(display, + &wl_subcompositor_interface, 1, subcompositor, subcompositor_bind); + if (subcompositor->wl_global == NULL) { + wlr_log_errno(L_ERROR, "Could not allocate subcompositor global"); + return; + } + wl_list_init(&subcompositor->wl_resources); +} + +static void subcompositor_finish(struct wlr_subcompositor *subcompositor) { + wl_global_destroy(subcompositor->wl_global); +} + + + + + + + static const struct wl_compositor_interface wl_compositor_impl; -static struct wlr_compositor *compositor_from_resource(struct wl_resource *resource) { +static struct wlr_compositor *compositor_from_resource( + struct wl_resource *resource) { assert(wl_resource_instance_of(resource, &wl_compositor_interface, &wl_compositor_impl)); return wl_resource_get_user_data(resource); @@ -86,16 +174,15 @@ static void wl_compositor_bind(struct wl_client *wl_client, void *data, struct wlr_compositor *compositor = data; assert(wl_client && compositor); - struct wl_resource *wl_resource = + struct wl_resource *resource = wl_resource_create(wl_client, &wl_compositor_interface, version, id); - if (wl_resource == NULL) { + if (resource == NULL) { wl_client_post_no_memory(wl_client); return; } - wl_resource_set_implementation(wl_resource, &wl_compositor_impl, + wl_resource_set_implementation(resource, &wl_compositor_impl, compositor, wl_compositor_destroy); - wl_list_insert(&compositor->wl_resources, - wl_resource_get_link(wl_resource)); + wl_list_insert(&compositor->wl_resources, wl_resource_get_link(resource)); } void wlr_compositor_destroy(struct wlr_compositor *compositor) { @@ -103,76 +190,12 @@ void wlr_compositor_destroy(struct wlr_compositor *compositor) { return; } wlr_signal_emit_safe(&compositor->events.destroy, compositor); + subcompositor_finish(&compositor->subcompositor); wl_list_remove(&compositor->display_destroy.link); wl_global_destroy(compositor->wl_global); free(compositor); } -static void subcompositor_destroy(struct wl_client *client, - struct wl_resource *resource) { - wl_resource_destroy(resource); -} - -static void subcompositor_get_subsurface(struct wl_client *client, - struct wl_resource *resource, uint32_t id, - struct wl_resource *surface_resource, - struct wl_resource *parent_resource) { - struct wlr_surface *surface = wlr_surface_from_resource(surface_resource); - struct wlr_surface *parent = wlr_surface_from_resource(parent_resource); - - static const char msg[] = "get_subsurface: wl_subsurface@"; - - if (surface == parent) { - wl_resource_post_error(resource, - WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, - "%s%d: wl_surface@%d cannot be its own parent", - msg, id, wl_resource_get_id(surface_resource)); - return; - } - - if (wlr_surface_is_subsurface(surface)) { - wl_resource_post_error(resource, - WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, - "%s%d: wl_surface@%d is already a sub-surface", - msg, id, wl_resource_get_id(surface_resource)); - return; - } - - if (wlr_surface_get_root_surface(parent) == surface) { - wl_resource_post_error(resource, - WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, - "%s%d: wl_surface@%d is an ancestor of parent", - msg, id, wl_resource_get_id(surface_resource)); - return; - } - - if (wlr_surface_set_role(surface, subsurface_role, resource, - WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE) < 0) { - return; - } - - wlr_surface_make_subsurface(surface, parent, id); -} - - -static const struct wl_subcompositor_interface subcompositor_interface = { - .destroy = subcompositor_destroy, - .get_subsurface = subcompositor_get_subsurface, -}; - -static void subcompositor_bind(struct wl_client *client, void *data, - uint32_t version, uint32_t id) { - struct wlr_compositor *compositor = data; - struct wl_resource *resource = - wl_resource_create(client, &wl_subcompositor_interface, 1, id); - if (resource == NULL) { - wl_client_post_no_memory(client); - return; - } - wl_resource_set_implementation(resource, &subcompositor_interface, - compositor, NULL); -} - static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_compositor *compositor = wl_container_of(listener, compositor, display_destroy); @@ -198,14 +221,13 @@ struct wlr_compositor *wlr_compositor_create(struct wl_display *display, compositor->wl_global = compositor_global; compositor->renderer = renderer; - wl_global_create(display, &wl_subcompositor_interface, 1, compositor, - subcompositor_bind); - wl_list_init(&compositor->wl_resources); wl_list_init(&compositor->surfaces); wl_signal_init(&compositor->events.new_surface); wl_signal_init(&compositor->events.destroy); + subcompositor_init(&compositor->subcompositor, display); + compositor->display_destroy.notify = handle_display_destroy; wl_display_add_destroy_listener(display, &compositor->display_destroy);