====== Windows Piling at the Monitor Seam — KDE X11, amdgpu, Odyssey G9 ====== Fix for every window gathering at the boundary between the two monitors after the screens blank. Verified on ''linux-cachyos 7.1.4-1'', KDE Plasma on X11, ''amdgpu'' driving a PowerColor RX 6600 XT, systemd-boot. **The layout:** Samsung Odyssey G93SC (5120x1440) is primary at ''+0+0'' on ''DisplayPort-1''. The 1080p sits to its right at ''+5120+206'' on ''DisplayPort-0''. **To the kernel, the G9 is ''card1-DP-2''** — the names do not match, see the gotchas. ===== Quick Reference ===== ^ Task ^ Command ^ | Check session type | ''echo $XDG_SESSION_TYPE'' | | Current layout | ''xrandr --listmonitors'' | | Log RandR events | ''xev -root -event randr'' | | Map DRM connector to panel | ''head -3 /sys/class/drm/card1-DP-*/modes'' | | Dump G9 EDID | ''cp /sys/class/drm/card1-DP-2/edid /usr/lib/firmware/edid/g9.bin'' | | Kernel parameters | ''video=DP-2:e drm.edid_firmware=DP-2:edid/g9.bin'' | | Rebuild initramfs | ''sudo mkinitcpio -P'' | | Confirm EDID in initramfs | ''sudo lsinitcpio /boot/initramfs-linux-cachyos.img'' | | Confirm params are live | ''cat /proc/cmdline'' | ===== What Is Actually Happening ===== The G9 has **DisplayPort Deep Sleep** and Samsung gives no OSD toggle for it. After the screen has been dark for a while — **minutes, not seconds** — the panel drops the DP link completely. amdgpu sees a hot-unplug, X tears down the G9's CRTC, and the only desktop left is the 1080p at x=5120. KWin evacuates every window onto it. When the G9 comes back the windows stay where they were shoved — bunched at the seam. The failure in the xev log, in order — EDID deleted, output disconnected, CRTC torn down to nothing: RRNotify event, serial 18, synthetic NO, window 0x3dc, subtype XRROutputPropertyChangeNotifyEvent output DisplayPort-1, property EDID, timestamp 1311448446, state Delete RRNotify event, serial 18, synthetic NO, window 0x3dc, subtype XRROutputChangeNotifyEvent output DisplayPort-1, crtc 79, mode 5120x1440 (5120x1440) rotation RR_Rotate_0 connection RR_Disconnected, subpixel_order SubPixelUnknown RRNotify event, serial 30, synthetic NO, window 0x3dc, subtype XRRCrtcChangeNotifyEvent crtc 79, mode None, rotation RR_Rotate_0 x 0, y 0, width 0, height 0 Windows 11 hides this by remembering window placement across display changes. KWin on X11 does not. ===== Diagnose It ===== **# Make a log directory:** mkdir -p ~/seamlog **# Log every RandR event, then walk away:** nohup xev -root -event randr > ~/seamlog/randr.log 2>&1 & ''xev'' is in ''xorg-xev''. Exit 127 on the job means it is not installed. **# Count events after waking the screens:** wc -l ~/seamlog/randr.log **One line** is xev's own header — nothing happened. The failing run produced **141 lines**. **# Look for the disconnect:** grep -c RR_Disconnected ~/seamlog/randr.log ==== Bisect lock versus blank ==== By default both happen at once — Power Management → Display and Brightness → Turn off screen is set to **When locked: Immediately**. Separate them: - **Lock, no blank.** Set Turn off screen and When locked to Never. Let it lock, wait, unlock. - **Blank, no lock.** Turn off auto-lock in Screen Locking, restore the screen timer, let it go dark on its own. Result here: locked with screens lit — zero RandR events, windows untouched. Blank without the greeter — 141 events, windows at the seam. **The blank is the trigger, not the lock screen.** ===== The Fix ===== Force the connector enabled so DRM ignores the G9 dropping its link, and pin its EDID so the identity never gets deleted. **# Find which DRM connector is the G9:** for f in /sys/class/drm/card1-DP-*/modes; do echo "== $f"; head -3 "$f"; done The one leading with 5120x1440 is the G9: == /sys/class/drm/card1-DP-1/modes 1920x1080 1920x1080 1920x1080 == /sys/class/drm/card1-DP-2/modes 5120x1440 3840x1080 3840x2160 **# Make the firmware directory:** sudo mkdir -p /usr/lib/firmware/edid **# Dump the G9's EDID while the panel is awake:** sudo cp /sys/class/drm/card1-DP-2/edid /usr/lib/firmware/edid/g9.bin **# Check the dump is real:** edid-decode /usr/lib/firmware/edid/g9.bin | head -20 Expect **384 bytes**, header ''00 ff ff ff ff ff ff 00'', and the name block decoding to ''Odyssey G93SC''. Zero bytes means the read failed — the panel was asleep. **# Add the EDID to the initramfs** — in ''/etc/mkinitcpio.conf'': FILES=(/usr/lib/firmware/edid/g9.bin) If ''FILES'' already has entries, add this one inside the existing parentheses. **# Rebuild the initramfs:** sudo mkinitcpio -P **# Confirm the EDID made it in:** sudo lsinitcpio /boot/initramfs-linux-cachyos.img | grep -i edid usr/lib/firmware/edid/ usr/lib/firmware/edid/g9.bin **# Back up the boot entry:** sudo cp /boot/loader/entries/linux-cachyos.conf /boot/loader/entries/linux-cachyos.conf.bak **# Append the parameters to the options line:** sudo sh -c "sed -i '/^options /s|\$| video=DP-2:e drm.edid_firmware=DP-2:edid/g9.bin|' /boot/loader/entries/linux-cachyos.conf" **# Verify — exactly one options line, params at the end:** sudo grep ^options /boot/loader/entries/linux-cachyos.conf options root=UUID=82b232c2-b345-41a9-9e9b-51b676c85bbc rw zswap.enabled=0 nowatchdog quiet splash video=DP-2:e drm.edid_firmware=DP-2:edid/g9.bin The LTS entry is deliberately left unpatched — it is never booted except as a rescue. **# After reboot, confirm the params are live:** cat /proc/cmdline **# Confirm the layout came back intact:** xrandr --listmonitors Monitors: 2 0: +*DisplayPort-1 5120/1190x1440/340+0+0 DisplayPort-1 1: +DisplayPort-0 1920/509x1080/286+5120+206 DisplayPort-0 **# Test — start the logger, leave it dark 15+ minutes, wake it:** wc -l ~/seamlog/randr.log **One line is a pass.** Give it a few days before calling it fixed — the failure was never on demand. ==== The gotchas that will waste your afternoon ==== **# 1. xrandr and the kernel name the connectors differently.** xrandr's ''DisplayPort-1'' is the kernel's ''card1-DP-2''. Off by one and in a different format. Never assume the mapping — read the ''modes'' files. Pinning the G9's EDID onto the 1080p connector is a mess to unwind. **# 2. sudo does not expand your globs.** [josephk@HPZ4G4-LAB ~]$ sudo grep ^options /boot/loader/entries/*.conf grep: /boot/loader/entries/*.conf: No such file or directory ''/boot/loader/entries'' is not readable as your user, so the shell cannot expand ''*.conf'' before sudo runs and grep gets the literal string. A ''sudo sed -i … *.conf'' fails the same way — **silently leaving the entry unedited**. Name the file, or wrap the whole command in ''sudo sh -c "…"''. **# 3. mkinitcpio does not pick up the EDID on its own.** The build output never mentions it and reports success. Without the ''FILES='' line, ''drm.edid_firmware'' silently does nothing. Always check with ''lsinitcpio''. **# 4. Quick tests lie.** ''xset dpms force off'' and a mouse wiggle never reproduced it, and neither did a fast Meta+L. The G9 needs **minutes of darkness** before deep sleep kicks in. Anything shorter is a false pass. **# 5. grep for ''RR_Disconnected'', not ''disconnected''.** ''grep -c disconnected'' on a failing log returned **0**. xev writes the constant name. That one nearly sent the whole diagnosis sideways. ===== Red Herrings ===== **RememberWindowPositions** (KWin script in ''~/.local/share/kwin/scripts/rememberwindowpositions'') logged loudly during every unlock — including capturing ''kscreenlocker_greet'' — but disabling it changed nothing. **Loud logs are not the culprit.** Prove it with a clean disable-and-test before tuning it. If it is re-enabled: * ''multiMonitorType=1'' is "Last position — even if windows end up off-screen", a single-monitor setting. Use **0**, last monitor the window was on. * Add ''kscreenlocker_greet'' to its blacklist. **The 5-second xrandr poll** showed 369 identical samples during a failure. Transient disconnects slip between samples. Use ''xev'' — it catches every event. ===== Recovery ===== **# G9 wrong or black after reboot — boot once without the params:** e Press it on the entry at the systemd-boot menu, delete the two parameters, Enter. One-shot, nothing saved. **# Roll back the boot entry:** sudo cp /boot/loader/entries/linux-cachyos.conf.bak /boot/loader/entries/linux-cachyos.conf **# G9 at the wrong resolution — drop the EDID half only:** sudo sh -c "sed -i 's| drm.edid_firmware=DP-2:edid/g9.bin||' /boot/loader/entries/linux-cachyos.conf" The G9's EDID is three blocks. ''drm.edid_firmware'' occasionally mishandles multi-block EDIDs. ''video=DP-2:e'' alone may still hold the connector. ===== Troubleshooting ===== ^ Symptom ^ Cause ^ Fix ^ | Windows at x=5120 after the screens blank | G9 deep sleep drops the DP link | ''video=DP-2:e'' plus EDID firmware | | Fine after a quick lock, bad after long idle | deep sleep needs minutes of dark | test with 15+ minutes blank | | ''grep disconnected'' finds nothing | xev writes ''RR_Disconnected'' | ''grep RR_Disconnected'' | | ''sudo grep … *.conf'': No such file | glob expanded as your user | name the file or ''sudo sh -c'' | | ''lsinitcpio'' shows no edid | file not in ''FILES='' | edit ''/etc/mkinitcpio.conf'', ''mkinitcpio -P'' | | G9 wrong resolution after reboot | multi-block EDID via firmware | drop ''drm.edid_firmware'', keep ''video=DP-2:e'' | | Problem back after a kernel update | entry rewritten or EDID dropped | check ''/proc/cmdline'' and ''lsinitcpio'' | | Rescue boot scatters windows | LTS entry unpatched | expected | | xev job shows Exit 127 | ''xorg-xev'' not installed | ''sudo pacman -S xorg-xev'' | ===== Which Fix Should I Use? ===== ^ ^ ''video='' + EDID ^ When locked: Never ^ Window Rules ^ | Panel still sleeps | **yes** | no | yes | | Stops the disconnect | **yes** | yes | no | | Safe for the OLED | **yes** | no — burn-in | yes | | Covers every window | **yes** | yes | only forced apps | | Setup effort | one-time | trivial | per app | Rule of thumb: **pin the connector in the kernel — never leave the OLED lit to dodge it**.