2022-05-07 Integrating swaylock-mobile with Sxmo 2/?
Sxmo 1.9.0 was released last weekend for PostmarketOS edge, which means … I have continued my work on the screenlocker as promised. In this part I'll mostly explain what needed to be done (and why) for the screenlocker to work.
What my current solution can and can't do
Current sate of swaylock-mobile is, that it's a pretty standard swaylock that fits on a touchscreen (even when rotated!) with a keypad for entering numeric pins without a real keyboard, that is enough to integrate it into Sxmo and get some additional security for my phone in daily use.
So the integration currently handles:
- Locking the screen, before turning it off
- Proximity-lock for both locked and unlocked states
- State-management for the idle locker and lisgd
More important, what does it NOT handle:
- X integration, I have not tested it with the dwm version
- Graceful degradation, fallback in case there is no screenlocker doesn't work
- Maybe I have broken some suspend inhibitors … I did
- Remaining slightly broken states
New Wrapper script run-screenlocker
This is a script that runs swaylock-mobile until it exits with a success status-code (the warning that you should make sure it is restarted in case of a crash still applies) and after that calls the unlock hook. This script gets called from the lock hook and should be the only thing that can call the unlock hook. (one exception would be the fallback …)
Hooks that were modified
- The Powerbutton now only toggles screenon and screenoff and calls the lock hook before off, also the corner-swipe locks the screen and turns it off.
- Just does, what it says on the tin: locking, also makes sure it only locks when called from an unlocked sate, also invokes the new idlelocker hook.
- The proximitylock now calls the screenon hook instead of the unlock hook, also disabled the can_suspend locks.
- Now uses $SXMO_STATE.screen for storing screen state.
- Now uses the idlelocker hook for setting the screenlocker.
Hooks that were added
- Sets the idlelocker for screenon scenarios, depending on the SXMO_STATE.
- Gets called for turning the screen on (and some screen related services).
There is a new file to keep track of things, previously $SXMO_STATE was used for storing three states sxmo could be in: screenoff, locked and unlocked.
These states would still be sufficient, but the model with a state for the lock (locked and unlocked) and a state for the screen (on and off), which allows me to simplify the previously error prone and complex state machine into two state-machines which just turn things on and off without having to make assumptions about the screen-state or the lock status.
For that I needed a second state-file though which I called $SXMO_STATE.screen for now (clean solution would be to introduce a $SXMO_SCREEN_STATE and $SXMO_LOCK_STATE).
New environment variable: SXMO_REASON
Before rewriting the state-machines, I tried to work with the old states and figuring out what to do depending on where the call came from, which turned out to be a horrible buggy mess, but its the reason SXMO_REASON was introduced.
Why is it still there you ask: Because if the screen is locked and the proximity-lock triggers in most of the cases you don't want the screen to turn on again by just uncovering the proximity sensor… the screenon hook script currently uses it to cancel if this variable is set to proximity-lock and the lockscreen is active. (Someone could make that a preference, however it won't work when the system goes to sleep)
Additional sway configuration
One thing that isn't immediately obvious is that you want to turn your screen back on again and that it doesn't work with the default configuration, the reason being that sway detects when a proper screenlocker is active it only allows keyboard bindings (the power-button behaves as if it was the XF86PowerOff key on a keyboard) when they are bound with a --locked switch, so I put a bindsym into my sway config file, the cleaner way would have been to update sxmo_swayinitconf.sh (I did it that way because I hope this way it will break less often than modifying the swayinitconf script).
Fixing the remaining TODOs
It doesn't work with X
I (or someone who knows sxmo) would have to make sure all modifications are also applied to the dwm version (not sure about how to solve the power-button problem though)
Graceful degradation in case of missing/disabled screenlocker
My approach would be a dummy screenlocker, that creates a file somewhere and then watches it for close_writes with inotifywait (and deletes it after), the handler for the power-button in the file exists + locked + screen on would touch that file, which would trigger an unlock.
Broken suspend inhibitors
The proximity-lock hook by default locks the can_suspend mutex, I leave it on for the lock-screen which blocks the suspend script from doing its job, that's not battery friendly … Lets just bypass that by disabling the lock and hope it won't break.
Slightly broken states
There are two scenarios I know of where the state handling is slightly broken, both involve the proximity-lock:
- When unlocked + proximity-lock active (sensor covered) + power button the screen turns on for a second and then goes to lock + screenoff. I currently don't know why exactly this happens as the power-button should check against the screen-state and toggle it once, turning it on …
- When locked + proximity-lock active + power button the screen turns on (like I want it when unlocked, ironically) and stays on for the 8 seconds timeout when not touched, this can be explained by how the proximity-lock currently triggers on changes (which is very good, because it saves power!)