KDE Plasma 6.4+ KWin script for snapping windows into zones with connected tile resizing.
Magnetile is a GPL-3.0 derivative of KZones. It keeps the core FancyZones-style zone workflow that made KZones useful, then extends it for a Wayland-only KDE Plasma 6 setup with connected resizing, stronger multi-monitor behavior, and a visual layout editor helper.
Development of the Magnetile-specific changes is AI-assisted. Human review, testing, packaging, and licensing responsibility remain with the Magnetile contributors.
Magnetile is not presented as an original clean-room replacement for KZones. It is derived from KZones and keeps KZones attribution in NOTICE.md. Because KZones is GPL-3.0, Magnetile is distributed under GPL-3.0 as well.
The goal is to preserve compatible KZones behavior while making targeted improvements for modern Plasma 6 Wayland workflows.
Magnetile keeps the original KZones-style workflow and feature set, including:
- FancyZones-style custom layouts made from percentage-based zones.
- A top-of-screen zone selector while dragging windows.
- A visual zone overlay while moving windows.
- Optional edge snapping.
- Multiple saved layouts.
- Keyboard shortcuts for moving windows to zones, cycling layouts, switching layouts, moving to neighboring zones, cycling windows in a zone, and snapping windows.
- Plasma color-scheme aware overlay and selector styling.
- JSON-based layout configuration.
These features come from the KZones base and are preserved so existing KZones users have a familiar workflow.
Compared with the original KZones base, Magnetile adds:
- Fluid connected resizing: adjacent tiled windows resize while a snapped window is manually resized, and later snaps can follow the resized runtime grid.
- KDE Plasma 6 / KWin 6 Wayland focus with no X11-specific code paths.
- Resolution-independent geometry fixes for multi-monitor layouts, including
outputs that do not start at
x=0, y=0. - Per-monitor layout defaults through
monitorLayoutsJson. - Independent active-layout tracking per output and optionally per virtual desktop.
- Free movement overrides for temporarily dragging a window outside Magnetile's snap grid.
- A visual layout editor helper for creating, renaming, duplicating, deleting, reordering, previewing, importing, and exporting JSON layouts.
- Editor support for snapping, padding preview, preview aspect ratios, and saved JSON layout files.
- Documentation for the current architecture, schema choices, local testing, and known KWin scripted-config limitations.
These features distinguish Magnetile from the original KZones base.
Resize a snapped window with the mouse and adjacent snapped windows on the same output, virtual desktop, activity, and layout resize live with it so the tile group stays connected. Future snaps on that output use the adjusted runtime grid until the script reloads or the configuration changes.
Recorded on 5120x1440.
Press Ctrl+Alt+F to toggle free movement for the active window. If you press
it while dragging a window, the current drop will stay at the custom size and
position. Press Ctrl+Alt+F again, or use any zone shortcut or snap shortcut,
to put the window back under Magnetile control.
Use the standalone browser editor at https://jcearnal.github.io/magnetile/ to design layouts without writing JSON by hand. The editor previews padding, screen ratios, and zone snapping, then exports the shared layout JSON schema used by Magnetile and KZones.
Each KWin output can seed its own default layout. Runtime layout switching can be tracked independently per monitor, and optionally per virtual desktop.
Magnetile keeps the familiar zone selector, drag overlay, edge snapping, multiple layouts, shortcuts, and Plasma-aware theming from its KZones base.
Drag a window toward the top of the current monitor to reveal a compact layout picker. Drop onto a zone preview to send the window there without cycling layouts first.
While moving a window, Magnetile can draw the active layout over the current monitor. Releasing the window over a highlighted zone snaps it into that zone.
Optional edge snapping lets a window target nearby zones when the pointer is close to a monitor edge. Disable KDE's built-in edge snap first if the two behaviors conflict.
Keep several percentage-based layouts and switch between them with shortcuts, the selector, or per-monitor defaults.
Shortcut actions cover moving windows to zones, switching layouts, moving to neighboring zones, cycling windows in a zone, and snapping all visible windows.
Overlay and selector colors follow the active Plasma color scheme.
- KDE Plasma 6.4 or newer
- KWin 6 on Wayland
kpackagetool6qdbus6makezip, or Python 3 for the Makefile fallback packager
Clone and install locally:
git clone https://github.com/jcearnal/magnetile.git
cd magnetile
make
kwriteconfig6 --file kwinrc --group Plugins --key magnetileEnabled true
qdbus6 org.kde.KWin /KWin reconfigure
qdbus6 org.kde.KWin /Scripting org.kde.kwin.Scripting.startAfter installing, open:
System Settings / Window Management / KWin Scripts
Enable Magnetile if it is not already enabled. Open Magnetile's settings with the gear button next to the script entry.
When updating an existing install, KWin may keep an older script instance alive. For normal QML/config changes, use the clean reload helper:
tools/reload-clean.sh --normalIf shortcut declarations or signal handlers changed, or if old development loads still appear in KWin logs, restart KWin after installing:
tools/reload-clean.sh --restartThe restart path calls qdbus6 org.kde.KWin /KWin org.kde.KWin.replace.
Open the settings from:
System Settings / Window Management / KWin Scripts / Magnetile / ⚙️
- Pick or create a layout in the Layouts tab.
- Move a window into a zone with
Ctrl+Alt+1..9, the top zone selector, or edge snapping if enabled. - Switch layouts with
Ctrl+Alt+Shift+1..9or cycle withCtrl+Alt+D. - Resize a snapped window by dragging an edge. Adjacent snapped windows in the same layout follow after release.
- Press
Ctrl+Alt+Fwhen a window should temporarily ignore Magnetile drag snapping.
Controls whether the top-of-screen layout picker appears while dragging a window, and how close the pointer needs to be before it opens.
Controls the moving-window overlay, when it appears, how zones are highlighted, and whether indicators show every zone or only the target zone.
Controls whether monitor edges can trigger zone targeting and how far from an edge the pointer can be before snapping begins.
Stores a window's floating geometry before it enters a zone and restores that geometry when it leaves Magnetile management.
Keeps the active layout separate for each KWin output. This is the setting that enables independent monitor presets.
Snaps new normal windows to the nearest zone as they appear.
Shows or hides layout-change OSD messages.
Temporarily dims other windows while one window is being moved.
Ctrl+Alt+F toggles free movement for the active window. A freed window keeps
its custom size and position when dragged, and Magnetile will not show the
snap overlay for that window. Press Ctrl+Alt+F again, or snap the window to a
zone, to return it to normal Magnetile control.
You can define your own layouts in the Layouts tab in the script settings.
layoutsJson is still the source of truth, but you do not have to hand-edit it
from scratch.
The visual layout editor is available on GitHub Pages:
https://jcearnal.github.io/magnetile/
The source lives in web-editor/. For local development, run a
static server from the repository root and open /web-editor/:
python3 -m http.server 8000Then open:
http://localhost:8000/web-editor/
The customizer is a browser helper, not a KWin settings page. It cannot write KWin settings directly.
To use it:
- Open Magnetile settings from
System Settings / Window Management / KWin Scripts / Magnetile / ⚙️. - Go to the Layouts tab.
- Copy the full JSON from the layout text box.
- Open the visual layout editor.
- Paste the JSON into the editor's JSON box and click Import pasted JSON.
- Edit layouts and zones visually.
- Keep Magnetile selected as the export target and click Copy JSON.
- Paste the generated JSON back into Magnetile's Layouts tab.
- Apply the settings, then disable and enable Magnetile or restart KWin if the new layout does not appear immediately.
The editor can also export KZones-compatible layout JSON. KZones users can
select KZones as the export target and paste the generated JSON into
System Settings / Window Management / KWin Scripts / KZones / Layouts.
You can also open and save .json files in the editor for backup or reuse.
The helper editor can:
- Create, rename, duplicate, delete, and reorder layouts.
- Add and delete zones.
- Move and resize zones by dragging.
- Snap zone edges to a grid, screen edges, or other zones.
- Preview common screen ratios and custom preview sizes.
- Preview layout padding on the canvas.
- Edit zone
x,y,width,height, and optionalcolorprecisely.
KWin's generic scripted config window cannot host a full drag/resize editor with custom save logic, so the helper keeps the existing KWin config model intact.
Example layouts:
Simple
[
{
"name": "Layout 1",
"padding": 0,
"zones": [
{
"x": 0,
"y": 0,
"height": 100,
"width": 25
},
{
"x": 25,
"y": 0,
"height": 100,
"width": 50
},
{
"x": 75,
"y": 0,
"height": 100,
"width": 25
}
]
}
]Advanced
[
{
"name": "Priority Grid",
"padding": 0,
"zones": [
{
"x": 0,
"y": 0,
"height": 100,
"width": 25
},
{
"x": 25,
"y": 0,
"height": 100,
"width": 50,
"applications": ["firefox"]
},
{
"x": 75,
"y": 0,
"height": 100,
"width": 25
}
]
},
{
"name": "Quadrant Grid",
"padding": 0,
"zones": [
{
"x": 0,
"y": 0,
"height": 50,
"width": 50
},
{
"x": 0,
"y": 50,
"height": 50,
"width": 50
},
{
"x": 50,
"y": 50,
"height": 50,
"width": 50
},
{
"x": 50,
"y": 0,
"height": 50,
"width": 50
}
]
},
{
"name": "Columns",
"padding": 0,
"zones": [
{
"x": 0,
"y": 0,
"height": 100,
"width": 25
},
{
"x": 25,
"y": 0,
"height": 100,
"width": 25
},
{
"x": 50,
"y": 0,
"height": 100,
"width": 25
},
{
"x": 75,
"y": 0,
"height": 100,
"width": 25
}
]
}
]The top-level value is an array of layout objects.
Each layout object supports:
name: The name of the layout, shown when cycling between layoutspadding: The amount of space between the window and the zone in pixelszones: An array containing all zone objects for this layout
Each zone object supports:
x,y: position of the top left corner of the zone in screen percentagewidth,height: size of the zone in screen percentageapplications: an array of window classes that should snap to this zone when launched (optional)indicator: an object containing the indicator settings (optional)position: default iscenter, other options aretop-left,top-center,top-right,right-center,bottom-right,bottom-center,bottom-left,left-centermargin: an object containing the margin for the indicatortop,right,bottom,left: margin in pixels
color: a color name or hex value to tint the zone with (optional)
Enable Track active layout per screen to keep a separate active layout for each physical output. Magnetile keys this by KWin output name, so monitor arrangements can be left, right, above, below, or use negative virtual coordinates.
Use Monitor layout defaults to seed a specific output or orientation with a
layout. The value is a JSON object whose keys are KWin output names,
landscape, or portrait, and whose values are layout names or zero-based
layout indexes:
{
"DP-1": "Priority Grid",
"HDMI-A-1": 1,
"landscape": "Priority Grid",
"portrait": "Horizontal Split"
}If no valid output or orientation default is set, Magnetile uses Priority Grid
on landscape outputs and Horizontal Split on portrait outputs when those
layouts exist. Orientation is part of the runtime per-screen key, so rotating a
monitor seeds a separate active layout for that orientation.
After a monitor has an active layout, layout switching on that monitor updates only that monitor's runtime selection. If Track active layout per virtual desktop is also enabled, Magnetile tracks the output and virtual desktop together.
Stop certain windows from snapping to zones by adding them to the filter list.
- Select Include or Exclude mode.
- Add one window class per line.
You can enable the debug overlay to see the window class of the active window.
The polling rate controls how often Magnetile checks hover state while dragging a window. Lower values feel more responsive and use more CPU.
Enable script logging or show the runtime debug overlay. The debug overlay is useful for finding a window's resource class for filters or application-based zone rules.
List of all available shortcuts:
| Shortcut | Default Binding |
|---|---|
| Move active window to zone | Ctrl + Alt + 1-9 |
| Move active window to previous zone | Ctrl + Alt + Left |
| Move active window to next zone | Ctrl + Alt + Right |
| Switch to previous window in current zone | Ctrl + Alt + Down |
| Switch to next window in current zone | Ctrl + Alt + Up |
| Cycle layouts | Ctrl + Alt + D |
| Cycle layouts (reversed) | Ctrl + Alt + Shift + D |
| Toggle zone overlay | Ctrl + Alt + C |
| Activate layout | Ctrl + Alt + Shift + 1-9 |
| Free active window | Ctrl + Alt + F |
| Reset current layout | Ctrl + Alt + R |
| Move active window up | Meta + Up |
| Move active window down | Meta + Down |
| Move active window left | Meta + Left |
| Move active window right | Meta + Right |
| Snap all windows | Meta + Space |
| Snap active window | Meta + Shift + Space |
To change the default bindings, go to System Settings / Shortcuts and search for Magnetile
Note
Not all shortcuts will be bound by default as they conflict with existing system bindings.
Multiple windows can occupy the same Magnetile zone. Use Ctrl+Alt+Up and
Ctrl+Alt+Down to cycle through visible windows in the active window's current
zone. The OSD reports the zone, stack position, stack size, and selected window.
Zone cycling is scoped to the same output, virtual desktop, activity, and layout. Minimized windows are skipped.
- Open three normal windows.
- Move them into the default Priority Grid using
Ctrl+Alt+1,Ctrl+Alt+2, andCtrl+Alt+3. - Resize the center window with the mouse by dragging its left or right edge.
- The adjacent window sharing that edge should resize live while dragging.
- Release the mouse and confirm the final geometry remains connected.
- For padded layouts, the visual gap between connected windows should remain.
- For split stacks, resize the full-height neighbor to move both stacked windows together. If you grab one half of the stack by accident, the matching split sibling should keep the same outer edge aligned.
- Snap another window into one of the resized zones. It should use the current resized grid, not the original JSON layout dimensions.
- Press
Ctrl+Alt+R. Windows in the current layout on the active output should return to the configured layout geometry.
Enable debug logging or the debug overlay when a nearby window does not follow a resize. These are independent toggles: logging writes the resize group to KWin logs, while the overlay shows the same resize summary while dragging. Magnetile reports the active resize group, participating windows, and windows skipped because they were filtered or outside the current scope.
If the resize debug overlay remains visible after disabling it, reload the current script build. A normal reload should be enough for config-only changes:
tools/reload-clean.sh --normalIf the overlay was created by an older running QML instance, restart KWin:
tools/reload-clean.sh --restartWhile daily driving Magnetile, useful things to note are resize jitter, windows that do not follow a resize, duplicated-looking resize participants, apps that resist requested geometry, stale shortcuts after reloads, and behavior changes after monitor, desktop, activity, or scaling changes.
- Move a window into a zone.
- Press
Ctrl+Alt+F; the OSD should say Free movement enabled. - Drag the window. The zone overlay should stay hidden and the window should keep the custom drop position.
- Press
Ctrl+Alt+Fagain; the OSD should say Free movement disabled. - Drag the window again. Magnetile snapping should be available again.
Magnetile ignores KDE Spectacle capture windows so Meta+Shift+S can select
regions across the full output even when Automatically snap all new windows
is enabled.
- Press
Meta+Shift+S. - Drag a region across each active Magnetile zone.
- Confirm the selector is not limited to a zone and the saved capture is not offset from the selected region.
Install the "Geometry change" KWin effect to animate window movements: https://store.kde.org/p/2136283
Replace the last part with any shortcut from the list above:
qdbus6 org.kde.kglobalaccel /component/kwin invokeShortcut "Magnetile: Cycle layouts"Sometimes KWin can leave behind corrupt or missing shortcuts in the Settings after uninstalling or updating scripts, you can remove those using this command:
qdbus6 org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.cleanUpConfirm you are running KDE Plasma 6.4+ on Wayland and that the Layouts setting contains at least one layout with at least one zone.
After changing settings, disable and enable the script again. KWin scripted config reloads can be inconsistent.
The visual customizer is not opened from System Settings. Open the local file
tools/layout-editor.html from the cloned Magnetile repository in a browser,
then copy JSON between the browser helper and Magnetile's Layouts settings
tab.
Press Ctrl+Alt+F again while the window is active, or use any zone shortcut
such as Ctrl+Alt+1. The OSD reports whether free movement is enabled or
disabled.
Follow KWin scripting logs while testing:
journalctl --user -u plasma-kwin_wayland -f QT_CATEGORY=kwin_scripting QT_CATEGORY=qml QT_CATEGORY=jsMagnetile targets KDE Plasma 6.4+ and Wayland. Plasma 5 and X11 are not supported.
Magnetile is derived from KZones and is distributed under GPL-3.0. Magnetile keeps upstream KZones attribution and documents Magnetile-specific AI-assisted changes in NOTICE.md.









