summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaindropsSys <contact@minteck.org>2023-06-27 16:29:53 +0200
committerRaindropsSys <contact@minteck.org>2023-06-27 16:29:53 +0200
commit08edb928a9a93dcc1e3a07fff4955770c2e05986 (patch)
tree35a0009e2737d7222afa5da7250a3378b3416467
parent370a0a0c63fa4ad3b35e90409749ea5d9240c32d (diff)
downloadkirinos-08edb928a9a93dcc1e3a07fff4955770c2e05986.tar.gz
kirinos-08edb928a9a93dcc1e3a07fff4955770c2e05986.tar.bz2
kirinos-08edb928a9a93dcc1e3a07fff4955770c2e05986.zip
Updated 8 files, added 13 files and renamed .idea/misc.xml (automated)
-rw-r--r--.idea/discord.xml (renamed from .idea/misc.xml)2
-rw-r--r--.idea/inspectionProfiles/Project_Default.xml21
-rw-r--r--ROADMAP.md8
-rw-r--r--core/desktop/icons/close.svg1
-rw-r--r--core/desktop/icons/maximise.svg1
-rw-r--r--core/desktop/icons/minimise.svg1
-rw-r--r--core/desktop/icons/restore.svg1
-rw-r--r--core/desktop/index.html127
-rw-r--r--core/desktop/wm.js437
-rw-r--r--core/login/index.html1
-rw-r--r--core/startup/index.html1
-rw-r--r--core/warning.js17
-rw-r--r--lib/mangokit/index.js5
-rw-r--r--main.js10
-rw-r--r--node_modules/.package-lock.json8
-rw-r--r--node_modules/uuid-v4/index.js28
-rw-r--r--node_modules/uuid-v4/package.json13
-rw-r--r--node_modules/uuid-v4/readme.md33
-rw-r--r--package-lock.json11
-rw-r--r--package.json3
-rw-r--r--release.json12
-rw-r--r--test.html28
22 files changed, 753 insertions, 16 deletions
diff --git a/.idea/misc.xml b/.idea/discord.xml
index 30bab2a..d8e9561 100644
--- a/.idea/misc.xml
+++ b/.idea/discord.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
- <option name="show" value="ASK" />
+ <option name="show" value="PROJECT_FILES" />
<option name="description" value="" />
</component>
</project> \ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..edbb1c1
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,21 @@
+<component name="InspectionProjectProfileManager">
+ <profile version="1.0">
+ <option name="myName" value="Project Default" />
+ <inspection_tool class="HtmlUnknownTag" enabled="true" level="WARNING" enabled_by_default="true">
+ <option name="myValues">
+ <value>
+ <list size="7">
+ <item index="0" class="java.lang.String" itemvalue="nobr" />
+ <item index="1" class="java.lang.String" itemvalue="noembed" />
+ <item index="2" class="java.lang.String" itemvalue="comment" />
+ <item index="3" class="java.lang.String" itemvalue="noscript" />
+ <item index="4" class="java.lang.String" itemvalue="embed" />
+ <item index="5" class="java.lang.String" itemvalue="script" />
+ <item index="6" class="java.lang.String" itemvalue="webview" />
+ </list>
+ </value>
+ </option>
+ <option name="myCustomValuesEnabled" value="true" />
+ </inspection_tool>
+ </profile>
+</component> \ No newline at end of file
diff --git a/ROADMAP.md b/ROADMAP.md
index a770f41..bda794d 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -3,7 +3,7 @@
* [x] <s>Startup screen **- Raindrops**</s>
* [x] <s>Login screen **- Raindrops**</s>
* [ ] Desktop
- * [ ] Window manager
+ * [x] <s>Window manager **- Raindrops**</s>
* [x] <s>Application menu **- Raindrops**</s>
* [ ] Task bar **- Raindrops**
* [ ] Media keys
@@ -43,7 +43,7 @@
* [ ] Visual Studio Code
* [ ] Discord
* [ ] Gmail
-* [ ] mangoOS SDK **- Meadowsys**
+* [ ] mangoOS SDK (codename "MangoKit") **- Meadowsys**
* [ ] Window management **- Meadowsys**
* [ ] Notifications **- Meadowsys**
* [ ] Permissions **- Meadowsys**
@@ -65,7 +65,7 @@
* [ ] Compression API **- Meadowsys**
* [ ] Automation API **- Meadowsys**
* [ ] Helper libraries **- Raindrops**
- * [ ] `libmangoaudio` **- Raindrops**
+ * [x] <s>`libmangoaudio` **- Raindrops**</s>
* *More if needed*
* [ ] System apps
* [ ] Calculator
@@ -84,4 +84,4 @@
* [ ] Weather
* [ ] Console
* [ ] Disks
- * [ ] Vault (codename "Lyra") \ No newline at end of file
+ * [ ] Vault <s>(codename "Lyra")</s> \ No newline at end of file
diff --git a/core/desktop/icons/close.svg b/core/desktop/icons/close.svg
new file mode 100644
index 0000000..ded3e2a
--- /dev/null
+++ b/core/desktop/icons/close.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path d="m249-207-42-42 231-231-231-231 42-42 231 231 231-231 42 42-231 231 231 231-42 42-231-231-231 231Z"/></svg> \ No newline at end of file
diff --git a/core/desktop/icons/maximise.svg b/core/desktop/icons/maximise.svg
new file mode 100644
index 0000000..6bbab6b
--- /dev/null
+++ b/core/desktop/icons/maximise.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path d="M120-120v-300h60v198l558-558H540v-60h300v300h-60v-198L222-180h198v60H120Z"/></svg> \ No newline at end of file
diff --git a/core/desktop/icons/minimise.svg b/core/desktop/icons/minimise.svg
new file mode 100644
index 0000000..38a2730
--- /dev/null
+++ b/core/desktop/icons/minimise.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path d="M240-130v-60h481v60H240Z"/></svg> \ No newline at end of file
diff --git a/core/desktop/icons/restore.svg b/core/desktop/icons/restore.svg
new file mode 100644
index 0000000..739f079
--- /dev/null
+++ b/core/desktop/icons/restore.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path d="m122-80-42-42 298-298H180v-60h300v300h-60v-198L122-80Zm358-400v-300h60v198l298-298 42 42-298 298h198v60H480Z"/></svg> \ No newline at end of file
diff --git a/core/desktop/index.html b/core/desktop/index.html
index 718d688..6e72485 100644
--- a/core/desktop/index.html
+++ b/core/desktop/index.html
@@ -2,12 +2,12 @@
<html lang="en">
<head>
<meta charset="UTF-8">
+ <script src="../warning.js"></script>
<title>mangoos-shell</title>
<style>
* {
font-family: "Inter", sans-serif;
user-select: none;
- user-focus: none;
outline: none;
}
@@ -80,6 +80,108 @@
border-radius: 7px;
box-shadow: 0 0 20px 7px rgba(0, 0, 0, .3);
}
+
+ .window {
+ backdrop-filter: blur(50px);
+ background-color: rgba(255, 255, 255, .5);
+ position: fixed;
+ border-top-left-radius: 7px;
+ border-top-right-radius: 7px;
+ box-shadow: 0 0 20px 7px rgba(0, 0, 0, .3);
+ border: 1px solid rgba(0, 0, 0, .1);
+ }
+
+ .window-titlebar {
+ height: 32px;
+ border-top-left-radius: 7px;
+ border-top-right-radius: 7px;
+ background: rgba(255, 255, 255, .1);
+ border-bottom: 1px solid rgba(0, 0, 0, .1);
+ display: grid;
+ grid-template-columns: max-content 1fr;
+ }
+
+ .window-titlebar-title {
+ text-align: center;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .window-titlebar-control:hover {
+ background: rgba(0, 0, 0, .05);
+ }
+
+ .window-titlebar-control:active {
+ background: rgba(0, 0, 0, .1);
+ }
+
+ .window-minimised {
+ opacity: 0;
+ pointer-events: none;
+ }
+
+ .window-maximised {
+ border-radius: 0 !important;
+ left: 0 !important;
+ right: 0 !important;
+ top: 32px !important;
+ width: calc(100vw - 2px) !important;
+ height: calc(100vh - 34px) !important;
+ }
+
+ .window-titlebar-control-disabled {
+ opacity: .5;
+ pointer-events: none;
+ }
+
+ .window.window-inactive .window-titlebar, .window.window-inactive .window-contents {
+ opacity: .5;
+ }
+
+ .window.window-inactive .window-contents, .window.window-inactive webview {
+ pointer-events: none;
+ }
+
+ .window-anchors {
+ width: 100%;
+ height: calc(100% - 32px);
+ box-sizing: border-box;
+ }
+
+ .window-anchors .window-anchor {
+ width: 10px;
+ height: 10px;
+ border-radius: 50%;
+ background: transparent;
+ border: 3px solid transparent;
+ opacity: 0;
+ position: absolute;
+ }
+
+ .window-anchors .window-anchor.window-anchor-top-left {
+ left: -5px;
+ top: -5px;
+ cursor: nwse-resize;
+ }
+
+ .window-anchors .window-anchor.window-anchor-top-right {
+ right: -5px;
+ top: -5px;
+ cursor: nesw-resize;
+ }
+
+ .window-anchors .window-anchor.window-anchor-bottom-left {
+ left: -5px;
+ bottom: -5px;
+ cursor: nesw-resize;
+ }
+
+ .window-anchors .window-anchor.window-anchor-bottom-right {
+ right: -5px;
+ bottom: -5px;
+ cursor: nwse-resize;
+ }
</style>
</head>
<body>
@@ -99,6 +201,27 @@
<iframe style="width: 454px; height: 128px;" id="power" src="../power/index.html"></iframe>
</div>
+ <div id="window-container"></div>
+
+ <div id="debug" style="position: fixed; bottom: 8px; right: 8px; text-align: right; text-shadow: 0 0 5px white;"></div>
+ <script>
+ const fs = require("fs");
+
+ const release = JSON.parse(fs.readFileSync("./release.json").toString());
+
+ document.getElementById("debug").innerText = release['name'] + "\n" + (release['experimental']['platform'] ? "For testing purposes only. " : "") + "Build " + release['build'];
+ </script>
+
+ <script src="./wm.js"></script>
+ <script>
+ const wm = new WindowManager();
+ wm.createWindow({
+ title: "Test Window",
+ sandbox: false,
+ url: "file:///mango/test.html"
+ });
+ </script>
+
<script>
function statusUpdate(payload) {
console.info("update =>", payload);
@@ -125,8 +248,6 @@
document.getElementById("status-outer").style.pointerEvents = "";
}
- const fs = require("fs");
-
if (fs.existsSync("/mango/session/config/wallpaper")) {
document.getElementById("bg").style.backgroundImage = 'url("file:///mango/session/config/wallpaper")';
}
diff --git a/core/desktop/wm.js b/core/desktop/wm.js
new file mode 100644
index 0000000..b9abb00
--- /dev/null
+++ b/core/desktop/wm.js
@@ -0,0 +1,437 @@
+const uuid = require('uuid-v4');
+
+class WindowManager {
+ #stack;
+ #list;
+ #properties;
+
+ constructor() {
+ this.#stack = [];
+ this.#list = [];
+ this.#properties = {};
+ }
+
+ #updateFocus() {
+ this.#stack = [...new Set(this.#stack)].filter(i => i);
+ let index = 0;
+
+ for (let window of this.#stack) {
+ let el = document.getElementById("window-" + window);
+ if (!el || !window) {
+ index++;
+ continue;
+ }
+
+ el.style.zIndex = ((this.#stack.length - 1 - index) + 1).toString();
+
+ if (index === 0 && el.classList.contains("window-inactive")) {
+ // TODO: Broadcast a focus event to the client
+ el.classList.remove("window-inactive");
+ } else if (index !== 0 && !el.classList.contains("window-inactive")) {
+ // TODO: Broadcast a blur event to the client
+ el.classList.add("window-inactive");
+ }
+
+ index++;
+ }
+ }
+
+ getWindow(id) {
+ let properties = this.#properties;
+
+ return {
+ get title() {
+ return properties[id]["title"];
+ },
+ get minWidth() {
+ return properties[id]["minWidth"];
+ },
+ get maxWidth() {
+ return properties[id]["maxWidth"];
+ },
+ get width() {
+ return properties[id]["width"];
+ },
+ get minHeight() {
+ return properties[id]["minHeight"];
+ },
+ get maxHeight() {
+ return properties[id]["maxHeight"];
+ },
+ get height() {
+ return properties[id]["height"];
+ },
+ get x() {
+ return properties[id]["x"];
+ },
+ get y() {
+ return properties[id]["y"];
+ },
+ get movable() {
+ return properties[id]["movable"];
+ },
+ get resizable() {
+ return properties[id]["resizable"];
+ },
+ get closable() {
+ return properties[id]["closable"];
+ },
+ get minimizable() {
+ return properties[id]["minimizable"];
+ },
+ get maximizable() {
+ return properties[id]["maximizable"];
+ },
+ get focused() {
+ return properties[id]["focused"];
+ },
+ get minimised() {
+ return properties[id]["minimised"];
+ },
+ get maximised() {
+ return properties[id]["maximised"];
+ },
+
+ set title(val) {
+ if (typeof val !== "string") return;
+ properties[id]["title"] = val;
+ document.getElementById("window-" + id + "-titlebar-title").innerText = val;
+ },
+ set minWidth(val) {
+ if (typeof val !== "number") return;
+ properties[id]["minWidth"] = val;
+ },
+ set maxWidth(val) {
+ if (typeof val !== "number") return;
+ properties[id]["maxWidth"] = val;
+ },
+ set minHeight(val) {
+ if (typeof val !== "number") return;
+ properties[id]["minHeight"] = val;
+ },
+ set maxHeight(val) {
+ if (typeof val !== "number") return;
+ properties[id]["maxHeight"] = val;
+ },
+ set width(val) {
+ if (typeof val !== "number") return;
+ wm.resizeWindow(id, val, properties[id]["height"], properties[id]["x"], properties[id]["y"]);
+ },
+ set height(val) {
+ if (typeof val !== "number") return;
+ wm.resizeWindow(id, properties[id]["width"], val, properties[id]["x"], properties[id]["y"]);
+ },
+ set x(val) {
+ if (typeof val !== "number") return;
+ wm.moveWindow(id, val, properties[id]["y"]);
+ },
+ set y(val) {
+ if (typeof val !== "number") return;
+ wm.moveWindow(id, properties[id]["x"], val);
+ },
+ set movable(val) {
+ if (typeof val !== "boolean") return;
+ properties[id]["movable"] = val;
+ },
+ set resizable(val) {
+ if (typeof val !== "boolean") return;
+ properties[id]["resizable"] = val;
+ },
+ set closable(val) {
+ if (typeof val !== "boolean") return;
+ properties[id]["closable"] = val;
+ },
+ set maximizable(val) {
+ if (typeof val !== "boolean") return;
+ properties[id]["maximizable"] = val;
+ },
+ set minimizable(val) {
+ if (typeof val !== "boolean") return;
+ properties[id]["minimizable"] = val;
+ },
+ set minimised(val) {
+ if (typeof val !== "boolean") return;
+
+ if (val) {
+ wm.minimiseWindow(id);
+ } else {
+ wm.unminimiseWindow(id);
+ }
+ },
+ set maximised(val) {
+ if (typeof val !== "boolean") return;
+
+ if (val) {
+ wm.maximiseWindow(id);
+ } else {
+ wm.restoreWindow(id);
+ }
+ },
+ };
+ }
+
+ createWindow(options) {
+ let id = uuid();
+
+ this.#properties[id] = {
+ title: options['title'] ?? "(none)",
+ minWidth: options['minWidth'] ?? 64,
+ minHeight: options['minHeight'] ?? 64,
+ maxWidth: options['maxWidth'] ?? Infinity,
+ maxHeight: options['maxHeight'] ?? Infinity,
+ width: options['width'] ?? 256,
+ height: options['height'] ?? 256,
+ x: options['x'] ?? 0,
+ y: options['y'] ?? 0,
+ centered: options['centered'] ?? true,
+ movable: options['movable'] ?? true,
+ closable: options['closable'] ?? true,
+ maximizable: options['maximizable'] ?? true,
+ minimizable: options['minimizable'] ?? true,
+ focused: options['focused'] ?? true,
+ resizable: options['resizable'] ?? true,
+ minimised: options['minimised'] ?? false,
+ maximised: options['maximised'] ?? false
+ }
+
+ if (this.#properties[id].centered) {
+ this.#properties[id]['x'] = window.innerWidth / 2 - this.#properties[id]['width'] / 2;
+ this.#properties[id]['y'] = window.innerHeight / 2 - this.#properties[id]['height'] / 2;
+ }
+
+ document.getElementById("window-container").insertAdjacentHTML("beforeend", `
+ <div onmousedown="wm.focusWindow('${id}');" class="window" id="window-${id}" style="width: ${this.#properties[id]['width']}px; height: ${this.#properties[id]['height']}px; top: ${this.#properties[id]['y']}px; left: ${this.#properties[id]['x']}px;">
+ <div class="window-titlebar" id="window-${id}-titlebar">
+ <div class="window-titlebar-controls" id="window-${id}-titlebar-controls">
+ <a onclick="wm.closeWindow('${id}');" class="window-titlebar-control window-titlebar-control-close ${!this.#properties[id]['closable'] ? "window-titlebar-control-disabled" : ""}" id="window-${id}-titlebar-control-close" style="padding: 4px; vertical-align: middle; width: 24px; height: 24px; display: inline-block;border-top-left-radius: 7px;">
+ <img src="./icons/close.svg" style="width: 24px; vertical-align: middle;">
+ </a><a onclick="wm.toggleMinimisedWindow('${id}');" class="window-titlebar-control window-titlebar-control-minimise ${!this.#properties[id]['maximizable'] ? "window-titlebar-control-disabled" : ""}" id="window-${id}-titlebar-control-minimise" style="padding: 4px; vertical-align: middle; width: 24px; height: 24px; display: inline-block;">
+ <img src="./icons/minimise.svg" style="width: 24px; vertical-align: middle;">
+ </a><a onclick="wm.toggleMaximisedWindow('${id}');" class="window-titlebar-control window-titlebar-control-maximise ${!this.#properties[id]['minimizable'] ? "window-titlebar-control-disabled" : ""}" id="window-${id}-titlebar-control-maximise" style="padding: 4px; vertical-align: middle; width: 24px; height: 24px; display: inline-block;">
+ <img src="./icons/maximise.svg" style="width: 24px; vertical-align: middle;">
+ </a>
+ </div>
+ <div class="window-titlebar-title" id="window-${id}-titlebar-title" style="white-space: nowrap;overflow: hidden !important;text-overflow: ellipsis;">${this.#properties[id]['title']}</div>
+ </div>
+ <div class="window-contents" id="window-${id}-contents" style="height: calc(100% - 33px);">
+ <webview id="window-${id}-contents-webview" class="window-contents-webview" style="display: flex; height: 100%; width: 100%;" src="${options['url']}" preload="file:///mango/lib/mangokit/index.js" ${options['sandbox'] === false ? "nodeintegration" : ""}></webview>
+ </div>
+ ${this.#properties[id]['resizable'] ? `
+ <div class="window-anchors">
+ <div class="window-anchor window-anchor-top-left"></div>
+ <div class="window-anchor window-anchor-top-right"></div>
+ <div class="window-anchor window-anchor-bottom-left"></div>
+ <div class="window-anchor window-anchor-bottom-right"></div>
+ </div>
+ ` : ''}
+ </div>
+ `);
+
+ let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
+
+ document.getElementById("window-" + id + "-titlebar-title").onmousedown = (e) => {
+ document.querySelector('#window-' + id + ' .window-contents-webview').style.pointerEvents = "none";
+
+ e.preventDefault();
+ pos3 = e.clientX;
+ pos4 = e.clientY;
+
+ document.onmouseup = () => {
+ document.onmouseup = null;
+ document.onmousemove = null;
+ document.querySelector('#window-' + id + ' .window-contents-webview').style.pointerEvents = "";
+ }
+
+ document.onmousemove = (e) => {
+ e.preventDefault();
+ pos1 = pos3 - e.clientX;
+ pos2 = pos4 - e.clientY;
+ pos3 = e.clientX;
+ pos4 = e.clientY;
+
+ this.moveWindow(id, document.getElementById("window-" + id).offsetLeft - pos1, document.getElementById("window-" + id).offsetTop - pos2);
+ }
+ }
+
+ if (this.#properties[id].resizable) {
+ const resizers = document.querySelectorAll('#window-' + id + ' .window-anchor');
+ const element = document.getElementById("window-" + id);
+
+ const minimum_size_x = this.#properties[id].minWidth;
+ const minimum_size_y = this.#properties[id].minHeight;
+ let original_width = 0;
+ let original_height = 0;
+ let original_x = 0;
+ let original_y = 0;
+ let original_mouse_x = 0;
+ let original_mouse_y = 0;
+
+ for (let i = 0;i < resizers.length; i++) {
+ const currentResizer = resizers[i];
+ currentResizer.addEventListener('mousedown', function(e) {
+ document.querySelector('#window-' + id + ' .window-contents-webview').style.pointerEvents = "none";
+
+ e.preventDefault()
+ original_width = parseFloat(getComputedStyle(element, null).getPropertyValue('width').replace('px', ''));
+ original_height = parseFloat(getComputedStyle(element, null).getPropertyValue('height').replace('px', ''));
+ original_x = element.getBoundingClientRect().left;
+ original_y = element.getBoundingClientRect().top;
+ original_mouse_x = e.pageX;
+ original_mouse_y = e.pageY;
+ window.addEventListener('mousemove', resize)
+ window.addEventListener('mouseup', stopResize)
+ })
+
+ function resize(e) {
+ if (currentResizer.classList.contains('window-anchor-bottom-right')) {
+ const width = original_width + (e.pageX - original_mouse_x);
+ const height = original_height + (e.pageY - original_mouse_y)
+
+ wm.resizeWindow(id, width, height, null, null);
+ } else if (currentResizer.classList.contains('window-anchor-bottom-left')) {
+ const height = original_height + (e.pageY - original_mouse_y)
+ const width = original_width - (e.pageX - original_mouse_x)
+
+ wm.resizeWindow(id, width, height, original_x + (e.pageX - original_mouse_x), null);
+ } else if (currentResizer.classList.contains('window-anchor-top-right')) {
+ const width = original_width + (e.pageX - original_mouse_x)
+ const height = original_height - (e.pageY - original_mouse_y)
+
+ wm.resizeWindow(id, width, height, null, original_y + (e.pageY - original_mouse_y));
+ } else {
+ const width = original_width - (e.pageX - original_mouse_x)
+ const height = original_height - (e.pageY - original_mouse_y)
+
+ wm.resizeWindow(id, width, height, original_x + (e.pageX - original_mouse_x), original_y + (e.pageY - original_mouse_y));
+ }
+ }
+
+ function stopResize() {
+ document.querySelector('#window-' + id + ' .window-contents-webview').style.pointerEvents = "";
+ window.removeEventListener('mousemove', resize)
+ }
+ }
+ }
+
+ this.#stack.unshift(id);
+ this.#list.push(id);
+
+ this.#updateFocus();
+ }
+
+ moveWindow(id, x, y) {
+ if (!this.#properties[id].movable) return;
+
+ if (y < 32) return;
+ if (y > window.innerHeight - 32) return;
+ if (x < 32) return;
+ if (x > window.innerWidth - 128) return;
+
+ this.#properties[id].x = x;
+ this.#properties[id].y = y;
+
+ document.getElementById("window-" + id).style.top = y + "px";
+ document.getElementById("window-" + id).style.left = x + "px";
+
+ // TODO: Broadcast a move event to the client
+ }
+
+ resizeWindow(id, width, height, x, y) {
+ console.log(id, width, height, x, y);
+
+ if (width > this.#properties[id].minWidth && width > 96 && ((this.#properties[id].maxWidth > 0 && width < this.#properties[id].maxWidth) || this.#properties[id].maxWidth < 0) && width < window.innerWidth) {
+ this.#properties[id].width = width;
+ document.getElementById("window-" + id).style.width = width + 'px';
+
+ if (x) {
+ this.#properties[id].x = x;
+ document.getElementById("window-" + id).style.left = x + "px";
+ }
+ }
+
+ if (height > this.#properties[id].minHeight && height > 64 && ((this.#properties[id].maxHeight > 0 && height < this.#properties[id].maxHeight) || this.#properties[id].maxHeight < 0) && height < window.innerHeight) {
+ this.#properties[id].height = height;
+ document.getElementById("window-" + id).style.height = height + 'px'
+
+ if (y) {
+ this.#properties[id].y = y;
+ document.getElementById("window-" + id).style.top = y + "px";
+ }
+ }
+
+ // TODO: Broadcast a resize event to the client
+ }
+
+ closeWindow(id) {
+ document.getElementById("window-" + id).outerHTML = "";
+ delete this.#stack[this.#stack.indexOf(id)];
+ delete this.#list[this.#list.indexOf(id)];
+ delete this.#properties[id];
+ this.#updateFocus();
+
+ // TODO: Broadcast a close event to the client
+ }
+
+ toggleMinimisedWindow(id) {
+ if (document.getElementById("window-" + id).classList.contains("window-minimised")) {
+ wm.unminimiseWindow(id);
+ } else {
+ wm.minimiseWindow(id);
+ }
+ }
+
+ unminimiseWindow(id) {
+ if (!document.getElementById("window-" + id).classList.contains("window-minimised")) return;
+ document.getElementById("window-" + id).classList.remove("window-minimised");
+ this.#stack.unshift(id);
+ this.#updateFocus();
+ this.#properties[id].minimised = false;
+
+ // TODO: Broadcast an unminimise event to the client
+ }
+
+ minimiseWindow(id) {
+ if (document.getElementById("window-" + id).classList.contains("window-minimised")) return;
+ document.getElementById("window-" + id).classList.add("window-minimised");
+ delete this.#stack[this.#stack.indexOf(id)];
+ this.#updateFocus();
+ this.#properties[id].minimised = false;
+
+ // TODO: Broadcast a minimise event to the client
+ }
+
+ focusWindow(id) {
+ if (!document.getElementById("window-" + id).classList.contains("window-inactive")) return;
+ delete this.#stack[this.#stack.indexOf(id)];
+ this.#stack.unshift(id);
+ this.#updateFocus();
+
+ // TODO: Broadcast a focus event to the client
+ }
+
+ toggleMaximisedWindow(id) {
+ if (document.getElementById("window-" + id).classList.contains("window-maximised")) {
+ wm.restoreWindow(id);
+ } else {
+ wm.maximiseWindow(id);
+ }
+ }
+
+ restoreWindow(id) {
+ if (!document.getElementById("window-" + id).classList.contains("window-maximised")) return;
+ document.getElementById("window-" + id).classList.remove("window-maximised");
+ document.getElementById("window-" + id + "-titlebar-control-maximise").children[0].src = "./icons/maximise.svg";
+ this.#properties[id].maximised = false;
+
+ // TODO: Broadcast a restore AND a resize event to the client
+ }
+
+ maximiseWindow(id) {
+ if (document.getElementById("window-" + id).classList.contains("window-maximised")) return;
+ document.getElementById("window-" + id).classList.add("window-maximised");
+ document.getElementById("window-" + id + "-titlebar-control-maximise").children[0].src = "./icons/restore.svg";
+ this.#properties[id].maximised = true;
+
+ // TODO: Broadcast a maximise AND a resize event to the client
+ }
+} \ No newline at end of file
diff --git a/core/login/index.html b/core/login/index.html
index 3dc7006..b333fb9 100644
--- a/core/login/index.html
+++ b/core/login/index.html
@@ -2,6 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8">
+ <script src="../warning.js"></script>
<title>mangoos-login</title>
<style>
* {
diff --git a/core/startup/index.html b/core/startup/index.html
index adc4dbd..2246f04 100644
--- a/core/startup/index.html
+++ b/core/startup/index.html
@@ -2,6 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8">
+ <script src="../warning.js"></script>
<title>mangoos-startup</title>
<style>
* {
diff --git a/core/warning.js b/core/warning.js
new file mode 100644
index 0000000..343b0cf
--- /dev/null
+++ b/core/warning.js
@@ -0,0 +1,17 @@
+function _showWarning(version, name) {
+ console.log("%c ___ ____\n" +
+ " _ __ ___ __ _ _ __ __ _ ___ / _ \\/ ___|\n" +
+ "| '_ ` _ \\ / _` | '_ \\ / _` |/ _ \\| | | \\___ \\\n" +
+ "| | | | | | (_| | | | | (_| | (_) | |_| |___) |\n" +
+ "|_| |_| |_|\\__,_|_| |_|\\__, |\\___/ \\___/|____/\n" +
+ " |___/\n\n%c" + version + "\n\n------------------------------\n\n%cHere be dragons!\n%c(I'm not talking about Sparky)\n%c<!> READ THIS CAREFULLY. <!>\n%cThis is the " + name + " developer console. It runs %ccompletely unisolated%c and has %cfull hardware access%c. If you were asked to run code inside of this console, %cDO NOT DO THIS%c. You have been warned.\n", "opacity: 1; color: #d87e08; font-weight: bold;", "opacity: .5;", "color: red; font-size: 24px; margin-bottom: 10px;", "opacity: .25; font-size: 10px; margin-bottom: 10px;", "opacity: 1; color: yellow; background-color: red; font-size: 20px; margin-bottom: 10px;", "font-size: 14px; ", "font-size: 14px; font-weight: bold;", "font-size: 14px; ", "font-size: 14px; font-weight: bold;", "font-size: 14px; ", "font-size: 14px; font-weight: bold;", "font-size: 14px; ");
+}
+
+try {
+ require('fs').promises.readFile("/mango/release.json").then((b) => {
+ let data = JSON.parse(b.toString());
+ _showWarning(data['name'] + ", Build " + data['build'], data['name']);
+ })
+} catch (e) {
+ _showWarning("-", "mangoOS");
+} \ No newline at end of file
diff --git a/lib/mangokit/index.js b/lib/mangokit/index.js
new file mode 100644
index 0000000..a13a386
--- /dev/null
+++ b/lib/mangokit/index.js
@@ -0,0 +1,5 @@
+const { contextBridge } = require('electron');
+
+contextBridge.exposeInMainWorld("MangoKit", {
+ // TODO: Add stuff
+}); \ No newline at end of file
diff --git a/main.js b/main.js
index 399c853..a307dae 100644
--- a/main.js
+++ b/main.js
@@ -1,5 +1,7 @@
-const { app, BrowserWindow, globalShortcut, ipcMain } = require('electron')
-const path = require('path')
+const { app, BrowserWindow, globalShortcut, ipcMain } = require('electron');
+const path = require('path');
+
+process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true';
const createWindow = () => {
const mainWindow = new BrowserWindow({
@@ -22,10 +24,6 @@ const createWindow = () => {
mainWindow.focus();
});
- ipcMain.on("statusbar", (event, data) => {
- mainWindow.send("statusbar", data);
- });
-
globalShortcut.register('Alt+Shift+Tab', () => {
mainWindow.send("switchBack");
});
diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json
index e45769e..c1c86f5 100644
--- a/node_modules/.package-lock.json
+++ b/node_modules/.package-lock.json
@@ -945,6 +945,14 @@
"node": ">= 4.0.0"
}
},
+ "node_modules/uuid-v4": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/uuid-v4/-/uuid-v4-0.1.0.tgz",
+ "integrity": "sha512-m11RYDtowtAIihBXMoGajOEKpAXrKbpKlpmxqyztMYQNGSY5nZAZ/oYch/w2HNS1RMA4WLGcZvuD8/wFMuCEzA==",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/wordwrapjs": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz",
diff --git a/node_modules/uuid-v4/index.js b/node_modules/uuid-v4/index.js
new file mode 100644
index 0000000..ce0a0bb
--- /dev/null
+++ b/node_modules/uuid-v4/index.js
@@ -0,0 +1,28 @@
+
+exports = module.exports = function() {
+ var ret = '', value;
+ for (var i = 0; i < 32; i++) {
+ value = exports.random() * 16 | 0;
+ // Insert the hypens
+ if (i > 4 && i < 21 && ! (i % 4)) {
+ ret += '-';
+ }
+ // Add the next random character
+ ret += (
+ (i === 12) ? 4 : (
+ (i === 16) ? (value & 3 | 8) : value
+ )
+ ).toString(16);
+ }
+ return ret;
+};
+
+var uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
+exports.isUUID = function(uuid) {
+ return uuidRegex.test(uuid);
+};
+
+exports.random = function() {
+ return Math.random();
+};
+
diff --git a/node_modules/uuid-v4/package.json b/node_modules/uuid-v4/package.json
new file mode 100644
index 0000000..4badb74
--- /dev/null
+++ b/node_modules/uuid-v4/package.json
@@ -0,0 +1,13 @@
+{
+ "author": "James Brumond <james@jbrumond.me> (http://jbrumond.me)",
+ "name": "uuid-v4",
+ "description": "A simple v4 UUID generator",
+ "version": "0.1.0",
+ "main": "index.js",
+ "dependencies": {},
+ "devDependencies": {},
+ "optionalDependencies": {},
+ "engines": {
+ "node": "*"
+ }
+}
diff --git a/node_modules/uuid-v4/readme.md b/node_modules/uuid-v4/readme.md
new file mode 100644
index 0000000..0b8110f
--- /dev/null
+++ b/node_modules/uuid-v4/readme.md
@@ -0,0 +1,33 @@
+# uuid-v4
+
+A Node.js module for generating and validation V4 UUIDs
+
+## Install
+
+```bash
+$ npm install uuid-v4
+```
+
+## Usage
+
+```javascript
+var uuid = require('uuid-v4');
+
+// Generate a new UUID
+var myUUID = uuid();
+
+// Validate a UUID as proper V4 format
+uuid.isUUID(myUUID); // true
+```
+
+## MIT License
+
+Copyright (c) 2012 James Brumond
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
diff --git a/package-lock.json b/package-lock.json
index aff89cb..465642b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7,7 +7,8 @@
"dependencies": {
"electron": "^25.1.1",
"node-wifi": "^2.0.16",
- "systeminformation": "^5.18.3"
+ "systeminformation": "^5.18.3",
+ "uuid-v4": "^0.1.0"
}
},
"node_modules/@electron/get": {
@@ -952,6 +953,14 @@
"node": ">= 4.0.0"
}
},
+ "node_modules/uuid-v4": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/uuid-v4/-/uuid-v4-0.1.0.tgz",
+ "integrity": "sha512-m11RYDtowtAIihBXMoGajOEKpAXrKbpKlpmxqyztMYQNGSY5nZAZ/oYch/w2HNS1RMA4WLGcZvuD8/wFMuCEzA==",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/wordwrapjs": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz",
diff --git a/package.json b/package.json
index bc5ca27..475e015 100644
--- a/package.json
+++ b/package.json
@@ -2,6 +2,7 @@
"dependencies": {
"electron": "^25.1.1",
"node-wifi": "^2.0.16",
- "systeminformation": "^5.18.3"
+ "systeminformation": "^5.18.3",
+ "uuid-v4": "^0.1.0"
}
}
diff --git a/release.json b/release.json
new file mode 100644
index 0000000..6d71763
--- /dev/null
+++ b/release.json
@@ -0,0 +1,12 @@
+{
+ "name": "mangoOS Developer Preview",
+ "shortName": "mangoOS DP",
+ "version": "Developer Preview",
+ "shortVersion": "DP",
+ "experimental": {
+ "os": true,
+ "platform": true,
+ "apps": true
+ },
+ "build": "Dev"
+}
diff --git a/test.html b/test.html
new file mode 100644
index 0000000..f8b9504
--- /dev/null
+++ b/test.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>test</title>
+</head>
+<body>
+ <h1>Test app</h1>
+ <p>Hello, I am a test application</p>
+ <h2>Scroll me</h2>
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias atque consectetur deserunt ducimus earum eum expedita ipsa itaque laudantium magnam nostrum, nulla pariatur quo repellat rerum saepe, ut vel voluptate.</p>
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias atque consectetur deserunt ducimus earum eum expedita ipsa itaque laudantium magnam nostrum, nulla pariatur quo repellat rerum saepe, ut vel voluptate.</p>
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias atque consectetur deserunt ducimus earum eum expedita ipsa itaque laudantium magnam nostrum, nulla pariatur quo repellat rerum saepe, ut vel voluptate.</p>
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias atque consectetur deserunt ducimus earum eum expedita ipsa itaque laudantium magnam nostrum, nulla pariatur quo repellat rerum saepe, ut vel voluptate.</p>
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias atque consectetur deserunt ducimus earum eum expedita ipsa itaque laudantium magnam nostrum, nulla pariatur quo repellat rerum saepe, ut vel voluptate.</p>
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias atque consectetur deserunt ducimus earum eum expedita ipsa itaque laudantium magnam nostrum, nulla pariatur quo repellat rerum saepe, ut vel voluptate.</p>
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias atque consectetur deserunt ducimus earum eum expedita ipsa itaque laudantium magnam nostrum, nulla pariatur quo repellat rerum saepe, ut vel voluptate.</p>
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias atque consectetur deserunt ducimus earum eum expedita ipsa itaque laudantium magnam nostrum, nulla pariatur quo repellat rerum saepe, ut vel voluptate.</p>
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias atque consectetur deserunt ducimus earum eum expedita ipsa itaque laudantium magnam nostrum, nulla pariatur quo repellat rerum saepe, ut vel voluptate.</p>
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias atque consectetur deserunt ducimus earum eum expedita ipsa itaque laudantium magnam nostrum, nulla pariatur quo repellat rerum saepe, ut vel voluptate.</p>
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias atque consectetur deserunt ducimus earum eum expedita ipsa itaque laudantium magnam nostrum, nulla pariatur quo repellat rerum saepe, ut vel voluptate.</p>
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias atque consectetur deserunt ducimus earum eum expedita ipsa itaque laudantium magnam nostrum, nulla pariatur quo repellat rerum saepe, ut vel voluptate.</p>
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias atque consectetur deserunt ducimus earum eum expedita ipsa itaque laudantium magnam nostrum, nulla pariatur quo repellat rerum saepe, ut vel voluptate.</p>
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias atque consectetur deserunt ducimus earum eum expedita ipsa itaque laudantium magnam nostrum, nulla pariatur quo repellat rerum saepe, ut vel voluptate.</p>
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias atque consectetur deserunt ducimus earum eum expedita ipsa itaque laudantium magnam nostrum, nulla pariatur quo repellat rerum saepe, ut vel voluptate.</p>
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias atque consectetur deserunt ducimus earum eum expedita ipsa itaque laudantium magnam nostrum, nulla pariatur quo repellat rerum saepe, ut vel voluptate.</p>
+</body>
+</html> \ No newline at end of file