diff options
Diffstat (limited to 'lib/App/XScreenSaver/DBus/Saver.pm')
-rw-r--r-- | lib/App/XScreenSaver/DBus/Saver.pm | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/lib/App/XScreenSaver/DBus/Saver.pm b/lib/App/XScreenSaver/DBus/Saver.pm new file mode 100644 index 0000000..6ae6e69 --- /dev/null +++ b/lib/App/XScreenSaver/DBus/Saver.pm @@ -0,0 +1,134 @@ +package App::XScreenSaver::DBus::Saver; +use Moo; +use experimental 'signatures'; +use curry; +use Log::Any; +use Try::Tiny; +use App::XScreenSaver::DBus::SaverProxy; + +has reactor => ( is => 'ro', required => 1 ); +has bus => ( is => 'lazy', builder => sub { Net::DBus->session() } ); +has dbus_srv => ( + is => 'lazy', + builder => sub { shift->bus->get_service('org.freedesktop.DBus') }, +); +has dbus_obj => ( + is => 'lazy', + builder => sub { shift->dbus_srv->get_object('/org/freedesktop/DBus') }, +); + +has service => ( + is => 'lazy', + builder => sub { + # this is the service name + shift->bus->export_service('org.freedesktop.ScreenSaver'); + }, +); +has paths => ( + is => 'ro', + default => sub { [qw(/ScreenSaver /org/freedesktop/ScreenSaver)] }, +); + +has log => ( is => 'lazy', builder => sub { Log::Any->get_logger } ); + +has _impls => ( is => 'rw' ); +has _prod_id => ( is => 'rw' ); +has _inhibits => ( is => 'rw', default => sub { +{} } ); + +sub start($self) { + my $inhibit_cb = $self->curry::weak::inhibit; + my $uninhibit_cb = $self->curry::weak::uninhibit; + + $self->_impls([ map { + App::XScreenSaver::DBus::SaverProxy->new( + $self->service, + $_, + $inhibit_cb, + $uninhibit_cb, + ) + } $self->paths->@* ]); + + $self->_prod_id( + $self->reactor->add_timeout( + 60_000, + Net::DBus::Callback->new( + method => $self->curry::weak::prod_screensaver + ), + 0, + ), + ); + + $self->dbus_obj->connect_to_signal( + 'NameOwnerChanged', + $self->curry::weak::name_owner_changed, + ); + + return; +} + +sub inhibit($self,$name,$reason,$message) { + my $cookie; + do { + $cookie = int(rand(2**31)) + } until !exists $self->_inhibits->{$cookie}; + + my $sender = $message->get_sender; + $self->_inhibits->{$cookie} = [ $name, $reason, $sender ]; + + $self->log->debugf( + '<%s> (%s) stops screensaver for <%s> (cookie %d) - %d active', + $name, $sender, $reason, $cookie, scalar(keys $self->_inhibits->%*), + ); + $self->reactor->toggle_timeout($self->_prod_id, 1); + + return $cookie; +} + +sub uninhibit($self,$cookie,$message) { + my $inhibit = delete $self->_inhibits->{$cookie} + or return; + my ($name, $reason, $sender) = @$inhibit; + my $this_sender = $message->get_sender; + + $self->log->debugf( + '<%s> (was %s, is %s) resumed screensaver for <%s> (cookie %d) - %d left', + $name, $sender, $this_sender, $reason, $cookie, scalar(keys $self->_inhibits->%*), + ); + + $self->reactor->toggle_timeout($self->_prod_id, 0) + unless $self->_inhibits->%*; + + return; +} + +sub name_owner_changed($self,$bus_name,$old,$new) { + $self->log->tracef('<%s> changed from <%s> to <%s>', + $bus_name, $old, $new); + + for my $cookie (sort keys $self->_inhibits->%*) { + my ($name, $reason, $sender) = @{$self->_inhibits->{$cookie}}; + # is this inhibit from that bus name? + next unless $sender && $sender eq $bus_name; + # did the bus owner just disconnect? + next unless $old && !$new; + + # if so, remove the inhibit + my $inhibit = delete $self->_inhibits->{$cookie}; + + $self->log->debugf( + '<%s> (%s) disconnected from the bus (it stopped screensaver for <%s>, cookie %d) - %d left', + $name, $bus_name, $reason, $cookie, scalar(keys $self->_inhibits->%*), + ); + } + + unless ($self->_inhibits->%*) { + $self->reactor->toggle_timeout($self->_prod_id, 0); + } +} + +sub prod_screensaver($self) { + $self->log->debug('prodding xscreensaver'); + system(qw(xscreensaver-command -deactivate)); +} + +1; |