ci / rust (push) Failing after 2m31s
ci / docs-site (push) Successful in 1m22s
ci / web (push) Successful in 1m48s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 1m1s
ci / rust-arm64 (push) Successful in 2m2s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 11s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 9s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 9s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
docker / builders-arm64cross (push) Successful in 20s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Canceled after 36s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Canceled after 36s
docker / deploy-docs (push) Canceled after 0s
~1150 feat/fix commits landed since v0.19 and the docs drifted badly. This is a full sweep of every page against the code as shipped: ~280 verified corrections, nine new pages, and one deletion. The worst of what was wrong: the quickstart's five-minute path could not work (`serve` never started the web console, so step 3 had no PIN to read); every packaged Linux host runs `serve --gamestream` while security.md told readers to leave GameStream off; HDR was documented as Windows-only; `PUNKTFUNK_SECURE_DDA` was documented as a working knob that nothing reads; `PUNKTFUNK_INPUT_BACKEND` listed a `uinput` value that does not exist and named libei for KDE instead of kwin; README linked three pages deleted on 2026-07-05; and the rpm-ostree update command pointed at a script no package installs. Completeness: about half of what shipped since v0.19 had no page at all. New: support-matrix (what works where, from 217 verified capability cells), input (mouse/touch/pen — and the in-stream chords, so the docs finally say how to get your mouse back), client-settings, profiles-and-links, game-library, clipboard, wake-on-lan, hdr, uninstall. Updating existed but had zero inbound links. status.md is gone: its facts moved into the support matrix, its shell stays as a redirect so the public URL does not 404. roadmap.md is themes now, not a feature checklist — checkboxes are what rotted. Debian is no longer claimed. The .deb's Depends resolve against Ubuntu images, nothing in CI builds or tests Debian, and Debian 12 is below the glibc 2.39 floor. The `debian` in the repo URL is the package format. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
176 lines
9.1 KiB
Markdown
176 lines
9.1 KiB
Markdown
---
|
|
title: Shared clipboard
|
|
description: Copy on one machine and paste on the other — the two switches that have to be on, what actually crosses, and why the toggle does nothing when only one of them is flipped.
|
|
---
|
|
|
|
Punktfunk can share the clipboard between the machine you are sitting at and the host you are
|
|
streaming. Copy a URL on your laptop, paste it into a browser on the host. Copy an error message on
|
|
the host, paste it into a chat app on your laptop.
|
|
|
|
**Two separate switches have to be on:**
|
|
|
|
1. The **host** operator has to allow it, with a line in `host.env` and a host restart. This one is
|
|
off by default.
|
|
2. **You** have to turn it on for that one host, in that host's edit sheet on your client. This one
|
|
is off by default on the macOS, Windows and Linux clients — but **on by default on Android**.
|
|
|
|
Flipping one and not the other looks exactly like the feature not existing. So check both.
|
|
|
|
## 1. Allow it on the host
|
|
|
|
Add a `PUNKTFUNK_CLIPBOARD` line to the host's `host.env` — `~/.config/punktfunk/host.env` on
|
|
Linux, `%ProgramData%\punktfunk\host.env` on Windows.
|
|
|
|
```ini
|
|
PUNKTFUNK_CLIPBOARD=on
|
|
```
|
|
|
|
The accepted values:
|
|
|
|
| Value | Effect |
|
|
|---|---|
|
|
| unset, empty, `0`, `off`, `false` | **Off (the default).** The host never advertises the clipboard capability and never accepts a clipboard transfer. |
|
|
| `text-only`, `no-files`, `text` | On for text, HTML, rich text and images. File transfer is refused. |
|
|
| `on`, `1` | On, and file transfer is permitted by policy. |
|
|
|
|
Values are trimmed and compared case-insensitively. **Anything the host doesn't recognise is
|
|
treated as `on`** — a typo like `PUNKTFUNK_CLIPBOARD=yes` or `no-file` enables the permissive
|
|
policy rather than failing, so check the spelling if you meant `text-only`.
|
|
|
|
The file is only read at startup, so restart the host. On Linux:
|
|
|
|
```bash
|
|
systemctl --user restart punktfunk-host
|
|
```
|
|
|
|
On Windows, from an Administrator prompt:
|
|
|
|
```powershell
|
|
punktfunk-host service restart
|
|
```
|
|
|
|
See [Configuration](/docs/configuration) for the rest of `host.env`.
|
|
|
|
> **About the file mode.** No client shipping today asks for file transfer, and no host clipboard
|
|
> backend offers file formats yet. `on` and `text-only` therefore behave the same in practice —
|
|
> `text-only` is how you make that explicit and keep it that way.
|
|
|
|
## 2. Turn it on for that host, in your client
|
|
|
|
The client switch is **per saved host**, not global: handing a machine your clipboard is a decision
|
|
about *that* machine. You set it in the host's edit sheet, and it is deliberately not something a
|
|
[settings profile can carry](/docs/profiles-and-links#what-a-profile-cant-change).
|
|
|
|
| Client | Where the switch is | Label | Default |
|
|
|---|---|---|---|
|
|
| macOS | Host card menu → **Edit…** | **Share clipboard with this host** | Off |
|
|
| Windows | Host tile menu → **Edit…** | **Share clipboard with this host** | Off |
|
|
| Linux (GTK) | Host card menu → **Edit…** | **Share clipboard** | Off |
|
|
| Android (touch) | Host card menu → **Edit…** | **Shared clipboard** | **On** |
|
|
|
|
On Android the switch is only in the touch edit dialog. The controller/TV interface — what you get
|
|
on Android TV, and on a phone when a controller is attached — has its own **Edit Host** screen with
|
|
no clipboard row, so there is nowhere to change it there. It stays on, which is the Android default.
|
|
|
|
The setting is read when a session starts, so if you change it while streaming, reconnect.
|
|
|
|
macOS can also flip it mid-session: **Stream ▸ Share Clipboard** (⌃⌥⇧C), which becomes **Stop
|
|
Sharing Clipboard** once the host has acknowledged it.
|
|
|
|
iOS, iPadOS, tvOS and the Steam Deck Decky plugin have no clipboard switch — see
|
|
[what each client does](#which-hosts-and-clients-support-it) below.
|
|
|
|
## Nothing crosses until something pastes
|
|
|
|
A copy costs nothing. When you copy, your machine announces only the **list of formats** it now
|
|
holds — no bytes. The bytes are pulled across on a separate transfer, and only when an application
|
|
on the other end actually pastes. Copying a large image and never pasting it transfers nothing.
|
|
|
|
That holds for everything you copy on your own machine, and for both directions on the host. It
|
|
does **not** hold for a host copy arriving at a Windows or Android client: those two fetch the
|
|
content straight away and put it on your local clipboard, whether or not you ever paste. On Windows
|
|
that is because the lazy path needs Windows delayed rendering, which the client doesn't implement
|
|
yet; on Android there is no way to satisfy a paste from the network at all. The macOS client is
|
|
lazy in both directions.
|
|
|
|
A single transfer is capped at 64 MiB. Nothing else limits size, so a very large host-side copy can
|
|
cross to a Windows or Android client for a paste that never happens.
|
|
|
|
What you copy on the **macOS or Windows client** is filtered for secrets: content marked
|
|
`org.nspasteboard.ConcealedType` or `org.nspasteboard.TransientType` on macOS, or
|
|
`ExcludeClipboardContentFromMonitorProcessing` on Windows — what password managers set — is never
|
|
announced and never served. That check exists only in those two clients. The Android client has no
|
|
equivalent, and neither does the host, so a password copied **on the host** is announced to your
|
|
client like anything else.
|
|
|
|
The clipboard rides the native Punktfunk protocol's control channel, so it only exists in sessions
|
|
from a Punktfunk client. A Moonlight client has no clipboard.
|
|
|
|
## Which hosts and clients support it
|
|
|
|
**Hosts.** The host runs on Linux and Windows, and both have a clipboard backend — but on Linux it
|
|
depends on the desktop session.
|
|
|
|
On Linux the host needs one of two mechanisms in the session it is streaming:
|
|
|
|
- `ext-data-control-v1` — KWin, wlroots/Sway and Hyprland. Tried first.
|
|
- GNOME's own `org.gnome.Mutter.RemoteDesktop.Session` clipboard, used directly. Tried second.
|
|
|
|
The older `zwlr-data-control-unstable-v1` is **not** implemented, so a compositor that offers only
|
|
that has no backend. Neither does a [gamescope](/docs/gamescope) session.
|
|
|
|
On Windows the host uses the Win32 clipboard, with delayed rendering so your content is only read
|
|
when a host application pastes.
|
|
|
|
**Clients**, and what each one actually moves:
|
|
|
|
| Client | What crosses |
|
|
|---|---|
|
|
| macOS | Plain text, rich text (RTF), HTML, and PNG, JPEG and GIF images |
|
|
| Windows | Plain text, and PNG images |
|
|
| Android, Android TV | **Plain text only** |
|
|
| Linux (GTK), Steam Deck | Nothing yet — see below |
|
|
| iOS, iPadOS, tvOS | Not implemented |
|
|
|
|
The **Linux client has the switch but no working clipboard bridge**: it enables the plane and then
|
|
has no code to read or write the desktop's own clipboard, so nothing is announced and nothing is
|
|
pasted. Turning it on there is harmless but has no effect today. The Decky plugin on the Steam Deck
|
|
has no switch at all.
|
|
|
|
When you copy **on the Windows client**, images cross only if the copying application publishes the
|
|
registered `PNG` clipboard format. Many Windows apps publish only a bitmap, and those copies aren't
|
|
announced yet. The other direction is fine: an image copied on the host reaches the Windows client
|
|
either way.
|
|
|
|
The host side is richer than any client: it can offer and accept text, HTML, RTF, PNG, JPEG and
|
|
GIF. What you get is therefore whatever your client supports.
|
|
|
|
## Why the toggle does nothing (or is greyed out)
|
|
|
|
On macOS, **Stream ▸ Share Clipboard** is greyed out whenever you are not streaming, or the
|
|
connected host did not advertise a clipboard. On the other clients there is nothing to grey out —
|
|
the per-host switch always looks available, and a host that can't do it simply does nothing. Work
|
|
through these in order:
|
|
|
|
- **The host has it off.** The default. Nothing was added to `host.env`, or the value is `off`,
|
|
`0`, `false` or empty. Fix it with step 1 above.
|
|
- **`host.env` was edited but the host wasn't restarted.** The file is read once, at startup.
|
|
- **The switch is off for this host in your client.** It is per saved host, and off by default
|
|
everywhere except Android. Check the host's **Edit…** sheet — step 2 above.
|
|
- **The host's session has no supported backend.** The host allows the clipboard, so it still
|
|
advertises the capability, but it has nothing to read the desktop's clipboard with. This is a
|
|
gamescope session, a compositor with only the old `zwlr-data-control-unstable-v1`, or a GNOME
|
|
session whose Mutter doesn't expose the direct RemoteDesktop clipboard. Nothing on screen tells
|
|
you this apart — the host log does.
|
|
- **The host is older than the feature.** A host from before clipboard sync never advertises it.
|
|
- **Your client doesn't implement it** — Linux, Steam Deck, iOS, iPadOS or tvOS. Nothing crosses
|
|
regardless of what the host allows.
|
|
- **You changed the switch while connected.** Reconnect, or use ⌃⌥⇧C on macOS.
|
|
- **The copy was a secret, or a format nobody handles.** Concealed content is skipped on purpose on
|
|
the macOS and Windows clients, and an image copied on Windows as a bare bitmap isn't announced.
|
|
|
|
Still stuck? The host log records what it decided on each session — a `clipboard control` line with
|
|
the resolved state, and a `clipboard backend unavailable` line when the session had nothing to bind
|
|
to. That is the fastest way to tell "off by policy" from "no backend" — see
|
|
[Troubleshooting](/docs/troubleshooting).
|