From 48e9418f6d0b2ccdc30bd68389c3ea6b218038e2 Mon Sep 17 00:00:00 2001 From: Joakim Hulthe Date: Sat, 20 Jul 2024 14:23:35 +0200 Subject: [PATCH] stuff --- src/hyprland.rs | 21 +++++++++++++ src/main.rs | 70 ++++--------------------------------------- src/niri.rs | 80 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 65 deletions(-) create mode 100644 src/hyprland.rs create mode 100644 src/niri.rs diff --git a/src/hyprland.rs b/src/hyprland.rs new file mode 100644 index 0000000..6fc1e0a --- /dev/null +++ b/src/hyprland.rs @@ -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(()) +} diff --git a/src/main.rs b/src/main.rs index b63af9c..c5df669 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,11 @@ 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; +mod hyprland; +mod niri; + #[derive(Parser)] struct Opt { #[clap(subcommand)] @@ -58,8 +58,8 @@ fn main() -> eyre::Result<()> { color_eyre::install()?; match &*WM { - WindowManager::Niri => handle_niri(opt.command)?, - WindowManager::Hyprland => handle_hyprland(opt.command)?, + WindowManager::Niri => niri::handle(opt.command)?, + WindowManager::Hyprland => hyprland::handle(opt.command)?, _ => eyre::bail!("Window manager not supported"), } @@ -71,63 +71,3 @@ 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 { - 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::>(); - - 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(()) -} diff --git a/src/niri.rs b/src/niri.rs new file mode 100644 index 0000000..a814673 --- /dev/null +++ b/src/niri.rs @@ -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 { + 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 { + 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::>(); + + Ok(serde_json::to_string(&workspaces)?) +}