summaryrefslogtreecommitdiff
path: root/lib/App/XScreenSaver/DBus/Saver.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/App/XScreenSaver/DBus/Saver.pm')
-rw-r--r--lib/App/XScreenSaver/DBus/Saver.pm134
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;