mirror of
https://gitlab.com/hyask/swaysome.git
synced 2025-12-10 07:44:43 +01:00
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:
parent
99a99648b1
commit
90ec4a2566
1 changed files with 551 additions and 521 deletions
426
src/main.rs
426
src/main.rs
|
|
@ -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,7 +79,43 @@ struct Index {
|
||||||
index: usize,
|
index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_stream() -> UnixStream {
|
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 {
|
||||||
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) {
|
||||||
Ok(val) => val,
|
Ok(val) => val,
|
||||||
|
|
@ -108,9 +145,9 @@ 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"] {
|
||||||
|
|
@ -177,20 +226,11 @@ fn check_success(stream: &UnixStream) {
|
||||||
}
|
}
|
||||||
Err(_) => panic!("Unable to read response"),
|
Err(_) => panic!("Unable to read response"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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"),
|
||||||
};
|
};
|
||||||
|
|
@ -201,97 +241,91 @@ fn get_outputs(stream: &UnixStream) -> Vec<Output> {
|
||||||
.collect();
|
.collect();
|
||||||
outputs.sort_by(|x, y| x.name.cmp(&y.name)); // sort_by_key doesn't work here (https://stackoverflow.com/a/47126516)
|
outputs.sort_by(|x, y| x.name.cmp(&y.name)); // sort_by_key doesn't work here (https://stackoverflow.com/a/47126516)
|
||||||
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"),
|
||||||
};
|
};
|
||||||
let mut workspaces: Vec<Workspace> = serde_json::from_str(&ws).unwrap();
|
let mut workspaces: Vec<Workspace> = serde_json::from_str(&ws).unwrap();
|
||||||
workspaces.sort_by_key(|x| x.num);
|
workspaces.sort_by_key(|x| x.num);
|
||||||
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???"),
|
||||||
};
|
};
|
||||||
|
|
||||||
focused_output_index.to_string()
|
focused_output_index.to_string()
|
||||||
}
|
|
||||||
|
|
||||||
fn get_current_workspace(stream: &UnixStream) -> Workspace {
|
|
||||||
let outputs = get_outputs(stream);
|
|
||||||
let workspaces = get_workspaces(stream);
|
|
||||||
workspaces
|
|
||||||
.into_iter()
|
|
||||||
.find(|w| w.visible && outputs.iter().find(|o| o.name == w.output).unwrap().focused)
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn move_container_to_workspace(stream: &UnixStream, workspace_index: usize) {
|
|
||||||
if workspace_index < MAX_GROUP_WS {
|
|
||||||
move_container_to_workspace_relative(stream, workspace_index);
|
|
||||||
} else {
|
|
||||||
move_container_to_workspace_absolute(stream, workspace_index);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn move_container_to_workspace_group(stream: &UnixStream, target_group: usize) {
|
fn get_current_workspace_index(&self) -> usize {
|
||||||
let current_workspace_index = get_current_workspace(stream).num;
|
self.workspaces
|
||||||
|
.iter()
|
||||||
|
.find(|w| {
|
||||||
|
w.visible
|
||||||
|
&& self
|
||||||
|
.outputs
|
||||||
|
.iter()
|
||||||
|
.find(|o| o.name == w.output)
|
||||||
|
.unwrap()
|
||||||
|
.focused
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
.num
|
||||||
|
}
|
||||||
|
|
||||||
|
fn move_container_to_workspace(&self, workspace_index: usize) {
|
||||||
|
if workspace_index < MAX_GROUP_WS {
|
||||||
|
self.move_container_to_workspace_relative(workspace_index);
|
||||||
|
} else {
|
||||||
|
self.move_container_to_workspace_absolute(workspace_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn move_container_to_workspace_group(&self, target_group: usize) {
|
||||||
|
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(¤t_output_name);
|
focus_cmd.push_str(¤t_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(¤t_output_name);
|
focus_cmd.push_str(¤t_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) {
|
|
||||||
if workspace_index < MAX_GROUP_WS {
|
|
||||||
focus_to_workspace_relative(stream, workspace_index);
|
|
||||||
} else {
|
|
||||||
focus_to_workspace_absolute(stream, workspace_index);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn focus_to_workspace_absolute(stream: &UnixStream, workspace_index: usize) {
|
fn focus_to_workspace(&self, workspace_index: usize) {
|
||||||
|
if workspace_index < MAX_GROUP_WS {
|
||||||
|
self.focus_to_workspace_relative(workspace_index);
|
||||||
|
} else {
|
||||||
|
self.focus_to_workspace_absolute(workspace_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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(¤t_output);
|
cmd.push_str(¤t_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) {
|
|
||||||
let outputs = get_outputs(stream);
|
|
||||||
|
|
||||||
|
fn init_workspaces(&self, workspace_index: usize) {
|
||||||
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) {
|
|
||||||
let outputs = get_outputs(stream);
|
|
||||||
let workspaces = get_workspaces(stream);
|
|
||||||
|
|
||||||
|
fn rearrange_workspaces(&self) {
|
||||||
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue