From 8119bddf1663d15989cafd23795ac05e0109ed52 Mon Sep 17 00:00:00 2001 From: Peter Fajdiga Date: Fri, 6 Jan 2023 14:46:51 +0100 Subject: [PATCH] split main.js into files --- .gitignore | 2 + Makefile | 8 ++ run.sh | 2 +- src/Column.js | 21 ++++ src/Grid.js | 36 +++++++ src/LinkedList.js | 99 ++++++++++++++++++ src/Window.js | 10 ++ src/World.js | 45 +++++++++ src/actions.js | 13 +++ src/constants.js | 3 + src/main.js | 249 ---------------------------------------------- src/shortcuts.js | 14 +++ 12 files changed, 252 insertions(+), 250 deletions(-) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 src/Column.js create mode 100644 src/Grid.js create mode 100644 src/LinkedList.js create mode 100644 src/Window.js create mode 100644 src/World.js create mode 100644 src/actions.js create mode 100644 src/constants.js create mode 100644 src/shortcuts.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c1ee0b9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/build +/.idea diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..502f140 --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ +SHELL := /bin/bash -O extglob + +build: $(wildcard ./src/*.js) + mkdir -p ./build + cat ./src/!(main).js ./src/main.js > ./build/main.js + +run: build + ./run.sh diff --git a/run.sh b/run.sh index 66338eb..76df706 100755 --- a/run.sh +++ b/run.sh @@ -6,7 +6,7 @@ set -e bash_source_absolute="$(pwd)/${BASH_SOURCE[0]}" basalt_dir="$(dirname "$bash_source_absolute")" -kwin_script_path="$basalt_dir/src/main.js" +kwin_script_path="$basalt_dir/build/main.js" num=$(dbus-send --print-reply --dest=org.kde.KWin \ /Scripting org.kde.kwin.Scripting.loadScript \ diff --git a/src/Column.js b/src/Column.js new file mode 100644 index 0000000..d0802f0 --- /dev/null +++ b/src/Column.js @@ -0,0 +1,21 @@ +class Column { + constructor(grid) { + this.grid = grid; + this.windows = new LinkedList(); + this.width = null; + } + + addWindow(windowNode) { + const window = windowNode.item + const client = window.client; + this.windows.insertEnd(windowNode); + if (this.width === null) { + this.width = client.frameGeometry.width; + } + // TODO: also change column width if the new window requires it + } + + removeWindow(windowNode) { + this.windows.remove(windowNode); + } +} diff --git a/src/Grid.js b/src/Grid.js new file mode 100644 index 0000000..15ff4a8 --- /dev/null +++ b/src/Grid.js @@ -0,0 +1,36 @@ +class Grid { + constructor(desktopIndex) { + this.desktopIndex = desktopIndex; + this.columns = new LinkedList(); + + const desktopNumber = desktopIndex + 1; + this.area = workspace.clientArea(workspace.PlacementArea, 0, desktopNumber); + // TODO: multi-screen support + // TODO: react to changes in resolution + } + + addColumn(columnNode) { + this.columns.insertEnd(columnNode); + } + + removeColumn(columnNode) { + this.columns.remove(columnNode); + } + + arrange() { + let x = this.area.x + GAPS_OUTER.x; + for (const columnNode of this.columns.iterator()) { + const column = columnNode.item; + let y = this.area.y + GAPS_OUTER.y; + for (const windowNode of column.windows.iterator()) { + // TODO: resize height to fit all + const window = windowNode.item; + const client = window.client; + client.frameGeometry.x = x; + client.frameGeometry.y = y; + y += client.frameGeometry.height + GAPS_INNER.y; + } + x += column.width + GAPS_INNER.x; + } + } +} diff --git a/src/LinkedList.js b/src/LinkedList.js new file mode 100644 index 0000000..7e164ec --- /dev/null +++ b/src/LinkedList.js @@ -0,0 +1,99 @@ +class LinkedList { + constructor() { + this.firstNode = null; + this.lastNode = null; + } + + insertBefore(node, nextNode) { + const prevNode = nextNode === null ? null : nextNode.prev; + this.insert(node, prevNode, nextNode); + } + + insertAfter(node, prevNode) { + const nextNode = prevNode === null ? null : prevNode.next; + this.insert(node, prevNode, nextNode); + } + + insertStart(node) { + this.insertBefore(node, this.firstNode); + } + + insertEnd(node) { + this.insertAfter(node, this.lastNode); + } + + swap(node0, node1) { + assert(node0.next === node1 && node1.prev === node0); + const prevNode = node0.prev; + const nextNode = node1.next; + + if (prevNode !== null) { + prevNode.next = node1; + } + node1.next = node0; + node0.next = nextNode; + + if (nextNode !== null) { + nextNode.prev = node0; + } + node0.prev = node1; + node1.prev = prevNode; + + if (this.firstNode === node0) { + this.firstNode = node1; + } + if (this.lastNode === node1) { + this.lastNode = node0; + } + } + + remove(node) { + const prevNode = node.prev; + const nextNode = node.next; + if (prevNode !== null) { + prevNode.next = nextNode; + } + if (nextNode !== null) { + nextNode.prev = prevNode; + } + if (this.firstNode === node) { + this.firstNode = nextNode; + } + if (this.lastNode === node) { + this.lastNode = prevNode; + } + } + + insert(node, prevNode, nextNode) { + node.next = nextNode; + node.prev = prevNode; + if (nextNode !== null) { + assert(nextNode.prev === prevNode); + nextNode.prev = node; + } + if (prevNode !== null) { + assert(prevNode.next === nextNode); + prevNode.next = node; + } + if (this.firstNode === nextNode) { + this.firstNode = node; + } + if (this.lastNode === prevNode) { + this.lastNode = node; + } + } + + *iterator() { + for (let node = this.firstNode; node !== null; node = node.next) { + yield node; + } + } +} + +class LinkedListNode { + constructor(item) { + this.item = item; + this.prev = null; + this.next = null; + } +} diff --git a/src/Window.js b/src/Window.js new file mode 100644 index 0000000..e9206e4 --- /dev/null +++ b/src/Window.js @@ -0,0 +1,10 @@ +class Window { + constructor(columnNode, client) { + this.columnNode = columnNode; + this.client = client; + this.floatingSize = { + width: client.frameGeometry.width, + height: client.frameGeometry.height, + }; + } +} diff --git a/src/World.js b/src/World.js new file mode 100644 index 0000000..65d5e1a --- /dev/null +++ b/src/World.js @@ -0,0 +1,45 @@ +class World { + constructor(nDesktops) { + // TODO: react to changes in number of desktops + // TODO: support Plasma activities + this.grids = new Array(nDesktops); + for (let i = 0; i < nDesktops; i++) { + this.grids[i] = new Grid(i); + } + this.clientMap = new Map(); + } + + addClient(id, client) { + const desktopIndex = client.desktop - 1; + const grid = this.grids[desktopIndex]; + const column = new Column(grid); + const columnNode = new LinkedListNode(column); + const windowNode = new LinkedListNode(new Window(columnNode, client)); + + column.addWindow(windowNode); + grid.addColumn(columnNode); + grid.arrange(); + + this.clientMap.set(id, windowNode); + } + + removeClient(id) { + const windowNode = this.clientMap.get(id); + const window = windowNode.item; + const columnNode = window.columnNode; + const column = columnNode.item; + const grid = column.grid; + + column.removeWindow(windowNode); + grid.removeColumn(columnNode); + grid.arrange(); + + const clientRect = window.client.frameGeometry; + clientRect.x += UNATTACH_OFFSET.x; + clientRect.y += UNATTACH_OFFSET.y; + clientRect.width = window.floatingSize.width; + clientRect.height = window.floatingSize.height; + + this.clientMap.delete(id); + } +} diff --git a/src/actions.js b/src/actions.js new file mode 100644 index 0000000..f0a2fbe --- /dev/null +++ b/src/actions.js @@ -0,0 +1,13 @@ +function moveLeft() { + print("key pressed"); +} + +function toggleFloating() { + const client = workspace.activeClient; + const id = client.windowId; + if (world.clientMap.has(id)) { + world.removeClient(id); + } else { + world.addClient(id, client); + } +} diff --git a/src/constants.js b/src/constants.js new file mode 100644 index 0000000..ea26a64 --- /dev/null +++ b/src/constants.js @@ -0,0 +1,3 @@ +const UNATTACH_OFFSET = { x: 24, y: 24 }; +const GAPS_OUTER = { x: 24, y: 24 }; +const GAPS_INNER = { x: 12, y: 12 }; diff --git a/src/main.js b/src/main.js index fd9a8ab..40dcfe7 100644 --- a/src/main.js +++ b/src/main.js @@ -1,252 +1,3 @@ -const UNATTACH_OFFSET = { x: 24, y: 24 }; -const GAPS_OUTER = { x: 24, y: 24 }; -const GAPS_INNER = { x: 12, y: 12 }; - -class LinkedList { - constructor() { - this.firstNode = null; - this.lastNode = null; - } - - insertBefore(node, nextNode) { - const prevNode = nextNode === null ? null : nextNode.prev; - this.insert(node, prevNode, nextNode); - } - - insertAfter(node, prevNode) { - const nextNode = prevNode === null ? null : prevNode.next; - this.insert(node, prevNode, nextNode); - } - - insertStart(node) { - this.insertBefore(node, this.firstNode); - } - - insertEnd(node) { - this.insertAfter(node, this.lastNode); - } - - swap(node0, node1) { - assert(node0.next === node1 && node1.prev === node0); - const prevNode = node0.prev; - const nextNode = node1.next; - - if (prevNode !== null) { - prevNode.next = node1; - } - node1.next = node0; - node0.next = nextNode; - - if (nextNode !== null) { - nextNode.prev = node0; - } - node0.prev = node1; - node1.prev = prevNode; - - if (this.firstNode === node0) { - this.firstNode = node1; - } - if (this.lastNode === node1) { - this.lastNode = node0; - } - } - - remove(node) { - const prevNode = node.prev; - const nextNode = node.next; - if (prevNode !== null) { - prevNode.next = nextNode; - } - if (nextNode !== null) { - nextNode.prev = prevNode; - } - if (this.firstNode === node) { - this.firstNode = nextNode; - } - if (this.lastNode === node) { - this.lastNode = prevNode; - } - } - - insert(node, prevNode, nextNode) { - node.next = nextNode; - node.prev = prevNode; - if (nextNode !== null) { - assert(nextNode.prev === prevNode); - nextNode.prev = node; - } - if (prevNode !== null) { - assert(prevNode.next === nextNode); - prevNode.next = node; - } - if (this.firstNode === nextNode) { - this.firstNode = node; - } - if (this.lastNode === prevNode) { - this.lastNode = node; - } - } - - *iterator() { - for (let node = this.firstNode; node !== null; node = node.next) { - yield node; - } - } -} - -class LinkedListNode { - constructor(item) { - this.item = item; - this.prev = null; - this.next = null; - } -} - -class World { - constructor(nDesktops) { - // TODO: react to changes in number of desktops - // TODO: support Plasma activities - this.grids = new Array(nDesktops); - for (let i = 0; i < nDesktops; i++) { - this.grids[i] = new Grid(i); - } - this.clientMap = new Map(); - } - - addClient(id, client) { - const desktopIndex = client.desktop - 1; - const grid = this.grids[desktopIndex]; - const column = new Column(grid); - const columnNode = new LinkedListNode(column); - const windowNode = new LinkedListNode(new Window(columnNode, client)); - - column.addWindow(windowNode); - grid.addColumn(columnNode); - grid.arrange(); - - this.clientMap.set(id, windowNode); - } - - removeClient(id) { - const windowNode = this.clientMap.get(id); - const window = windowNode.item; - const columnNode = window.columnNode; - const column = columnNode.item; - const grid = column.grid; - - column.removeWindow(windowNode); - grid.removeColumn(columnNode); - grid.arrange(); - - const clientRect = window.client.frameGeometry; - clientRect.x += UNATTACH_OFFSET.x; - clientRect.y += UNATTACH_OFFSET.y; - clientRect.width = window.floatingSize.width; - clientRect.height = window.floatingSize.height; - - this.clientMap.delete(id); - } -} - -class Grid { - constructor(desktopIndex) { - this.desktopIndex = desktopIndex; - this.columns = new LinkedList(); - - const desktopNumber = desktopIndex + 1; - this.area = workspace.clientArea(workspace.PlacementArea, 0, desktopNumber); - // TODO: multi-screen support - // TODO: react to changes in resolution - } - - addColumn(columnNode) { - this.columns.insertEnd(columnNode); - } - - removeColumn(columnNode) { - this.columns.remove(columnNode); - } - - arrange() { - let x = this.area.x + GAPS_OUTER.x; - for (const columnNode of this.columns.iterator()) { - const column = columnNode.item; - let y = this.area.y + GAPS_OUTER.y; - for (const windowNode of column.windows.iterator()) { - // TODO: resize height to fit all - const window = windowNode.item; - const client = window.client; - client.frameGeometry.x = x; - client.frameGeometry.y = y; - y += client.frameGeometry.height + GAPS_INNER.y; - } - x += column.width + GAPS_INNER.x; - } - } -} - -class Column { - constructor(grid) { - this.grid = grid; - this.windows = new LinkedList(); - this.width = null; - } - - addWindow(windowNode) { - const window = windowNode.item - const client = window.client; - this.windows.insertEnd(windowNode); - if (this.width === null) { - this.width = client.frameGeometry.width; - } - // TODO: also change column width if the new window requires it - } - - removeWindow(windowNode) { - this.windows.remove(windowNode); - } -} - -class Window { - constructor(columnNode, client) { - this.columnNode = columnNode; - this.client = client; - this.floatingSize = { - width: client.frameGeometry.width, - height: client.frameGeometry.height, - }; - } -} - -function moveLeft() { - print("key pressed"); -} - -function toggleFloating() { - const client = workspace.activeClient; - const id = client.windowId; - if (world.clientMap.has(id)) { - world.removeClient(id); - } else { - world.addClient(id, client); - } -} - -function catchWrap(f) { - return _ => { - try { - f(); - } catch (error) { - print(error); - } - } -} - -function registerShortcuts() { - registerShortcut("basalt-window-move-left", "Basalt: Move window left", "Meta+Shift+A", moveLeft); - registerShortcut("basalt-window-toggle-floating", "Basalt: Toggle floating", "Meta+Space", catchWrap(toggleFloating)); -} - function init() { registerShortcuts(); } diff --git a/src/shortcuts.js b/src/shortcuts.js new file mode 100644 index 0000000..c5a2514 --- /dev/null +++ b/src/shortcuts.js @@ -0,0 +1,14 @@ +function catchWrap(f) { + return () => { + try { + f(); + } catch (error) { + print(error); + } + } +} + +function registerShortcuts() { + registerShortcut("basalt-window-move-left", "Basalt: Move window left", "Meta+Shift+A", moveLeft); + registerShortcut("basalt-window-toggle-floating", "Basalt: Toggle floating", "Meta+Space", catchWrap(toggleFloating)); +}