Skip to content

Wayland drm multimonitor layout#351

Open
Rambomst wants to merge 17 commits into
Ylianst:masterfrom
Rambomst:wayland-drm-multimonitor-layout
Open

Wayland drm multimonitor layout#351
Rambomst wants to merge 17 commits into
Ylianst:masterfrom
Rambomst:wayland-drm-multimonitor-layout

Conversation

@Rambomst

@Rambomst Rambomst commented May 25, 2026

Copy link
Copy Markdown

This is an extension of #335.and Fixes Ylianst/MeshCentral#2719

What I have introduced on top of that PR:

Improve DRM Wayland KVM multi-monitor layout handling

Add multi-output DRM capture support and compose active scanout buffers
into a single logical desktop frame. When running under KWin, read the
session's logical output geometry and apply it to the DRM outputs so
capture and input coordinates follow the desktop monitor arrangement,
including scaled displays.

Also make verbose DRM/EGL diagnostics opt-in through MESH_KVM_DRM_DEBUG
to avoid repeated framebuffer logging during normal agent operation.

I also merged in the latest updated from master

Tested on:
EndevourOS with KDE Plasma - Local env
CatchyOS with KDE Plasma - Test VM

Disclaimer: I used an AI coding assistant during the development of these changes.

bmharper and others added 11 commits March 5, 2026 14:23
The Wayland support comes from changing the way input and output works:

1. Screen output is captured via DRM (Direct Rendering Manager)
2. Keyboard/Mouse input is injected via libevdev

Both of these methods are lower level than the previous X11 code,
so they're actually capable of becoming full replacements for the X11
mechanisms, should we ever want to do that.

I've tried to make the changes minimally invasive to the existing code,
instead of a big refactor into X11 vs DRM code paths.

Known issues:
1. Logging out back to the greeter breaks the screen scraping.
   This is fixable, just requires work to figure some things out.
2. Cursor state is not reflected in the screen output

To get the greeter working will require some more surgery. I haven't
figured out how all of that session stuff works yet, but it is possible.
It's largely just an issue of the system getting confused between
Wayland/X11 states. One quite simple solution could be that once we
detect Wayland, we remain in that state for the duration of the process
life. I'm not sure if people care about dynamic switching between X11
and Wayland during a single boot - and I suspect not, so I think this
would be a simple and robust solution to get the greeter working.

If cursor state is necessary, then I can look into that. It just hasn't
felt like a priority.

I don't consider this work 100% finished. We still need to get the
greeter working, and more testing/feedback. But if possible, I'd like
to get this on a public branch so that I can start getting feedback.

This work is sponsored by touchsource.com
This fixes a warning on modern compilers
Previously, we only worked on eg Ubuntu 24.04, where they still shipped
Xorg/X11. Without this change the agent does not advertise desktop
capability, and the "Desktop" tab in MeshCentral is unavailable.
This prevents us from switching back to X11 mode if we connect at the
greeter screen.

We may still be able to simplify the wayland detection to just the
seat0 read.
It was already in monitor-info.js
Aiming to find the reason why we're failing on i915
* The screen capture now resumes automatically after a blank screen
* Fixed leaking of framebuffer handle
* Fixed spurious noisy logs on nvidia capture due to changing handles
Unfortunately I haven't yet found a reliable universal way to detect
display rotation on wayland, so I'm adding an env var override, eg

For "portrait right":

MESH_KVM_ROTATION=270

By setting MESH_KVM_ROTATION to anything besides zero, we force the
treatment of the display as rotated by either 90,180,270 degrees.

I split it into it's own .c file, because I forsee this getting a bit
messy, having to support various compositors.
Add multi-output DRM capture support and compose active scanout buffers
into a single logical desktop frame. When running under KWin, read the
session's logical output geometry and apply it to the DRM outputs so
capture and input coordinates follow the desktop monitor arrangement,
including scaled displays.

Also make verbose DRM/EGL diagnostics opt-in through MESH_KVM_DRM_DEBUG
to avoid repeated framebuffer logging during normal agent operation.
…onitor-layout

# Conflicts:
#	meshcore/KVM/Linux/linux_kvm.c
Make Wayland client support mandatory for Linux KVM builds so release and CI
builds cannot silently omit the generic xdg-output monitor layout path. The DRM
backend now includes wayland-client directly, and the makefile fails early when
the wayland-client development package is unavailable.

This keeps Wayland monitor positioning and scaling behavior consistent between
build servers and deployed agents.
@Rambomst

Copy link
Copy Markdown
Author

I changed the monitor layout path to prefer the Wayland xdg-output protocol instead of relying only on KWin support-info.

The KWin path worked for KDE, but it made multi-monitor positioning/scaling KDE-specific. xdg-output is exposed by multiple Wayland compositors and provides the logical output position and scaled size we need to map DRM-captured frames into the same layout the desktop is using.

KWin support-info is still kept as a fallback if xdg-output is unavailable or cannot match every DRM connector, so KDE keeps the working path while non-KDE Wayland sessions get a compositor-neutral layout path as well.

@msegec

msegec commented Jun 3, 2026

Copy link
Copy Markdown

Tested on Bazzite/Fedora with KDE Plasma Wayland and two DisplayPort monitors, including fractional scaling.

PR #351 improves the important baseline issue for this setup: MeshAgent can run through the DRM/libevdev path instead of relying on Xwayland geometry. On my system the agent now starts with:

  • Using DRM/libevdev mode
  • MeshAgent: evdev virtual input device created successfully

That fixed the major pointer-offset problem caused by Xwayland exposing a physical/scaled virtual layout that did not match KDE's logical Wayland layout.

I also tested the MeshCentral multi-monitor selector goal: letting the server/viewer know this is a multi-monitor system so the user can choose all displays or one specific display.

