subsurface stacking requests

This commit is contained in:
Tony Crisci 2017-09-29 08:40:37 -04:00
parent 2e8543cac0
commit 93f79378f7
2 changed files with 96 additions and 4 deletions

View File

@ -48,8 +48,10 @@ struct wlr_subsurface {
bool has_cache; bool has_cache;
bool synchronized; bool synchronized;
bool reordered;
struct wl_list parent_link; struct wl_list parent_link;
struct wl_list parent_pending_link;
}; };
struct wlr_surface { struct wlr_surface {
@ -76,6 +78,8 @@ struct wlr_surface {
struct wlr_subsurface *subsurface; struct wlr_subsurface *subsurface;
struct wl_list subsurface_list; // wlr_subsurface::parent_link struct wl_list subsurface_list; // wlr_subsurface::parent_link
// wlr_subsurface::parent_pending_link
struct wl_list subsurface_pending_list;
void *data; void *data;
}; };

View File

@ -290,12 +290,44 @@ static void wlr_surface_move_state(struct wlr_surface *surface, struct wlr_surfa
next->invalid = 0; next->invalid = 0;
} }
static void wlr_surface_damage_subsurfaces(struct wlr_subsurface *subsurface) {
// XXX: This is probably the wrong way to do it, because this damage should
// come from the client, but weston doesn't do it correctly either and it
// seems to work ok. See the comment on weston_surface_damage for more info
// about a better approach.
struct wlr_surface *surface = subsurface->surface;
pixman_region32_union_rect(&surface->current->surface_damage,
&surface->current->surface_damage,
0, 0, surface->current->width,
surface->current->height);
subsurface->reordered = false;
struct wlr_subsurface *child;
wl_list_for_each(child, &subsurface->surface->subsurface_list, parent_link) {
wlr_surface_damage_subsurfaces(child);
}
}
static void wlr_surface_commit_pending(struct wlr_surface *surface) { static void wlr_surface_commit_pending(struct wlr_surface *surface) {
int32_t oldw = surface->current->buffer_width; int32_t oldw = surface->current->buffer_width;
int32_t oldh = surface->current->buffer_height; int32_t oldh = surface->current->buffer_height;
wlr_surface_move_state(surface, surface->pending, surface->current); wlr_surface_move_state(surface, surface->pending, surface->current);
// commit subsurface order
struct wlr_subsurface *subsurface;
wl_list_for_each_reverse(subsurface, &surface->subsurface_pending_list,
parent_pending_link) {
wl_list_remove(&subsurface->parent_link);
wl_list_insert(&surface->subsurface_list, &subsurface->parent_link);
if (subsurface->reordered) {
// TODO: damage all the subsurfaces
wlr_surface_damage_subsurfaces(subsurface);
}
}
surface->reupload_buffer = oldw != surface->current->buffer_width || surface->reupload_buffer = oldw != surface->current->buffer_width ||
oldh != surface->current->buffer_height; oldh != surface->current->buffer_height;
@ -546,6 +578,7 @@ struct wlr_surface *wlr_surface_create(struct wl_resource *res,
wl_signal_init(&surface->signals.commit); wl_signal_init(&surface->signals.commit);
wl_signal_init(&surface->signals.destroy); wl_signal_init(&surface->signals.destroy);
wl_list_init(&surface->subsurface_list); wl_list_init(&surface->subsurface_list);
wl_list_init(&surface->subsurface_pending_list);
wl_resource_set_implementation(res, &surface_interface, wl_resource_set_implementation(res, &surface_interface,
surface, destroy_surface); surface, destroy_surface);
return surface; return surface;
@ -612,14 +645,69 @@ static void subsurface_set_position(struct wl_client *client,
surface->pending->subsurface_position.y = y; surface->pending->subsurface_position.y = y;
} }
static struct wlr_subsurface *subsurface_find_sibling(
struct wlr_subsurface *subsurface, struct wlr_surface *surface) {
struct wlr_surface *parent = subsurface->parent;
struct wlr_subsurface *sibling;
wl_list_for_each(sibling, &parent->subsurface_list, parent_link) {
if (sibling->surface == surface && sibling != subsurface)
return sibling;
}
return NULL;
}
static void subsurface_place_above(struct wl_client *client, static void subsurface_place_above(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *sibling) { struct wl_resource *resource, struct wl_resource *sibling_resource) {
wlr_log(L_DEBUG, "TODO: subsurface place above"); struct wlr_subsurface *subsurface = wl_resource_get_user_data(resource);
if (!subsurface) {
return;
}
struct wlr_surface *sibling_surface =
wl_resource_get_user_data(sibling_resource);
struct wlr_subsurface *sibling =
subsurface_find_sibling(subsurface, sibling_surface);
if (!sibling) {
wl_resource_post_error(subsurface->resource,
WL_SUBSURFACE_ERROR_BAD_SURFACE,
"%s: wl_surface@%d is not a parent or sibling",
"place_above", wl_resource_get_id(sibling_surface->resource));
return;
}
wl_list_remove(&subsurface->parent_pending_link);
wl_list_insert(sibling->parent_pending_link.prev,
&subsurface->parent_pending_link);
subsurface->reordered = true;
} }
static void subsurface_place_below(struct wl_client *client, static void subsurface_place_below(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *sibling) { struct wl_resource *resource, struct wl_resource *sibling_resource) {
wlr_log(L_DEBUG, "TODO: subsurface place below"); struct wlr_subsurface *subsurface = wl_resource_get_user_data(resource);
struct wlr_surface *sibling_surface =
wl_resource_get_user_data(sibling_resource);
struct wlr_subsurface *sibling =
subsurface_find_sibling(subsurface, sibling_surface);
if (!sibling) {
wl_resource_post_error(subsurface->resource,
WL_SUBSURFACE_ERROR_BAD_SURFACE,
"%s: wl_surface@%d is not a parent or sibling",
"place_below", wl_resource_get_id(sibling_surface->resource));
return;
}
wl_list_remove(&subsurface->parent_pending_link);
wl_list_insert(&sibling->parent_pending_link,
&subsurface->parent_pending_link);
subsurface->reordered = true;
} }
static void subsurface_set_sync(struct wl_client *client, static void subsurface_set_sync(struct wl_client *client,