#!/usr/bin/perl

use warnings;
use strict;
use Data::Dumper;
use Getopt::Long;

use constant XMOUSEPOS => 'xmousepos';

my %options =
 (
  x => 1920,
  y => 1200,
  1 => '',				# TL
  2 => '',				# TR
  3 => '',				# BR
  4 => '',				# BL
  idle => 3,
  size => 15,
 );

GetOptions (
	    \%options,
	    "x=i",
	    "y=i",
	    "1|tl=s",
	    "2|tr=s",
	    "3|br=s",
	    "4|bl=s",
	    "i|idle=i",
	    "s|size=i",
	    "h|help",
	   );

if (exists $options{help})
{
 print <<EOHIPPUS;
$0

Options (defaults shown):
  X and Y dimensions of the monitor:
  --x $options{x}
  --y $options{y}

  Idle time before triggering a command (in seconds):
  --idle $options{idle} (or -i)

  Spot size in pixels:
  --size $options{size}

  Commands to run (numbered from top left, empty by default):
  --1 COMMAND # also --tl
  --2 COMMAND # also --tr
  --3 COMMAND # also --br
  --4 COMMAND # also --bl

EOHIPPUS
 exit;
}

my %state = (last => -1);

while (1)
{
 open X, XMOUSEPOS() . '|';
 $_ = <X>;
 my ($x, $y) = m/(\d+)\s+(\d+)/;
 close X;
# printf "coords %d %d\n", $x, $y;
 my $command = choose_command(\%state, \%options, $x, $y);
 sleep 1;
}

sub get_spot
{
  my $options = shift @_;
  my $x       = shift @_;
  my $y       = shift @_;

  return 1 if $x < $options->{size} && $y < $options->{size};
  return 2 if $x > $options->{x}-2-$options->{size} && $y < $options->{size};
  return 3 if $x > $options->{x}-2-$options->{size} && $y > $options->{y}-2-$options->{size};
  return 4 if $x < $options->{size} && $y > $options->{y}-2-$options->{size};

  return undef;
}

sub choose_command
{
 my $state   = shift @_;
 my $options = shift @_;
 my $x       = shift @_;
 my $y       = shift @_;

 my $spot = get_spot($options, $x, $y);

 unless (defined $spot)
 {
  delete @state{1..4};
  return;
 }

 $state->{$spot}++;

 if ($spot != $state->{last})
 {
  delete @state{grep { $_ ne $spot } keys %$state};
  $state->{last} = $spot;
 }

# print Dumper $state;

 return if $state->{$spot} != $options->{idle};
 
 return unless $options->{$spot};
 print "Triggered command $options->{$spot}\n";
 system $options->{$spot};
}

