* Slider: `show_value`, hide tooltip on button press [skip ci] * DashInterface, DashInterfaceEmulated * `display_list`, `add_display` views (wip) [skip ci] * `add_display::View` done * `display_options::View` done * `process_list::View` done * Merge remote-tracking branch 'origin/main' into next-dash-interface [skip ci] * tooltip wrap, clippy [skip ci] * App launcher [skip ci] * toast_manager: fix delay, add vulkan feat [skip ci] * smithay deps egl → vk * rewrite built-in wayland compositor egl → vulkan * move `add_display::View` -> `add_window::View` & `display_options::View` -> `window_options::VIew`, remove displays logic and replace it with window ones [skip ci] * Merge remote-tracking branch 'origin/wlvk' into next-dash-interface [skip ci] * when is maybeuninit not a bad idea? * wayland_server: make frame callbacks, release buffers. logging * wayvrctl process-launch args fix * wayland_server: fix mouse * `game_list::View` (wip) [skip ci] * `~/.cache/` IO [skip ci] * HTTP client, game cover art fetcher, game list image display, use `smol::LocalExecutor` for async runtime * wayvr overlay removal * WayVRData → WayVRState in the RefCell * rearrange deps, add dash * add back regex for build * [skip ci] refactor dash? * remove RcFrontend & RcLayout [skip ci] * todo in wrong place * enjoy dashboard in vr * Placeholder cover arts [skip ci] * fix DashFrontend not updating [skip ci] * fix animations, fix SlotMap dirty widget panic, set gui scale, set dash to 1080p [skip ci] * wgui to use srgb * fix srgb in uidev mode, tweak colors a bit [skip ci] * dash-frontend: Detect and switch to WiVRn speakers [skip ci] * Game launcher (wip), wgui refactor [skip ci] * get rid of wayvr refcell * clippy * use freedesktop instead of gtk * glob-based icon discovery but very slow * background app entry finder * cached image loading * cached image loading: auto cleanup * app entry cache build log level * bump freedesktop to include flatpak search paths * Nice Word Wrap™ for apps.xml * overhaul desktop finder * Game launcher (fully functional) * app_launcher: fix exec label * ShouldRender::Should if mouse moved * generics + DashInterface impl (#334) * fix uidev build * make apps think that they are fullscreen * fix cage * implement xdg_popup support * RadioBox & RadioGroup * AppLauncher radio boxes * app launcher res & orientation functionality * fix scaling * fix wrong default for res_mode * typo * separator placement * poc window decorations * move audio system to wlx-common, compress audio data, sample player * dash and wgui sounds * decor mouse fix * decor improvements * battery percentage sign ("%") in watch * update decor.xml, fix max_size * decor mouse hover & leave * decor window close * fallback identicons * wayvr window size from res. remove decor tooltips * wip: add bar to keyboard * bar design * tweak ui, clippy, modify desktop finder blacklist * do not keep startup sound in memory * tweak watch ui, load application list gradually (prevent lag) * bar functionality * tooltip raw text, inline translation fallback support * bar app icons & tooltips * bar dropdown backend logic * fix wayvrctl * fmt * bar: dash button * add ::OverlayReset * add ::CustomOverlayReload * bring back ToggleDashboard keybind support * wgui: windowing: `close_if_clicked_outside` support, context menus * ticking context menu * on_custom_attribs Box → Rc * context menu custom attribs * dash-frontend: application list grouping * checkbox sounds, app launch sounds * settings implementation * fix uidev build * batteries: hide % if more than 3 devices * ::OverlayToggle to not reset overlay on show * update lang * settings ui changes * fallback fonts * remove old gh actions * app categories * fix set_stereo * pass template_params to context_menu * refactor context_menu to only require parser_state on tick * working bar context menus + kbd downsize * fix hidden overlays all popping up after restart * context to use release → press; cleanups * list helpers * watch rework * reverse sets_on_watch * settings tab buttons; autorestart * tweak keycaps * fix bar doing out of date on keymap change * settings saving * fix context menus, reload-from-disk * fix force close not force closing * burger menu + fix crash after removing set * dropdown for capture_method + random tweaks * support _format on clock time label (#344) use _display as format string directly remove log message update docs * more useful parser warnings + cleanups * reduce warings, xml fixes * keyboard middle click setting; docs, readme & logs * app autostart * implement spawn positioning * rearrange settings * update lang, update description.txt * sort json * Monado app switcher, lang update * Update Monado IPC, display brightness slider * fmt * zwlr_screencopy v3 support * remove wayvr feature * fix features --------- Co-authored-by: galister <22305755+galister@users.noreply.github.com> Co-authored-by: Tayou <git@tayou.org>
WlxOverlay-S
A lightweight OpenXR/OpenVR overlay for Wayland and X11 desktops, inspired by XSOverlay.
WlxOverlay-S lets you to access your desktop screens while in VR.
In comparison to similar overlays, WlxOverlay-S aims to run alongside VR games and experiences while having as little performance impact as possible. The UI appearance and rendering techniques are kept as simple and efficient as possible, while still allowing a high degree of customizability.
Join the Linux VR Community
We are available on either Discord or Matrix space:
Questions/issues specific to WlxOverlay-S will be handled in the wlxoverlay chat room. Feel free to ask anything.
Setup
Installation
There are multiple ways to install WlxOverlay-S:
- AppImage: Download from Releases
- AUR package: wlx-overlay-s-git
- Homebrew:
- Add AtomicXR tap:
brew tap matrixfurry.com/atomicxr https://tangled.sh/@matrixfurry.com/homebrew-atomicxr - Install WlxOverlay-S:
brew install wlx-overlay-s
General Setup
- Start Monado, WiVRn or SteamVR.
- Run the overlay
Note: If you are using Monado or WiVRn, no additional setup steps are required for Flatpak Steam compatibility—most people use WlxOverlay-S seamlessly with Monado/WiVRn.
SteamVR via Steam Flatpak
For users specifically running SteamVR via Steam Flatpak, follow these steps:
- Grab the latest AppImage from Releases.
WlxOverlay-S-*.AppImage --appimage-extractchmod +x squashfs-root/AppRun- Move the newly created
squashfs-rootfolder to a location accessible by the Steam Flatpak. flatpak override com.valvesoftware.Steam --user --filesystem=xdg-run/pipewire-0/:rw- Restart Steam.
- Start SteamVR.
flatpak run --command='/path/to/squashfs-root/AppRun' com.valvesoftware.Steam
First Start
When the screen share pop-up appears, check your notifications or the terminal and select the screens in the order it requests.
In case screens were selected in the wrong order:
- Go to Settings and press
Clear PipeWire tokensand thenRestart software - Pay attention to your notifications, it tells you in which order to pick the screens.
- If notifications don't show, try start Wlx from the terminal and look for instructions in there.
WiVRn users: Select WlxOverlay-S from the Application drop-down. If there's no such entry, select Custom and browse to your WlxOverlay-S executable or AppImage.
Envision users: Go to the Plugins menu and select the WlxOverlay-S plugin. This will download and run the AppImage version of the overlay.
In order to run a standalone installation (for instance from the AUR), create a bash script containing wlx-overlay-s --openxr --show and then set this bash script as a custom Envision plugin.
This will show a home environment with headset passthrough by default or a customizable background!
SteamVR users: WlxOverlay-S will register itself for auto-start, so there is no need to start it every time. Disclaimer: SteamVR will sometimes disregard this and not start Wlx anyway.
Please continue reading the guide below.
Getting Started
Working Set
The working set consists of all currently selected overlays; screens, mirrors, keyboard, etc.
The working set appears in front of the headset when shown, and can be re-centered by hiding and showing again.
Show and hide the working set using:
- Non-vive controller: double-tap B or Y on the left controller.
- Vive controller: double-tap the menu button on the left controller (for SteamVR, the
showhidebinding must be bound)
See the bindings section on how to grab, move and resize overlay windows.
Pointer Modes AKA Laser Colors
Much of the functionality in WlxOverlay-S depends on what color of laser is used to interact with a UI element.
Using the default settings, there are 3 modes:
- Regular Mode: Blue laser
- Right-click Mode: Orange laser
- Middle-click Mode: Purple laser
Please see the bindings section below on how to activate these modes.
The guide here uses the colors for ease of getting started.
The watch
Check your left wrist for the watch. The watch is the primary tool for controlling the app.
The top of the watch shows device batteries, and the bottom shows your overlay controls.
Enter edit mode (leftmost button on bottom) to edit your overlay sets.
While in edit mode, the watch can also be grabbed, and passed between your hands.
After grabbing, the watch will automatically attach to the hand that's opposite from the one that held it.
In edit mode, try hovering other overlays to see their advanced options!
The screens
Hovering a pointer over a screen will move the mouse. If there are more than one pointers hovering a screen, the pointer that was last used to click will take precedence.
The click type depends on the laser color:
- Blue laser: Left click
- Orange laser: Right click
- Purple laser: Middle click
- Stick up/down: Scroll wheel
The keyboard
The keyboard is fully customizable via the keyboard.yaml file.
Download it into the ~/.config/wlxoverlay/ folder and edit it to your liking.
Typing
- Use the BLUE laser when typing regularly.
- While using ORANGE laser, all keystrokes will have SHIFT applied.
- Purple laser is customizable via the
keyboard.yaml'salt_modifiersettings.
Modifier Keys are sticky. They will remain pressed until a non-modifier key is pressed, the modifier gets toggled off, or the keyboard gets hidden.
Default Bindings
To customize bindings on OpenXR, refer to the OpenXR Bindings wiki page.
If your bindings are not supported, please reach out.
We would like to work with you and include additional bindings.
Troubleshooting
When an error is detected, we often print tips for fixing into the log file.
Logs will be at /tmp/wlx.log for most distros.
Check here for tips.
Known Issues
Mouse is not where it should be
If the mouse is moving on a completely different screen, the screens were likely selected in the wrong order:
- Go to Settings and press
Clear PipeWire tokensand thenRestart software - Pay attention to your notifications, it tells you in which order to pick the screens.
- If notifications don't show, try start Wlx from the terminal and look for instructions in there.
COSMIC destkop:
- Due to limitations with COSMIC, the mouse can only move on a single display.
X11 users:
- Might be dealing with a Phantom Monitor.
- DPI scaling is not supported and will mess with the mouse.
- Upright screens are not supported and will mess with the mouse.
Screens are blank or black or frozen on Steam Link
As of SteamVR version 2.14.x, PipeWire capture no longer works when using Steam Link.
We're unable to completely troubleshoot how and why Steam Link interferes with PipeWire, so consider the following workarounds for the time being:
- Use another streamer, such as WiVRn or ALVR
- If your desktop supports ScreenCopy, go to Settings and set
Wayland capture methodtoScreenCopy - If your desktop has an X11 mode, try using that
Modifiers get stuck
Hiding the keyboard will un-press all of its buttons. Alternatively, go to Settings and use the Restart software button.
X11 limitations
- X11 capture can generally seem slow. This is because zero-copy GPU capture is not supported on the general X11 desktop. Consider trying Wayland.
- DPI scaling is not supported and may cause the mouse to not follow the laser properly.
- Upright screens are not supported and can cause the mouse to not follow the laser properly.
- Screen changes (connecting / disconnecting a display, resolution changes, etc) are not handled at runtime. Restart the overlay for these to take effect.



