diff --git a/src/mach.js b/src/mach.js new file mode 100644 index 00000000..2c7e1e5d --- /dev/null +++ b/src/mach.js @@ -0,0 +1,77 @@ +const original_title = document.title; +const text_decoder = new TextDecoder(); +const text_encoder = new TextEncoder(); +let log_buf = ""; + +const mach = { + canvases: [], + wasm: undefined, + events: [], + + init(wasm) { + this.wasm = wasm; + }, + + getString(str, len) { + const memory = mach.wasm.exports.memory.buffer; + return text_decoder.decode(new Uint8Array(memory, str, len)); + }, + + setString(str, buf) { + const memory = this.wasm.exports.memory.buffer; + const strbuf = text_encoder.encode(str); + const outbuf = new Uint8Array(memory, buf, strbuf.length); + for (let i = 0; i < strbuf.length; i += 1) { + outbuf[i] = strbuf[i]; + } + }, + + machCanvasInit(width, height, id) { + let canvas = document.createElement("canvas"); + canvas.id = "#mach-canvas-" + mach.canvases.length; + canvas.width = width; + canvas.height = height; + canvas.tabIndex = 1; + + mach.setString(canvas.id, id); + + canvas.addEventListener("contextmenu", (ev) => ev.preventDefault()); + + document.body.appendChild(canvas); + return mach.canvases.push({ canvas: canvas, title: undefined }) - 1; + }, + + machCanvasDeinit(canvas) { + if (mach.canvases[canvas] != undefined) { + mach.canvases.splice(canvas, 1); + } + }, + + machCanvasSetTitle(canvas, title, len) { + const str = len > 0 ? + mach.getString(title, len) : + original_title; + + mach.canvases[canvas].title = str; + }, + + machCanvasSetSize(canvas, width, height) { + const cv = mach.canvases[canvas]; + if (width > 0 && height > 0) { + cv.canvas.width = width; + cv.canvas.height = height; + } + }, + + machCanvasGetWidth(canvas) { + const cv = mach.canvases[canvas]; + return cv.canvas.width; + }, + + machCanvasGetHeight(canvas) { + const cv = mach.canvases[canvas]; + return cv.canvas.height; + }, +}; + +export { mach }; diff --git a/src/wasm.zig b/src/wasm.zig index 842ee549..0353c777 100644 --- a/src/wasm.zig +++ b/src/wasm.zig @@ -4,17 +4,42 @@ const Engine = @import("Engine.zig"); const structs = @import("structs.zig"); const enums = @import("enums.zig"); -const js = struct {}; +const js = struct { + extern fn machCanvasInit(width: u32, height: u32, selector_id: *u8) CanvasId; + extern fn machCanvasDeinit(canvas: CanvasId) void; + extern fn machCanvasSetTitle(canvas: CanvasId, title: [*]const u8, len: u32) void; + extern fn machCanvasSetSize(canvas: CanvasId, width: u32, height: u32) void; + extern fn machCanvasGetWidth(canvas: CanvasId) u32; + extern fn machCanvasGetHeight(canvas: CanvasId) u32; +}; + +pub const CanvasId = u32; pub const CoreWasm = struct { - pub fn init(_: std.mem.Allocator, _: *Engine) !CoreWasm { - return CoreWasm{}; + id: CanvasId, + selector_id: []const u8, + + pub fn init(allocator: std.mem.Allocator, eng: *Engine) !CoreWasm { + const options = eng.options; + var selector = [1]u8{0} ** 15; + const id = js.machCanvasInit(options.width, options.height, &selector[0]); + + const title = std.mem.span(options.title); + js.machCanvasSetTitle(id, title.ptr, title.len); + + return CoreWasm{ + .id = id, + .selector_id = try allocator.dupe(u8, selector[0 .. selector.len - @as(u32, if (selector[selector.len - 1] == 0) 1 else 0)]), + }; } pub fn setShouldClose(_: *CoreWasm, _: bool) void {} - pub fn getFramebufferSize(_: *CoreWasm) !structs.Size { - return structs.Size{ .width = 0, .height = 0 }; + pub fn getFramebufferSize(core: *CoreWasm) !structs.Size { + return structs.Size{ + .width = js.machCanvasGetWidth(core.id), + .height = js.machCanvasGetHeight(core.id), + }; } pub fn setSizeLimits(_: *CoreWasm, _: structs.SizeOptional, _: structs.SizeOptional) !void {} diff --git a/www/template.html b/www/template.html new file mode 100644 index 00000000..0b45f3d2 --- /dev/null +++ b/www/template.html @@ -0,0 +1,38 @@ + + + + + + + + + +