Linux - dekay/vpinball-wiki GitHub Wiki
Help Needed
Do you run VPinball on Linux? We’d love to hear your experience and tips!
Table of Contents
Running VPinball Under Wayland
The Problem With Wayland
Running VPinball under pure Wayland can be a frustrating experience because the placement of multiple windows across multiple screens that is critical for our purposes is not allowed. Trying to run VPinball under Wayland often results in windows that are piled on top of each other on a single screen despite how you've configured them in the LiveUI. Things get worse when you add VPinFE to the mix, as the additional windows increase the chance of something messing up. Making matters worse is the issue of window focus: the right window needs focus at the right times to access input events from keyboards and controllers.
If Wayland won't allow the window placement capability we need, we need to use a Window Manager that works around the problem. Let's look at our options:
- Gnome's Mutter Window Manager doesn't support window placement rules. Running VPinball under pure Wayland is not going to be a good time. Gnome also doesn't include the automatic taskbar hiding out of the box that we'd like to have.
- Sway is a tiling window manager and Wayland compositor, not a full desktop environment. Rules can be written in Sway to manage the placement of windows on specific screens and positions, but most people will probably find Sway to be too bare-bones for their purposes. Hyprland is similar but perhaps even more challenging for inexperienced users.
- KDE's KWin Window Manager does support window placement rules, does support taskbar hiding out of the box, and does support automatic cursor hiding to boot. It also supports a wide range of window focus options that we'll need to get everything running smoothly, is easy to use, very popular, and well supported. The icing on the cake is that KDE offers an edge across many games and graphics workloads vs Gnome both on AMD and on NVidia.
The Problem With Everything Other Than Wayland
If we don't take the Wayland route, we've got two other mainstream choices: X11 and XWayland.
X11 had a great run but its days are numbered. Gnome has already dropped X11 support and KDE has plans to do so in the future. Support for X11 is winding down and the bugs are piling up. Batocera still depends on X11 but even it will have to transition off of it sometime down the road.
XWayland essentially offers a bridge between X11 and Wayland. It is an X server that runs under Wayland and provides compatibility for native X11 applications that are yet to provide Wayland support. However, window placement isn't guaranteed to work when using XWayland either: apps can make a request for screen and position placement but those requests may not be honored. Your mileage may vary. Another strike against XWayland is that lag may be double that of X11, pure Wayland or even Windows.
Given all this, let's future proof ourselves and develop a couple of solid high-performance solutions: one for KDE and then one for Sway.
Setting Up Window Rules and Window Focus in KDE
KDE supports "Window Rules" available within System Settings that allows absolute positioning of any given window across one or more screens. The rules also support KDE's Kwin window manager concept of layers that have the order of priority shown below. Desktop has lowest priority and Overlay the highest. This gives more fine-grained control than another rule for "Keep above / below other windows"

We will demonstrate by example how to setup VPinFE + VPinball on a two screen pincab with a 4K (3840x2160) Playfield configured as the Primary display and a 16:10 (2560x1600) Backglass display on the right. KDE's Display Configuration window ends up looking like this.

There are some really important things to take note of here:
- The Playfield display is designated as the Primary Display in the normal non-rotated orientation, putting the Taskbar running along the side of the cabinet. You will be tempted to rotate the display 90 degrees so the Desktop displays normally when you stand in front of the cab. Resist This Temptation for a number of reasons
- VPinFE assumes this orientation and things can get messed up otherwise. The GUI option that lets you choose the orientation doesn't in fact to that much.
- VPX works best in this orientation when Cabinet Mode is selected in the LiveUI. It will automatically rotate the Playfield for you so it displays properly (on most tables anyway), it will properly size the LiveUI text in this orientation, etc.
- The Backglass display is to the right of the Playfield and the tops of the two are aligned.
Click the "Edit Arrangement" button to move the screens around as necessary to match this layout. If you have a third display for the DMD, place it on the right of the Backglass display with its top lined up with the other two.
Now it is time to set up the two windows that will appear on the playfield. Create two new Window Rules to match the two images shown below. Be sure to click the "Apply" button as each rule is added. Note the following:
- The Window titles
VPinFE TableandVisual Pinball Playerare as named by the application themselves. You cannot give these any names you want. What you can do is name theDescriptionfield whatever you like. - Both windows have a rule to
Forcethem to0 x 0. This corresponds to the bottom corner of the Primary (Playfield) display. - VPinFEs Player is on the
Normallayer and the VPX Playfield is one higher atAbove. When a table is selected in VPinFE, the VPX playfield will automatically appear over top of the VPinFE window.


