Initial commit

This commit is contained in:
2024-06-02 13:19:52 +02:00
commit 59758bfec5
4 changed files with 667 additions and 0 deletions

141
src/main.rs Normal file
View File

@ -0,0 +1,141 @@
use clap::{Parser, Subcommand};
use eyre::{bail, eyre};
use niri_ipc::WorkspaceReferenceArg;
use once_cell::sync::Lazy;
use serde::Serialize;
use std::collections::HashMap;
use std::env;
#[derive(Parser)]
struct Opt {
#[clap(subcommand)]
command: Command,
}
#[derive(Clone, Subcommand)]
enum Command {
/// Get the list of workspaces
Workspaces {},
KeyboardLayout {
/// Switch to the next keyboard layout
#[clap(long)]
next: bool,
},
SwitchWorkspace {
to: u8,
},
}
enum WindowManager {
Hyprland,
Niri,
Unknown,
}
static WM: Lazy<WindowManager> = Lazy::new(|| {
// SUPPORTED_COMPOSITORS="sway river Hyprland"
// if [ "${XDG_SESSION_TYPE:-""}" = "wayland" ] && \
// echo " $SUPPORTED_COMPOSITORS " | \
// grep -qi -e " ${XDG_CURRENT_DESKTOP:-""} " -e " ${XDG_SESSION_DESKTOP:-""} "
let session_type = env::var("XDG_SESSION_TYPE").ok();
if session_type.as_deref() != Some("wayland") {
return WindowManager::Unknown;
}
// TODO: might be relevant?
let _session_desktop = env::var("XDG_SESSION_DESKTOP").ok();
let current_desktop = env::var("XDG_CURRENT_DESKTOP").ok();
match current_desktop.as_deref() {
Some("niri") => WindowManager::Niri,
Some("Hyprland") => WindowManager::Hyprland,
_ => WindowManager::Unknown,
}
});
fn main() -> eyre::Result<()> {
let opt = Opt::parse();
color_eyre::install()?;
match &*WM {
WindowManager::Niri => handle_niri(opt.command)?,
WindowManager::Hyprland => handle_hyprland(opt.command)?,
_ => eyre::bail!("Window manager not supported"),
}
Ok(())
}
// Map<i32, Workspace>
#[derive(Serialize)]
struct Workspace {
monitor: i32,
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 {
panic!();
};
let workspaces = workspaces
.into_iter()
.map(|ws| {
(
ws.idx,
Workspace {
monitor: 0,
active: ws.is_active,
},
)
})
.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(())
}