mirror of
https://github.com/labwc/labwc.git
synced 2026-04-07 08:21:20 -04:00
toplevel-capture: work around missing frame events due to wlroots bug
In wlroots 0.20.0 there is an issue where a capture scene removes outputs from a wlr_surface which belong to another scene. This in turn causes `wlr_scene_output_send_frame_done()` to fail for our main scene after a toplevel has been captured once, for example via grim -T. To work around the issue we look for views with a capture session, iterate over all its wlr_scene_buffers and if they have the primary output set (e.g. they are not completely covered / hidden) we send the frame event manually. As wlroots turns multiple frame events without a new callback registered by the client into no-ops this also doesn't result in duplicated frame events seen by the client. Note that the other way around also causes an issue which this workaround does not fix. When capturing a toplevel and then changing its visibility state on screen and then covering it up completely / hiding it the capture will stall instead.
This commit is contained in:
parent
facf3856cb
commit
d9649d630a
1 changed files with 53 additions and 0 deletions
53
src/output.c
53
src/output.c
|
|
@ -51,6 +51,36 @@
|
||||||
#include <wlr/backend/session.h>
|
#include <wlr/backend/session.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Partial workaround for toplevel capture on wlroots 0.20.0
|
||||||
|
* Note that even with this workaround the capture itself might still stall.
|
||||||
|
*
|
||||||
|
* See https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5315
|
||||||
|
*
|
||||||
|
* TODO: Remove once we start tracking wlroots 0.21.x
|
||||||
|
* or labwc depends on wlroots >= 0.20.1
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <wlr/types/wlr_compositor.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
workaround_frame_done_iter(struct wlr_scene_buffer *buffer, int sx, int sy, void *data)
|
||||||
|
{
|
||||||
|
if (!buffer->primary_output) {
|
||||||
|
/* Catches hidden views, e.g. completely covered or disabled */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_scene_surface *scene_surface = wlr_scene_surface_try_from_buffer(buffer);
|
||||||
|
if (!scene_surface) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_surface_send_frame_done(scene_surface->surface, (struct timespec *)data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Workaround for toplevel capture end */
|
||||||
|
|
||||||
bool
|
bool
|
||||||
output_get_tearing_allowance(struct output *output)
|
output_get_tearing_allowance(struct output *output)
|
||||||
{
|
{
|
||||||
|
|
@ -121,6 +151,29 @@ handle_output_frame(struct wl_listener *listener, void *data)
|
||||||
struct timespec now = { 0 };
|
struct timespec now = { 0 };
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
wlr_scene_output_send_frame_done(output->scene_output, &now);
|
wlr_scene_output_send_frame_done(output->scene_output, &now);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Workaround for toplevel capture on wlroots 0.20.0
|
||||||
|
*
|
||||||
|
* TODO: Remove once we start tracking wlroots 0.21.x
|
||||||
|
* or labwc depends on wlroots >= 0.20.1
|
||||||
|
*/
|
||||||
|
if (LAB_WLR_VERSION_LOWER(0, 20, 1)) {
|
||||||
|
struct view *view;
|
||||||
|
wl_list_for_each(view, &server.views, link) {
|
||||||
|
if (view->capture.source) {
|
||||||
|
if (!view_on_output(view, output)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* view might still be covered / disabled,
|
||||||
|
* but the iterator takes care of that.
|
||||||
|
*/
|
||||||
|
wlr_scene_node_for_each_buffer(&view->content_tree->node,
|
||||||
|
workaround_frame_done_iter, &now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue