╭ changed ────╮ │build.zig.zon│ ╰─────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 3 .version = "0.0.0", │ │ 4 .dependencies = .{ │ │ 5 .xit = .{ │ │ 6 - .url = "git+https://github.com/xit-vcs/xit#1a3a1a5fa7c4ba02744143860a163ca9c3ba6134",│ │ 7 - .hash = "xit-0.0.0-Ub3nDNd6TwHoFJU-wpiLMIT_unxAx6zF2YJvLL5LrOU6", │ │ 6 + .url = "git+https://github.com/xit-vcs/xit#79042ff35368db1b5eb0cc187d34b2c4ccd70603",│ │ 7 + .hash = "xit-0.0.0-Ub3nDDKUTwHvU_taqYYqUs7Pbx8kg5Yrgcks_URi4AKm", │ │ 8 }, │ │ 9 }, │ │10 .paths = .{ │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───────────╮ │src/assets/script.js│ ╰────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────╮ │ 7 │ │ 8 const MIN_COLS = 30; │ │ 9 │ │10 -// measured once after the font is loaded. recomputed lazily if it ever │ │11 -// reads back as zero (e.g. measured before the font was actually ready).│ │10 +// measured once after the font is loaded. recomputed lazily if they ever│ │11 +// read back as zero (e.g. measured before the font was actually ready). │ │12 let cellWidth = null; │ │13 +let cellHeight = null; │ │14 │ │14 -function measureCellWidth() { │ │15 +function measureCellSize() { │ │16 const probe = document.createElement("span"); │ │17 probe.style.position = "absolute"; │ │18 probe.style.visibility = "hidden"; │ ╰─────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────╮ │19 probe.style.whiteSpace = "pre"; │ │20 probe.textContent = "X".repeat(100); │ │21 grid.appendChild(probe); │ │21 - const w = probe.getBoundingClientRect().width / 100;│ │22 + const rect = probe.getBoundingClientRect(); │ │23 probe.remove(); │ │23 - return w; │ │24 + cellWidth = rect.width / 100; │ │25 + cellHeight = rect.height; │ │26 } │ │27 │ │28 function maxCols() { │ ╰────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────╮ │27 - if (!cellWidth) cellWidth = measureCellWidth(); │ │29 + if (!cellWidth) measureCellSize(); │ │30 return Math.max(MIN_COLS, Math.floor(document.body.clientWidth / cellWidth));│ │31 } │ │32 │ ╰─────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────╮ │72 event.preventDefault(); │ │73 } │ │74 wasmInstance.exports._onKeyDown(event.keyCode); │ │75 + wasmInstance.exports._tick(maxCols()); │ │76 + }); │ │77 + │ │78 + grid.addEventListener("click", (event) => { │ │79 + // ensure cellWidth/cellHeight are measured before converting pixels to grid cells│ │80 + maxCols(); │ │81 + const rect = grid.getBoundingClientRect(); │ │82 + const col = Math.floor((event.clientX - rect.left) / cellWidth); │ │83 + const row = Math.floor((event.clientY - rect.top) / cellHeight); │ │84 + if (col < 0 || row < 0) return; │ │85 + wasmInstance.exports._onMouseClick(col, row); │ │86 wasmInstance.exports._tick(maxCols()); │ │87 }); │ │88 │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ────────╮ │src/main_wasm.zig│ ╰─────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────╮ │66 try root_ptr.input(key, root_ptr.getFocus()); │ │67 } │ │68 │ │69 +fn onMouseClick(x: usize, y: usize) !void { │ │70 + const root_ptr = if (root) |*root_value| root_value else return error.NotStarted; │ │71 + const root_focus = root_ptr.getFocus(); │ │72 + var iter = root_focus.children.iterator(); │ │73 + while (iter.next()) |entry| { │ │74 + const child = entry.value_ptr.*; │ │75 + if (!child.focus.focusable) continue; │ │76 + const r = child.rect; │ │77 + if (x >= r.x and y >= r.y and x < r.x + r.size.width and y < r.y + r.size.height) {│ │78 + try root_focus.setFocus(entry.key_ptr.*); │ │79 + break; │ │80 + } │ │81 + } │ │82 +} │ │83 + │ │84 fn consoleLog(arg: []const u8) void { │ │85 _consoleLog(arg.ptr, @intCast(arg.len)); │ │86 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────╮ │126 }; │ │127 } │ │128 │ │129 +export fn _onMouseClick(x: u32, y: u32) void { │ │130 + onMouseClick(x, y) catch |err| { │ │131 + var buf: [256]u8 = undefined; │ │132 + const str = std.fmt.bufPrint(&buf, "onMouseClick: {}", .{err}) catch unreachable;│ │133 + consoleLog(str); │ │134 + }; │ │135 +} │ │136 + │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────╮ │38 while (try terminal.readKey(io, blocking)) |key| { │ │39 switch (key) { │ │40 .codepoint => |cp| if (cp == 'q') return else try root.input(key, root.getFocus()),│ │41 + .mouse => |mouse| { │ │42 + if (mouse.action == .press and mouse.action.press == .left) { │ │43 + const root_focus = root.getFocus(); │ │44 + var iter = root_focus.children.iterator(); │ │45 + while (iter.next()) |entry| { │ │46 + const child = entry.value_ptr.*; │ │47 + if (!child.focus.focusable) continue; │ │48 + const r = child.rect; │ │49 + if (mouse.x >= r.x and mouse.y >= r.y and │ │50 + mouse.x < r.x + r.size.width and mouse.y < r.y + r.size.height) │ │51 + { │ │52 + try root_focus.setFocus(entry.key_ptr.*); │ │53 + break; │ │54 + } │ │55 + } │ │56 + } else { │ │57 + try root.input(key, root.getFocus()); │ │58 + } │ │59 + }, │ │60 else => try root.input(key, root.getFocus()), │ │61 } │ │62 blocking = false; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────╮ │277 index = @min(index + half_count, children.count() - 1);│ │278 } │ │279 } │ │280 + }, │ │281 + .mouse => |mouse| switch (mouse.action) { │ │282 + .scroll => |dir| switch (dir) { │ │283 + .up => index -|= 1, │ │284 + .down => if (index + 1 < children.count()) { │ │285 + index += 1; │ │286 + }, │ │287 + }, │ │288 + else => {}, │ │289 }, │ │290 else => {}, │ │291 } │ ╰────────────────────────────────────────────────────────────────────────────────────────────╯