Arrange floating windows freely while keeping their geometry aligned. KWin Compose snaps moved and resized windows to a shared screen grid without creating a tiling layout or rearranging other windows.
| Event | Operation |
|---|---|
| New window | Snap position and size |
| Move finished | Snap position only |
| Resize finished | Snap changed edges |
| Script enabled | Track existing windows without modifying them |
KWin maximization and edge tiling override grid snapping. Moving a window outside the work area is allowed. The script does not modify other windows, focus, stacking order, output, or virtual desktop.
Dialogs, popups, special windows, panels, notifications, hidden, minimized, maximized, full-screen, deleted, and invalid windows are excluded. KWin's own maximize and tiling preview outlines are never tracked or snapped, even when KWin reports them as normal windows.
- Base area:
KWin.MaximizeAreafor the window output and desktop. - Default grid step: 40 logical units.
- Default padding: 20 logical units on each side.
- Floating Breeze panel inset: 8 logical units before bottom padding.
- Window constraints:
moveable,resizeable,minSize, andmaxSize.
Application constraints override exact grid alignment and work-area containment. The grid is deterministic and idempotent.
src/config.js: defaults, limits, timing.src/grid.js: KWin-independent geometry and snapping.src/kwin-adapter.js: KWin API, signals, geometry, constraints, readiness.src/main.js: event controller and window lifecycle.scripts/kwin-entry.js: KWin bootstrap, Qt timers, configuration.scripts/build.mjs: bundle and.kwinscriptpackage generation.
The runtime is signal-driven and uses bounded readiness timers. Generated files
under package/contents/ and dist/ must not be edited.
KWin Compose does not manage layouts. Windows remain ordinary floating windows, may overlap, and are never rearranged as a group. Only their geometry is quantized to a shared grid after an individual window event.
| Environment | Status |
|---|---|
| KDE Plasma 6 | Required |
| Wayland on Arch Linux | Tested |
| XWayland applications | Manual testing required |
| X11 session | Not verified |
Requires Node.js 20 or newer.
npm install
npm run format
npm run check
npm test
npm run buildBuild outputs:
package/contents/code/main.jsdist/kwin-compose.kwinscript
Release archives attach dist/kwin-compose.kwinscript; end users do not need
Node.js.
Node tests cover geometry, the controller, and the KWin adapter.
tests/qt-smoke.qml checks Qt JavaScript compatibility. Plasma integration
requires manual Wayland and XWayland testing.
kpackagetool6 --type KWin/Script --install dist/kwin-compose.kwinscriptUpgrade an installed package:
kpackagetool6 --type KWin/Script --upgrade dist/kwin-compose.kwinscriptEnable Compose under System Settings → Window Management → KWin Scripts. Disable and re-enable the script after changing configuration.
Remove the package:
kpackagetool6 --type KWin/Script --remove kwin-composeKWin reads values from [Script-kwin-compose] in kwinrc.
| Key | Default |
|---|---|
DesiredStep |
40 |
PaddingLeft |
20 |
PaddingRight |
20 |
PaddingTop |
20 |
PaddingBottom |
20 |
FloatingPanelInset |
8 |
kwriteconfig6 --file kwinrc --group Script-kwin-compose --key DesiredStep 40