{"id":24761567,"url":"https://github.com/ferdi265/wl-mirror","last_synced_at":"2025-05-16T07:05:39.021Z","repository":{"id":46943003,"uuid":"426827755","full_name":"Ferdi265/wl-mirror","owner":"Ferdi265","description":"a simple Wayland output mirror client","archived":false,"fork":false,"pushed_at":"2025-04-24T10:19:05.000Z","size":431,"stargazers_count":374,"open_issues_count":16,"forks_count":14,"subscribers_count":11,"default_branch":"main","last_synced_at":"2025-04-24T10:43:41.220Z","etag":null,"topics":["c","cmake","opengl","wayland","wayland-client","wlroots"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Ferdi265.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-11-11T01:03:44.000Z","updated_at":"2025-04-24T10:22:12.000Z","dependencies_parsed_at":"2023-11-08T02:35:47.561Z","dependency_job_id":"3ab59f03-0de1-453f-9bce-48885cc3dca8","html_url":"https://github.com/Ferdi265/wl-mirror","commit_stats":{"total_commits":164,"total_committers":3,"mean_commits":"54.666666666666664","dds":"0.012195121951219523","last_synced_commit":"be671e36d8f1c50acef7ab6b85c559d9c81f719e"},"previous_names":[],"tags_count":43,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ferdi265%2Fwl-mirror","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ferdi265%2Fwl-mirror/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ferdi265%2Fwl-mirror/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ferdi265%2Fwl-mirror/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Ferdi265","download_url":"https://codeload.github.com/Ferdi265/wl-mirror/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254485062,"owners_count":22078767,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","cmake","opengl","wayland","wayland-client","wlroots"],"created_at":"2025-01-28T19:18:05.501Z","updated_at":"2025-05-16T07:05:33.995Z","avatar_url":"https://github.com/Ferdi265.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `wl-mirror` - a simple Wayland output mirror client\n\n`wl-mirror` attempts to provide a solution to sway's lack of output mirroring\nby mirroring an output onto a client surface.\n\n## Features\n\n- Mirror an output onto a resizable window\n- Mirror an output onto another output by fullscreening the window\n- Reacts to changes in output scale (including fractional scaling)\n- Preserves aspect ratio\n- Corrects for flipped or rotated outputs\n- Supports custom flips or rotations\n- Supports mirroring custom regions of outputs\n- Supports receiving additional options on stdin for changing the mirrored\n  screen or region on the fly (works best when used with [pipectl](https://github.com/Ferdi265/pipectl))\n\n![demo screenshot](https://user-images.githubusercontent.com/4077106/141605347-37ba690c-f885-422a-93a6-81d5a48bee13.png)\n\n## Usage\n\n```\nusage: wl-mirror [options] \u003coutput\u003e\n\noptions:\n  -h,   --help                  show this help\n  -V,   --version               print version\n  -v,   --verbose               enable debug logging\n        --no-verbose            disable debug logging (default)\n  -c,   --show-cursor           show the cursor on the mirrored screen (default)\n        --no-show-cursor        don't show the cursor on the mirrored screen\n  -i,   --invert-colors         invert colors in the mirrored screen\n        --no-invert-colors      don't invert colors in the mirrored screen (default)\n  -f,   --freeze                freeze the current image on the screen\n        --unfreeze              resume the screen capture after a freeze\n        --toggle-freeze         toggle freeze state of screen capture\n  -F,   --fullscreen            display wl-mirror as fullscreen\n        --no-fullscreen         display wl-mirror as a window (default)\n        --fullscreen-output O   set fullscreen target output to output O, implies --fullscreen\n        --no-fullscreen-output  unset fullscreen target output, implies --no-fullscreen (default)\n  -s f, --scaling fit           scale to fit (default)\n  -s c, --scaling cover         scale to cover, cropping if needed\n  -s e, --scaling exact         only scale to exact multiples of the output size\n  -s l, --scaling linear        use linear scaling (default)\n  -s n, --scaling nearest       use nearest neighbor scaling\n  -b B  --backend B             use a specific backend for capturing the screen\n  -t T, --transform T           apply custom transform T\n  -r R, --region R              capture custom region R\n        --no-region             capture the entire output (default)\n  -S,   --stream                accept a stream of additional options on stdin\n        --title N               specify a custom title N for the mirror window\n\nbackends:\n  - auto                automatically try the backends in order of efficiency and use the first that works (default)\n  - export-dmabuf       use the wlr-export-dmabuf-unstable-v1 protocol to capture outputs\n  - screencopy          use the wlr-screencopy-unstable-v1 protocol to capture outputs (auto)\n  - screencopy-dmabuf   use the wlr-screencopy-unstable-v1 protocol to capture outputs (via DMA-BUF)\n  - screencopy-shm      use the wlr-screencopy-unstable-v1 protocol to capture outputs (via SHM)\n  - extcopy             use the ext-image-copy-capture-v1 protocol to capture outputs (auto)\n  - extcopy-dmabuf      use the ext-image-copy-capture-v1 protocol to capture outputs (via DMA-BUF)\n  - extcopy-shm         use the ext-image-copy-capture-v1 protocol to capture outputs (via SHM)\n\ntransforms:\n  transforms are specified as a dash-separated list of flips followed by a rotation\n  flips are applied before rotations\n  - normal                         no transformation\n  - flipX, flipY                   flip the X or Y coordinate\n  - 0cw,  90cw,  180cw,  270cw     apply a clockwise rotation\n  - 0ccw, 90ccw, 180ccw, 270ccw    apply a counter-clockwise rotation\n  the following transformation options are provided for compatibility with sway output transforms\n  - flipped                        flip the X coordinate\n  - 0,    90,    180,    270       apply a clockwise rotation\n\nregions:\n  regions are specified in the format used by the slurp utility\n  - '\u003cx\u003e,\u003cy\u003e \u003cwidth\u003ex\u003cheight\u003e [output]'\n  on start, the region is translated into output coordinates\n  when the output moves, the captured region moves with it\n  when a region is specified, the \u003coutput\u003e argument is optional\n\nstream mode:\n  in stream mode, wl-mirror interprets lines on stdin as additional command line options\n  - arguments can be quoted with single or double quotes, but every argument must be fully\n    quoted or fully unquoted\n  - unquoted arguments are split on whitespace\n  - no escape sequences are implemented\n\ntitle placeholders:\n  the title string supports the following placeholders:\n  - {width}, {height}:               size of the mirrored area\n  - {x}, {y}:                        offsets on the screen\n  - {target_width}, {target_height}\n    {target_output}:                 info about the mirrored device\n  a few perhaps useful examples:\n    --title='Wayland Mirror Output {target_output}'\n    --title='{target_output}:{width}x{height}+{x}+{y}'\n    --title='resize set {width} {height} move position {x} {y}'\n```\n\nThe [`scripts/`](scripts/) folder contains examples on how `wl-mirror` can be used.\n\n- [`wl-present`](scripts/wl-present) is a small script to demonstrate the use\n  of the `-S` option to interactively present on Sway.  \n  This script is especially useful when binding the `wl-present` subcommands to\n  keyboard shortcuts. See example below.\n- [`release.sh`](scripts/release.sh) Generates a release tar ball for the\n  currently checked out commit if there's a release tag on it.\n\n### Sway Keybindings Example\n\nThe following keybindings shortcuts can be used in your sway config.\n\n```\nmode \"present\" {\n    # command starts mirroring\n    bindsym m mode \"default\"; exec wl-present mirror\n    # these commands modify an already running mirroring window\n    bindsym o mode \"default\"; exec wl-present set-output\n    bindsym r mode \"default\"; exec wl-present set-region\n    bindsym Shift+r mode \"default\"; exec wl-present unset-region\n    bindsym s mode \"default\"; exec wl-present set-scaling\n    bindsym f mode \"default\"; exec wl-present toggle-freeze\n    bindsym c mode \"default\"; exec wl-present custom\n\n    # return to default mode\n    bindsym Return mode \"default\"\n    bindsym Escape mode \"default\"\n}\nbindsym $mod+p mode \"present\"\n```\n\nThis requires `wl-mirror`, the `wl-present` script, `pipectl` (optional),\nslurp, and one of `wofi`, `wmenu`, `rofi`, or `dmenu`. \n\nNote that wl-present only allows one instance by default, but multiple\ninstances can be used at the same time using the `--name` option or\n`WL_PRESENT_PIPE_NAME` environment variable.\n\n### Kanshi Configuration Example\n\nThe following [kanshi](https://git.sr.ht/~emersion/kanshi) profile will launch\nwl-mirror in fullscreen on an external output mirroring your internal output\nwhen switched to with `kanshictl switch mirror-hdmi` or when selected\nautomatically.\n\n```\nprofile mirror-hdmi {\n    output eDP-1 enable mode 1920x1080 position 0,0\n    output HDMI-A-1 enable mode 1920x1080 position 1920,0\n    exec wl-present mirror eDP-1 --fullscreen-output HDMI-A-1 --fullscreen\n\n    # alternatively, for wl-mirror \u003c 0.16.4\n    # exec wl-present mirror eDP-1 \u0026 sleep .5; wl-present fullscreen-output HDMI-A-1; wl-present fullscreen\n}\n```\n\n## Installation\n\n`wl-mirror` is already packaged in many distros and can be installed via the\npackage manager:\n\n[![Packaging Status](https://repology.org/badge/vertical-allrepos/wl-mirror.svg?columns=3)](https://repology.org/project/wl-mirror/versions)\n\n## Supported Wayland Compositors\n\n`wl-mirror` should work on all Wayland compositors based on wlroots, such as\nsway or hyprland, as well as compositors that implement the standard\n`ext-image-copy-capture-v1` protocol.\n\n`wl-mirror` currently does not work on KDE and Gnome, due to `wl-mirror` not\nsupporting the XDG Desktop Portal screen sharing protocol. This is being worked\non (see issues [#16](https://github.com/Ferdi265/wl-mirror/issues/16) and\n[#17](https://github.com/Ferdi265/wl-mirror/issues/17)).\n\n## Dependencies\n\n- `CMake`\n- `pkg-config`\n- `libwayland-client`\n- `libwayland-egl`\n- `libEGL`\n- `libGLESv2`\n- `epoll-shim` (on systems that do not have `epoll`, e.g. FreeBSD)\n- `libdecor` (see `WITH_LIBDECOR`)\n- `libgbm` (see `WITH_GBM`)\n- `libdrm` (see `WITH_GBM`)\n- `wayland-scanner`\n- `scdoc` (for manual pages, see `INSTALL_DOCUMENTATION`)\n\n## Script Dependencies\n\n- `pipectl` (optional for `scripts/wl-present`)\n- `slurp` (`scripts/wl-present`)\n- `wofi`, `wmenu`, `rofi` or `dmenu` (`scripts/wl-present`)\n\n## Building\n\n- Install Dependencies\n- Clone Submodules (`git submodule update --init`)\n- Run `cmake -B build`\n- Run `cmake --build build`\n\n## CMake Options\n\n- `INSTALL_EXAMPLE_SCRIPTS`: also install example scripts (default `OFF`)\n- `INSTALL_DOCUMENTATION`: also build and install manual pages (default `OFF`)\n- `WITH_LIBDECOR`: build with libdecor for window decoration (default `OFF`)\n- `WITH_GBM`: build with GBM and libdrm for DMA-BUF allocation (default `OFF`)\n- `FORCE_WAYLAND_SCANNER_PATH`: always use the provided path for wayland-scanner, do not use pkg-config (default empty)\n- `FORCE_SYSTEM_WL_PROTOCOLS`: always use system-installed wayland-protocols, do not use submodules (default `OFF`)\n- `FORCE_SYSTEM_WLR_PROTOCOLS`: always use system-installed wlr-protocols, do not use submodules (default `OFF`)\n- `WL_PROTOCOL_DIR`: directory where system-installed wayland-protocols are located (default `/usr/share/wayland-protocols`)\n- `WLR_PROTOCOL_DIR`: directory where system-installed wlr-protocols are located (default `/usr/share/wlr-protocols`)\n\n## Files\n\n- `src/main.c`: main entrypoint\n- `src/options.c`: CLI and stream option parsing\n- `src/wayland.c`: Wayland and `xdg_surface` boilerplate\n- `src/wayland/shm.c`: Wayland SHM buffer allocation\n- `src/wayland/dmabuf.c`: GBM DMA-BUF buffer allocation\n- `src/egl.c`: EGL boilerplate\n- `src/egl/shm.c`: EGL SHM buffer import\n- `src/egl/dmabuf.c`: EGL DMA-BUF buffer import\n- `src/mirror.c`: output mirroring code\n- `src/mirror-export-dmabuf.c`: wlr-export-dmabuf-unstable-v1 backend code\n- `src/mirror-screencopy.c`: wlr-screencopy-unstable-v1 backend code\n- `src/mirror-extcopy.c`: ext-image-copy-capture-v1 backend code\n- `src/transform.c`: matrix transformation code\n- `src/event.c`: event loop\n- `src/stream.c`: asynchronous option stream input\n\n## License\n\nThis project is licensed under the GNU GPL version 3.0 or later (SPDX\n[GPL-3.0-or-later](https://spdx.org/licenses/GPL-3.0-or-later.html)). The full\nlicense text can also be found in the [LICENSE](/LICENSE) file.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fferdi265%2Fwl-mirror","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fferdi265%2Fwl-mirror","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fferdi265%2Fwl-mirror/lists"}