aboutsummaryrefslogtreecommitdiff
path: root/sway/desktop
diff options
context:
space:
mode:
authorRyan Dwyer <ryandwyer1@gmail.com>2018-07-31 18:41:30 +1000
committerRyan Dwyer <ryandwyer1@gmail.com>2018-07-31 18:41:30 +1000
commitde86d65627e96cffe77f4abf11c4a0b982326ff9 (patch)
tree1a3a914fdf561884b1bb0425d51d15684b629b3a /sway/desktop
parentf19add2702f1215bf58aa8790bf3f46e50800e57 (diff)
downloadsway-de86d65627e96cffe77f4abf11c4a0b982326ff9.tar.xz
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)
Diffstat (limited to 'sway/desktop')
-rw-r--r--sway/desktop/output.c52
-rw-r--r--sway/desktop/render.c37
-rw-r--r--sway/desktop/xdg_shell.c9
-rw-r--r--sway/desktop/xdg_shell_v6.c10
4 files changed, 101 insertions, 7 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 31b53213..4c9d978c 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -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);
diff --git a/sway/desktop/render.c b/sway/desktop/render.c
index f25055b8..ea4361f2 100644
--- a/sway/desktop/render.c
+++ b/sway/desktop/render.c
@@ -186,13 +186,36 @@ static void premultiply_alpha(float color[4], float opacity) {
color[2] *= color[3];
}
-static void render_view_surfaces(struct sway_view *view,
+static void render_view_toplevels(struct sway_view *view,
struct sway_output *output, pixman_region32_t *damage, float alpha) {
struct render_data data = {
.damage = damage,
.alpha = alpha,
};
- output_view_for_each_surface(output, view, render_surface_iterator, &data);
+ // Render all toplevels without descending into popups
+ output_surface_for_each_surface(output, view->surface,
+ view->swayc->current.view_x, view->swayc->current.view_y,
+ render_surface_iterator, &data);
+}
+
+static void render_popup_iterator(struct sway_output *output,
+ struct wlr_surface *surface, struct wlr_box *box, float rotation,
+ void *data) {
+ // Render this popup's surface
+ render_surface_iterator(output, surface, box, rotation, data);
+
+ // Render this popup's child toplevels
+ output_surface_for_each_surface(output, surface, box->x, box->y,
+ render_surface_iterator, data);
+}
+
+static void render_view_popups(struct sway_view *view,
+ struct sway_output *output, pixman_region32_t *damage, float alpha) {
+ struct render_data data = {
+ .damage = damage,
+ .alpha = alpha,
+ };
+ output_view_for_each_popup(output, view, render_popup_iterator, &data);
}
static void render_saved_view(struct sway_view *view,
@@ -241,7 +264,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage,
if (view->swayc->instructions->length) {
render_saved_view(view, output, damage, view->swayc->alpha);
} else {
- render_view_surfaces(view, output, damage, view->swayc->alpha);
+ render_view_toplevels(view, output, damage, view->swayc->alpha);
}
if (view->using_csd) {
@@ -845,7 +868,7 @@ void output_render(struct sway_output *output, struct timespec *when,
render_saved_view(fullscreen_con->sway_view,
output, damage, 1.0f);
} else {
- render_view_surfaces(fullscreen_con->sway_view,
+ render_view_toplevels(fullscreen_con->sway_view,
output, damage, 1.0f);
}
} else {
@@ -881,6 +904,12 @@ void output_render(struct sway_output *output, struct timespec *when,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]);
}
+ struct sway_seat *seat = input_manager_current_seat(input_manager);
+ struct sway_container *focus = seat_get_focus(seat);
+ if (focus && focus->type == C_VIEW) {
+ render_view_popups(focus->sway_view, output, damage, focus->alpha);
+ }
+
render_overlay:
render_layer(output, damage,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]);
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c
index e6e1527e..9f94bd74 100644
--- a/sway/desktop/xdg_shell.c
+++ b/sway/desktop/xdg_shell.c
@@ -179,6 +179,14 @@ static void for_each_surface(struct sway_view *view,
user_data);
}
+static void for_each_popup(struct sway_view *view,
+ wlr_surface_iterator_func_t iterator, void *user_data) {
+ if (xdg_shell_view_from_view(view) == NULL) {
+ return;
+ }
+ wlr_xdg_surface_for_each_popup(view->wlr_xdg_surface, iterator, user_data);
+}
+
static void _close(struct sway_view *view) {
if (xdg_shell_view_from_view(view) == NULL) {
return;
@@ -207,6 +215,7 @@ static const struct sway_view_impl view_impl = {
.set_fullscreen = set_fullscreen,
.wants_floating = wants_floating,
.for_each_surface = for_each_surface,
+ .for_each_popup = for_each_popup,
.close = _close,
.destroy = destroy,
};
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c
index 5feee3e4..4502c386 100644
--- a/sway/desktop/xdg_shell_v6.c
+++ b/sway/desktop/xdg_shell_v6.c
@@ -175,6 +175,15 @@ static void for_each_surface(struct sway_view *view,
user_data);
}
+static void for_each_popup(struct sway_view *view,
+ wlr_surface_iterator_func_t iterator, void *user_data) {
+ if (xdg_shell_v6_view_from_view(view) == NULL) {
+ return;
+ }
+ wlr_xdg_surface_v6_for_each_popup(view->wlr_xdg_surface_v6, iterator,
+ user_data);
+}
+
static void _close(struct sway_view *view) {
if (xdg_shell_v6_view_from_view(view) == NULL) {
return;
@@ -203,6 +212,7 @@ static const struct sway_view_impl view_impl = {
.set_fullscreen = set_fullscreen,
.wants_floating = wants_floating,
.for_each_surface = for_each_surface,
+ .for_each_popup = for_each_popup,
.close = _close,
.destroy = destroy,
};