#!/usr/bin/env bash

# locker script -- makes sure that x does not give up the lock easily (using i3lock)
# simply locks the screen on wayland (using waylock)

## CONFIGURATION ##############################################################

is_wayland() {
    # alternative $(</proc/self/sessionid), see
    # https://stackoverflow.com/questions/3214935/can-a-bash-script-tell-if-its-being-run-via-cron
    if loginctl show-session "$(loginctl show-user "$(whoami)" -p Display --value)" -p Type --value | grep -q wayland; then
        true
    else
        false
    fi
}

# Options to pass to i3lock
i3lock_options="-e -f -c 1d2021"
waylock_options="--init-color #223344 --input-color #224444 --fail-color #554444"

# Run before starting the locker
pre_lock() {
    # pause all currently playing media and mute system
    type mpc >/dev/null 2>&1 && mpc -q pause
    type playerctl >/dev/null 2>&1 && playerctl -s pause
    type amixer >/dev/null 2>&1 && amixer -q set Master mute
    return
}

# Run after the locker exits
post_lock() {
    return
}

###############################################################################

pre_lock

if is_wayland; then
    # shellcheck disable=SC2086
    waylock $waylock_options
elif [ -e "/dev/fd/${XSS_SLEEP_LOCK_FD:--1}" ]; then
    # On X, we set a trap to kill the locker if we get killed, then start the locker and
    # wait for it to exit. The waiting is not that straightforward when the locker
    # forks, so we use this polling only if we have a sleep lock to deal with.
    kill_i3lock() {
        pkill -xu "$EUID" "$@" i3lock
    }

    trap kill_i3lock TERM INT

    # we have to make sure the locker does not inherit a copy of the lock fd
    i3lock "$i3lock_options" {XSS_SLEEP_LOCK_FD}<&-

    # now close our fd (only remaining copy) to indicate we're ready to sleep
    exec {XSS_SLEEP_LOCK_FD}<&-

    while kill_i3lock -0; do
        sleep 0.5
    done
else
    trap 'kill %%' TERM INT
    i3lock -n "$i3lock_options" &
    wait
fi

post_lock
