Daemon mode causes stuttering when two monitors are connected
thiagokokada opened this issue · comments
Firstly, great project. mons
is exactly what I needed to manage multiple monitors using i3wm
.
To the issue I am having: running mons
in daemon mode with two monitors cause a small stuttering each dozen of seconds, that is quite noticiable when watching a video. The issue seems to be xrandr
itself, that causes this stuttering when two monitors are enabled, however if only one monitor is connected there is no problem. To easily reproduce the problem, you can run in a terminal;
while true; do xrandr; done
With two monitor connected, open a video in YouTube for example. The frame rate is completely choppy. Of course, mons
runs xrandr
in a much slower rate (each 3 seconds it seems by looking at the code), however it is still distracting.
I don't know a good solution. Maybe this could be fixable in xrandr
itself, maybe not. Or there could be another way to query the connected monitors instead of using xrandr
. Any ideas?
Hi @m45t3r, thanks for the feedback.
Indeed, I came across the problem as well. Few weeks ago, I tried the deamon mode on two different computers, but I couldn't reproduce that stuttering.
After an investigation:
- EDID is a data structure provided by a digital display to describe its capabilities to a video source
- After plugging-in a monitor, a file called
edid
is created in/sys/class/drm/*/
.
Inconvenience:
- If your driver doesn't use/support DRM, you won't get it
- Some amplificators are considered as monitors, causing
edid
file creation as well
The juice is worth the squeeze and I can't keep using xrandr after getting such a stuttering.
So a first workaround would be:
prev=0; i=0
while true; do
for edid in /sys/class/drm/*/edid; do
[ -n "$(cat "$edid")" ] && i=$((i+1))
done
[ "$i" -eq 1 ] && [ "$i" != "$prev" ] && "${XRANDR}" --auto
prev="$i"; i=0
sleep 2
done
Looks good, however I am getting the following warning though:
./mons: line 244: warning: command substitution: ignored null byte in input
And btw, there is another interesting file in this directory:
$ cat /sys/class/drm/card0-eDP-1/enabled
enabled
$ cat /sys/class/drm/card0-HDMI-A-1/enabled
disabled
In fact, this seems to be a good choice for detecting connect/disconnect monitors, since my eDP entry is enabled and HDMI were disabled in the above case.
Warning message, but does it work ?
What is your /bin/sh
?
Try to replace this:
[ -n "$(cat "$edid")" ] && i=$((i+1))
With this:
[ -n "$(<"$edid")" ] && i=$((i+1))
It avoids both forking a subshell and executing the /bin/cat
non-builtin command.
In Arch Linux, {/usr}/bin/sh
points to bash
:
$ pacman -Qo /usr/bin/sh
/usr/bin/sh is owned by bash 4.4.012-2
Btw, even changing the line I as suggested:
[ -n "$(<"$edid")" ] && i=$((i+1))
I get the same error. However, this seems to work though:
# Daemon mode
if $aFlag ; then
prev=0; i=0
while true; do
for status in /sys/class/drm/*/status; do
[ "$(<"$status")" = "connected" ] && i=$((i+1))
done
if [ "$i" -eq 1 ] && [ "$i" != "$prev" ]; then
"${XRANDR}" --auto --dpi "${dpi}"
fi
prev="$i"; i=0
sleep 2
done
fi
BTW, /sys/class/drm/*/status
seems to return connected
or disconected
, exactly what we want (and without relaying in EDID support).
Sold !
I had chosen edid
to avoid extending the door for non-monitor devices.
Hoping that the check on status
file (which is more generic) does the job for everyone.
Thanks @Ventto.