Linux, laptop and external HDMI display problem.

After I moved (yes, again) to (this time) Kubuntu I am by and large satisfied. Of course there are bugs and glitches but there is no sanctuary for me now. Windows 7 cannot be installed on my laptops and Windows 10 in a horrible uncontrollable disaster. In terms of stability it is no better than Linux for me.

One of the issues that irritated me during current endeavor was the handling of an external monitor in Linux.
I’m using laptops and connect/disconnect external display to them few times a day so it is important for me to have a reliable support of multiple displays.

At first glance multi-monitor support in Kubuntu 18.04 works well. It’s behavior is predictable when plugging external monitor, closing/open lid. It works almost fine for me especially after some adjustments – setting internal display as default and allow task manager to show windows from all displays.

But after some time I noticed that my laptop thinks that external HDMI display is still connected after I had unplugged it. Therefore I have a virtual space beyond one of the screen edges where mouse pointer could go and be lost there.
It is very inconvenient.

I have two laptops, one having resolution of internal screen 1366×768 and the other with 1920×1080 resolution. My external monitor has 1920×1080 panel.
Usually I use FullHD laptop with FullHD screen so I just switched on “unify outputs” option and forget about this problem.
But when resolutions of internal and external displays are different this solution is unacceptable.

A couple of weeks I’d been thinking that I’m doing something wrong with display settings then I accidentally understood that external monitor must automatically become disabled in GUI when it is disconnected from laptop. But it wasn’t. It remained active upon disconnection.

So, my system does not notice the fact that external HDMI display is disconnected.
It seems that this problem is known though is rarely mentioned.
Here is description of EXACTLY my problem without any solution.

After some time I found one more description of this problem which I first didn’t recognize as relevant.
I tested it and yes, if I fiercely tug HDMI cable using all my force so it takes about 0.1s to completely remove it from the socket – udevadm monitor and acpi_listen notice changes and external display becomes unplugged.
I have no other words except offensive to express my attitude to this situation and the resolution “WONTFIX” at the end of this 4 years old bugreport, but because I am unable to swear in English – my attitude will remain unknown for reader…

I found two ways to force my system to notice that external monitor has already been disconnected.
1) Run xrandr without arguments.
2) Write command detect to the file /sys/class/drm/card0-HDMI-A-1/status

I found the second variant more promising because it doesn’t require connection with xsession etc, but on your system the path may be different.
Essentially, I need to execute “echo detect > /sys/class/drm/card0-HDMI-A-1/status” after external monitor has been disconnected, but I have no any event when it happens.
Usually after detaching external monitor I open laptop’s lid. So I decided to make a callback on “lid open” acpi event.

On my system I’ve made a file /etc/acpi/events/lm_lid0, containing two strings:

event=button/lid LID open
action=/etc/acpi/lid_open.sh

and file /etc/acpi/lid_open.sh consists of:

sleep 2
echo detect >  /sys/class/drm/card0-HDMI-A-1/status

Unfortunately it didn’t work properly.
Somehow this hook intervened with “lid close” event and after attaching external display to closed laptop I got expanded desktop on my external screen instead of single display configuration, system didn’t understand that internal display is switched off.
So I was forced to handle manually both events (“lid open” and “lid close”) for both displays (internal and external).

Eventually I have two files in /etc/acpi/events:

#/etc/acpi/events/lm_lid0
event=button/lid LID open
action=/etc/acpi/lid_open.sh
#/etc/acpi/events/lm_lid1
event=button/lid LID close
action=/etc/acpi/lid_close.sh

corresponding shell scripts are:

#! /bin/bash
#/etc/acpi/lid_open.sh
echo on > /sys/class/drm/card0-eDP-1/status # switch on internal display immediately
sleep 2 # time for internal display to switch on and related processes
echo detect >  /sys/class/drm/card0-HDMI-A-1/status # check if there is an external display
exit 0
#! /bin/bash
#/etc/acpi/lid_close.sh
echo off > /sys/class/drm/card0-eDP-1/status # disable internal display
exit 0

So far it seems to work for me on Kubuntu 18.04 for my usage pattern. It may or may not work for you.

Update
Later I noticed one more problem in Kubuntu display manager.
I have cheap IPS displays in both my laptops (LP116WH7-SPB2 for instance). Apparently they have 6-bit matrix and able to show only 262K colors.
Default settings for these matrices lead to high picture contrast but very poor discernibility of dark shades.
In Kubuntu’s monitor calibration tool I am able to control the gamma only so I increased gamma value to approximately 1.35 to see more details on dark images when I use internal display.
Unfortunately, monitor calibration tool does not allow me to set different gamma values for different displays. Gamma correction applies to all monitors but my external monitor does not require gamma correction.
Calibration tool has some drop down list which, apparently, should allow to select a different Screen, but it is grayed-out and I don’t know the meaning of “Screen” in this case.
So, finally I was forced to use xrandr and I extended my ACPI scripts to adjust gamma value:

#! /bin/bash
#/etc/acpi/lid_open.sh
 
export DISPLAY=:0
export XAUTHORITY=/home/myUserName/.Xauthority
 
echo on > /sys/class/drm/card0-eDP-1/status # switch on internal display immediately
sleep 2 # time for internal display to switch on and related processes
echo detect >  /sys/class/drm/card0-HDMI-A-1/status # check if there is an external display
 
xrandr --output eDP-1  --gamma 1.35:1.35:1.35
xrandr --output HDMI-1  --gamma 1:1:1
 
exit 0
#! /bin/bash
#/etc/acpi/lid_close.sh
 
export DISPLAY=:0
export XAUTHORITY=/home/myUserName/.Xauthority
 
echo off > /sys/class/drm/card0-eDP-1/status # disable internal display
 
xrandr --output HDMI-1  --gamma 1:1:1
 
exit 0

I am sad. User shouldn’t be forced to do such things.
This system isn’t ready for desktop and, apparently, never will.