mirror of
https://gitlab.com/hyask/swaysome.git
synced 2025-12-10 07:44:43 +01:00
Merge branch 'workspaces_groups' into 'master'
Workspaces groups This feature brings a lot of new possibilities. A workspace group is group of ten workspaces inside a decimal range (ex: from 10 to 19). It introduces `relative` and `absolute` scopes. For a move or a focus, if the target index is only one digit it will focus the wanted workspace relative to the current group focused. But if the target index is above 9, it will directly focus the workspace inside the group if it is already opened, if not, it will open the group on the current screen. Example 1: I'm focused on 21. If I do `swaysome focus 5` it's going to focus the workspace 25 on the same output than the other 20s. Example 2: I'm focused on 21. If I do `swaysome focus 35` it's going to focus the workspace 35. If there is no 30s opened yet, it's going to open it on my current screen, but I already have 32 opened on another screen, so it's going to open the workspace 35 on it. It also brings the `next-group` and `prev-group` features to switch focus from 21 to 31 or 21 to 11 for example. There is the `focus-group` action that allows you to directly focus a specified group and so creating multiple workspace groups on one output (For example, 20s for work and 30s for private stuff). There is one breaking behavior: I had to edit the `init` function to begin from 10 and not from 1. So with `swaysome init 1`, a triple screen is now initialized like this: 11, 21, 31 instead of 1, 11, 21. See merge request hyask/swaysome!6
This commit is contained in:
commit
e8fc73c5da
1 changed files with 279 additions and 15 deletions
294
src/main.rs
294
src/main.rs
|
|
@ -29,15 +29,18 @@ struct Cli {
|
|||
|
||||
#[derive(Subcommand, Debug)]
|
||||
enum Command {
|
||||
#[clap(about = "Initialize the workspaces for all the outputs")]
|
||||
#[clap(about = "Initialize the workspace groups for all the outputs")]
|
||||
Init(InitAction),
|
||||
|
||||
#[clap(about = "Move the focused container to another workspace on the same output")]
|
||||
#[clap(about = "Move the focused container to another workspace on the same workspace group")]
|
||||
Move(MoveAction),
|
||||
|
||||
#[clap(about = "Focus to another workspace on the same output")]
|
||||
#[clap(about = "Focus to another workspace on the same workspace group")]
|
||||
Focus(FocusAction),
|
||||
|
||||
#[clap(about = "Focus to workspace group")]
|
||||
FocusGroup(FocusAction),
|
||||
|
||||
#[clap(about = "Focus to another workspace on all the outputs")]
|
||||
FocusAllOutputs(FocusAction),
|
||||
|
||||
|
|
@ -47,6 +50,12 @@ enum Command {
|
|||
#[clap(about = "Move the focused container to the previous output")]
|
||||
PrevOutput,
|
||||
|
||||
#[clap(about = "Move the focused container to the next group")]
|
||||
NextGroup,
|
||||
|
||||
#[clap(about = "Move the focused container to the previous group")]
|
||||
PrevGroup,
|
||||
|
||||
#[clap(about = "Rearrange already opened workspaces")]
|
||||
RearrangeWorkspaces,
|
||||
}
|
||||
|
|
@ -195,7 +204,7 @@ fn get_current_output_index(stream: &UnixStream) -> usize {
|
|||
let outputs = get_outputs(stream);
|
||||
|
||||
match outputs.iter().position(|x| x.focused) {
|
||||
Some(i) => i,
|
||||
Some(i) => i + 1,
|
||||
None => panic!("WTF! No focused output???"),
|
||||
}
|
||||
}
|
||||
|
|
@ -211,9 +220,111 @@ fn get_current_output_name(stream: &UnixStream) -> 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 < 10 {
|
||||
move_container_to_workspace_relative(stream, workspace_index);
|
||||
} else {
|
||||
move_container_to_workspace_absolute(stream, workspace_index);
|
||||
}
|
||||
}
|
||||
|
||||
fn move_container_to_workspace_absolute(stream: &UnixStream, workspace_index: usize) {
|
||||
let output_index = (workspace_index / 10) as usize;
|
||||
let outputs = get_outputs(stream);
|
||||
let workspaces = get_workspaces(stream);
|
||||
|
||||
// If the workspace already exists
|
||||
match workspaces.iter().find(|w| w.num == workspace_index) {
|
||||
Some(_) => {
|
||||
let mut focus_cmd: String = "move container to workspace number ".to_string();
|
||||
focus_cmd.push_str(&workspace_index.to_string());
|
||||
send_command(stream, &focus_cmd);
|
||||
}
|
||||
None => {
|
||||
let target_group = workspace_index / 10;
|
||||
let target_screen_index = match workspaces.iter().find(|w| w.num / 10 == target_group) {
|
||||
// If other workspaces on the same group exists
|
||||
Some(other_workspace) => Some(
|
||||
outputs
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|i| i.1.name == other_workspace.output)
|
||||
.unwrap()
|
||||
.0,
|
||||
),
|
||||
None => {
|
||||
// Or if the targeted output is currently connected
|
||||
if output_index < outputs.len() {
|
||||
Some(output_index)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
match target_screen_index {
|
||||
// If we have to send it to another screen
|
||||
Some(target_screen_index) => {
|
||||
let target_output = &outputs[target_screen_index - 1];
|
||||
|
||||
let current_output_name = get_current_output_name(stream);
|
||||
|
||||
let mut focus_cmd: String = "focus output ".to_string();
|
||||
focus_cmd.push_str(&target_output.name);
|
||||
send_command(stream, &focus_cmd);
|
||||
|
||||
let focused_workspace_index = get_current_workspace(stream).num;
|
||||
|
||||
let mut focus_cmd: String = "workspace ".to_string();
|
||||
focus_cmd.push_str(&workspace_index.to_string());
|
||||
send_command(stream, &focus_cmd);
|
||||
|
||||
let mut focus_cmd: String = "focus output ".to_string();
|
||||
focus_cmd.push_str(¤t_output_name);
|
||||
send_command(stream, &focus_cmd);
|
||||
|
||||
let mut focus_cmd: String = "move container to workspace ".to_string();
|
||||
focus_cmd.push_str(&workspace_index.to_string());
|
||||
send_command(stream, &focus_cmd);
|
||||
|
||||
let mut focus_cmd: String = "focus output ".to_string();
|
||||
focus_cmd.push_str(&target_output.name);
|
||||
send_command(stream, &focus_cmd);
|
||||
|
||||
let mut focus_cmd: String = "workspace ".to_string();
|
||||
focus_cmd.push_str(&focused_workspace_index.to_string());
|
||||
send_command(stream, &focus_cmd);
|
||||
|
||||
let mut focus_cmd: String = "focus output ".to_string();
|
||||
focus_cmd.push_str(¤t_output_name);
|
||||
send_command(stream, &focus_cmd);
|
||||
}
|
||||
None => {
|
||||
// Else, we send the container on the current output
|
||||
let mut focus_cmd: String = "move container to workspace ".to_string();
|
||||
focus_cmd.push_str(&workspace_index.to_string());
|
||||
send_command(stream, &focus_cmd);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn move_container_to_workspace_relative(stream: &UnixStream, workspace_index: usize) {
|
||||
let current_workspace_index: usize = get_current_workspace(stream).num;
|
||||
let focused_output_index = current_workspace_index / 10;
|
||||
|
||||
let mut cmd: String = "move container to workspace number ".to_string();
|
||||
let full_ws_name = format!("{}{}", get_current_output_index(stream), workspace_index)
|
||||
let full_ws_name = format!("{}{}", focused_output_index, workspace_index)
|
||||
.parse::<i32>()
|
||||
.unwrap();
|
||||
cmd.push_str(&full_ws_name.to_string());
|
||||
|
|
@ -221,14 +332,136 @@ fn move_container_to_workspace(stream: &UnixStream, workspace_index: usize) {
|
|||
}
|
||||
|
||||
fn focus_to_workspace(stream: &UnixStream, workspace_index: usize) {
|
||||
if workspace_index < 10 {
|
||||
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) {
|
||||
let output_index = (workspace_index / 10) as usize;
|
||||
let outputs = get_outputs(stream);
|
||||
let workspaces = get_workspaces(stream);
|
||||
|
||||
// If the workspace already exists
|
||||
match workspaces.iter().find(|w| w.num == workspace_index) {
|
||||
Some(_) => {
|
||||
let mut focus_cmd: String = "workspace number ".to_string();
|
||||
focus_cmd.push_str(&workspace_index.to_string());
|
||||
send_command(stream, &focus_cmd);
|
||||
}
|
||||
None => {
|
||||
let target_group = workspace_index / 10;
|
||||
let target_screen_index = match workspaces.iter().find(|w| w.num / 10 == target_group) {
|
||||
// If other workspaces on the same group exists
|
||||
Some(other_workspace) => Some(
|
||||
outputs
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|i| i.1.name == other_workspace.output)
|
||||
.unwrap()
|
||||
.0,
|
||||
),
|
||||
None => {
|
||||
// Or if the targeted output is currently connected
|
||||
if output_index < outputs.len() {
|
||||
Some(output_index)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
match target_screen_index {
|
||||
// If we have to send it to another screen
|
||||
Some(target_screen_index) => {
|
||||
let target_output = &outputs[target_screen_index - 1];
|
||||
|
||||
let mut focus_cmd: String = "focus output ".to_string();
|
||||
focus_cmd.push_str(&target_output.name);
|
||||
send_command(stream, &focus_cmd);
|
||||
}
|
||||
None => {}
|
||||
};
|
||||
// Then we focus the workspace
|
||||
let mut focus_cmd: String = "workspace number ".to_string();
|
||||
focus_cmd.push_str(&workspace_index.to_string());
|
||||
send_command(stream, &focus_cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn focus_to_workspace_relative(stream: &UnixStream, workspace_index: usize) {
|
||||
let current_workspace_index: usize = get_current_workspace(stream).num;
|
||||
let focused_output_index = current_workspace_index / 10;
|
||||
|
||||
let mut cmd: String = "workspace number ".to_string();
|
||||
let full_ws_name = format!("{}{}", get_current_output_index(stream), &workspace_index)
|
||||
let full_ws_name = format!("{}{}", focused_output_index, &workspace_index)
|
||||
.parse::<i32>()
|
||||
.unwrap();
|
||||
cmd.push_str(&full_ws_name.to_string());
|
||||
send_command(stream, &cmd);
|
||||
}
|
||||
|
||||
fn focus_to_group(stream: &UnixStream, group_index: usize) {
|
||||
let outputs = get_outputs(stream);
|
||||
let workspaces = get_workspaces(stream);
|
||||
|
||||
let current_workspace_index: usize = get_current_workspace(stream).num;
|
||||
let contextual_target_workspace_index =
|
||||
current_workspace_index - (current_workspace_index / 10) * 10;
|
||||
|
||||
let target_workspace_index = group_index * 10 + contextual_target_workspace_index;
|
||||
|
||||
// If the workspace already exists
|
||||
match workspaces.iter().find(|w| w.num == target_workspace_index) {
|
||||
Some(_) => {
|
||||
let mut focus_cmd: String = "workspace number ".to_string();
|
||||
focus_cmd.push_str(&target_workspace_index.to_string());
|
||||
send_command(stream, &focus_cmd);
|
||||
}
|
||||
None => {
|
||||
let target_screen_index = match workspaces.iter().find(|w| w.num / 10 == group_index) {
|
||||
// If other workspaces on the same group exists
|
||||
Some(other_workspace) => Some(
|
||||
outputs
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|i| i.1.name == other_workspace.output)
|
||||
.unwrap()
|
||||
.0
|
||||
+ 1,
|
||||
),
|
||||
None => {
|
||||
// Or if the targeted output is currently connected
|
||||
if group_index <= outputs.len() {
|
||||
Some(group_index)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
match target_screen_index {
|
||||
// If we have to send it to another screen
|
||||
Some(target_screen_index) => {
|
||||
let target_output = &outputs[target_screen_index - 1];
|
||||
|
||||
let mut focus_cmd: String = "focus output ".to_string();
|
||||
focus_cmd.push_str(&target_output.name);
|
||||
send_command(stream, &focus_cmd);
|
||||
}
|
||||
None => {}
|
||||
};
|
||||
// Then we focus the workspace
|
||||
let mut focus_cmd: String = "workspace number ".to_string();
|
||||
focus_cmd.push_str(&target_workspace_index.to_string());
|
||||
send_command(stream, &focus_cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn focus_all_outputs_to_workspace(stream: &UnixStream, workspace_index: usize) {
|
||||
let current_output = get_current_output_name(stream);
|
||||
|
||||
|
|
@ -258,15 +491,12 @@ fn move_container_to_prev_output(stream: &UnixStream) {
|
|||
|
||||
fn move_container_to_next_or_prev_output(stream: &UnixStream, go_to_prev: bool) {
|
||||
let outputs = get_outputs(stream);
|
||||
let focused_output_index = match outputs.iter().position(|x| x.focused) {
|
||||
Some(i) => i,
|
||||
None => panic!("WTF! No focused output???"),
|
||||
};
|
||||
let focused_output_index = get_current_output_index(stream);
|
||||
|
||||
let target_output = if go_to_prev {
|
||||
&outputs[(focused_output_index + outputs.len() - 1) % outputs.len()]
|
||||
&outputs[(focused_output_index + outputs.len() - 1) % outputs.len() - 1]
|
||||
} else {
|
||||
&outputs[(focused_output_index + 1) % outputs.len()]
|
||||
&outputs[(focused_output_index + 1) % outputs.len() - 1]
|
||||
};
|
||||
|
||||
let workspaces = get_workspaces(stream);
|
||||
|
|
@ -286,6 +516,25 @@ fn move_container_to_next_or_prev_output(stream: &UnixStream, go_to_prev: bool)
|
|||
send_command(stream, &cmd);
|
||||
}
|
||||
|
||||
fn focus_container_to_next_group(stream: &UnixStream) {
|
||||
focus_container_to_next_or_prev_group(stream, false);
|
||||
}
|
||||
|
||||
fn focus_container_to_prev_group(stream: &UnixStream) {
|
||||
focus_container_to_next_or_prev_group(stream, true);
|
||||
}
|
||||
|
||||
fn focus_container_to_next_or_prev_group(stream: &UnixStream, go_to_prev: bool) {
|
||||
let current_workspace_index: usize = get_current_workspace(stream).num;
|
||||
let focused_group_index = current_workspace_index / 10;
|
||||
|
||||
if go_to_prev {
|
||||
focus_to_group(stream, focused_group_index - 1);
|
||||
} else {
|
||||
focus_to_group(stream, focused_group_index + 1);
|
||||
};
|
||||
}
|
||||
|
||||
fn init_workspaces(stream: &UnixStream, workspace_index: usize) {
|
||||
let outputs = get_outputs(stream);
|
||||
|
||||
|
|
@ -294,7 +543,13 @@ fn init_workspaces(stream: &UnixStream, workspace_index: usize) {
|
|||
let mut cmd = cmd_prefix.clone();
|
||||
cmd.push_str(output.name.as_str());
|
||||
send_command(stream, &cmd);
|
||||
focus_to_workspace(stream, workspace_index);
|
||||
|
||||
let mut cmd: String = "workspace number ".to_string();
|
||||
let full_ws_name = format!("{}{}", get_current_output_index(stream), &workspace_index)
|
||||
.parse::<i32>()
|
||||
.unwrap();
|
||||
cmd.push_str(&full_ws_name.to_string());
|
||||
send_command(stream, &cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -310,9 +565,9 @@ fn rearrange_workspaces(stream: &UnixStream) {
|
|||
send_command(stream, &focus_cmd);
|
||||
|
||||
let output_index = workspace.num / 10;
|
||||
if output_index < outputs.len() {
|
||||
if output_index <= outputs.len() - 1 {
|
||||
let mut move_cmd = move_cmd_prefix.clone();
|
||||
move_cmd.push_str(&outputs[output_index].name);
|
||||
move_cmd.push_str(&outputs[output_index.max(1) - 1].name);
|
||||
send_command(stream, &move_cmd);
|
||||
}
|
||||
}
|
||||
|
|
@ -332,6 +587,9 @@ fn main() {
|
|||
Command::Focus(action) => {
|
||||
focus_to_workspace(&stream, action.index);
|
||||
}
|
||||
Command::FocusGroup(action) => {
|
||||
focus_to_group(&stream, action.index);
|
||||
}
|
||||
Command::FocusAllOutputs(action) => {
|
||||
focus_all_outputs_to_workspace(&stream, action.index);
|
||||
}
|
||||
|
|
@ -341,6 +599,12 @@ fn main() {
|
|||
Command::PrevOutput => {
|
||||
move_container_to_prev_output(&stream);
|
||||
}
|
||||
Command::NextGroup => {
|
||||
focus_container_to_next_group(&stream);
|
||||
}
|
||||
Command::PrevGroup => {
|
||||
focus_container_to_prev_group(&stream);
|
||||
}
|
||||
Command::RearrangeWorkspaces => {
|
||||
rearrange_workspaces(&stream);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue