Merge pull request #420 from mitchellh/macos-prev-next-tab

macos: add prev/next tab custom binding support
This commit is contained in:
Mitchell Hashimoto
2023-09-09 13:02:53 -07:00
committed by GitHub
3 changed files with 58 additions and 6 deletions

View File

@ -76,6 +76,11 @@ typedef enum {
GHOSTTY_NON_NATIVE_FULLSCREEN_VISIBLE_MENU, GHOSTTY_NON_NATIVE_FULLSCREEN_VISIBLE_MENU,
} ghostty_non_native_fullscreen_e; } ghostty_non_native_fullscreen_e;
typedef enum {
GHOSTTY_TAB_PREVIOUS = -1,
GHOSTTY_TAB_NEXT = -2,
} ghostty_tab_e;
// This is a packed struct (see src/input/mouse.zig) but the C standard // This is a packed struct (see src/input/mouse.zig) but the C standard
// afaik doesn't let us reliably define packed structs so we build it up // afaik doesn't let us reliably define packed structs so we build it up
// from scratch. // from scratch.

View File

@ -148,11 +148,28 @@ struct PrimaryView: View {
guard let tabGroup = windowController.window?.tabGroup else { return } guard let tabGroup = windowController.window?.tabGroup else { return }
let tabbedWindows = tabGroup.windows let tabbedWindows = tabGroup.windows
// Tabs are 0-indexed here, so we subtract one from the key the user hit. // This will be the index we want to actual go to
let adjustedIndex = Int(tabIndex - 1); let finalIndex: Int
guard adjustedIndex >= 0 && adjustedIndex < tabbedWindows.count else { return }
let targetWindow = tabbedWindows[adjustedIndex] // An index that is invalid is used to signal some special values.
if (tabIndex <= 0) {
guard let selectedWindow = tabGroup.selectedWindow else { return }
guard let selectedIndex = tabbedWindows.firstIndex(where: { $0 == selectedWindow }) else { return }
if (tabIndex == GHOSTTY_TAB_PREVIOUS.rawValue) {
finalIndex = selectedIndex - 1
} else if (tabIndex == GHOSTTY_TAB_NEXT.rawValue) {
finalIndex = selectedIndex + 1
} else {
return
}
} else {
// Tabs are 0-indexed here, so we subtract one from the key the user hit.
finalIndex = Int(tabIndex - 1)
}
guard finalIndex >= 0 && finalIndex < tabbedWindows.count else { return }
let targetWindow = tabbedWindows[finalIndex]
targetWindow.makeKeyAndOrderFront(nil) targetWindow.makeKeyAndOrderFront(nil)
} }

View File

@ -76,12 +76,19 @@ pub const App = struct {
toggle_split_zoom: ?*const fn (SurfaceUD) callconv(.C) void = null, toggle_split_zoom: ?*const fn (SurfaceUD) callconv(.C) void = null,
/// Goto tab /// Goto tab
goto_tab: ?*const fn (SurfaceUD, usize) callconv(.C) void = null, goto_tab: ?*const fn (SurfaceUD, GotoTab) callconv(.C) void = null,
/// Toggle fullscreen for current window. /// Toggle fullscreen for current window.
toggle_fullscreen: ?*const fn (SurfaceUD, configpkg.NonNativeFullscreen) callconv(.C) void = null, toggle_fullscreen: ?*const fn (SurfaceUD, configpkg.NonNativeFullscreen) callconv(.C) void = null,
}; };
/// Special values for the goto_tab callback.
const GotoTab = enum(i32) {
previous = -1,
next = -2,
_,
};
core_app: *CoreApp, core_app: *CoreApp,
config: *const Config, config: *const Config,
opts: Options, opts: Options,
@ -637,7 +644,30 @@ pub const Surface = struct {
return; return;
}; };
func(self.opts.userdata, n); const idx = std.math.cast(i32, n) orelse {
log.warn("cannot cast tab index to i32 n={}", .{n});
return;
};
func(self.opts.userdata, @enumFromInt(idx));
}
pub fn gotoPreviousTab(self: *Surface) void {
const func = self.app.opts.goto_tab orelse {
log.info("runtime embedder does not goto_tab", .{});
return;
};
func(self.opts.userdata, .previous);
}
pub fn gotoNextTab(self: *Surface) void {
const func = self.app.opts.goto_tab orelse {
log.info("runtime embedder does not goto_tab", .{});
return;
};
func(self.opts.userdata, .next);
} }
pub fn toggleFullscreen(self: *Surface, nonNativeFullscreen: configpkg.NonNativeFullscreen) void { pub fn toggleFullscreen(self: *Surface, nonNativeFullscreen: configpkg.NonNativeFullscreen) void {