From 15144220fa207cd909282ea9f91cf794a7762fd8 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Tue, 31 Oct 2023 17:06:14 +0400 Subject: Show notification on screenshot --- Cargo.lock | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 4 +- src/niri.rs | 15 ++++- src/utils.rs | 31 +++++++++ 4 files changed, 263 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c1c60c98..f6994b55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -348,6 +348,12 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + [[package]] name = "block-buffer" version = "0.10.4" @@ -696,6 +702,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "740bb192a8e2d1350119916954f4409ee7f62f149b536911eeb78ba5a20526bf" +[[package]] +name = "deranged" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +dependencies = [ + "powerfmt", +] + [[package]] name = "derivative" version = "2.2.0" @@ -726,6 +741,16 @@ dependencies = [ "dirs-sys", ] +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + [[package]] name = "dirs-sys" version = "0.4.1" @@ -738,6 +763,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "dispatch" version = "0.2.0" @@ -921,6 +957,15 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" +[[package]] +name = "form_urlencoded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +dependencies = [ + "percent-encoding", +] + [[package]] name = "futures-core" version = "0.3.28" @@ -1010,7 +1055,7 @@ dependencies = [ "libc", "log", "rustversion", - "windows", + "windows 0.48.0", ] [[package]] @@ -1103,6 +1148,16 @@ dependencies = [ "objc2", ] +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "indexmap" version = "2.0.2" @@ -1386,6 +1441,28 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "mac-notification-sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51fca4d74ff9dbaac16a01b924bc3693fa2bba0862c2c633abc73f9a8ea21f64" +dependencies = [ + "cc", + "dirs-next", + "objc-foundation", + "objc_id", + "time", +] + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + [[package]] name = "matchers" version = "0.1.0" @@ -1523,6 +1600,7 @@ dependencies = [ "log", "logind-zbus", "miette", + "notify-rust", "pipewire", "png", "portable-atomic", @@ -1536,6 +1614,7 @@ dependencies = [ "tracing", "tracing-subscriber", "tracy-client", + "url", "xcursor", "zbus", ] @@ -1574,6 +1653,19 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "notify-rust" +version = "4.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d7b75c8958cb2eab3451538b32db8a7b74006abc33eb2e6a9a56d21e4775c2b" +dependencies = [ + "log", + "mac-notification-sys", + "serde", + "tauri-winrt-notification", + "zbus", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1615,6 +1707,26 @@ dependencies = [ "syn 2.0.38", ] +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +dependencies = [ + "block", + "objc", + "objc_id", +] + [[package]] name = "objc-sys" version = "0.3.1" @@ -1637,6 +1749,15 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + [[package]] name = "once_cell" version = "1.18.0" @@ -1798,6 +1919,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b559898e0b4931ed2d3b959ab0c2da4d99cc644c4b0b1a35b4d344027f474023" +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -2373,6 +2500,16 @@ version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" +[[package]] +name = "tauri-winrt-notification" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "006851c9ccefa3c38a7646b8cec804bb429def3da10497bfa977179869c3e8e2" +dependencies = [ + "quick-xml", + "windows 0.51.1", +] + [[package]] name = "tempfile" version = "3.8.0" @@ -2416,6 +2553,39 @@ dependencies = [ "once_cell", ] +[[package]] +name = "time" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +dependencies = [ + "deranged", + "powerfmt", + "serde", + "time-core", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "toml" version = "0.8.4" @@ -2587,12 +2757,27 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-segmentation" version = "1.10.1" @@ -2605,6 +2790,17 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +[[package]] +name = "url" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + [[package]] name = "utf8parse" version = "0.2.1" @@ -2945,6 +3141,25 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +dependencies = [ + "windows-core", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.45.0" diff --git a/Cargo.toml b/Cargo.toml index 1f228785..856c3f6c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ libc = "0.2.149" logind-zbus = { version = "3.1.2", optional = true } log = { version = "0.4.20", features = ["max_level_trace", "release_max_level_debug"] } miette = "5.10.0" +notify-rust = { version = "4.9.0", optional = true } pipewire = { version = "0.7.2", optional = true } png = "0.17.10" portable-atomic = { version = "1.5.0", default-features = false, features = ["float"] } @@ -29,6 +30,7 @@ serde = { version = "1.0.189", features = ["derive"] } tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } tracing = { version = "0.1.40", features = ["max_level_trace", "release_max_level_debug"] } tracy-client = { version = "0.16.3", default-features = false } +url = { version = "2.4.1", optional = true } xcursor = "0.3.4" zbus = { version = "3.14.1", optional = true } @@ -63,7 +65,7 @@ proptest-derive = "0.4.0" [features] default = ["dbus", "xdp-gnome-screencast"] # Enables DBus support (required for xdp-gnome and power button inhibiting). -dbus = ["zbus", "logind-zbus", "async-channel", "async-io"] +dbus = ["zbus", "logind-zbus", "async-channel", "async-io", "notify-rust", "url"] # Enables screencasting support through xdg-desktop-portal-gnome. xdp-gnome-screencast = ["dbus", "pipewire"] # Enables the Tracy profiler instrumentation. diff --git a/src/niri.rs b/src/niri.rs index 5f5a02e4..440962c2 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -2053,14 +2053,25 @@ impl Niri { let buf: Arc<[u8]> = Arc::from(buf.into_boxed_slice()); let _ = tx.send(buf.clone()); + let mut image_path = None; + if let Some(path) = path { debug!("saving screenshot to {path:?}"); - if let Err(err) = std::fs::write(path, buf) { - warn!("error saving screenshot image: {err:?}"); + + match std::fs::write(&path, buf) { + Ok(()) => image_path = Some(path), + Err(err) => { + warn!("error saving screenshot image: {err:?}"); + } } } else { debug!("not saving screenshot to disk"); } + + #[cfg(feature = "dbus")] + crate::utils::show_screenshot_notification(image_path); + #[cfg(not(feature = "dbus"))] + drop(image_path); }); Ok(()) diff --git a/src/utils.rs b/src/utils.rs index 15917f85..a04b8e9b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -112,3 +112,34 @@ pub fn write_png_rgba8( let mut writer = encoder.write_header()?; writer.write_image_data(pixels) } + +#[cfg(feature = "dbus")] +pub fn show_screenshot_notification(image_path: Option) { + let mut notification = notify_rust::Notification::new(); + notification + .summary("Screenshot captured") + .body("You can paste the image from the clipboard.") + .urgency(notify_rust::Urgency::Normal) + .hint(notify_rust::Hint::Transient(true)); + + // Try to add the screenshot as an image if possible. + if let Some(path) = image_path { + match path.canonicalize() { + Ok(path) => match url::Url::from_file_path(path) { + Ok(url) => { + notification.image_path(url.as_str()); + } + Err(err) => { + warn!("error converting screenshot path to file url: {err:?}"); + } + }, + Err(err) => { + warn!("error canonicalizing screenshot path: {err:?}"); + } + } + } + + if let Err(err) = notification.show() { + warn!("error showing screenshot notification: {err:?}"); + } +} -- cgit