/
Notify.pm6
executable file
·325 lines (257 loc) · 11.3 KB
/
Notify.pm6
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
#!/usr/bin/env perl6
unit class Desktop::Notify:ver<0.3.2>;
use NativeCall;
constant LIB = ('notify', v4);
class NotifyNotification is repr('CPointer') is export { * } # libnotify private struct
class GError is repr('CStruct') is export {
has int32 $.domain;
has int32 $.code;
has Str $.message;
}
class GList is repr('CStruct') is export {
has Pointer[void] $.data;
has GList $.next;
has GList $.prev;
}
# Raw interface to libnotify
sub notify_init(Str $appname --> int32) is native(LIB) is export { * }
sub notify_uninit() is native(LIB) is export { * }
sub notify_is_initted(--> int32) is native(LIB) is export { * }
sub notify_get_app_name(--> Str) is native(LIB) is export { * }
sub notify_set_app_name(Str $appname) is native(LIB) is export { * }
sub notify_notification_new(Str $summary,
Str $body,
Str $icon --> NotifyNotification)
is native(LIB) is export { * }
sub notify_notification_show(NotifyNotification $notification, GError $error is rw --> int32)
is native(LIB) is export { * }
sub notify_notification_close(NotifyNotification $notification, GError $error is rw --> int32)
is native(LIB) is export { * }
sub notify_notification_get_closed_reason(NotifyNotification $notification --> int32)
is native(LIB) is export { * }
sub notify_notification_get_type(--> uint64) is native(LIB) { * }
sub notify_notification_update(NotifyNotification $notification,
Str $summary,
Str $body,
Str $icon --> int32)
is native(LIB) is export { * }
sub notify_notification_set_timeout(NotifyNotification $notification, int32 $timeout)
is native(LIB) is export { * }
sub notify_notification_set_category(NotifyNotification $notification, Str $category)
is native(LIB) is export { * }
sub notify_notification_set_urgency(NotifyNotification $notification, int32 $urgency)
is native(LIB) is export { * }
sub notify_get_server_caps(--> GList) is native(LIB) is export { * }
sub notify_get_server_info(Pointer[Str] $name is rw,
Pointer[Str] $vendor is rw,
Pointer[Str] $version is rw,
Pointer[Str] $spec_version is rw --> int32)
is native(LIB) is export { * }
sub notify_notification_add_action(NotifyNotification $notification2,
Str $action2,
Str $label,
&callback (NotifyNotification $notification1, Str $action1, Pointer[void] $dummy1?),
Pointer[void] $dummy2?,
&free? (Pointer[void] $mem))
is native(LIB) is export { * }
sub notify_notification_clear_actions(NotifyNotification $notification) is native(LIB) is export { * }
# OO interface
has GError $.error is rw;
has GList $.glist is rw;
enum NotifyUrgency is export(:constants) <NotifyUrgencyLow NotifyUrgencyNormal NotifyUrgencyCritical>;
submethod BUILD(:$app-name!) { notify_init($app-name); $!error = GError.new };
submethod DESTROY { notify_uninit(); $!error.free };
method is-initted(--> Bool) { notify_is_initted.Bool }
multi method app-name(--> Str) { notify_get_app_name }
multi method app-name(Str $appname!)
{
notify_set_app_name($appname);
self;
}
multi method new-notification(Str $summary!, Str $body!, Str $icon! --> NotifyNotification)
{
notify_notification_new($summary, $body, $icon);
}
multi method new-notification(Str :$summary!,
Str :$body!,
Str :$icon!,
Int :$timeout?,
Str :$category?,
NotifyUrgency :$urgency?
--> NotifyNotification)
{
my NotifyNotification $n = notify_notification_new($summary, $body, $icon);
notify_notification_set_timeout($n, $timeout) with $timeout;
notify_notification_set_category($n, $category) with $category;
notify_notification_set_urgency($n, $urgency) with $urgency;
return $n;
}
method show(NotifyNotification $notification!, GError $err? --> Bool)
{
notify_notification_show($notification, $err // $!error).Bool;
}
method close(NotifyNotification $notification!, GError $err? --> Bool)
{
notify_notification_close($notification, $err // $!error).Bool;
}
method add-action(NotifyNotification $notification!, Str $action, Str $label, &callback (NotifyNotification $notification1, Str $action1))
{
notify_notification_add_action($notification, $action, $label, callback);
self;
}
method get-type(--> Int)
{
notify_notification_get_type();
}
method update(NotifyNotification $notification!, Str $summary, Str $body, Str $icon --> Bool)
{
notify_notification_update($notification, $summary, $body, $icon).Bool;
}
constant NOTIFY_EXPIRES_DEFAULT is export(:constants) = -1;
constant NOTIFY_EXPIRES_NEVER is export(:constants) = 0;
method set-timeout(NotifyNotification $notification!, Int $timeout!)
{
notify_notification_set_timeout($notification, $timeout);
self;
}
method set-category(NotifyNotification $notification!, Str $category!)
{
notify_notification_set_category($notification, $category);
self;
}
method set-urgency(NotifyNotification $notification!, NotifyUrgency $urgency!)
{
notify_notification_set_urgency($notification, $urgency);
self;
}
method why-closed(NotifyNotification $notification! --> Int)
{
notify_notification_get_closed_reason($notification);
}
method server-caps(--> Seq)
{
$!glist = notify_get_server_caps();
my GList $l = self.glist;
gather loop {
take nativecast(Str, $l.data);
last unless $l.next;
$l = $l.next;
}
}
method server-info(--> Hash)
{
my $name = Pointer[Str].new;
my $vendor = Pointer[Str].new;
my $version = Pointer[Str].new;
my $spec-version = Pointer[Str].new;
my $ret = notify_get_server_info($name, $vendor, $version, $spec-version).Bool;
return { return => $ret,
name => nativecast(Str, $name),
vendor => nativecast(Str, $vendor),
version => Version.new(nativecast(Str, $version)),
spec-version => Version.new(nativecast(Str, $spec-version)),
};
}
=begin pod
=head1 NAME
Desktop::Notify - A simple interface to libnotify
=head1 SYNOPSIS
=begin code
use v6;
use Desktop::Notify :constants;
my $notify = Desktop::Notify.new(app-name => 'myapp');
my $n = $notify.new-notification('Attention!', 'What just happened?', 'stop');
$notify.set-timeout($n, NOTIFY_EXPIRES_NEVER);
$notify.show($n);
sleep 2;
$notify.update($n, 'Oh well!', 'Not quite a disaster!', 'stop');
$notify.show($n);
=end code
=head1 DESCRIPTION
B<Desktop::Notify> is a set of simple bindings to libnotify using NativeCall. Some
function calls are not currently implemented (see the I<TODO> section).
=head2 new(Str $appname)
Constructs a new B<Desktop::Notify> object. It takes one I<mandatory> argument:
B<app-name>, the name of the app that will be registered with the notify dæmon.
=head2 is-initted(--> Bool)
Returns True if the object has been successfully initialized.
=head2 app-name(--> Str)
=head2 app-name(Str $appname)
Queries or sets the app name.
=head2 new-notification(Str $summary!, Str $body!, Str $icon! --> NotifyNotification)
=head2 new-notification(Str :$summary!, Str :$body!, Str :$icon!, Int :$timeout?, Str :$category?, NotifyUrgency :$urgency? --> NotifyNotification)
Creates a new notification.
The first form takes three positional arguments: the summary string, the notification string and
the icon to display (See the libnotify documentation for the available icons).
The second form takes a number of named argument. B<summary>, B<body>, and B<icon> are I<mandatory>,
the others are optional. If B<timeout>, B<category>, and B<urgency> are defined, this method will call
the corresponding "set" methods documented below.
=head2 show(NotifyNotification $notification!, GError $err? --> Bool)
Shows the notification on screen. It takes one mandatory argument, the
NotifyNotification object, and one optional argument, the GError object.
(The default Desktop::Notify error handling is not thread safe. See
I<Threading safety> for more info)
=head2 close(NotifyNotification $notification!, GError $err? --> Bool)
Closes the notification. It takes one mandatory argument, the NotifyNotification
object, and one optional argument, the GError object. (The default
Desktop::Notify error handling is not thread safe. See I<Threading safety> for
more info)
Note that usually there's no need to explicitly 'close' a notification, since
the default is to automatically expire after a while.
=head2 why-closed(NotifyNotification $notification! --> Int)
Returns the the closed reason code for the notification. It takes one argument,
the NotifyNotification object. (See the libnotify documentation for the meaning of
this code)
=head2 get-type(--> Int)
Returns the notification type.
=head2 update(NotifyNotification $notification!, Str $summary, Str $body, Str $icon --> Bool)
Modifies the messages of a notification which is already on screen.
=head2 set-timeout(NotifyNotification $notification!, Int $timeout!)
Sets the notification timeout. There are two available constants,
B<NOTIFY_EXPIRES_DEFAULT> and B<NOTIFY_EXPIRES_NEVER>, when explicitly imported
with B<use Desktop::Notify :constants;>.
=head2 set-category(NotifyNotification $notification, Str $category!)
Sets the notification category (See the libnotify documentation).
=head2 set-urgency(NotifyNotification $notification, NotifyUrgency $urgency!)
Sets the notification urgency. An B<enum NotifyUrgency <NotifyUrgencyLow NotifyUrgencyNormal NotifyUrgencyCritical>>
is available when explicitly imported with B<use Desktop::Notify :constants;>.
=head2 server-caps(--> Seq)
Reads server capabilities and returns a sequence.
=head2 server-info(--> Hash)
Reads the server info and returns an hash. The return value of the C function call is
returned as the value of the B<return> key of the hash.
=head1 Threading safety
Desktop::Notify offers a simple interface which provides an B<error> class member,
which is automatically used by the functions which need it.
Since 'error' is a shared class member, if a program makes use of threading, its value
might be written by another thread before it's been read.
In this case one can declare their own GError variables:
=begin code
my $err = Desktop::Notify::GError.new;
=end code
and pass it as an optional argument to the .show() and .close() methods; it will be
used instead of the object-wide one.
=head1 Prerequisites
This module requires the libnotify library to be installed. Please follow the
instructions below based on your platform:
=head2 Debian Linux
=begin code
sudo apt-get install libnotify4
=end code
=head1 Installation
=begin code
$ zef install Desktop::Notify
=end code
=head1 Testing
To run the tests:
=begin code
$ prove -e "perl6 -Ilib"
=end code
=head1 Note
With version 0.2.0 I modified the B<enum NotifyUrgency> to avoid polluting (too much) the namespace.
Now instead of e.g. B<low>, one has to use B<NotifyUrgencyLow>.
=head1 Author
Fernando Santagata
=head1 License
The Artistic License 2.0
=end pod