Workspaces on hyprland
This commit is contained in:
23
src/eww.rs
Normal file
23
src/eww.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
use eyre::{bail, Context};
|
||||||
|
|
||||||
|
/// Update eww bar variable
|
||||||
|
pub fn update_var(key: &str, value: &str) -> eyre::Result<()> {
|
||||||
|
println!("eww update {key}={value}");
|
||||||
|
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(())
|
||||||
|
}
|
||||||
@ -1,16 +1,31 @@
|
|||||||
use eyre::{bail, eyre};
|
use crate::{eww, output, Command};
|
||||||
|
use eyre::{bail, eyre, Context};
|
||||||
|
use serde::{de::DeserializeOwned, Deserialize};
|
||||||
|
use std::str;
|
||||||
|
|
||||||
use crate::Command;
|
#[derive(Deserialize)]
|
||||||
|
struct HyprWorkspace {
|
||||||
|
name: String,
|
||||||
|
|
||||||
|
#[serde(rename = "monitorID")]
|
||||||
|
monitor_id: u32,
|
||||||
|
//
|
||||||
|
// id, windows, monitor, hasfullscreen, lastwindow, lastwindowtitle
|
||||||
|
}
|
||||||
|
|
||||||
pub fn handle(command: Command) -> eyre::Result<()> {
|
pub fn handle(command: Command) -> eyre::Result<()> {
|
||||||
match command {
|
match command {
|
||||||
Command::Workspaces {} => {
|
Command::Workspaces {} => {
|
||||||
std::process::Command::new("eww-workspaces")
|
println!("{}", get_workspaces()?);
|
||||||
.status()
|
|
||||||
.map_err(|e| eyre!("unga bunga: {e}"))?;
|
|
||||||
}
|
}
|
||||||
Command::SwitchWorkspace { .. } => {
|
Command::SwitchWorkspace { to } => {
|
||||||
bail!("not supported on Hyprland");
|
std::process::Command::new("hyprctl")
|
||||||
|
.args(["dispatch", "workspace"])
|
||||||
|
.arg(format!("{to}"))
|
||||||
|
.status()
|
||||||
|
.map_err(|e| eyre!("hyprctl error: {e}"))?;
|
||||||
|
|
||||||
|
eww::update_var("workspaces", &get_workspaces()?)?;
|
||||||
}
|
}
|
||||||
Command::KeyboardLayout { .. } => {
|
Command::KeyboardLayout { .. } => {
|
||||||
bail!("not supported on Hyprland");
|
bail!("not supported on Hyprland");
|
||||||
@ -19,3 +34,42 @@ pub fn handle(command: Command) -> eyre::Result<()> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn hyprctl<T: DeserializeOwned>(args: &[&str]) -> eyre::Result<T> {
|
||||||
|
let workspaces_output = std::process::Command::new("hyprctl")
|
||||||
|
.args(args)
|
||||||
|
.arg("-j") // JSON output
|
||||||
|
.output()
|
||||||
|
.map_err(|e| eyre!("hyprctl error: {e}"))?;
|
||||||
|
|
||||||
|
let workspaces_stdout = str::from_utf8(&workspaces_output.stdout)?;
|
||||||
|
//let workspaces_stderr = str::from_utf8(&workspaces_output.stderr)?;
|
||||||
|
|
||||||
|
if !workspaces_output.status.success() {
|
||||||
|
bail!("hyprctl error, non-zero exit code");
|
||||||
|
}
|
||||||
|
|
||||||
|
serde_json::from_str(workspaces_stdout).wrap_err("Failed to deserialize output from hyprctl")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a JSON-string containing info about workspaces
|
||||||
|
fn get_workspaces() -> eyre::Result<String> {
|
||||||
|
let active_workspace: HyprWorkspace = hyprctl(&["activeworkspace"])?;
|
||||||
|
let workspaces: Vec<HyprWorkspace> = hyprctl(&["workspaces"])?;
|
||||||
|
|
||||||
|
let workspaces: output::Workspaces = workspaces
|
||||||
|
.into_iter()
|
||||||
|
.map(|workspace| {
|
||||||
|
let is_active = workspace.name == active_workspace.name;
|
||||||
|
(
|
||||||
|
workspace.name,
|
||||||
|
output::Workspace {
|
||||||
|
monitor: workspace.monitor_id,
|
||||||
|
active: is_active,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
serde_json::to_string(&workspaces).wrap_err("Failed to serialize workspaces")
|
||||||
|
}
|
||||||
|
|||||||
@ -3,8 +3,10 @@ use once_cell::sync::Lazy;
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
|
mod eww;
|
||||||
mod hyprland;
|
mod hyprland;
|
||||||
mod niri;
|
mod niri;
|
||||||
|
mod output;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
struct Opt {
|
struct Opt {
|
||||||
|
|||||||
25
src/niri.rs
25
src/niri.rs
@ -1,6 +1,6 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::{Command, Workspace};
|
use crate::{eww, Command, Workspace};
|
||||||
use eyre::{bail, eyre, Context};
|
use eyre::{bail, eyre, Context};
|
||||||
use niri_ipc::{Socket, WorkspaceReferenceArg};
|
use niri_ipc::{Socket, WorkspaceReferenceArg};
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ pub fn handle(command: Command) -> eyre::Result<()> {
|
|||||||
))?
|
))?
|
||||||
.map_err(|e| eyre!("niri error: {e}"))?;
|
.map_err(|e| eyre!("niri error: {e}"))?;
|
||||||
|
|
||||||
update_eww("workspaces", &get_workspaces()?)?;
|
eww::update_var("workspaces", &get_workspaces()?)?;
|
||||||
}
|
}
|
||||||
Command::KeyboardLayout { next: _ } => todo!(),
|
Command::KeyboardLayout { next: _ } => todo!(),
|
||||||
}
|
}
|
||||||
@ -32,27 +32,6 @@ fn open_socket() -> eyre::Result<Socket> {
|
|||||||
niri_ipc::Socket::connect().wrap_err("Failed to open niri 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
|
/// Get a JSON-string containing info about workspaces
|
||||||
fn get_workspaces() -> eyre::Result<String> {
|
fn get_workspaces() -> eyre::Result<String> {
|
||||||
let socket = open_socket()?;
|
let socket = open_socket()?;
|
||||||
|
|||||||
10
src/output.rs
Normal file
10
src/output.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
use serde::Serialize;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
pub type Workspaces = HashMap<String, Workspace>;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize)]
|
||||||
|
pub struct Workspace {
|
||||||
|
pub monitor: u32,
|
||||||
|
pub active: bool,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user