core: move password input into action enum

This commit is contained in:
Mitchell Hashimoto
2024-09-25 11:43:35 -07:00
parent ae98dddead
commit 02d7e766e1
5 changed files with 38 additions and 15 deletions

View File

@ -549,6 +549,9 @@ extension Ghostty {
} }
static func setPasswordInput(_ userdata: UnsafeMutableRawPointer?, value: Bool) { static func setPasswordInput(_ userdata: UnsafeMutableRawPointer?, value: Bool) {
// We don't currently allow global password input being set from this.
guard let userdata else { return }
let surfaceView = self.surfaceUserdata(from: userdata) let surfaceView = self.surfaceUserdata(from: userdata)
guard let appState = self.appState(fromView: surfaceView) else { return } guard let appState = self.appState(fromView: surfaceView) else { return }
guard appState.config.autoSecureInput else { return } guard appState.config.autoSecureInput else { return }

View File

@ -838,9 +838,16 @@ fn passwordInput(self: *Surface, v: bool) !void {
} }
// Notify our apprt so it can do whatever it wants. // Notify our apprt so it can do whatever it wants.
if (@hasDecl(apprt.Surface, "setPasswordInput")) { self.rt_app.performAction(
self.rt_surface.setPasswordInput(v); .{ .surface = self },
} .secure_input,
v,
) catch |err| {
// We ignore this error because we don't want to fail this
// entire operation just because the apprt failed to set
// the secure input state.
log.warn("apprt failed to set secure input state err={}", .{err});
};
try self.queueRender(); try self.queueRender();
} }

View File

@ -30,6 +30,13 @@ pub const Action = union(enum) {
/// happen and can be ignored or cause a restart it isn't that important. /// happen and can be ignored or cause a restart it isn't that important.
quit_timer: enum { start, stop }, quit_timer: enum { start, stop },
/// Set the secure input functionality on or off. "Secure input" means
/// that the user is currently at some sort of prompt where they may be
/// entering a password or other sensitive information. This can be used
/// by the app runtime to change the appearance of the cursor, setup
/// system APIs to not log the input, etc.
secure_input: bool,
/// The enum of keys in the tagged union. /// The enum of keys in the tagged union.
pub const Key = @typeInfo(Action).Union.tag_type.?; pub const Key = @typeInfo(Action).Union.tag_type.?;

View File

@ -138,6 +138,8 @@ pub const App = struct {
/// Notifies that a password input has been started for the given /// Notifies that a password input has been started for the given
/// surface. The apprt can use this to modify UI, enable features /// surface. The apprt can use this to modify UI, enable features
/// such as macOS secure input, etc. /// such as macOS secure input, etc.
///
/// The surface userdata will be null if a surface isn't focused.
set_password_input: ?*const fn (SurfaceUD, bool) callconv(.C) void = null, set_password_input: ?*const fn (SurfaceUD, bool) callconv(.C) void = null,
/// Toggle secure input for the application. /// Toggle secure input for the application.
@ -504,6 +506,18 @@ pub const App = struct {
func(null, .{}); func(null, .{});
} }
fn setPasswordInput(self: *App, target: apprt.Target, v: bool) void {
const func = self.opts.set_password_input orelse {
log.info("runtime embedder does not set_password_input", .{});
return;
};
func(switch (target) {
.app => null,
.surface => |surface| surface.rt_surface.userdata,
}, v);
}
/// Perform a given action. /// Perform a given action.
pub fn performAction( pub fn performAction(
self: *App, self: *App,
@ -511,8 +525,6 @@ pub const App = struct {
comptime action: apprt.Action.Key, comptime action: apprt.Action.Key,
value: apprt.Action.Value(action), value: apprt.Action.Value(action),
) !void { ) !void {
_ = value;
switch (action) { switch (action) {
.new_window => _ = try self.newWindow(switch (target) { .new_window => _ = try self.newWindow(switch (target) {
.app => null, .app => null,
@ -521,6 +533,8 @@ pub const App = struct {
.open_config => try configpkg.edit.open(self.core_app.alloc), .open_config => try configpkg.edit.open(self.core_app.alloc),
.secure_input => self.setPasswordInput(target, value),
// Unimplemented // Unimplemented
.close_all_windows, .close_all_windows,
.quit_timer, .quit_timer,
@ -1112,15 +1126,6 @@ pub const Surface = struct {
func(); func();
} }
pub fn setPasswordInput(self: *Surface, v: bool) void {
const func = self.app.opts.set_password_input orelse {
log.info("runtime embedder does not set_password_input", .{});
return;
};
func(self.userdata, v);
}
pub fn newTab(self: *const Surface) !void { pub fn newTab(self: *const Surface) !void {
const func = self.app.opts.new_tab orelse { const func = self.app.opts.new_tab orelse {
log.info("runtime embedder does not support new_tab", .{}); log.info("runtime embedder does not support new_tab", .{});

View File

@ -147,7 +147,8 @@ pub const App = struct {
// Unimplemented // Unimplemented
.close_all_windows, .close_all_windows,
.quit_timer, .quit_timer,
=> log.warn("unimplemented action={}", .{action}), .secure_input,
=> log.info("unimplemented action={}", .{action}),
} }
} }