-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hello,

despite the disappointing lack of response i kept working on this little
plugin. It now features

* setting the brightness threshold via the 'brightnessThreshold' X resource
* inverting any web-(html-) style color code (e.g. #123abc), named
colors (like defined in $prefix/share/X11/rgb.txt) and the convenience
urxvt color codes (0-15)
* if 'RGBColourFile' is not set (e.g. to /usr/share/X11/rgb.txt) tries
to read '/usr/share/X11/rgb.txt' and '/usr/local/share/X11/rgb.txt',
does not invert colour otherwise
* inverts foreground, background and if set: colorBD, colorIT, and colorUL
* respects colorRV resource
* currently ignores alpha values for inverted colours, keeps the
original colour though

I've done some testing with different combinations of colour
names/values and I think it works pretty well now. Any comments or bug
fixes are welcome though. :)

Best regards,

Jochen


On 19.10.2010 11:04, Jochen Keil wrote:
> Hello altogether,
> 
> Maybe you remember my questions back in the end of August about how I
> could invert the terminal (using reversed video) as a reaction on the
> DBus event 'BrightnessChanged' (at least as it is emitted by the
> 'org.gnome.PowerManager.Backlight' interface).
> 
> Marc pointed me to the AnyEvent::DBus module which does a good job
> dealing with Net::DBus (no more Net::DBus::Reactor which causes the
> module to block). Furthermore, since urxvt provides already an AnyEvent
> event loop integrating my module was fairly easy.
> 
> I stumbled about some really nasty problem though which caused the long
> delay and nearly brought me away from this. Let me briefly explain it to
> you and show you the solution.
> 
> Initially I just tried to get a DBus session bus object with
> Net::DBus->session(). This worked but unfortunately the bus object
> blocked and kept the process running even after closing the terminal.
> The solution to this was quite simple but took me a long time to figure
> out because I had to dig through the whole Net::DBus API. A connection
> can be closed with the 'disconnect()' method. Having a bus object with a
> get_connection() method this is as simple as
> '$bus->get_connection()->disconnect()'. Since you are not allowed to
> close a shared connection it has to be opened private (session(private
> => 1)).
> That's it. Now it is possible to shut down the DBus connection and exit
> gracefully.
> 
> I hope you found this interesting and if you like this module feel free
> to add it to urxvt. Any comments and improvements are welcome.
> Some of the ideas I have include
> 
> * making the threshold (currently fixed to 80) a configurable X resource
> * reacting on any BrightnessChanged signal, not only from gnome pm
> * making the behaviour configurable (e.g. set fg/bg color instead of rvid)
> * abstract the whole thing so that any DBus event can cause any action
> 
> Please tell me if you are interested in this, or have suggestions. Of
> course, if there's no interest in it I'll probably keep it in an IWM (it
> works for me) state..
> 
> I can also upload to a public repository if you want to, so I don't need
> to send updates every time to this list.
> 
> Have fun,
> 
> Jochen
> 
> 
> 
> _______________________________________________
> rxvt-unicode mailing list
> [email protected]
> http://lists.schmorp.de/cgi-bin/mailman/listinfo/rxvt-unicode
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)

iEYEARECAAYFAkzB+SwACgkQtVwvsA+W4CD1sQCeOH8qkiDqa3RuHH1saUx9TbVZ
ibYAniyQMwjDpUbDKTfCGL6R0i0lu1bI
=SAm9
-----END PGP SIGNATURE-----
#! perl

use AnyEvent::DBus;
use Net::DBus::Annotation qw(:call);

sub on_start {
  my ($self) = @_;
  my ($term) = $self->{term};
  my ($reversed) = 0;
  my ($thresh) = $term->x_resource("brightnessThreshold");

  %{$term->{colours}} = getColours($self);

  $term->{bus} = Net::DBus->session(private => 1);
  $term->{upower} = $self->{term}->{bus}->get_service('org.gnome.PowerManager');
  $term->{object} = $self->{term}->{upower}->get_object(
    '/org/gnome/PowerManager/Backlight',
    'org.gnome.PowerManager.Backlight');

  if ($term->{object}->GetBrightness() < $thresh) {
    reverseVideo($self, 1);
    $reversed = 1;
  }

  $term->{object}->connect_to_signal('BrightnessChanged', sub {
      my $brightness = $_[0];
      if ($brightness < $thresh && $reversed == 0) {
        reverseVideo($self, 1);
        $reversed = 1;
      } elsif ($brightness > $thresh && $reversed == 1) {
        reverseVideo($self, 0);
        $reversed = 0;
      }
  });

  ()
}

sub on_destroy {
  my ($self) = @_;
  $self->{term}->{bus}->get_connection()->disconnect();
  ()
}

sub reverseVideo {
  my ($self, $reverse) = @_;
  my ($term) = $self->{term};
  my (%colours) = %{$term->{colours}};

  my (%tc) = ("foreground" => 10,
              "background" => 11,
              "colorIT" => 704,
              "colorBD" => 706,
              "colorUL" => 707);

  if ($reverse == 1) {
    while (my ($cotype, $colour) = each(%colours)) {
      if ($cotype =~ m/(reverse)(.*)/) {
        $term->cmd_parse("\033]$tc{$2};$colour\007");
      }
    }
  } else {
    while (my ($cotype, $colour) = each(%colours)) {
      if ($cotype !~ m/(reverse)(.*)/) {
        $term->cmd_parse("\033]$tc{$cotype};$colour\007");
      }
    }
  }
  $self->want_refresh();

}

sub getColours {
  my ($self) = @_;
  my %colours = readColours($self);
  %colours = resolveColours($self, %colours);

  return %colours;
}

sub readColours {
  my ($self) = @_;
  my ($term) = ($self->{term});

  return (
      foreground => $term->x_resource("foreground")
    , background => $term->x_resource("background")
    , colorBD => $term->x_resource("colorBD")
    , colorIT => $term->x_resource("colorIT")
    , colorUL => $term->x_resource("colorUL")
    , colorRV => $term->x_resource("colorRV")
  );

}

sub invertHexRGB {
  my ($colour, $mask, @invrgb);
  $_[0] =~ m/rgb(a?):(\w{1,4})\/(\w{1,4})\/(\w{1,4})\/?(\w{1,4})?/i;
  my @rgb = ($2, $3, $4);

  foreach $colour (@rgb) {
    my $bitlen = length($colour);
    $mask = "f" x $bitlen;
    push(@invrgb, sprintf("%0*x", $bitlen, (hex($mask) - hex($colour))));
  }

  return "rgb:" . $invrgb[0] . "/" . $invrgb[1] . "/" . $invrgb[2];
}

sub resolveColours {
  my ($self, %colours) = @_;
  my %reverseColours;

  while (my ($key, $value) = each(%colours)) {
    if ($key eq "colorRV") {
      next;
    }

    if (!defined($value)) {
      if ($key eq "foreground") {
        $colours{$key} = "rgb:0000/0000/0000";
        $reverseColours{ "reverse" . $key } = "rgb:ffff/ffff/ffff";
      } elsif ($key eq "background") {
        $colours{$key} = "rgb:ffff/ffff/ffff";
        $reverseColours{ "reverse" . $key } = "rgb:0000/0000/0000";
      } elsif ($key eq "colorBD") {
        $colours{$key} = "rgb:0000/0000/0000";
        $reverseColours{ "reverse" . $key } = "rgb:ffff/ffff/ffff";
      } elsif ($key eq "colorIT") {
        $colours{$key} = "rgb:0000/0000/0000";
        $reverseColours{ "reverse" . $key } = "rgb:ffff/ffff/ffff";
      } elsif ($key eq "colorUL") {
        $colours{$key} = "rgb:0000/0000/0000";
        $reverseColours{ "reverse" . $key } = "rgb:ffff/ffff/ffff";
      } else {
        delete $colours{$key};
      }

    } elsif ($value =~ m/^(\d{1,2})/i) { # shorthand urxvt
      if ((my $colour = getRGBColour($self, resolveShorthand($1))) != -1) {
        $colours{$key} = $value;
        $reverseColours{ "reverse" . $key } = invertHexRGB($colour);
      } else {
        delete $colours{$key};
      }
    } elsif ($value =~ m/(\[\d{1,3}\])((\w|\s)*)/i) { # named colour with alpha
      if ((my $colour = getRGBColour($self, $2)) != -1) {
        $colours{$key} = $value;
        $reverseColours{ "reverse" . $key } = invertHexRGB($colour);
      } else {
        delete $colours{$key};
      }
    } elsif ($value =~ m/(^[#])([[:alnum:]]{6})/i) { # web colour
      if ((my $colour = resolveWebColour($value)) != -1) {
        $colours{$key} = $value;
        $reverseColours{ "reverse" . $key } = invertHexRGB($colour);
      } else {
        delete $colours{$key};
      }
    } elsif ($value =~ m/(^[^(rgb)|^#])((\w|\s)*)/i) { # named colour
      if ((my $colour = getRGBColour($self, $value)) != -1) {
        $colours{$key} = $value;
        $reverseColours{ "reverse" . $key } = invertHexRGB($colour);
      } else {
        delete $colours{$key};
      }
    } elsif ($value =~ 
m/rgb(a?):(\w{1,4})\/(\w{1,4})\/(\w{1,4})\/?(\w{1,4})?/i) {
      $colours{$key} = $value;
      $reverseColours{ "reverse" . $key } = invertHexRGB($value);
    }
  }

  if (defined($colours{"colorRV"})) {
    $reverseColours{"reversebackground"} = $colours{"colorRV"};
    delete $colours{"colorRV"};
  }

  return (%colours, %reverseColours);

}

sub resolveWebColour {
  $_[0] =~ m/(^[#])(\w{2})(\w{2})(\w{2})/i;
  return "rgb:" . $2 . "/" . $3 . "/" . $4;
}

sub resolveShorthand {

  my (%shorthand) = (
      0 => "black"
    , 1 => "red3"
    , 2 => "green3"
    , 3 => "yellow3"
    , 4 => "blue3"
    , 5 => "magenta3"
    , 6 => "cyan3"
    , 7 => "antiquewhite"
    , 8 => "grey25"
    , 9 => "red"
    , 10 => "green"
    , 11 => "yellow"
    , 12 => "blue"
    , 13 => "magenta"
    , 14 => "cyan"
    , 15 => "white" );

  if ($_[0] >= 0 && $_[0] <= 15) {
    return $shorthand{$_[0]};
  } else {
    return -1;
  }

}

sub getRGBColour {
  my ($self, $colourname) = @_;
  my ($term) = ($self->{term});

  my $file = $term->x_resource("RGBColourFile");
  if (!defined($file)) {
    if (  ! open(RGB, "</usr/share/X11/rgb.txt")
      ||  ! open(RGB, "</usr/local/share/X11/rgb.txt")) {
        return -1;
      }
  } elsif (! open(RGB, "<" . $file)) {
    return -1;
  }

  while (<RGB>) {
    my ($line) = $_;
    chomp($line);
    if ($line =~ m/(\d{1,3})\s*(\d{1,3})\s*(\d{1,3})\s*($colourname)/i) {
        close RGB;
        return sprintf("rgb:%x/%x/%x", $1, $2, $3);
    }
  }
  close RGB;

  return -1;

}

Attachment: rvid-on-brightnesschanged.sig
Description: PGP signature

_______________________________________________
rxvt-unicode mailing list
[email protected]
http://lists.schmorp.de/cgi-bin/mailman/listinfo/rxvt-unicode

Reply via email to