summaryrefslogtreecommitdiff
path: root/src/gui
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-30 14:29:44 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:17 -0300
commit8262f315538b70ab8a123ef1e9346f25b25ec939 (patch)
tree7e0058b229bcf974758f748cbca5b7730aef856c /src/gui
parent505d15e238e4e9c5020a8e567d700bdbf67a8528 (diff)
downloadpardes-8262f315538b70ab8a123ef1e9346f25b25ec939.tar.gz
pardes-8262f315538b70ab8a123ef1e9346f25b25ec939.zip
The window's F1-F24, Insert, Print Screen, Scroll Lock, Pause and Menu keys reach a terminal's program, which they never did; every key a program gets follows its cursor keys' mode and kitty keyboard flags, pinned for both shells
The keys went through ghostty's encoder already (DECCKM, the kitty flags); the GUI's native key map simply dropped the function and editing keys it did not name. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/gui.zig48
1 files changed, 48 insertions, 0 deletions
diff --git a/src/gui/gui.zig b/src/gui/gui.zig
index 14205906..1e58d3ba 100644
--- a/src/gui/gui.zig
+++ b/src/gui/gui.zig
@@ -3444,6 +3444,47 @@ test "the GUI's stdin keys reach a terminal pane as the tty's do: F5, Insert and
try std.testing.expectEqualStrings("\x1b[15~\x1b[2~\x1b[A", written.written());
}
+test "the window's function and editing keys reach a terminal as its cursor keys' mode and keyboard flags say" {
+ const gpa = std.testing.allocator;
+ const core = try pardes.Pardes.init(gpa, .{ .tty_only = true });
+ defer core.deinit();
+ core.panes[0].?.body.mode = .tty;
+ while (core.nextEffect()) |_| {}
+ var in: Input = .{ .core = core };
+ var written: std.Io.Writer.Allocating = .init(gpa);
+ defer written.deinit();
+ const Case = struct { modes: []const u8, sym: c.SDL_Keycode, mod: c.SDL_Keymod = 0, sent: []const u8 };
+ const cases = [_]Case{
+ .{ .modes = "", .sym = c.SDLK_UP, .sent = "\x1b[A" },
+ .{ .modes = "", .sym = c.SDLK_HOME, .sent = "\x1b[H" },
+ .{ .modes = "", .sym = c.SDLK_F1, .sent = "\x1bOP" },
+ .{ .modes = "", .sym = c.SDLK_F5, .sent = "\x1b[15~" },
+ .{ .modes = "", .sym = c.SDLK_F12, .mod = c.SDL_KMOD_LSHIFT, .sent = "\x1b[24;2~" },
+ .{ .modes = "", .sym = c.SDLK_INSERT, .sent = "\x1b[2~" },
+ // DECCKM: less, vim, htop.
+ .{ .modes = "\x1b[?1h", .sym = c.SDLK_UP, .sent = "\x1bOA" },
+ .{ .modes = "", .sym = c.SDLK_END, .sent = "\x1bOF" },
+ .{ .modes = "", .sym = c.SDLK_LEFT, .mod = c.SDL_KMOD_LCTRL, .sent = "\x1b[1;5D" },
+ // codex's kitty flags (>7u): Ctrl-C and Alt-a are unambiguous.
+ // (A bare Escape at a shell prompt is pardes's way out of raw input.)
+ .{ .modes = "\x1b[?1l\x1b[>7u", .sym = 'c', .mod = c.SDL_KMOD_LCTRL, .sent = "\x1b[99;5u" },
+ .{ .modes = "", .sym = 'a', .mod = c.SDL_KMOD_LALT, .sent = "\x1b[97;3u" },
+ // With event types asked for (2), an arrow says it is a press, as
+ // ghostty says it.
+ .{ .modes = "", .sym = c.SDLK_UP, .sent = "\x1b[1;1:1A" },
+ };
+ for (cases) |case| {
+ core.update(.{ .output = .{ .pane = 0, .bytes = case.modes } });
+ while (core.nextEffect()) |_| {}
+ keyDown(&in, case.sym, case.mod);
+ written.clearRetainingCapacity();
+ while (core.nextEffect()) |effect| {
+ if (effect == .write) try written.writer.writeAll(effect.write.bytes.slice());
+ }
+ try std.testing.expectEqualStrings(case.sent, written.written());
+ }
+}
+
const Input = struct {
core: ?*pardes.Pardes = null,
client: ?*detached_client.Client = null,
@@ -3783,6 +3824,13 @@ fn keyDown(in: *Input, sym: c.SDL_Keycode, mod: c.SDL_Keymod) void {
c.SDLK_PAGEUP => pardes.Key.page_up,
c.SDLK_PAGEDOWN => pardes.Key.page_down,
c.SDLK_DELETE => pardes.Key.delete,
+ c.SDLK_INSERT => pardes.Key.insert,
+ c.SDLK_PRINTSCREEN => pardes.Key.print_screen,
+ c.SDLK_SCROLLLOCK => pardes.Key.scroll_lock,
+ c.SDLK_PAUSE => pardes.Key.pause,
+ c.SDLK_APPLICATION => pardes.Key.menu,
+ c.SDLK_F1...c.SDLK_F12 => pardes.Key.f1 + @as(u21, @intCast(sym - c.SDLK_F1)),
+ c.SDLK_F13...c.SDLK_F24 => pardes.Key.f1 + 12 + @as(u21, @intCast(sym - c.SDLK_F13)),
else => blk: {
if (!(ctrl or alt or gui_mod)) break :blk 0;
if (sym < 128 and sym >= ' ') break :blk @intCast(sym);