Skip to content

Add support for Wayland on Linux#335

Open
bmharper wants to merge 9 commits intoYlianst:masterfrom
bmharper:wayland
Open

Add support for Wayland on Linux#335
bmharper wants to merge 9 commits intoYlianst:masterfrom
bmharper:wayland

Conversation

@bmharper
Copy link
Copy Markdown

@bmharper bmharper commented Mar 5, 2026

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

Fixes #115 Ylianst/MeshCentral#2719

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
@si458
Copy link
Copy Markdown
Collaborator

si458 commented Mar 5, 2026

@bmharper omg thank you so much! ❤️
i will do some building/testing here!
have you done a build yourself and is it as simple as using a new agent and the server side just works (web ui)?

@bmharper
Copy link
Copy Markdown
Author

bmharper commented Mar 5, 2026

Awesome, will be great to get some testing help!
And yes, it builds the same way it used to (eg make linux ARCHID=6 JPEGVER=v80 -j8 for ubuntu x64), and it's purely a question of replacing the agent binary. No changes to the server.

@DaanSelen
Copy link
Copy Markdown

Wow! This is amazing, did you code this all by yourself? AMAZING!

@si458
Copy link
Copy Markdown
Collaborator

si458 commented Mar 5, 2026

@bmharper ok great ill build and test here,
BTW, we building using make linux ARCHID=6 -j8 ?
also have u tested it works with arm64? (pi 4/5)

@bmharper
Copy link
Copy Markdown
Author

bmharper commented Mar 5, 2026

I haven't tested on arm/pi, but will do that now.

@bmharper
Copy link
Copy Markdown
Author

bmharper commented Mar 5, 2026

Wow! This is amazing, did you code this all by yourself? AMAZING!

I have been writing C/C++ for 30 years, but Codex 5.3 certainly had a hand in the implementation here.

@si458
Copy link
Copy Markdown
Collaborator

si458 commented Mar 5, 2026

@bmharper i dont mind PRs that are AI helped,
so long as people are honest and say i know x,y,z but ive no bloody clue on a,b,c so i asked AI to help me!

@bmharper
Copy link
Copy Markdown
Author

bmharper commented Mar 5, 2026

@bmharper i dont mind PRs that are AI helped, so long as people are honest and say i know x,y,z but ive no bloody clue on a,b,c so i asked AI to help me!

I think most projects will get left behind with a strict "no AI" policy. Ultimately, we just have to judge the work on its merits.

@bmharper
Copy link
Copy Markdown
Author

bmharper commented Mar 5, 2026

I see this is not working on a Pi5 running Ubuntu 25.10.
Will ping back here once I've got that working.

@si458
Copy link
Copy Markdown
Collaborator

si458 commented Mar 5, 2026

@bmharper well i am gob smacked! give your AI a pat on the back from me 👏 it works!
image

EDIT:
@bmharper whenever my device turns the screen off (not pc sleep, just monitor sleep), then i move the mouse in the web ui, i get a message Active CRTC has no framebuff� until i physically mouse the mouse/keyboard on the device to wake the monitor up, then the desktop access works again,
so defo more issues need fixing first!

@bmharper
Copy link
Copy Markdown
Author

bmharper commented Mar 5, 2026

@si458 Thanks for that - I'll get that fixed, and also make sure that logging back out the greeter works.

@edlins
Copy link
Copy Markdown

edlins commented Mar 6, 2026

Sorry guys, I'm having a little trouble compiling and installing on Ubuntu 26 - not getting the Desktop tab. Server version 1.1.44. Is there a docker build or a dependency list? Or just post the linux x86_64 build somewhere? Thanks for any help.

@bmharper
Copy link
Copy Markdown
Author

bmharper commented Mar 6, 2026

@edlins I've discovered a problem on 25.10 and upwards, due to the fact that XOrg/X11 is no longer available there. I have something working on 25.10 - will add it to this PR when it's ready

