Rework everything to have a global SwaySome object with methods in it

This allows easily keeping state across the various function calls.
This commit is contained in:
Skia 2023-11-14 09:44:33 +01:00
parent 99a99648b1
commit 90ec4a2566

View file

@ -5,6 +5,7 @@ extern crate serde_json;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use clap::{Args, Parser, Subcommand}; use clap::{Args, Parser, Subcommand};
use std::cell::Cell;
use std::env; use std::env;
use std::io::Cursor; use std::io::Cursor;
use std::io::{Read, Write}; use std::io::{Read, Write};
@ -78,6 +79,42 @@ struct Index {
index: usize, index: usize,
} }
struct SwaySome {
socket: Cell<Option<UnixStream>>,
outputs: Vec<Output>,
// current_output: Output,
workspaces: Vec<Workspace>,
// current_workspace: Workspace,
}
#[derive(Serialize, Deserialize, Debug)]
struct Output {
name: String,
#[serde(default)]
focused: bool,
#[serde(default)]
active: bool,
}
#[derive(Serialize, Deserialize, Debug)]
struct Workspace {
num: usize,
output: String,
visible: bool,
}
impl SwaySome {
fn new() -> SwaySome {
let mut swaysome = SwaySome {
socket: Cell::new(Some(SwaySome::get_stream())),
outputs: vec![],
workspaces: vec![],
};
swaysome.outputs = swaysome.get_outputs();
swaysome.workspaces = swaysome.get_workspaces();
swaysome
}
fn get_stream() -> UnixStream { fn get_stream() -> UnixStream {
for socket_var in ["SWAYSOCK", "I3SOCK"] { for socket_var in ["SWAYSOCK", "I3SOCK"] {
let socket_path = match env::var(socket_var) { let socket_path = match env::var(socket_var) {
@ -110,7 +147,7 @@ fn get_stream() -> UnixStream {
panic!("couldn't find any i3/sway socket") panic!("couldn't find any i3/sway socket")
} }
fn send_msg(mut stream: &UnixStream, msg_type: u32, payload: &str) { fn send_msg(&self, msg_type: u32, payload: &str) {
let payload_length = payload.len() as u32; let payload_length = payload.len() as u32;
let mut msg_prefix: [u8; 6 * mem::size_of::<u8>() + 2 * mem::size_of::<u32>()] = let mut msg_prefix: [u8; 6 * mem::size_of::<u8>() + 2 * mem::size_of::<u32>()] =
@ -129,20 +166,30 @@ fn send_msg(mut stream: &UnixStream, msg_type: u32, payload: &str) {
let mut msg: Vec<u8> = msg_prefix[..].to_vec(); let mut msg: Vec<u8> = msg_prefix[..].to_vec();
msg.extend(payload.as_bytes()); msg.extend(payload.as_bytes());
if stream.write_all(&msg[..]).is_err() { let mut socket = self
.socket
.take()
.expect("Unexisting socket, there probably is a logic error");
if socket.write_all(&msg[..]).is_err() {
panic!("couldn't send message"); panic!("couldn't send message");
} }
self.socket.set(Some(socket));
} }
fn send_command(stream: &UnixStream, command: &str) { fn send_command(&self, command: &str) {
eprint!("Sending command: '{}' - ", &command); eprint!("Sending command: '{}' - ", &command);
send_msg(stream, RUN_COMMAND, command); self.send_msg(RUN_COMMAND, command);
check_success(stream); self.check_success();
} }
fn read_msg(mut stream: &UnixStream) -> Result<String, &str> { fn read_msg(&self) -> Result<String, &str> {
let mut response_header: [u8; 14] = *b"uninitialized."; let mut response_header: [u8; 14] = *b"uninitialized.";
stream.read_exact(&mut response_header).unwrap(); let mut socket = self
.socket
.take()
.expect("Unexisting socket, there probably is a logic error");
socket.read_exact(&mut response_header).unwrap();
if &response_header[0..6] == b"i3-ipc" { if &response_header[0..6] == b"i3-ipc" {
let mut v = Cursor::new(vec![ let mut v = Cursor::new(vec![
@ -154,20 +201,22 @@ fn read_msg(mut stream: &UnixStream) -> Result<String, &str> {
let payload_length = v.read_u32::<LittleEndian>().unwrap(); let payload_length = v.read_u32::<LittleEndian>().unwrap();
let mut payload = vec![0; payload_length as usize]; let mut payload = vec![0; payload_length as usize];
stream.read_exact(&mut payload[..]).unwrap(); socket.read_exact(&mut payload[..]).unwrap();
let payload_str = String::from_utf8(payload).unwrap(); let payload_str = String::from_utf8(payload).unwrap();
self.socket.set(Some(socket));
Ok(payload_str) Ok(payload_str)
} else { } else {
eprint!("Not an i3-icp packet, emptying the buffer: "); eprint!("Not an i3-icp packet, emptying the buffer: ");
let mut v = vec![]; let mut v = vec![];
stream.read_to_end(&mut v).unwrap(); socket.read_to_end(&mut v).unwrap();
eprintln!("{:?}", v); eprintln!("{:?}", v);
self.socket.set(Some(socket));
Err("Unable to read i3-ipc packet") Err("Unable to read i3-ipc packet")
} }
} }
fn check_success(stream: &UnixStream) { fn check_success(&self) {
match read_msg(stream) { match self.read_msg() {
Ok(msg) => { Ok(msg) => {
let r: Vec<serde_json::Value> = serde_json::from_str(&msg).unwrap(); let r: Vec<serde_json::Value> = serde_json::from_str(&msg).unwrap();
match r[0]["success"] { match r[0]["success"] {
@ -179,18 +228,9 @@ fn check_success(stream: &UnixStream) {
}; };
} }
#[derive(Serialize, Deserialize, Debug)] fn get_outputs(&self) -> Vec<Output> {
struct Output { self.send_msg(GET_OUTPUTS, "");
name: String, let o = match self.read_msg() {
#[serde(default)]
focused: bool,
#[serde(default)]
active: bool,
}
fn get_outputs(stream: &UnixStream) -> Vec<Output> {
send_msg(stream, GET_OUTPUTS, "");
let o = match read_msg(stream) {
Ok(msg) => msg, Ok(msg) => msg,
Err(_) => panic!("Unable to get outputs"), Err(_) => panic!("Unable to get outputs"),
}; };
@ -203,16 +243,9 @@ fn get_outputs(stream: &UnixStream) -> Vec<Output> {
outputs outputs
} }
#[derive(Serialize, Deserialize, Debug)] fn get_workspaces(&self) -> Vec<Workspace> {
struct Workspace { self.send_msg(GET_WORKSPACES, "");
num: usize, let ws = match self.read_msg() {
output: String,
visible: bool,
}
fn get_workspaces(stream: &UnixStream) -> Vec<Workspace> {
send_msg(stream, GET_WORKSPACES, "");
let ws = match read_msg(stream) {
Ok(msg) => msg, Ok(msg) => msg,
Err(_) => panic!("Unable to get current workspace"), Err(_) => panic!("Unable to get current workspace"),
}; };
@ -221,19 +254,15 @@ fn get_workspaces(stream: &UnixStream) -> Vec<Workspace> {
workspaces workspaces
} }
fn get_current_output_index(stream: &UnixStream) -> usize { fn get_current_output_index(&self) -> usize {
let outputs = get_outputs(stream); match self.outputs.iter().position(|x| x.focused) {
match outputs.iter().position(|x| x.focused) {
Some(i) => i, Some(i) => i,
None => panic!("WTF! No focused output???"), None => panic!("WTF! No focused output???"),
} }
} }
fn get_current_output_name(stream: &UnixStream) -> String { fn get_current_output_name(&self) -> String {
let outputs = get_outputs(stream); let focused_output_index = match self.outputs.iter().find(|x| x.focused) {
let focused_output_index = match outputs.iter().find(|x| x.focused) {
Some(i) => i.name.as_str(), Some(i) => i.name.as_str(),
None => panic!("WTF! No focused output???"), None => panic!("WTF! No focused output???"),
}; };
@ -241,57 +270,62 @@ fn get_current_output_name(stream: &UnixStream) -> String {
focused_output_index.to_string() focused_output_index.to_string()
} }
fn get_current_workspace(stream: &UnixStream) -> Workspace { fn get_current_workspace_index(&self) -> usize {
let outputs = get_outputs(stream); self.workspaces
let workspaces = get_workspaces(stream); .iter()
workspaces .find(|w| {
.into_iter() w.visible
.find(|w| w.visible && outputs.iter().find(|o| o.name == w.output).unwrap().focused) && self
.outputs
.iter()
.find(|o| o.name == w.output)
.unwrap() .unwrap()
.focused
})
.unwrap()
.num
} }
fn move_container_to_workspace(stream: &UnixStream, workspace_index: usize) { fn move_container_to_workspace(&self, workspace_index: usize) {
if workspace_index < MAX_GROUP_WS { if workspace_index < MAX_GROUP_WS {
move_container_to_workspace_relative(stream, workspace_index); self.move_container_to_workspace_relative(workspace_index);
} else { } else {
move_container_to_workspace_absolute(stream, workspace_index); self.move_container_to_workspace_absolute(workspace_index);
} }
} }
fn move_container_to_workspace_group(stream: &UnixStream, target_group: usize) { fn move_container_to_workspace_group(&self, target_group: usize) {
let current_workspace_index = get_current_workspace(stream).num; let current_workspace_index = self.get_current_workspace_index();
let current_workspace_index_relative = (current_workspace_index % MAX_GROUP_WS) as usize; let current_workspace_index_relative = (current_workspace_index % MAX_GROUP_WS) as usize;
move_container_to_workspace_absolute( self.move_container_to_workspace_absolute(
stream,
current_workspace_index_relative + target_group * MAX_GROUP_WS, current_workspace_index_relative + target_group * MAX_GROUP_WS,
); );
} }
fn move_container_to_workspace_absolute(stream: &UnixStream, workspace_index: usize) { fn move_container_to_workspace_absolute(&self, workspace_index: usize) {
let group_index = (workspace_index / MAX_GROUP_WS) as usize; let group_index = (workspace_index / MAX_GROUP_WS) as usize;
let outputs = get_outputs(stream);
let workspaces = get_workspaces(stream);
let full_ws_name = format!( let full_ws_name = format!(
"{}", "{}",
group_index * MAX_GROUP_WS + workspace_index % MAX_GROUP_WS group_index * MAX_GROUP_WS + workspace_index % MAX_GROUP_WS
); );
// If the workspace already exists // If the workspace already exists
match workspaces.iter().find(|w| w.num == workspace_index) { match self.workspaces.iter().find(|w| w.num == workspace_index) {
Some(_) => { Some(_) => {
let mut focus_cmd: String = "move container to workspace number ".to_string(); let mut focus_cmd: String = "move container to workspace number ".to_string();
focus_cmd.push_str(&full_ws_name); focus_cmd.push_str(&full_ws_name);
send_command(stream, &focus_cmd); self.send_command(&focus_cmd);
} }
None => { None => {
let target_group = workspace_index / MAX_GROUP_WS; let target_group = workspace_index / MAX_GROUP_WS;
let target_screen_index = match workspaces let target_screen_index = match self
.workspaces
.iter() .iter()
.find(|w| w.num / MAX_GROUP_WS == target_group) .find(|w| w.num / MAX_GROUP_WS == target_group)
{ {
// If other workspaces on the same group exists // If other workspaces on the same group exists
Some(other_workspace) => Some( Some(other_workspace) => Some(
outputs self.outputs
.iter() .iter()
.enumerate() .enumerate()
.find(|i| i.1.name == other_workspace.output) .find(|i| i.1.name == other_workspace.output)
@ -300,7 +334,7 @@ fn move_container_to_workspace_absolute(stream: &UnixStream, workspace_index: us
), ),
None => { None => {
// Or if the targeted output is currently connected // Or if the targeted output is currently connected
if group_index < outputs.len() { if group_index < self.outputs.len() {
Some(group_index) Some(group_index)
} else { } else {
None None
@ -310,97 +344,96 @@ fn move_container_to_workspace_absolute(stream: &UnixStream, workspace_index: us
match target_screen_index { match target_screen_index {
Some(target_screen_index) => { Some(target_screen_index) => {
let target_output = &outputs[target_screen_index]; let target_output = &self.outputs[target_screen_index];
let current_output_name = get_current_output_name(stream); let current_output_name = self.get_current_output_name();
if target_output.name == current_output_name { if target_output.name == current_output_name {
let mut focus_cmd: String = "move container to workspace ".to_string(); let mut focus_cmd: String = "move container to workspace ".to_string();
focus_cmd.push_str(&full_ws_name); focus_cmd.push_str(&full_ws_name);
send_command(stream, &focus_cmd); self.send_command(&focus_cmd);
} else { } else {
// If we have to send it to another screen // If we have to send it to another screen
let mut focus_cmd: String = "focus output ".to_string(); let mut focus_cmd: String = "focus output ".to_string();
focus_cmd.push_str(&target_output.name); focus_cmd.push_str(&target_output.name);
send_command(stream, &focus_cmd); self.send_command(&focus_cmd);
let focused_workspace_index = get_current_workspace(stream).num; let focused_workspace_index = self.get_current_workspace_index();
let mut focus_cmd: String = "workspace ".to_string(); let mut focus_cmd: String = "workspace ".to_string();
focus_cmd.push_str(&full_ws_name); focus_cmd.push_str(&full_ws_name);
send_command(stream, &focus_cmd); self.send_command(&focus_cmd);
let mut focus_cmd: String = "focus output ".to_string(); let mut focus_cmd: String = "focus output ".to_string();
focus_cmd.push_str(&current_output_name); focus_cmd.push_str(&current_output_name);
send_command(stream, &focus_cmd); self.send_command(&focus_cmd);
let mut focus_cmd: String = "move container to workspace ".to_string(); let mut focus_cmd: String = "move container to workspace ".to_string();
focus_cmd.push_str(&full_ws_name); focus_cmd.push_str(&full_ws_name);
send_command(stream, &focus_cmd); self.send_command(&focus_cmd);
let mut focus_cmd: String = "focus output ".to_string(); let mut focus_cmd: String = "focus output ".to_string();
focus_cmd.push_str(&target_output.name); focus_cmd.push_str(&target_output.name);
send_command(stream, &focus_cmd); self.send_command(&focus_cmd);
let mut focus_cmd: String = "workspace ".to_string(); let mut focus_cmd: String = "workspace ".to_string();
focus_cmd.push_str(&focused_workspace_index.to_string()); focus_cmd.push_str(&focused_workspace_index.to_string());
send_command(stream, &focus_cmd); self.send_command(&focus_cmd);
let mut focus_cmd: String = "focus output ".to_string(); let mut focus_cmd: String = "focus output ".to_string();
focus_cmd.push_str(&current_output_name); focus_cmd.push_str(&current_output_name);
send_command(stream, &focus_cmd); self.send_command(&focus_cmd);
} }
} }
None => { None => {
// Else, we send the container on the current output // Else, we send the container on the current output
let mut focus_cmd: String = "move container to workspace ".to_string(); let mut focus_cmd: String = "move container to workspace ".to_string();
focus_cmd.push_str(&full_ws_name); focus_cmd.push_str(&full_ws_name);
send_command(stream, &focus_cmd); self.send_command(&focus_cmd);
} }
}; };
} }
} }
} }
fn move_container_to_workspace_relative(stream: &UnixStream, workspace_index: usize) { fn move_container_to_workspace_relative(&self, workspace_index: usize) {
let current_workspace_index: usize = get_current_workspace(stream).num; let current_workspace_index: usize = self.get_current_workspace_index();
let focused_output_index = current_workspace_index / MAX_GROUP_WS; let focused_output_index = current_workspace_index / MAX_GROUP_WS;
let mut cmd: String = "move container to workspace number ".to_string(); let mut cmd: String = "move container to workspace number ".to_string();
let full_ws_name = format!("{}", focused_output_index * MAX_GROUP_WS + workspace_index); let full_ws_name = format!("{}", focused_output_index * MAX_GROUP_WS + workspace_index);
cmd.push_str(&full_ws_name); cmd.push_str(&full_ws_name);
send_command(stream, &cmd); self.send_command(&cmd);
} }
fn focus_to_workspace(stream: &UnixStream, workspace_index: usize) { fn focus_to_workspace(&self, workspace_index: usize) {
if workspace_index < MAX_GROUP_WS { if workspace_index < MAX_GROUP_WS {
focus_to_workspace_relative(stream, workspace_index); self.focus_to_workspace_relative(workspace_index);
} else { } else {
focus_to_workspace_absolute(stream, workspace_index); self.focus_to_workspace_absolute(workspace_index);
} }
} }
fn focus_to_workspace_absolute(stream: &UnixStream, workspace_index: usize) { fn focus_to_workspace_absolute(&self, workspace_index: usize) {
let output_index = (workspace_index / MAX_GROUP_WS) as usize; let output_index = (workspace_index / MAX_GROUP_WS) as usize;
let outputs = get_outputs(stream);
let workspaces = get_workspaces(stream);
// If the workspace already exists // If the workspace already exists
match workspaces.iter().find(|w| w.num == workspace_index) { match self.workspaces.iter().find(|w| w.num == workspace_index) {
Some(_) => { Some(_) => {
let mut focus_cmd: String = "workspace number ".to_string(); let mut focus_cmd: String = "workspace number ".to_string();
focus_cmd.push_str(&workspace_index.to_string()); focus_cmd.push_str(&workspace_index.to_string());
send_command(stream, &focus_cmd); self.send_command(&focus_cmd);
} }
None => { None => {
let target_group = workspace_index / MAX_GROUP_WS; let target_group = workspace_index / MAX_GROUP_WS;
let target_screen_index = match workspaces let target_screen_index = match self
.workspaces
.iter() .iter()
.find(|w| w.num / MAX_GROUP_WS == target_group) .find(|w| w.num / MAX_GROUP_WS == target_group)
{ {
// If other workspaces on the same group exists // If other workspaces on the same group exists
Some(other_workspace) => Some( Some(other_workspace) => Some(
outputs self.outputs
.iter() .iter()
.enumerate() .enumerate()
.find(|i| i.1.name == other_workspace.output) .find(|i| i.1.name == other_workspace.output)
@ -409,7 +442,7 @@ fn focus_to_workspace_absolute(stream: &UnixStream, workspace_index: usize) {
), ),
None => { None => {
// Or if the targeted output is currently connected // Or if the targeted output is currently connected
if output_index < outputs.len() { if output_index < self.outputs.len() {
Some(output_index) Some(output_index)
} else { } else {
None None
@ -420,37 +453,34 @@ fn focus_to_workspace_absolute(stream: &UnixStream, workspace_index: usize) {
match target_screen_index { match target_screen_index {
// If we have to send it to another screen // If we have to send it to another screen
Some(target_screen_index) => { Some(target_screen_index) => {
let target_output = &outputs[target_screen_index - 1]; let target_output = &self.outputs[target_screen_index - 1];
let mut focus_cmd: String = "focus output ".to_string(); let mut focus_cmd: String = "focus output ".to_string();
focus_cmd.push_str(&target_output.name); focus_cmd.push_str(&target_output.name);
send_command(stream, &focus_cmd); self.send_command(&focus_cmd);
} }
None => {} None => {}
}; };
// Then we focus the workspace // Then we focus the workspace
let mut focus_cmd: String = "workspace number ".to_string(); let mut focus_cmd: String = "workspace number ".to_string();
focus_cmd.push_str(&workspace_index.to_string()); focus_cmd.push_str(&workspace_index.to_string());
send_command(stream, &focus_cmd); self.send_command(&focus_cmd);
} }
} }
} }
fn focus_to_workspace_relative(stream: &UnixStream, workspace_index: usize) { fn focus_to_workspace_relative(&self, workspace_index: usize) {
let current_workspace_index: usize = get_current_workspace(stream).num; let current_workspace_index: usize = self.get_current_workspace_index();
let focused_output_index = current_workspace_index / MAX_GROUP_WS; let focused_output_index = current_workspace_index / MAX_GROUP_WS;
let mut cmd: String = "workspace number ".to_string(); let mut cmd: String = "workspace number ".to_string();
let full_ws_name = format!("{}", focused_output_index * MAX_GROUP_WS + workspace_index); let full_ws_name = format!("{}", focused_output_index * MAX_GROUP_WS + workspace_index);
cmd.push_str(&full_ws_name); cmd.push_str(&full_ws_name);
send_command(stream, &cmd); self.send_command(&cmd);
} }
fn focus_to_group(stream: &UnixStream, group_index: usize) { fn focus_to_group(&self, group_index: usize) {
let outputs = get_outputs(stream); let current_workspace_index: usize = self.get_current_workspace_index();
let workspaces = get_workspaces(stream);
let current_workspace_index: usize = get_current_workspace(stream).num;
let target_workspace_relative_index = current_workspace_index % MAX_GROUP_WS; let target_workspace_relative_index = current_workspace_index % MAX_GROUP_WS;
let target_workspace_index = group_index * MAX_GROUP_WS + target_workspace_relative_index; let target_workspace_index = group_index * MAX_GROUP_WS + target_workspace_relative_index;
@ -460,20 +490,25 @@ fn focus_to_group(stream: &UnixStream, group_index: usize) {
); );
// If the workspace already exists // If the workspace already exists
match workspaces.iter().find(|w| w.num == target_workspace_index) { match self
.workspaces
.iter()
.find(|w| w.num == target_workspace_index)
{
Some(_) => { Some(_) => {
let mut focus_cmd: String = "workspace number ".to_string(); let mut focus_cmd: String = "workspace number ".to_string();
focus_cmd.push_str(&full_ws_name); focus_cmd.push_str(&full_ws_name);
send_command(stream, &focus_cmd); self.send_command(&focus_cmd);
} }
None => { None => {
let target_screen_index = match workspaces let target_screen_index = match self
.workspaces
.iter() .iter()
.find(|w| w.num / MAX_GROUP_WS == group_index) .find(|w| w.num / MAX_GROUP_WS == group_index)
{ {
// If other workspaces on the same group exists // If other workspaces on the same group exists
Some(other_workspace) => Some( Some(other_workspace) => Some(
outputs self.outputs
.iter() .iter()
.enumerate() .enumerate()
.find(|i| i.1.name == other_workspace.output) .find(|i| i.1.name == other_workspace.output)
@ -483,7 +518,7 @@ fn focus_to_group(stream: &UnixStream, group_index: usize) {
), ),
None => { None => {
// Or if the targeted output is currently connected // Or if the targeted output is currently connected
if group_index > 0 && group_index <= outputs.len() { if group_index > 0 && group_index <= self.outputs.len() {
Some(group_index) Some(group_index)
} else { } else {
None None
@ -494,60 +529,58 @@ fn focus_to_group(stream: &UnixStream, group_index: usize) {
match target_screen_index { match target_screen_index {
// If we have to send it to another screen // If we have to send it to another screen
Some(target_screen_index) => { Some(target_screen_index) => {
let target_output = &outputs[target_screen_index - 1]; let target_output = &self.outputs[target_screen_index - 1];
let mut focus_cmd: String = "focus output ".to_string(); let mut focus_cmd: String = "focus output ".to_string();
focus_cmd.push_str(&target_output.name); focus_cmd.push_str(&target_output.name);
send_command(stream, &focus_cmd); self.send_command(&focus_cmd);
} }
None => {} None => {}
}; };
// Then we focus the workspace // Then we focus the workspace
let mut focus_cmd: String = "workspace number ".to_string(); let mut focus_cmd: String = "workspace number ".to_string();
focus_cmd.push_str(&target_workspace_index.to_string()); focus_cmd.push_str(&target_workspace_index.to_string());
send_command(stream, &focus_cmd); self.send_command(&focus_cmd);
} }
} }
} }
fn focus_all_outputs_to_workspace(stream: &UnixStream, workspace_index: usize) { fn focus_all_outputs_to_workspace(&self, workspace_index: usize) {
let current_output = get_current_output_name(stream); let current_output = self.get_current_output_name();
// Iterate on all outputs to focus on the given workspace // Iterate on all outputs to focus on the given workspace
let outputs = get_outputs(stream); for output in self.outputs.iter() {
for output in outputs.iter() {
let mut cmd: String = "focus output ".to_string(); let mut cmd: String = "focus output ".to_string();
cmd.push_str(output.name.as_str()); cmd.push_str(output.name.as_str());
send_command(stream, &cmd); self.send_command(&cmd);
focus_to_workspace(stream, workspace_index); self.focus_to_workspace(workspace_index);
} }
// Get back to currently focused output // Get back to currently focused output
let mut cmd: String = "focus output ".to_string(); let mut cmd: String = "focus output ".to_string();
cmd.push_str(&current_output); cmd.push_str(&current_output);
send_command(stream, &cmd); self.send_command(&cmd);
} }
fn move_container_to_next_output(stream: &UnixStream) { fn move_container_to_next_output(&self) {
move_container_to_next_or_prev_output(stream, false); self.move_container_to_next_or_prev_output(false);
} }
fn move_container_to_prev_output(stream: &UnixStream) { fn move_container_to_prev_output(&self) {
move_container_to_next_or_prev_output(stream, true); self.move_container_to_next_or_prev_output(true);
} }
fn move_container_to_next_or_prev_output(stream: &UnixStream, go_to_prev: bool) { fn move_container_to_next_or_prev_output(&self, go_to_prev: bool) {
let outputs = get_outputs(stream); let focused_output_index = self.get_current_output_index();
let focused_output_index = get_current_output_index(stream);
let target_output = if go_to_prev { let target_output = if go_to_prev {
&outputs[(focused_output_index + outputs.len() - 1) % outputs.len()] &self.outputs[(focused_output_index + self.outputs.len() - 1) % self.outputs.len()]
} else { } else {
&outputs[(focused_output_index + 1) % outputs.len()] &self.outputs[(focused_output_index + 1) % self.outputs.len()]
}; };
let workspaces = get_workspaces(stream); let workspaces = self.get_workspaces();
let target_workspace = workspaces let target_workspace = workspaces
.iter() .iter()
.find(|x| x.output == target_output.name && x.visible) .find(|x| x.output == target_output.name && x.visible)
@ -561,109 +594,106 @@ fn move_container_to_next_or_prev_output(stream: &UnixStream, go_to_prev: bool)
// Move container to target workspace // Move container to target workspace
let mut cmd: String = "move container to workspace number ".to_string(); let mut cmd: String = "move container to workspace number ".to_string();
cmd.push_str(&full_ws_name); cmd.push_str(&full_ws_name);
send_command(stream, &cmd); self.send_command(&cmd);
// Focus that workspace to follow the container // Focus that workspace to follow the container
let mut cmd: String = "workspace number ".to_string(); let mut cmd: String = "workspace number ".to_string();
cmd.push_str(&target_workspace.num.to_string()); cmd.push_str(&full_ws_name);
send_command(stream, &cmd); self.send_command(&cmd);
} }
fn focus_container_to_next_group(stream: &UnixStream) { fn focus_container_to_next_group(&self) {
focus_container_to_next_or_prev_group(stream, false); self.focus_container_to_next_or_prev_group(false);
} }
fn focus_container_to_prev_group(stream: &UnixStream) { fn focus_container_to_prev_group(&self) {
focus_container_to_next_or_prev_group(stream, true); self.focus_container_to_next_or_prev_group(true);
} }
fn focus_container_to_next_or_prev_group(stream: &UnixStream, go_to_prev: bool) { fn focus_container_to_next_or_prev_group(&self, go_to_prev: bool) {
let current_workspace_index: usize = get_current_workspace(stream).num; let current_workspace_index: usize = self.get_current_workspace_index();
let focused_group_index = current_workspace_index / MAX_GROUP_WS; let focused_group_index = current_workspace_index / MAX_GROUP_WS;
if go_to_prev { if go_to_prev {
focus_to_group(stream, focused_group_index - 1); self.focus_to_group(focused_group_index - 1);
} else { } else {
focus_to_group(stream, focused_group_index + 1); self.focus_to_group(focused_group_index + 1);
}; };
} }
fn init_workspaces(stream: &UnixStream, workspace_index: usize) { fn init_workspaces(&self, workspace_index: usize) {
let outputs = get_outputs(stream);
let cmd_prefix: String = "focus output ".to_string(); let cmd_prefix: String = "focus output ".to_string();
for output in outputs.iter().rev() { for output in self.outputs.iter().rev() {
let mut cmd = cmd_prefix.clone(); let mut cmd = cmd_prefix.clone();
cmd.push_str(output.name.as_str()); cmd.push_str(output.name.as_str());
send_command(stream, &cmd); self.send_command(&cmd);
let mut cmd: String = "workspace number ".to_string(); let mut cmd: String = "workspace number ".to_string();
let full_ws_name = format!( let full_ws_name = format!(
"{}", "{}",
(get_current_output_index(stream) + 1) * MAX_GROUP_WS + workspace_index (self.get_current_output_index() + 1) * MAX_GROUP_WS + workspace_index
); );
cmd.push_str(&full_ws_name); cmd.push_str(&full_ws_name);
send_command(stream, &cmd); self.send_command(&cmd);
} }
} }
fn rearrange_workspaces(stream: &UnixStream) { fn rearrange_workspaces(&self) {
let outputs = get_outputs(stream);
let workspaces = get_workspaces(stream);
let focus_cmd_prefix: String = "workspace number ".to_string(); let focus_cmd_prefix: String = "workspace number ".to_string();
let move_cmd_prefix: String = "move workspace to ".to_string(); let move_cmd_prefix: String = "move workspace to ".to_string();
for workspace in workspaces.iter() { for workspace in self.workspaces.iter() {
let mut focus_cmd = focus_cmd_prefix.clone(); let mut focus_cmd = focus_cmd_prefix.clone();
focus_cmd.push_str(&workspace.num.to_string()); focus_cmd.push_str(&workspace.num.to_string());
send_command(stream, &focus_cmd); self.send_command(&focus_cmd);
let group_index = workspace.num / MAX_GROUP_WS; let group_index = workspace.num / MAX_GROUP_WS;
if group_index <= outputs.len() - 1 { if group_index <= self.outputs.len() - 1 {
let mut move_cmd = move_cmd_prefix.clone(); let mut move_cmd = move_cmd_prefix.clone();
move_cmd.push_str(&outputs[group_index.max(1) - 1].name); move_cmd.push_str(&self.outputs[group_index.max(1) - 1].name);
send_command(stream, &move_cmd); self.send_command(&move_cmd);
}
} }
} }
} }
fn main() { fn main() {
let cli = Cli::parse(); let cli = Cli::parse();
let stream = get_stream();
let swaysome = SwaySome::new();
match &cli.command { match &cli.command {
Command::Init(action) => { Command::Init(action) => {
init_workspaces(&stream, action.index); swaysome.init_workspaces(action.index);
} }
Command::Move(action) => { Command::Move(action) => {
move_container_to_workspace(&stream, action.index); swaysome.move_container_to_workspace(action.index);
} }
Command::MoveToGroup(action) => { Command::MoveToGroup(action) => {
move_container_to_workspace_group(&stream, action.index); swaysome.move_container_to_workspace_group(action.index);
} }
Command::Focus(action) => { Command::Focus(action) => {
focus_to_workspace(&stream, action.index); swaysome.focus_to_workspace(action.index);
} }
Command::FocusGroup(action) => { Command::FocusGroup(action) => {
focus_to_group(&stream, action.index); swaysome.focus_to_group(action.index);
} }
Command::FocusAllOutputs(action) => { Command::FocusAllOutputs(action) => {
focus_all_outputs_to_workspace(&stream, action.index); swaysome.focus_all_outputs_to_workspace(action.index);
} }
Command::NextOutput => { Command::NextOutput => {
move_container_to_next_output(&stream); swaysome.move_container_to_next_output();
} }
Command::PrevOutput => { Command::PrevOutput => {
move_container_to_prev_output(&stream); swaysome.move_container_to_prev_output();
} }
Command::NextGroup => { Command::NextGroup => {
focus_container_to_next_group(&stream); swaysome.focus_container_to_next_group();
} }
Command::PrevGroup => { Command::PrevGroup => {
focus_container_to_prev_group(&stream); swaysome.focus_container_to_prev_group();
} }
Command::RearrangeWorkspaces => { Command::RearrangeWorkspaces => {
rearrange_workspaces(&stream); swaysome.rearrange_workspaces();
} }
} }
} }