From 1b0cf70d774da1316960ab0044c4ec5ab9f8df41 Mon Sep 17 00:00:00 2001 From: Ivan Duran Date: Sun, 10 Nov 2024 09:49:58 +0300 Subject: [PATCH] Add custom size splits in macOS --- include/ghostty.h | 14 +++++++++++--- .../Features/Terminal/BaseTerminalController.swift | 4 ++-- macos/Sources/Ghostty/Ghostty.App.swift | 11 ++++++----- macos/Sources/Ghostty/Ghostty.TerminalSplit.swift | 7 ++++++- macos/Sources/Ghostty/SurfaceView_AppKit.swift | 4 ++-- src/apprt/embedded.zig | 9 +++++++-- 6 files changed, 34 insertions(+), 15 deletions(-) diff --git a/include/ghostty.h b/include/ghostty.h index f4836f210..2b28c6cc7 100644 --- a/include/ghostty.h +++ b/include/ghostty.h @@ -348,7 +348,7 @@ typedef struct { ghostty_target_u target; } ghostty_target_s; -// apprt.action.SplitDirection +// apprt.action.SplitDirection.direction typedef enum { GHOSTTY_SPLIT_DIRECTION_RIGHT, GHOSTTY_SPLIT_DIRECTION_DOWN, @@ -356,6 +356,12 @@ typedef enum { GHOSTTY_SPLIT_DIRECTION_UP, } ghostty_action_split_direction_e; +// apprt.action.SplitDirection +typedef struct { + float percent; + ghostty_action_split_direction_e direction; +} ghostty_action_split_s; + // apprt.action.GotoSplit typedef enum { GHOSTTY_GOTO_SPLIT_PREVIOUS, @@ -564,7 +570,7 @@ typedef enum { } ghostty_action_tag_e; typedef union { - ghostty_action_split_direction_e new_split; + ghostty_action_split_s new_split; ghostty_action_fullscreen_e toggle_fullscreen; ghostty_action_move_tab_s move_tab; ghostty_action_goto_tab_e goto_tab; @@ -693,7 +699,9 @@ void ghostty_surface_mouse_scroll(ghostty_surface_t, void ghostty_surface_mouse_pressure(ghostty_surface_t, uint32_t, double); void ghostty_surface_ime_point(ghostty_surface_t, double*, double*); void ghostty_surface_request_close(ghostty_surface_t); -void ghostty_surface_split(ghostty_surface_t, ghostty_action_split_direction_e); +void ghostty_surface_split(ghostty_surface_t, + ghostty_action_split_direction_e, + float); void ghostty_surface_split_focus(ghostty_surface_t, ghostty_action_goto_split_e); void ghostty_surface_split_resize(ghostty_surface_t, diff --git a/macos/Sources/Features/Terminal/BaseTerminalController.swift b/macos/Sources/Features/Terminal/BaseTerminalController.swift index 000d72418..ca03e17f7 100644 --- a/macos/Sources/Features/Terminal/BaseTerminalController.swift +++ b/macos/Sources/Features/Terminal/BaseTerminalController.swift @@ -476,12 +476,12 @@ class BaseTerminalController: NSWindowController, @IBAction func splitRight(_ sender: Any) { guard let surface = focusedSurface?.surface else { return } - ghostty.split(surface: surface, direction: GHOSTTY_SPLIT_DIRECTION_RIGHT) + ghostty.split(surface: surface, direction: GHOSTTY_SPLIT_DIRECTION_RIGHT, percent: 0.5) } @IBAction func splitDown(_ sender: Any) { guard let surface = focusedSurface?.surface else { return } - ghostty.split(surface: surface, direction: GHOSTTY_SPLIT_DIRECTION_DOWN) + ghostty.split(surface: surface, direction: GHOSTTY_SPLIT_DIRECTION_DOWN, percent: 0.5) } @IBAction func splitZoom(_ sender: Any) { diff --git a/macos/Sources/Ghostty/Ghostty.App.swift b/macos/Sources/Ghostty/Ghostty.App.swift index 07acf0f91..7019e9504 100644 --- a/macos/Sources/Ghostty/Ghostty.App.swift +++ b/macos/Sources/Ghostty/Ghostty.App.swift @@ -170,8 +170,8 @@ extension Ghostty { } } - func split(surface: ghostty_surface_t, direction: ghostty_action_split_direction_e) { - ghostty_surface_split(surface, direction) + func split(surface: ghostty_surface_t, direction: ghostty_action_split_direction_e, percent: Float) { + ghostty_surface_split(surface, direction, percent) } func splitMoveFocus(surface: ghostty_surface_t, direction: SplitFocusDirection) { @@ -453,7 +453,7 @@ extension Ghostty { newTab(app, target: target) case GHOSTTY_ACTION_NEW_SPLIT: - newSplit(app, target: target, direction: action.action.new_split) + newSplit(app, target: target, split: action.action.new_split) case GHOSTTY_ACTION_TOGGLE_FULLSCREEN: toggleFullscreen(app, target: target, mode: action.action.toggle_fullscreen) @@ -607,7 +607,7 @@ extension Ghostty { private static func newSplit( _ app: ghostty_app_t, target: ghostty_target_s, - direction: ghostty_action_split_direction_e) { + split: ghostty_action_split_s) { switch (target.tag) { case GHOSTTY_TARGET_APP: // New split does nothing with an app target @@ -622,7 +622,8 @@ extension Ghostty { name: Notification.ghosttyNewSplit, object: surfaceView, userInfo: [ - "direction": direction, + "direction": split.direction, + "percent": split.percent, Notification.NewSurfaceConfigKey: SurfaceConfiguration(from: ghostty_surface_inherited_config(surface)), ] ) diff --git a/macos/Sources/Ghostty/Ghostty.TerminalSplit.swift b/macos/Sources/Ghostty/Ghostty.TerminalSplit.swift index d4f82620c..3c55e789d 100644 --- a/macos/Sources/Ghostty/Ghostty.TerminalSplit.swift +++ b/macos/Sources/Ghostty/Ghostty.TerminalSplit.swift @@ -217,9 +217,11 @@ extension Ghostty { let configAny = notification.userInfo?[Ghostty.Notification.NewSurfaceConfigKey] let config = configAny as? SurfaceConfiguration - // Determine our desired direction + // Determine our desired direction and percent guard let directionAny = notification.userInfo?["direction"] else { return } guard let direction = directionAny as? ghostty_action_split_direction_e else { return } + guard let percentAny = notification.userInfo?["percent"] else { return } + guard let percent = percentAny as? Float else { return } let splitDirection: SplitViewDirection let swap: Bool switch (direction) { @@ -243,6 +245,9 @@ extension Ghostty { // Setup our new container since we are now split let container = SplitNode.Container(from: leaf, direction: splitDirection, baseConfig: config) + // Set the split ratio + container.split = 1.0 - CGFloat(percent) + // Change the parent node. This will trigger the parent to relayout our views. node = .split(container) diff --git a/macos/Sources/Ghostty/SurfaceView_AppKit.swift b/macos/Sources/Ghostty/SurfaceView_AppKit.swift index 872ce17ec..40dea9784 100644 --- a/macos/Sources/Ghostty/SurfaceView_AppKit.swift +++ b/macos/Sources/Ghostty/SurfaceView_AppKit.swift @@ -963,12 +963,12 @@ extension Ghostty { @IBAction func splitRight(_ sender: Any) { guard let surface = self.surface else { return } - ghostty_surface_split(surface, GHOSTTY_SPLIT_DIRECTION_RIGHT) + ghostty_surface_split(surface, GHOSTTY_SPLIT_DIRECTION_RIGHT, 0.5) } @IBAction func splitDown(_ sender: Any) { guard let surface = self.surface else { return } - ghostty_surface_split(surface, GHOSTTY_SPLIT_DIRECTION_DOWN) + ghostty_surface_split(surface, GHOSTTY_SPLIT_DIRECTION_DOWN, 0.5) } @objc func resetTerminal(_ sender: Any) { diff --git a/src/apprt/embedded.zig b/src/apprt/embedded.zig index 4d45166aa..ce6e6491f 100644 --- a/src/apprt/embedded.zig +++ b/src/apprt/embedded.zig @@ -1634,11 +1634,16 @@ pub const CAPI = struct { } /// Request that the surface split in the given direction. - export fn ghostty_surface_split(ptr: *Surface, direction: apprt.action.SplitDirection) void { + export fn ghostty_surface_split(ptr: *Surface, direction: apprt.action.SplitDirection.Direction, percent: f32) void { + const split_direction = apprt.action.SplitDirection{ + .direction = direction, + .percent = percent, + }; + ptr.app.performAction( .{ .surface = &ptr.core_surface }, .new_split, - direction, + split_direction, ) catch |err| { log.err("error creating new split err={}", .{err}); return;