How to fix the multiple monitor resize after lock screen issue in PopOS and Ubuntu Linux with GNOME

TL;DR Quick Fix is at the END for people who want to get to the deets w/o prolegomenon.

I put as many keywords as I could into the headline so this post is easy for others to find. Although I'm not a gamer, I have a super duper Lenovo Legion gamer laptop with all kinds of nVidia power for my daily software dev work. I'm running PopOS which is a System76 flavor derived from Ubuntu. I love the System76 product because they've put a lot of work into resolving a wide variety of driver issues that can make Linux frustrating to use. For the most part I use this OS aggressively on many different machines and it Just Works. But occasionally I run into oddities like the following:

Ever since I upgraded to the latest, when I walk away from my laptop, it locks the screen as designed and that's fine. But when I return and unlock the screen, the monitors resize themselves back to the default resolution. (I prefer to keep both monitors at the same resolution even though one is physically larger.) This lock screen issue weirdly mirrors my laptop screen into a tiny inset within the ultra high-resolution 2nd monitor. Everything gets wopperjawed. I have to right-click on the desktop, select "Display Settings" and reconfigure the resolution and placement for each monitor. Every time.

Did that for a few weeks til today I said "Enough of that" and spent time researching how to fix this. Turns out this is a very old problem. It's been around for years and years, and has a lot of causes, lots of fixes and non-fixes and bugs that have been open for years without resolution. I'll list a bunch of links at the end of this post, but after a few searches and a few experiments, this is the paragraph that got me headed in the right direction:

When I examined the ~.config/monitors.xml file I saw that it had six display entries instead of just three. I suspect that something having to do with the updates had made some new, weird entries in the monitors.xml file. I kept the first three and deleted the rest then saved the file and rebooted.

I checked my monitors.xml file and saw that it had four display entries instead of just two. One of the duplicated entries had a serial number so I knew it was a duplicate. The only field that was different was the <connector> field which had appended a -1 to distinguish it from the original entry (i.e. HDMI-1-0 vs HDMI-0). Take a look at the sample file at the end of this post to see what I mean.

I did the following:

  1. Made a copy of monitors.xml so I could roll back if I needed to (see below for an example of what it looked like).
  2. Deleted the duplicates.
  3. Saved the file.
  4. Rebooted the computer.

Same problem occurred. I checked monitors.xml again and it was back to duplicates. I assume this happened with some kind of automatic process when I shut down the laptop. However, it might have been because I used two <configuration> tags to hold everything. Not sure, but the next iteration fixed the problem:

  1. Removed the duplicates again. This time I used a single <configuration> tag, as seen in the example below.
  2. Saved the file.
  3. Locked the computer and went away for a while.

When I came back, the problem did not occur.

  1. Logged out, logged back in again.

The problem was back.

So I had made progress, but the solution wasn't yet stable.

I did some more searching and experimenting. One thing I found along the way is that using "suspend" instead of the default lock is a good workaround. The issue still happens during reboots but if you just suspend when leaving the computer, you can bypass the problem.

However, this is not a solution, and although Linux suspend is working well these days, it has a long history of causing problems similar to this one, so I've learned to use it cautiously. So I kept searching, and eventually found this comment:

I fixed the issue between re-boots and logouts, using the xandr command in my xstartup file, or perhaps it was my .xinitrc, can't actually remember now.

xrandr --output edp-1 --mode 1600x900_60.00

That was from Display configuration resets after screen locks:
https://github.com/pop-os/pop/issues/214#issuecomment-570065108

Not a full solution, but it was better than what I had. So I modified this solution to match the 1920x1080 which I prefer, and got the following response:

warning: output eDP-1 not found; ignoring

I then found this:

xrandr: cannot find output "eDP-1"
https://askubuntu.com/questions/1127428/xrandr-cannot-find-output-edp-1

On a hunch, I ran this command:

xrandr | grep -e " connected [^(]" | cut "-d " -f1

and got this:

HDMI-0
eDP-1-1

Aha! Clearly, the eDP-1-1 name exists somewhere outside the monitors.xml file. I imagined the following: after returning from lock, logout, etc., some app checks monitors.xml, sees that the "true" monitor name isn't there, and re-creates a new configuration to match what it sees as a "new" monitor group. By deleting the new section, I was only fixing half the problem. Fixing a symptom, not a cause.

So I modified the monitors.xml file again, keeping only as many config sections as I had monitors. I changed the original eDP-1 to eDP-1-1 to match what xrandr showed. Back to testing:

  1. I logged out, and back in again. It worked.
  2. Rebooted. Problem was still solved...
  3. Logged out again. Problem was... happily... solved.
  4. Locked screen and went away for awhile. Problem was still solved.

Yay! Back to my usual two monitors with the same resolution:

I then confirmed that this diagnosis and solution was correct by the following steps:

  1. Make backup of monitors.xml.
  2. Delete monitors.xml.
  3. Reboot.
  4. A new monitors.xml gets created during the boot process as described earlier, but note this one has only the correct <connector> names.
  5. Of course the resolution problem is there again but... now when I change the resolution it stays.
  6. It works permanently thereafter.

Yay!2

If you're following my logic here, this effectively creates the same monitors.xml file as the first solution using xrandr and deleting config sections. It is theoretically possible to create a tiny shell script to fix this problem, but that's out of scope for my discovery purposes here.

The right way to do this is for Linux distros to perform this xrandr-tuning step during installation, but that's even more out of scope for me here. Anyone seeing this article please feel free to pass the fix upstream to the kernel hackers.

Since some people will want to see the BEFORE and AFTER monitors.xml so you can visualize the change, I summarized the steps needed in a very brief TL;DR at the end of this article.

But for those who want the deets, here is the original file:

<monitors version="2">
  <configuration>
    <logicalmonitor>
      <x>0</x>
      <y>1080</y>
      <scale>1</scale>
      <primary>yes</primary>
      <monitor>
        <monitorspec>
          <connector>eDP-1</connector>
          <vendor>CSO</vendor>
          <product>0x1606</product>
          <serial>0x00000000</serial>
        </monitorspec>
        <mode>
          <width>1920</width>
          <height>1080</height>
          <rate>60.007877349853516</rate>
        </mode>
      </monitor>
    </logicalmonitor>
    <logicalmonitor>
      <x>0</x>
      <y>0</y>
      <scale>1</scale>
      <monitor>
        <monitorspec>
          <connector>HDMI-1-0</connector>
          <vendor>GSM</vendor>
          <product>LG HDR 4K</product>
          <serial>SERIALNUMBERHERE</serial>
        </monitorspec>
        <mode>
          <width>1920</width>
          <height>1080</height>
          <rate>60</rate>
        </mode>
      </monitor>
    </logicalmonitor>
  </configuration>
  <configuration>
    <logicalmonitor>
      <x>0</x>
      <y>0</y>
      <scale>1</scale>
      <primary>yes</primary>
      <monitor>
        <monitorspec>
          <connector>eDP-1-1</connector>
          <vendor>CSO</vendor>
          <product>0x1606</product>
          <serial>0x00000000</serial>
        </monitorspec>
        <mode>
          <width>1920</width>
          <height>1080</height>
          <rate>60.007877349853516</rate>
        </mode>
      </monitor>
    </logicalmonitor>
  </configuration>
  <configuration>
    <logicalmonitor>
      <x>0</x>
      <y>0</y>
      <scale>1</scale>
      <monitor>
        <monitorspec>
          <connector>HDMI-0</connector>
          <vendor>GSM</vendor>
          <product>LG HDR 4K</product>
          <serial>SERIALNUMBERHERE</serial>
        </monitorspec>
        <mode>
          <width>1920</width>
          <height>1080</height>
          <rate>60</rate>
        </mode>
      </monitor>
    </logicalmonitor>
    <logicalmonitor>
      <x>0</x>
      <y>1080</y>
      <scale>1</scale>
      <primary>yes</primary>
      <monitor>
        <monitorspec>
          <connector>eDP-1-1</connector>
          <vendor>CSO</vendor>
          <product>0x1606</product>
          <serial>0x00000000</serial>
        </monitorspec>
        <mode>
          <width>1920</width>
          <height>1080</height>
          <rate>60.007877349853516</rate>
        </mode>
      </monitor>
    </logicalmonitor>
  </configuration>
</monitors>

And this is what I ended up with:

<monitors version="2">
  <configuration>
    <logicalmonitor>
      <x>0</x>
      <y>1080</y>
      <scale>1</scale>
      <primary>yes</primary>
      <monitor>
        <monitorspec>
          <connector>eDP-1-1</connector>
          <vendor>CSO</vendor>
          <product>0x1606</product>
          <serial>0x00000000</serial>
        </monitorspec>
        <mode>
          <width>1920</width>
          <height>1080</height>
          <rate>60.007877349853516</rate>
        </mode>
      </monitor>
    </logicalmonitor>
    <logicalmonitor>
      <x>0</x>
      <y>0</y>
      <scale>1</scale>
      <monitor>
        <monitorspec>
          <connector>HDMI-0</connector>
          <vendor>GSM</vendor>
          <product>LG HDR 4K</product>
          <serial>SERIALNUMBERHERE</serial>
        </monitorspec>
        <mode>
          <width>1920</width>
          <height>1080</height>
          <rate>60</rate>
        </mode>
      </monitor>
    </logicalmonitor>
  </configuration>
</monitors>

For even more details, here are some of the many URLs that I looked into, only a small portion of those available on this topic:

TL;DR how to fix it:

  1. Run xrandr | grep -e " connected [^(]" | cut "-d " -f1 to get the names of your monitors. (Mine were HDMI-0 and eDP-1-1)
  2. Modify the ~./config/monitors.xml file to keep only one config section per correctly-named monitor. (See example above if needed)
  3. Use Settings,Displays to change resolution one last time.

(For those who want to fix it without using bash)

  1. Delete monitors.xml. (See screenshot below for how to do this using your file manager)
  2. Reboot
  3. Use Settings,Displays to change resolution one last time.

How to delete monitors.xml after showing hidden files

 

Add a comment

Fields followed by * are mandatory

HTML code is displayed as text and web addresses are automatically converted.

Page top