diff --git a/ac-electron/main.js b/ac-electron/main.js index 8a2a1218c6..3060d2f9a4 100644 --- a/ac-electron/main.js +++ b/ac-electron/main.js @@ -935,6 +935,22 @@ function createMenu() { isMac ? { role: 'close' } : { role: 'quit' } ] }, + // Edit menu — macOS only delivers Cmd+C/V/X/A to the page when these + // role items exist in the app menu; without them paste is dead app-wide. + { + label: 'Edit', + submenu: [ + { role: 'undo' }, + { role: 'redo' }, + { type: 'separator' }, + { role: 'cut' }, + { role: 'copy' }, + { role: 'paste' }, + ...(isMac ? [{ role: 'pasteAndMatchStyle' }] : []), + { role: 'delete' }, + { role: 'selectAll' } + ] + }, // Go menu (navigation) { label: 'Go', diff --git a/ac-electron/package-lock.json b/ac-electron/package-lock.json index d425b12902..8df6701274 100644 --- a/ac-electron/package-lock.json +++ b/ac-electron/package-lock.json @@ -1,12 +1,12 @@ { "name": "aesthetic-computer", - "version": "0.1.48", + "version": "0.1.49", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "aesthetic-computer", - "version": "0.1.48", + "version": "0.1.49", "license": "MIT", "dependencies": { "@electron/rebuild": "^4.0.2", diff --git a/ac-electron/package.json b/ac-electron/package.json index 04069e59cf..e1a1bf8800 100644 --- a/ac-electron/package.json +++ b/ac-electron/package.json @@ -1,6 +1,6 @@ { "name": "aesthetic-computer", - "version": "0.1.48", + "version": "0.1.49", "description": "Aesthetic Computer", "homepage": "https://aesthetic.computer", "author": "Aesthetic Computer ", diff --git a/system/public/aesthetic.computer/bios.mjs b/system/public/aesthetic.computer/bios.mjs index c77f87957e..70453a619d 100644 --- a/system/public/aesthetic.computer/bios.mjs +++ b/system/public/aesthetic.computer/bios.mjs @@ -11933,13 +11933,14 @@ async function boot(parsed, bpm = 60, resolution, debug) { // event listener on the document. // 📓 Re-adding the same label updates the hitbox in place. This matters // for pieces whose layout reflows on resize — the hitbox needs to - // track the latest button box. The `state` down/up flag is local to - // each handler closure and resets on re-add, which is fine so long - // as layout updates don't happen mid-tap. + // track the latest button box. Pieces that repaint every frame + // (laklok's marquee, blinking cursors) re-publish their buttons every + // frame, replacing this handler mid-tap — so the down/up state is + // carried over from the handler being replaced, otherwise pointerup + // never sees the pointerdown and the button can't fire. if (type === "button:hitbox:add") { - let state = "up"; // Event handler for each button press. - hitboxes[content.label] = async (e) => { + const handler = async (e) => { const frame = canvas.getBoundingClientRect(); const xscale = projectedWidth / canvas.width; const yscale = projectedHeight / canvas.height; @@ -11963,7 +11964,7 @@ async function boot(parsed, bpm = 60, resolution, debug) { const hit = hitbox.contains({ x: e.x, y: e.y }); - if (e.type === "pointerup" && state === "down" && hit) { + if (e.type === "pointerup" && handler.state === "down" && hit) { // This is pretty specific to the "copy" clipboard // stuff for now. 23.06.16.15.03 // console.log("🔘 Button tap label:", content.label); @@ -12087,13 +12088,15 @@ async function boot(parsed, bpm = 60, resolution, debug) { } } - state = "up"; + handler.state = "up"; } else if (e.type === "pointerdown" && hit) { - state = "down"; + handler.state = "down"; } else if (e.type === "pointerup" && !hit) { - state = "up"; + handler.state = "up"; } }; + handler.state = hitboxes[content.label]?.state || "up"; + hitboxes[content.label] = handler; return; }