1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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);
|