From ccbc782177506a9c14c3e7dedbad64afb92c239c Mon Sep 17 00:00:00 2001 From: Andrew Hamilton Date: Tue, 8 Sep 2026 06:49:39 +1000 Subject: [PATCH] migrate screen capture from wlr-screencopy to ext-image-copy-capture The wlr-screencopy unstable protocol is deprecated; its superseding staging protocols ext-image-copy-capture-v1 and ext-image-capture-source-v1 ship in wayland-protocols. Migrate: - advertise wlr_ext_image_copy_capture_manager_v1 and wlr_ext_output_image_capture_source_manager_v1 instead of the wlr_screencopy_manager_v1 global (wlroots runs the whole session/frame flow off the output commit path, so no listener wiring is needed) - rewrite wltest --screencopy for the new client flow: bind the capture managers, create an output capture source, open a copy-capture session, wait for the constraint batch (buffer_size/shm_format/done), then attach a shm buffer and ask for one frame - generate the two client stubs from wayland-protocols and drop the bundled wlr-screencopy-unstable-v1.xml - update the globals test to the new interface names Existing wl_data_device-based clipboard bridge code is unaffected. --- README.md | 19 +- kick.c | 23 +- meson.build | 30 +-- tests/test_smoke.py | 13 +- tests/wltest.c | 206 ++++++++++------ wlr-protocols/wlr-screencopy-unstable-v1.xml | 232 ------------------- 6 files changed, 185 insertions(+), 338 deletions(-) delete mode 100644 wlr-protocols/wlr-screencopy-unstable-v1.xml diff --git a/README.md b/README.md index b9f1116..7bd04a1 100644 --- a/README.md +++ b/README.md @@ -21,12 +21,13 @@ The resulting binary is `build/kick`. The Wayland protocol stubs (`xdg-shell`, `xdg-decoration`, `cursor-shape-v1` and `tablet-v2`, `ext-data-control-v1`, -`ext-image-copy-capture-v1`) are not committed; they are generated into the -build directory by `wayland-scanner` from the system `wayland-protocols` -(and the bundled `wlr-layer-shell-unstable-v1.xml`), so they always match -the installed protocol headers. This adds no extra dependency beyond what -the wlroots fallback already requires. (`tablet-v2` is generated only -because cursor-shape's implementation references `wl_tablet_tool_v2_interface`.) +`ext-image-copy-capture-v1`, `ext-image-capture-source-v1`) are not +committed; they are generated into the build directory by `wayland-scanner` +from the system `wayland-protocols` (and the bundled +`wlr-layer-shell-unstable-v1.xml`), so they always match the installed +protocol headers. This adds no extra dependency beyond what the wlroots +fallback already requires. (`tablet-v2` is generated only because +cursor-shape's implementation references `wl_tablet_tool_v2_interface`.) ### Debian / Ubuntu @@ -338,9 +339,9 @@ Wayland compositor and draws every tab inside that single window. when no TTY is available. `test_nested_host_primary_to_kick` exercises the host->nested primary -selection path, which only exists over the data-control v2 bridge; it skips -on hosts without it (e.g. GNOME), so use a data-control host (labwc, sway) -for it. +selection path, which only exists over the ext-data-control bridge; it skips +on hosts without it (e.g. GNOME), so use an ext-data-control host (labwc, +sway) for it. Known-flaky tests are marked `@pytest.mark.flaky`. `pytest.ini` defaults to `-m "not flaky"`, so they are excluded from every plain run (`./test.sh` or diff --git a/kick.c b/kick.c index e62a16d..b7c0050 100644 --- a/kick.c +++ b/kick.c @@ -81,6 +81,8 @@ #include #include #include +#include +#include #include #include #include @@ -105,7 +107,6 @@ #include #include #include -#include #include #include #include @@ -394,12 +395,13 @@ struct kick_server { struct wl_listener idle_new_inhibitor; struct wl_listener idle_inhibit_destroy; struct wl_list idle_inhibitors; - /* Screen capture (wlr-screencopy-unstable-v1) for tools like grim. wlroots - drives the output commit path itself (it locks attach-render and calls - wlr_output_update_needs_frame), so beyond advertising the global there is - nothing to wire up: every output commit that carries a rendered buffer - becomes a copyable frame. */ - struct wlr_screencopy_manager_v1 *screencopy_mgr; + /* Screen capture (ext-image-copy-capture-v1 + ext-image-capture-source-v1) + for tools like grim. wlroots drives the output commit path itself (it + locks attach-render and calls wlr_output_update_needs_frame), so beyond + advertising the two globals there is nothing to wire up: every output + commit that carries a rendered buffer becomes a copyable frame. */ + struct wlr_ext_image_copy_capture_manager_v1 *copy_capture_mgr; + struct wlr_ext_output_image_capture_source_manager_v1 *output_capture_mgr; /* Tearing (wp-tearing-control-v1) + fractional-scale (wp-fractional-scale): the shown surface's hint drives the commit's async-flip flag (see apply_tearing_hint), and each surface learns the output scale at @@ -11551,9 +11553,12 @@ int main(int argc, char *argv[]) { wl_signal_add(&server.session_lock_manager->events.new_lock, &server.session_lock_new_lock); - /* Screen capture (wlr-screencopy-unstable-v1), for grim & co. wlroots + /* Screen capture (ext-image-copy-capture-v1), for grim & co. wlroots runs the whole capture flow itself off the output commit path. */ - server.screencopy_mgr = wlr_screencopy_manager_v1_create(server.wl_display); + server.copy_capture_mgr = wlr_ext_image_copy_capture_manager_v1_create( + server.wl_display, 1); + server.output_capture_mgr = wlr_ext_output_image_capture_source_manager_v1_create( + server.wl_display, 1); /* Tearing-control + fractional-scale: the shown surface's tearing hint drives the commit's async-flip flag (see apply_tearing_hint), and diff --git a/meson.build b/meson.build index fddb6b7..113cdde 100644 --- a/meson.build +++ b/meson.build @@ -102,16 +102,15 @@ protocols = { ], # wlr-layer-shell is what waybar and other panels use to make an # always-visible bar. Bundled locally (like the foreign-toplevel and - # screencopy XMLs) rather than referenced from the wlroots tree, so it - # works with either a system wlroots or the pinned subproject. + # output-management XMLs) rather than referenced from the wlroots tree, + # so it works with either a system wlroots or the pinned subproject. 'wlr-layer-shell-unstable-v1': [ 'wlr-protocols/wlr-layer-shell-unstable-v1.xml', 'wlr-layer-shell-unstable-v1', ], # wlr-foreign-toplevel-management is the taskbar protocol: a per-window # handle with client-pull state. Bundled locally (like the layer-shell - # and data-control XMLs) so it works with either a system wlroots or the - # pinned subproject. + # XML) so it works with either a system wlroots or the pinned subproject. 'wlr-foreign-toplevel-management-unstable-v1': [ 'wlr-protocols/wlr-foreign-toplevel-management-unstable-v1.xml', 'wlr-foreign-toplevel-management', @@ -141,13 +140,16 @@ protocols = { wl_protocols_dir / 'staging/ext-session-lock/ext-session-lock-v1.xml', 'ext-session-lock-v1', ], - # Screen capture (wlr-screencopy-unstable-v1), the protocol grim uses. The - # XML ships inside the pinned wlroots subproject; copied here (like the - # other bundled wlr-protocols XMLs) because Meson forbids referencing a - # nested subproject's files from the parent project. - 'wlr-screencopy-unstable-v1': [ - 'wlr-protocols/wlr-screencopy-unstable-v1.xml', - 'wlr-screencopy-unstable-v1', + # Screen capture (ext-image-copy-capture-v1 + ext-image-capture-source-v1), + # the protocol grim uses. Staging protocols from wayland-protocols; the + # XMLs are referenced from the installed package. + 'ext-image-copy-capture': [ + wl_protocols_dir / 'staging/ext-image-copy-capture/ext-image-copy-capture-v1.xml', + 'ext-image-copy-capture-v1', + ], + 'ext-image-capture-source': [ + wl_protocols_dir / 'staging/ext-image-capture-source/ext-image-capture-source-v1.xml', + 'ext-image-capture-source-v1', ], # Tearing control (a surface asks for unthrottled presentation) and # fractional scale (a surface learns a non-integer output scale). @@ -387,7 +389,8 @@ executable('wltest', code_by_name['ext-idle-notify'], code_by_name['idle-inhibit-unstable-v1'], code_by_name['ext-session-lock'], - code_by_name['wlr-screencopy-unstable-v1'], + code_by_name['ext-image-copy-capture'], + code_by_name['ext-image-capture-source'], code_by_name['keyboard-shortcuts-inhibit'], code_by_name['wlr-output-power-management-unstable-v1'], code_by_name['virtual-keyboard-unstable-v1'], @@ -411,7 +414,8 @@ executable('wltest', client_headers['ext-idle-notify'], client_headers['idle-inhibit-unstable-v1'], client_headers['ext-session-lock'], - client_headers['wlr-screencopy-unstable-v1'], + client_headers['ext-image-copy-capture'], + client_headers['ext-image-capture-source'], client_headers['keyboard-shortcuts-inhibit'], client_headers['virtual-keyboard-unstable-v1'], client_headers['wlr-virtual-pointer-unstable-v1'], diff --git a/tests/test_smoke.py b/tests/test_smoke.py index 723c487..cdabc65 100644 --- a/tests/test_smoke.py +++ b/tests/test_smoke.py @@ -4657,8 +4657,9 @@ def test_standalone_headless_session_lock_locker_dies(tmp_path): def test_standalone_headless_screencopy_globals(tmp_path): - """The compositor advertises the zwlr_screencopy_manager_v1 global so a - capture tool (grim) can grab output frames.""" + """The compositor advertises the ext_image_copy_capture_manager_v1 and + ext_output_image_capture_source_manager_v1 globals so a capture tool + (grim) can grab output frames.""" out = tmp_path / "globals.txt" s = _spawn_standalone({}, "%s --globals-out '%s' '#112233'" % (WL, out)) try: @@ -4669,8 +4670,12 @@ def test_standalone_headless_screencopy_globals(tmp_path): time.sleep(0.1) assert out.exists(), "wltest --globals-out never wrote its file" names = {line.split()[0] for line in out.read_text().splitlines()} - assert "zwlr_screencopy_manager_v1" in names, \ - f"missing zwlr_screencopy_manager_v1; advertised: {sorted(names)}" + assert "ext_image_copy_capture_manager_v1" in names, \ + f"missing ext_image_copy_capture_manager_v1; " \ + f"advertised: {sorted(names)}" + assert "ext_output_image_capture_source_manager_v1" in names, \ + f"missing ext_output_image_capture_source_manager_v1; " \ + f"advertised: {sorted(names)}" finally: s.close() diff --git a/tests/wltest.c b/tests/wltest.c index 6993fa0..1998457 100644 --- a/tests/wltest.c +++ b/tests/wltest.c @@ -27,7 +27,8 @@ #include "ext-idle-notify-v1-client.h" #include "idle-inhibit-unstable-v1-client.h" #include "ext-session-lock-v1-client.h" -#include "wlr-screencopy-unstable-v1-client.h" +#include "ext-image-copy-capture-v1-client.h" +#include "ext-image-capture-source-v1-client.h" #include "keyboard-shortcuts-inhibit-unstable-v1-client.h" #include "wlr-output-power-management-unstable-v1-client.h" #include "virtual-keyboard-unstable-v1-client.h" @@ -165,7 +166,8 @@ static struct ext_foreign_toplevel_list_v1 *ext_list; static struct ext_idle_notifier_v1 *idle_mgr; static struct zwp_idle_inhibit_manager_v1 *inhib_mgr; static struct ext_session_lock_manager_v1 *lock_mgr; -static struct zwlr_screencopy_manager_v1 *sc_mgr; +static struct ext_image_copy_capture_manager_v1 *sc_mgr; +static struct ext_output_image_capture_source_manager_v1 *sc_out_mgr; static struct zwp_keyboard_shortcuts_inhibit_manager_v1 *kb_inhibit_mgr; static struct zwlr_output_power_manager_v1 *power_mgr; static struct zwp_virtual_keyboard_manager_v1 *virtual_kb_mgr; @@ -909,10 +911,15 @@ static void registry_global(void *data, struct wl_registry *reg, uint32_t name, wl_output = wl_registry_bind(reg, name, &wl_output_interface, version < 2 ? version : 2); } else if (strcmp(interface, - zwlr_screencopy_manager_v1_interface.name) == 0) { + ext_output_image_capture_source_manager_v1_interface.name) == 0) { + sc_out_mgr = wl_registry_bind(reg, name, + &ext_output_image_capture_source_manager_v1_interface, + version < 1 ? version : 1); + } else if (strcmp(interface, + ext_image_copy_capture_manager_v1_interface.name) == 0) { sc_mgr = wl_registry_bind(reg, name, - &zwlr_screencopy_manager_v1_interface, - version < 3 ? version : 3); + &ext_image_copy_capture_manager_v1_interface, + version < 1 ? version : 1); } else if (strcmp(interface, zwp_keyboard_shortcuts_inhibit_manager_v1_interface.name) == 0) { kb_inhibit_mgr = wl_registry_bind(reg, name, @@ -1534,19 +1541,21 @@ static void lock_run(void) { } } -/* --- Screen capture (wlr-screencopy-unstable-v1) --- +/* --- Screen capture (ext-image-copy-capture-v1 / ext-image-capture-source-v1) --- --screencopy [--screencopy-out ]: ask the compositor to capture the single output into a fresh shm buffer the same size as the current target - window (the red test surface), then write "ready-x/<1st-byte>". Proves - kick advertises the screencopy global and that wlroots can copy a rendered - output frame into the client's buffer: the captured geometry matching the - output (the maximized red window) is what confirms the composited frame was - delivered. The trailing byte is a peek at the first captured pixel for - debugging only, not asserted. */ + window (the red test surface), then write "ready-x/<1st-byte>". + Proves kick advertises the capture globals and that wlroots can copy a + rendered output frame into the client's buffer: the captured geometry + matching the output (the maximized red window) is what confirms the + composited frame was delivered. The trailing byte is a peek at the first + captured pixel for debugging only, not asserted. */ static bool screencopy_mode; static const char *screencopy_out; -static struct zwlr_screencopy_frame_v1 *sc_frame; -static bool sc_ready, sc_failed; +static struct ext_image_capture_source_v1 *sc_source; +static struct ext_image_copy_capture_session_v1 *sc_session; +static struct ext_image_copy_capture_frame_v1 *sc_frame; +static bool sc_have_constraints, sc_ready, sc_failed; static uint32_t sc_fmt, sc_w, sc_h, sc_stride; static uint8_t *sc_map; @@ -1554,59 +1563,61 @@ static void sc_note(const char *s) { if (screencopy_out) write_outfile(screencopy_out, s, strlen(s)); } -/* The buffer event tells us the target geometry/stride; both are stored for - buffer creation (done on buffer_done) and for the geometry report in ready. */ -static void sc_on_buffer(void *data, struct zwlr_screencopy_frame_v1 *frame, - uint32_t format, uint32_t width, uint32_t height, - uint32_t stride) { - (void)data; (void)frame; - sc_fmt = format; - sc_w = width; sc_h = height; sc_stride = stride; +/* The session constraint events give us the target geometry and a usable + shm format; buffered until the done event tells us the batch is complete. */ +static void sc_session_on_buffer_size(void *data, + struct ext_image_copy_capture_session_v1 *s, + uint32_t width, uint32_t height) { + (void)data; (void)s; + sc_w = width; sc_h = height; } -/* We advertise the shm path and ignore the dmabuf suggestion; the base shm - buffer handed to copy() is what wlroots fills. */ -static void sc_on_linux_dmabuf(void *data, - struct zwlr_screencopy_frame_v1 *frame, - uint32_t format, uint32_t width, - uint32_t height) { - (void)data; (void)frame; (void)format; (void)width; (void)height; +static void sc_session_on_shm_format(void *data, + struct ext_image_copy_capture_session_v1 *s, + uint32_t format) { + (void)data; (void)s; + if (sc_fmt == 0) + sc_fmt = format; } -/* Frame flags: we don't depend on any flag, just acknowledge the event. */ -static void sc_on_flags(void *data, struct zwlr_screencopy_frame_v1 *frame, - uint32_t flags) { - (void)data; (void)frame; (void)flags; +static void sc_session_on_dmabuf_device(void *data, + struct ext_image_copy_capture_session_v1 *s, + struct wl_array *device) { + (void)data; (void)s; (void)device; } -static void sc_on_buffer_done(void *data, struct zwlr_screencopy_frame_v1 *frame) { - (void)data; (void)frame; - if (sc_fmt == 0) { sc_note("no-buffer"); return; } - size_t size = (size_t)sc_stride * sc_h; - int fd; - struct wl_shm_pool *pool = make_pool(size, &fd); - if (!pool) { sc_note("shm-fail"); return; } - /* Keep the shm fd open and mapped so we can read the copied pixels back - once the compositor fills it on copy()/ready. */ - sc_map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (sc_map == MAP_FAILED) { - sc_map = NULL; - close(fd); - wl_shm_pool_destroy(pool); - sc_note("mmap-fail"); - return; - } - struct wl_buffer *buf = wl_shm_pool_create_buffer(pool, 0, (int32_t)sc_w, - (int32_t)sc_h, - (int32_t)sc_stride, - sc_fmt); - wl_shm_pool_destroy(pool); - zwlr_screencopy_frame_v1_copy(frame, buf); +static void sc_session_on_dmabuf_format(void *data, + struct ext_image_copy_capture_session_v1 *s, + uint32_t format, struct wl_array *modifiers) { + (void)data; (void)s; (void)format; (void)modifiers; } -static void sc_on_ready(void *data, struct zwlr_screencopy_frame_v1 *frame, - uint32_t h, uint32_t l, uint32_t ns) { - (void)data; (void)frame; (void)h; (void)l; (void)ns; +static void sc_session_on_done(void *data, + struct ext_image_copy_capture_session_v1 *s) { + (void)data; (void)s; + sc_have_constraints = true; +} + +static void sc_session_on_stopped(void *data, + struct ext_image_copy_capture_session_v1 *s) { + (void)data; (void)s; + sc_failed = true; + sc_note("stopped"); +} + +static const struct ext_image_copy_capture_session_v1_listener sc_session_listener = { + .buffer_size = sc_session_on_buffer_size, + .shm_format = sc_session_on_shm_format, + .dmabuf_device = sc_session_on_dmabuf_device, + .dmabuf_format = sc_session_on_dmabuf_format, + .done = sc_session_on_done, + .stopped = sc_session_on_stopped, +}; + +static void sc_start_capture(void); + +static void sc_frame_on_ready(void *data, struct ext_image_copy_capture_frame_v1 *f) { + (void)data; (void)f; sc_ready = true; /* The trailing "/" is a peek at the first captured pixel for debugging (the software cursor may sit over the top-left corner, so it @@ -1632,21 +1643,68 @@ static void sc_on_ready(void *data, struct zwlr_screencopy_frame_v1 *frame, sc_note(buf); } -static void sc_on_failed(void *data, struct zwlr_screencopy_frame_v1 *frame) { - (void)data; (void)frame; +static void sc_frame_on_failed(void *data, struct ext_image_copy_capture_frame_v1 *f, + uint32_t reason) { + (void)data; (void)f; (void)reason; sc_failed = true; sc_note("failed"); } -static const struct zwlr_screencopy_frame_v1_listener sc_listener = { - .buffer = sc_on_buffer, - .flags = sc_on_flags, - .linux_dmabuf = sc_on_linux_dmabuf, - .buffer_done = sc_on_buffer_done, - .ready = sc_on_ready, - .failed = sc_on_failed, +static void sc_frame_on_transform(void *data, struct ext_image_copy_capture_frame_v1 *f, + uint32_t transform) { + (void)data; (void)f; (void)transform; +} + +static void sc_frame_on_damage(void *data, struct ext_image_copy_capture_frame_v1 *f, + int32_t x, int32_t y, int32_t width, int32_t height) { + (void)data; (void)f; (void)x; (void)y; (void)width; (void)height; +} + +static void sc_frame_on_presentation_time(void *data, struct ext_image_copy_capture_frame_v1 *f, + uint32_t s_hi, uint32_t s_lo, uint32_t ns) { + (void)data; (void)f; (void)s_hi; (void)s_lo; (void)ns; +} + +static const struct ext_image_copy_capture_frame_v1_listener sc_frame_listener = { + .transform = sc_frame_on_transform, + .damage = sc_frame_on_damage, + .presentation_time = sc_frame_on_presentation_time, + .ready = sc_frame_on_ready, + .failed = sc_frame_on_failed, }; +/* Once the constraints are known, allocate the shm buffer, attach it to a + fresh frame, damage it fully and ask for a capture. */ +static void sc_start_capture(void) { + if (!sc_have_constraints || sc_w == 0 || sc_h == 0 || sc_fmt == 0) + return; + sc_stride = sc_w * 4; + size_t size = (size_t)sc_stride * sc_h; + int fd; + struct wl_shm_pool *pool = make_pool(size, &fd); + if (!pool) { sc_note("shm-fail"); sc_failed = true; return; } + sc_map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (sc_map == MAP_FAILED) { + sc_map = NULL; + close(fd); + wl_shm_pool_destroy(pool); + sc_note("mmap-fail"); + sc_failed = true; + return; + } + struct wl_buffer *buf = wl_shm_pool_create_buffer(pool, 0, (int32_t)sc_w, + (int32_t)sc_h, + (int32_t)sc_stride, + sc_fmt); + wl_shm_pool_destroy(pool); + sc_frame = ext_image_copy_capture_session_v1_create_frame(sc_session); + ext_image_copy_capture_frame_v1_add_listener(sc_frame, &sc_frame_listener, NULL); + ext_image_copy_capture_frame_v1_attach_buffer(sc_frame, buf); + ext_image_copy_capture_frame_v1_damage_buffer(sc_frame, 0, 0, + (int32_t)sc_w, (int32_t)sc_h); + ext_image_copy_capture_frame_v1_capture(sc_frame); +} + static void screencopy_run(void) { display = wl_display_connect(NULL); if (!display) { @@ -1656,17 +1714,23 @@ static void screencopy_run(void) { struct wl_registry *reg = wl_display_get_registry(display); wl_registry_add_listener(reg, ®istry_listener, NULL); wl_display_roundtrip(display); - if (!sc_mgr || !wl_output) { + if (!sc_mgr || !sc_out_mgr || !wl_output) { fprintf(stderr, "wltest: screencopy: global not advertised\n"); exit(1); } /* The test window (the red target) is spawned separately and fills the output; capture the whole output. */ - sc_frame = zwlr_screencopy_manager_v1_capture_output(sc_mgr, 0, wl_output); - zwlr_screencopy_frame_v1_add_listener(sc_frame, &sc_listener, NULL); + sc_source = ext_output_image_capture_source_manager_v1_create_source( + sc_out_mgr, wl_output); + sc_session = ext_image_copy_capture_manager_v1_create_session(sc_mgr, + sc_source, 0); + ext_image_copy_capture_session_v1_add_listener(sc_session, + &sc_session_listener, NULL); for (;;) { if (wl_display_dispatch(display) < 0) break; + if (sc_have_constraints && !sc_frame) + sc_start_capture(); if (sc_ready || sc_failed) break; } diff --git a/wlr-protocols/wlr-screencopy-unstable-v1.xml b/wlr-protocols/wlr-screencopy-unstable-v1.xml deleted file mode 100644 index 50b1b7d..0000000 --- a/wlr-protocols/wlr-screencopy-unstable-v1.xml +++ /dev/null @@ -1,232 +0,0 @@ - - - - Copyright © 2018 Simon Ser - Copyright © 2019 Andri Yngvason - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice (including the next - paragraph) shall be included in all copies or substantial portions of the - Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - - - - This protocol allows clients to ask the compositor to copy part of the - screen content to a client buffer. - - Warning! The protocol described in this file is experimental and - backward incompatible changes may be made. Backward compatible changes - may be added together with the corresponding interface version bump. - Backward incompatible changes are done by bumping the version number in - the protocol and interface names and resetting the interface version. - Once the protocol is to be declared stable, the 'z' prefix and the - version number in the protocol and interface names are removed and the - interface version number is reset. - - - - - This object is a manager which offers requests to start capturing from a - source. - - - - - Capture the next frame of an entire output. - - - - - - - - - Capture the next frame of an output's region. - - The region is given in output logical coordinates, see - xdg_output.logical_size. The region will be clipped to the output's - extents. - - - - - - - - - - - - - All objects created by the manager will still remain valid, until their - appropriate destroy request has been called. - - - - - - - This object represents a single frame. - - When created, a series of buffer events will be sent, each representing a - supported buffer type. The "buffer_done" event is sent afterwards to - indicate that all supported buffer types have been enumerated. The client - will then be able to send a "copy" request. If the capture is successful, - the compositor will send a "flags" followed by a "ready" event. - - For objects version 2 or lower, wl_shm buffers are always supported, ie. - the "buffer" event is guaranteed to be sent. - - If the capture failed, the "failed" event is sent. This can happen anytime - before the "ready" event. - - Once either a "ready" or a "failed" event is received, the client should - destroy the frame. - - - - - Provides information about wl_shm buffer parameters that need to be - used for this frame. This event is sent once after the frame is created - if wl_shm buffers are supported. - - - - - - - - - - Copy the frame to the supplied buffer. The buffer must have a the - correct size, see zwlr_screencopy_frame_v1.buffer and - zwlr_screencopy_frame_v1.linux_dmabuf. The buffer needs to have a - supported format. - - If the frame is successfully copied, a "flags" and a "ready" events are - sent. Otherwise, a "failed" event is sent. - - - - - - - - - - - - - - - - Provides flags about the frame. This event is sent once before the - "ready" event. - - - - - - - Called as soon as the frame is copied, indicating it is available - for reading. This event includes the time at which presentation happened - at. - - The timestamp is expressed as tv_sec_hi, tv_sec_lo, tv_nsec triples, - each component being an unsigned 32-bit value. Whole seconds are in - tv_sec which is a 64-bit value combined from tv_sec_hi and tv_sec_lo, - and the additional fractional part in tv_nsec as nanoseconds. Hence, - for valid timestamps tv_nsec must be in [0, 999999999]. The seconds part - may have an arbitrary offset at start. - - After receiving this event, the client should destroy the object. - - - - - - - - - This event indicates that the attempted frame copy has failed. - - After receiving this event, the client should destroy the object. - - - - - - Destroys the frame. This request can be sent at any time by the client. - - - - - - - Same as copy, except it waits until there is damage to copy. - - - - - - - This event is sent right before the ready event when copy_with_damage is - requested. It may be generated multiple times for each copy_with_damage - request. - - The arguments describe a box around an area that has changed since the - last copy request that was derived from the current screencopy manager - instance. - - The union of all regions received between the call to copy_with_damage - and a ready event is the total damage since the prior ready event. - - - - - - - - - - - Provides information about linux-dmabuf buffer parameters that need to - be used for this frame. This event is sent once after the frame is - created if linux-dmabuf buffers are supported. - - - - - - - - - This event is sent once after all buffer events have been sent. - - The client should proceed to create a buffer of one of the supported - types, and send a "copy" request. - - - -