Skip to content

Instantly share code, notes, and snippets.

@diocletiann
Created August 20, 2022 15:08
Show Gist options
  • Save diocletiann/af57c17f8c657fde086bf20aac6141df to your computer and use it in GitHub Desktop.
Save diocletiann/af57c17f8c657fde086bf20aac6141df to your computer and use it in GitHub Desktop.
use compact_str::{CompactString, ToCompactString};
use tokio::task::JoinHandle;
use crate::yabai::{
send, send_async, CmdError, Display, Space, Window, STACKED_BORDER, UNFOCUSED_BORDER, UNSTACKED_BORDER,
};
#[derive(Default)]
pub struct Mover {
input_dir: CompactString,
// playing with crates
sw_id: u32,
sw_id_str: CompactString,
tw_id: u32,
uw_id: u32,
td_id: u8,
sw_is_stacked: bool,
sw_full_height: bool,
// tw_full_height: bool,
sw_is_top_row: bool,
similar_h: bool,
similar_w: bool,
}
// enum Direction {
// North(&'static str),
// South(&'static str),
// East(&'static str),
// West(&'static str),
// }
impl Mover {
pub fn move_setup(input_dir: &str, sw: &Window, tw: &Window, sd: &Display, td: &Display) -> Self {
// let m = Self {
Self {
input_dir: input_dir.to_compact_string(),
sw_id: sw.id,
sw_id_str: sw.id.to_compact_string(),
tw_id: tw.id,
uw_id: sw.id_below,
td_id: td.id,
sw_is_stacked: sw.stack_index > 0,
sw_full_height: (sd.frame.h - sw.frame.h) < 40_f32,
// tw_full_height: (td.frame.h - tw.frame.h) < 40_f32,
sw_is_top_row: (sw.frame.y - sd.frame.y) < 40_f32,
similar_h: (sw.frame.h - tw.frame.h).abs() < 20_f32, // TODO: find way to query notch height
similar_w: (sw.frame.w - tw.frame.w).abs() < 20_f32,
}
// m.move_window().await?;
// Ok(())
}
pub async fn move_window(&self) -> anyhow::Result<()> {
if !self.sw_is_stacked && self.sw_full_height && self.tw_id == 0 && self.td_id == 0 {
if self.input_dir == "east" || self.input_dir == "west" {
return Ok(());
} else if self.input_dir == "north" || self.input_dir == "south" {
self.rotate().await?;
return Ok(());
}
}
if !self.sw_is_stacked && self.sw_full_height && self.tw_id == 0 && self.td_id > 0 {
self.move_to_display().await?;
return Ok(());
}
if self.sw_is_stacked && self.tw_id == 0 {
self.unstack().await?;
return Ok(());
}
if self.similar_h && self.similar_w {
self.stack().await?;
return Ok(());
}
if self.sw_is_top_row {
if self.tw_id == 0 && self.td_id == 0 && (self.input_dir == "north" || self.input_dir == "south") {
return Ok(());
} else if self.tw_id == 0 {
self.insert_warp("south", &self.input_dir).await?;
return Ok(());
}
self.insert_warp(&self.input_dir, "north").await?;
return Ok(());
}
if self.tw_id == 0 && self.td_id == 0 && (self.input_dir == "north" || self.input_dir == "south") {
return Ok(());
}
if self.tw_id == 0 {
self.insert_warp("north", &self.input_dir).await?;
return Ok(());
}
self.insert_warp(&self.input_dir, "south").await?;
Ok(())
}
async fn rotate(&self) -> anyhow::Result<()> {
let s = Space::get_source().await?;
if self.sw_id == s.first_window {
self.insert_warp("east", &self.input_dir).await?;
} else if self.sw_id == s.last_window {
self.insert_warp("west", &self.input_dir).await?;
}
Ok(())
}
async fn stack(&self) -> anyhow::Result<()> {
let h1 = send_async(&["window", &self.input_dir, "--stack", &self.sw_id_str]).await?;
let h2 = send_async(&["window", "--focus", "stack.prev"]).await?;
let h3 = send_async(&["window", "--focus", "stack.next"]).await?;
let h4 = send_async(&[STACKED_BORDER]).await?;
h1.await.unwrap()?;
h2.await.unwrap()?;
h3.await.unwrap()?;
h4.await.unwrap()?;
Ok(())
}
async fn unstack(&self) -> anyhow::Result<()> {
let h1 = send_async(&["window", &self.sw_id_str, "--toggle", "float"]).await?;
let h2 = send_async(&["window", &self.uw_id.to_compact_string(), "--insert", &self.input_dir]).await?;
let h3 = send_async(&["window", &self.sw_id_str, "--toggle", "float"]).await?;
let h4 = send_async(&[UNSTACKED_BORDER]).await?;
h1.await.unwrap()?;
h2.await.unwrap()?;
h3.await.unwrap()?;
h4.await.unwrap()?;
Ok(())
}
async fn insert_warp(&self, target: &str, side: &str) -> anyhow::Result<()> {
let h = send_async(&["window", target, "--insert", side]).await?;
send(&["window", "--warp", target]).await?;
h.await.unwrap()?;
Ok(())
}
async fn move_to_display(&self) -> anyhow::Result<()> {
let spaces = Space::get_target_all(&self.input_dir).await?;
let mut h1: Option<JoinHandle<Result<(), CmdError>>> = None;
let mut h2: Option<JoinHandle<Result<(), CmdError>>> = None;
for s in spaces {
if s.is_visible {
send(&[UNFOCUSED_BORDER]).await?;
if s.first_window == 0 {
// move directly to empty space
h1 = Some(send_async(&["window", "--display", &self.input_dir]).await?);
send(&["window", "--focus", &self.sw_id_str]).await?;
} else {
// insert into nearest window
if self.input_dir == "east" {
h1 = Some(
send_async(&["window", &s.first_window.to_compact_string(), "--insert", "west"]).await?,
);
} else if self.input_dir == "west" {
h1 = Some(
send_async(&["window", &s.last_window.to_compact_string(), "--insert", "east"]).await?,
);
}
h2 = Some(send_async(&["window", "--display", &self.input_dir]).await?);
send(&["window", "--focus", &self.sw_id_str]).await?;
}
}
}
send(&[UNSTACKED_BORDER]).await?;
if let Some(h1) = h1 {
h1.await.unwrap()?;
}
if let Some(h2) = h2 {
h2.await.unwrap()?;
}
Ok(())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment