-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathlibnotify-ffi.ts
More file actions
80 lines (75 loc) · 2.92 KB
/
Copy pathlibnotify-ffi.ts
File metadata and controls
80 lines (75 loc) · 2.92 KB
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
import { FFIType } from 'bun:ffi';
import { dlopen } from '../dlopen';
import { UnsupportedPlatformError } from '../../../common/errors';
import { currentPlatform } from '../../../common/platform';
/**
* Loads the libnotify symbols behind Bunmaska's `Notification` API on Linux.
*
* libnotify is the freedesktop desktop-notification client library; it forwards
* to the session's notification daemon over D-Bus. CI runs headless (xvfb) with
* NO notification daemon, so `notify_notification_show` may return FALSE / no-op
* there — that is EXPECTED. The integration test therefore asserts only that the
* symbols resolve, `notify_init` runs, and construct/show/close do not throw; it
* does NOT assert a banner appeared.
*
* Convention (matches the existing Linux loaders): `gboolean` is modelled as
* {@link FFIType.i32} (compare `!== 0`); the `NotifyNotification*` handle and the
* `GError**` out-param are real pointers ({@link FFIType.pointer}); `cstring`
* args are NUL-terminated UTF-8 strings. The `GError**` arg is always passed as
* `null` (failures are reported via the gboolean return, not unwrapped).
*/
const LIBNOTIFY_PATH = 'libnotify.so.4';
/** The libnotify FFI symbol descriptor table (from `libnotify.so.4`). */
export const LIBNOTIFY_FFI_SYMBOLS = {
// (app_name) -> gboolean; call once per process before creating notifications.
notify_init: {
args: [FFIType.cstring],
returns: FFIType.i32,
},
notify_is_initted: {
args: [],
returns: FFIType.i32,
},
// (summary, body, icon) -> NotifyNotification*; body/icon may be NULL.
notify_notification_new: {
args: [FFIType.cstring, FFIType.cstring, FFIType.cstring],
returns: FFIType.pointer,
},
// (notification, GError** /*null*/) -> gboolean (FALSE if no daemon).
notify_notification_show: {
args: [FFIType.pointer, FFIType.pointer],
returns: FFIType.i32,
},
// (notification, GError** /*null*/) -> gboolean.
notify_notification_close: {
args: [FFIType.pointer, FFIType.pointer],
returns: FFIType.i32,
},
// (notification, timeout_ms) -> void; -1 = default, 0 = never expire.
notify_notification_set_timeout: {
args: [FFIType.pointer, FFIType.i32],
returns: FFIType.void,
},
// (NotifyNotification*, const char* key, GVariant* value) -> void; sinks the floating variant
notify_notification_set_hint: {
args: [FFIType.pointer, FFIType.cstring, FFIType.pointer],
returns: FFIType.void,
},
} as const;
const cache: { ffi: ReturnType<typeof dlopen<typeof LIBNOTIFY_FFI_SYMBOLS>> | undefined } = {
ffi: undefined,
};
export const loadLibnotifyFFI = () => {
const platform = currentPlatform();
if (platform !== 'linux') {
throw new UnsupportedPlatformError(
`loadLibnotifyFFI() is only supported on Linux; current platform is ${platform}`,
);
}
if (cache.ffi) {
return cache.ffi;
}
const ffi = dlopen(LIBNOTIFY_PATH, LIBNOTIFY_FFI_SYMBOLS);
cache.ffi = ffi;
return ffi;
};