Skip to content

fix(linux): Add optional wlroots (wlr-virtual-pointer) backend for mouse input#4972

Open
Cm4nXD wants to merge 3 commits intoLizardByte:masterfrom
Cm4nXD:wlr-virtual-input
Open

fix(linux): Add optional wlroots (wlr-virtual-pointer) backend for mouse input#4972
Cm4nXD wants to merge 3 commits intoLizardByte:masterfrom
Cm4nXD:wlr-virtual-input

Conversation

@Cm4nXD
Copy link
Copy Markdown

@Cm4nXD Cm4nXD commented Apr 11, 2026

Description

This PR introduces an optional wlroots-based input backend for mouse events, allowing Sunshine to forward pointer input using the wlr-virtual-pointer protocol instead of the existing uinput path.

This is implemented as a runtime toggle, preserving full backward compatibility with the current behavior.
The primary motivation for this change is to support nested Wayland compositors, specifically:

Running a nested Sway session inside Gamescope (SteamOS GameMode)
Using a headless/virtual output to render secondary content (e.g., Wii U gamepad view from Cemu)
Streaming that headless output via Sunshine to a Moonlight client

In this configuration, the existing uinput backend causes incorrect behavior:

Input events are injected at the system level
The host compositor (Gamescope) receives the events
Gamescope is unaware of the nested compositor's virtual outputs
As a result, mouse input is mapped to the wrong display

By contrast, using wlr-virtual-pointer:

Injects input directly into the target Wayland compositor (Sway)
Allows proper interaction with headless / virtual outputs
Ensures mouse input maps correctly to the streamed surface

Currently this doesn't map keyboard inputs, but it does map to just the selected display using create_virtual_pointer_with_output, but I'd be willing to try.

I've worked very hard, and am perfectly willing to make any adjustments needed to implement this feature! I've never contributed to an open source project or tried to tackle anything even remotely this complicated before as far as coding. 😅
I did use AI to help me, if I hadn't I'm not sure I could even have attempted this. But I did test it on my system, and filmed a demo showing it in action.

Screenshot

Issues Fixed or Closed

I'm not sure....

Roadmap Issues

I'm not sure

Type of Change

  • feat: New feature (non-breaking change which adds functionality)
  • fix: Bug fix (non-breaking change which fixes an issue)
  • docs: Documentation only changes
  • style: Changes that do not affect the meaning of the code (white-space, formatting, missing semicolons, etc.)
  • refactor: Code change that neither fixes a bug nor adds a feature
  • perf: Code change that improves performance
  • test: Adding missing tests or correcting existing tests
  • build: Changes that affect the build system or external dependencies
  • ci: Changes to CI configuration files and scripts
  • chore: Other changes that don't modify src or test files
  • revert: Reverts a previous commit
  • BREAKING CHANGE: Introduces a breaking change (can be combined with any type above)

Checklist

  • Code follows the style guidelines of this project
  • Code has been self-reviewed
  • Code has been commented, particularly in hard-to-understand areas
  • Code docstring/documentation-blocks for new or existing methods/components have been added or updated
  • Unit tests have been added or updated for any new or modified functionality

AI Usage

  • None: No AI tools were used in creating this PR
  • Light: AI provided minor assistance (formatting, simple suggestions)
  • Moderate: AI helped with code generation or debugging specific parts
  • Heavy: AI generated most or all of the code changes
output.mp4

Christian Maxwell and others added 3 commits April 8, 2026 12:27
Adds a configurable alternative to uinput for mouse input on Wayland.
When enabled, mouse movement, buttons, and scroll are injected via the
zwlr_virtual_pointer_v1 Wayland protocol instead of /dev/uinput.

- Generate wlr-virtual-pointer-unstable-v1 bindings via wayland-scanner
- New wl_mouse.h / wl_mouse.cpp implement the Wayland virtual pointer
- input_raw_t initialises and owns the wl_mouse state when enabled
- Each platf::mouse:: function routes through wl_mouse when active
- config::input.wlr_virtual_mouse (default: false) controls the toggle
- Linux-only checkbox added to the web UI Inputs tab
- Locale strings added to all 22 locale files

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use create_virtual_pointer_with_output() so that motion_absolute
coordinates are interpreted in the captured output's local coordinate
frame rather than the full global compositor space. Previously, without
an output binding, absolute mouse events were mapped across all monitors
in the compositor layout, causing inputs to split across the real and
headless virtual displays in a nested sway session.

The output is selected using the same index as config::video.capture so
the input and capture sides always refer to the same physical output.
Falls back to the unbound creation path if no wl_output globals are
discovered.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Cm4nXD Cm4nXD changed the title Add optional wlroots (wlr-virtual-pointer) backend for mouse input (toggleable alternative to uinput) fix/feat: Add optional wlroots (wlr-virtual-pointer) backend for mouse input (toggleable alternative to uinput) Apr 11, 2026
@Cm4nXD Cm4nXD changed the title fix/feat: Add optional wlroots (wlr-virtual-pointer) backend for mouse input (toggleable alternative to uinput) fix/feat(linux): Add optional wlroots (wlr-virtual-pointer) backend for mouse input (toggleable alternative to uinput) Apr 11, 2026
@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
5 New issues
5 New Code Smells (required ≤ 0)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@ReenigneArcher ReenigneArcher changed the title fix/feat(linux): Add optional wlroots (wlr-virtual-pointer) backend for mouse input (toggleable alternative to uinput) fix(linux): Add optional wlroots (wlr-virtual-pointer) backend for mouse input Apr 11, 2026
@ReenigneArcher ReenigneArcher added the ai PR has signs of heavy ai usage (either indicated by user or assumed) label Apr 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai PR has signs of heavy ai usage (either indicated by user or assumed)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants