apprt/gtk: clean up gotoWindow

pull/9899/head
Mitchell Hashimoto 2025-12-13 14:17:55 -08:00
parent bb246b2e0c
commit dfb94cd55d
No known key found for this signature in database
GPG Key ID: 523D5DC389D273BC
2 changed files with 55 additions and 30 deletions

View File

@ -2016,44 +2016,69 @@ const Action = struct {
} }
} }
pub fn gotoWindow( pub fn gotoWindow(direction: apprt.action.GotoWindow) bool {
direction: apprt.action.GotoWindow,
) bool {
const glist = gtk.Window.listToplevels(); const glist = gtk.Window.listToplevels();
defer glist.free(); defer glist.free();
const node = @as(?*glib.List, glist.findCustom(null, findActiveWindow)); // The window we're starting from is typically our active window.
const starting: *glib.List = @as(?*glib.List, glist.findCustom(
null,
findActiveWindow,
)) orelse glist;
const target_node = if (node) |n| switch (direction) { // Go forward or backwards in the list until we find a valid
.next => n.f_next orelse glist, // window that is visible.
.previous => n.f_prev orelse last: { var current_: ?*glib.List = starting;
var current = glist; while (current_) |node| : (current_ = switch (direction) {
while (current.f_next) |next| { .next => node.f_next,
current = next; .previous => node.f_prev,
} }) {
break :last current; const data = node.f_data orelse continue;
}, const gtk_window: *gtk.Window = @ptrCast(@alignCast(data));
} else glist; if (gotoWindowMaybe(gtk_window)) return true;
}
const data = target_node.f_data orelse return false;
const gtk_window: *gtk.Window = @ptrCast(@alignCast(data)); // If we reached here, we didn't find a valid window to focus.
gtk.Window.present(gtk_window); // Wrap around.
current_ = switch (direction) {
const ghostty_window = gobject.ext.cast(Window, gtk_window) orelse return false; .next => glist,
.previous => last: {
var surface: ?*gobject.Object = null; var end: *glib.List = glist;
ghostty_window.as(gobject.Object).get("active-surface", &surface, @as(?*anyopaque, null)); while (end.f_next) |next| end = next;
break :last end;
if (surface) |s| { },
const surface_obj = gobject.ext.cast(Surface, s) orelse return false; };
surface_obj.grabFocus(); while (current_) |node| : (current_ = switch (direction) {
return true; .next => node.f_next,
.previous => node.f_prev,
}) {
if (current_ == starting) break;
const data = node.f_data orelse continue;
const gtk_window: *gtk.Window = @ptrCast(@alignCast(data));
if (gotoWindowMaybe(gtk_window)) return true;
} }
log.warn("window has no active surface, cannot grab focus", .{});
return false; return false;
} }
fn gotoWindowMaybe(gtk_window: *gtk.Window) bool {
// If it is already active skip it.
if (gtk_window.isActive() != 0) return false;
// If it is hidden, skip it.
if (gtk_window.as(gtk.Widget).isVisible() == 0) return false;
// If it isn't a Ghostty window, skip it.
const window = gobject.ext.cast(
Window,
gtk_window,
) orelse return false;
// Focus our active surface
const surface = window.getActiveSurface() orelse return false;
gtk.Window.present(gtk_window);
surface.grabFocus();
return true;
}
pub fn initialSize( pub fn initialSize(
target: apprt.Target, target: apprt.Target,
value: apprt.action.InitialSize, value: apprt.action.InitialSize,

View File

@ -793,7 +793,7 @@ pub const Window = extern struct {
/// Get the currently active surface. See the "active-surface" property. /// Get the currently active surface. See the "active-surface" property.
/// This does not ref the value. /// This does not ref the value.
fn getActiveSurface(self: *Self) ?*Surface { pub fn getActiveSurface(self: *Self) ?*Surface {
const tab = self.getSelectedTab() orelse return null; const tab = self.getSelectedTab() orelse return null;
return tab.getActiveSurface(); return tab.getActiveSurface();
} }