termio: use surface messages to trigger password input state

This commit is contained in:
Mitchell Hashimoto
2024-09-18 21:13:54 -07:00
parent 42e7cbc475
commit e3d528cf0b
3 changed files with 40 additions and 13 deletions

View File

@ -818,9 +818,28 @@ pub fn handleMessage(self: *Surface, msg: Message) !void {
.report_color_scheme => try self.reportColorScheme(), .report_color_scheme => try self.reportColorScheme(),
.present_surface => try self.presentSurface(), .present_surface => try self.presentSurface(),
.password_input => |v| try self.passwordInput(v),
} }
} }
/// Called when the terminal detects there is a password input prompt.
fn passwordInput(self: *Surface, v: bool) !void {
{
self.renderer_state.mutex.lock();
defer self.renderer_state.mutex.unlock();
// If our password input state is unchanged then we don't
// waste time doing anything more.
const old = self.io.terminal.flags.password_input;
if (old == v) return;
self.io.terminal.flags.password_input = v;
}
try self.queueRender();
}
/// Sends a DSR response for the current color scheme to the pty. /// Sends a DSR response for the current color scheme to the pty.
fn reportColorScheme(self: *Surface) !void { fn reportColorScheme(self: *Surface) !void {
const output = switch (self.color_scheme) { const output = switch (self.color_scheme) {

View File

@ -65,6 +65,11 @@ pub const Message = union(enum) {
/// a window and switching tabs. /// a window and switching tabs.
present_surface: void, present_surface: void,
/// Notifies the surface that password input has started within
/// the terminal. This should always be followed by a false value
/// unless the surface exits.
password_input: bool,
pub const ReportTitleStyle = enum { pub const ReportTitleStyle = enum {
csi_21_t, csi_21_t,

View File

@ -143,7 +143,6 @@ pub fn threadEnter(
.read_thread_pipe = pipe[1], .read_thread_pipe = pipe[1],
.read_thread_fd = pty_fds.read, .read_thread_fd = pty_fds.read,
.termios_timer = termios_timer, .termios_timer = termios_timer,
.renderer_wakeup = io.renderer_wakeup,
} }; } };
// Start our process watcher // Start our process watcher
@ -460,24 +459,31 @@ fn termiosTimer(
}; };
// If the mode changed, then we process it. // If the mode changed, then we process it.
if (!std.meta.eql(mode, exec.termios_mode)) { if (!std.meta.eql(mode, exec.termios_mode)) mode_change: {
log.debug("termios change mode={}", .{mode}); log.debug("termios change mode={}", .{mode});
exec.termios_mode = mode; exec.termios_mode = mode;
// We assume we're in some sort of password input if we're
// in canonical mode and not echoing. This is a heuristic.
const password_input = mode.canonical and !mode.echo;
// If our password input state changed on the terminal then
// we notify the surface.
{ {
td.renderer_state.mutex.lock(); td.renderer_state.mutex.lock();
defer td.renderer_state.mutex.unlock(); defer td.renderer_state.mutex.unlock();
const t = td.renderer_state.terminal; const t = td.renderer_state.terminal;
if (t.flags.password_input == password_input) {
// We assume we're in some sort of password input if we're break :mode_change;
// in canonical mode and not echoing. This is a heuristic. }
t.flags.password_input = mode.canonical and !mode.echo;
} }
// Notify the renderer of our state change // We have to notify the surface that we're in password input.
exec.renderer_wakeup.notify() catch |err| { // We must block on this because the balanced true/false state
log.warn("error notifying renderer err={}", .{err}); // of this is critical to apprt behavior.
}; _ = td.surface_mailbox.push(.{
.password_input = password_input,
}, .{ .forever = {} });
} }
// Repeat the timer // Repeat the timer
@ -645,9 +651,6 @@ pub const ThreadData = struct {
/// to prevent unnecessary locking of expensive mutexes. /// to prevent unnecessary locking of expensive mutexes.
termios_mode: ptypkg.Mode = .{}, termios_mode: ptypkg.Mode = .{},
/// The handle to wake up the renderer.
renderer_wakeup: xev.Async,
pub fn deinit(self: *ThreadData, alloc: Allocator) void { pub fn deinit(self: *ThreadData, alloc: Allocator) void {
posix.close(self.read_thread_pipe); posix.close(self.read_thread_pipe);