Initial commit
This commit is contained in:
141
src/main.rs
Normal file
141
src/main.rs
Normal 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(())
|
||||
}
|
||||
Reference in New Issue
Block a user