Skip to content

wayland: add --wayland-display option - #18523

Open
hadrien-f wants to merge 2 commits into
mpv-player:masterfrom
hadrien-f:wayland-display
Open

hadrien-f wants to merge 2 commits into
mpv-player:masterfrom
hadrien-f:wayland-display

Conversation

@hadrien-f

Copy link
Copy Markdown

Hello,

I tried to work around Wayland embedding in libmpv not being possible (#9654).
The use case is Jellyfin Desktop HDR playback on Linux: libmpv with vo=gpu-next runs in-process behind a Wayland proxy.

One solution is to proxy mpv's Wayland connection through a private socket served by the app, and turn mpv's toplevel into a subsurface of the app's window.
The only way to point mpv at that socket today is to change WAYLAND_DISPLAY for the whole process. That also redirects the host toolkit (Qt reconnects with wl_display_connect(NULL) after a compositor restart) and every child process.
WAYLAND_SOCKET is not good for this: it's one-shot, and mpv connects more than once (clipboard, VO re-creation).

This change adds an option --wayland-display=<name>: a socket name relative to XDG_RUNTIME_DIR or an absolute path, like WAYLAND_DISPLAY. When unset or empty, nothing changes.

  • The VO and the Wayland clipboard backend connect to it, and neither requires WAYLAND_DISPLAY/WAYLAND_SOCKET when it is set, including while probing VOs.
  • The X11 clipboard backend treats it as a Wayland environment, like WAYLAND_DISPLAY.
  • WAYLAND_SOCKET still takes precedence, since wl_display_connect() ignores the name when it is set. The VO warns when both are set.
  • Changing it at runtime reconnects the clipboard (UPDATE_CLIPBOARD). The VO uses the new value the next time it is created.

AI disclosure

Written with Claude Opus 5.5 (claude-opus-5-5) in Claude Code. I reviewed every change and checked the behaviour myself. I also read the code, but I am not an expert.

Testing

Automated: Claude created its own scripts (not included in this PR; I can share them or add them to the PR). 10 cases on two headless weston compositors all pass; on master, the ones using the option fail. Claude also checked on KWin with an HDR output: gpu-next/waylandvk through the option picks VK_COLOR_SPACE_HDR10_ST2084_EXT.

Manually, on GNOME 46, with a nested weston (weston --backend=wayland --socket=nested) running as a window on the desktop and WAYLAND_DISPLAY=wayland-0 (the real desktop):

  • Without the option, the video opens as a normal window on the desktop.
  • With --wayland-display=nested, it opens inside the nested weston window. The verbose log shows Connecting to Wayland display: nested, and the clipboard connects there too.
  • With WAYLAND_DISPLAY unset and --wayland-display=nested, it still opens in weston.
  • set wayland-display wayland-0 at runtime leaves the video in weston (it applies on the next VO creation) and reconnects the clipboard.
  • mpv built from master rejects the option.

Applications that embed mpv on Wayland cannot parent mpv's surface under
their own, so one way to embed it is to proxy mpv's Wayland connection
through a private socket and turn its toplevel into a subsurface. Today
the only way to point mpv at such a socket is to change WAYLAND_DISPLAY
for the whole process, which also redirects the host toolkit (e.g. when
Qt reconnects after a compositor restart) and every child process.

Add --wayland-display to name the display the VO connects to. When it
is set, the VO no longer requires WAYLAND_DISPLAY or WAYLAND_SOCKET to
be set while probing. WAYLAND_SOCKET still takes precedence, as
wl_display_connect() ignores the name when it is set, so warn about it.
The Wayland clipboard backend opens its own connection at player start.
Pass --wayland-display to it, so that all of mpv's Wayland connections
go to the same display, and skip the environment check when it is set.
Also treat the option as a Wayland environment in the X11 backend, so it
doesn't fall back to an X11 clipboard when the Wayland one fails.

Mark the option UPDATE_CLIPBOARD so changing it at runtime reconnects
the clipboard.
@llyyr

llyyr commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Why does this need to exist? Changing WAYLAND_DISPLAY passed to mpv should have the exact same effect.

That also redirects the host toolkit

You can set it only for mpv no?

@hadrien-f

Copy link
Copy Markdown
Author

Thanks for the quick reading.
The intent is to improve hdr media playing inside jellyfin.
Currently jellyfin uses libmpv in-process and vo=libmpv so hdr content is tone-mapped to sdr.
I am trying to make a version that uses libmpv --vo=gpu-next and embed its window but --wid doesn't exist on wayland.

To do this I would introduce a fake compositor, libmpv would render in a specific display "jellyfin-mpv", and the fake compositor forwards its window to the main compositor inside the Qt window.

The issue is that Jellyfin has one process for both Qt and libmpv, all share the same environment.
The Qt interface of jellyfin should render to the main compositor "wayland-0".

So if I change WAYLAND_DISPLAY for libmpv, Qt also uses it when it reconnects after a compositor restart, and so do processes jellyfin starts: they all end up on the fake compositor.
A workaround is to change WAYLAND_DISPLAY briefly, then restore it but this timing-based solution is fragile.

With an option string it would make that solution for hdr much stronger.

Setting WAYLAND_DISPLAY only for libmpv would need to run mpv as a separate process and rewrite jellyfin PlayerComponent that integrates the player, but it would not be compatible with the normal SDR path vo=libmpv.

Do you think I could have chosen a better approach ?

@llyyr

llyyr commented Sep 26, 2026

Copy link
Copy Markdown
Contributor

Setting WAYLAND_DISPLAY only for libmpv would need to run mpv as a separate process and rewrite jellyfin PlayerComponent that integrates the player, but it would not be compatible with the normal SDR path vo=libmpv.

Note that it's not only HDR that's better with gpu-next. It just has better color management in general, even for non-HDR videos. Rewriting jellyfin to run mpv as a separate process all the time would indeed be better, but whether this can be merged in its current state or not is upto maintainers.

Have you also considered wl-proxy to embed mpv instead? https://github.com/MutsumiUniverse/Mutsumi achieves this use case the best out of all the similar projects I've seen

@mahkoh

mahkoh commented Sep 26, 2026

Copy link
Copy Markdown
Contributor

A workaround is to change WAYLAND_DISPLAY briefly, then restore it but this timing-based solution is fragile.

You can change the environment after fork and before exec.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants