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. /// For example, the config file couldn't be parsed.
failed: bool, 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 { 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}"); 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()); state.apply(event.clone());
server.send_event(event); 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(); .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. // Encode and save the image in a thread as it's slow.
thread::spawn(move || { thread::spawn(move || {
let mut buf = vec![]; let mut buf = vec![];
@@ -5685,11 +5696,16 @@ impl Niri {
} }
#[cfg(feature = "dbus")] #[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:?}"); 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(()) Ok(())
+1 -1
View File
@@ -461,7 +461,7 @@ pub fn baba_is_float_offset(now: Duration, view_height: f64) -> f64 {
} }
#[cfg(feature = "dbus")] #[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 std::collections::HashMap;
use zbus::zvariant; use zbus::zvariant;