From e3d528cf0bdc970a9033aefe84ed5054c874486f Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 18 Sep 2024 21:13:54 -0700 Subject: [PATCH] termio: use surface messages to trigger password input state --- src/Surface.zig | 19 +++++++++++++++++++ src/apprt/surface.zig | 5 +++++ src/termio/Exec.zig | 29 ++++++++++++++++------------- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/src/Surface.zig b/src/Surface.zig index baa8dc6b0..cb7f8a9ae 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -818,9 +818,28 @@ pub fn handleMessage(self: *Surface, msg: Message) !void { .report_color_scheme => try self.reportColorScheme(), .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. fn reportColorScheme(self: *Surface) !void { const output = switch (self.color_scheme) { diff --git a/src/apprt/surface.zig b/src/apprt/surface.zig index d73dcea05..daa2ad547 100644 --- a/src/apprt/surface.zig +++ b/src/apprt/surface.zig @@ -65,6 +65,11 @@ pub const Message = union(enum) { /// a window and switching tabs. 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 { csi_21_t, diff --git a/src/termio/Exec.zig b/src/termio/Exec.zig index 73bccab2e..87e7e4b2f 100644 --- a/src/termio/Exec.zig +++ b/src/termio/Exec.zig @@ -143,7 +143,6 @@ pub fn threadEnter( .read_thread_pipe = pipe[1], .read_thread_fd = pty_fds.read, .termios_timer = termios_timer, - .renderer_wakeup = io.renderer_wakeup, } }; // Start our process watcher @@ -460,24 +459,31 @@ fn termiosTimer( }; // 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}); 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(); defer td.renderer_state.mutex.unlock(); const t = td.renderer_state.terminal; - - // We assume we're in some sort of password input if we're - // in canonical mode and not echoing. This is a heuristic. - t.flags.password_input = mode.canonical and !mode.echo; + if (t.flags.password_input == password_input) { + break :mode_change; + } } - // Notify the renderer of our state change - exec.renderer_wakeup.notify() catch |err| { - log.warn("error notifying renderer err={}", .{err}); - }; + // We have to notify the surface that we're in password input. + // We must block on this because the balanced true/false state + // of this is critical to apprt behavior. + _ = td.surface_mailbox.push(.{ + .password_input = password_input, + }, .{ .forever = {} }); } // Repeat the timer @@ -645,9 +651,6 @@ pub const ThreadData = struct { /// to prevent unnecessary locking of expensive mutexes. termios_mode: ptypkg.Mode = .{}, - /// The handle to wake up the renderer. - renderer_wakeup: xev.Async, - pub fn deinit(self: *ThreadData, alloc: Allocator) void { posix.close(self.read_thread_pipe);