feat(wm): add cmd to move ws to other monitors

This commit adds a new komorebic command to move the entire focused
workspace and all managed windows and containers to a target monitor
index. Windows that have been excluded from management using various
rules will not be moved as they are not tracked in the window manager
state.

resolve #88
This commit is contained in:
LGUG2Z
2021-12-31 09:21:47 -08:00
parent 228ef78d7f
commit 39685dd615
7 changed files with 59 additions and 0 deletions

View File

@@ -311,6 +311,7 @@ focus-workspace Focus the specified workspace on the focuse
focus-monitor-workspace Focus the specified workspace on the target monitor
cycle-monitor Focus the monitor in the given cycle direction
cycle-workspace Focus the workspace in the given cycle direction
move-workspace-to-monitor Move the focused workspace to the specified monitor
new-workspace Create and append a new workspace on the focused monitor
resize-delta Set the resize delta (used by resize-edge and resize-axis)
invisible-borders Set the invisible border dimensions around each window
@@ -376,6 +377,7 @@ used [is available here](komorebi.sample.with.lib.ahk).
- [x] Move focused window container to workspace follow
- [x] Send focused window container to monitor
- [x] Send focused window container to workspace
- [x] Move focused workspace to monitor
- [x] Mouse follows focused container
- [x] Resize window container in direction
- [x] Resize window container on axis

View File

@@ -47,6 +47,7 @@ pub enum SocketMessage {
MoveContainerToWorkspaceNumber(usize),
SendContainerToMonitorNumber(usize),
SendContainerToWorkspaceNumber(usize),
MoveWorkspaceToMonitorNumber(usize),
Promote,
ToggleFloat,
ToggleMonocle,

View File

@@ -68,6 +68,20 @@ impl Monitor {
Ok(())
}
pub fn remove_workspace_by_idx(&mut self, idx: usize) -> Option<Workspace> {
if idx < self.workspaces().len() {
return self.workspaces_mut().remove(idx);
}
if idx == 0 {
self.workspaces_mut().push_back(Workspace::default());
} else {
self.focus_workspace(idx - 1).ok()?;
};
None
}
pub fn ensure_workspace_count(&mut self, ensure_count: usize) {
if self.workspaces().len() < ensure_count {
self.workspaces_mut()

View File

@@ -147,6 +147,9 @@ impl WindowManager {
SocketMessage::SendContainerToMonitorNumber(monitor_idx) => {
self.move_container_to_monitor(monitor_idx, false)?;
}
SocketMessage::MoveWorkspaceToMonitorNumber(monitor_idx) => {
self.move_workspace_to_monitor(monitor_idx)?;
}
SocketMessage::TogglePause => {
if self.is_paused {
tracing::info!("resuming");

View File

@@ -828,6 +828,34 @@ impl WindowManager {
self.update_focused_workspace(mouse_follows_focus)
}
pub fn remove_focused_workspace(&mut self) -> Option<Workspace> {
let focused_monitor: &mut Monitor = self.focused_monitor_mut()?;
let focused_workspace_idx = focused_monitor.focused_workspace_idx();
focused_monitor.remove_workspace_by_idx(focused_workspace_idx)
}
#[tracing::instrument(skip(self))]
pub fn move_workspace_to_monitor(&mut self, idx: usize) -> Result<()> {
tracing::info!("moving workspace");
let mouse_follows_focus = self.mouse_follows_focus;
let workspace = self
.remove_focused_workspace()
.ok_or_else(|| anyhow!("there is no workspace"))?;
{
let target_monitor: &mut Monitor = self
.monitors_mut()
.get_mut(idx)
.ok_or_else(|| anyhow!("there is no monitor"))?;
target_monitor.workspaces_mut().push_back(workspace);
target_monitor.focus_workspace(target_monitor.workspaces().len() - 1)?;
target_monitor.load_focused_workspace(mouse_follows_focus)?;
}
self.focus_monitor(idx)?;
self.update_focused_workspace(mouse_follows_focus)
}
#[tracing::instrument(skip(self))]
pub fn focus_container_in_direction(&mut self, direction: OperationDirection) -> Result<()> {

View File

@@ -116,6 +116,10 @@ CycleWorkspace(cycle_direction) {
Run, komorebic.exe cycle-workspace %cycle_direction%, , Hide
}
MoveWorkspaceToMonitor(target) {
Run, komorebic.exe move-workspace-to-monitor %target%, , Hide
}
NewWorkspace() {
Run, komorebic.exe new-workspace, , Hide
}

View File

@@ -114,6 +114,7 @@ gen_target_subcommand_args! {
SendToWorkspace,
FocusMonitor,
FocusWorkspace,
MoveWorkspaceToMonitor,
}
// Thanks to @danielhenrymantilla for showing me how to use cfg_attr with an optional argument like
@@ -445,6 +446,9 @@ enum SubCommand {
/// Focus the workspace in the given cycle direction
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
CycleWorkspace(CycleWorkspace),
/// Move the focused workspace to the specified monitor
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
MoveWorkspaceToMonitor(MoveWorkspaceToMonitor),
/// Create and append a new workspace on the focused monitor
NewWorkspace,
/// Set the resize delta (used by resize-edge and resize-axis)
@@ -633,6 +637,9 @@ fn main() -> Result<()> {
SubCommand::SendToWorkspace(arg) => {
send_message(&*SocketMessage::SendContainerToWorkspaceNumber(arg.target).as_bytes()?)?;
}
SubCommand::MoveWorkspaceToMonitor(arg) => {
send_message(&*SocketMessage::MoveWorkspaceToMonitorNumber(arg.target).as_bytes()?)?;
}
SubCommand::InvisibleBorders(arg) => {
send_message(
&*SocketMessage::InvisibleBorders(Rect {