Open Vladimir-csp opened 6 years ago
This change would increase the complexity from a user's perspective a lot. Currently, it's fairly easy: A set of specific monitors connected to specific physical outputs is what autorandr calls a setup. Reproduce a setup, and autorandr will reload the configuration you stored earlier for you. I'd rather not add complexity to this. (For example, valid follow up questions would be: Shouldn't we then distinguish between monitors in stand-by and powered-on monitors as well?)
That being said, you can use the block
hook to add this to your personal configurations.
For example, valid follow up questions would be: Shouldn't we then distinguish between monitors in stand-by and powered-on monitors as well?
No, there isn't any ambiguous continuation for this. The laptop case is pretty straightforward: if lid is closed, internal monitor becomes useless and is expected to be unused.
There may be a different approach: add a config option to mark output(s) as internal. Treat those outputs as disconnected if lid is closed.
I think it would be very useful too
@phillipberndt As a user, I would have expected autorandr to treat lid open/close events as a screen connect/disconnect. At least this is essentially how I think about it when I open/close the lid, since there is no way to actually disconnect it.
That being said, even though I would enjoy if autorandr's behavior would match my way of thinking, it is nice to see that it also provides ways to work around such edge cases and I thank you for that. I just spent an hour figuring this out, so I figured I would share for others who bump into the same issue.
config-open
and config-close
)..config/autorandr/config-open/block
, which indicates when to block the config
#!/bin/bash
exec grep -q close /proc/acpi/button/lid/LID0/state
3. And the executable file `.config/autorandr/config-open/block`
```bash
#!/bin/bash
exec grep -q open /proc/acpi/button/lid/LID0/state
It's time to test: open/close the lid and then run
autorandr --change
Your preferred config should apply accordingly. If it does not, make sure you made both block files executables.
Repeat steps 1-4 for as many configs where you want to a different behavior when the lid is open/closed
Automate the whole thing. I used acpid for this, but there could be better ways. Create the executable file /etc/acpi/autorandr.sh
#!/bin/bash
/usr/bin/autorandr --batch --change --default default
Create the file `/etc/acpi/events/lid-switch`
event=button/lid LID (open|close) action=/etc/acpi/autorandr.sh
And then restart acpid. The configuration switch should now happen automatically. If not, double check that `/etc/acpi/autorandr.sh` is executable.
This change would increase the complexity from a user's perspective a lot.
Honestly, after going through this, I would find it easier if autorandr treated a closed lid as disconnected (what am I going to display on it when it is closed anyway?)
Honestly, after going through this, I would find it easier if autorandr treated a closed lid as disconnected (what am I going to display on it when it is closed anyway?)
Open questions:
/proc/acpi/button/lid/LID0/state
? (I guess the answer to that is yes)laptop_output
. If it is set, then also enable the mechanism.laptop_output
is considered disconnected, profile configuration does not need any change.config option in settings.ini, something like laptop_output. If it is set, then also enable the mechanism.
As I wrote, I don't think this should be something that needs manual configuration. If it does then there's no real advantage over the block
script - users still need to know about the feature and configure something to make this work.
there is no need to store additional information (at least in this case). If laptop_output is considered disconnected, profile configuration does not need any change.
The profile must store whether the lid is supposed to be open or closed, for the profile to apply, doesn't it?
The profile must store whether the lid is supposed to be open or closed, for the profile to apply, doesn't it?
Why? The profile would just lack an internal output, no EDID, no config (or off). Just like with any other disconnected outputs.
Why? The profile would just lack an internal output, no EDID, no config (or off). Just like with any other disconnected outputs.
The config
file contains the parameters that need to be passed to xrandr. And xrandr needs to be passed the information that the internal output is to be disabled. The setup
file contains the displays attached to outputs as reported by the system. If the internal display is missing autorandr won't be able to detect that the profile applies.
Send --off
to every output that isn't listed in config.
No EDID on "disconnected" output, no EDID in profile's setup
. What is the problem?
No EDID on "disconnected" output
If the system reports that an output has a monitor attached and the setup
says that there should be none then the profile doesn't match and autorandr won't attempt to load it. If that'd change, then a profile where a notebook isn't attached to any output but its internal LCD would match even if there's something else attached.
By treating internal output as disconnected I meant faking it at info gathering stage. Inject xrandr data characteristic of a disconnected output if lid is closed. Everything else does not need to change in this case.
If autorandr receives output as disconnected
, then:
if not match["connected"]:
edid = None
This bit is already in the code. Just fake disconnected
before this if
happens.
Does every notebook expose lid state through /proc/acpi/button/lid/LID0/state? (I guess the answer to that is yes)
For some laptops, the lid state appears to be reported in /proc/acpi/button/lid/LID/state
(see this thread for example). A good catch-all seems to be /proc/acpi/button/lid/*/state
How can autorandr find out which display is the notebook's LCD? Hardcoding a couple of common names doesn't sound good enough. (Forcing users to configure this manually doesn't sound considerably better than what's possible already.)
Unfortunately, I don't know about a bulletproof approach. I would suggest using a list of common names, but make it override-able. This way we would catch 80% of the users by default, and the last 20% can fine-tune their configuration if their use-case is not covered.
How should it store the additional information about lid state? I made the promise not to break with the original autorandr's format, so this'd have to be an additional file I guess. A generic additional data file, json-encoded or .ini, probably?
What would make sense to me would be that autoxrandr would just pretend the screen is disconnected if the lid is closed. Looking at the setup files I have in my profiles, that would correspond to removing the line of the lid from the setup file when the lid is closed.
@chmduquesne Looks like Lenovo X1 Carbon is a practical example of one of the ones that use LID
as opposed to LID0
. One thing that seems confusing here is whether or not it is safe to assume that a lid always maps to a device called eDP*
. /proc/
doesn't seem to tell us which display maps to the lid...
Hi,
I developed a branch where a closed lid is treated as if it was a disconnected output. This means, essentially, that running autorandr --save
while the lid is closed will generate a setup
file without a line for the lid. This line will still be present when the lid is open.
This is of course not backward compatible with current configurations, but I think it matches better what any user would expect. I know @phillipberndt wants to stay backward compatible, but I find it silly to make this behavior optional, because I can't think of anyone who would like to configure an output they can't see. If there is a situation justifying doing this, I am willing to modify my PR, but I am curious to read about it.
I also wrote code to trigger autorandr
automatically when the lid is open/closed. On this part, I would particularly like to have feedback: Generally I tried to avoid depending on acpid, since nowadays I don't see a reason for installing it. I ended up writing a desktop autostart script monitoring the output of libinput debug-events
, which I find pretty clean since it runs in userspace. However, there is a catch: for this to work, you must be in the group input
. I am not sure whether the benefit of running this process in userspace is a good reason enough to justify forcing the user to be in a given group. The alternative is to make this a systemd service and to run the snippet as root.
What is your general opinion? Does it make sense to make this the default? Is it desirable to keep supporting old configs? Should the lid monitor be a systemd script, or an autostart desktop entry?
edid = None
during xrandr parsing. Count connected outputs after xrandr parsing and then decide. Some comments about the two links you suggested:
The systemd service that I provided solves the problem and does not require the user to be in input
. I will make the parsing of this output a bit more rigorous, but mostly I think that libinput is the cleanest way of getting the lid events: libinput is also how window managers get keystrokes, and how wayland handles the lid.
Thanks for implementing this, this makes the decision whether to do this way easier ;-)
re 3: I'm fine with the systemd stuff as it is in the PR. Those files are in the contrib folder, and others are free to improve it later.
re 2: IMHO it'd suffice to add this once someone complains. Your version should cover almost all cases.
re 1: Sounds good, and having this logic outside the xrandr parser is nicer from a code perspective, too.
re 3: If overhead of dumping and grepping through all input events is negligible, then ok.
1 is now implemented.
I elected not to implement 2, because I believe that my version covers all cases (as I mentioned in the PR, I went through the code of the graphic drivers to determine how the output names are generated for xrandr). I would prefer to add code only if we are sure that somebody needs it.
I understand why 3 is controversial. I agree that there is an small overhead: libinput does indeed receive all input events. I tried to mitigate this by improving the regexp performance and only look at the relevant part of the events. All I can say is that I am already using this code on my personal laptop as well as my work laptop without noticeable impact, but that is a totally subjective remark.
Alternatively, I can include code for doing this based on acpid hooks in the contrib directory. I was doing this before and it was working quite well. IMHO it's a heavier dependency, but the users may choose as they wish.
@Vladimir-csp if you can come up with a better implementation, you are very welcome to do so!
Merged as is for now, thanks for your work! (Happy to accept further PRs if you guys have good ideas for improving lid event integration.)
Cool, thanks!
As far as I am concerned, this issue can be closed, then 🙂
Thanks! I've tested it. There was an issue, fix in PR.
In case anyone is interested, I used acpid
to trigger autorandr
on lid change.
sudo pacman -S acpid
sudo systemctl enable --now acpid
Then in /etc/acpi/handler.sh
I added this call on the lid close and open to trigger autorandr
the same way udev does.
systemctl start --no-block autorandr.service
acpid
also supports custom event configuration in /etc/acpi/events/
so I guess this may be another way to do it
I used NixOS own module for acpid:
services.acpid = {
enable = true;
lidEventCommands = ''
#!${pkgs.bash}/bin/bash
export DISPLAY=:0
if grep -q open /proc/acpi/button/lid/LID/state; then
${pkgs.sudo}/bin/sudo -u ivan ${pkgs.autorandr}/bin/autorandr all
else
${pkgs.sudo}/bin/sudo -u ivan ${pkgs.autorandr}/bin/autorandr monitor
fi
'';
};
In plain it looks similar to this:
cat /nix/store/grkf04p1asj2q07ac472njl8wi8lz4np-acpi-events/lidEvent
───────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ File: /nix/store/grkf04p1asj2q07ac472njl8wi8lz4np-acpi-events/lidEvent
───────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ event=button/lid.*
2 │ action=/nix/store/l333rww8bci83pnwbr06i1la0kcfcs1p-lidEvent.sh/bin/lidEvent.sh '%e'
───────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cat /nix/store/l333rww8bci83pnwbr06i1la0kcfcs1p-lidEvent.sh/bin/lidEvent.sh
───────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ File: /nix/store/l333rww8bci83pnwbr06i1la0kcfcs1p-lidEvent.sh/bin/lidEvent.sh
───────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ #!/nix/store/a54wrar1jym1d8yvlijq0l2gghmy8szz-bash-5.1-p12/bin/bash
2 │ export DISPLAY=:0
3 │
4 │ if grep -q open /proc/acpi/button/lid/LID/state; then
5 │ /nix/store/rh30apmhk2vsnzd9dp60zyfni87v500i-sudo-1.9.7p2/bin/sudo -u ivan /nix/store/igzf3bhn1brjvx07mi2yw270f7c1npab-autorandr-1.11/bin/autorandr all
6 │ else
7 │ /nix/store/rh30apmhk2vsnzd9dp60zyfni87v500i-sudo-1.9.7p2/bin/sudo -u ivan /nix/store/igzf3bhn1brjvx07mi2yw270f7c1npab-autorandr-1.11/bin/autorandr monitor
8 │ fi
Here is a small script I created & it worked for me without issues:
#!/bin/bash
# Allows to automatically disable/enable the laptop screen when the lid is opend/closed
sudo pacman -S acpid --needed --noconfirm
sudo mkdir /etc/acpi/actions
sudo tee /etc/acpi/actions/lid.sh > /dev/null <<EOT
#!/bin/bash
# Automatically enable/disable output to Laptop (LVDS1) when lid close/open event happens
export XAUTHORITY=/home/$USER/.Xauthority
export DISPLAY=":0.0"
case "$3" in
close)
logger 'LID closed'
xrandr --output LVDS1 --off
;;
open)
logger 'LID opened'
xrandr --output LVDS1 --auto
;;
*)
logger "ACPI action undefined: $3"
;;
esac
EOT
sudo tee /etc/acpi/events/lid > /dev/null <<EOT
event=button/lid LID (open|close)
action=/etc/acpi/actions/lid.sh
EOT
sudo chmod +x /etc/acpi/actions/lid.sh
# remove 'anything' event handler
sudo rm /etc/acpi/events/anything
# restart acpid
sudo systemctl stop acpid
sudo systemctl enable acpid
sudo systemctl start acpid
Checked in at https://github.com/Xcalizorz/endeavouros-i3wm-setup/blob/main/custom-scripts/install-acpid-events.sh
For what it's worth, with current autorandr the lid is handled exactly as I expect, i.e. "lid closed" means internal monitor is disconnected. However, I need to manually run autorandr --change
to detect this. It would be great if autorandr were to run automatically when the lid is closed/opened.
For what it's worth, with current autorandr the lid is handled exactly as I expect, i.e. "lid closed" means internal monitor is disconnected.
Yes, that was implemented in #169.
However, I need to manually run
autorandr --change
to detect this. It would be great if autorandr were to run automatically when the lid is closed/opened.
For this to happen, make sure contrib/etc/xdg/autostart/autorandr-lid-listener.desktop is installed properly.
Alternatively, you can run the script I suggested in #269, available in https://github.com/chmduquesne/autorandr/blob/dbus_monitor/contrib/autorandr_dbus_monitor.sh, which can replace every script that triggers autorandr.
Thanks! Why not close this issue as fixed then? :-).
To handle situations like laptop lid being closed or open with regards to external monitor:
Lid states can be acquired from /proc/acpi/button/lid/*/state