macos: add key binding for equalizing split sizes

This commit is contained in:
Gregory Anders
2023-11-07 16:15:46 -06:00
parent 36dd5ef4ee
commit cd01340cce
12 changed files with 103 additions and 4 deletions

View File

@@ -38,6 +38,7 @@ class AppDelegate: NSObject, ObservableObject, NSApplicationDelegate, GhosttyApp
@IBOutlet private var menuResetFontSize: NSMenuItem?
@IBOutlet private var menuTerminalInspector: NSMenuItem?
@IBOutlet private var menuEqualizeSplits: NSMenuItem?
@IBOutlet private var menuMoveSplitDividerUp: NSMenuItem?
@IBOutlet private var menuMoveSplitDividerDown: NSMenuItem?
@IBOutlet private var menuMoveSplitDividerLeft: NSMenuItem?
@@ -215,6 +216,7 @@ class AppDelegate: NSObject, ObservableObject, NSApplicationDelegate, GhosttyApp
syncMenuShortcut(action: "resize_split:down,10", menuItem: self.menuMoveSplitDividerDown)
syncMenuShortcut(action: "resize_split:right,10", menuItem: self.menuMoveSplitDividerRight)
syncMenuShortcut(action: "resize_split:left,10", menuItem: self.menuMoveSplitDividerLeft)
syncMenuShortcut(action: "equalize_splits", menuItem: self.menuEqualizeSplits)
syncMenuShortcut(action: "increase_font_size:1", menuItem: self.menuIncreaseFontSize)
syncMenuShortcut(action: "decrease_font_size:1", menuItem: self.menuDecreaseFontSize)

View File

@@ -271,6 +271,11 @@ class TerminalController: NSWindowController, NSWindowDelegate,
splitMoveFocus(direction: .right)
}
@IBAction func equalizeSplits(_ sender: Any) {
guard let surface = focusedSurface?.surface else { return }
ghostty.splitEqualize(surface: surface)
}
@IBAction func moveSplitDividerUp(_ sender: Any) {
guard let surface = focusedSurface?.surface else { return }
ghostty.splitResize(surface: surface, direction: .up, amount: 10)

View File

@@ -160,6 +160,8 @@ extension Ghostty {
focus_split_cb: { userdata, direction in AppState.focusSplit(userdata, direction: direction) },
resize_split_cb: { userdata, direction, amount in
AppState.resizeSplit(userdata, direction: direction, amount: amount) },
equalize_splits_cb: { userdata in
AppState.equalizeSplits(userdata) },
toggle_split_zoom_cb: { userdata in AppState.toggleSplitZoom(userdata) },
goto_tab_cb: { userdata, n in AppState.gotoTab(userdata, n: n) },
toggle_fullscreen_cb: { userdata, nonNativeFullscreen in AppState.toggleFullscreen(userdata, nonNativeFullscreen: nonNativeFullscreen) },
@@ -298,6 +300,10 @@ extension Ghostty {
ghostty_surface_split_resize(surface, direction.toNative(), amount)
}
func splitEqualize(surface: ghostty_surface_t) {
ghostty_surface_split_equalize(surface)
}
func splitToggleZoom(surface: ghostty_surface_t) {
let action = "toggle_split_zoom"
if (!ghostty_surface_binding_action(surface, action, UInt(action.count))) {
@@ -383,6 +389,11 @@ extension Ghostty {
)
}
static func equalizeSplits(_ userdata: UnsafeMutableRawPointer?) {
guard let surface = self.surfaceUserdata(from: userdata) else { return }
NotificationCenter.default.post(name: Notification.didEqualizeSplits, object: surface)
}
static func toggleSplitZoom(_ userdata: UnsafeMutableRawPointer?) {
guard let surface = self.surfaceUserdata(from: userdata) else { return }

View File

@@ -171,7 +171,31 @@ extension Ghostty {
}
}
/// Equalize the splits in this container. Each split is equalized
/// based on its weight, i.e. the number of leaves it contains.
/// This function returns the weight of this container.
func equalize() -> UInt {
let topLeftWeight: UInt
switch (topLeft) {
case .leaf:
topLeftWeight = 1
case .split(let c):
topLeftWeight = c.equalize()
}
let bottomRightWeight: UInt
switch (bottomRight) {
case .leaf:
bottomRightWeight = 1
case .split(let c):
bottomRightWeight = c.equalize()
}
let weight = topLeftWeight + bottomRightWeight
split = Double(topLeftWeight) / Double(weight)
return weight
}
// MARK: - Hashable
func hash(into hasher: inout Hasher) {

View File

@@ -50,6 +50,7 @@ extension Ghostty {
var body: some View {
let center = NotificationCenter.default
let pubZoom = center.publisher(for: Notification.didToggleSplitZoom)
let pubEqualize = center.publisher(for: Notification.didEqualizeSplits)
// If we're zoomed, we don't render anything, we are transparent. This
// ensures that the View stays around so we don't lose our state, but
@@ -75,6 +76,7 @@ extension Ghostty {
container: container
)
.onReceive(pubZoom) { onZoom(notification: $0) }
.onReceive(pubEqualize) { onEqualize(notification: $0) }
}
}
.navigationTitle(surfaceTitle ?? "Ghostty")
@@ -135,8 +137,18 @@ extension Ghostty {
}
}
}
func onEqualize(notification: SwiftUI.Notification) {
// If there are no splits then there is nothing to do
switch (node) {
case .split(let c):
_ = c.equalize()
default:
return
}
}
}
/// A noSplit leaf node of a split tree.
private struct TerminalSplitLeaf: View {
/// The leaf to draw the surface for.

View File

@@ -150,6 +150,9 @@ extension Ghostty.Notification {
static let didResizeSplit = Notification.Name("com.mitchellh.ghostty.didResizeSplit")
static let ResizeSplitDirectionKey = didResizeSplit.rawValue + ".direction"
static let ResizeSplitAmountKey = didResizeSplit.rawValue + ".amount"
/// Notification sent to the split root to equalize split sizes
static let didEqualizeSplits = Notification.Name("com.mitchellh.ghostty.didEqualizeSplits")
}
// Make the input enum hashable.

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22155" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22154" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22155"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22154"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
@@ -18,6 +18,7 @@
<outlet property="menuCloseWindow" destination="W5w-UZ-crk" id="6ff-BT-ENV"/>
<outlet property="menuCopy" destination="Jqf-pv-Zcu" id="bKd-1C-oy9"/>
<outlet property="menuDecreaseFontSize" destination="kzb-SZ-dOA" id="Y1B-Vh-6Z2"/>
<outlet property="menuEqualizeSplits" destination="3gH-VD-vL9" id="SiZ-ce-FOF"/>
<outlet property="menuIncreaseFontSize" destination="CIH-ey-Z6x" id="hkc-9C-80E"/>
<outlet property="menuMoveSplitDividerDown" destination="Zj7-2W-fdF" id="997-LL-nlN"/>
<outlet property="menuMoveSplitDividerLeft" destination="wSR-ny-j1a" id="HCZ-CI-2ob"/>
@@ -270,6 +271,13 @@
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Resize Split" id="t7T-Ti-0im">
<items>
<menuItem title="Equalize Splits" id="3gH-VD-vL9">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="equalizeSplits:" target="-1" id="RE0-hS-YLf"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="XKA-Jd-h9t"/>
<menuItem title="Move Divider Up" id="h9Y-40-3oo">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>