use crate::{
core::{
bindings::KeyEventHandler,
client::Client,
data_types::RelativePosition,
helpers::{spawn, spawn_for_output},
layout::Layout,
manager::WindowManager,
ring::Selector,
workspace::Workspace,
xconnection::XConn,
},
Result,
};
pub fn create_or_switch_to_workspace<X: XConn>(
get_name: fn() -> Option<String>,
layouts: Vec<Layout>,
) -> KeyEventHandler<X> {
Box::new(move |wm: &mut WindowManager<X>| {
if let Some(s) = get_name() {
let name = &s;
let cond = |ws: &Workspace| ws.name() == name;
let sel = Selector::Condition(&cond);
if wm.workspace(&sel).is_none() {
wm.push_workspace(Workspace::new(name, layouts.clone()))?;
}
wm.focus_workspace(&sel)
} else {
Ok(())
}
})
}
pub fn focus_or_spawn<X: XConn>(
class: impl Into<String>,
command: impl Into<String>,
) -> KeyEventHandler<X> {
let (class, command) = (class.into(), command.into());
Box::new(move |wm: &mut WindowManager<X>| {
let cond = |c: &Client| c.class() == class;
if let Some(client) = wm.client(&Selector::Condition(&cond)) {
let workspace = client.workspace();
wm.focus_workspace(&Selector::Index(workspace))
} else {
spawn(&command)
}
})
}
pub fn update_monitors_via_xrandr(
primary: &str,
secondary: &str,
position: RelativePosition,
) -> Result<()> {
let raw = spawn_for_output("xrandr")?;
let secondary_line = raw
.lines()
.find(|line| line.starts_with(secondary))
.ok_or_else(|| perror!("unable to find secondary monitor in xrandr output"))?;
let status = secondary_line
.split(' ')
.nth(1)
.ok_or_else(|| perror!("unexpected xrandr output"))?;
let position_flag = match position {
RelativePosition::Left => "--left-of",
RelativePosition::Right => "--right-of",
RelativePosition::Above => "--above",
RelativePosition::Below => "--below",
};
spawn(format!("xrandr --output {} --primary --auto", primary))?;
match status {
"disconnected" => spawn(format!("xrandr --output {} --off", secondary)),
"connected" => spawn(format!(
"xrandr --output {} --auto {} {}",
secondary, position_flag, primary
)),
_ => Ok(()),
}
}