#!/usr/bin/perl -w

use X11::Protocol;

# This script is written by Andrei Perhinschi
# and modified by Atsushi Kawai.
# It is licensed under the GNU GPL license
# http://www.gnu.org/licenses/gpl.html
#
# Much thanks goes to Daniel Forchheimer (http://www.forchheimer.se/)
# for creating transset-df and the eutotrans
# script from which this script gets its inspiration


if ( !defined $ARGV[0] ) {
    die "Usage: focustran <app-list-file>\n";
}

$infile = $ARGV[0]; # list of applications to be translucent
$trans_val = 0.7;  # alpha for transparent win
$trans_val = "bf";
$opaque_val = 1.0; # alpha for opaque win
$opaque_val = "ff";
$sleep_val = 0.1;  # refresh interval (sec)
my $verbosity   = 2;    # 0 - silent, 1 - info, 2 - debug

#my $OPAQUE      = "ffffffff";
#my $TRANS       = "d0000000";
#my $OPACITY     = 38;
# my $OPACITY     = 'NET-WM-WINDOW-OPACITY'; has to be numeric


my $x = X11::Protocol->new();

open($infp,  $infile)   or die "Can't open $infile: $!";

my @lines = <$infp>;
close($infp);

foreach my $appname (@lines) {
    $appname =~ s/^[\s\t\n]*//g;
    if ($appname ne '') {
        push @appnames, $appname;
    }
}

print "going to make apps below transparent...\n";
print @appnames;
print "\n";

select ( undef, undef, undef, 0.3 ); # wait for a while

# grab all window IDs
print "Calling \'xwininfo -root -all\'\n" if ($verbosity >= 2);
@win_ids = `xwininfo -root -all`;
foreach my $win_id ( @win_ids ) {
    unless ( $win_id =~ /has\ no\ name/ ||
             $win_id !~ /0x[0-9abcdef]/ ||
             $win_id =~ /Desktop/) {
        foreach my $appname (@appnames) {
            $appname =~ s/[\s\t\n]//g;
#            chop($appname);
            if ($win_id =~ /$appname/) {
                if ($win_id =~ /^[\s\t]*0x[0-9a-f]{6}/) {
                    $win_id =~ /\ \"/;
                    $win_id = "$`";
                    $win_id =~ s/\s//g;
                    push @id_lines, $win_id;
                }
                else {
                    push @removed_lines, $win_id;
                }
            }
        }
    }
}

print "ID_LINES:@id_lines\n";
print "REMOVED_LINES:@removed_lines\n";

# make all windows transparent
foreach my $win_id ( @id_lines ) {
#    system ( "transset-df --id $win_id $trans_val" );
#    $x->DeleteProperty ($win_id=~/^0x/i ? oct $win_id : $win_id, $x->atom("WM_WINDOW_OPACITY"));
    &transparentify ($win_id, $trans_val);
}

$old_id = 0;
$do_trans = 0;

# get currently focused window's ID
while ( 1 ) {
        print "\n";
#    my $active_id = `xprop -root  | grep "_NET_ACTIVE_WINDOW(WINDOW): window id # "`;;

#    print "active_ID0:$active_id\n";
#    $active_id =~ /\#\s/;
#    $active_id = "$'";


=pod
    $active_id =~ /\#\s(0x[0-9a-f]*),/;
    $active_id = $1;
    chomp $active_id;

    my $win_id_cmd = "xwininfo -id $active_id";
    print "Calling $win_id_cmd\n" if ($verbosity >= 2);
    my $win_id = `$win_id_cmd`;
=cut

    my ($win_id_no) = $x->GetInputFocus();
    my $active_id = $win_id_no;
    print "Focused window Id is $win_id_no.\n";
    $win_id_no =~ /^[0-9a-fx]+$/ or next; # Focused window Id is PointerRoot ?! How come?!

#    my $win_name = $x->GetAtomName( $win_id );
#    print "Focused window name is $win_name.\n";

=pod
    my $win_attr = $x->GetWindowAttributes ($win_id);
    print "Win attr = $win_attr\n";
    foreach my $attr (%$win_attr) {
            print "Attribute $attr = $win_attr->{$attr}\n";
    }
=cut

    my $win_id = 'has no name';
    foreach my $atom ($x->ListProperties($win_id_no)) {
            my ($atom_name, $atom_value) = ( $x->GetAtomName ($atom), $x->GetProperty ($win_id_no, $atom, 0, 0, 128, 0) );
#            print "$atom - Name = $atom_name, Value = $atom_value\n" if defined $atom_value;
            $win_id = $atom_value if $atom_name eq 'WM_CLASS';
    }
    print "Window class is $win_id.\n";

    $will_trans = 0;
    unless ( $win_id =~ /has\ no\ name/ ||
#             $win_id !~ /0x[0-9abcdef]/ ||
             $win_id =~ /Desktop/) {
        foreach my $appname (@appnames) {
            $appname =~ s/[\s\t\n]//g;
            print "Testing $win_id against $appname.\n";
            if ($win_id =~ /$appname/) {
                $will_trans = 1;
                print "matched: $appname. Old Id = $old_id. New Id = $active_id\n";
            }
        }
    }

# set active window to opaque_val and old window to trans_val
    if ( $old_id ne $active_id ) {
#        print "transset-df --id $active_id $opaque_val\n";
#        system ( "transset-df --id $active_id $opaque_val" );
         &transparentify ($active_id, $opaque_val);

        if ($old_id ne 0 && $do_trans == 1) {
#            print "transset-df --id $old_id $trans_val\n";
#            system ( "transset-df --id $old_id $trans_val" );
            &transparentify ($old_id, $trans_val);
        }
        $do_trans = $will_trans;
    }
    $old_id = $active_id;
    select ( undef, undef, undef, $sleep_val );
}

sub transparentify {
    my ($id, $opacity) = @_;
    if (1) {
#            Gives _NET_WM_WINDOW_OPACITY(CARDINAL) = 2147483647 (although it says XA_CARDINAL)
#            opacity 0x7fffffff
#            XChangeProperty(x, x, x, XA_CARDINAL, 32, PropModeReplace, 0x7fffffff, 1L)
        $opacity = (1 + hex $opacity) / 256;
        print    "transset-df --id $id $opacity\n";
        system ( "transset-df --id $id $opacity &" );
    } else {
#            Gives _NET_WM_WINDOW_OPACITY(XA_CARDINAL) = 0x66666666, 0x66666666
#            Or    _NET_WM_WINDOW_OPACITY(CARDINAL) = 1717986871, 1717986918
#            opacity 0x7fffffff
 
#        if ($opacity > 0.999) {
#            $x->DeleteProperty ($id=~/^0x/i ? oct $id : $id, $OPACITY);
#        } else {
#            $x->ChangeProperty($window, $property, $type, $format, $mode, $data)

#            $x->ChangeProperty (oct $id, $OPACITY, 6, 32, 0, int ($opacity * oct ($OPAQUE)));
#            $x->ChangeProperty ($id=~/^0x/i ? oct $id : $id, $OPACITY, 6, 32, 'Replace', $TRANS);
=pod
            $x->ChangeProperty ($id=~/^0x/i ? oct $id : $id,
                                $x->atom('WM_WINDOW_OPACITY'),
                                $x->atom('STRING'),
                                8,
                                'Replace',
                                $opacity );
=cut
            $x->DeleteProperty ($id=~/^0x/i ? oct $id : $id, $x->atom("WM_WINDOW_OPACITY"));
            $x->DeleteProperty ($id=~/^0x/i ? oct $id : $id, $x->atom("_NET_WM_WINDOW_OPACITY"));
            $x->ChangeProperty ($id=~/^0x/i ? oct $id : $id,
                                $x->atom('_NET_WM_WINDOW_OPACITY'),
                                $x->atom('CARDINAL'),
                                32,
                                'Replace',
                                0xffffffff);
=pod
            $x->ChangeProperty ($id=~/^0x/i ? oct $id : $id,
                                $x->atom('_NET_WM_WINDOW_OPACITY'),
                                $x->atom('STRING'),
                                8,
                                'Replace',
                                $opacity);
#                                (1 << 24) * (hex $opacity) );
=cut
#        }
    }
}