That takes care of the Playfield displays. Next it's the Backglass. Note the following:
- The Window titles
VPinFE BG,Visual Pinball Backglass, andVisual Pinball Score View(note the space inScore View) are again as named by the application themselves. You cannot give these any names you want but you can name theDescriptionfield whatever you like. - VPinFEs Backglass is on the
Normallayer, VPX Backglass is one higher atAbove, and Score View is highest atNotification. - The Position of the two Backglasses is set to
Forceat3840 x 0. In other words position these two windows just past the right edge of the Playfield's3840 x 2160display to the Backglass monitor. Adjust this parameter to match your monitor resolution. - I found it necessary to force the Size of the VPinFE Backglass to match the
2560 x 1600resolution of my monitor or else it would sometimes be too large. I didn't find this necessary for the VPX Backglass but the option is there for you if necessary to do so. - The absolute Position of the Score View display is pushed further to the right and most of the way down the screen at
4608 x 1244. The Score View can be sized to whatever you like in the LiveUI. I have it set to a 4:1 ratio of1024 x 256. The Positionyvalue moves the Score View well down the Backglass screen where it looks good. The Positionxvalue of4608centers the Score View on the Backglass based on this bit of math for the displays used:
Score View Starting X = Playfield width + Backglass Width / 2 - Score View Width / 2
Score View Starting X = 3840 + 2560 / 2 - 1024 / 2 = 4608



That's it for the Window rules. Note how this approach can be easily scaled to a three screen setup for a DMD.
- The DMD would be arranged to align with top right corner of the Backglass display, just like the Backglass is arranged to the top right corner of the Playfield display.
- The VPin FE DMD would be placed on the Normal layer at
x = 3840 + 2560 = 6400, y = 0and the Score View would be offset something like
Score View Starting X = Playfield width + Backglass Width + DMD Width / 2 - Score View Width / 2
The last part of this is getting the Window Focus correct. The issue is that VPinFE and VPX Playfield windows pop in and out of existence depending on what's going on. If VPX starts and its Playfield doesn't get focus, VPinball will put the window in a Paused state until it does get focus. The only way to get around this seems to configure KDE to use Focus under mouse. KDE warns you against this option as shown below, but no other option reliably works. The downside to this approach is, as noted by the KDE warning, that Alt-Tab won't work. If you really need this capability, you can always switch it to Focus follows mouse when you aren't playing pinball and switch it back when you are.

