From 40c19fd4f52d20df94c2dfa2d68102b89bd9d3f1 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Tue, 15 Sep 2026 14:46:38 -0300 Subject: Add optional compact tagline styling for source context --- src/macos.zig | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) (limited to 'src/macos.zig') diff --git a/src/macos.zig b/src/macos.zig index 7b71d9d5..bb5b6bf6 100644 --- a/src/macos.zig +++ b/src/macos.zig @@ -637,6 +637,7 @@ const State = struct { core: *pardes.Pardes, started: bool = false, runtime: Runtime, + layer_cells: [pardes.MAX_PANES][]Cell = @splat(&.{}), cells: []Cell = &.{}, previous_cells: []Cell = &.{}, changed_cells: []u8 = &.{}, @@ -778,6 +779,7 @@ export fn pardes_deinit() void { st.inbox.close(st.gpa, st.io); st.file_watches.deinit(st.gpa); if (st.cells.len > 0) st.gpa.free(st.cells); + for (st.layer_cells) |cells| st.gpa.free(cells); if (st.previous_cells.len > 0) st.gpa.free(st.previous_cells); if (st.changed_cells.len > 0) st.gpa.free(st.changed_cells); if (st.images.len > 0) st.gpa.free(st.images); @@ -1480,6 +1482,22 @@ export fn pardes_paste(text_ptr: ?[*]const u8, len: usize) void { } export fn pardes_mouse(button_arg: c_int, kind_arg: c_int, col: u16, row: u16, mods: u32) void { + mouseWithHit(button_arg, kind_arg, col, row, mods, null); +} + +export fn pardes_mouse_pixel(button_arg: c_int, kind_arg: c_int, col: u16, row: u16, mods: u32, x: f32, y: f32, bw: f32, bh: f32, tw: f32, th: f32) void { + const st = &(state orelse return); + const source = st.core.presentation.pointerFractional(st.core.screen_w, st.core.screen_h, x / @max(1, bw), y / @max(1, bh)); + var hit: ?pardes.Mouse.BodyHit = null; + for (&st.core.surface.body_layers) |*layer| { + const point = source orelse break; + hit = layer.hitAt(point.x * bw, point.y * bh, bw, bh, tw, th); + if (hit != null) break; + } + mouseWithHit(button_arg, kind_arg, col, row, mods, hit); +} + +fn mouseWithHit(button_arg: c_int, kind_arg: c_int, col: u16, row: u16, mods: u32, hit: ?pardes.Mouse.BodyHit) void { const st = &(state orelse return); const button: pardes.Mouse.Button = switch (button_arg) { 0 => .left, @@ -1502,6 +1520,7 @@ export fn pardes_mouse(button_arg: c_int, kind_arg: c_int, col: u16, row: u16, m else => return, }; st.core.update(.{ .mouse = .{ + .body_hit = hit, .button = button, .kind = kind, .col = col, @@ -1827,6 +1846,46 @@ export fn pardes_cursor_x() i32 { return if (st.core.surface.cursor) |c| c.x else -1; } +export fn pardes_body_layer_value(index: u32, field: u32) u32 { + const st = &(state orelse return 0); + if (index >= pardes.MAX_PANES) return 0; + const layer = &st.core.surface.body_layers[index]; + return switch (field) { + 0 => layer.rows, + 1 => layer.cols, + 2 => layer.context_rows, + 3 => layer.viewport.x, + 4 => layer.viewport.y, + 5 => layer.viewport.w, + 6 => layer.viewport.h, + 7 => layer.serial, + 8 => if (layer.cursor) |c| c.x else 65535, + 9 => if (layer.cursor) |c| c.y else 65535, + 10 => if (layer.cursor) |c| @intFromBool(c.bar) else 0, + else => 0, + }; +} + +export fn pardes_body_layer_cells(index: u32) ?[*]const Cell { + const st = &(state orelse return null); + if (index >= pardes.MAX_PANES) return null; + const layer = &st.core.surface.body_layers[index]; + if (layer.rows == 0) return null; + const cells = &st.layer_cells[index]; + if (cells.len != layer.cells.len) cells.* = st.gpa.realloc(cells.*, layer.cells.len) catch return null; + for (layer.cells, cells.*) |cell, *out| out.* = encodeCell(cell); + return cells.ptr; +} + +export fn pardes_body_layer_limit() u32 { + return pardes.MAX_PANES; +} + +export fn pardes_row_metrics(body_w: u16, body_h: u16, tagline_w: u16, tagline_h: u16) void { + const st = &(state orelse return); + st.core.update(.{ .resize = .{ .cols = st.core.screen_w, .rows = st.core.screen_h, .cell_pixels = st.core.cell_pixels, .row_metrics = .{ .body_w = @max(1, body_w), .body_h = @max(1, body_h), .tagline_w = @max(1, tagline_w), .tagline_h = @max(1, tagline_h) } } }); +} + export fn pardes_pointer_shape() u32 { const st = &(state orelse return 0); return @intFromEnum(st.core.surface.pointer_shape); @@ -2287,6 +2346,10 @@ test "pardes.h declares every export the way it is defined" { try expectSameAbi(@TypeOf(c.pardes_cursor_y), @TypeOf(pardes_cursor_y)); try expectSameAbi(@TypeOf(c.pardes_cursor_bar), @TypeOf(pardes_cursor_bar)); try expectSameAbi(@TypeOf(c.pardes_pointer_shape), @TypeOf(pardes_pointer_shape)); + try expectSameAbi(@TypeOf(c.pardes_mouse_pixel), @TypeOf(pardes_mouse_pixel)); + try expectSameAbi(@TypeOf(c.pardes_row_metrics), @TypeOf(pardes_row_metrics)); + try expectSameAbi(@TypeOf(c.pardes_body_layer_value), @TypeOf(pardes_body_layer_value)); + try expectSameAbi(@TypeOf(c.pardes_body_layer_cells), @TypeOf(pardes_body_layer_cells)); try expectSameAbi(@TypeOf(c.pardes_take_haptic), @TypeOf(pardes_take_haptic)); try expectSameAbi(@TypeOf(c.pardes_font_take), @TypeOf(pardes_font_take)); try expectSameAbi(@TypeOf(c.pardes_font_observe), @TypeOf(pardes_font_observe)); @@ -2565,3 +2628,22 @@ test "a live session renders on the draw and animates only on the display clock" _ = pardes_frame(); try std.testing.expectEqual(step + 1, st.core.chrome_animation.step); } + +test "mac row metrics ABI preserves PDF cell dimensions and the unrendered grid" { + const gpa = std.testing.allocator; + const core = try pardes.Pardes.init(gpa, .{ .tty_only = true, .cols = 80, .rows = 24 }); + defer core.deinit(); + state = .{ .gpa = gpa, .threaded = undefined, .io = std.testing.io, .core = core, .runtime = .{}, .config_arena = .init(gpa), .prompt_rcs = .{} }; + defer { + state.?.config_arena.deinit(); + state = null; + } + if (comptime pardes.pdf_enabled) core.cell_pixels = .{ .w = 22, .h = 39 }; + const pixels = core.cell_pixels; + try std.testing.expectEqual(@as(u16, 0), core.surface.cols); + pardes_row_metrics(22, 39, 17, 30); + try std.testing.expectEqualDeep(pixels, core.cell_pixels); + try std.testing.expectEqual(@as(u16, 80), core.screen_w); + try std.testing.expectEqual(@as(u16, 24), core.screen_h); + try std.testing.expectEqualDeep(pardes.RowMetrics{ .body_w = 22, .body_h = 39, .tagline_w = 17, .tagline_h = 30 }, core.row_metrics); +} -- cgit v1.3