For that, I needed an additional local patch on top of PR #351:

  • populate MeshAgent's existing g_monitors[] / g_monitor_count from the DRM/Wayland logical outputs
  • send MNG_KVM_DISPLAY_INFO in DRM mode instead of returning early
  • make MNG_KVM_GET_DISPLAYS advertise 65535 for all monitors plus 1..N for individual monitors
  • allow MNG_KVM_SET_DISPLAY in DRM mode instead of forcing display 0
  • when a single display is selected, crop the DRM capture to that output and report that output's resolution
  • keep evdev absolute input scaled against the full virtual desktop (VSCREEN_WIDTH / VSCREEN_HEIGHT) so clicks on non-origin monitors still land correctly

With those changes, MeshCentral exposes the normal monitor choices and I can select all monitors or an individual monitor, with control working on the selected display.

The key point: PR #351 fixed the Wayland/DRM coordinate path for this setup, but the extra local patch is what changed DRM mode from "single display 0" to the normal multi-monitor display-list behavior.

Populate the existing monitor list from DRM/Wayland logical outputs and
advertise the normal multi-monitor display list in DRM mode. Allow
MNG_KVM_SET_DISPLAY to select all monitors or an individual monitor,
crop DRM capture to the selected output, and keep evdev absolute input
mapped against the full virtual desktop so pointer control remains
correct across non-origin displays.
@Rambomst

Rambomst commented Jun 3, 2026

Copy link
Copy Markdown
Author

@msegec Thanks for testing this out and the detailed info on a way forward with the monitor selection. Those changes have been made and pushed. They appear to be working for me without any issues, I can select any of my 4 monitors or switch back to viewing all.

Tbh I had no idea this functionality even existed, I had to hunt down the UI in mesh central for it haha.

@si458

si458 commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

oh sorry my bad! can u fix conflict! i need to learn git properly at times!

@Rambomst

Rambomst commented Jun 4, 2026

Copy link
Copy Markdown
Author

@si458 The merge conflict has been resolved

@si458

si458 commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

@Rambomst unforutunately i still get this problem message when i click connect in the desktop tab
KVM child process has unexpectedly exited :(
Ubuntu 24.04 x64

EDIT: also randomly get this error too now?
image

@msegec

msegec commented Jun 9, 2026

Copy link
Copy Markdown

@Rambomst unforutunately i still get this problem message when i click connect in the desktop tab KVM child process has unexpectedly exited :( Ubuntu 24.04 x64

EDIT: also randomly get this error too now? image

Hi Simon,

Can you elaborate if it is just this one Ubuntu machine or many, or any other specifiic conditions such as multiple session connections etc, as I have not tested that yet. I literally solved the issue for my use case on Bazzite (Fedora based) and have not really pushed it elsewhere yet, was hoping the community etc could find parts useful from it and expand until its stable for full release.

Let me know if I can assist you in any way.

Mark

@si458

si458 commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

@msegec many ubuntu machines sadly, both VM and physicals.
what ive found is if ubuntu is on the login screen, you get KVM child process has unexpectedly exited
and when you login, use the machine, then wait for it to auto-lock, you then get the same error
so im not sure if its something to do with the lock screen maybe?

im happy for people to submit their PRs then i can piece them together haha

@msegec

msegec commented Jun 9, 2026

Copy link
Copy Markdown

@si458 oh that is quite funny, I have been kind of ignoring that problem for a while, and working around it with other 'things' but yes, I too have that issue - I will see what I can come up with... not much time at the moment, but hopefully by the weekend, if someone else does not.

@Rambomst

Rambomst commented Jun 9, 2026

Copy link
Copy Markdown
Author

I'm on holidays and will be back next week, I will admit I didn't test this at all on Ubuntu, will give it a go when I get back and work through those issues if no one else has come up with a fix.

Enable runtime loading of required libraries (libdrm, libEGL, and libGLESv2) using `dlopen` to allow the agent to function without a pre-installed GL/DRM stack. Refactor the makefile to remove hard library linking while retaining headers for build compatibility. Additionally, update Wayland integration to dynamically load libwayland-client and provide fallbacks for missing libraries.
@Rambomst

Rambomst commented Jun 13, 2026

Copy link
Copy Markdown
Author

@si458 @msegec I have pushed some changes that will hopefully resolve your issue.

Fixed the "KVM child process has unexpectedly exited" error, it was a libjpeg version mismatch (built against jpeg8 headers but linked the v62 lib). The makefile now auto-selects the matching turbojpeg so plain builds work.

Also switched the KVM graphics libs (libdrm/EGL/GLESv2/wayland) to load via dlopen instead of being hard-linked, so the agent still starts on hosts without them and KVM just disables itself when they're missing.

Introduce logic to nudge sleeping displays (DPMS) awake during DRM desktop layout calculations and retry within a timeout. Enhance KVM pipe cleanup by canceling timers and broken-pipe handlers to prevent errors from delayed memory access. Define `KVM_DRM_DISPLAY_WAKE_TIMEOUT_MS` and implement `kvm_events_evdev_wake` for pointer-based wake functionality.
@Rambomst

Copy link
Copy Markdown
Author

Two more Wayland/DRM KVM fixes.

Made remote desktop wake the screens on connect. Before, connecting while they were asleep just failed, since there's no active scanout to capture, now it should nudge them awake through the virtual input device and retries for a few seconds instead of giving up.

Also fixed a crash on reconnect where tearing down a session could free the KVM pipe while a delayed "child unexpectedly exited" message was still queued against it, so it fired on freed memory. Now it cancels that timer before freeing the pipe.

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.

Wayland Capturing

4 participants