Merge pull request #2260 from ghostty-org/adw-focus

Fix: AdwTabOverview loses focus on close
This commit is contained in:
Mitchell Hashimoto
2024-09-18 09:12:40 -07:00
committed by GitHub
2 changed files with 66 additions and 4 deletions

View File

@ -35,7 +35,7 @@ elem: Surface.Container.Elem,
// We'll update this every time a Surface gains focus, so that we have it
// when we switch to another Tab. Then when we switch back to this tab, we
// can easily re-focus that terminal.
focus_child: *Surface,
focus_child: ?*Surface,
pub fn create(alloc: Allocator, window: *Window, parent_: ?*CoreSurface) !*Tab {
var tab = try alloc.create(Tab);
@ -52,7 +52,7 @@ pub fn init(self: *Tab, window: *Window, parent_: ?*CoreSurface) !void {
.label_text = undefined,
.box = undefined,
.elem = undefined,
.focus_child = undefined,
.focus_child = null,
};
// Create a Box in which we'll later keep either Surface or Split.

View File

@ -45,6 +45,9 @@ context_menu: *c.GtkWidget,
/// not used, this is null and unused.
toast_overlay: ?*c.GtkWidget,
/// See adwTabOverviewOpen for why we have this.
adw_tab_overview_focus_timer: ?c.guint = null,
pub fn create(alloc: Allocator, app: *App) !*Window {
// Allocate a fixed pointer for our window. We try to minimize
// allocations but windows and other GUI requirements are so minimal
@ -122,6 +125,14 @@ pub fn init(self: *Window, app: *App) !void {
null,
c.G_CONNECT_DEFAULT,
);
_ = c.g_signal_connect_data(
tab_overview,
"notify::open",
c.G_CALLBACK(&adwTabOverviewOpen),
self,
null,
c.G_CONNECT_DEFAULT,
);
break :overview tab_overview;
} else null;
@ -368,6 +379,10 @@ fn initActions(self: *Window) void {
pub fn deinit(self: *Window) void {
c.gtk_widget_unparent(@ptrCast(self.context_menu));
if (self.adw_tab_overview_focus_timer) |timer| {
_ = c.g_source_remove(timer);
}
}
/// Returns true if this window should use an Adwaita window.
@ -477,7 +492,8 @@ pub fn toggleWindowDecorations(self: *Window) void {
/// Grabs focus on the currently selected tab.
pub fn focusCurrentTab(self: *Window) void {
const tab = self.notebook.currentTab() orelse return;
const gl_area = @as(*c.GtkWidget, @ptrCast(tab.focus_child.gl_area));
const surface = tab.focus_child orelse return;
const gl_area = @as(*c.GtkWidget, @ptrCast(surface.gl_area));
_ = c.gtk_widget_grab_focus(gl_area);
}
@ -516,6 +532,51 @@ fn gtkNewTabFromOverview(_: *c.GtkWidget, ud: ?*anyopaque) callconv(.C) ?*c.AdwT
return c.adw_tab_view_get_page(self.notebook.adw_tab_view, @ptrCast(@alignCast(tab.box)));
}
fn adwTabOverviewOpen(
object: *c.GObject,
_: *c.GParamSpec,
ud: ?*anyopaque,
) void {
const tab_overview: *c.AdwTabOverview = @ptrCast(@alignCast(object));
// We only care about when the tab overview is closed.
if (c.adw_tab_overview_get_open(tab_overview) == 1) {
return;
}
// On tab overview close, focus is sometimes lost. This is an
// upstream issue in libadwaita[1]. When this is resolved we
// can put a runtime version check here to avoid this workaround.
//
// Our workaround is to start a timer after 500ms to refocus
// the currently selected tab. We choose 500ms because the adw
// animation is 400ms.
//
// [1]: https://gitlab.gnome.org/GNOME/libadwaita/-/issues/670
const window: *Window = @ptrCast(@alignCast(ud.?));
// If we have an old timer remove it
if (window.adw_tab_overview_focus_timer) |timer| {
_ = c.g_source_remove(timer);
}
// Restart our timer
window.adw_tab_overview_focus_timer = c.g_timeout_add(
500,
@ptrCast(&adwTabOverviewFocusTimer),
window,
);
}
fn adwTabOverviewFocusTimer(
self: *Window,
) callconv(.C) c.gboolean {
self.focusCurrentTab();
// Remove the timer
return 0;
}
fn gtkRefocusTerm(v: *c.GtkWindow, ud: ?*anyopaque) callconv(.C) bool {
_ = v;
log.debug("refocus term request", .{});
@ -761,7 +822,8 @@ fn gtkActionReset(
/// Returns the surface to use for an action.
fn actionSurface(self: *Window) ?*CoreSurface {
const tab = self.notebook.currentTab() orelse return null;
return &tab.focus_child.core_surface;
const surface = tab.focus_child orelse return null;
return &surface.core_surface;
}
fn userdataSelf(ud: *anyopaque) *Window {