aboutsummaryrefslogtreecommitdiff
path: root/src/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipc')
-rw-r--r--src/ipc/client.rs35
-rw-r--r--src/ipc/server.rs25
2 files changed, 53 insertions, 7 deletions
diff --git a/src/ipc/client.rs b/src/ipc/client.rs
index 094bb636..4c356355 100644
--- a/src/ipc/client.rs
+++ b/src/ipc/client.rs
@@ -1,20 +1,34 @@
use std::io::ErrorKind;
use std::iter::Peekable;
-use std::slice;
+use std::path::Path;
+use std::{env, slice};
use anyhow::{anyhow, bail, Context};
use niri_config::OutputName;
use niri_ipc::socket::Socket;
use niri_ipc::{
- Event, KeyboardLayouts, LogicalOutput, Mode, Output, OutputConfigChanged, Overview, Request,
- Response, Transform, Window, WindowLayout,
+ Action, Event, KeyboardLayouts, LogicalOutput, Mode, Output, OutputConfigChanged, Overview,
+ Request, Response, Transform, Window, WindowLayout,
};
use serde_json::json;
use crate::cli::Msg;
use crate::utils::version;
-pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> {
+pub fn handle_msg(mut msg: Msg, json: bool) -> anyhow::Result<()> {
+ // For actions taking paths, prepend the niri CLI's working directory.
+ if let Msg::Action {
+ action:
+ Action::Screenshot { path, .. }
+ | Action::ScreenshotScreen { path, .. }
+ | Action::ScreenshotWindow { path, .. },
+ } = &mut msg
+ {
+ if let Some(path) = path {
+ ensure_absolute_path(path).context("error making the path absolute")?;
+ }
+ }
+
let request = match &msg {
Msg::Version => Request::Version,
Msg::Outputs => Request::Outputs,
@@ -668,6 +682,19 @@ fn fmt_rounded(x: f64) -> String {
}
}
+fn ensure_absolute_path(path: &mut String) -> anyhow::Result<()> {
+ let p = Path::new(path);
+ if p.is_relative() {
+ let mut cwd = env::current_dir().context("error getting current working directory")?;
+ cwd.push(p);
+ match cwd.into_os_string().into_string() {
+ Ok(absolute) => *path = absolute,
+ Err(cwd) => bail!("couldn't convert absolute path to string: {cwd:?}"),
+ }
+ }
+ Ok(())
+}
+
#[cfg(test)]
mod tests {
use insta::assert_snapshot;
diff --git a/src/ipc/server.rs b/src/ipc/server.rs
index 051bccab..354023b7 100644
--- a/src/ipc/server.rs
+++ b/src/ipc/server.rs
@@ -2,7 +2,7 @@ use std::cell::RefCell;
use std::collections::HashSet;
use std::ffi::OsStr;
use std::os::unix::net::{UnixListener, UnixStream};
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use std::{env, io, process};
@@ -17,8 +17,8 @@ use futures_util::{select_biased, AsyncBufReadExt, AsyncWrite, AsyncWriteExt, Fu
use niri_config::OutputName;
use niri_ipc::state::{EventStreamState, EventStreamStatePart as _};
use niri_ipc::{
- Event, KeyboardLayouts, OutputConfigChanged, Overview, Reply, Request, Response, WindowLayout,
- Workspace,
+ Action, Event, KeyboardLayouts, OutputConfigChanged, Overview, Reply, Request, Response,
+ WindowLayout, Workspace,
};
use smithay::desktop::layer_map_for_output;
use smithay::input::pointer::{
@@ -379,6 +379,8 @@ async fn process(ctx: &ClientCtx, request: Request) -> Reply {
Response::PickedColor(color)
}
Request::Action(action) => {
+ validate_action(&action)?;
+
let (tx, rx) = async_channel::bounded(1);
let action = niri_config::Action::from(action);
@@ -451,6 +453,23 @@ async fn process(ctx: &ClientCtx, request: Request) -> Reply {
Ok(response)
}
+fn validate_action(action: &Action) -> Result<(), String> {
+ if let Action::Screenshot { path, .. }
+ | Action::ScreenshotScreen { path, .. }
+ | Action::ScreenshotWindow { path, .. } = action
+ {
+ if let Some(path) = path {
+ // Relative paths are resolved against the niri compositor's working directory, which
+ // is almost certainly not what you want.
+ if !Path::new(path).is_absolute() {
+ return Err(format!("path must be absolute: {path}"));
+ }
+ }
+ }
+
+ Ok(())
+}
+
async fn handle_event_stream_client(client: EventStreamClient) -> anyhow::Result<()> {
let EventStreamClient {
events,