aboutsummaryrefslogtreecommitdiff
path: root/src/ipc
diff options
context:
space:
mode:
authorrustysec <russ@infocyte.com>2024-05-22 16:16:03 -0700
committerIvan Molodetskikh <yalterz@gmail.com>2024-05-26 21:29:22 +0400
commitae7fb4c4f405aa0ff49930040d414581a812d938 (patch)
treeed87cf6c57a3332f4077fae0dd49a0d0d2f97662 /src/ipc
parent4746a0da7dffde6befcb3c80609fa3d31bffc29c (diff)
downloadniri-ae7fb4c4f405aa0ff49930040d414581a812d938.tar.gz
niri-ae7fb4c4f405aa0ff49930040d414581a812d938.tar.bz2
niri-ae7fb4c4f405aa0ff49930040d414581a812d938.zip
Add niri msg focused-output
Diffstat (limited to 'src/ipc')
-rw-r--r--src/ipc/client.rs203
-rw-r--r--src/ipc/server.rs25
2 files changed, 138 insertions, 90 deletions
diff --git a/src/ipc/client.rs b/src/ipc/client.rs
index f97cc80a..3192925f 100644
--- a/src/ipc/client.rs
+++ b/src/ipc/client.rs
@@ -12,6 +12,7 @@ pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> {
Msg::Version => Request::Version,
Msg::Outputs => Request::Outputs,
Msg::FocusedWindow => Request::FocusedWindow,
+ Msg::FocusedOutput => Request::FocusedOutput,
Msg::Action { action } => Request::Action(action.clone()),
Msg::Output { output, action } => Request::Output {
output: output.clone(),
@@ -117,96 +118,7 @@ pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> {
outputs.sort_unstable_by(|a, b| a.0.cmp(&b.0));
for (connector, output) in outputs.into_iter() {
- let Output {
- name,
- make,
- model,
- physical_size,
- modes,
- current_mode,
- vrr_supported,
- vrr_enabled,
- logical,
- } = output;
-
- println!(r#"Output "{connector}" ({make} - {model} - {name})"#);
-
- if let Some(current) = current_mode {
- let mode = *modes
- .get(current)
- .context("invalid response: current mode does not exist")?;
- let Mode {
- width,
- height,
- refresh_rate,
- is_preferred,
- } = mode;
- let refresh = refresh_rate as f64 / 1000.;
- let preferred = if is_preferred { " (preferred)" } else { "" };
- println!(" Current mode: {width}x{height} @ {refresh:.3} Hz{preferred}");
- } else {
- println!(" Disabled");
- }
-
- if vrr_supported {
- let enabled = if vrr_enabled { "enabled" } else { "disabled" };
- println!(" Variable refresh rate: supported, {enabled}");
- } else {
- println!(" Variable refresh rate: not supported");
- }
-
- if let Some((width, height)) = physical_size {
- println!(" Physical size: {width}x{height} mm");
- } else {
- println!(" Physical size: unknown");
- }
-
- if let Some(logical) = logical {
- let LogicalOutput {
- x,
- y,
- width,
- height,
- scale,
- transform,
- } = logical;
- println!(" Logical position: {x}, {y}");
- println!(" Logical size: {width}x{height}");
- println!(" Scale: {scale}");
-
- let transform = match transform {
- Transform::Normal => "normal",
- Transform::_90 => "90° counter-clockwise",
- Transform::_180 => "180°",
- Transform::_270 => "270° counter-clockwise",
- Transform::Flipped => "flipped horizontally",
- Transform::Flipped90 => "90° counter-clockwise, flipped horizontally",
- Transform::Flipped180 => "flipped vertically",
- Transform::Flipped270 => "270° counter-clockwise, flipped horizontally",
- };
- println!(" Transform: {transform}");
- }
-
- println!(" Available modes:");
- for (idx, mode) in modes.into_iter().enumerate() {
- let Mode {
- width,
- height,
- refresh_rate,
- is_preferred,
- } = mode;
- let refresh = refresh_rate as f64 / 1000.;
-
- let is_current = Some(idx) == current_mode;
- let qualifier = match (is_current, is_preferred) {
- (true, true) => " (current, preferred)",
- (true, false) => " (current)",
- (false, true) => " (preferred)",
- (false, false) => "",
- };
-
- println!(" {width}x{height}@{refresh:.3}{qualifier}");
- }
+ print_output(connector, output)?;
println!();
}
}
@@ -239,6 +151,23 @@ pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> {
println!("No window is focused.");
}
}
+ Msg::FocusedOutput => {
+ let Response::FocusedOutput(output) = response else {
+ bail!("unexpected response: expected FocusedOutput, got {response:?}");
+ };
+
+ if json {
+ let output = serde_json::to_string(&output).context("error formatting response")?;
+ println!("{output}");
+ return Ok(());
+ }
+
+ if let Some(output) = output {
+ print_output(output.name.clone(), output)?;
+ } else {
+ println!("No output is focused.");
+ }
+ }
Msg::Action { .. } => {
let Response::Handled = response else {
bail!("unexpected response: expected Handled, got {response:?}");
@@ -313,3 +242,97 @@ pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> {
Ok(())
}
+
+fn print_output(connector: String, output: Output) -> anyhow::Result<()> {
+ let Output {
+ name,
+ make,
+ model,
+ physical_size,
+ modes,
+ current_mode,
+ vrr_supported,
+ vrr_enabled,
+ logical,
+ } = output;
+
+ println!(r#"Output "{connector}" ({make} - {model} - {name})"#);
+
+ if let Some(current) = current_mode {
+ let mode = *modes
+ .get(current)
+ .context("invalid response: current mode does not exist")?;
+ let Mode {
+ width,
+ height,
+ refresh_rate,
+ is_preferred,
+ } = mode;
+ let refresh = refresh_rate as f64 / 1000.;
+ let preferred = if is_preferred { " (preferred)" } else { "" };
+ println!(" Current mode: {width}x{height} @ {refresh:.3} Hz{preferred}");
+ } else {
+ println!(" Disabled");
+ }
+
+ if vrr_supported {
+ let enabled = if vrr_enabled { "enabled" } else { "disabled" };
+ println!(" Variable refresh rate: supported, {enabled}");
+ } else {
+ println!(" Variable refresh rate: not supported");
+ }
+
+ if let Some((width, height)) = physical_size {
+ println!(" Physical size: {width}x{height} mm");
+ } else {
+ println!(" Physical size: unknown");
+ }
+
+ if let Some(logical) = logical {
+ let LogicalOutput {
+ x,
+ y,
+ width,
+ height,
+ scale,
+ transform,
+ } = logical;
+ println!(" Logical position: {x}, {y}");
+ println!(" Logical size: {width}x{height}");
+ println!(" Scale: {scale}");
+
+ let transform = match transform {
+ Transform::Normal => "normal",
+ Transform::_90 => "90° counter-clockwise",
+ Transform::_180 => "180°",
+ Transform::_270 => "270° counter-clockwise",
+ Transform::Flipped => "flipped horizontally",
+ Transform::Flipped90 => "90° counter-clockwise, flipped horizontally",
+ Transform::Flipped180 => "flipped vertically",
+ Transform::Flipped270 => "270° counter-clockwise, flipped horizontally",
+ };
+ println!(" Transform: {transform}");
+ }
+
+ println!(" Available modes:");
+ for (idx, mode) in modes.into_iter().enumerate() {
+ let Mode {
+ width,
+ height,
+ refresh_rate,
+ is_preferred,
+ } = mode;
+ let refresh = refresh_rate as f64 / 1000.;
+
+ let is_current = Some(idx) == current_mode;
+ let qualifier = match (is_current, is_preferred) {
+ (true, true) => " (current, preferred)",
+ (true, false) => " (current)",
+ (false, true) => " (preferred)",
+ (false, false) => "",
+ };
+
+ println!(" {width}x{height}@{refresh:.3}{qualifier}");
+ }
+ Ok(())
+}
diff --git a/src/ipc/server.rs b/src/ipc/server.rs
index 26958a7f..7987ca5c 100644
--- a/src/ipc/server.rs
+++ b/src/ipc/server.rs
@@ -208,6 +208,31 @@ async fn process(ctx: &ClientCtx, request: Request) -> Reply {
let workspaces = result.map_err(|_| String::from("error getting workspace info"))?;
Response::Workspaces(workspaces)
}
+ Request::FocusedOutput => {
+ let (tx, rx) = async_channel::bounded(1);
+ ctx.event_loop.insert_idle(move |state| {
+ let active_output = state
+ .niri
+ .layout
+ .active_output()
+ .map(|output| output.name());
+
+ let output = active_output.and_then(|active_output| {
+ state
+ .backend
+ .ipc_outputs()
+ .lock()
+ .unwrap()
+ .get(&active_output)
+ .cloned()
+ });
+
+ let _ = tx.send_blocking(output);
+ });
+ let result = rx.recv().await;
+ let output = result.map_err(|_| String::from("error getting active output info"))?;
+ Response::FocusedOutput(output)
+ }
};
Ok(response)