This commit is contained in:
2024-07-20 14:23:35 +02:00
parent 125e996599
commit 48e9418f6d
3 changed files with 106 additions and 65 deletions

21
src/hyprland.rs Normal file
View File

@ -0,0 +1,21 @@
use eyre::{bail, eyre};
use crate::Command;
pub fn handle(command: Command) -> eyre::Result<()> {
match command {
Command::Workspaces {} => {
std::process::Command::new("eww-workspaces")
.status()
.map_err(|e| eyre!("unga bunga: {e}"))?;
}
Command::SwitchWorkspace { .. } => {
bail!("not supported on Hyprland");
}
Command::KeyboardLayout { .. } => {
bail!("not supported on Hyprland");
}
}
Ok(())
}

View File

@ -1,11 +1,11 @@
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use eyre::{bail, eyre};
use niri_ipc::WorkspaceReferenceArg;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use serde::Serialize; use serde::Serialize;
use std::collections::HashMap;
use std::env; use std::env;
mod hyprland;
mod niri;
#[derive(Parser)] #[derive(Parser)]
struct Opt { struct Opt {
#[clap(subcommand)] #[clap(subcommand)]
@ -58,8 +58,8 @@ fn main() -> eyre::Result<()> {
color_eyre::install()?; color_eyre::install()?;
match &*WM { match &*WM {
WindowManager::Niri => handle_niri(opt.command)?, WindowManager::Niri => niri::handle(opt.command)?,
WindowManager::Hyprland => handle_hyprland(opt.command)?, WindowManager::Hyprland => hyprland::handle(opt.command)?,
_ => eyre::bail!("Window manager not supported"), _ => eyre::bail!("Window manager not supported"),
} }
@ -71,63 +71,3 @@ struct Workspace {
monitor: i32, monitor: i32,
active: bool, active: bool,
} }
fn handle_niri(command: Command) -> eyre::Result<()> {
let socket = niri_ipc::Socket::connect()?;
match command {
Command::Workspaces {} => {
let reply = socket
.send(niri_ipc::Request::Workspaces)?
.map_err(|e| eyre!("niri error: {e}"))?;
let niri_ipc::Response::Workspaces(workspaces) = reply else {
bail!("Wrong response from niri: {reply:?}");
};
let workspaces = workspaces
.into_iter()
.map(|ws| {
let workspace = Workspace {
monitor: 0,
active: ws.is_active,
};
(ws.idx, workspace)
})
.collect::<HashMap<_, _>>();
println!("{}", serde_json::to_string(&workspaces)?);
}
Command::SwitchWorkspace { to } => {
let _reply = socket
.send(niri_ipc::Request::Action(
niri_ipc::Action::FocusWorkspace {
reference: WorkspaceReferenceArg::Index(to),
},
))?
.map_err(|e| eyre!("niri error: {e}"))?;
}
Command::KeyboardLayout { next: _ } => todo!(),
}
Ok(())
}
fn handle_hyprland(command: Command) -> eyre::Result<()> {
match command {
Command::Workspaces {} => {
std::process::Command::new("eww-workspaces")
.status()
.map_err(|e| eyre!("unga bunga: {e}"))?;
}
Command::SwitchWorkspace { .. } => {
bail!("not supported on Hyprland");
}
Command::KeyboardLayout { .. } => {
bail!("not supported on Hyprland");
}
}
Ok(())
}

80
src/niri.rs Normal file
View File

@ -0,0 +1,80 @@
use std::collections::HashMap;
use crate::{Command, Workspace};
use eyre::{bail, eyre, Context};
use niri_ipc::{Socket, WorkspaceReferenceArg};
pub fn handle(command: Command) -> eyre::Result<()> {
match command {
Command::Workspaces {} => {
println!("{}", get_workspaces()?);
}
Command::SwitchWorkspace { to } => {
let _reply = open_socket()?
.send(niri_ipc::Request::Action(
niri_ipc::Action::FocusWorkspace {
reference: WorkspaceReferenceArg::Index(to),
},
))?
.map_err(|e| eyre!("niri error: {e}"))?;
update_eww("workspaces", &get_workspaces()?)?;
}
Command::KeyboardLayout { next: _ } => todo!(),
}
Ok(())
}
/// Open a socket to niri
fn open_socket() -> eyre::Result<Socket> {
niri_ipc::Socket::connect().wrap_err("Failed to open niri socket")
}
/// Update eww bar variable
fn update_eww(key: &str, value: &str) -> eyre::Result<()> {
let output = std::process::Command::new("eww")
.arg("update")
.arg(format!("{key}={value}"))
.output()
.wrap_err("failed to execute 'eww update'")?;
if !output.status.success() {
let stdout = std::str::from_utf8(&output.stdout).unwrap_or("Invalid UTF-8");
let stderr = std::str::from_utf8(&output.stderr).unwrap_or("Invalid UTF-8");
eprintln!("'eww update' stdout: {stdout}");
eprintln!("'eww update' stderr: {stderr}");
bail!("'eww update' failed. See logs.");
}
Ok(())
}
/// Get a JSON-string containing info about workspaces
fn get_workspaces() -> eyre::Result<String> {
let socket = open_socket()?;
let reply = socket
.send(niri_ipc::Request::Workspaces)?
.map_err(|e| eyre!("niri error: {e}"))?;
let niri_ipc::Response::Workspaces(workspaces) = reply else {
bail!("Wrong response from niri: {reply:?}");
};
let workspaces = workspaces
.into_iter()
.map(|ws| {
let workspace = Workspace {
monitor: 0,
active: ws.is_active,
};
(ws.idx, workspace)
})
.collect::<HashMap<_, _>>();
Ok(serde_json::to_string(&workspaces)?)
}