Window switching initial

pull/9899/head
Max Bretschneider 2025-10-21 22:13:42 +02:00 committed by Mitchell Hashimoto
parent 1805a9cb87
commit 1c1ef99fb1
6 changed files with 88 additions and 0 deletions

View File

@ -512,6 +512,12 @@ typedef enum {
GHOSTTY_GOTO_SPLIT_RIGHT, GHOSTTY_GOTO_SPLIT_RIGHT,
} ghostty_action_goto_split_e; } ghostty_action_goto_split_e;
// apprt.action.GotoWindow
typedef enum {
GHOSTTY_GOTO_WINDOW_PREVIOUS,
GHOSTTY_GOTO_WINDOW_NEXT,
} ghostty_action_goto_window_e;
// apprt.action.ResizeSplit.Direction // apprt.action.ResizeSplit.Direction
typedef enum { typedef enum {
GHOSTTY_RESIZE_SPLIT_UP, GHOSTTY_RESIZE_SPLIT_UP,

View File

@ -5390,6 +5390,17 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
}, },
), ),
.goto_window => |direction| return try self.rt_app.performAction(
.{ .surface = self },
.goto_window,
switch (direction) {
inline else => |tag| @field(
apprt.action.GotoWindow,
@tagName(tag),
),
},
),
.resize_split => |value| return try self.rt_app.performAction( .resize_split => |value| return try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.resize_split, .resize_split,

View File

@ -129,6 +129,9 @@ pub const Action = union(Key) {
/// Jump to a specific split. /// Jump to a specific split.
goto_split: GotoSplit, goto_split: GotoSplit,
/// Jump to next/previous window.
goto_window: GotoWindow,
/// Resize the split in the given direction. /// Resize the split in the given direction.
resize_split: ResizeSplit, resize_split: ResizeSplit,
@ -335,6 +338,7 @@ pub const Action = union(Key) {
move_tab, move_tab,
goto_tab, goto_tab,
goto_split, goto_split,
goto_window,
resize_split, resize_split,
equalize_splits, equalize_splits,
toggle_split_zoom, toggle_split_zoom,
@ -474,6 +478,13 @@ pub const GotoSplit = enum(c_int) {
right, right,
}; };
// This is made extern (c_int) to make interop easier with our embedded
// runtime. The small size cost doesn't make a difference in our union.
pub const GotoWindow = enum(c_int) {
previous,
next,
};
/// The amount to resize the split by and the direction to resize it in. /// The amount to resize the split by and the direction to resize it in.
pub const ResizeSplit = extern struct { pub const ResizeSplit = extern struct {
amount: u16, amount: u16,

View File

@ -659,6 +659,8 @@ pub const Application = extern struct {
.goto_split => return Action.gotoSplit(target, value), .goto_split => return Action.gotoSplit(target, value),
.goto_window => return Action.gotoWindow(value),
.goto_tab => return Action.gotoTab(target, value), .goto_tab => return Action.gotoTab(target, value),
.initial_size => return Action.initialSize(target, value), .initial_size => return Action.initialSize(target, value),
@ -2014,6 +2016,40 @@ const Action = struct {
} }
} }
pub fn gotoWindow(
direction: apprt.action.GotoWindow,
) bool {
const glist = gtk.Window.listToplevels();
defer glist.free();
const node = glist.findCustom(null, findActiveWindow);
// Check based on direction if we are at beginning or end of window list to loop around
// else just go to next/previous window
switch(direction) {
.next => {
const next_node = node.f_next orelse glist;
const window: *gtk.Window = @ptrCast(@alignCast(next_node.f_data orelse return false));
gtk.Window.present(window);
return true;
},
.previous => {
const prev_node = node.f_prev orelse last: {
var current = glist;
while (current.f_next) |next| {
current = next;
}
break :last current;
};
const window: *gtk.Window = @ptrCast(@alignCast(prev_node.f_data orelse return false));
gtk.Window.present(window);
return true;
},
}
return false;
}
pub fn initialSize( pub fn initialSize(
target: apprt.Target, target: apprt.Target,
value: apprt.action.InitialSize, value: apprt.action.InitialSize,

View File

@ -545,6 +545,10 @@ pub const Action = union(enum) {
/// (`previous` and `next`). /// (`previous` and `next`).
goto_split: SplitFocusDirection, goto_split: SplitFocusDirection,
/// Focus on either the previous window or the next one ('previous', 'next')
goto_window: WindowDirection,
/// Zoom in or out of the current split. /// Zoom in or out of the current split.
/// ///
/// When a split is zoomed into, it will take up the entire space in /// When a split is zoomed into, it will take up the entire space in
@ -931,6 +935,11 @@ pub const Action = union(enum) {
right, right,
}; };
pub const WindowDirection = enum {
previous,
next,
};
pub const SplitResizeParameter = struct { pub const SplitResizeParameter = struct {
SplitResizeDirection, SplitResizeDirection,
u16, u16,
@ -1250,6 +1259,7 @@ pub const Action = union(enum) {
.toggle_tab_overview, .toggle_tab_overview,
.new_split, .new_split,
.goto_split, .goto_split,
.goto_window,
.toggle_split_zoom, .toggle_split_zoom,
.toggle_readonly, .toggle_readonly,
.resize_split, .resize_split,

View File

@ -479,6 +479,20 @@ fn actionCommands(action: Action.Key) []const Command {
}, },
}, },
.goto_window => comptime &.{
.{
.action = .{ .goto_window = .previous },
.title = "Focus Window: Previous",
.description = "Focus the previous window, if any.",
},
.{
.action = .{ .goto_window = .previous },
.title = "Focus Window: Next",
.description = "Focus the next window, if any.",
},
},
.toggle_split_zoom => comptime &.{.{ .toggle_split_zoom => comptime &.{.{
.action = .toggle_split_zoom, .action = .toggle_split_zoom,
.title = "Toggle Split Zoom", .title = "Toggle Split Zoom",