DPI-aware mouse transition fix for multi-monitor setups on Linux/X11.
Eliminates the "mouse jump" when moving the cursor between monitors with different resolutions or DPI values. This is the Linux equivalent of LittleBigMouse for Windows.
Includes a KDE kscreen UI patch that fixes the false "gap" warning in KDE display settings and shows monitors correctly bottom-aligned — exactly like the real physical setup.
When using monitors with different resolutions (e.g., a 4K/UWQHD center monitor with 1080p side monitors), moving the mouse across screen boundaries causes a jarring position jump. The mouse enters the adjacent screen at the wrong vertical position because X11 maps pixels 1:1 regardless of physical monitor size.
Without fix-mouse-jump: With fix-mouse-jump:
┌──────┐┌──────────────┐ ┌──────┐┌──────────────┐
│ ││ │ │ ││ │
│ 1080p ││ UWQHD │ │ 1080p ││ UWQHD │
│ ││ │ │ ││ │
│ ──→ ││ ↑ JUMP! │ │ ──→ ││→ smooth! │
└──────┘│ │ └──────┘│ │
└──────────────┘ └──────────────┘
Additionally, KDE's display settings (kscreen2) cannot understand xrandr scaling. It shows a false "Lücken zwischen Anzeigen werden nicht unterstützt" (gaps between displays) warning and renders monitor positions incorrectly. This tool fixes that too.
The tool uses xrandr --scale to virtually increase the resolution of lower-DPI monitors, so their pixel density matches the higher-DPI center monitor. This makes mouse transitions physically accurate.
The scale factor is calculated from the physical pixel densities:
center_ppmm = center_height_px / center_height_mm (e.g., 1600 / 370 = 4.32)
side_ppmm = side_height_px / side_height_mm (e.g., 1080 / 336 = 3.21)
SCALE = center_ppmm / side_ppmm (e.g., 4.32 / 3.21 = 1.35)
With SCALE=1.35, the 1920×1080 side monitors are virtually upscaled to 2592×1458. This matches the pixel density of the UWQHD center monitor — mouse transitions become seamless.
When xrandr scaling is applied, KDE's kscreen2 sees the X11 geometry (scaled positions and native sizes) and thinks there are gaps between monitors:
What kscreen2 sees (WRONG):
DP-0: size 1920×1080, position x=0 → ends at x=1920
DP-4: size 3840×1600, position x=2592 → gap of 672px!
DP-2: size 1920×1080, position x=6432 → gap of 672px!
The fix has two parts:
-
sync_kscreen()— Writes native (unscaled) monitor positions to the kscreen2 config file after plasmashell restart, so monitors appear side-by-side:DP-0: pos 0×520 (1920px wide, bottom-aligned) DP-4: pos 1920×0 (right after DP-0) DP-2: pos 5760×520 (right after DP-4, bottom-aligned) -
QML UI Patch — Overrides KDE's display settings UI (
~/.local/share/kpackage/kcms/kcm_kscreen/):main.qml: Suppresses the falseConfigHasGapswarningScreen.qml: Recalculates monitor positions using native sizes, producing a gap-free layoutOutput.qml: Uses the corrected positions for rendering each monitor rectangle
- Linux with X11 (not Wayland)
- KDE Plasma 5 (for plasmashell restart + kscreen patch)
xrandrbash≥ 4.0awkjq(for kscreen config patching)
git clone https://github.com/brainAThome/fix-mouse-jump.git
cd fix-mouse-jump
chmod +x install.sh
./install.shThen edit the config to match your monitor setup:
nano ~/.config/fix-mouse-jump/config| Component | Location | Purpose |
|---|---|---|
| Main script | ~/.local/bin/fix-mouse-jump |
xrandr scaling + kscreen sync |
| Config | ~/.config/fix-mouse-jump/config |
Monitor names, resolutions, scale |
| Autostart | ~/.config/autostart/fix-mouse-jump.desktop |
Auto-apply at login |
| KDE UI patch | ~/.local/share/kpackage/kcms/kcm_kscreen/contents/ui/ |
Fix display settings UI |
| Version fingerprint | ~/.config/fix-mouse-jump/kscreen-version |
Detects kscreen package updates |
| systemd watcher | ~/.config/systemd/user/fix-mouse-jump-watch.* |
Triggers on kscreen file changes |
| Logs | ~/.local/share/fix-mouse-jump/ |
Runtime log + watchdog PID |
xrandr --query | grep " connected"Example output:
DP-0 connected 1920x1080+0+520 597mm x 336mm
DP-4 connected primary 3840x1600+1920+0 880mm x 370mm
DP-2 connected 1920x1080+5760+520 597mm x 336mm
# From the xrandr output above:
# Center monitor: 1600px height, 370mm physical height
# Side monitors: 1080px height, 336mm physical height
python3 -c "print(f'SCALE = {(1600/370) / (1080/336):.2f}')"
# Output: SCALE = 1.35# ─── Monitor Output Names ───────────────────────────────────────────────────
LEFT_MONITOR="DP-0"
CENTER_MONITOR="DP-4"
RIGHT_MONITOR="DP-2"
# ─── Native Resolutions ─────────────────────────────────────────────────────
LEFT_RES="1920x1080"
CENTER_RES="3840x1600"
RIGHT_RES="1920x1080"
# ─── Refresh Rates (Hz) ─────────────────────────────────────────────────────
LEFT_RATE="144"
CENTER_RATE="144"
RIGHT_RATE="144"
# ─── Scale Factor ────────────────────────────────────────────────────────────
SCALE="1.35"
# ─── Autostart Settings ─────────────────────────────────────────────────────
AUTOSTART_DELAY=10 # Wait for kscreen2 before first apply
AUTOSTART_REAPPLY_DELAY=20 # Re-apply after kscreen2 may reset layout
# ─── Plasmashell ─────────────────────────────────────────────────────────────
RESTART_PLASMASHELL=true # Restart plasmashell (fixes wallpaper rendering)
# ─── Watchdog ────────────────────────────────────────────────────────────────
WATCHDOG_ENABLED=true # Monitor layout and auto-restore if reset
WATCHDOG_INTERVAL=30 # Check interval in seconds# Apply the fix (scaling + plasmashell restart + kscreen sync)
fix-mouse-jump apply
# Revert to original layout (no scaling)
fix-mouse-jump revert
# Start watchdog manually (auto-restores scaling if reset)
fix-mouse-jump watchdog
# Check if kscreen was updated (patches may need reinstall)
fix-mouse-jump check-update
# Save current kscreen version fingerprint
fix-mouse-jump save-fingerprint
# Show current monitor status
fix-mouse-jump status
# Show help
fix-mouse-jump helpThe fix is automatically applied at login via the autostart entry.
apply_scale— Sets xrandr scaling on side monitors + positions all monitors bottom-alignedrestart_plasmashell— Restarts plasmashell (fixes wallpaper rendering on scaled monitors)- Wait 3 seconds — Lets kscreen2 finish writing its config after plasmashell restart
sync_kscreen— Patches the kscreen2 config with native positions (gap-free)
- Version check — Compares kscreen QML fingerprint with saved version; warns via desktop notification if kscreen was updated
- Wait
AUTOSTART_DELAYseconds (default: 10) for kscreen2 to finish initial setup - Apply scaling + restart plasmashell + sync kscreen
- Wait
AUTOSTART_REAPPLY_DELAYseconds (default: 20) in case kscreen2 resets the layout - Re-apply scaling + re-sync kscreen
- Start watchdog — Monitors xrandr layout every
WATCHDOG_INTERVALseconds and re-applies if scaling is lost
./uninstall.shThis reverts the monitor layout, removes the script, autostart entry, KDE UI patches, and logs. Config is kept unless you confirm deletion.
The tool is designed to survive reboots and system updates:
| Scenario | Protection |
|---|---|
| Reboot | Autostart re-applies xrandr scaling + kscreen sync on every login |
| plasmashell crash | Watchdog detects scaling loss within 30s and re-applies automatically |
| kscreen2 layout reset | Watchdog monitors xrandr positions and restores correct layout |
| KDE/kscreen package update | systemd path watcher triggers immediately; desktop notification warns to re-run install.sh |
| Login version check | On every autostart, kscreen QML fingerprint is compared with saved version |
After the autostart apply sequence, the script enters a watchdog loop that checks every WATCHDOG_INTERVAL seconds (default: 30) whether the center monitor is still at the expected scaled position. If the layout was reset (by kscreen, plasmashell crash, or manual xrandr call), the watchdog automatically:
- Re-applies xrandr scaling
- Re-syncs the kscreen config
- Sends a desktop notification
Disable with WATCHDOG_ENABLED=false in the config.
During installation, an MD5 fingerprint of the system kscreen QML files is saved. Two mechanisms detect updates:
- systemd path watcher — Monitors
/usr/share/kpackage/kcms/kcm_kscreen/contents/ui/main.qmlfor changes. Triggers immediately whenapt upgradeupdates the kscreen package. - Login check — Every autostart compares the current fingerprint with the saved one.
Both send a desktop notification if a mismatch is detected. Re-run ./install.sh to re-apply patches after updates.
fix-mouse-jump/
├── fix-mouse-jump # Main script (bash)
├── config.example # Example configuration
├── install.sh # Installer (+ fingerprint + systemd watcher)
├── uninstall.sh # Uninstaller (cleans up everything)
├── kscreen-patch/ # KDE display settings UI fix
│ └── contents/ui/
│ ├── main.qml # Suppresses ConfigHasGaps warning
│ ├── Output.qml # Uses corrected positions for rendering
│ └── Screen.qml # Recalculates gap-free layout
├── README.md
└── LICENSE
KDE Plasma 5's display settings KCM (kcm_kscreen) reads monitor geometry from the X11 backend via kscreen-doctor. When xrandr scaling is active, the X11 positions are inflated (e.g., a 1920px-wide monitor at scale 1.35 occupies 2592px in X space), but model.size still reports the native resolution. This mismatch creates visual gaps in the UI.
The QML patch fixes this by:
-
Screen.qml— Adds arecalcPositions()function that:- Collects all enabled outputs with their X11 positions and native sizes
- Sorts them left-to-right by X11 position
- Rebuilds positions using cumulative native widths (gap-free)
- Bottom-aligns shorter monitors relative to the tallest
-
Output.qml— Each monitor delegate:- Exposes
modelPositionandmodelSizeproperties forScreen.qmlto read - Uses
displayPos(corrected position fromScreen.qml) instead of rawmodel.position
- Exposes
-
main.qml— TheonInvalidConfighandler:- Still shows the warning for
NoEnabledOutputs(all monitors disabled) - Ignores
ConfigHasGaps(false positive from xrandr scaling)
- Still shows the warning for
The patches are installed as local KPackage overrides in ~/.local/share/kpackage/kcms/kcm_kscreen/, which KDE loads before the system-wide files in /usr/share/. No sudo or system file modifications needed.
Note: After KDE/kscreen system updates, the patched QML files may become outdated. Re-run
./install.shto re-apply the patches from the latest originals.
- X11 only — On Wayland, per-monitor scaling is handled natively by the compositor (no fix needed).
- KDE Plasma 5 only — The QML patch targets KDE Plasma 5's
kcm_kscreen. Plasma 6 (expected in Kubuntu 26.04 LTS) handles per-monitor scaling natively. - Don't click "Apply" in KDE display settings — This would override the xrandr layout. The watchdog will auto-restore within 30s, or run
fix-mouse-jump applymanually. - Text size — Side monitors show slightly smaller text due to the virtual resolution increase. This is expected and matches the physical DPI.
- System updates — KDE updates may change the QML APIs. The systemd watcher and login check will warn you; re-run
./install.shto re-apply patches. - Boot window — For the first ~10 seconds after login, scaling is not yet active (xrandr is volatile). The autostart delay lets kscreen2 settle first.
| Monitor | Model | Resolution | Refresh Rate | Physical Size |
|---|---|---|---|---|
| Left | Dell S2721HGF (27") | 1920×1080 | 144 Hz | 597mm × 336mm |
| Center | Dell AW3821DW (38") | 3840×1600 | 144 Hz | 880mm × 370mm |
| Right | Dell S2721HGFA (27") | 1920×1080 | 144 Hz | 597mm × 336mm |
System: Ubuntu 24.04 LTS, KDE Plasma 5.27.12, X11, NVIDIA RTX 4080 (driver 590.48.01)
- LittleBigMouse — Windows equivalent (inspiration for this project)
- Wayland — Native per-monitor scaling (but may have app compatibility issues)
- KDE Plasma 6 — Native per-monitor DPI support on X11 (Kubuntu 26.04 LTS, April 2026)
