|
|
|
@ -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,
|
|
|
|
|