bmharper added 3 commits March 6, 2026 08:28
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.
Comment thread microscript/ILibDuktape_Polyfills.c
It was already in monitor-info.js
@bmharper
Copy link
Copy Markdown
Author

bmharper commented Mar 6, 2026

@edlins Give it another try on ubuntu 26.04 with the latest commits.
To build on Ubuntu, I'm using just this: make linux ARCHID=6
And to prepare the machine for building, I do this:
sudo apt-get install libx11-dev libxtst-dev libxext-dev libjpeg62-dev libegl1-mesa-dev libdrm-dev pkg-config build-essential
And then to test it running as a service, I create this systemd service in /etc/systemd/system/meshagent.service

[Unit]
Description=MeshCentral Agent
After=network-online.target graphical.target
Wants=network-online.target

[Service]
Type=simple
WorkingDirectory=/home/user1
ExecStart=/home/user1/meshagent_x86-64
Restart=always
RestartSec=10

[Install]
WantedBy=graphical.target

And then systemctl daemon-reload
systemctl enable meshagent
reboot

There are still issues with the agent dying if one disconnects and reconnects at certain times. I'm using the wrong UID for setuid.. but this should be a fairly minor thing to fix.

Also, I still haven't fixed the blank screen disconnect issue that @si458 brought up.

@si458
Copy link
Copy Markdown
Collaborator

si458 commented Mar 6, 2026

@bmharper dont worry about it! just keep at it! we have all the time in the world as its a community project after all!
we wont merge it until we are 110% sure everything works and is correct!

@edlins
Copy link
Copy Markdown

edlins commented Mar 6, 2026

For clean consistent builds,

docker build -t meshagent .
docker create --name meshagentbuild meshagent
docker cp meshagentbuild:/meshagent_x86-64 .
docker rm meshagentbuild
FROM ubuntu:26.04

RUN apt-get update

RUN apt-get install -y \
    libx11-dev \
    libxtst-dev \
    libxext-dev \
    libjpeg62-dev \
    libegl1-mesa-dev \
    libdrm-dev pkg-config \
    build-essential

COPY . /

RUN make clean && make linux ARCHID=6 JPEGVER=v80

CMD [ "/meshagent_x86-64", "-info" ]

I can stop the mesh agent service, add disableUpdate=1 to meshagent.msh, copy meshagent_x86-64 over the existing meshagent binary and run it by hand with sudo ./meshagent. Then I can see it online in the server, and there is a desktop tab, but when I connect it says connected but is just a black screen.

Agent says

Connecting to: wss://...
Connected.
Server verified meshcore...  Launching meshcore...
Using DRM/libevdev mode
MeshAgent: evdev virtual input device created successfully

Console says

uncaughtException1: Error: timers.onElapsed() callback handler on '()'  => waitExit() aborted because thread is exiting

I also tried without the JPEGVER arg and got the same result. You can add this dockerfile to the repo if it's useful. Do you have any other ideas to try?

Oh, and terminal and files are working fine.

@edlins
Copy link
Copy Markdown

edlins commented Mar 6, 2026

Okay, I got it working. The keys were

Dockerfile:

  • FROM ubuntu:26.04
  • RUN make clean && make linux ARCHID=6

/etc/default/grub:

  • GRUB_CMDLINE_LINUX_DEFAULT="quiet splash i915.force_probe=!46d4 xe.force_probe=46d4"

It did not work under the default i915 driver on an Alder Lake-N GPU. It worked with the newer xe driver.

00:02.0 VGA compatible controller: Intel Corporation Alder Lake-N [Intel Graphics]
        Kernel driver in use: xe
        Kernel modules: i915, xe
Screenshot from 2026-03-06 15-33-21

This is awesome!!

@edlins
Copy link
Copy Markdown

edlins commented Mar 6, 2026

Bug: Rotate the display to portrait right and the mesh desktop doesn't realign to vertical, and the mouse input is rotated 90 degrees so it appears in a different place in mesh vs on the device. X11 desktops would rotate in mesh so you would see portrait right in a vertical orientation. Currently it shows portrait right in landscape.

