feat: add readonly surface mode
parent
dd06d8a13b
commit
12bb2f3f47
|
|
@ -797,6 +797,7 @@ typedef enum {
|
|||
GHOSTTY_ACTION_RESIZE_SPLIT,
|
||||
GHOSTTY_ACTION_EQUALIZE_SPLITS,
|
||||
GHOSTTY_ACTION_TOGGLE_SPLIT_ZOOM,
|
||||
GHOSTTY_ACTION_TOGGLE_READONLY,
|
||||
GHOSTTY_ACTION_PRESENT_TERMINAL,
|
||||
GHOSTTY_ACTION_SIZE_LIMIT,
|
||||
GHOSTTY_ACTION_RESET_WINDOW_SIZE,
|
||||
|
|
|
|||
|
|
@ -145,6 +145,12 @@ focused: bool = true,
|
|||
/// Used to determine whether to continuously scroll.
|
||||
selection_scroll_active: bool = false,
|
||||
|
||||
/// True if the surface is in read-only mode. When read-only, no input
|
||||
/// is sent to the PTY but terminal-level operations like selections,
|
||||
/// scrolling, and copy/paste keybinds still work. Warn before quit is
|
||||
/// always enabled in this state.
|
||||
readonly: bool = false,
|
||||
|
||||
/// Used to send notifications that long running commands have finished.
|
||||
/// Requires that shell integration be active. Should represent a nanosecond
|
||||
/// precision timestamp. It does not necessarily need to correspond to the
|
||||
|
|
@ -871,6 +877,9 @@ pub fn deactivateInspector(self: *Surface) void {
|
|||
/// True if the surface requires confirmation to quit. This should be called
|
||||
/// by apprt to determine if the surface should confirm before quitting.
|
||||
pub fn needsConfirmQuit(self: *Surface) bool {
|
||||
// If the surface is in read-only mode, always require confirmation
|
||||
if (self.readonly) return true;
|
||||
|
||||
// If the child has exited, then our process is certainly not alive.
|
||||
// We check this first to avoid the locking overhead below.
|
||||
if (self.child_exited) return false;
|
||||
|
|
@ -2559,6 +2568,12 @@ pub fn keyCallback(
|
|||
if (insp_ev) |*ev| ev else null,
|
||||
)) |v| return v;
|
||||
|
||||
// If the surface is in read-only mode, we consume the key event here
|
||||
// without sending it to the PTY.
|
||||
if (self.readonly) {
|
||||
return .consumed;
|
||||
}
|
||||
|
||||
// If we allow KAM and KAM is enabled then we do nothing.
|
||||
if (self.config.vt_kam_allowed) {
|
||||
self.renderer_state.mutex.lock();
|
||||
|
|
@ -3267,7 +3282,9 @@ pub fn scrollCallback(
|
|||
// we convert to cursor keys. This only happens if we're:
|
||||
// (1) alt screen (2) no explicit mouse reporting and (3) alt
|
||||
// scroll mode enabled.
|
||||
if (self.io.terminal.screens.active_key == .alternate and
|
||||
// Additionally, we don't send cursor keys if the surface is in read-only mode.
|
||||
if (!self.readonly and
|
||||
self.io.terminal.screens.active_key == .alternate and
|
||||
self.io.terminal.flags.mouse_event == .none and
|
||||
self.io.terminal.modes.get(.mouse_alternate_scroll))
|
||||
{
|
||||
|
|
@ -3393,6 +3410,9 @@ fn mouseReport(
|
|||
assert(self.config.mouse_reporting);
|
||||
assert(self.io.terminal.flags.mouse_event != .none);
|
||||
|
||||
// If the surface is in read-only mode, do not send mouse reports to the PTY
|
||||
if (self.readonly) return;
|
||||
|
||||
// Depending on the event, we may do nothing at all.
|
||||
switch (self.io.terminal.flags.mouse_event) {
|
||||
.none => unreachable, // checked by assert above
|
||||
|
|
@ -5383,6 +5403,15 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
|
|||
{},
|
||||
),
|
||||
|
||||
.toggle_readonly => {
|
||||
self.readonly = !self.readonly;
|
||||
return try self.rt_app.performAction(
|
||||
.{ .surface = self },
|
||||
.toggle_readonly,
|
||||
{},
|
||||
);
|
||||
},
|
||||
|
||||
.reset_window_size => return try self.rt_app.performAction(
|
||||
.{ .surface = self },
|
||||
.reset_window_size,
|
||||
|
|
|
|||
|
|
@ -139,6 +139,11 @@ pub const Action = union(Key) {
|
|||
/// to take up the entire window.
|
||||
toggle_split_zoom,
|
||||
|
||||
/// Toggle whether the surface is in read-only mode. When read-only,
|
||||
/// no input is sent to the PTY but terminal-level operations like
|
||||
/// selections, scrolling, and copy/paste keybinds still work.
|
||||
toggle_readonly,
|
||||
|
||||
/// Present the target terminal whether its a tab, split, or window.
|
||||
present_terminal,
|
||||
|
||||
|
|
@ -335,6 +340,7 @@ pub const Action = union(Key) {
|
|||
resize_split,
|
||||
equalize_splits,
|
||||
toggle_split_zoom,
|
||||
toggle_readonly,
|
||||
present_terminal,
|
||||
size_limit,
|
||||
reset_window_size,
|
||||
|
|
|
|||
|
|
@ -724,6 +724,10 @@ pub const Application = extern struct {
|
|||
.toggle_window_decorations => return Action.toggleWindowDecorations(target),
|
||||
.toggle_command_palette => return Action.toggleCommandPalette(target),
|
||||
.toggle_split_zoom => return Action.toggleSplitZoom(target),
|
||||
.toggle_readonly => {
|
||||
// The readonly state is managed in Surface.zig.
|
||||
return true;
|
||||
},
|
||||
.show_on_screen_keyboard => return Action.showOnScreenKeyboard(target),
|
||||
.command_finished => return Action.commandFinished(target, value),
|
||||
|
||||
|
|
|
|||
|
|
@ -552,6 +552,16 @@ pub const Action = union(enum) {
|
|||
/// reflect this by displaying an icon indicating the zoomed state.
|
||||
toggle_split_zoom,
|
||||
|
||||
/// Toggle read-only mode for the current surface.
|
||||
///
|
||||
/// When a surface is in read-only mode:
|
||||
/// - No input is sent to the PTY (mouse events, key encoding)
|
||||
/// - Input can still be used at the terminal level to make selections,
|
||||
/// copy/paste (keybinds), scroll, etc.
|
||||
/// - Warn before quit is always enabled in this state even if an active
|
||||
/// process is not running
|
||||
toggle_readonly,
|
||||
|
||||
/// Resize the current split in the specified direction and amount in
|
||||
/// pixels. The two arguments should be joined with a comma (`,`),
|
||||
/// like in `resize_split:up,10`.
|
||||
|
|
@ -1241,6 +1251,7 @@ pub const Action = union(enum) {
|
|||
.new_split,
|
||||
.goto_split,
|
||||
.toggle_split_zoom,
|
||||
.toggle_readonly,
|
||||
.resize_split,
|
||||
.equalize_splits,
|
||||
.inspector,
|
||||
|
|
|
|||
|
|
@ -485,6 +485,12 @@ fn actionCommands(action: Action.Key) []const Command {
|
|||
.description = "Toggle the zoom state of the current split.",
|
||||
}},
|
||||
|
||||
.toggle_readonly => comptime &.{.{
|
||||
.action = .toggle_readonly,
|
||||
.title = "Toggle Read-Only Mode",
|
||||
.description = "Toggle read-only mode for the current surface.",
|
||||
}},
|
||||
|
||||
.equalize_splits => comptime &.{.{
|
||||
.action = .equalize_splits,
|
||||
.title = "Equalize Splits",
|
||||
|
|
|
|||
Loading…
Reference in New Issue