From 1ab4c071be58033d5452f69797ca8e2c32240cff Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Tue, 15 Sep 2026 16:28:57 -0300 Subject: Separate tag text geometry from physical pane grips --- src/web.zig | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) (limited to 'src/web.zig') diff --git a/src/web.zig b/src/web.zig index 46e8c3b4..a4e46276 100644 --- a/src/web.zig +++ b/src/web.zig @@ -99,6 +99,7 @@ comptime { const State = struct { core: *pardes.Pardes, + tag_cells: [pardes.MAX_TAG_LAYERS][]WebCell = @splat(&.{}), layer_cells: [pardes.MAX_PANES][]WebCell = @splat(&.{}), cells: []WebCell = &.{}, frame_len: usize = 0, @@ -129,6 +130,7 @@ const State = struct { fn deinit(s: *State) void { if (s.cells.len > 0) gpa.free(s.cells); for (s.layer_cells) |cells| gpa.free(cells); + for (s.tag_cells) |cells| gpa.free(cells); s.core.deinit(); pardes.image.stop(); if (comptime pardes.pdf_enabled) pardes.pdf.stop(); @@ -209,7 +211,7 @@ export fn pardes_paste(len_arg: u32) void { /// Buttons and kinds are their boundary enum ordinals. Invalid values are /// ignored rather than reaching an unchecked enum cast inside wasm. export fn pardes_mouse(button_arg: u32, kind_arg: u32, col_arg: u32, row_arg: u32, mods: u32) void { - mouseWithHit(button_arg, kind_arg, col_arg, row_arg, mods, null); + mouseWithHit(button_arg, kind_arg, col_arg, row_arg, mods, null, null); } export fn pardes_mouse_pixel(button_arg: u32, kind_arg: u32, col_arg: u32, row_arg: u32, mods: u32, x: f32, y: f32, bw: f32, bh: f32, tw: f32, th: f32) void { @@ -221,10 +223,16 @@ export fn pardes_mouse_pixel(button_arg: u32, kind_arg: u32, col_arg: u32, row_a hit = layer.hitAt(point.x * bw, point.y * bh, bw, bh, tw, th); if (hit != null) break; } - mouseWithHit(button_arg, kind_arg, col_arg, row_arg, mods, hit); + var tag_hit: ?pardes.TagHit = null; + for (&s.core.surface.tag_layers) |*layer| { + const point = source orelse break; + tag_hit = layer.hitAt(point.x * bw, point.y * bh, bw, bh, tw, th); + if (tag_hit != null) break; + } + mouseWithHit(button_arg, kind_arg, col_arg, row_arg, mods, hit, tag_hit); } -fn mouseWithHit(button_arg: u32, kind_arg: u32, col_arg: u32, row_arg: u32, mods: u32, hit: ?pardes.Mouse.BodyHit) void { +fn mouseWithHit(button_arg: u32, kind_arg: u32, col_arg: u32, row_arg: u32, mods: u32, hit: ?pardes.Mouse.BodyHit, tag_hit: ?pardes.TagHit) void { const s = &(state orelse return); const button: pardes.Mouse.Button = switch (button_arg) { 0 => .left, @@ -248,6 +256,7 @@ fn mouseWithHit(button_arg: u32, kind_arg: u32, col_arg: u32, row_arg: u32, mods }; s.core.update(.{ .mouse = .{ .body_hit = hit, + .tag_hit = tag_hit, .button = button, .kind = kind, .col = @intCast(@min(col_arg, std.math.maxInt(u16))), @@ -323,6 +332,45 @@ export fn pardes_cursor_x() i32 { return if (s.core.surface.cursor) |cursor| cursor.x else -1; } +export fn pardes_tag_layer_limit() u32 { + return pardes.MAX_TAG_LAYERS; +} + +export fn pardes_tag_layer_value(index: u32, field: u32) u32 { + const s = &(state orelse return 0); + if (index >= pardes.MAX_TAG_LAYERS) return 0; + const layer = &s.core.surface.tag_layers[index]; + return switch (field) { + 0 => layer.cols, + 1 => @intFromEnum(layer.kind), + 2 => layer.id, + 3 => layer.serial, + 4 => layer.viewport.x, + 5 => layer.viewport.y, + 6 => layer.viewport.w, + 7 => layer.viewport.h, + 8 => if (layer.cursor) |c| c.col else 65535, + 9 => if (layer.cursor) |c| @intFromBool(c.bar) else 0, + 10 => @as(u32, layer.bg[0]) << 16 | @as(u32, layer.bg[1]) << 8 | layer.bg[2], + else => 0, + }; +} + +export fn pardes_tag_layer_cells(index: u32) ?[*]const WebCell { + const s = &(state orelse return null); + if (index >= pardes.MAX_TAG_LAYERS) return null; + const layer = &s.core.surface.tag_layers[index]; + if (layer.cols == 0) return null; + const cells = &s.tag_cells[index]; + if (cells.len != layer.cells.len) cells.* = gpa.realloc(cells.*, layer.cells.len) catch return null; + for (layer.cells, cells.*) |source, *out| out.* = encodeWebCell(source); + return cells.ptr; +} + +export fn pardes_tagline_band_offset(row: u16, canvas_h: f32, cell_h: u32, tagline_h: u32) u32 { + return pardes.taglineBandOffset(row, canvas_h, cell_h, tagline_h); +} + export fn pardes_body_layer_value(index: u32, field: u32) u32 { const s = &(state orelse return 0); if (index >= pardes.MAX_PANES) return 0; -- cgit v1.3