Setting Up Window Rules and Window Focus in Sway
While Sway is very barebones compared to KDE, it is attractive to somebody running a dedicated VPinball setup that wants to maximize the resources the host PC gives to the application. VPin creator @superhac has come up with a Sway script that does just this. The full script can be found at this Discord link. The relevant snippet for VPX is provided below. The idle portion of the configuration is included to help save your screen if you're running an OLED. Include this in your ~/.config/sway/config and edit it to your liking.
<snip the "Variables section that defines basic direction keys, terminal emulator, and app launcher>
...
# Example configuration:
#
# output HDMI-A-1 resolution 1920x1080 position 1920,0
#
# You can get the names of your outputs by running: swaymsg -t get_outputs
output DP-2 resolution 3840x2160 position 0 0
output DP-3 resolution 1920x1080 position 3840 0
output HDMI-A-1 resolution 1920x1080 position 5870 0
workspace 1 output DP-2
workspace 2 output DP-3
workspace 3 output HDMI-A-1
assign [title="^VPinFE DMD$"] 3
assign [title="^VPinFE BG$"] 2
assign [title="^VPinFE Table$"] 1
assign [title="^Visual Pinball Score View$"] 3
assign [title="^Visual Pinball Backglass$"] 2
assign [title="^Visual Pinball Player$"] 1
# turn off mouse auto focus
focus_follows_mouse no
# Auto-switch to it when it appears (aka Force Focus)
for_window [title="^Table Screen$"] focus
for_window [title="^Visual Pinball Player$"] focus
### Idle configuration
#
# Example configuration:
#
# exec swayidle -w \
# timeout 300 'swaylock -f -c 000000' \
# timeout 600 'swaymsg "output * power off"' resume 'swaymsg "output * power on"' \
# before-sleep 'swaylock -f -c 000000'
#
# This will lock your screen after 300 seconds of inactivity, then turn off
# your displays after another 300 seconds, and turn your screens back on when
# resumed. It will also lock your screen before your computer goes to sleep.
...
<snip other stuff including input configuration, key bindings, movement keys, workspaces & layout stuff, etc)
Note the following in the script above
- Sway treats the screens as a continuous set of pixels, similar to KDE. Screens are placed by pixel offset from the origin of the first screen rather than by screen number
- The Sway implementation has a mechanism that handles window focus but it works differently than KDE's. Sway forces focus to a new window when it appears vs. the KDE method that gives focus to the window on the highest layer under the mouse.
Setting Up Window Rules and Window Focus in Hyprland
Hyprland is similar to Sway in that it is a tiling window manager and not a full-fledged desktop environment. @patsoffice has come up with a way to run VPinball + VinFE on Hyprland running NixOS(!). This is the Discord announcement, the Readme is here, and the .nix config is here.
Troubleshooting
Can't Enable 4K60 on Samsung TVs
So you've built an awesome virtual pinball cabinet running Linux, your Nvidia GPU is connected to a Samsung 4K TV via HDMI, and:
- Linux only offers 1920x1080 @ 60Hz over HDMI
- If you manually force 4K, the screen says Out of Range
- Using an HDMI-to-DisplayPort adapter gives you 4K but only at 30Hz
- Everything works fine in Windows so the hardware is not broken
This happens because Samsung TVs ship with a setting called "HDMI UHD Color" that is OFF by default. When it is off, the TV advertises itself to every connected device — including your GPU — as an HDMI 1.4 device. HDMI 1.4 has a bandwidth ceiling that caps 4K at 30Hz and prevents 60Hz entirely. Windows quietly works around this by using a compressed color format (YCbCr 4:2:0) to squeeze 4K @ 60Hz through an HDMI 1.4 connection without telling you. The image looks okay but colour quality is reduced. Linux takes the TV at its word and simply refuses to offer modes the hardware claims it cannot do without explicit permission.
If you happen to be using a passive HDMI-to-DP adapter, that doesn't change anything. They do not convert the signal — they just reshape the plug. The bandwidth is still limited by whatever HDMI version the TV is advertising. With "HDMI UHD Color" set to OFF, that is HDMI 1.4 which caps 4K at 30Hz. If your display has a DisplayPort input, the best long-term solution is to connect directly to that.
The steps that follow tell the Samsung TV to stop lying about its capabilities. Once HDMI UHD Color is enabled, the TV correctly advertises HDMI 2.0 support and true 4K @ 60Hz in full color becomes available immediately.
Reference & Credit: Major Frenchy on the Virtual Pinball Chat Discord
Step 1 — Enable HDMI UHD Color on your Samsung TV
Using your Samsung TV remote, navigate to:
Settings → General → External Device Manager → HDMI UHD Color
[!TIP] On newer Samsung TVs and monitors the setting may be called Input Signal Plus or HDMI Black Level. Check under Connection, External Device Manager, or Input settings depending on your model year. The option to look for is anything that enables HDMI 2.0 or higher bandwidth on a specific port.
Set it to ON for the HDMI port your PC is connected to (usually HDMI 1 or HDMI 2). After turning this on, your TV may go black for a second and reconnect. That is normal — it is re-negotiating the signal with your GPU. Now go to your Linux display settings and check if 3840x2160 @ 60Hz is now available. For many people this single step solves everything and you're done.
[!NOTE] The two steps below are optional but recommended to make the fix permanent and improve driver behaviour.
Step 2 — Apply the Nvidia HDMI 2.0 Driver Fix
Even with HDMI UHD Color enabled, the Nvidia driver on Linux sometimes still under-negotiates the HDMI version after a reboot. This one-liner fixes that permanently even across OS updates (including Bazzite, where the file is in the writable overlay).
echo 'options nvidia NVreg_UseHDMI2deepColor=1' | sudo tee /etc/modprobe.d/nvidia-hdmi.conf```
Verify it was written correctly:
cat /etc/modprobe.d/nvidia-hdmi.conf
# Should output exactly one line:
# options nvidia NVreg_UseHDMI2deepColor=1
Then rebuild your initramfs so the setting is loaded at boot.
- On Fedora-based system, use
sudo dracut --force - On Debian/Ubuntu-based systems use
sudo update-initramfs -u-On Arch usesudo mkinitcpio -P linux
You'll need to reboot after making these changes
Step 3 — Verify After Reboot
TODO Expand this section to cover Wayland.
After rebooting, open a terminal and run xrandr. Look for your Samsung display (usually HDMI-A-1). You should now see 3840x2160 listed with 60Hz available. The currently active mode will have an asterisk (*) next to it. If it is not yet set to 4K @ 60Hz, open your display settings and select it manually. It should stick from now on.
Diagnostic Commands (Advanced)
If the steps above did not work, these commands will help diagnose exactly what is going on.
First, check what your TV is advertising to Linux. For this,edid-decode will need to be installed if it isn't already
- Nobara / Fedora:
sudo dnf install edid-decode - Bazzite:
sudo rpm-ostree install edid-decode - Arch:
sudo pacman -S v4l-utils
Run it with sudo cat /sys/class/drm/card1-HDMI-A-1/edid | edid-decode
Look for the line Maximum TMDS clock. If it says 300 MHz, the TV is still advertising HDMI 1.4. Go back and make sure HDMI UHD Color is ON. After enabling it, the value should jump to 600.
Next, check what resolutions and refresh rates are available by running xrandr. Your 4K display should appear as HDMI-A-1. Look for 3840x2160 entries. If all refresh rates are 29.xx Hz, the TV is still in HDMI 1.4 mode.
Finally, make sure the proprietary nvidia driver is loaded and not the open-source nouveau driver. Bazzite and Nobara install the proprietary driver by default, but it is worth confirming with:
nvidia-smi
lsmod | grep nvidia
Can't Enable 4K60 on LG TVs Running Batocera
This issue is similar to the Samsung issue above. Using the TV's remote control, go to Settings → General → External Devices → HDMI Settings → HDMI Deep Color → Enable 4k. You should then be able to select 60 Hz in Batocera without restarting (Discord Reference).
Can't enable 4K120 VRR 10Bit Color on AMD GPUs
TODO
Problem description and solution found on this Reddit post