#!/usr/bin/perl

# Copyright (C) 2007-2019 by X2Go project, https://wiki.x2go.org
#       Oleksandr Shneyder <o.shneyder@phoca-gmbh.de>

# X2Go 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.
#
# X2Go 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.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.


use strict;
use File::Path::Expand;
use IPC::Open3;

sub catch_term
{
	system ("killall --user x2gothinclient --wait x2goclient");
	system ("killall --wait Xorg");
	system ("killall --user x2gothinclient --wait pulseaudio");
	system ("killall --user x2gothinclient --wait dbus-daemon");
	system ("killall --user x2gothinclient --wait dbus-launch");
	unlink("/var/run/x2gothinclient.pid");
	exit;
}

sub check_x
{
	my $x=`ps ax | grep X`;
	if ( $x=~m/Xorg/ )
	{
		return 1;
	}
	return 0;
}

sub check_pulse
{
	my $pulse=`ps ax | grep pulse`;

	if ( $pulse=~m/pulseaudio/)
	{
		return 1;
	}
	return 0;
}

sub check_client
{
	my $client=`ps ax | grep x2goc`;

	if ( $client=~m/lient/)
	{
		return 1;
	}
	return 0;
}

# make sure the .halt file is not present when we start this script
system("rm -f ~x2gothinclient/.halt");

# pre-load the thinclient initialization script
system("su x2gothinclient -c \". /etc/x2go/x2gothinclient_init\"");

# fork to background, check if forked state is ok...
my $pid = fork();
if (not defined $pid)
{
	print "resources not avilable.\n";
}
elsif ($pid != 0)
{
	open (F,">/var/run/x2gothinclient.pid");
	print F "$pid\n";
	close(F);
}
elsif ($pid == 0 )
{

	# silence this daemon script completely...
	close(STDOUT);
	close(STDERR);

	$SIG{TERM}=\&catch_term;

	while(sleep 1)
	{
		# test if shutdown button on X2Go Client was clicked
		if (-e expand_filename("~x2gothinclient/.halt"))
		{
			# when used with plymouth, make sure we stay on the correct terminal
			system("killall Xorg");
			system("shutdown -h now");
			system("chvt 7");
		}
		# test if XServer is running, if not launch it...
		if ( check_x() ==0 )
		{
			system("/usr/bin/Xorg -br &");

			# wait for X-Server to come up
			sleep(3);

			# Align displays next to each other in order of appearance in xrandr, unless touch
			# devices are detected - in that case, clone displays so that touchable area and display
			# stay aligned.  This fix has been introduced for a certain make of wacom touch-sensitive
			# displays.  If you have a touch-sensitive device that isn't affected by this, or that
			# is negatively affected by this fix, please let us know so we can add a better detection.
			# The fix is bypassed if a mouse device is detected.
			# Note that you can manually override the behavior by passing a kernel parameter
			# xinerama=above|below|same-as|left-of|right-of to override the autodetection.

			# check if a xinerama kernel parameter is set
			my $xrandrcmdtainted = `cat /proc/cmdline | tr ' ' '\n' | awk -F '=' '\$1 == "xinerama" { print \$2 }'`;
			my $xrandrcmd;
			if ($xrandrcmdtainted =~ /(^above$|^below$|^same-as$|^left-of$|^right-of$)/)
			{
				# if the parameter value matches one value of the defined set, use that
				$xrandrcmd = $1;
			}
			else
			{
				# else default to "left-of", which was our standard behavior in previous versions
				$xrandrcmd = "left-of";
			}

			# find out how many touch devices we have
			my $touchdevicescount = `DISPLAY=:0 LANG=C xsetwacom --list devices | wc -l`;

			# find out how many mouse devices we have
			my $micecount = `find /dev/input -maxdepth 1 -name "mouse*" | wc -l`;

			# declare two variables for the upcoming loop
			my $this_display;
			my $next_display;

			# loop through the following code block for all connected display devices
			foreach (`DISPLAY=:0 LANG=C xrandr 2>/dev/null | grep ' connected ' | cut -d ' ' -f1`)
			{
				# assign a value to $next_display and remove newline from it
				chomp ($next_display = $_);

				# $this_display won't be defined until the second time the loop is executed, which is a
				# neat way of running xrandr only if there are at least two connected display devices
				if (defined($this_display))
				{
					if (($touchdevicescount > 0) && ($micecount < 1) && ($xrandrcmdtainted eq ""))
					{
						# we have a touch device and no mice, and no xinerama parameter was set,
						# so switch to clone view to make the touch device usable
						`DISPLAY=:0 /usr/bin/xrandr --output $next_display --same-as $this_display`;
					}
					else
					{
						# else use whatever is in $xrandrcmd (which is either our default of "left-of",
						# or a valid xinerama kernel parameter value)
						`DISPLAY=:0 /usr/bin/xrandr --output $next_display --$xrandrcmd $this_display`;
					}

				}

				# now set $this_display -> every subsequent iteration of the loop will now enter the code block
				# above where (defined($this_display)) is the conditional
				$this_display = $next_display;
			}
			# set screen background to X2Go default blue on all detected screens
			`DISPLAY=:0 xsetroot -solid "#246ed8"`;

		}

		# test if pulseaudio is running, if not launch it...
		if ( !check_pulse() )
		{
			system("su - x2gothinclient -c \"DISPLAY=:0 pulseaudio -D " .
			       "-L 'module-native-protocol-tcp port=4713' " .
			       "--exit-idle-time=65535\"");
		}

		# test if x2goclient is running, if not launch it...
		if ( !check_client() ) {
			open (F,">/tmp/startwrap");
print F "#!/bin/bash

  set +e
. /etc/X11/Xsession.d/20dbus_xdg-runtime
. /etc/X11/Xsession.d/75dbus_dbus-launch
. /etc/X11/Xsession.d/90gpg-agent
. /etc/X11/Xsession.d/95dbus_update-activation-env
  set -e\n";
			close (F);
			qx(cat /etc/x2go/x2gothinclient-displaymanager_start >> /tmp/startwrap);
			chmod(0755, "/tmp/startwrap");
			qx(su - x2gothinclient -c \"export DISPLAY=:0; /tmp/startwrap 1>/dev/null 2>/dev/null\");
		}
	}
}
