summaryrefslogtreecommitdiff
path: root/notifd/src
diff options
context:
space:
mode:
Diffstat (limited to 'notifd/src')
-rw-r--r--notifd/src/cli.vala115
-rw-r--r--notifd/src/config.vala.in6
-rw-r--r--notifd/src/daemon.vala255
-rw-r--r--notifd/src/meson.build79
-rw-r--r--notifd/src/notifd.vala140
-rw-r--r--notifd/src/notification.vala160
-rw-r--r--notifd/src/proxy.vala129
-rw-r--r--notifd/src/signals.md35
8 files changed, 0 insertions, 919 deletions
diff --git a/notifd/src/cli.vala b/notifd/src/cli.vala
deleted file mode 100644
index afce774..0000000
--- a/notifd/src/cli.vala
+++ /dev/null
@@ -1,115 +0,0 @@
-static bool help;
-static bool version;
-static bool daemonize;
-static bool list;
-static string invoke;
-static int close_n;
-static int get_n;
-static bool toggle_dnd;
-
-const OptionEntry[] options = {
- { "version", 'v', OptionFlags.NONE, OptionArg.NONE, ref version, null, null },
- { "help", 'h', OptionFlags.NONE, OptionArg.NONE, ref help, null, null },
- { "daemonize", 'd', OptionFlags.NONE, OptionArg.NONE, ref daemonize, null, null },
- { "list", 'l', OptionFlags.NONE, OptionArg.NONE, ref list, null, null },
- { "invoke", 'i', OptionFlags.NONE, OptionArg.STRING, ref invoke, null, null },
- { "close", 'c', OptionFlags.NONE, OptionArg.INT, ref close_n, null, null },
- { "get", 'g', OptionFlags.NONE, OptionArg.INT, ref get_n, null, null },
- { "toggle-dnd", 't', OptionFlags.NONE, OptionArg.NONE, ref toggle_dnd, null, null },
- { null },
-};
-
-int main(string[] argv) {
- try {
- var opts = new OptionContext();
- opts.add_main_entries(options, null);
- opts.set_help_enabled(false);
- opts.set_ignore_unknown_options(false);
- opts.parse(ref argv);
- } catch (OptionError err) {
- printerr (err.message);
- return 1;
- }
-
- if (help) {
- print("Cli client for astal-notifd\n\n");
- print("Usage:\n");
- print(" %s [flags]\n\n", argv[0]);
- print("Flags:\n");
- print(" -h, --help Print this help and exit\n");
- print(" -v, --version Print version number and exit\n");
- print(" -l, --list Print every notification and exit\n");
- print(" -d, --daemonize Watch for new notifications\n");
- print(" -i, --invoke Invoke a notification action\n");
- print(" -c, --close Close a notification by its id\n");
- print(" -g, --get Print a notification by its id\n");
- print(" -t, --toggle-dnd Toggle do not disturb\n");
- return 0;
- }
-
- var notifd = new AstalNotifd.Notifd();
-
- if (version) {
- print(AstalNotifd.VERSION);
- return 0;
- }
-
- if (list) {
- var state = Environment.get_user_state_dir() + "/astal/notifd/notifications.json";
- if (FileUtils.test(state, FileTest.EXISTS)) {
- try {
- uint8[] json;
- File.new_for_path(state).load_contents(null, out json, null);
-
- var obj = Json.from_string((string)json);
-
- var list = obj.get_object().get_member("notifications");
- stdout.printf("%s\n", Json.to_string(list, true));
- return 0;
- } catch (Error err) {
- stderr.printf("failed to load cache: %s", err.message);
- }
- }
- stdout.printf("[]\n");
- return 0;
- }
-
- if (toggle_dnd) {
- notifd.dont_disturb = !notifd.dont_disturb;
- return 0;
- }
-
- if (daemonize) {
- notifd.notified.connect((id) => {
- stdout.printf("%s\n", notifd.get_notification_json(id));
- stdout.flush();
- });
- new MainLoop().run();
- }
-
- if (invoke != null) {
- if (!invoke.contains(":")) {
- stderr.printf("invoke format needs to be <notif-id>:<action-id>");
- return 1;
- }
-
- var split = invoke.split(":");
- var n_id = int.parse(split[0]);
- var a_id = split[1];
-
- notifd.get_notification(n_id).invoke(a_id);
- }
-
- if (close_n > 0) {
- notifd.get_notification(close_n).dismiss();
- }
-
- if (get_n > 0) {
- stdout.printf("%s", notifd.get_notification(get_n).to_json_string());
- }
-
- if (!daemonize && invoke == null && close_n == 0 && get_n == 0)
- return 1;
-
- return 0;
-}
diff --git a/notifd/src/config.vala.in b/notifd/src/config.vala.in
deleted file mode 100644
index 752c754..0000000
--- a/notifd/src/config.vala.in
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace AstalNotifd {
- public const int MAJOR_VERSION = @MAJOR_VERSION@;
- public const int MINOR_VERSION = @MINOR_VERSION@;
- public const int MICRO_VERSION = @MICRO_VERSION@;
- public const string VERSION = "@VERSION@";
-}
diff --git a/notifd/src/daemon.vala b/notifd/src/daemon.vala
deleted file mode 100644
index b8fb598..0000000
--- a/notifd/src/daemon.vala
+++ /dev/null
@@ -1,255 +0,0 @@
-[DBus (name = "org.freedesktop.Notifications")]
-internal class AstalNotifd.Daemon : Object {
- public static string name = "notifd";
- public static string vendor = "astal";
- public static string version = "0.1";
-
- private string state_file;
- private string state_directory;
- private string cache_directory;
-
- private uint n_id = 1;
- private HashTable<uint, Notification> notifs =
- new HashTable<uint, Notification>((i) => i, (a, b) => a == b);
-
- private bool _ignore_timeout;
- public bool ignore_timeout {
- get { return _ignore_timeout; }
- set {
- _ignore_timeout = value;
- write_state();
- }
- }
-
- private bool _dont_disturb;
- public bool dont_disturb {
- get { return _dont_disturb; }
- set {
- _dont_disturb = value;
- write_state();
- }
- }
-
- public signal void notified(uint id, bool replaced);
- public signal void resolved(uint id, ClosedReason reason);
- public signal void action_invoked(uint id, string action);
- 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); }
-
- construct {
- cache_directory = Environment.get_user_cache_dir() + "/astal/notifd";
- state_directory = Environment.get_user_state_dir() + "/astal/notifd";
- state_file = state_directory + "/notifications.json";
-
- if (FileUtils.test(state_file, FileTest.EXISTS)) {
- try {
- uint8[] json;
- File.new_for_path(state_file).load_contents(null, out json, null);
-
- var obj = Json.from_string((string)json);
-
- var list = obj.get_object().get_array_member("notifications");
- for (var i = 0; i < list.get_length(); ++i) {
- add_notification(new Notification.from_json(list.get_object_element(i)));
- }
- n_id = list.get_length() + 1;
-
- _dont_disturb = obj.get_object().get_boolean_member("dont_disturb");
- _ignore_timeout = obj.get_object().get_boolean_member("ignore_timeout");
- } catch (Error err) {
- warning("failed to load cache: %s", err.message);
- }
- }
-
- notify.connect((prop) => prop_changed(prop.name));
-
- notified.connect(() => {
- notify_property("notifications");
- });
-
- resolved.connect((id, reason) => {
- notifs.get(id).resolved(reason);
- notifs.remove(id);
- write_state();
- notify_property("notifications");
- notification_closed(id, reason);
- });
- }
-
- public uint[] notification_ids() throws DBusError, IOError {
- var keys = notifs.get_keys();
- uint[] id = new uint[keys.length()];
- for (var i = 0; i < keys.length(); ++i)
- id[i] = keys.nth_data(i);
- return id;
- }
-
- [DBus (visible = false)]
- public List<weak Notification> notifications {
- owned get { return notifs.get_values(); }
- }
-
- [DBus (visible = false)]
- public Notification get_notification(uint id) {
- return notifs.get(id);
- }
-
- public string get_notification_json(uint id) throws DBusError, IOError {
- return notifs.get(id).to_json_string();
- }
-
- [DBus (name = "Notify")]
- public uint Notify(
- string app_name,
- uint replaces_id,
- string app_icon,
- string summary,
- string body,
- string[] actions,
- HashTable<string, Variant> hints,
- int expire_timeout
- ) throws DBusError, IOError {
- if (hints.get("image-data") != null) {
- var file = cache_image(hints.get("image-data"), app_name);
- if (file != null) {
- hints.set("image-path", new Variant.string(file));
- hints.remove("image-data");
- }
- }
-
- // deprecated hints
- hints.remove("image_data");
- hints.remove("icon_data");
-
- var id = replaces_id > 0 ? replaces_id : n_id++;
-
- var replaced = add_notification(new Notification(
- app_name, id, app_icon, summary, body, actions, hints, expire_timeout
- ));
-
- if (!ignore_timeout && expire_timeout > 0) {
- Timeout.add(expire_timeout, () => {
- resolved(id, ClosedReason.EXPIRED);
- return Source.REMOVE;
- }, Priority.DEFAULT);
- }
-
- notified(id, replaced);
-
- write_state();
- return id;
- }
-
- private bool add_notification(Notification n) {
- n.dismissed.connect(() => resolved(n.id, ClosedReason.DISMISSED_BY_USER));
- n.invoked.connect((action) => action_invoked(n.id, action));
- var replaced = notifs.contains(n.id);
- notifs.set(n.id, n);
- return replaced;
- }
-
- private void write_state() {
- var list = new Json.Builder().begin_array();
- foreach (var n in notifications) {
- list.add_value(n.to_json());
- }
- list.end_array();
-
- var obj = new Json.Builder()
- .begin_object()
- .set_member_name("notifications").add_value(list.get_root())
- .set_member_name("ignore_timeout").add_boolean_value(ignore_timeout)
- .set_member_name("dont_disturb").add_boolean_value(dont_disturb)
- .end_object();
-
- try {
- if (!FileUtils.test(state_directory, FileTest.EXISTS))
- File.new_for_path(state_directory).make_directory_with_parents(null);
-
- FileUtils.set_contents_full(state_file, Json.to_string(obj.get_root(), false));
- } catch (Error err) {
- warning("failed to cache notifications: %s", err.message);
- }
- }
-
- public signal void notification_closed(uint id, uint reason);
- public signal void activation_token(uint id, string token);
-
- public void close_notification(uint id) throws DBusError, IOError {
- resolved(id, ClosedReason.CLOSED);
- }
-
- public void get_server_information(
- out string name,
- out string vendor,
- out string version,
- out string spec_version
- ) throws DBusError, IOError {
- name = Daemon.name;
- vendor = Daemon.vendor;
- version = Daemon.version;
- spec_version = "1.2";
- }
-
- public string[] get_capabilities() throws DBusError, IOError {
- return {"action-icons", "actions", "body", "icon-static", "persistence", "sound"};
- }
-
- private string? cache_image(Variant image, string app_name) {
- int w = image.get_child_value(0).get_int32();
- int h = image.get_child_value(1).get_int32();
- int rs = image.get_child_value(2).get_int32();
- bool alpha = image.get_child_value(3).get_boolean();
- int bps = image.get_child_value(4).get_int32();
- Bytes data = image.get_child_value(6).get_data_as_bytes();
-
- if (bps != 8) {
- warning("Can not cache image from %s. %s", app_name,
- "Currently only RGB images with 8 bits per sample are supported.");
- return null;
- }
-
- var pixbuf = new Gdk.Pixbuf.from_bytes(
- data, Gdk.Colorspace.RGB, alpha, bps, w, h, rs);
-
- if (pixbuf == null)
- return null;
-
- var file_name = cache_directory + "/" + data.hash().to_string("%u.png");
-
- try {
- if (!FileUtils.test(cache_directory, FileTest.EXISTS))
- File.new_for_path(cache_directory).make_directory_with_parents(null);
-
- var output_stream = File.new_for_path(file_name)
- .replace(null, false, FileCreateFlags.NONE, null);
-
- pixbuf.save_to_streamv(output_stream, "png", null, null, null);
- output_stream.close(null);
- } catch (Error err) {
- warning("could not cache image %s", err.message);
- return null;
- }
-
- return file_name;
- }
-
- internal Daemon register(DBusConnection conn) {
- try {
- conn.register_object("/org/freedesktop/Notifications", this);
- } catch (Error err) {
- critical(err.message);
- }
- return this;
- }
-}
-
-public enum AstalNotifd.ClosedReason {
- EXPIRED = 1,
- DISMISSED_BY_USER = 2,
- CLOSED = 3,
- UNDEFINED = 4,
-}
diff --git a/notifd/src/meson.build b/notifd/src/meson.build
deleted file mode 100644
index d3efa36..0000000
--- a/notifd/src/meson.build
+++ /dev/null
@@ -1,79 +0,0 @@
-version_split = meson.project_version().split('.')
-api_version = version_split[0] + '.' + version_split[1]
-gir = 'AstalNotifd-' + api_version + '.gir'
-typelib = 'AstalNotifd-' + api_version + '.typelib'
-
-config = configure_file(
- input: 'config.vala.in',
- output: 'config.vala',
- configuration: {
- 'VERSION': meson.project_version(),
- 'MAJOR_VERSION': version_split[0],
- 'MINOR_VERSION': version_split[1],
- 'MICRO_VERSION': version_split[2],
- },
-)
-
-deps = [
- dependency('glib-2.0'),
- dependency('gobject-2.0'),
- dependency('gio-2.0'),
- dependency('json-glib-1.0'),
- dependency('gdk-pixbuf-2.0'),
-]
-
-sources = [
- config,
- 'daemon.vala',
- 'notifd.vala',
- 'notification.vala',
- 'proxy.vala',
-]
-
-if get_option('lib')
- lib = library(
- meson.project_name(),
- sources,
- dependencies: deps,
- vala_header: meson.project_name() + '.h',
- vala_vapi: meson.project_name() + '-' + api_version + '.vapi',
- vala_gir: gir,
- version: meson.project_version(),
- install: true,
- 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',
- )
-
- custom_target(
- typelib,
- command: [
- find_program('g-ir-compiler'),
- '--output', '@OUTPUT@',
- '--shared-library', get_option('prefix') / get_option('libdir') / '@PLAINNAME@',
- meson.current_build_dir() / gir,
- ],
- input: lib,
- output: typelib,
- depends: lib,
- install: true,
- install_dir: get_option('libdir') / 'girepository-1.0',
- )
-endif
-
-if get_option('cli')
- executable(
- meson.project_name(),
- ['cli.vala', sources],
- dependencies: deps,
- install: true,
- )
-endif
diff --git a/notifd/src/notifd.vala b/notifd/src/notifd.vala
deleted file mode 100644
index c962862..0000000
--- a/notifd/src/notifd.vala
+++ /dev/null
@@ -1,140 +0,0 @@
-namespace AstalNotifd {
- public Notifd get_default() {
- return Notifd.get_default();
- }
-}
-
-public class AstalNotifd.Notifd : Object {
- private static Notifd _instance;
- public static Notifd get_default() {
- if (_instance == null)
- _instance = new Notifd();
-
- return _instance;
- }
-
- private Daemon daemon;
- private DaemonProxy proxy;
-
- public signal void active(ActiveType type);
-
- public bool ignore_timeout {
- get {
- return proxy != null ? proxy.ignore_timeout : daemon.ignore_timeout;
- }
- set {
- if (proxy != null)
- proxy.ignore_timeout = value;
- else
- daemon.ignore_timeout = value;
- }
- }
-
- public bool dont_disturb {
- get {
- return proxy != null ? proxy.dont_disturb : daemon.dont_disturb;
- }
- set {
- if (proxy != null)
- proxy.dont_disturb = value;
- else
- daemon.dont_disturb = value;
- }
- }
-
- 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();
- }
-
- public Notification get_notification(uint id) {
- return proxy != null ? proxy.get_notification(id) : daemon.get_notification(id);
- }
-
- public string get_notification_json(uint id) {
- return get_notification(id).to_json_string();
- }
-
- public signal void notified(uint id, bool replaced);
- public signal void resolved(uint id, ClosedReason reason);
-
- construct {
- // hack to make it synchronous
- MainLoop? loop = null;
-
- if (!MainContext.default().is_owner()) {
- loop = new MainLoop();
- }
-
- bool done = false;
-
- Bus.own_name(
- BusType.SESSION,
- "org.freedesktop.Notifications",
- BusNameOwnerFlags.NONE,
- acquire_daemon,
- on_daemon_acquired,
- make_proxy
- );
-
- active.connect(() => {
- done = true;
- if (loop != null && loop.is_running()) {
- loop.quit();
- }
- });
-
- if (loop != null) {
- loop.run();
- } else {
- while (!done) {
- MainContext.default().iteration(false);
- }
- }
- }
-
- private void acquire_daemon(DBusConnection conn) {
- daemon = new Daemon().register(conn);
- }
-
- private void on_daemon_acquired() {
- if (proxy != null) {
- proxy.stop();
- proxy = null;
- }
- daemon.notified.connect((id, replaced) => notified(id, replaced));
- daemon.resolved.connect((id, reason) => resolved(id, reason));
- daemon.notify.connect((prop) => {
- if (get_class().find_property(prop.name) != null) {
- notify_property(prop.name);
- }
- });
- active(ActiveType.DAEMON);
- }
-
- private void make_proxy() {
- proxy = new DaemonProxy();
-
- if (proxy.start()) {
- active(ActiveType.PROXY);
- } else {
- return;
- }
-
- proxy.notified.connect((id, replaced) => notified(id, replaced));
- proxy.resolved.connect((id, reason) => resolved(id, reason));
- proxy.notify.connect((prop) => {
- if (get_class().find_property(prop.name) != null) {
- notify_property(prop.name);
- }
- });
- }
-}
-
-public enum AstalNotifd.ActiveType {
- DAEMON,
- PROXY,
-}
diff --git a/notifd/src/notification.vala b/notifd/src/notification.vala
deleted file mode 100644
index 0b4af06..0000000
--- a/notifd/src/notification.vala
+++ /dev/null
@@ -1,160 +0,0 @@
-public enum AstalNotifd.Urgency {
- LOW = 0,
- NORMAL = 1,
- CRITICAL = 2,
-}
-
-public struct AstalNotifd.Action {
- public string id;
- public string label;
-}
-
-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; }
- public List<Action?> actions { get { return _actions; } }
-
- public string image { get { return get_str_hint("image-path"); } }
- public bool action_icons { get { return get_bool_hint("action-icons"); } }
- public string category { get { return get_str_hint("category"); } }
- public string desktop_entry { get { return get_str_hint("desktop-entry"); } }
- public bool resident { get { return get_bool_hint("resident"); } }
- public string sound_file { get { return get_str_hint("sound-file"); } }
- public string sound_name { get { return get_str_hint("sound-name"); } }
- public bool suppress_sound { get { return get_bool_hint("suppress-sound"); } }
- public bool transient { get { return get_bool_hint("transient"); } }
- public int x { get { return get_int_hint("x"); } }
- public int y { get { return get_int_hint("y"); } }
- public Urgency urgency { get { return get_int_hint("urgency"); } }
-
- internal Notification(
- string app_name,
- uint id,
- string app_icon,
- string summary,
- string body,
- string[] actions,
- HashTable<string, Variant> hints,
- int expire_timeout
- ) {
- Object(
- app_name: app_name,
- id: id,
- app_icon: app_icon,
- summary: summary,
- body: body,
- expire_timeout: expire_timeout,
- time: new DateTime.now_local().to_unix()
- );
-
- this.hints = hints;
- _actions = new List<Action?>();
- for (var i = 0; i < actions.length; i += 2) {
- _actions.append(Action() {
- id = actions[i],
- label = actions[i + 1]
- });
- }
- }
-
- public Variant? get_hint(string hint) {
- return hints.contains(hint) ? hints.get(hint) : null;
- }
-
- public unowned string get_str_hint(string hint) {
- return hints.contains(hint) ? hints.get(hint).get_string() : null;
- }
-
- public bool get_bool_hint(string hint) {
- return hints.contains(hint) ? hints.get(hint).get_boolean() : false;
- }
-
- public int get_int_hint(string hint) {
- return hints.contains(hint) ? hints.get(hint).get_int32() : 0;
- }
-
- public signal void resolved(ClosedReason reason);
- public signal void dismissed();
- public signal void invoked(string action);
-
- public void dismiss() { dismissed(); }
- public void invoke(string action) { invoked(action); }
-
- internal Notification.from_json(Json.Object root) throws GLib.Error {
- foreach (var key in root.get_members()) {
- var node = root.get_member(key);
- switch (key) {
- case "id": id = (uint)node.get_int(); break;
- case "time": time = node.get_int(); break;
- case "expire_timeout": expire_timeout = (int)node.get_int(); break;
- case "app_name": app_name = node.get_string(); break;
- case "app_icon": app_icon = node.get_string(); break;
- case "summary": summary = node.get_string(); break;
- case "body": body = node.get_string(); break;
- case "hints":
- hints = new HashTable<string, Variant>(str_hash, str_equal);
- var obj = node.get_object();
- foreach (var hint in obj.get_members()) {
- hints.set(hint, Json.gvariant_deserialize(obj.get_member(hint), null));
- }
- break;
- case "actions":
- _actions = new List<Action?>();
- for (var i = 0; i < node.get_array().get_length(); ++i) {
- var o = node.get_array().get_object_element(i);
- _actions.append(Action() {
- id = o.get_member("id").get_string(),
- label = o.get_member("label").get_string()
- });
- }
- break;
- default: break;
- }
- }
- }
-
- internal static Notification from_json_string(string json) throws GLib.Error {
- var parser = new Json.Parser();
- parser.load_from_data(json);
- return new Notification.from_json(parser.get_root().get_object());
- }
-
- public string to_json_string() {
- var generator = new Json.Generator();
- generator.set_root(to_json());
- return generator.to_data(null);
- }
-
- internal Json.Node to_json() {
- var acts = new Json.Builder().begin_array();
- foreach (var action in actions) {
- acts.begin_object()
- .set_member_name("id").add_string_value(action.id)
- .set_member_name("label").add_string_value(action.label)
- .end_object();
- }
- acts.end_array();
-
- return new Json.Builder()
- .begin_object()
- .set_member_name("id").add_int_value(id)
- .set_member_name("time").add_int_value(time)
- .set_member_name("expire_timeout").add_int_value(expire_timeout)
- .set_member_name("app_name").add_string_value(app_name)
- .set_member_name("app_icon").add_string_value(app_icon)
- .set_member_name("summary").add_string_value(summary)
- .set_member_name("body").add_string_value(body)
- .set_member_name("actions").add_value(acts.get_root())
- .set_member_name("hints").add_value(Json.gvariant_serialize(hints))
- .end_object()
- .get_root();
- }
-}
diff --git a/notifd/src/proxy.vala b/notifd/src/proxy.vala
deleted file mode 100644
index bedb8b9..0000000
--- a/notifd/src/proxy.vala
+++ /dev/null
@@ -1,129 +0,0 @@
-[DBus (name = "org.freedesktop.Notifications")]
-internal interface AstalNotifd.IDaemon : DBusProxy {
- public abstract bool ignore_timeout { get; set; }
- public abstract bool dont_disturb { get; set; }
-
- public abstract uint[] notification_ids() throws DBusError, IOError;
- public abstract string get_notification_json(uint id) throws DBusError, IOError;
-
- public signal void notified(uint id, bool replaced);
- public signal void resolved(uint id, ClosedReason reason);
- public signal void prop_changed(string prop);
-
- public abstract void emit_resolved(uint id, ClosedReason reason);
- public abstract void emit_action_invoked(uint id, string action);
-}
-
-internal class AstalNotifd.DaemonProxy : Object {
- private HashTable<uint, Notification> notifs =
- new HashTable<uint, Notification>((i) => i, (a, b) => a == b);
-
- public List<weak Notification> notifications {
- owned get { return notifs.get_values(); }
- }
-
- public bool ignore_timeout {
- get { return proxy.ignore_timeout; }
- set { proxy.ignore_timeout = value; }
- }
-
- public bool dont_disturb {
- get { return proxy.dont_disturb; }
- set { proxy.dont_disturb = value; }
- }
-
- public uint[] notification_ids() throws DBusError, IOError {
- return proxy.notification_ids();
- }
-
- public Notification get_notification(uint id) {
- return notifs.get(id);
- }
-
- public signal void notified(uint id, bool replaced);
- public signal void resolved(uint id, ClosedReason reason);
-
- private IDaemon proxy;
- private List<ulong> ids = new List<ulong>();
-
- public void stop() {
- if (ids.length() > 0) {
- foreach (var id in ids)
- SignalHandler.disconnect(proxy, id);
- }
- }
-
- public bool start() {
- try {
- var bus = Bus.get_sync(BusType.SESSION, null);
- var variant = bus.call_sync(
- "org.freedesktop.Notifications",
- "/org/freedesktop/Notifications",
- "org.freedesktop.Notifications",
- "GetServerInformation",
- null,
- null,
- DBusCallFlags.NONE,
- -1,
- null);
-
- var name = variant.get_child_value(0).get_string();
- var vendor = variant.get_child_value(1).get_string();
- var version = variant.get_child_value(2).get_string();
-
- var running = name == Daemon.name
- && vendor == Daemon.vendor
- && version == Daemon.version;
-
- if (running) {
- setup_proxy();
- return true;
- } else {
- critical("cannot get proxy: %s is already running", name);
- }
- } catch (Error err) {
- critical("cannot get proxy: %s", err.message);
- }
- return false;
- }
-
- private void setup_proxy() throws Error {
- proxy = Bus.get_proxy_sync(
- BusType.SESSION,
- "org.freedesktop.Notifications",
- "/org/freedesktop/Notifications"
- );
-
- foreach (var id in proxy.notification_ids())
- add_notification(id);
-
- ids.append(proxy.prop_changed.connect((prop) => {
- if (prop == "ignore-timeout" || prop == "dont-disturb")
- notify_property(prop);
- }));
-
- ids.append(proxy.notified.connect((id, replaced) => {
- add_notification(id);
- notified(id, replaced);
- notify_property("notifications");
- }));
-
- ids.append(proxy.resolved.connect((id, reason) => {
- notifs.remove(id);
- resolved(id, reason);
- notify_property("notifications");
- }));
- }
-
- private void add_notification(uint id) {
- try {
- var n = Notification.from_json_string(proxy.get_notification_json(id));
- proxy.resolved.connect((id, reason) => n.resolved(reason));
- n.dismissed.connect(() => proxy.emit_resolved(id, ClosedReason.DISMISSED_BY_USER));
- n.invoked.connect((action) => proxy.emit_action_invoked(id, action));
- notifs.set(id, n);
- } catch (Error err) {
- critical(err.message);
- }
- }
-}
diff --git a/notifd/src/signals.md b/notifd/src/signals.md
deleted file mode 100644
index cdc6688..0000000
--- a/notifd/src/signals.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# Signals
-
-ignore this, I'm just dumb and can't follow where signals go or get emitted from
-
-## Notification
-
-* resolved(reason) - by daemon/proxy
-* dismissed() - by user with `.dismiss()`
-* invoked(action) - by user with `.invoke()`
-
-## Deamon
-
-non-spec, used by user
-
-* notified(id, replaced) - by outside through dbus with `.Notify()`
-* resolved(id, reason) - by `Notification.dismiss()` or outside with `.CloseNotification`
-
-spec, not used by user
-
-* notification_closed(id, reason) - sideeffect of `resolved`
-* action_invoked(id, action) - by `Notification.invoke()`
-
-## Proxy
-
-mirrors Daemon
-
-* notified(id, replaced)
-* resolved(id, reason)
-
-creates `Notification` objects through daemon's json strings
-and hooks them up to call daemon's signals and vice versa
-
-## Notifd
-
-acts as a bridge between Proxy/Daemon, everything else is internal only