Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ extension ShortcutAction {
case .prevSurface: return ShortcutStroke(key: "[", command: true, shift: true)
case .moveSurfaceLeft: return ShortcutStroke(key: "[", command: true, shift: true, option: true)
case .moveSurfaceRight: return ShortcutStroke(key: "]", command: true, shift: true, option: true)
case .moveSurfaceToPreviousPane, .moveSurfaceToNextPane,
.moveSurfaceToPaneLeft, .moveSurfaceToPaneRight,
.moveSurfaceToPaneUp, .moveSurfaceToPaneDown:
return nil
case .selectSurfaceByNumber: return ShortcutStroke(key: "1", control: true)
case .selectWorkspaceByNumber: return ShortcutStroke(key: "1", command: true)
case .moveWorkspaceUp: return ShortcutStroke(key: "[", command: true, option: true, control: true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ public enum ShortcutAction: String, CaseIterable, Sendable, Hashable, SettingCod
case moveSurfaceLeft
/// Moves the selected surface one position right.
case moveSurfaceRight
/// Moves the selected surface to the previous pane in spatial order.
case moveSurfaceToPreviousPane
/// Moves the selected surface to the next pane in spatial order.
case moveSurfaceToNextPane
case moveSurfaceToPaneLeft
case moveSurfaceToPaneRight
case moveSurfaceToPaneUp
case moveSurfaceToPaneDown
case selectSurfaceByNumber
case nextSidebarTab
case prevSidebarTab
Expand Down Expand Up @@ -186,7 +194,10 @@ extension ShortcutAction {
.switchRightSidebarToSessions, .switchRightSidebarToFeed,
.switchRightSidebarToDock, .triggerFlash:
return .workspace
case .nextSurface, .prevSurface, .moveSurfaceLeft, .moveSurfaceRight, .selectSurfaceByNumber,
case .nextSurface, .prevSurface, .moveSurfaceLeft, .moveSurfaceRight,
.moveSurfaceToPreviousPane, .moveSurfaceToNextPane,
.moveSurfaceToPaneLeft, .moveSurfaceToPaneRight, .moveSurfaceToPaneUp, .moveSurfaceToPaneDown,
.selectSurfaceByNumber,
.nextSidebarTab, .prevSidebarTab, .moveWorkspaceUp, .moveWorkspaceDown, .focusHistoryBack, .focusHistoryForward,
.selectWorkspaceByNumber, .renameTab, .renameWorkspace,
.editWorkspaceDescription, .markWorkspaceDone, .cycleWorkspaceStatus, .toggleChecklistItemComplete, .closeTab, .closeOtherTabsInPane, .closeWorkspace,
Expand Down Expand Up @@ -360,8 +371,14 @@ extension ShortcutAction {
case .triggerFlash: return "Flash Focused Panel"
case .nextSurface: return "Next Surface"
case .prevSurface: return "Previous Surface"
case .moveSurfaceLeft: return String(localized: "shortcut.moveSurfaceLeft.label", defaultValue: "Move Surface Left")
case .moveSurfaceRight: return String(localized: "shortcut.moveSurfaceRight.label", defaultValue: "Move Surface Right")
case .moveSurfaceLeft: return String(localized: "shortcut.moveSurfaceLeft.label", defaultValue: "Reorder Surface Left")
case .moveSurfaceRight: return String(localized: "shortcut.moveSurfaceRight.label", defaultValue: "Reorder Surface Right")
case .moveSurfaceToPreviousPane: return String(localized: "shortcut.moveSurfaceToPreviousPane.label", defaultValue: "Move Surface to Previous Pane")
case .moveSurfaceToNextPane: return String(localized: "shortcut.moveSurfaceToNextPane.label", defaultValue: "Move Surface to Next Pane")
case .moveSurfaceToPaneLeft: return String(localized: "shortcut.moveSurfaceToPaneLeft.label", defaultValue: "Move Surface to Pane on Left")
case .moveSurfaceToPaneRight: return String(localized: "shortcut.moveSurfaceToPaneRight.label", defaultValue: "Move Surface to Pane on Right")
case .moveSurfaceToPaneUp: return String(localized: "shortcut.moveSurfaceToPaneUp.label", defaultValue: "Move Surface to Pane Above")
case .moveSurfaceToPaneDown: return String(localized: "shortcut.moveSurfaceToPaneDown.label", defaultValue: "Move Surface to Pane Below")
case .selectSurfaceByNumber: return "Select Surface 1…9"
case .nextSidebarTab: return "Next Workspace"
case .prevSidebarTab: return "Previous Workspace"
Expand Down
110 changes: 106 additions & 4 deletions Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -196267,13 +196267,13 @@
"en": {
"stringUnit": {
"state": "translated",
"value": "Move Surface Left"
"value": "Reorder Surface Left"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "サーフェスを左へ移動"
"value": "サーフェスを左へ並べ替え"
}
}
}
Expand All @@ -196284,13 +196284,115 @@
"en": {
"stringUnit": {
"state": "translated",
"value": "Move Surface Right"
"value": "Reorder Surface Right"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "サーフェスを右へ移動"
"value": "サーフェスを右へ並べ替え"
}
}
}
},
"shortcut.moveSurfaceToNextPane.label": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Move Surface to Next Pane"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "サーフェスを次のペインへ移動"
}
}
}
},
"shortcut.moveSurfaceToPaneDown.label": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Move Surface to Pane Below"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "サーフェスを下のペインへ移動"
}
}
}
},
"shortcut.moveSurfaceToPaneLeft.label": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Move Surface to Pane on Left"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "サーフェスを左のペインへ移動"
}
}
}
},
"shortcut.moveSurfaceToPaneRight.label": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Move Surface to Pane on Right"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "サーフェスを右のペインへ移動"
}
}
}
},
"shortcut.moveSurfaceToPaneUp.label": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Move Surface to Pane Above"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "サーフェスを上のペインへ移動"
}
}
}
},
"shortcut.moveSurfaceToPreviousPane.label": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Move Surface to Previous Pane"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "サーフェスを前のペインへ移動"
}
}
}
Expand Down
64 changes: 58 additions & 6 deletions Sources/AppDelegate+AdjacentNavigationShortcut.swift
Original file line number Diff line number Diff line change
@@ -1,37 +1,89 @@
import AppKit
import Bonsplit

extension AppDelegate {
/// Routes adjacent surface navigation and surface/workspace reordering through
/// the main-window context selected for the key event.
func handleAdjacentNavigationShortcut(event: NSEvent) -> Bool {
let routedTabManager = preferredMainWindowContextForShortcutRouting(event: event)?.tabManager
?? tabManager
if matchConfiguredShortcut(event: event, action: .nextSurface) {
if performFocusedDockShortcut(.selectNextSurface, event: event) { return true }
(preferredMainWindowContextForShortcutRouting(event: event)?.tabManager ?? tabManager)?.selectNextSurface()
routedTabManager?.selectNextSurface()
return true
}
if matchConfiguredShortcut(event: event, action: .prevSurface) {
if performFocusedDockShortcut(.selectPreviousSurface, event: event) { return true }
(preferredMainWindowContextForShortcutRouting(event: event)?.tabManager ?? tabManager)?.selectPreviousSurface()
routedTabManager?.selectPreviousSurface()
return true
}
if matchConfiguredShortcut(event: event, action: .moveSurfaceLeft) {
if performFocusedDockShortcut(.moveSurface(offset: -1), event: event) { return true }
(preferredMainWindowContextForShortcutRouting(event: event)?.tabManager ?? tabManager)?.selectedWorkspace?.moveSelectedSurface(by: -1)
routedTabManager?.selectedWorkspace?.moveSelectedSurface(by: -1)
return true
}
if matchConfiguredShortcut(event: event, action: .moveSurfaceRight) {
if performFocusedDockShortcut(.moveSurface(offset: 1), event: event) { return true }
(preferredMainWindowContextForShortcutRouting(event: event)?.tabManager ?? tabManager)?.selectedWorkspace?.moveSelectedSurface(by: 1)
routedTabManager?.selectedWorkspace?.moveSelectedSurface(by: 1)
return true
}
if matchConfiguredDirectionalShortcut(
event: event,
action: .moveSurfaceToPreviousPane,
arrowGlyph: "←",
arrowKeyCode: 123
) {
performSurfacePaneMoveShortcut(event: event) {
routedTabManager?.moveSelectedSurfaceToPane(offset: -1) == true
}
return true
}
if matchConfiguredDirectionalShortcut(
event: event,
action: .moveSurfaceToNextPane,
arrowGlyph: "→",
arrowKeyCode: 124
) {
performSurfacePaneMoveShortcut(event: event) {
routedTabManager?.moveSelectedSurfaceToPane(offset: 1) == true
}
return true
}
let directionalPaneMoveActions: [(KeyboardShortcutSettings.Action, NavigationDirection, String, UInt16)] = [
(.moveSurfaceToPaneLeft, .left, "←", 123),
(.moveSurfaceToPaneRight, .right, "→", 124),
(.moveSurfaceToPaneUp, .up, "↑", 126),
(.moveSurfaceToPaneDown, .down, "↓", 125),
]
for (action, direction, arrowGlyph, arrowKeyCode) in directionalPaneMoveActions {
if matchConfiguredDirectionalShortcut(
event: event,
action: action,
arrowGlyph: arrowGlyph,
arrowKeyCode: arrowKeyCode
) {
performSurfacePaneMoveShortcut(event: event) {
routedTabManager?.moveSelectedSurfaceToAdjacentPane(direction) == true
}
return true
}
}
if matchConfiguredShortcut(event: event, action: .moveWorkspaceUp) {
(preferredMainWindowContextForShortcutRouting(event: event)?.tabManager ?? tabManager)?.moveSelectedWorkspace(by: -1)
routedTabManager?.moveSelectedWorkspace(by: -1)
return true
}
if matchConfiguredShortcut(event: event, action: .moveWorkspaceDown) {
(preferredMainWindowContextForShortcutRouting(event: event)?.tabManager ?? tabManager)?.moveSelectedWorkspace(by: 1)
routedTabManager?.moveSelectedWorkspace(by: 1)
return true
}
return false
}

private func performSurfacePaneMoveShortcut(event: NSEvent, operation: () -> Bool) {
guard focusedDockStoreForShortcut(preferredWindow: event.window) == nil,
operation() else {
NSSound.beep()
return
}
}
}
12 changes: 12 additions & 0 deletions Sources/ContentView+RightSidebarCommandPalette.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ extension ContentView {
return .nextSurface
case "palette.previousTabInPane":
return .prevSurface
case "palette.moveSurfaceToPreviousPane":
return .moveSurfaceToPreviousPane
case "palette.moveSurfaceToNextPane":
return .moveSurfaceToNextPane
case "palette.moveSurfaceToPaneLeft":
return .moveSurfaceToPaneLeft
case "palette.moveSurfaceToPaneRight":
return .moveSurfaceToPaneRight
case "palette.moveSurfaceToPaneUp":
return .moveSurfaceToPaneUp
case "palette.moveSurfaceToPaneDown":
return .moveSurfaceToPaneDown
case "palette.browserToggleDevTools":
return .toggleBrowserDeveloperTools
case "palette.browserConsole":
Expand Down
82 changes: 82 additions & 0 deletions Sources/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7476,6 +7476,52 @@ struct ContentView: View {
when: { $0.bool(CommandPaletteContextKeys.hasFocusedPanel) }
)
)
let paneMoveSubtitle = constant(
String(localized: "shortcutDiscovery.section.navigation", defaultValue: "Navigation")
)
let paneMoveCommands: [(id: String, title: String, keywords: [String])] = [
(
"palette.moveSurfaceToPreviousPane",
String(localized: "shortcut.moveSurfaceToPreviousPane.label", defaultValue: "Move Surface to Previous Pane"),
["move", "surface", "tab", "previous", "pane"]
),
(
"palette.moveSurfaceToNextPane",
String(localized: "shortcut.moveSurfaceToNextPane.label", defaultValue: "Move Surface to Next Pane"),
["move", "surface", "tab", "next", "pane"]
),
(
"palette.moveSurfaceToPaneLeft",
String(localized: "shortcut.moveSurfaceToPaneLeft.label", defaultValue: "Move Surface to Pane on Left"),
["move", "surface", "tab", "left", "pane"]
),
(
"palette.moveSurfaceToPaneRight",
String(localized: "shortcut.moveSurfaceToPaneRight.label", defaultValue: "Move Surface to Pane on Right"),
["move", "surface", "tab", "right", "pane"]
),
(
"palette.moveSurfaceToPaneUp",
String(localized: "shortcut.moveSurfaceToPaneUp.label", defaultValue: "Move Surface to Pane Above"),
["move", "surface", "tab", "up", "above", "upper", "pane"]
),
(
"palette.moveSurfaceToPaneDown",
String(localized: "shortcut.moveSurfaceToPaneDown.label", defaultValue: "Move Surface to Pane Below"),
["move", "surface", "tab", "down", "below", "lower", "pane"]
),
]
for command in paneMoveCommands {
contributions.append(
CommandPaletteCommandContribution(
commandId: command.id,
title: constant(command.title),
subtitle: paneMoveSubtitle,
keywords: command.keywords,
when: { $0.bool(CommandPaletteContextKeys.hasFocusedPanel) }
)
)
}

contributions.append(
CommandPaletteCommandContribution(
Expand Down Expand Up @@ -8457,6 +8503,42 @@ struct ContentView: View {
registry.register(commandId: "palette.previousTabInPane") {
tabManager.selectPreviousSurface()
}
registry.register(commandId: "palette.moveSurfaceToPreviousPane") {
guard tabManager.moveSelectedSurfaceToPane(offset: -1) else {
NSSound.beep()
return
}
}
registry.register(commandId: "palette.moveSurfaceToNextPane") {
guard tabManager.moveSelectedSurfaceToPane(offset: 1) else {
NSSound.beep()
return
}
}
registry.register(commandId: "palette.moveSurfaceToPaneLeft") {
guard tabManager.moveSelectedSurfaceToAdjacentPane(.left) else {
NSSound.beep()
return
}
}
registry.register(commandId: "palette.moveSurfaceToPaneRight") {
guard tabManager.moveSelectedSurfaceToAdjacentPane(.right) else {
NSSound.beep()
return
}
}
registry.register(commandId: "palette.moveSurfaceToPaneUp") {
guard tabManager.moveSelectedSurfaceToAdjacentPane(.up) else {
NSSound.beep()
return
}
}
registry.register(commandId: "palette.moveSurfaceToPaneDown") {
guard tabManager.moveSelectedSurfaceToAdjacentPane(.down) else {
NSSound.beep()
return
}
}
registry.register(commandId: "palette.openWorkspacePullRequests") {
DispatchQueue.main.async {
if !openWorkspacePullRequestsInConfiguredBrowser() {
Expand Down
Loading