summaryrefslogtreecommitdiff
path: root/lib/App/XScreenSaver/DBus/Saver.pm
blob: 6ae6e69c8df50e5a85e23e489a0df2ada9f20e72 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
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$cookiescalar(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$cookiescalar(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$cookiescalar(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;