#!/usr/bin/perl

use X11::GUITest qw/GetWindowName SetWindowName GetInputFocus IsWindow IsKeyPressed/;
use X11::Protocol;
use X11::Keyboard;

my @ps = split "\n", `ps -ef|awk '{print \$2 " " \$9}'`;
my ($pid) = grep($_ =~ /keylistener\.pl/, @ps);
($pid) = split /\s/, $pid;
if($pid && $pid != $$)
{
  print "Terminating $pid\n";
  kill 15, $pid;
  exit;
}

$x = X11::Protocol->new();
$kbd = X11::Keyboard->new($x);
my $win = GetInputFocus();
my $origname = GetWindowName($win);
my $setname;
$main::term = 0;

$SIG{'TERM'} = 'term_handler';

my $code = &GetKey();
my $keystate = 0;

while(IsWindow($win) &! $main::term)
{
  my $currentname = GetWindowName($win);
  if($currentname ne $setname)
  {
    $origname = $currentname;
    $setname = $origname." (Key $code captured)";
    SetWindowName($win, $setname);
  }
  if(GetInputFocus() != $win)
  {
    if(IsKeyPressed($code))
    {
      if(!$keystate)
      {
        $x->SendEvent($win, 1, $x->pack_event_mask("KeyPress"),
		$x->pack_event(
			'name'=>"KeyPress",
			'detail'=>$kbd->KeysymToKeycode($code),
			'state'=>0,
			'time'=>time,
			'root'=>$x->root(),
			'same_screen'=>1,
		));
	$x->flush();
        $keystate = 1;
      }
    }
    elsif($keystate)
    {
        $x->SendEvent($win, 1, $x->pack_event_mask("KeyRelease"),
		$x->pack_event(
			'name'=>"KeyRelease",
			'detail'=>$kbd->KeysymToKeycode($code),
			'state'=>0,
			'time'=>time,
			'root'=>$x->root(),
			'same_screen'=>1,
		));
	$x->flush();
      $keystate = 0;
    }
  }
  select(undef, undef, undef, 0.01);
}

SetWindowName($win, $origname);
print "Releasing keycode $code\n";
exit;

sub term_handler
{
  $main::term = 1;
}

sub GetKey
{
  my $keypressed;
  my $code;
  open my $fh, "xev -name 'Press a Key' -geometry 300x50 |";
  select($fh);$| = 1; select(STDOUT);
  while(!$code)
  {
    my $line;
    sysread($fh, $line, 10000);
    print $line;
    if($line =~ /^KeyPress event/){ $keypressed = 1; }
    if($line =~ /keycode .* ([^\) ]+)\)/){ $code = $1; }
  }
  close $fh;
  print "Found key $code (".$kbd->KeysymToKeycode($code).")\n";
  return $code;
}

