I just found a brilliantly easy quality-of-life improvement I needed to share: display-switch.
Context
I’m the type of person who invests in interfaces. Consequently, I generally like to work at my desk, with my chosen peripherals and tools. Typically, the two most common computers I use there are a work-issued MacBook, and a personal workstation running Linux. I want to switch between them without dealing with a lot of plugging and unplugging of cables.
For years, my solution was to use a USB switch with my monitor plugged into both computers simultaneously (e.g., one via USB-C, one via DisplayPort). When I’d switch, I’d click my USB switch to flip my five peripherals (mouse, keyboard, webcam, USB audio interface, YubiKey). Then, I’d toggle my monitor’s menu to switch inputs. This is fine.
The USB switch is nice because even if a monitor has built-in KVM functionality, it rarely has enough ports for my use case. They also often have fatal design flaws that make them not very functional.
Today, my USB switch broke. Naturally, I took it as an opportunity to revisit the space and see how I could improve my setup.
What I found
First, I discovered UGREEN makes 2-in, 7-out USB 3.2 switches now. I picked one up and it’s been great. I even have two free USB ports now.
Second, and the motivation for this blog post, there are cool software solutions for switching display inputs without touching your monitor settings!
If your monitor supports DDC/CI (display data channel/command interface), then it supports being sent commands via software to switch inputs.
With that, you can wire up display-switch, and now your cheap (relative to full-fledged KVMs) USB switch can effectively function as a full KVM, switching your monitor input, too, at the press of a single button!
Simply follow the guide on the display-switch repository README.
That said, I will leave you with a few tips not covered by the README.
Tip: use display-switch for monitors normal KVMs don’t support
Most KVMs, even higher-end ones, do not support very high resolution displays.
For example, most will do 4K@60Hz or similar.
If you have a higher resolution or refresh-rate monitor, you might have thought that you can’t enjoy the KVM convenience.
display-switch works by assuming you are just directly wired into your monitor on both computers, so this isn’t a problem!
Tip: use the brew path for the service on macOS
On macOS, it’s simpler to just brew install haimgel/tools/display_switch.
But, if you do, the README leaves you with a footgun when setting it up to run at startup.
Specifically, the example dev.haim.display-switch.daemon.plist assumes you have installed it manually and moved it to /usr/local/bin/display_switch.
Instead, just install it with brew and update that path to be accurate:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>dev.haim.display-switch.daemon</string>
<key>Program</key>
<string>/opt/homebrew/bin/display_switch</string>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>Tip: find USB device IDs without lsusb
For unknown reasons, I couldn’t get lsusb to work on macOS.
If you find yourself in the same boat, here’s a simple way to get the same information.
I suggest uv so you don’t need to deal with Python virtualenvs manually:
uv run --with pyusb python
Then, paste this into your interpreter:
import usb.core
for dev in usb.core.find(find_all=True):
try:
name = f"{dev.manufacturer} — {dev.product}"
except Exception:
name = ""
print(f"{dev.idVendor:04x}:{dev.idProduct:04x} {name}")
This should get you lsusb-like output:
046d:0892 None — HD Pro Webcam C920
1532:0085 Razer — Razer Basilisk V2
07fd:000b MOTU — M2
05e3:0610 GenesysLogic — USB2.1 Hub
04fe:0021 PFU Limited — HHKB-Hybrid
05e3:0625 GenesysLogic — USB3.2 Hub
1050:0406 Yubico — YubiKey FIDO+CCID
05e3:0625 GenesysLogic — USB3.2 Hub
05e3:0610 GenesysLogic — USB2.1 Hub
0b95:1790 ASIX — AX88179A
0b05:0411 Generic — USB3.2 Hub
0b05:0c23 Generic — USB2.1 Hub
0b05:1c55 Cypress Semiconductor — DMC Device
8087:0b40 Intel Corporation. — USB3.0 Hub
1d5c:5801 Fresco Logic, Inc. — USB2.0 HubTip: use cargo to install on Linux
For Linux, rather than downloading releases or building from source manually, use cargo.
Doing so will let you use tools like cargo-update to easily keep it up to date with minimal work (via cargo install-update --all --git).
cargo install --locked --git https://github.com/haimgel/display-switch
Like the brew case for macOS, you will now need to change the default $XDG_CONFIG_HOME/systemd/user/display-switch.service example to have the right path.
By default it will look like $HOME/.cargo/bin/display_switch.
[Unit]
Description=Display switch via USB switch
[Service]
# update this path
ExecStart=/home/youruser/.cargo/bin/display_switch
Type=simple
StandardOutput=journal
Restart=always
[Install]
WantedBy=default.targetTip: use on_usb_disconnect to reduce latency
Finally, display-switch supports an on_usb_disconnect configuration:
usb_device = "1050:0407"
on_usb_connect = "Hdmi1"
on_usb_disconnect = "Hdmi2"
But the README notes:
The optional
on_usb_disconnectsettings allows to switch in the other direction when the USB device is disconnected. Note that the preferred way is to have this app installed on both computers. Switching “away” is problematic: if the other computer has put the monitors to sleep, they will switch immediately back to the original input.
While this is true, if your monitor and setup support it, using on_usb_disconnect can significantly reduce the latency of the switch.
Without it, the chain of delays is:
Push button
↓
USB devices switch
↓
2nd computer detects new USB devices
↓
2nd computer runs display-switch
↓
Monitor switches input
↓
2nd computer ready to use
With it, the monitor input switch and the USB handoff happen in parallel.
Push button
│
├─────────────────────────────────┐
↓ ↓
USB devices switch 1st computer runs display-switch
↓ ↓
2nd computer detects Monitor switches input
new USB devices │
│ │
└──────────────┬──────────────────┘
↓
2nd computer ready to useSummary
If you frequently switch between two computers at your desk, you don’t need an expensive KVM.
A USB switch paired with display-switch gets you the same convenience for a fraction of the price.
It’s a $500+ KVM-like experience for the cost of an $80 USB switch and a free tool.
I’m all about software that reduces friction and makes computing more delightful, and display-switch is a great example of that: switching my monitor and full peripheral set is now a single button press, and meaningfully faster than before.