feat: event-stream event for when a screenshot is taken (#2565)

* feat: event-stream event for when a screenshot is taken

* ScreenshotTaken --> ScreenshotCaptured

* review comments

* fix: screenshot completion event path serializatation

* fixes

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
This commit is contained in:
Kainoa Kanter
2025-10-25 23:33:49 -07:00
committed by GitHub
parent 4310c20c32
commit e6f3c538da
5 changed files with 48 additions and 4 deletions
+8
View File
@@ -1483,6 +1483,14 @@ pub enum Event {
/// For example, the config file couldn't be parsed.
failed: bool,
},
/// A screenshot was captured.
ScreenshotCaptured {
/// The file path where the screenshot was saved, if it was written to disk.
///
/// If `None`, the screenshot was either only copied to the clipboard, or the path couldn't
/// be converted to a `String` (e.g. contained invalid UTF-8 bytes).
path: Option<String>,
},
}
impl FromStr for WorkspaceReferenceArg {
+9
View File
@@ -481,6 +481,15 @@ pub fn handle_msg(mut msg: Msg, json: bool) -> anyhow::Result<()> {
};
println!("Config loaded {status}");
}
Event::ScreenshotCaptured { path } => {
let mut parts = vec![];
parts.push("copied to clipboard".to_string());
if let Some(path) = &path {
parts.push(format!("saved to {path}"));
}
let description = parts.join(" and ");
println!("Screenshot captured: {description}");
}
}
}
}
+11
View File
@@ -792,4 +792,15 @@ impl State {
state.apply(event.clone());
server.send_event(event);
}
pub fn ipc_screenshot_taken(&mut self, path: Option<String>) {
let Some(server) = &self.niri.ipc_server else {
return;
};
let mut state = server.event_stream_state.borrow_mut();
let event = Event::ScreenshotCaptured { path };
state.apply(event.clone());
server.send_event(event);
}
}
+19 -3
View File
@@ -5643,6 +5643,17 @@ impl Niri {
})
.unwrap();
// Prepare to send screenshot completion event back to main thread.
let (event_tx, event_rx) = calloop::channel::sync_channel::<Option<String>>(1);
self.event_loop
.insert_source(event_rx, move |event, _, state| match event {
calloop::channel::Event::Msg(path) => {
state.ipc_screenshot_taken(path);
}
calloop::channel::Event::Closed => (),
})
.unwrap();
// Encode and save the image in a thread as it's slow.
thread::spawn(move || {
let mut buf = vec![];
@@ -5685,11 +5696,16 @@ impl Niri {
}
#[cfg(feature = "dbus")]
if let Err(err) = crate::utils::show_screenshot_notification(image_path) {
if let Err(err) = crate::utils::show_screenshot_notification(image_path.as_deref()) {
warn!("error showing screenshot notification: {err:?}");
}
#[cfg(not(feature = "dbus"))]
drop(image_path);
// Send screenshot completion event.
let path_string = image_path
.as_ref()
.and_then(|p| p.to_str())
.map(|s| s.to_owned());
let _ = event_tx.send(path_string);
});
Ok(())
+1 -1
View File
@@ -461,7 +461,7 @@ pub fn baba_is_float_offset(now: Duration, view_height: f64) -> f64 {
}
#[cfg(feature = "dbus")]
pub fn show_screenshot_notification(image_path: Option<PathBuf>) -> anyhow::Result<()> {
pub fn show_screenshot_notification(image_path: Option<&Path>) -> anyhow::Result<()> {
use std::collections::HashMap;
use zbus::zvariant;