#!/bin/sh
#
#  xfce4
#
#  Copyright (C) 1999, 2003 Olivier Fourdan (fourdan@xfce.org)
#  Copyright (C) 2011       Guido Berhoerster (guido+xfce.org@berhoerster.name)
#  Copyright (C) 2011, 2016, 2017 Jarno Suni (8@iki.fi)
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
set -eu
unset -v IFS
display_off_timeout=15

export PATH=/usr/local/bin:$(command -p getconf PATH)
# Note that adding /usr/local/bin explicitly is not needed here, except
# maybe for testing, or if you want to allow locally build software.

# Lock by a known screensaver, if its daemon is running
for lock_cmd in \
  light-locker \
  mate-screensaver \
  cinnamon-screensaver \
  gnome-screensaver
do
  lock_cmd=${lock_cmd}-command
  [ -n "$($lock_cmd --query 2>/dev/null)" ] &&
   $lock_cmd --lock && exit
done
xscreensaver-command -lock </dev/null >/dev/null 2>&1 && exit

# Run command with DPMS, if wanted.
# First argument is boolean one telling, if this should touch DPMS setting.
# Rest arguments are command with its arguments.
command_dpms() {
	set_dpms="$1"
	shift
	[ "$set_dpms" = true ] && {
		# Save the state of DPMS; rely on the output format of `xset q`.
		xstate=$(xset q | awk '/^DPMS /{getline; printf "%s %s %s ", $2, $4, $6;
			getline; if($3=="Enabled"){print "+"}else{print "-"}exit}')
		# Enable monitor power management
		xset dpms 0 0 "$display_off_timeout"
	}
	error_code=0
	$* || error_code=$?
	[ "$set_dpms" = true ] && {
		# Restore DPMS state
		xset dpms $(printf %s "$xstate" | cut -d' ' -f1-3)
		xset $(printf %s "$xstate" | cut -d' ' -f4)dpms
	}
	return $error_code
}

# Use custom lock expression, if given
LOCK_CMD=$(xfconf-query -c xfce4-session -p /general/LockCommand || :) 
[ -n "$LOCK_CMD" ] && {
	LOCK_SET_DPMS=$(xfconf-query -c xfce4-session -p /general/LockSetDPMS || :)
	LOCK_WAIT_COMPLETE=$(xfconf-query -c xfce4-session -p /general/LockWaitComplete || :)

	[ "$LOCK_WAIT_COMPLETE" = true ] && {
		exit_code=0;
		command_dpms "$LOCK_SET_DPMS" $LOCK_CMD || exit_code=$?
	} || {
		command_dpms "$LOCK_SET_DPMS" $LOCK_CMD &
		pid=$!
		sleep 1 & # wait at most this long time
		pid_sleep=$!
		# Test, if command_dpms is running after small delay.
		while kill -0 "$pid" 2>/dev/null; do
			kill -0 "$pid_sleep" 2>/dev/null || {
				# command_dpms still running after the maximum delay
				exit 0 # suppose lock_cmd locked
			}
			sleep 0.1 || ( : ) # small delay, needed for some reason.
		done

		# command_dpms finished; get the exit code
		exit_code=0; wait "$pid" || exit_code=$?
	}

	[ "$exit_code" -eq 0 ] && exit 0 # suppose LOCK_CMD locked in background
	>&2 printf "'%s' exited with error %s\n" "$LOCK_CMD" "$exit_code"
}

# these fallback lockers do not fork
for lock_cmd in \
	'i3lock --nofork' \
	'xtrlock -b' \
	'slimlock' \
	'slock' \
	'alock -bg blank -auth pam' \
	'xlock -mode blank'
do
	set -- $lock_cmd
	if command -v -- "$1" >/dev/null 2>&1; then
		command_dpms true $lock_cmd &
		exit 0
	fi
done

# else access locking failed
exit 1
