GTK: start search accepts selection contents (#10262)

Fixes: #10196

If user invokes `search_selection` the contents of that string are no
longer ignored.

I'm not very familar with how apprt actions are sent to macos to ensure
the defer free will work there, but it is required for GTK otherwise we
are leaking the memory

I'm also open to making the string optional instead of checking against
`""` thats just how the current `start_search` action was sending its
needle (which I assume is better for macos?)

The text is also highlighted currently due to `grabFocus` always
selecting the search contents, not sure how the macos part works but
that could easily be changed to change the contents after focus was
grabbed

https://github.com/ghostty-org/ghostty/blob/main/src/apprt/gtk/class/search_overlay.zig#L233-L241
pull/10285/head
Mitchell Hashimoto 2026-01-11 07:23:29 -08:00 committed by GitHub
commit 4db3245a92
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 17 additions and 5 deletions

View File

@ -5221,6 +5221,7 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
.search_selection => {
const selection = try self.selectionString(self.alloc) orelse return false;
defer self.alloc.free(selection);
return try self.rt_app.performAction(
.{ .surface = self },
.start_search,

View File

@ -734,7 +734,7 @@ pub const Application = extern struct {
.show_on_screen_keyboard => return Action.showOnScreenKeyboard(target),
.command_finished => return Action.commandFinished(target, value),
.start_search => Action.startSearch(target),
.start_search => Action.startSearch(target, value),
.end_search => Action.endSearch(target),
.search_total => Action.searchTotal(target, value),
.search_selected => Action.searchSelected(target, value),
@ -2439,17 +2439,17 @@ const Action = struct {
}
}
pub fn startSearch(target: apprt.Target) void {
pub fn startSearch(target: apprt.Target, value: apprt.action.StartSearch) void {
switch (target) {
.app => {},
.surface => |v| v.rt_surface.surface.setSearchActive(true),
.surface => |v| v.rt_surface.surface.setSearchActive(true, value.needle),
}
}
pub fn endSearch(target: apprt.Target) void {
switch (target) {
.app => {},
.surface => |v| v.rt_surface.surface.setSearchActive(false),
.surface => |v| v.rt_surface.surface.setSearchActive(false, ""),
}
}

View File

@ -250,6 +250,13 @@ pub const SearchOverlay = extern struct {
priv.active = active;
}
// Set contents of search
pub fn setSearchContents(self: *Self, content: [:0]const u8) void {
const priv = self.private();
priv.search_entry.as(gtk.Editable).setText(content);
signals.@"search-changed".impl.emit(self, null, .{content}, null);
}
/// Set the total number of search matches.
pub fn setSearchTotal(self: *Self, total: ?usize) void {
const priv = self.private();

View File

@ -2091,7 +2091,7 @@ pub const Surface = extern struct {
self.as(gobject.Object).notifyByPspec(properties.@"error".impl.param_spec);
}
pub fn setSearchActive(self: *Self, active: bool) void {
pub fn setSearchActive(self: *Self, active: bool, needle: [:0]const u8) void {
const priv = self.private();
var value = gobject.ext.Value.newFrom(active);
defer value.unset();
@ -2101,6 +2101,10 @@ pub const Surface = extern struct {
&value,
);
if (!std.mem.eql(u8, needle, "")) {
priv.search_overlay.setSearchContents(needle);
}
if (active) {
priv.search_overlay.grabFocus();
}