#!/bin/sh
# A simple NX client
# Copyright(C) 2010 Miguel Angel Alvarez <maacruz@gmail.com>

# 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 3 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, see <http://www.gnu.org/licenses/>.

#set -x

WMCTRL=$(which wmctrl)
XBINDKEYS=$(which xbindkeys)


cleanup()
{
	[[ $xbkpid ]]&&kill $xbkpid&&echo snx: xbindkeys stopped
	exit
}

# main
MODE="-R"
if [[ "${1#-}" != "$1" ]]; then
	case "${1#-}" in
	"d"|"D")
		MODE="-D"
		shift
		;;
	*)
		echo A simple nx client for the NITs
		echo Usage: snx [-d] [user@host] [command]
		echo environment variable NXHOST can be set to user@host to avoid typing
		echo the address every time
		echo if command is not provided a xterm will be opened
		echo remote windows are locally managed, unless \"-d\" is provided
		echo \"-d\" opens a remote desktop
		echo Install telescope if you have problems with \"lost\" windows
		echo or switching from/to the nx desktop
		echo Install wmctrl and xbindkeys to be able to fullscreen remote windows
		echo Examples:
		echo Open kde3 desktop: snx -d user@host startkde
		echo Open firefox: snx user@host firefox
		echo Open xterm: snx user@host
		echo Some kde3 fun in your tablet: snx user@host \"kicker --nofork\"
		echo "If NXHOST is defined (export NXHOST=user@host): snx [command]"
		echo to override NXHOST: snx otheruser@otherhost command
		exit 1
		;;
	esac
fi 
if [[ $# == 2 ]]; then
	NXHOST="$1"
	shift
fi
if [[ "$NXHOST" == "" ]]; then
	if [[ "$1" != "" ]]; then
		NXHOST="$1"
		shift
	else
		echo Please provide your ssh account
		exit 1
	fi
fi

if [[ $WMCTRL ]]&&[[ $XBINDKEYS ]]; then
	if [[ $(busybox ps|awk '$5 ~ /xbindkeys$/ {print $1}') ]]; then
		echo snx: xbindkeys is already running
	else
		$XBINDKEYS -n -f /etc/xbindkeysrc.snx -fg /dev/none &
		xbkpid=$!
		trap cleanup SIGINT SIGTERM SIGHUP SIGQUIT
		echo snx: Starting xbindkeys, fullscreen key will work on nx windows
	fi
fi

# if remote command is not provided, use xterm
COMMAND="$1"
[[ "$COMMAND" == "" ]]&&COMMAND="xterm -fg \"#000000\" -bg \"#ffffff\""

# NXDISPLAY is hardcoded by now, so only one session by host
NXDISPLAY=1011
NXPORT=$(expr 4000 + $NXDISPLAY)

# xmodmap hack to make the keyboard work
# Fn (N810 keycode 216, N900 keycode 108) has to be changed to ISO_Group_Latch to work (ISO_Level3_Shift doesn't, why?)
# Chr locks/unlocks upper 4 levels
# Fn + Shift locks shift
# N810 (keycode 135): Fn + Chr locks/unlocks Fn
if [[ "$OSSO_PRODUCT_NAME" == "N900" ]]; then
	KEYMAP=$(echo -e "$(DISPLAY=:0 xmodmap -pke|awk '(NF>3)&&($2!=50)&&($2!=37)&&($2!=108) { if (NF>7) {$6 = $8; if (NF>8) $7 = $9; else $7 = $8}; print $0 }')""\nkeycode 50 = Shift_L Shift_L Shift_Lock Shift_Lock Shift_L Shift_L Shift_L Shift_L\nkeycode 37 = Control_L Control_L Multi_key ISO_Prev_Group ISO_Next_Group ISO_Next_Group ISO_First_Group ISO_First_Group\nkeycode 108 = ISO_Group_Latch")
else
	KEYMAP=$(echo -e "$(DISPLAY=:0 xmodmap -pke|awk '(NF>3)&&($2!=50)&&($2!=135)&&($2!=216)')""\nkeycode 50 = Shift_L Shift_L Shift_Lock Shift_Lock Shift_L Shift_L Shift_L Shift_L\nkeycode 135 = Multi_key ISO_Prev_Group ISO_Next_Group ISO_Next_Group ISO_First_Group ISO_First_Group ISO_First_Group ISO_First_Group\nkeycode 216 = ISO_Group_Latch")
fi
# Make sure we are connected
dbus-send --system --print-reply --type=method_call --dest=com.nokia.icd /com/nokia/icd com.nokia.icd.connect string:"[ANY]" uint32:0 >/dev/null

# To avoid the whole thing showing in process listing in the remote server
# send some of the code through stdin into the remote side 
REMOTE_ENVIRON=$(cat<<END
export KEYMAP=\""$KEYMAP"\"
export DISPLAY=nx/nx,link=modem,accept=127.0.0.1:$NXDISPLAY
END
)

# Start a ssh tunnel and run nxagent in the remote side
# when nxagent is awaiting for connection launch nxproxy in this side
# In the remote side once nxagent has a session started launch the command
# and when the command finishes kill nxagent
# In the local side once the session has started wait for the NX window to appear and make it fullscreen if in desktop mode
# Session is non persisten because I haven't managed to reconnect

echo Connecting to $NXHOST...
echo $REMOTE_ENVIRON|ssh -L $NXPORT:localhost:$NXPORT "$NXHOST" \
	"eval $(cat)\ 
	nxagent -nopersistent $MODE :$NXDISPLAY 2>&1|while read line; do \
		echo "\$line"
		if [[ \"\${line#Session: Session started}\" != \"\$line\" ]]; then
			export DISPLAY=:$NXDISPLAY
			echo \"$KEYMAP\"|xmodmap -
			echo RUNNING >&2
			"$COMMAND"
			sleep 5
	 		agentpid=\$(ps axj |awk -v ppid=\$\$ '(\$1 == ppid)&&(\$10 ~ /nxagent$/) {print \$2}') >&2
			[[ \$agentpid ]]&&kill \$agentpid
		fi
	done"|while read line; do
		echo Server says: $line
		if [[ "${line#Info: Waiting for connection}" != "$line" ]]; then
			nxproxy -S localhost:$NXDISPLAY 2>&1|while read line; do
				echo Client says: $line
				if [[ $WMCTRL ]]&&[[ "${line#Session: Session started}" != "$line" ]]&&[[ "$MODE" == "-D" ]]; then
					t=0
					while [[ ! $WID ]]&&[[ $t -lt 100 ]]; do
						WID=$(wmctrl -l|awk '(NF == 4)&&($4 == "NX") {print $1}')
						/usr/share/snx/usleep 100000
						let t+=1
					done
					[[ $WID ]]&&wmctrl -i -r $WID -b toggle,fullscreen
				fi
			done
		fi
	done

cleanup

