Skip to content

Commit

Permalink
Provide the user of the "move-workspace-to-monitor" command more capa…
Browse files Browse the repository at this point in the history
…biltities for moving their workspaces between monitors

The "move-workspace-to-monitor" command provides now the requested features of Issue nikitabobko#766.
This commit makes it  possible to move workspaces to a specific monitor with a monitor pattern
Additonally to the next|prev i have added the left|down|up|right option
  • Loading branch information
Franz Murner committed Dec 7, 2024
1 parent 21336ad commit 9125a7d
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 26 deletions.
34 changes: 21 additions & 13 deletions Sources/AppBundle/command/impl/MoveWorkspaceToMonitorCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,28 @@ struct MoveWorkspaceToMonitorCommand: Command {
guard let target = args.resolveTargetOrReportError(env, io) else { return false }
let focusedWorkspace = target.workspace
let prevMonitor = focusedWorkspace.workspaceMonitor
let sortedMonitors = sortedMonitors
guard let index = sortedMonitors.firstIndex(where: { $0.rect.topLeftCorner == prevMonitor.rect.topLeftCorner }) else { return false }
let targetMonitor = args.wrapAround
? sortedMonitors.get(wrappingIndex: args.target.val == .next ? index + 1 : index - 1)
: sortedMonitors.getOrNil(atIndex: args.target.val == .next ? index + 1 : index - 1)
guard let targetMonitor else { return false }

if targetMonitor.setActiveWorkspace(focusedWorkspace) {
let stubWorkspace = getStubWorkspace(for: prevMonitor)
check(prevMonitor.setActiveWorkspace(stubWorkspace),
"getStubWorkspace generated incompatible stub workspace (\(stubWorkspace)) for the monitor (\(prevMonitor)")
return true
} else {
return io.err("Can't move workspace '\(focusedWorkspace.name)' to monitor '\(targetMonitor.name)'. workspace-to-monitor-force-assignment doesn't allow it")
switch args.target.val.resolve(
target.workspace.workspaceMonitor, wrapAround: args.wrapAround)
{
case .success(let targetMonitor):
if targetMonitor.monitorId == prevMonitor.monitorId {
return true
}
if targetMonitor.setActiveWorkspace(focusedWorkspace) {
let stubWorkspace = getStubWorkspace(for: prevMonitor)
check(
prevMonitor.setActiveWorkspace(stubWorkspace),
"getStubWorkspace generated incompatible stub workspace (\(stubWorkspace)) for the monitor (\(prevMonitor)"
)
return true
} else {
return io.err(
"Can't move workspace '\(focusedWorkspace.name)' to monitor '\(targetMonitor.name)'. workspace-to-monitor-force-assignment doesn't allow it"
)
}
case .failure(let msg):
return io.err(msg)
}
}
}
2 changes: 1 addition & 1 deletion Sources/Cli/subcommandDescriptionsGenerated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ let subcommandDescriptions = [
[" move-mouse", "Move mouse to the requested position"],
[" move-node-to-monitor", "Move window to monitor targeted by relative direction, by order, or by pattern"],
[" move-node-to-workspace", "Move the focused window to the specified workspace"],
[" move-workspace-to-monitor", "Move the focused workspace to the next or previous monitor."],
[" move-workspace-to-monitor", "Move workspace to monitor targeted by relative direction, by order, or by pattern."],
[" move", "Move the focused window in the given direction"],
[" reload-config", "Reload currently active config"],
[" resize", "Resize the focused window"],
Expand Down
2 changes: 1 addition & 1 deletion Sources/Common/cmdArgs/cmdArgsManifest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func initSubcommands() -> [String: any SubCommandParserProtocol] {
case .moveNodeToWorkspace:
result[kind.rawValue] = SubCommandParser(parseMoveNodeToWorkspaceCmdArgs)
case .moveWorkspaceToMonitor:
result[kind.rawValue] = SubCommandParser(MoveWorkspaceToMonitorCmdArgs.init)
result[kind.rawValue] = SubCommandParser(parseWorkspaceToMonitorCmdArgs)
// deprecated
result["move-workspace-to-display"] = SubCommandParser(MoveWorkspaceToMonitorCmdArgs.init)
case .reloadConfig:
Expand Down
21 changes: 13 additions & 8 deletions Sources/Common/cmdArgs/impl/MoveWorkpsaceToMonitorCmdArgs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,23 @@ public struct MoveWorkspaceToMonitorCmdArgs: CmdArgs {
"--wrap-around": trueBoolFlag(\.wrapAround),
"--workspace": optionalWorkspaceFlag(),
],
arguments: [newArgParser(\.target, parseMonitorTarget, mandatoryArgPlaceholder: "(next|prev)")]
arguments: [
newArgParser(
\.target, parseTarget,
mandatoryArgPlaceholder: "(left|down|up|right|next|prev|<monitor-pattern>)"),
]
)

public var windowId: UInt32?
public var workspaceName: WorkspaceName?
public var wrapAround: Bool = false
public var target: Lateinit<MoveWorkspaceToMonitorCmdArgs.MonitorTarget> = .uninitialized
public enum MonitorTarget: String, CaseIterable {
case next, prev
}
public var target: Lateinit<MonitorTarget> = .uninitialized
}

private func parseMonitorTarget(arg: String, nextArgs: inout [String]) -> Parsed<MoveWorkspaceToMonitorCmdArgs.MonitorTarget> {
parseEnum(arg, MoveWorkspaceToMonitorCmdArgs.MonitorTarget.self)
public func parseWorkspaceToMonitorCmdArgs(_ args: [String]) -> ParsedCmd<
MoveWorkspaceToMonitorCmdArgs
> {
parseSpecificCmdArgs(MoveWorkspaceToMonitorCmdArgs(rawArgs: args), args)
.filter("--wrap-around is incompatible with <monitor-pattern> argument") {
$0.wrapAround.implies(!$0.target.val.isPatterns)
}
}
3 changes: 2 additions & 1 deletion Sources/Common/cmdHelpGenerated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ let move_node_to_workspace_help_generated = """
[--window-id <window-id>] <workspace-name>
"""
let move_workspace_to_monitor_help_generated = """
USAGE: move-workspace-to-monitor [-h|--help] [--workspace <workspace>] [--wrap-around] (next|prev)
USAGE: move-workspace-to-monitor [-h|--help] [--workspace <workspace>] [--wrap-around] (left|down|up|right|next|prev)
OR: move-workspace-to-monitor [-h|--help] [--workspace <workspace>] <monitor-pattern>...
"""
let move_help_generated = """
USAGE: move [-h|--help] [--window-id <window-id>] (left|down|up|right)
Expand Down
12 changes: 10 additions & 2 deletions docs/aerospace-move-workspace-to-monitor.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
include::util/man-attributes.adoc[]
:manname: aerospace-move-workspace-to-monitor
// tag::purpose[]
:manpurpose: Move the focused workspace to the next or previous monitor.
:manpurpose: Move workspace to monitor targeted by relative direction, by order, or by pattern.
// end::purpose[]

// =========================================================== Synopsis
== Synopsis
[verse]
// tag::synopsis[]
aerospace move-workspace-to-monitor [-h|--help] [--workspace <workspace>] [--wrap-around] (next|prev)
aerospace move-workspace-to-monitor [-h|--help] [--workspace <workspace>] [--wrap-around] (left|down|up|right|next|prev)
aerospace move-workspace-to-monitor [-h|--help] [--workspace <workspace>] <monitor-pattern>...

// end::synopsis[]

Expand All @@ -34,10 +35,17 @@ include::./util/workspace-flag-desc.adoc[]
// =========================================================== Arguments
include::./util/conditional-arguments-header.adoc[]

(left|down|up|right)::
Move workspace to monitor in direction relative to the focused monitor

(next|prev)::
Move the workspace to next or prev monitor.
'next' or 'prev' monitor is calculated relative to the monitor `<workspace>` currently belongs to.

<monitor-pattern>::
Find the first monitor pattern in the list that doesn't describe the current monitor and move the workspace to the appropriate monitor.
Monitor pattern is the same as in `workspace-to-monitor-force-assignment` config option

// end::body[]

// =========================================================== Footer
Expand Down

0 comments on commit 9125a7d

Please sign in to comment.