mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
macos: change focus callback to use an enum so we can get other dirs
This commit is contained in:
@ -32,8 +32,7 @@ typedef const char* (*ghostty_runtime_read_clipboard_cb)(void *);
|
|||||||
typedef void (*ghostty_runtime_write_clipboard_cb)(void *, const char *);
|
typedef void (*ghostty_runtime_write_clipboard_cb)(void *, const char *);
|
||||||
typedef void (*ghostty_runtime_new_split_cb)(void *, ghostty_split_direction_e);
|
typedef void (*ghostty_runtime_new_split_cb)(void *, ghostty_split_direction_e);
|
||||||
typedef void (*ghostty_runtime_close_surface_cb)(void *);
|
typedef void (*ghostty_runtime_close_surface_cb)(void *);
|
||||||
typedef void (*ghostty_runtime_focus_next_split_cb)(void *);
|
typedef void (*ghostty_runtime_focus_split_cb)(void *, ghostty_split_focus_direction_e);
|
||||||
typedef void (*ghostty_runtime_focus_previous_split_cb)(void *);
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *userdata;
|
void *userdata;
|
||||||
@ -43,8 +42,7 @@ typedef struct {
|
|||||||
ghostty_runtime_write_clipboard_cb write_clipboard_cb;
|
ghostty_runtime_write_clipboard_cb write_clipboard_cb;
|
||||||
ghostty_runtime_new_split_cb new_split_cb;
|
ghostty_runtime_new_split_cb new_split_cb;
|
||||||
ghostty_runtime_close_surface_cb close_surface_cb;
|
ghostty_runtime_close_surface_cb close_surface_cb;
|
||||||
ghostty_runtime_focus_next_split_cb focus_next_split_cb;
|
ghostty_runtime_focus_split_cb focus_split_cb;
|
||||||
ghostty_runtime_focus_previous_split_cb focus_previous_split_cb;
|
|
||||||
} ghostty_runtime_config_s;
|
} ghostty_runtime_config_s;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -58,6 +56,15 @@ typedef enum {
|
|||||||
GHOSTTY_SPLIT_DOWN
|
GHOSTTY_SPLIT_DOWN
|
||||||
} ghostty_split_direction_e;
|
} ghostty_split_direction_e;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GHOSTTY_SPLIT_FOCUS_PREVIOUS,
|
||||||
|
GHOSTTY_SPLIT_FOCUS_NEXT,
|
||||||
|
GHOSTTY_SPLIT_FOCUS_TOP,
|
||||||
|
GHOSTTY_SPLIT_FOCUS_LEFT,
|
||||||
|
GHOSTTY_SPLIT_FOCUS_BOTTOM,
|
||||||
|
GHOSTTY_SPLIT_FOCUS_RIGHT,
|
||||||
|
} ghostty_split_focus_direction_e;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GHOSTTY_MOUSE_RELEASE,
|
GHOSTTY_MOUSE_RELEASE,
|
||||||
GHOSTTY_MOUSE_PRESS,
|
GHOSTTY_MOUSE_PRESS,
|
||||||
@ -258,8 +265,7 @@ void ghostty_surface_mouse_scroll(ghostty_surface_t, double, double);
|
|||||||
void ghostty_surface_ime_point(ghostty_surface_t, double *, double *);
|
void ghostty_surface_ime_point(ghostty_surface_t, double *, double *);
|
||||||
void ghostty_surface_request_close(ghostty_surface_t);
|
void ghostty_surface_request_close(ghostty_surface_t);
|
||||||
void ghostty_surface_split(ghostty_surface_t, ghostty_split_direction_e);
|
void ghostty_surface_split(ghostty_surface_t, ghostty_split_direction_e);
|
||||||
void ghostty_surface_split_focus_previous(ghostty_surface_t);
|
void ghostty_surface_split_focus(ghostty_surface_t, ghostty_split_focus_direction_e);
|
||||||
void ghostty_surface_split_focus_next(ghostty_surface_t);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -59,8 +59,8 @@ extension Ghostty {
|
|||||||
write_clipboard_cb: { userdata, str in AppState.writeClipboard(userdata, string: str) },
|
write_clipboard_cb: { userdata, str in AppState.writeClipboard(userdata, string: str) },
|
||||||
new_split_cb: { userdata, direction in AppState.newSplit(userdata, direction: ghostty_split_direction_e(UInt32(direction))) },
|
new_split_cb: { userdata, direction in AppState.newSplit(userdata, direction: ghostty_split_direction_e(UInt32(direction))) },
|
||||||
close_surface_cb: { userdata in AppState.closeSurface(userdata) },
|
close_surface_cb: { userdata in AppState.closeSurface(userdata) },
|
||||||
focus_next_split_cb: { userdata in AppState.focusSplit(userdata, direction: .next) },
|
focus_split_cb: { userdata, direction in
|
||||||
focus_previous_split_cb: { userdata in AppState.focusSplit(userdata, direction: .previous) }
|
AppState.focusSplit(userdata, direction: ghostty_split_focus_direction_e(UInt32(direction))) }
|
||||||
)
|
)
|
||||||
|
|
||||||
// Create the ghostty app.
|
// Create the ghostty app.
|
||||||
@ -95,13 +95,7 @@ extension Ghostty {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func splitMoveFocus(surface: ghostty_surface_t, direction: SplitFocusDirection) {
|
func splitMoveFocus(surface: ghostty_surface_t, direction: SplitFocusDirection) {
|
||||||
switch (direction) {
|
ghostty_surface_split_focus(surface, direction.toNative())
|
||||||
case .previous:
|
|
||||||
ghostty_surface_split_focus_previous(surface)
|
|
||||||
|
|
||||||
case .next:
|
|
||||||
ghostty_surface_split_focus_next(surface)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Ghostty Callbacks
|
// MARK: Ghostty Callbacks
|
||||||
@ -118,13 +112,14 @@ extension Ghostty {
|
|||||||
NotificationCenter.default.post(name: Notification.ghosttyCloseSurface, object: surface)
|
NotificationCenter.default.post(name: Notification.ghosttyCloseSurface, object: surface)
|
||||||
}
|
}
|
||||||
|
|
||||||
static func focusSplit(_ userdata: UnsafeMutableRawPointer?, direction: SplitFocusDirection) {
|
static func focusSplit(_ userdata: UnsafeMutableRawPointer?, direction: ghostty_split_focus_direction_e) {
|
||||||
guard let surface = self.surfaceUserdata(from: userdata) else { return }
|
guard let surface = self.surfaceUserdata(from: userdata) else { return }
|
||||||
|
guard let splitDirection = SplitFocusDirection.from(direction: direction) else { return }
|
||||||
NotificationCenter.default.post(
|
NotificationCenter.default.post(
|
||||||
name: Notification.ghosttyFocusSplit,
|
name: Notification.ghosttyFocusSplit,
|
||||||
object: surface,
|
object: surface,
|
||||||
userInfo: [
|
userInfo: [
|
||||||
Notification.SplitDirectionKey: direction,
|
Notification.SplitDirectionKey: splitDirection,
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
import GhosttyKit
|
||||||
|
|
||||||
struct Ghostty {
|
struct Ghostty {
|
||||||
// All the notifications that will be emitted will be put here.
|
// All the notifications that will be emitted will be put here.
|
||||||
@ -11,6 +12,30 @@ extension Ghostty {
|
|||||||
/// An enum that is used for the directions that a split focus event can change.
|
/// An enum that is used for the directions that a split focus event can change.
|
||||||
enum SplitFocusDirection {
|
enum SplitFocusDirection {
|
||||||
case previous, next
|
case previous, next
|
||||||
|
|
||||||
|
/// Initialize from a Ghostty API enum.
|
||||||
|
static func from(direction: ghostty_split_focus_direction_e) -> Self? {
|
||||||
|
switch (direction) {
|
||||||
|
case GHOSTTY_SPLIT_FOCUS_PREVIOUS:
|
||||||
|
return .previous
|
||||||
|
|
||||||
|
case GHOSTTY_SPLIT_FOCUS_NEXT:
|
||||||
|
return .next
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toNative() -> ghostty_split_focus_direction_e {
|
||||||
|
switch (self) {
|
||||||
|
case .previous:
|
||||||
|
return GHOSTTY_SPLIT_FOCUS_PREVIOUS
|
||||||
|
|
||||||
|
case .next:
|
||||||
|
return GHOSTTY_SPLIT_FOCUS_NEXT
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -947,16 +947,10 @@ pub fn keyCallback(
|
|||||||
} else log.warn("runtime doesn't implement newSplit", .{});
|
} else log.warn("runtime doesn't implement newSplit", .{});
|
||||||
},
|
},
|
||||||
|
|
||||||
.next_split => {
|
.goto_split => |direction| {
|
||||||
if (@hasDecl(apprt.Surface, "gotoNextSplit")) {
|
if (@hasDecl(apprt.Surface, "gotoSplit")) {
|
||||||
self.rt_surface.gotoNextSplit();
|
self.rt_surface.gotoSplit(direction);
|
||||||
} else log.warn("runtime doesn't implement gotoNextSplit", .{});
|
} else log.warn("runtime doesn't implement gotoSplit", .{});
|
||||||
},
|
|
||||||
|
|
||||||
.previous_split => {
|
|
||||||
if (@hasDecl(apprt.Surface, "gotoPreviousSplit")) {
|
|
||||||
self.rt_surface.gotoPreviousSplit();
|
|
||||||
} else log.warn("runtime doesn't implement gotoPreviousSplit", .{});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
.close_surface => {
|
.close_surface => {
|
||||||
|
@ -53,8 +53,7 @@ pub const App = struct {
|
|||||||
close_surface: ?*const fn (SurfaceUD) callconv(.C) void = null,
|
close_surface: ?*const fn (SurfaceUD) callconv(.C) void = null,
|
||||||
|
|
||||||
/// Focus the previous/next split (if any).
|
/// Focus the previous/next split (if any).
|
||||||
focus_next_split: ?*const fn (SurfaceUD) callconv(.C) void = null,
|
focus_split: ?*const fn (SurfaceUD, input.SplitFocusDirection) callconv(.C) void = null,
|
||||||
focus_previous_split: ?*const fn (SurfaceUD) callconv(.C) void = null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
core_app: *CoreApp,
|
core_app: *CoreApp,
|
||||||
@ -177,22 +176,13 @@ pub const Surface = struct {
|
|||||||
func(self.opts.userdata);
|
func(self.opts.userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gotoNextSplit(self: *const Surface) void {
|
pub fn gotoSplit(self: *const Surface, direction: input.SplitFocusDirection) void {
|
||||||
const func = self.app.opts.focus_next_split orelse {
|
const func = self.app.opts.focus_split orelse {
|
||||||
log.info("runtime embedder does not support focus next split", .{});
|
log.info("runtime embedder does not support focus split", .{});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
func(self.opts.userdata);
|
func(self.opts.userdata, direction);
|
||||||
}
|
|
||||||
|
|
||||||
pub fn gotoPreviousSplit(self: *const Surface) void {
|
|
||||||
const func = self.app.opts.focus_previous_split orelse {
|
|
||||||
log.info("runtime embedder does not support focus previous split", .{});
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
func(self.opts.userdata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getContentScale(self: *const Surface) !apprt.ContentScale {
|
pub fn getContentScale(self: *const Surface) !apprt.ContentScale {
|
||||||
@ -505,12 +495,7 @@ pub const CAPI = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Focus on the next split (if any).
|
/// Focus on the next split (if any).
|
||||||
export fn ghostty_surface_split_focus_next(ptr: *Surface) void {
|
export fn ghostty_surface_split_focus(ptr: *Surface, direction: input.SplitFocusDirection) void {
|
||||||
ptr.gotoNextSplit();
|
ptr.gotoSplit(direction);
|
||||||
}
|
|
||||||
|
|
||||||
/// Focus on the previous split (if any).
|
|
||||||
export fn ghostty_surface_split_focus_previous(ptr: *Surface) void {
|
|
||||||
ptr.gotoPreviousSplit();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -314,12 +314,12 @@ pub const Config = struct {
|
|||||||
try result.keybind.set.put(
|
try result.keybind.set.put(
|
||||||
alloc,
|
alloc,
|
||||||
.{ .key = .left_bracket, .mods = .{ .super = true } },
|
.{ .key = .left_bracket, .mods = .{ .super = true } },
|
||||||
.{ .previous_split = {} },
|
.{ .goto_split = .previous },
|
||||||
);
|
);
|
||||||
try result.keybind.set.put(
|
try result.keybind.set.put(
|
||||||
alloc,
|
alloc,
|
||||||
.{ .key = .right_bracket, .mods = .{ .super = true } },
|
.{ .key = .right_bracket, .mods = .{ .super = true } },
|
||||||
.{ .next_split = {} },
|
.{ .goto_split = .next },
|
||||||
);
|
);
|
||||||
{
|
{
|
||||||
// Cmd+N for goto tab N
|
// Cmd+N for goto tab N
|
||||||
|
@ -4,6 +4,7 @@ pub usingnamespace @import("input/mouse.zig");
|
|||||||
pub usingnamespace @import("input/key.zig");
|
pub usingnamespace @import("input/key.zig");
|
||||||
pub const Binding = @import("input/Binding.zig");
|
pub const Binding = @import("input/Binding.zig");
|
||||||
pub const SplitDirection = Binding.Action.SplitDirection;
|
pub const SplitDirection = Binding.Action.SplitDirection;
|
||||||
|
pub const SplitFocusDirection = Binding.Action.SplitFocusDirection;
|
||||||
|
|
||||||
test {
|
test {
|
||||||
std.testing.refAllDecls(@This());
|
std.testing.refAllDecls(@This());
|
||||||
|
@ -184,11 +184,8 @@ pub const Action = union(enum) {
|
|||||||
/// in the direction given.
|
/// in the direction given.
|
||||||
new_split: SplitDirection,
|
new_split: SplitDirection,
|
||||||
|
|
||||||
/// Go to the previous split.
|
/// Focus on a split in a given direction.
|
||||||
previous_split: void,
|
goto_split: SplitFocusDirection,
|
||||||
|
|
||||||
/// Go to the next split.
|
|
||||||
next_split: void,
|
|
||||||
|
|
||||||
/// Close the current "surface", whether that is a window, tab, split,
|
/// Close the current "surface", whether that is a window, tab, split,
|
||||||
/// etc. This only closes ONE surface.
|
/// etc. This only closes ONE surface.
|
||||||
@ -213,6 +210,17 @@ pub const Action = union(enum) {
|
|||||||
|
|
||||||
// Note: we don't support top or left yet
|
// Note: we don't support top or left yet
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Extern because it is used in the embedded runtime ABI.
|
||||||
|
pub const SplitFocusDirection = enum(c_int) {
|
||||||
|
previous,
|
||||||
|
next,
|
||||||
|
|
||||||
|
top,
|
||||||
|
left,
|
||||||
|
bottom,
|
||||||
|
right,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Trigger is the associated key state that can trigger an action.
|
/// Trigger is the associated key state that can trigger an action.
|
||||||
|
Reference in New Issue
Block a user