#!/bin/bash

# granger.sh
#   determine active screen based on mouse cursor location,
#   launch ranger in urxvt and center window on that screen
#
# ed <irc.rizon.net> MIT-licensed
# https://ocv.me/dev/?granger.sh
#
# install:
#   xfconf-query -c xfce4-keyboard-shortcuts -p "/commands/custom/<Shift><Alt>f" -n -t string -s "/usr/local/bin/granger.sh"
#   xfconf-query -c xfce4-keyboard-shortcuts -p "/commands/custom/<Shift><Alt><Primary>f" -n -t string -s "/usr/local/bin/granger.sh -s"

dbg()
{
	return
	echo "$@"
}

miss=
for c in ranger urxvt xdotool xrandr
do
	command -v $c >/dev/null ||
		miss="$miss $c"
done
[ -z "$miss" ] || {
	echo "missing commands:$miss"
	exit 1
}

sudo=
[ "$1" = -s ] &&
	sudo=sudo && shift

# generate window title based on current uptime
wt="ranger $(printf %x $(sed -r 's/ .*//;s/\.//' /proc/uptime))"

# determine mouse cursor location
eval "$(xdotool getmouselocation --shell 2>/dev/null)"

dbg "title $wt"
dbg "mouse [$X] [$Y]"

getscreen()
{
	xrandr |
	perl -e '
		use strict;
		my $cx = int('$X');
		my $cy = int('$Y');
		my $ww = int('$W');
		my $wh = int('$H');
		while (<>)
		{
			# find xrandr screen size/position declarations
			next unless /^[^ ]+ connected[^0-9]* ([0-9]+)x([0-9]+)\+([0-9]+)\+([0-9]+)/;
			my $w = int($1);
			my $h = int($2);
			my $l = int($3);
			my $t = int($4);
			my $r = $w + $l;
			my $b = $h + $t;
			# printf("%s<%s<%s %s<%s<%s\n", $l, $cx, $r, $t, $cy, $b);

			# check if mouse cursor is within this screen
			if ($cx >= $l && $cx < $r && $cy >= $t && $cy < $b)
			{
				if ($w < $ww) { $ww = $w; }
				if ($h < $wh) { $wh = $h; }
				my $x = $l + int(($w - $ww)/2);
				my $y = $t + int(($h - $wh)/2);
				printf("X=%s\nY=%s\nW=%s\nH=%s\n", $x, $y, $ww, $wh);
				exit 0;
			}
		}

		# could not determine active monitor
		print "X=-1\nY=-1\n";
	'
}

center()
{
	# wait until the urxvt window appears
	for ((n=0; n<100; n++))
	do
		wid=$(xdotool search --name "$wt") && break
		read -t0.05 || true
	done

	dbg "hwnd [$wid]"

	# abort if it didn't
	[ -z "$wid" ] && return

	# determine current window location and dimensions
	eval "$(
		{
			xdotool getwindowgeometry $wid |
			grep Geometry: |
			sed -r 's/.*Geometry: *([^ ]*)x([^ ]*).*/W=\1\nH=\2/'

			printf 'W=-1\nH=-1\n'
		} |
		head -n 2
	)"

	dbg "geom [$W] [$H]"

	# abort if that somehow failed
	[ $W -eq -1 ] && [ $H -eq -1 ] && return

	# determine new window size (if larger than active screen)
	# and the position which would make the window screen-centered
	eval "$(getscreen)"
	dbg "wloc ${W}x${H}+$X+$Y"

	# return if active montior could not be determined
	[ $X -eq -1 ] && [ $Y -eq -1 ] && return

	# move and resize the ranger urxvt
	xdotool windowmove --sync $wid $X $Y
	xdotool windowsize --sync $wid $W $H
}

# start scanning for the ranger window in the background
center &

# create urxvt window running ranger
urxvt -geometry 169x50 -title "$wt" -bl -sb -e $sudo ranger