bmharper added 3 commits March 9, 2026 07:31
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.
@bmharper
Copy link
Copy Markdown
Author

bmharper commented Mar 9, 2026

@si458 I've added a fix for the screen blank issue (if I understand correctly - it's when the screen goes into blank/power saving mode). The KVM session should automatically resume.

@edlins I've added more logging, to try help figure out why the i915 driver doesn't work - let me know what MeshAgent spits out.

Also, I've implemented support for rotated screens, but I have not yet found a universal way of detecting this under Wayland, so at present the only way to get it to work, is with an env var, eg:

# for portrait right
MESH_KVM_ROTATION=270

Rotation support looks like it's going to need platform-specific code, so I'll make it work on ubuntu 26 first, and then we can add support for other platforms as they appear.

@si458 si458 mentioned this pull request Mar 9, 2026
@edlins
Copy link
Copy Markdown

edlins commented Mar 9, 2026

@si458 I've added a fix for the screen blank issue (if I understand correctly - it's when the screen goes into blank/power saving mode). The KVM session should automatically resume.

@edlins I've added more logging, to try help figure out why the i915 driver doesn't work - let me know what MeshAgent spits out.

ProcessCommand(31522)
Using DRM/libevdev mode
MeshAgent: evdev virtual input device created successfully
DRM: Selected output HDMI-A-2 on /dev/dri/card1 (connector=395 crtc=148 index=0)

I confirmed the port is correct. The behavior is that desktop says connected, the input works (mouse at least), but the mesh desktop screen stays black. This could just be ancient i915 not properly supporting newer Alder Lake-N graphics.

Also, I've implemented support for rotated screens, but I have not yet found a universal way of detecting this under Wayland, so at present the only way to get it to work, is with an env var, eg:

# for portrait right
MESH_KVM_ROTATION=270

Rotation support looks like it's going to need platform-specific code, so I'll make it work on ubuntu 26 first, and then we can add support for other platforms as they appear.

Yeah, seems that orientation is completely handled by the compositor and there's nothing in the Wayland protocol to consistently fetch it across compositors. Anyhow, I set my system to portrait right and set the env var to 90 and it was upside down. I've noticed there's a quirk in Gnome where "portrait right" rotates the output CCW 90 degrees which seems the opposite of what it should do. I think what "portrait right" means in Gnome is "after applying this setting you have to rotate your monitor to the right (90 degrees CW). I'll bet there were fist fights over that..

I'm documenting additional issues that may have nothing to do with your work.

It seems that when I build new agents they don't update the commit info seen with -info, but they do show the compile datetime. They are different filesizes and I got the new functionality.

Some connections don't establish for like 60s after an agent restart, or randomly, not sure.

Warning for testers - I switched from default i915 to xe and it worked great I switched back to i915 for some testing, and switched back to xe again but I seem to have hosed up my system. I'm getting a ton of xe errors with a black screen and a mouse pointer.. If I get back into working xe I'll test the screen blanking fix.

@si458
Copy link
Copy Markdown
Collaborator

si458 commented May 5, 2026

@bmharper can you fix the conflict at all please?
this was my bad as i merged the multiple monitor support for x11 which then broke this PR
going to try do more testing next week for this!

@si458 si458 linked an issue May 5, 2026 that may be closed by this pull request
@patrezp
Copy link
Copy Markdown

patrezp commented May 5, 2026

I tried this today on my Acer laptop
CachyOS / Plasma Wayland / amdgpu HawkPoint1 [1002:1900]
Input works via libevdev.
DRM selected eDP-1 on /dev/dri/card1.
GETCRTC and GETFB2 succeed continuously.
Desktop view is black. Not coming up even after multiple connect/disconnect
No DRM ioctl failures except harmless /dev/dri/card0 ENOENT.

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.

Linux Wayland support Wayland Capturing

5 participants