Fix popups

Fixes the render and container_at order for popups.

Fixes #2210

For rendering:

* render_view_surfaces has been renamed to render_view_toplevels
* render_view_toplevels now uses output_surface_for_each_surface (which
is now public), as that function uses wlr_surface_for_each_surface which
doesn't descend into popups
* Views now have a for_each_popup iterator, which is used by the
renderer to render the focused view's popups
* When rendering a popup, toplevels (xdg subsurfaces) of that popup are
also rendered

For sending frame done, the logic has been updated to match the
rendering logic:

* send_frame_done_container no longer descends into popups
* for_each_popup is used to send frame done to the focused view's popups
and their child toplevels

For container_at:

* floating_container_at is now static, which means it had to be moved
higher in the file.
* container_at now considers popups for the focused view before checking
containers.
* tiling_container_at has been introduced, so that it doesn't call
container_at recursively (it would check popups recursively if it did)
This commit is contained in:
Ryan Dwyer 2018-07-31 18:41:30 +10:00
parent f19add2702
commit de86d65627
10 changed files with 228 additions and 57 deletions

View file

@ -119,7 +119,7 @@ static void output_for_each_surface_iterator(struct wlr_surface *surface,
data->user_data);
}
static void output_surface_for_each_surface(struct sway_output *output,
void output_surface_for_each_surface(struct sway_output *output,
struct wlr_surface *surface, double ox, double oy,
sway_surface_iterator_func_t iterator, void *user_data) {
struct surface_iterator_data data = {
@ -155,6 +155,23 @@ void output_view_for_each_surface(struct sway_output *output,
output_for_each_surface_iterator, &data);
}
void output_view_for_each_popup(struct sway_output *output,
struct sway_view *view, sway_surface_iterator_func_t iterator,
void *user_data) {
struct surface_iterator_data data = {
.user_iterator = iterator,
.user_data = user_data,
.output = output,
.ox = view->swayc->current.view_x - output->swayc->current.swayc_x,
.oy = view->swayc->current.view_y - output->swayc->current.swayc_y,
.width = view->swayc->current.view_width,
.height = view->swayc->current.view_height,
.rotation = 0, // TODO
};
view_for_each_popup(view, output_for_each_surface_iterator, &data);
}
void output_layer_for_each_surface(struct sway_output *output,
struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator,
void *user_data) {
@ -295,8 +312,9 @@ static void send_frame_done_container_iterator(struct sway_container *con,
return;
}
output_view_for_each_surface(data->output, con->sway_view,
send_frame_done_iterator, data->when);
// Toplevels only
output_surface_for_each_surface(data->output, con->sway_view->surface,
con->x, con->y, send_frame_done_iterator, data->when);
}
static void send_frame_done_container(struct sway_output *output,
@ -309,6 +327,27 @@ static void send_frame_done_container(struct sway_output *output,
send_frame_done_container_iterator, &data);
}
static void send_frame_done_popup_iterator(struct sway_output *output,
struct wlr_surface *surface, struct wlr_box *box, float rotation,
void *data) {
// Send frame done to this popup's surface
send_frame_done_iterator(output, surface, box, rotation, data);
// Send frame done to this popup's child toplevels
output_surface_for_each_surface(output, surface, box->x, box->y,
send_frame_done_iterator, data);
}
static void send_frame_done_popups(struct sway_output *output,
struct sway_view *view, struct timespec *when) {
struct send_frame_done_data data = {
.output = output,
.when = when,
};
output_view_for_each_popup(output, view,
send_frame_done_popup_iterator, &data);
}
static void send_frame_done(struct sway_output *output, struct timespec *when) {
if (output_has_opaque_overlay_layer_surface(output)) {
goto send_frame_overlay;
@ -346,6 +385,13 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) {
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], when);
}
struct sway_seat *seat = input_manager_current_seat(input_manager);
struct sway_container *focus = seat_get_focus(seat);
if (focus && focus->type == C_VIEW) {
send_frame_done_popups(output, focus->sway_view, when);
}
send_frame_overlay:
send_frame_done_layer(output,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], when);