diff options
| author | Gabriel Schneider <[email protected]> | 2026-08-10 09:58:31 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-08-11 09:58:59 -0300 |
| commit | eb11ab331b4e13e2b9e5a673a4c012d22fdd1d9c (patch) | |
| tree | cc993ad239451adb6f23645ee5ca001802832ed0 /src/pardes.zig | |
| parent | 38e9919a9ea9055538409b388d580c4e4c838434 (diff) | |
| download | pardes-eb11ab331b4e13e2b9e5a673a4c012d22fdd1d9c.tar.gz pardes-eb11ab331b4e13e2b9e5a673a4c012d22fdd1d9c.zip | |
macos: the AppKit shell, its icon, and the offscreen e2e harness
Diffstat (limited to 'src/pardes.zig')
| -rw-r--r-- | src/pardes.zig | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/src/pardes.zig b/src/pardes.zig index 4ce4d101..ec938a6d 100644 --- a/src/pardes.zig +++ b/src/pardes.zig @@ -45,6 +45,12 @@ pub const lsp = @import("lsp/lsp.zig"); pub const Platform = enum { tty, gui, web, macos }; pub const platform: Platform = @field(Platform, @tagName(@import("pardes_config").platform)); +/// Frontends that draw their own text, and can therefore be told which face to +/// wear. On the tty the font belongs to the terminal emulator and in the +/// browser it belongs to the page, so there the Font builtins are not +/// disabled so much as meaningless — see builtins.zig. +pub const font_picker = platform == .gui or platform == .macos; + /// Native PDF quality is a shell property, but the core owns MuPDF and the /// RGBA cache. Kitty favors wire bandwidth; SDL favors physical-pixel text /// quality and asks the renderer to cover either fit axis without upscaling. @@ -4199,6 +4205,18 @@ const PendingPipe = struct { } }; +/// The acme verb the core just performed, for a shell that can answer with +/// something physical. macOS taps the trackpad under the finger that asked +/// (NSHapticFeedbackManager); the SDL shell already does the same thing with a +/// gamepad — `rumble` in src/gui/deck.zig, "a brief gentle ack for +/// execute/look, not a buzz". Two verbs rather than one flag because they +/// deserve to feel different: Exec did something, Look went somewhere. +pub const Haptic = enum { none, exec, look }; + +/// Zero-sized off macOS, the way PdfSlot is off -Dmupdf: no other shell reads +/// the field, so no other shell carries it. +const HapticSlot = if (platform == .macos) Haptic else void; + pub const Pardes = struct { gpa: std.mem.Allocator, image_gpa: std.mem.Allocator, @@ -4273,6 +4291,10 @@ pub const Pardes = struct { /// the PETSCII matcher without it. native_images: bool = false, quit: bool = false, + /// The Look or Exec that has happened and not yet been felt, taken by the + /// shell once per pump (takeHaptic). A pulse, not a queue: five Execs + /// inside one keystroke are still one thing the hand did. + haptic: HapticSlot = if (platform == .macos) .none else {}, drag: Drag = .none, hover_col: u16 = 0, hover_row: u16 = 0, @@ -4431,6 +4453,9 @@ pub const Pardes = struct { p.applyStartupConfig(); p.finishThemeInitialization(); p.sync(); + // A config file that opens a file with `Look …` armed the pulse before + // anyone touched anything. Nobody asked for that, so boot is silent. + _ = p.takeHaptic(); return p; } @@ -11603,6 +11628,7 @@ pub const Pardes = struct { /// search of the pane it came from, which is acme's button-3. pub fn lookAt(p: *Pardes, id: usize, txt: []const u8) void { const pane = p.panes[id] orelse return; + p.noteHaptic(.look); const trimmed = std.mem.trim(u8, txt, " \t\r\n"); // `` @`ls -la` `` names a COMMAND, not a path: run it, and land in the // pane that answers — looking at a thing means being SHOWN it, and a @@ -11770,6 +11796,10 @@ pub const Pardes = struct { const pane = p.panes[id] orelse return null; const cmd = commandText(txt); if (cmd.len == 0) return null; + // Before the builtin dispatch, and only at depth zero: `Exec ls` comes + // back through here as `ls` (executeBuiltinLine holds the depth), and + // one Tab is one thing the hand did, however many words it unwraps to. + if (p.exec_depth == 0) p.noteHaptic(.exec); if (p.executeBuiltinLine(id, cmd)) return null; if (p.exec_depth >= max_exec_depth) return null; p.exec_depth += 1; @@ -12244,6 +12274,7 @@ pub const Pardes = struct { p.applyStartupConfig(); p.finishThemeInitialization(); p.sync(); + _ = p.takeHaptic(); // see init: a restored session is not a gesture return p; } @@ -12511,6 +12542,23 @@ pub const Pardes = struct { return p.chrome_animation.isActive(); } + /// Arm the pulse. Look wins a tie because a Look that runs a command + /// (`` @`ls` ``, which is one gesture spelled as both) is felt as the + /// thing the user asked for, not as the shell it happened to need. + fn noteHaptic(p: *Pardes, pulse: Haptic) void { + if (comptime platform != .macos) return; + if (p.haptic == .look) return; + p.haptic = pulse; + } + + /// Take the armed pulse and disarm. The shell calls this once per pump, + /// after the tick that may have set it. + pub fn takeHaptic(p: *Pardes) Haptic { + if (comptime platform != .macos) return .none; + defer p.haptic = .none; + return p.haptic; + } + fn finishThemeInitialization(p: *Pardes) void { p.chrome_animation.snap(ChromeTheme.fromTheme(p.theme())); p.animate_theme_changes = true; |
