diff --git a/include/wlr/types/wlr_surface.h b/include/wlr/types/wlr_surface.h index 87d421e3..eb88a663 100644 --- a/include/wlr/types/wlr_surface.h +++ b/include/wlr/types/wlr_surface.h @@ -19,6 +19,12 @@ struct wlr_frame_callback { #define WLR_SURFACE_INVALID_TRANSFORM 32 #define WLR_SURFACE_INVALID_SCALE 64 +struct wlr_subsurface { + struct wl_resource *resource; + struct wlr_surface *surface; + struct wlr_surface *parent; +}; + struct wlr_surface_state { uint32_t invalid; struct wl_resource *buffer; @@ -52,6 +58,9 @@ struct wlr_surface { struct wl_listener compositor_listener; // destroy listener used by compositor void *compositor_data; + // subsurface properties + struct wlr_subsurface *subsurface; + void *data; }; @@ -80,4 +89,10 @@ void wlr_surface_get_matrix(struct wlr_surface *surface, int wlr_surface_set_role(struct wlr_surface *surface, const char *role, struct wl_resource *error_resource, uint32_t error_code); +/** + * Create the subsurface implementation for this surface. + */ +void wlr_surface_make_subsurface(struct wlr_surface *surface, + struct wlr_surface *parent, uint32_t id); + #endif diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c index 75bf6146..a142ddd4 100644 --- a/types/wlr_compositor.c +++ b/types/wlr_compositor.c @@ -78,9 +78,27 @@ static void subcompositor_destroy(struct wl_client *client, } static void subcompositor_get_subsurface(struct wl_client *client, - struct wl_resource *resource, uint32_t id, struct wl_resource *surface, - struct wl_resource *parent) { - wlr_log(L_DEBUG, "TODO: subcompositor get subsurface"); + struct wl_resource *resource, uint32_t id, + struct wl_resource *surface_resource, + struct wl_resource *parent_resource) { + struct wlr_surface *surface = wl_resource_get_user_data(surface_resource); + struct wlr_surface *parent = wl_resource_get_user_data(parent_resource); + + // TODO: errors + // * cannot be its own parent + // * cannot already a subsurface + // * cannot be an ancestor of parent + + if (wlr_surface_set_role(surface, "wl_subsurface", resource, + WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE) < 0) { + return; + } + + wlr_surface_make_subsurface(surface, parent, id); + if (!surface->subsurface) { + wl_resource_post_no_memory(resource); + return; + } } diff --git a/types/wlr_surface.c b/types/wlr_surface.c index a9a54abe..de28f4df 100644 --- a/types/wlr_surface.c +++ b/types/wlr_surface.c @@ -443,3 +443,79 @@ int wlr_surface_set_role(struct wlr_surface *surface, const char *role, return -1; } + +void wlr_subsurface_destroy(struct wlr_subsurface *subsurface) { + wlr_log(L_DEBUG, "TODO: wlr subsurface destroy"); +} + +static void subsurface_resource_destroy(struct wl_resource *resource) { + struct wlr_subsurface *subsurface = wl_resource_get_user_data(resource); + + if (subsurface) { + wlr_subsurface_destroy(subsurface); + } +} + +static void subsurface_destroy(struct wl_client *client, + struct wl_resource *resource) { + wl_resource_destroy(resource); +} + +static void subsurface_set_position(struct wl_client *client, + struct wl_resource *resource, int32_t x, int32_t y) { + wlr_log(L_DEBUG, "TODO: subsurface set position"); +} + +static void subsurface_place_above(struct wl_client *client, + struct wl_resource *resource, struct wl_resource *sibling) { + wlr_log(L_DEBUG, "TODO: subsurface place above"); +} + +static void subsurface_place_below(struct wl_client *client, + struct wl_resource *resource, struct wl_resource *sibling) { + wlr_log(L_DEBUG, "TODO: subsurface place below"); +} + +static void subsurface_set_sync(struct wl_client *client, + struct wl_resource *resource) { + wlr_log(L_DEBUG, "TODO: subsurface set sync"); +} + +static void subsurface_set_desync(struct wl_client *client, + struct wl_resource *resource) { + wlr_log(L_DEBUG, "TODO: subsurface set desync"); +} + +static const struct wl_subsurface_interface subsurface_implementation = { + .destroy = subsurface_destroy, + .set_position = subsurface_set_position, + .place_above = subsurface_place_above, + .place_below = subsurface_place_below, + .set_sync = subsurface_set_sync, + .set_desync = subsurface_set_desync, +}; + +void wlr_surface_make_subsurface(struct wlr_surface *surface, + struct wlr_surface *parent, uint32_t id) { + assert(surface->subsurface == NULL); + + struct wlr_subsurface *subsurface = + calloc(1, sizeof(struct wlr_subsurface)); + if (!subsurface) { + return; + } + + subsurface->surface = surface; + subsurface->parent = parent; + + struct wl_client *client = wl_resource_get_client(surface->resource); + + subsurface->resource = + wl_resource_create(client, &wl_subsurface_interface, 1, id); + + wl_resource_set_implementation(subsurface->resource, + &subsurface_implementation, subsurface, + subsurface_resource_destroy); + + surface->subsurface = subsurface; +}