diff options
-rw-r--r-- | lib/notifd/cli.vala | 2 | ||||
-rw-r--r-- | lib/notifd/daemon.vala | 12 | ||||
-rw-r--r-- | lib/notifd/meson.build | 99 | ||||
-rw-r--r-- | lib/notifd/notifd.vala | 53 | ||||
-rw-r--r-- | lib/notifd/notification.vala | 97 |
5 files changed, 228 insertions, 35 deletions
diff --git a/lib/notifd/cli.vala b/lib/notifd/cli.vala index afce774..ab1ddef 100644 --- a/lib/notifd/cli.vala +++ b/lib/notifd/cli.vala @@ -47,7 +47,7 @@ int main(string[] argv) { return 0; } - var notifd = new AstalNotifd.Notifd(); + var notifd = AstalNotifd.get_default(); if (version) { print(AstalNotifd.VERSION); diff --git a/lib/notifd/daemon.vala b/lib/notifd/daemon.vala index b7a76df..d09564c 100644 --- a/lib/notifd/daemon.vala +++ b/lib/notifd/daemon.vala @@ -36,8 +36,12 @@ internal class AstalNotifd.Daemon : Object { public signal void prop_changed(string prop); // emitting an event from proxy doesn't seem to work - public void emit_resolved(uint id, ClosedReason reason) { resolved(id, reason); } - public void emit_action_invoked(uint id, string action) { action_invoked(id, action); } + public void emit_resolved(uint id, ClosedReason reason) throws Error { + resolved(id, reason); + } + public void emit_action_invoked(uint id, string action) throws Error { + action_invoked(id, action); + } construct { cache_directory = Environment.get_user_cache_dir() + "/astal/notifd"; @@ -157,7 +161,9 @@ internal class AstalNotifd.Daemon : Object { private void write_state() { var list = new Json.Builder().begin_array(); foreach (var n in notifications) { - list.add_value(n.to_json()); + if (!n.transient) { + list.add_value(n.to_json()); + } } list.end_array(); diff --git a/lib/notifd/meson.build b/lib/notifd/meson.build index 6bea022..b6ef59a 100644 --- a/lib/notifd/meson.build +++ b/lib/notifd/meson.build @@ -18,8 +18,9 @@ assert( version_split = meson.project_version().split('.') api_version = version_split[0] + '.' + version_split[1] -gir = 'AstalNotifd-' + api_version + '.gir' -typelib = 'AstalNotifd-' + api_version + '.typelib' +namespace = 'AstalNotifd' +gir = namespace + '-' + api_version + '.gir' +typelib = namespace + '-' + api_version + '.typelib' config = configure_file( input: 'config.vala.in', @@ -40,19 +41,19 @@ deps = [ dependency('gdk-pixbuf-2.0'), ] -sources = [ - config, +sources = [config] + files( 'daemon.vala', 'notifd.vala', 'notification.vala', 'proxy.vala', -] +) if get_option('lib') lib = library( meson.project_name(), sources, dependencies: deps, + vala_args: ['--vapi-comments', '--ccode'], vala_header: meson.project_name() + '.h', vala_vapi: meson.project_name() + '-' + api_version + '.vapi', vala_gir: gir, @@ -61,15 +62,75 @@ if get_option('lib') install_dir: [true, true, true, true], ) - import('pkgconfig').generate( - lib, - name: meson.project_name(), - filebase: meson.project_name() + '-' + api_version, - version: meson.project_version(), - subdirs: meson.project_name(), - requires: deps, - install_dir: get_option('libdir') / 'pkgconfig', - ) + # import('gnome').generate_gir( + # lib, + # sources: [], + # nsversion: api_version, + # namespace: namespace, + # symbol_prefix: meson.project_name().replace('-', '_'), + # identifier_prefix: namespace, + # includes: ['GObject-2.0'], + # header: meson.project_name() + '.h', + # export_packages: meson.project_name() + '-' + api_version, + # install: true, + # ) + + # custom_target( + # gir, + # command: [ + # find_program('g-ir-scanner'), + # '--namespace=' + namespace, + # '--nsversion=' + api_version, + # '--library=' + meson.project_name(), + # '--include=GObject-2.0', + # '--output=' + gir, + # '--symbol-prefix=' + meson.project_name().replace('-', '_'), + # '--identifier-prefix=' + namespace, + # ] + # + pkgs + # + ['@INPUT@'], + # output: gir, + # depends: lib, + # input: meson.current_build_dir() / meson.project_name() + '.h', + # install: true, + # install_dir: get_option('datadir') / 'gir-1.0', + # ) + + # custom_target( + # gir, + # command: [ + # find_program('g-ir-scanner'), + # '--namespace=' + namespace, + # '--nsversion=' + api_version, + # '--library=' + meson.project_name(), + # '--include=GObject-2.0', + # '--output=' + gir, + # '--symbol-prefix=' + meson.project_name().replace('-', '_'), + # '--identifier-prefix=' + namespace, + # ] + # + pkgs + # + ['@INPUT@'], + # input: lib.extract_all_objects(), + # output: gir, + # depends: lib, + # install: true, + # install_dir: get_option('datadir') / 'gir-1.0', + # ) + + # pkgs = [] + # foreach dep : deps + # pkgs += ['--pkg=' + dep.name()] + # endforeach + # + # gir_tgt = custom_target( + # gir, + # command: [find_program('valadoc'), '-o', 'docs', '--gir', gir] + pkgs + sources, + # input: sources, + # depends: lib, + # output: gir, + # install: true, + # install_dir: get_option('datadir') / 'gir-1.0', + # ) custom_target( typelib, @@ -85,6 +146,16 @@ if get_option('lib') install: true, install_dir: get_option('libdir') / 'girepository-1.0', ) + + import('pkgconfig').generate( + lib, + name: meson.project_name(), + filebase: meson.project_name() + '-' + api_version, + version: meson.project_version(), + subdirs: meson.project_name(), + requires: deps, + install_dir: get_option('libdir') / 'pkgconfig', + ) endif if get_option('cli') diff --git a/lib/notifd/notifd.vala b/lib/notifd/notifd.vala index c962862..6ca25fa 100644 --- a/lib/notifd/notifd.vala +++ b/lib/notifd/notifd.vala @@ -1,11 +1,23 @@ +/** + * Get the singleton instance of {@link Notifd} + */ namespace AstalNotifd { public Notifd get_default() { return Notifd.get_default(); } } +/** + * The Notification daemon. + * + * This class queues up to become the next daemon, while acting as a proxy in the meantime. + */ public class AstalNotifd.Notifd : Object { private static Notifd _instance; + + /** + * Get the singleton instance + */ public static Notifd get_default() { if (_instance == null) _instance = new Notifd(); @@ -16,8 +28,14 @@ public class AstalNotifd.Notifd : Object { private Daemon daemon; private DaemonProxy proxy; - public signal void active(ActiveType type); + internal signal void active(ActiveType type); + /** + * Ignore the timeout specified by incoming notifications. + * + * By default notifications can specify a timeout in milliseconds + * after which the daemon will resolve them even without user input. + */ public bool ignore_timeout { get { return proxy != null ? proxy.ignore_timeout : daemon.ignore_timeout; @@ -30,6 +48,12 @@ public class AstalNotifd.Notifd : Object { } } + /** + * Indicate to frontends to not show popups to the user. + * + * This property does not have any effect on its own, its merely + * a value to use between the daemon process and proxies for frontends to use. + */ public bool dont_disturb { get { return proxy != null ? proxy.dont_disturb : daemon.dont_disturb; @@ -42,23 +66,38 @@ public class AstalNotifd.Notifd : Object { } } + /** + * List of currently unresolved notifications. + */ public List<weak Notification> notifications { owned get { return proxy != null ? proxy.notifications : daemon.notifications; } } - public uint[] notification_ids() throws Error { - return proxy != null ? proxy.notification_ids() : daemon.notification_ids(); - } - + /** + * Gets the {@link Notification} with id or null if there is no such Notification. + */ public Notification get_notification(uint id) { return proxy != null ? proxy.get_notification(id) : daemon.get_notification(id); } - public string get_notification_json(uint id) { + internal string get_notification_json(uint id) { return get_notification(id).to_json_string(); } + /** + * Emitted when the daemon receives a {@link Notification}. + * + * @param id The ID of the Notification. + * @param replaced Indicates if an existing Notification was replaced. + */ public signal void notified(uint id, bool replaced); + + /** + * Emitted when a {@link Notification} is resolved. + * + * @param id The ID of the Notification. + * @param reason The reason how the Notification was resolved. + */ public signal void resolved(uint id, ClosedReason reason); construct { @@ -134,7 +173,7 @@ public class AstalNotifd.Notifd : Object { } } -public enum AstalNotifd.ActiveType { +internal enum AstalNotifd.ActiveType { DAEMON, PROXY, } diff --git a/lib/notifd/notification.vala b/lib/notifd/notification.vala index 74b428e..c3a1186 100644 --- a/lib/notifd/notification.vala +++ b/lib/notifd/notification.vala @@ -9,30 +9,75 @@ public struct AstalNotifd.Action { public string label; } +/** + * Class representing a notification. + */ public class AstalNotifd.Notification : Object { private List<Action?> _actions; private HashTable<string, Variant> hints; - public int64 time { construct set; get; } - public string app_name { construct set; get; } - public string app_icon { construct set; get; } - public string summary { construct set; get; } - public string body { construct set; get; } - public uint id { construct set; get; } - public int expire_timeout { construct set; get; } + /** Unix time of when the notification was sent. */ + public int64 time { private construct set; get; } + + /** Name of the sending application. */ + public string app_name { private construct set; get; } + + /** Icon name of the sending application. */ + public string app_icon { private construct set; get; } + + /** Single line overview of the notification. */ + public string summary { private construct set; get; } + + /** Multi-line body of text, where each line is a paragraph. May contain markup. */ + public string body { private construct set; get; } + + /** Id of the notification. */ + public uint id { private construct set; get; } + + /** Time in milliseconds after the notification expires. */ + public int expire_timeout { private construct set; get; } + + /** + * List of {@link Action} of the notification. + * + * Can be invoked by calling {@link Notification.invoke} with the action's id. + */ public List<Action?> actions { get { return _actions; } } + /** Path of an image */ public string image { get { return get_str_hint("image-path"); } } + + /** Indicates whether {@link Action} identifier should be interpreted as a named icon. */ public bool action_icons { get { return get_bool_hint("action-icons"); } } + + /** [[https://specifications.freedesktop.org/notification-spec/latest/categories.html|Category of the notification.]] */ public string category { get { return get_str_hint("category"); } } + + /** Specifies the name of the desktop filename representing the calling program. */ public string desktop_entry { get { return get_str_hint("desktop-entry"); } } + + /** Indicates whether notification is kept after action invocation. */ public bool resident { get { return get_bool_hint("resident"); } } + + /** The path to a sound file to play when the notification pops up. */ public string sound_file { get { return get_str_hint("sound-file"); } } + + /** A themeable named sound from to play when the notification pops up */ public string sound_name { get { return get_str_hint("sound-name"); } } + + /** Indicates to suppress playing any sounds. */ public bool suppress_sound { get { return get_bool_hint("suppress-sound"); } } + + /** Indicates that the notification should be excluded from persistency. */ public bool transient { get { return get_bool_hint("transient"); } } + + /** Specifies the X location on the screen that the notification should point to. The "y" hint must also be specified. */ public int x { get { return get_int_hint("x"); } } + + /** Specifies the Y location on the screen that the notification should point to. The "x" hint must also be specified. */ public int y { get { return get_int_hint("y"); } } + + /** {@link Urgency} level of the notification. */ public Urgency urgency { get { return get_byte_hint("urgency"); } } internal Notification( @@ -95,12 +140,44 @@ public class AstalNotifd.Notification : Object { return 0; } + /** + * Emitted when this {@link Notification} is resolved. + * + * @param reason The reason how the Notification was resolved. + */ public signal void resolved(ClosedReason reason); + + /** + * Emitted when the user dismisses this {@link Notification} + * + * @see dismiss + */ public signal void dismissed(); - public signal void invoked(string action); + /** + * Emitted when an {@link Action} of this {@link Notification} is invoked. + * + * @param action_id id of the invoked action + * @see invoke + */ + public signal void invoked(string action_id); + + /** + * Dismiss this notification popup + * + * This method doesn't have any functionality on its own, but should be handled + * by frontend implementation to hide notification popups. + */ public void dismiss() { dismissed(); } - public void invoke(string action) { invoked(action); } + + /** + * Invoke an {@link Action} of this {@link Notification} + * + * Note that this method just notifies the client that this action was invoked + * by the user. If for example this notification persists through the lifetime + * of the sending program this action will have no effect. + */ + public void invoke(string action_id) { invoked(action_id); } internal Notification.from_json(Json.Object root) throws GLib.Error { foreach (var key in root.get_members()) { @@ -141,7 +218,7 @@ public class AstalNotifd.Notification : Object { return new Notification.from_json(parser.get_root().get_object()); } - public string to_json_string() { + internal string to_json_string() { var generator = new Json.Generator(); generator.set_root(to_json()); return generator.to_data(null); |