diff --git a/app/mxwm/startz.js b/app/mxwm/startz.js index bb6d374..6263cdb 100644 --- a/app/mxwm/startz.js +++ b/app/mxwm/startz.js @@ -6,13 +6,27 @@ async function drawScreen(ctx) { ctx.fillStyle = "darkcyan" ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height) + ctx.fillStyle = "cyan"; + ctx.font = "bold 14px comic-sans"; + ctx.textBaseline = "middle"; + ctx.textAlign = "left"; + ctx.fillText(`Alt+Shift+Q - выключить оконный менеджер | Alt+Enter - включить zterm | Alt+Shift+C - закрыть окно`, 10, 16); + for (const win of window.mxwm_windows) { - drawWindowDecorations(ctx, win.x, win.y, win.width, win.height, win.title) + drawWindowDecorations( + ctx, + win.wid == selected_window, + win.x, + win.y, + win.width, + win.height, + win.title + ) ctx.drawImage(win.canvas, win.x, win.y); } } -async function drawWindowDecorations(ctx, x, y, width, height, title) { +async function drawWindowDecorations(ctx, is_selected, x, y, width, height, title) { const borderRadius = 8; const borderWidth = 1; const buttonRadius = 6; @@ -23,7 +37,7 @@ async function drawWindowDecorations(ctx, x, y, width, height, title) { const outerWidth = width + borderWidth * 2 + 2; const outerHeight = height + headerHeight + borderWidth * 2 + 3; - ctx.fillStyle = "#f4f4f4"; + ctx.fillStyle = is_selected ? "#f4f4f4" : "#d3f4d3"; ctx.fillRect(outerX, outerY, outerWidth, outerHeight) ctx.fillStyle = "#222"; @@ -34,17 +48,56 @@ async function drawWindowDecorations(ctx, x, y, width, height, title) { } async function onStart(screen_ctx) { - executeCommand(["/app/zterm.js"]) + } -async function onKeyDown(ctx, key) { - if (key == "Escape") { - disableGraphics() +function moveWindowToTop(wid) { + let my_win + let windows = [] + for (let win of window.mxwm_windows) { + if (win.wid == wid) { + my_win = win + continue + } + windows.push(win) } + windows.push(my_win) + window.mxwm_windows = windows +} + +let altKey = false +let shiftKey = false +let ctrlKey = false + +async function onKeyDown(ctx, key) { + if (key == "Control") ctrlKey = true + if (key == "Alt") altKey = true + if (key == "Shift") shiftKey = true + + if (altKey && shiftKey && key == "Q") { + disableGraphics() + return + } + + if (altKey && shiftKey && key == "C") { + signalWindow(selected_window, 9) + closeWindow(selected_window) + return + } + + if (altKey && key == "Enter") { + executeCommand(["/app/zterm.js"]) + return + } + if (selected_window != null) getWindow(selected_window).onkeydown(key) } async function onKeyUp(ctx, key) { + if (key == "Control") ctrlKey = false + if (key == "Alt") altKey = false + if (key == "Shift") shiftKey = false + if (selected_window != null) getWindow(selected_window).onkeyup(key) } @@ -69,9 +122,11 @@ async function onMouseDown(ctx, button) { dragging_window = window["wid"] selected_window = window["wid"] setGraphicsCursor("grabbing") + moveWindowToTop(window.wid) } if (isMouseInside(window)) { selected_window = window["wid"] + moveWindowToTop(window.wid) window.onmousedown(button) } } diff --git a/app/mxwm/zcom.js b/app/mxwm/zcom.js index 3f55bc3..e5ffad2 100644 --- a/app/mxwm/zcom.js +++ b/app/mxwm/zcom.js @@ -4,6 +4,8 @@ function hasGraphicsImplementation() { /** returns wid and context */ function createWindow(options) { + console.log("create", options) + let canvas = document.createElement("canvas") let wid = Date.now().toString() + Math.round(Math.random() * 100).toString() @@ -37,7 +39,7 @@ function createWindow(options) { window.mxwm_windows = [ win ] } - return (wid, context) + return [wid, context] } function moveWindow(wid, x, y, w, h) { @@ -68,6 +70,8 @@ function signalWindow(wid, signal) { } function closeWindow(wid) { + console.log("remove", wid) + if (!("mxwm_windows" in window)) { window.mxwm_windows = [ ] } diff --git a/app/mxwm/zterm.js b/app/mxwm/zterm.js index eeb8455..4737974 100644 --- a/app/mxwm/zterm.js +++ b/app/mxwm/zterm.js @@ -4,8 +4,10 @@ let text = "" let stdin_text = "" let stdin_visible = true let stdin_disable = true +let ctx = null +let wid = null -async function draw(ctx) { +async function draw() { ctx.fillStyle = "black" ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height) @@ -19,6 +21,7 @@ async function draw(ctx) { y -= 18 } } + function setStdinFlag(flag) { if (flag == SILENT_STDIN) { stdin_visible = false @@ -42,6 +45,101 @@ async function readStdin() { async function writeStdout(wh) { text += wh + draw() +} + +async function readLine(on_key=(key, ctrl, alt, shift, content, pos) => [content, pos]) { + setStdinFlag(ENABLE_STDIN) + + let start_terminal = text + + // let start_cursor_pos = getCursor() + + let pos = 0 + let content = "" + + while (true) { + let event = await pollStdinEvent() + + if (event.type == "key") { + if (event.key == "Backspace") { + if (pos >= 1) { + content = content.slice(0, pos - 1) + content.slice(pos) + pos -= 1 + text = start_terminal + content + // let cursor = getCursor() + // setCursor(cursor[0]-1, cursor[1]) + // updateTerminalWOCursor() + } + } else if (event.key == "Delete") { + content = content.slice(0, pos) + content.slice(pos + 1) + text = start_terminal + content + // updateTerminalWOCursor() + // } else if (event.key == "ArrowLeft") { + // let cursor = getCursor() + // if (cursor[0] > start_cursor_pos[0]) { + // setCursor(cursor[0]-1, cursor[1]) + // pos -= 1 + // } + // } else if (event.key == "ArrowRight") { + // let cursor = getCursor() + // if (cursor[0] < start_cursor_pos[0] + content.length) { + // setCursor(cursor[0]+1, cursor[1]) + // pos += 1 + // } + } else { + let res = on_key(event.key, event.ctrl, event.alt, event.shift, content, pos) + text = text.slice(0, text.length - content.length) + res[0] + // updateTerminal() + // setCursor(start_cursor_pos[0] + res[1], start_cursor_pos[1]) + content = res[0] + pos = res[1] + } + } else if (event.type == "char") { + if (event.char == "\n") break + if (event.char == "\0") continue + + content = content.slice(0, pos) + event.char + content.slice(pos) + pos += 1 + } + + draw() + } + + setStdinFlag(DISABLE_STDIN) + + return content +} + +async function pollStdinEvent() { + let char = await readStdin() + + if (char == "\r") { + let key = "" + char = await readStdin() + while (char != "\r") { + key += char + char = await readStdin() + } + + let is_ctrl = key.charAt(0) == "1" + let is_alt = key.charAt(1) == "1" + let is_shift = key.charAt(2) == "1" + key = key.slice(3) + + return { + "type": "key", + "ctrl": is_ctrl, + "alt": is_alt, + "shift": is_shift, + "key": key + } + } + + return { + "type": "char", + "char": char + } } let altKey = false @@ -49,7 +147,6 @@ let ctrlKey = false let shiftKey = false async function onKeyDown(key) { - console.log(key) if (!stdin_disable) { if (key == "Enter") { stdin_text += "\n" @@ -72,6 +169,7 @@ async function onKeyDown(key) { stdin_text += "\r"+(ctrlKey ? "1" : "0")+(altKey ? "1" : "0")+(shiftKey ? "1" : "0")+key+"\r" } } + draw() } async function onKeyUp(key) { @@ -84,8 +182,8 @@ async function onKeyUp(key) { } } -async function main(args) { - let wid, ctx = createWindow({ +async function main(args) { + [wid, ctx] = createWindow({ "title": "zterm", "width": 500, "height": 500, @@ -95,12 +193,20 @@ async function main(args) { "onkeyup": onKeyUp }) - setTimeout(() => { - executeCommand(["/app/posh.js"], readStdin, writeStdout, setStdinFlag) - }) + draw() - while (graphics_canvas != null) { - draw(ctx) - await new Promise(res => setTimeout(res, 100)); - } + await executeCommand( + ["/app/posh.js"], + readStdin, + writeStdout, + setStdinFlag, + readLine, + pollStdinEvent + ).promise + + ctx = null + + console.log("posh exit") + + closeWindow(wid) } diff --git a/sys/system.js b/sys/system.js index 10ea7af..1497925 100644 --- a/sys/system.js +++ b/sys/system.js @@ -13,7 +13,45 @@ const SILENT_STDIN = 2 const DISABLE_STDIN = 3 const ENABLE_STDIN = 4 -const READ_FUNCTIONS_CODE = `async function readLine(on_key=(key, ctrl, alt, shift, content, pos) => [content, pos]) { +const EXECUTE_COMMAND_CODE = ` +function executeCommand( + args, + read=readStdin, + write=writeStdout, + set_flag=setStdinFlag, + read_line=readLine, + poll_stdin=pollStdinEvent, + inject="" +) { + let id = new Date().getMilliseconds().toString()+(Math.random()*100) + let func_content = readFile(args[0]) + if (func_content == null || !func_content.includes("function main")) return + let func = new Function( + "args", "readStdin", "writeStdout", "setStdinFlag", "readLine", "pollStdinEvent", + EXECUTE_COMMAND_CODE+"\\n"+inject+"\\n"+func_content+"\\nreturn main(args)" + ) + let process = { + "id": id, + "name": args.join(" "), + "promise": new Promise((resolve, reject) => { + setTimeout(() => { + try { + resolve(func(args, read, write, set_flag, read_line, poll_stdin)) + } catch (e) { + reject(e) + } + }, 0) + }).then(o => { + processes = processes.filter(x => x.id != id) + return o + }) + } + processes.push(process) + return process +}` + + +async function readLine(on_key=(key, ctrl, alt, shift, content, pos) => [content, pos]) { setStdinFlag(ENABLE_STDIN) let start_terminal = getTerminal() @@ -63,8 +101,8 @@ const READ_FUNCTIONS_CODE = `async function readLine(on_key=(key, ctrl, alt, shi continue } else if (event.type == "char") { - if (event.char == "\\n") break - if (event.char == "\\0") continue + if (event.char == "\n") break + if (event.char == "\0") continue content = content.slice(0, pos) + event.char + content.slice(pos) pos += 1 @@ -79,10 +117,10 @@ const READ_FUNCTIONS_CODE = `async function readLine(on_key=(key, ctrl, alt, shi async function pollStdinEvent() { let char = await readStdin() - if (char == "\\r") { + if (char == "\r") { let key = "" char = await readStdin() - while (char != "\\r") { + while (char != "\r") { key += char char = await readStdin() } @@ -106,34 +144,6 @@ async function pollStdinEvent() { "char": char } } - -function executeCommand(args, read=readStdin, write=writeStdout, set_flag=setStdinFlag, inject="") { - let id = new Date().getMilliseconds().toString()+(Math.random()*100) - let func_content = readFile(args[0]) - if (func_content == null || !func_content.includes("function main")) return - let func = new Function( - "args", "readStdin", "writeStdout", "setStdinFlag", - READ_FUNCTIONS_CODE+"\\n\\n\\n"+func_content+"\\n"+inject+"\\nreturn main(args)" - ) - let process = { - "id": id, - "name": args.join(" "), - "promise": new Promise((resolve, reject) => { - setTimeout(() => { - try { - resolve(func(args, read, write, set_flag)) - } catch (e) { - reject(e) - } - }, 0) - }).then(o => { - processes = processes.filter(x => x.id != id) - return o - }) - } - processes.push(process) - return process -}` async function readStdin() { while (stdin.length == 0) { @@ -161,34 +171,6 @@ function setStdinFlag(flag) { } } -function executeCommand(args, read=readStdin, write=writeStdout, set_flag=setStdinFlag, inject="") { - let id = new Date().getMilliseconds().toString()+(Math.random()*100) - let func_content = readFile(args[0]) - if (func_content == null || !func_content.includes("function main")) return - let func = new Function( - "args", "readStdin", "writeStdout", "setStdinFlag", - READ_FUNCTIONS_CODE+"\n\n\n"+func_content+"\n"+inject+"\nreturn main(args)" - ) - let process = { - "id": id, - "name": args.join(" "), - "promise": new Promise((resolve, reject) => { - setTimeout(() => { - try { - resolve(func(args, read, write, set_flag)) - } catch (e) { - reject(e) - } - }, 0) - }).then(o => { - processes = processes.filter(x => x.id != id) - return o - }) - } - processes.push(process) - return process -} - async function resetSystem() { clearFileSystem() @@ -204,6 +186,8 @@ async function resetSystem() { } } +eval(EXECUTE_COMMAND_CODE) + if (Object.keys(fs_mapping).length == 0) { resetSystem() } diff --git a/sys/terminal.js b/sys/terminal.js index 447206f..330fad6 100644 --- a/sys/terminal.js +++ b/sys/terminal.js @@ -157,7 +157,6 @@ var clipboard_collect = document.getElementById("clipboard-collect") document.onkeydown = (e) => { let key = e.key; if (!disable_stdin) { - console.log(e.key) if (key == "Enter") { stdin += "\n" if (!silent_stdin) {