====== 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**.