How to run a script when the lid is closed?
I am trying to configure my laptop running LUbuntu 18.04 to first go to the login screen, and then after the login screen is displayed, the suspend. The reason for this is that the default of simply suspending and then displaying the login screen on resume results in a delay of about 5 seconds before the login screen is displayed upon resume, whereas if the login screen is already up when the machine is suspended, it is available almost instantly on resume.
In any case, I have been researching how to do this, and it seems like my best option is to simply run a script when the lid is closed which first calls dm-tool lock
followed by a delay if needed to wait for the login screen to be display, and then systemctl suspend
.
However, how to I link the action of the lid being closed to running this script? From my research it appears that acpid
is the way to go. From reading the man page, it appears that there needs to be an executable script in /etc/acpi/events
called lidbtn
. The directory exists on my system but no such script exists, and the man page is unclear as to exactly what it needs to contain. Looking at the other scripts in this directory it appears that I need to know what to put for the "event=" line, but I haven't found this anywhere.
There is also mention of the window manager handling this event, and it is unclear what I need to do to make sure my script doesn't conflict with that. Under the Xfce Power Manager (Menu -> Preferences -> Power Manager) under the General tab I see "When laptop lid is closed"... Suspend, but the only other choices are "Switch off display" and "Lock screen". There is no choice for "do nothing". What do I need to do here? Does the requested action happen before or after whenever acpid script I might create get executed, or does that completely override this?
Solution 1:
First, I created a new file /etc/acpi/events/laptop-lid
containing the following:
event=button/lid.*
action=/etc/acpi/laptop-lid.sh
Then I created /etc/acpi/laptop-lid.sh
containing this code:
#!/bin/bash
source $HOME/.Xdbus
grep -q closed /proc/acpi/button/lid/LID/state
if [ $? = 0 ]
then
# close action
dm-tool switch-to-greeter
sleep 5
systemctl suspend
else
# open action
fi
In $HOME/.Xdbus
I put the following:
export XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0
And I made /etc/acpi/laptop-lid.sh
executable (chmod a+x
).
Then I ran
/etc/init.d/acpid restart
Finally, I went into XFCE Power Manager and set it to "Switch off display" when the laptop lid is closed, so as to avoid conflicting with my new, improved functionality.
However, I found there was still a problem - after I came out of suspend, the login screen would be displayed and then the machine would suspend again. After a bit of searching I think this is due to a bug in Ubuntu that apparently still exists in 18.04. I worked around it by checking if more than 6 seconds have passed since I tried to sleep 5 seconds, and if so I don't suspend. It seems like my laptop actually suspends in under 2 seconds, so this is always working for me. I tried setting Xfce to lock the screen, but it didn't seem to honor that either - in both cases, my machine was suspended in under 2 seconds, whereas my script should be forcing it to wait at least 5.
Update:
After doing all of this, I was still totally unsatisfied. Because my XFCE Power Manager settings are basically ignored leading the machine to always sleep when I close the lid, this creates a race condition between the sleep process and how far the dm-tool gets towards creating the greeter, which always results in some delay on resume while that process finishes bringing up the greeter. So I totally undid all of the above work and instead did the following:
Edit ~/.config/openbox/lubuntu-rc.xml
. Find the key binding to lock the screen and change it to switch to the greeter instead. The main effect of this seems to be to not turn off the display, which seems important to making the greeter show up instantly on resume:
<keybind key='W-L'>
<action name='Execute'>
<command>dm-tool switch-to-greeter</command>
</action>
</keybind>
Now instead of closing the lid, I hit Win+L, and as soon as the greeter appears I then close the lid.
Note: I wanted to have a separate script that first switches to the greeter, then suspends, but it seems like no matter how I try to suspend (systemctl, dbus, etc.) they all refuse to suspend from the lock screen without manual intervention - entering a password from a dialog box - that impossible to satisfy because we are at the lock screen!