From 4b5f2d60e7bc347c502ea9c13a59ba1f3f0546ff Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Sun, 22 Mar 2026 20:53:28 -0500 Subject: [PATCH] core/gtk: ensure that first surface gets marked as focused surface by app --- src/Surface.zig | 11 ++++++----- src/apprt/gtk/class/surface.zig | 27 ++++++++++++++++----------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/Surface.zig b/src/Surface.zig index 61e7bd6e0..dfc3a50ea 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -3282,7 +3282,11 @@ pub fn focusCallback(self: *Surface, focused: bool) !void { crash.sentry.thread_state = self.crashThreadState(); defer crash.sentry.thread_state = null; - // If our focus state is the same we do nothing. + // Always update the app focused surface, otherwise we miss + // the first surface created. + if (focused) self.app.focusSurface(self); + + // If our focus state is unchanged we do nothing else. if (self.focused == focused) return; self.focused = focused; @@ -3291,10 +3295,7 @@ pub fn focusCallback(self: *Surface, focused: bool) !void { .focus = focused, }, .{ .forever = {} }); - if (focused) { - // Notify our app if we gained focus. - self.app.focusSurface(self); - } else unfocused: { + if (!focused) unfocused: { // If we lost focus and we have a keypress, then we want to send a key // release event for it. Depending on the apprt, this CAN result in // duplicate key release events, but that is better than not sending diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index f1e1c3907..32d29ba9c 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -2698,22 +2698,25 @@ pub const Surface = extern struct { } fn ecFocusEnter(_: *gtk.EventControllerFocus, self: *Self) callconv(.c) void { + self.updateFocus(true); + } + + fn ecFocusLeave(_: *gtk.EventControllerFocus, self: *Self) callconv(.c) void { + self.updateFocus(false); + } + + fn updateFocus(self: *Self, focused: bool) void { const priv = self.private(); - priv.focused = true; - priv.im_context.as(gtk.IMContext).focusIn(); + priv.focused = focused; + + const ctx = priv.im_context.as(gtk.IMContext); + if (focused) ctx.focusIn() else ctx.focusOut(); + _ = glib.idleAddOnce(idleFocus, self.ref()); self.as(gobject.Object).notifyByPspec(properties.focused.impl.param_spec); // Bell stops ringing as soon as we gain focus - self.setBellRinging(false); - } - - fn ecFocusLeave(_: *gtk.EventControllerFocus, self: *Self) callconv(.c) void { - const priv = self.private(); - priv.focused = false; - priv.im_context.as(gtk.IMContext).focusOut(); - _ = glib.idleAddOnce(idleFocus, self.ref()); - self.as(gobject.Object).notifyByPspec(properties.focused.impl.param_spec); + if (focused) self.setBellRinging(false); } /// The focus callback must be triggered on an idle loop source because @@ -3406,6 +3409,8 @@ pub const Surface = extern struct { .{}, null, ); + + self.updateFocus(priv.focused); } fn resizeOverlaySchedule(self: *Self) void {