summaryrefslogtreecommitdiff
path: root/config/kwin/sz-window-layout/contents/code/main.js
diff options
context:
space:
mode:
Diffstat (limited to 'config/kwin/sz-window-layout/contents/code/main.js')
-rw-r--r--config/kwin/sz-window-layout/contents/code/main.js57
1 files changed, 57 insertions, 0 deletions
diff --git a/config/kwin/sz-window-layout/contents/code/main.js b/config/kwin/sz-window-layout/contents/code/main.js
new file mode 100644
index 0000000..2b498a2
--- /dev/null
+++ b/config/kwin/sz-window-layout/contents/code/main.js
@@ -0,0 +1,57 @@
+// The window shortcuts from config/hammerspoon/init.lua, for KWin on Plasma 6.
+// Linked into ~/.local/share/kwin/scripts/ and enabled by link.sh.
+//
+// Every action is registered twice, because Toshy sits between the keyboard
+// and KWin. On a Mac keyboard it turns physical Ctrl into Meta in GUI apps but
+// leaves it as Ctrl in terminals, so the same physical Ctrl+Opt+2 reaches KWin
+// as Meta+Alt+2 in a browser and as Ctrl+Alt+2 in Ghostty. The Ctrl variant
+// also covers Toshy being paused or absent.
+//
+// KWin compiles this at load: after an edit, toggle the script off and on in
+// System Settings -> Window Management -> KWin Scripts. A changed default key
+// may not replace one already saved in kglobalshortcutsrc.
+
+// [key, name, left edge, width], as fractions of the usable screen area.
+const layouts = [
+ ["1", "Maximize", 0, 1],
+ ["2", "Left 50%", 0, 0.5],
+ ["3", "Right 50%", 0.5, 0.5],
+ ["4", "Left 30%", 0, 0.3],
+ ["5", "Right 70%", 0.3, 0.7],
+ ["6", "Left 25%", 0, 0.25],
+ ["7", "Right 75%", 0.25, 0.75],
+ ["8", "Left 20%", 0, 0.2],
+ ["9", "Right 80%", 0.2, 0.8],
+];
+
+function place(x, w) {
+ const win = workspace.activeWindow;
+ if (!win) return;
+ const area = workspace.clientArea(KWin.MaximizeArea, win);
+ // Rounding both edges rather than the width keeps a left/right pair flush.
+ const left = Math.round(area.x + area.width * x);
+ const right = Math.round(area.x + area.width * (x + w));
+ // A window left in a quick tile (Meta+Left/Right) or maximized would
+ // otherwise be pulled back to that geometry.
+ win.tile = null;
+ win.setMaximize(false, false);
+ win.frameGeometry = { x: left, y: area.y, width: right - left, height: area.height };
+}
+
+function nextScreen() {
+ const win = workspace.activeWindow;
+ if (!win) return;
+ const screens = workspace.screens;
+ // By name: the wrappers of one output are not guaranteed to be ===.
+ let i = 0;
+ while (i < screens.length && screens[i].name !== win.output.name) i++;
+ workspace.sendClientToScreen(win, screens[(i + 1) % screens.length]);
+}
+
+for (const [key, name, x, w] of layouts) {
+ const fn = () => place(x, w);
+ registerShortcut(`sz ${name}`, `sz: ${name}`, `Meta+Alt+${key}`, fn);
+ registerShortcut(`sz ${name} (Ctrl)`, `sz: ${name} (Ctrl)`, `Ctrl+Alt+${key}`, fn);
+}
+registerShortcut("sz Next Screen", "sz: Next Screen", "Meta+Shift+Space", nextScreen);
+registerShortcut("sz Next Screen (Ctrl)", "sz: Next Screen (Ctrl)", "Ctrl+Shift+Space", nextScreen);