This forum has been archived. All content is frozen. Please use KDE Discuss instead.

Multiple screens with xrandr in defeat of kscreen?

Tags: None
(comma "," separated)
xen111
Registered Member
Posts
9
Karma
1
I know I can disable KScreen now:

Code: Select all
kcmshell5 kded

But KScreen messed up my multi-monitor display within minutes of setting up it, so it wasn't getting off so lightly ;-).

I created a script in my home directory:

Code: Select all
/home/xen/scripts/fixscreen

And a file in /etc/udev/rules.d/99-monitor-change.rules

Code: Select all
ACTION=="change", SUBSYSTEM=="drm", RUN+="/home/xen/scripts/fixscreen"

But then came the arduous journey of really getting it to work. First, to allow root to access my session I created this function:

Code: Select all
sudo_xrandr() {
    sudo -u xen DISPLAY=$D xrandr "$@"
}

Together with:

Code: Select all
D=${DISPLAY:-:1}    # effectively setting it to :1 for root

Now I could do certain things such as:

Code: Select all
sudo_xrandr --output DVI-I-1 --primary --mode 1440x900 --output HDMI-1 --same-as DVI-I-1 --mode 1360x768 --scale 2x2
     # borks the display
sudo_xrandr --output DVI-I-1 --primary --mode 1440x900 --output HDMI-1 --same-as DVI-I-1 --mode 1360x768 --scale 1.06x1.17
     # fixes it again

In this case I have my main monitor at 1440x900 and my TV is 1080p but also has a mode 1360x768 which is much close and I zoom in a bit and I end up at 1442x900 which looks okay (the 1442x900 image is shrunk to 1360x768 which is why I call it zooming in) --- but this looks a bit better than 1440x900. I have a problem with aspect ratios anyway (1440x900 = 1.6:1, 1920x1080 = 1.78:1, 1360x768 = 1.77:1).

But I want it to fix itself according to the setup of my monitors. When the TV is turned off but HDMI is still connected to the receiver the 1360x768 mode disappears from it:

Code: Select all
HDMI-1 connected 1442x899+0+0 (normal left inverted right x axis y axis) 1600mm x 900mm
   1920x1080i    60.00 +  60.00    50.00    59.94 
   1920x1080     60.00    50.00    59.94 
   2880x576      50.00

And with the TV on, it is still there:

Code: Select all
HDMI-1 connected 1442x899+0+0 (normal left inverted right x axis y axis) 1600mm x 900mm
   1920x1080i    60.00 +  60.00    50.00    59.94 
   1360x768      60.37*+
   1920x1080     60.00    50.00    59.94 
   2880x576      50.00

Actually I faked the above. More disappears from the HDMI-1 line when the TV is off:

Code: Select all
HDMI-1 connected (normal left inverted right x axis y axis)

Even though it is still set to connected (audio will still work). So I test for this line to know which is which:

Code: Select all
resolutions=$(sudo_xrandr -q | sed -n '/HDMI-1 connected/,/^[^ ]/p' | sed -e "1d;\$d" | awk '{print $1}')
echo "$resolutions" | grep 1360x768 > /dev/null && tv_on=yes

As well as to know about HDMI in the first place, and I get these three options:

Code: Select all
sudo_xrandr -q | grep "HDMI-1 connected" > /dev/null && hdmi_connected=yes

[ $hdmi_connected ] && {
    [ $tv_on ] && {
         # commands
        true
   } || {
        # command
    } || true
} || {
    # command
}

Which turns into these three sets of configurations:

Code: Select all
1. xrandr --output DVI-I-1 --primary --mode 1440x900 --output HDMI-1 --same-as DVI-I-1 --mode 1360x768 --scale 1.06x1.17   # TV on
2. xrandr --output DVI-I-1 --primary --mode 1440x900 --output HDMI-1 --same-as DVI-I-1 --scale-from 1440x900   # TV off
3. xrandr --auto   # HDMI off

However if I turn my TV back on the problem is that KScreen fires after my own script and it will set about setting everything "in order" once more. At first I thought it would always call "setConfig" but it turns out it only does that if it starts messing with me. There is not really a good way to know when it is done configurating.

In the end I created a hugely complex function to wait for a certain line in the log file:

Code: Select all
wait_log() {
    skip=.
    found=
    [ -n "$2" ] && {
        cursor=$2
        skip=$3
    } || update_cursor

    while ! {
            current=$(journalctl --after-cursor="$cursor" --show-cursor)    # get tail of log
            valid=$(echo "$current" | sed -n "/$skip/,\$p")    # if $3 was given skip to it first
            found=$(echo "$valid" | grep -F "$1")    # text to find
            cursor=$(echo "$current" | tail -1 | awk '{print $3}')    # new cursor
            [ -n "$found" ]
    }; do
        [ "$cursor" = "$old_cursor" ] && return 1;    # don't keep looping if no new log entries
        old_cursor=$cursor
        sleep 1s
        skip=.
    done

    echo "$cursor"  # this is the cursor containing the found string
    return 0
}

But it turned out waiting for "XRandR::setConfig done!" didn't make sense and "Emitting configChanged()" can basically appear anywhere.

Maybe I will just wait until KScreen stops outputting data for 2 seconds ;-).

This was my original wait function:
Code: Select all
[ $(id -u) -eq 0 ] && {
    # I thought I could depend on this thing always calling setConfig.
    t1="XRandR::setConfig done!"
    t2="Emitting configChanged()"
    cursor=$(wait_log "$t1") && {
        wait_log "$t2" "$cursor" "$t1" > /dev/null
    }
    wait_log "$t2"
}

But the effect is already that it can't find anything and just times out after a second of no new logs, and it works :p. So whatever you do, look for a string you can never find, and you'll be okay.

The reason I bork the display first is because xrandr sometimes won't work if the existing values are too close to the new value you won't. I guess it would be better to create a flag for that because this causes the display to flicker twice. The new script has a --bork option for when you use it manually.

Here it is if you want it: http://www.xen.dds.nl/f/scripts/fixscreen

It contains a lot of logging code. It is executed in the background so as to not hold up udev. It logs 2 entries to syslog under the name of KScreen-fighter ;-). You'll have to adust the xrandr calls for your own situation and accept the pointlessness of searching for a string that will never appear. And then it times out and you're safe anyway ;-).


Bookmarks



Who is online

Registered users: Bing [Bot], Google [Bot], Yahoo [Bot]