From cdbe45254d832c05a89d3b20ce15f91a1ba7ee98 Mon Sep 17 00:00:00 2001 From: MeexReay Date: Mon, 21 Apr 2025 00:49:06 +0300 Subject: [PATCH] libnotify --- Cargo.lock | 196 +++++++++++++++++++++++++++++++++++++----------- Cargo.toml | 8 +- flake.lock | 33 ++++++++ flake.nix | 80 ++++++++------------ src/chat/gui.rs | 80 +++++++++++++++----- 5 files changed, 286 insertions(+), 111 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0503881..d3ce65a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -94,9 +94,11 @@ version = "0.1.4+2.0" dependencies = [ "chrono", "clap", + "gdk-pixbuf 0.3.0", "gtk4", "homedir", "lazy_static", + "libnotify", "native-tls", "rand", "regex", @@ -106,6 +108,12 @@ dependencies = [ "socks", ] +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.9.0" @@ -130,9 +138,9 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae50b5510d86cf96ac2370e66d8dc960882f3df179d6a5a1e52bd94a1416c0f7" dependencies = [ - "bitflags", + "bitflags 2.9.0", "cairo-sys-rs", - "glib", + "glib 0.20.9", "libc", ] @@ -142,7 +150,7 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f18b6bb8e43c7eb0f2aac7976afe0c61b6f5fc2ab7bc4c139537ea56c92290df" dependencies = [ - "glib-sys", + "glib-sys 0.20.9", "libc", "system-deps", ] @@ -405,27 +413,54 @@ dependencies = [ "slab", ] +[[package]] +name = "gdk-pixbuf" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16160d212ae91abe9f3324c3fb233929ba322dde63585d15cda3336f8c529ed1" +dependencies = [ + "gdk-pixbuf-sys 0.5.0", + "glib 0.4.1", + "glib-sys 0.5.0", + "gobject-sys 0.5.0", + "libc", +] + [[package]] name = "gdk-pixbuf" version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7563afd6ff0a221edfbb70a78add5075b8d9cb48e637a40a24c3ece3fea414d0" dependencies = [ - "gdk-pixbuf-sys", + "gdk-pixbuf-sys 0.20.7", "gio", - "glib", + "glib 0.20.9", "libc", ] +[[package]] +name = "gdk-pixbuf-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "798f97101eea8180da363d0e80e07ec7ec6d1809306601c0100c1de5bc8b4f52" +dependencies = [ + "bitflags 1.3.2", + "gio-sys 0.5.0", + "glib-sys 0.5.0", + "gobject-sys 0.5.0", + "libc", + "pkg-config", +] + [[package]] name = "gdk-pixbuf-sys" version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67f2587c9202bf997476bbba6aaed4f78a11538a2567df002a5f57f5331d0b5c" dependencies = [ - "gio-sys", - "glib-sys", - "gobject-sys", + "gio-sys 0.20.9", + "glib-sys 0.20.9", + "gobject-sys 0.20.9", "libc", "system-deps", ] @@ -437,10 +472,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4850c9d9c1aecd1a3eb14fadc1cdb0ac0a2298037e116264c7473e1740a32d60" dependencies = [ "cairo-rs", - "gdk-pixbuf", + "gdk-pixbuf 0.20.9", "gdk4-sys", "gio", - "glib", + "glib 0.20.9", "libc", "pango", ] @@ -452,10 +487,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f6eb95798e2b46f279cf59005daf297d5b69555428f185650d71974a910473a" dependencies = [ "cairo-sys-rs", - "gdk-pixbuf-sys", - "gio-sys", - "glib-sys", - "gobject-sys", + "gdk-pixbuf-sys 0.20.7", + "gio-sys 0.20.9", + "glib-sys 0.20.9", + "gobject-sys 0.20.9", "libc", "pango-sys", "pkg-config", @@ -484,42 +519,68 @@ dependencies = [ "futures-core", "futures-io", "futures-util", - "gio-sys", - "glib", + "gio-sys 0.20.9", + "glib 0.20.9", "libc", "pin-project-lite", "smallvec", ] +[[package]] +name = "gio-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a303bbf7a5e75ab3b627117ff10e495d1b9e97e1d68966285ac2b1f6270091bc" +dependencies = [ + "bitflags 1.3.2", + "glib-sys 0.5.0", + "gobject-sys 0.5.0", + "libc", + "pkg-config", +] + [[package]] name = "gio-sys" version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "160eb5250a26998c3e1b54e6a3d4ea15c6c7762a6062a19a7b63eff6e2b33f9e" dependencies = [ - "glib-sys", - "gobject-sys", + "glib-sys 0.20.9", + "gobject-sys 0.20.9", "libc", "system-deps", "windows-sys", ] +[[package]] +name = "glib" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9b0452824cc63066940f01adc721804919f0b76cdba3cfab977b00b87f16d4a" +dependencies = [ + "bitflags 1.3.2", + "glib-sys 0.5.0", + "gobject-sys 0.5.0", + "lazy_static", + "libc", +] + [[package]] name = "glib" version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707b819af8059ee5395a2de9f2317d87a53dbad8846a2f089f0bb44703f37686" dependencies = [ - "bitflags", + "bitflags 2.9.0", "futures-channel", "futures-core", "futures-executor", "futures-task", "futures-util", - "gio-sys", + "gio-sys 0.20.9", "glib-macros", - "glib-sys", - "gobject-sys", + "glib-sys 0.20.9", + "gobject-sys 0.20.9", "libc", "memchr", "smallvec", @@ -538,6 +599,17 @@ dependencies = [ "syn", ] +[[package]] +name = "glib-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9693049613ff52b93013cc3d2590366d8e530366d288438724b73f6c7dc4be8" +dependencies = [ + "bitflags 1.3.2", + "libc", + "pkg-config", +] + [[package]] name = "glib-sys" version = "0.20.9" @@ -548,13 +620,25 @@ dependencies = [ "system-deps", ] +[[package]] +name = "gobject-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60d507c87a71b1143c66ed21a969be9b99a76df234b342d733e787e6c9c7d7c2" +dependencies = [ + "bitflags 1.3.2", + "glib-sys 0.5.0", + "libc", + "pkg-config", +] + [[package]] name = "gobject-sys" version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c773a3cb38a419ad9c26c81d177d96b4b08980e8bdbbf32dace883e96e96e7e3" dependencies = [ - "glib-sys", + "glib-sys 0.20.9", "libc", "system-deps", ] @@ -565,7 +649,7 @@ version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cbc5911bfb32d68dcfa92c9510c462696c2f715548fcd7f3f1be424c739de19" dependencies = [ - "glib", + "glib 0.20.9", "graphene-sys", "libc", ] @@ -576,7 +660,7 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11a68d39515bf340e879b72cecd4a25c1332557757ada6e8aba8654b4b81d23a" dependencies = [ - "glib-sys", + "glib-sys 0.20.9", "libc", "pkg-config", "system-deps", @@ -590,7 +674,7 @@ checksum = "61f5e72f931c8c9f65fbfc89fe0ddc7746f147f822f127a53a9854666ac1f855" dependencies = [ "cairo-rs", "gdk4", - "glib", + "glib 0.20.9", "graphene-rs", "gsk4-sys", "libc", @@ -605,8 +689,8 @@ checksum = "755059de55fa6f85a46bde8caf03e2184c96bfda1f6206163c72fb0ea12436dc" dependencies = [ "cairo-sys-rs", "gdk4-sys", - "glib-sys", - "gobject-sys", + "glib-sys 0.20.9", + "gobject-sys 0.20.9", "graphene-sys", "libc", "pango-sys", @@ -622,10 +706,10 @@ dependencies = [ "cairo-rs", "field-offset", "futures-channel", - "gdk-pixbuf", + "gdk-pixbuf 0.20.9", "gdk4", "gio", - "glib", + "glib 0.20.9", "graphene-rs", "gsk4", "gtk4-macros", @@ -653,11 +737,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41e03b01e54d77c310e1d98647d73f996d04b2f29b9121fe493ea525a7ec03d6" dependencies = [ "cairo-sys-rs", - "gdk-pixbuf-sys", + "gdk-pixbuf-sys 0.20.7", "gdk4-sys", - "gio-sys", - "glib-sys", - "gobject-sys", + "gio-sys 0.20.9", + "glib-sys 0.20.9", + "gobject-sys 0.20.9", "graphene-sys", "gsk4-sys", "libc", @@ -763,6 +847,34 @@ version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +[[package]] +name = "libnotify" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10506a4f8bc6f8f7ccc6fde3a8290378d7aed3d1a26dca606a73e2ffe140cc2d" +dependencies = [ + "gdk-pixbuf 0.3.0", + "gdk-pixbuf-sys 0.5.0", + "glib 0.4.1", + "glib-sys 0.5.0", + "gobject-sys 0.5.0", + "libnotify-sys", +] + +[[package]] +name = "libnotify-sys" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0a716b9b7d24ed10f1eb431e1527fa13c9a4bf2d4fa68bb3e54da1d0747383c" +dependencies = [ + "bitflags 1.3.2", + "gdk-pixbuf-sys 0.5.0", + "glib-sys 0.5.0", + "gobject-sys 0.5.0", + "libc", + "pkg-config", +] + [[package]] name = "libyml" version = "0.0.5" @@ -823,7 +935,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags", + "bitflags 2.9.0", "cfg-if", "cfg_aliases", "libc", @@ -850,7 +962,7 @@ version = "0.10.70" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61cfb4e166a8bb8c9b55c500bc2308550148ece889be90f609377e58140f42c6" dependencies = [ - "bitflags", + "bitflags 2.9.0", "cfg-if", "foreign-types", "libc", @@ -895,7 +1007,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b1f5dc1b8cf9bc08bfc0843a04ee0fa2e78f1e1fa4b126844a383af4f25f0ec" dependencies = [ "gio", - "glib", + "glib 0.20.9", "libc", "pango-sys", ] @@ -906,8 +1018,8 @@ version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dbb9b751673bd8fe49eb78620547973a1e719ed431372122b20abd12445bab5" dependencies = [ - "glib-sys", - "gobject-sys", + "glib-sys 0.20.9", + "gobject-sys 0.20.9", "libc", "system-deps", ] @@ -1040,7 +1152,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags", + "bitflags 2.9.0", "errno", "libc", "linux-raw-sys", @@ -1074,7 +1186,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags", + "bitflags 2.9.0", "core-foundation", "core-foundation-sys", "libc", @@ -1541,7 +1653,7 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" dependencies = [ - "bitflags", + "bitflags 2.9.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index ae0796b..861ce45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,4 +15,10 @@ serde = { version = "1.0.219", features = ["serde_derive"] } gtk4 = { version = "0.9.6", features = [ "v4_10" ] } chrono = "0.4.40" serde_default = "0.2.0" -socks = "0.3.4" \ No newline at end of file +socks = "0.3.4" +libnotify = { version = "1.0.3", optional = true } +gdk-pixbuf = "0.3.0" + +[features] +default = ["libnotify"] +libnotify = ["dep:libnotify"] diff --git a/flake.lock b/flake.lock index 0476fdd..e462e6f 100644 --- a/flake.lock +++ b/flake.lock @@ -18,6 +18,23 @@ "type": "github" } }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "id": "flake-utils", + "type": "indirect" + } + }, "nixpkgs": { "locked": { "lastModified": 1744463964, @@ -68,6 +85,7 @@ "root": { "inputs": { "flake-parts": "flake-parts", + "flake-utils": "flake-utils", "nixpkgs": "nixpkgs", "rust-overlay": "rust-overlay" } @@ -89,6 +107,21 @@ "repo": "rust-overlay", "type": "github" } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index ab92bea..0bd27c6 100644 --- a/flake.nix +++ b/flake.nix @@ -7,53 +7,37 @@ rust-overlay.url = "github:oxalica/rust-overlay"; }; - outputs = inputs: - inputs.flake-parts.lib.mkFlake { inherit inputs; } { - systems = [ "x86_64-linux" ]; - perSystem = { config, self', pkgs, lib, system, ... }: - let - devDeps = with pkgs; [ pkg-config openssl gtk4 pango ]; - - cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml); - msrv = cargoToml.package.rust-version; - - mkDevShell = rustc: - pkgs.mkShell { - shellHook = '' - export RUST_SRC_PATH=${pkgs.rustPlatform.rustLibSrc} - ''; - buildInputs = devDeps; - nativeBuildInputs = devDeps ++ [ rustc ]; - }; - in { - _module.args.pkgs = import inputs.nixpkgs { - inherit system; - overlays = [ (import inputs.rust-overlay) ]; - }; - - devShells.default = self'.devShells.stable; - - packages.default = let - deps = with pkgs; [ - pkg-config - openssl - gtk4 - pango - ]; - in (pkgs.makeRustPlatform { - cargo = pkgs.rust-bin.stable.latest.minimal; - rustc = pkgs.rust-bin.stable.latest.minimal; - }).buildRustPackage { - inherit (cargoToml.package) name version; - src = ./.; - cargoLock.lockFile = ./Cargo.lock; - buildInputs = deps; - nativeBuildInputs = deps; - }; - - devShells.nightly = (mkDevShell (pkgs.rust-bin.selectLatestNightlyWith (toolchain: toolchain.default))); - devShells.stable = (mkDevShell pkgs.rust-bin.stable.latest.default); - devShells.msrv = (mkDevShell pkgs.rust-bin.stable.${msrv}.default); + outputs = { self, nixpkgs, rust-overlay, flake-utils, ... }: + flake-utils.lib.eachDefaultSystem (system: + let + devDeps = with pkgs; [ pkg-config openssl gtk4 pango libnotify ]; + cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml); + overlays = [ (import rust-overlay) ]; + pkgs = import nixpkgs { + inherit system overlays; }; - }; + mkDevShell = rustc: + pkgs.mkShell { + shellHook = '' + export RUST_SRC_PATH=${pkgs.rustPlatform.rustLibSrc} + ''; + buildInputs = devDeps; + nativeBuildInputs = devDeps ++ [ rustc ]; + }; + in { + devShells.nightly = (mkDevShell (pkgs.rust-bin.selectLatestNightlyWith (toolchain: toolchain.default))); + devShells.default = (mkDevShell pkgs.rust-bin.stable.latest.default); + + packages.default = (pkgs.makeRustPlatform { + cargo = pkgs.rust-bin.stable.latest.minimal; + rustc = pkgs.rust-bin.stable.latest.minimal; + }).buildRustPackage { + inherit (cargoToml.package) name version; + src = ./.; + cargoLock.lockFile = ./Cargo.lock; + buildInputs = devDeps; + nativeBuildInputs = devDeps ++ [ pkgs.rustc ]; + }; + } + ); } diff --git a/src/chat/gui.rs b/src/chat/gui.rs index aaa303f..2e89c4e 100644 --- a/src/chat/gui.rs +++ b/src/chat/gui.rs @@ -1,22 +1,23 @@ -use std::sync::{mpsc::{channel, Receiver}, Arc}; +use std::{sync::{mpsc::{channel, Receiver}, Arc}, time::UNIX_EPOCH}; use std::cell::RefCell; use std::time::{Duration, SystemTime}; use std::thread; use chrono::Local; -use gtk4::{self as gtk, gio::Notification, glib::timeout_add_once}; +use gtk4 as gtk; +use gtk::gdk_pixbuf::{Pixbuf, PixbufAnimation, PixbufLoader}; use gtk::prelude::*; use gtk::gdk::{Cursor, Display, Texture}; -use gtk::gdk_pixbuf::{Pixbuf, PixbufAnimation, PixbufLoader}; use gtk::gio::{self, ActionEntry, ApplicationFlags, MemoryInputStream, Menu}; use gtk::glib::clone; use gtk::glib::{ self, clone::Downgrade, timeout_add_local, source::timeout_add_local_once, - ControlFlow + ControlFlow, + timeout_add_once }; use gtk::pango::WrapMode; use gtk::{ @@ -31,7 +32,8 @@ ctx::Context, on_send_message, parse_message, print_message, recv_tick, sanitize struct UiModel { chat_box: GtkBox, chat_scrolled: ScrolledWindow, - app: Application + app: Application, + window: ApplicationWindow } thread_local!( @@ -53,6 +55,13 @@ fn load_pixbuf(data: &[u8]) -> Pixbuf { loader.pixbuf().unwrap() } +fn load_gdk_pixbuf(data: &[u8]) -> gdk_pixbuf::Pixbuf { + let loader = gdk_pixbuf::PixbufLoader::new(); + loader.loader_write(data).unwrap(); + loader.close().unwrap(); + loader.get_pixbuf().unwrap() +} + macro_rules! gui_entry_setting { ($e:expr, $i:ident, $ctx:ident, $vbox:ident) => { { @@ -585,7 +594,8 @@ fn build_ui(ctx: Arc, app: &Application) -> UiModel { UiModel { chat_scrolled, chat_box, - app: app.clone() + app: app.clone(), + window: window.clone() } } @@ -653,9 +663,26 @@ fn load_css() { ); } -fn on_add_message(ctx: Arc, ui: &UiModel, message: String) { - let app = ui.app.clone(); +#[cfg(feature = "libnotify")] +fn send_notification(_: Arc, _: &UiModel, title: &str, message: &str) { + use libnotify::Notification; + let notification = Notification::new(title, message, None); + notification.set_app_name("bRAC"); + notification.set_image_from_pixbuf(&load_gdk_pixbuf(include_bytes!("images/icon.png"))); + notification.show().expect("libnotify send error"); +} + +#[cfg(not(feature = "libnotify"))] +fn send_notification(ctx: Arc, ui: &UiModel, title: &str, message: &str) { + use gtk4::gio::Notification; + + let notif = Notification::new(title); + notif.set_body(Some(&message)); + ui.app.send_notification(None, ¬if); +} + +fn on_add_message(ctx: Arc, ui: &UiModel, message: String) { let Some(message) = sanitize_message(message) else { return; }; if message.is_empty() { @@ -701,19 +728,21 @@ fn on_add_message(ctx: Arc, ui: &UiModel, message: String) { hbox.append(&name_label); - if !app.windows()[0].is_active() { + if !ui.window.is_active() { if ctx.config(|o| o.chunked_enabled) { - let notif = Notification::new(&format!("{}'s Message", &name)); - notif.set_body(Some(&content)); - app.send_notification(Some("user-message"), ¬if); + send_notification(ctx.clone(), ui, &format!("{}'s Message", &name), &content); + // let notif = Notification::new(&format!("{}'s Message", &name)); + // notif.set_body(Some(&content)); + // app.send_notification(Some("user-message"), ¬if); } } } else { - if !app.windows()[0].is_active() { + if !ui.window.is_active() { if ctx.config(|o| o.chunked_enabled) { - let notif = Notification::new("System Message"); - notif.set_body(Some(&content)); - app.send_notification(Some("system-message"), ¬if); + send_notification(ctx.clone(), ui, "System Message", &content); + // let notif = Notification::new("System Message"); + // notif.set_body(Some(&content)); + // app.send_notification(Some("system-message"), ¬if); } } } @@ -743,11 +772,12 @@ fn on_add_message(ctx: Arc, ui: &UiModel, message: String) { hbox.append(&content_label); - if !app.windows()[0].is_active() { + if !ui.window.is_active() { if ctx.config(|o| o.chunked_enabled) { - let notif = Notification::new("Chat Message"); - notif.set_body(Some(&message)); - app.send_notification(Some("chat-message"), ¬if); + send_notification(ctx.clone(), ui, "Chat Message", &message); + // let notif = Notification::new("Chat Message"); + // notif.set_body(Some(&message)); + // app.send_notification(Some("chat-message"), ¬if); } } } @@ -776,6 +806,11 @@ fn run_recv_loop(ctx: Arc) { } pub fn run_main_loop(ctx: Arc) { + #[cfg(feature = "libnotify")] + { + libnotify::init("ru.themixray.bRAC").expect("libnotify init error"); + } + let application = Application::builder() .application_id("ru.themixray.bRAC") .flags(ApplicationFlags::FLAGS_NONE) @@ -800,4 +835,9 @@ pub fn run_main_loop(ctx: Arc) { }); application.run_with_args::<&str>(&[]); + + #[cfg(feature = "libnotify")] + { + libnotify::uninit(); + } } \ No newline at end of file