subsurface stacking requests
This commit is contained in:
parent
2e8543cac0
commit
93f79378f7
|
@ -48,8 +48,10 @@ struct wlr_subsurface {
|
|||
bool has_cache;
|
||||
|
||||
bool synchronized;
|
||||
bool reordered;
|
||||
|
||||
struct wl_list parent_link;
|
||||
struct wl_list parent_pending_link;
|
||||
};
|
||||
|
||||
struct wlr_surface {
|
||||
|
@ -76,6 +78,8 @@ struct wlr_surface {
|
|||
struct wlr_subsurface *subsurface;
|
||||
struct wl_list subsurface_list; // wlr_subsurface::parent_link
|
||||
|
||||
// wlr_subsurface::parent_pending_link
|
||||
struct wl_list subsurface_pending_list;
|
||||
void *data;
|
||||
};
|
||||
|
||||
|
|
|
@ -290,12 +290,44 @@ static void wlr_surface_move_state(struct wlr_surface *surface, struct wlr_surfa
|
|||
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) {
|
||||
int32_t oldw = surface->current->buffer_width;
|
||||
int32_t oldh = surface->current->buffer_height;
|
||||
|
||||
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 ||
|
||||
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.destroy);
|
||||
wl_list_init(&surface->subsurface_list);
|
||||
wl_list_init(&surface->subsurface_pending_list);
|
||||
wl_resource_set_implementation(res, &surface_interface,
|
||||
surface, destroy_surface);
|
||||
return surface;
|
||||
|
@ -612,14 +645,69 @@ static void subsurface_set_position(struct wl_client *client,
|
|||
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,
|
||||
struct wl_resource *resource, struct wl_resource *sibling) {
|
||||
wlr_log(L_DEBUG, "TODO: subsurface place above");
|
||||
struct wl_resource *resource, struct wl_resource *sibling_resource) {
|
||||
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,
|
||||
struct wl_resource *resource, struct wl_resource *sibling) {
|
||||
wlr_log(L_DEBUG, "TODO: subsurface place below");
|
||||
struct wl_resource *resource, struct wl_resource *sibling_resource) {
|
||||
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,
|
||||
|
|
Loading…
Reference in New Issue