PlasmaZones v3.0.0
Added
- Virtual screens for ultrawide monitors: physical monitors can be subdivided into independent logical screens, each with its own layouts, autotile state, snap-assist, OSDs, shortcuts, and per-desktop or per-activity assignments. A new
VirtualScreenSwapperexposes swap and rotate D-Bus methods plus global shortcuts, and a monitor-level OSD acknowledges the action so the user sees which regions moved. The layout editor and settings app are virtual-screen aware throughout, and the configuration UI moved from the editor into the settings app. - Animation App Rules: a new Animations → App Rules page assigns motion curves, shader overrides, and per-event timings to specific window classes. The resolver cascades through global, app-rule, and window-filter layers inside the kwin-effect, and the editor supports curve picking, shader-parameter overrides, lock and randomize controls, and window-class filtering with a
Disable animationsshort-circuit. A two-layer resolver with leaf seeds gives widgets distinctive tunings even when they share a parent rule. - Unified
PassiveOverlayShell: OSDs, snap-assist, the layout picker, the zone selector, and the main zone overlay now run inside one shell surface instead of five separate layer-shell windows. The shell is click-through except when a modal popup is up, hides itself when no slot is visible so clicks pass through, releases its input region after every slot show, and enforces explicit z-order. Slots animate independently, so a snap-assist show no longer cancels an in-flight OSD. Replaces the legacyNotificationOverlay.qmllifecycle. - Krohnkite-style autotile reorder and unlimited stack: dragging a tiled window onto another inserts or swaps it into the target slot live via a new Reorder drag behavior. A new Unlimited overflow lets the stack grow past the algorithm's natural cap instead of evicting windows. Drag-insert has always-active and toggle modes matching the snap trigger, and the dropdowns are exposed in Settings → Tiling → Behavior.
- Animation engine and 47 ported shader transitions: window transitions run through a new
OffscreenEffectredirect path with vertex-shader plumbing, parent-FBO bounds extent, live-texture sampling of the rendered surface, and direction-aware leg signals. The release ships compatibility shims that port 28 niri animation shaders vianiri_compatand 9 Burn-My-Windows shaders viabmw_compat, plus 10 new BMW-inspired transitions, an audio-reactiveneon-citycityscape, a Matrix rain port, a 3Dchrome-protocolrewrite, and user-texture support for image-driven effects. OSDs use surface sampling for morph, slide, slidefade, and popin. - Animations settings UI overhaul: an eight-phase rework adds an
AnimationsPageControllerand drill-down sub-pages for OSDs, overlays, shaders, motion sets, app rules, widgets, windows, and side panels. The Shaders page hosts a per-event shader picker backed by a generic shader browser. Motion sets bundle themed overrides users can switch between. A timing-mode toggle on the General page and change detection on save round it out. A separate Snapping → Shaders page exposes the same browser for snap-assist, zone-selector, and layout-picker effects. - Layout ordering for cycling: the cycle shortcut and zone-selector cycling follow a user-configurable order set under Settings → Snapping → Ordering and Settings → Tiling → Ordering, instead of the implicit save-time order.
- Per-mode disable lists: snapping and autotiling each have their own exclusion lists for monitors, virtual desktops, and activities, replacing the single global disable. The disabled-context OSD explains which exclusion is active so the user can find the toggle.
- Native-feeling wheel scroll in settings (#405): every Flickable settings page uses
Kirigami.WheelHandlerso scroll speed matches the rest of Plasma System Settings, while preserving the Flickable drag-to-flick path. - Hold/Toggle controls now work in always-active mode (#249): "Hold to activate" and "Toggle mode" stay enabled when "Activate on every drag" is on, with inverted semantics. The configured trigger deactivates the overlay instead of activating it, so a binding like Right Mouse Button activates when always-active is off and deactivates when on. Esc continues to cancel the drag entirely.
- Global "auto-assign new windows for all layouts" toggle (#370): a master switch in Snapping Behavior → Window Handling that forces auto-assign on for every manual layout, regardless of the per-layout icon. Effective behavior is
globalToggle OR layout.autoAssign, and the default is off so existing semantics are preserved on upgrade. While the global is on, the per-layout toggle is disabled and the Auto/Manual badge in the Layouts grid, layout combo, zone selector, layout picker, and layout OSD shows the effective on state. - Separate "Desktop switch OSD" toggle (#372, #373): the layout-preview OSD that fires on virtual-desktop change, activity change, and daemon startup is now governed by its own setting,
Snapping.Effects/OsdOnDesktopSwitch, independent ofOsdOnLayoutSwitch. Manual layout switches continue to gate on the existing layout-switch toggle. Default istrueto preserve current behavior. Upgrade note: users who previously setOsdOnLayoutSwitch=falseto silence the startup or VD-switch flash will see those OSDs return on first launch under the new schema. Toggle "Desktop switch OSD" off in Settings → On-Screen Display to restore the old quiet behavior. - New D-Bus methods:
setPerScreenSettingsaccepts a batched per-screen settings map so the editor and KCM can apply screen-scoped changes in one round-trip.requestRunningWindowsand therunningWindowsAvailablesignal give the App Rules editor an async window picker that doesn't block while the daemon enumerates KWin clients. - Phosphor SDK foundation libraries: core services are extracted into reusable LGPL libraries, each with its own export macro, headers, and minimal Qt dependencies. The set covers
phosphor-engine(renamed fromphosphor-engine-api),phosphor-layout-api,phosphor-animation,phosphor-shaders(extracted fromphosphor-shell),phosphor-workspaces(VirtualDesktopManager and ActivityManager),phosphor-placement(WindowTrackingService and WindowRegistry),phosphor-tiles,phosphor-zonesfor manual zone-layout primitives,phosphor-screens,phosphor-snap-engineandphosphor-tile-enginefor the physically moved SnapEngine and AutotileEngine,phosphor-config,phosphor-fsloader(renamed fromphosphor-jsonloader, with theWatchedDirectorySetbase extracted),phosphor-shell-patterns,phosphor-wayland(renamed fromphosphor-shell), andphosphor-layer. Geometry primitives use domain-neutral identifiers so the libraries are reusable outside PlasmaZones.SnapStateis now the single source of truth for snap window state, owned bySnapEngine. Forwarding headers were removed in favor of direct library includes. - Phosphor compositor SDK: a new
phosphor-compositorlibrary exposesDaemonClientplus handler interfaces, extracted from the oldcompositor-common, so third-party Wayland compositors such as river can host the placement, tiling, and overlay services without depending on KWin.
Changed
- KCM Apply now respects the layout-switch OSD toggle: the per-screen preview OSDs emitted after a System Settings → Apply previously fired unconditionally, ignoring the user's
OsdOnLayoutSwitchsetting. They now gate on the same flag as cycle, quick-layout, and zone-selector drop. The locked-context OSD remains unconditional so it can explain why a requested change had no visible effect on a locked screen. - Drag protocol refactor (#310): the kwin-effect is now a dumb relay for drag events. The daemon owns all drag routing decisions through a new
beginDrag,updateDragCursor, andendDragprotocol with typedDragPolicyandDragOutcomestructs. The previous effect-side distributed state (m_dragBypassedForAutotile,m_cachedZoneSelectorEnabled,m_autotileScreenslocal cache) went stale during the asynchronous settings-reload window and produced ~40 seconds of dead drags in the reporter's log on #310. The new protocol makes the daemon the single source of truth at drag start, drag cursor update (30Hz fire-and-forget), and drag end. Cross-VS mid-drag flips are emitted by the daemon viadragPolicyChangedand applied locally by the plugin, replacing the effect-side flip loop that walkedKWin::effects->screens()against a local autotile-screen cache. Pinned against drift by a new 8-state truth table test. - Meta-F float toggle now runs daemon-local (#310): the keyboard shortcut previously made 4 D-Bus hops across 3 processes (KWin → daemon → effect → daemon → engine → effect), stalling under any D-Bus backpressure and producing the "pressed Meta-F, nothing happened, seconds later it toggled" symptom. It now reads the active window from
WindowTrackingAdaptor::m_lastActiveWindowId, fresh frame geometry from a 50ms-debounced shadow (setFrameGeometry), and dispatches to the engine in-process. One D-Bus hop remains for the daemon → effectapplyGeometryRequestedpaint, targeting sub-50ms latency from keypress to visible toggle. The 100ms debounce onhandleFloathas been dropped since the in-process path has no D-Bus latency to coalesce. - Settings nesting made compile-time:
ISettingsgainsisZoneSelectorActive()andisSnapAssistActive()composite accessors that returnsnappingEnabled() && <child>Enabled(). Consumers can no longer forget the parent-gate check when reading a nestedSnapping.*flag. Raw child accessors remain for KCM settings UI code that genuinely needs the unaffected value.
Fixed
- No default layout assignment on brand-new virtual desktops (#368): a fresh virtual desktop had no stored entry in the per-context assignment table, so the cascade fell through to a snap-only
defaultLayout()that had no concept of mode. Users with autotile configured globally saw new desktops behave as if no mode were set at all: autotile never activated, snapping was disabled, drag overlays did not appear, and windows just floated. The cascade now consults a settings-derivedAssignmentEntryprovider as the final step, applying the user's intended mode and default to fresh desktops. - Autotile shortcut-adjusted ratio and master count did not persist (#271): shortcut adjustments to the autotile master ratio and master count updated runtime state but not the config, the per-algorithm saved settings, or Settings, so the change reverted on the next reload. Shortcut-driven adjustments now propagate through all three with signal-blocking so the values survive every propagation path.
- Snap-assist showed occupied windows from other virtual desktops (#323): the drag-path occupancy filter walked the live window list without scoping to the current virtual desktop, so a zone that was empty on the user's desktop showed as occupied because a window from another desktop matched it. Now filtered to the current desktop before the occupancy check.
- Per-activity layout assignments could be overridden by per-monitor defaults (#413): in the layout registry, the fallback chain resolved monitor defaults before per-activity overrides, so a user-set activity-scoped layout could lose to a monitor default that predated it. Activity assignments now win in the precedence order, matching what the assignments UI implies.
- Layouts context menu eventually stopped opening (#406): in the Layouts page, the right-click context menu would silently fail to open after enough show and hide cycles because separator visibility was imperatively flipped on each show, eventually leaving a dead
null-context binding. Separator visibility is now declarative and the dead null-context guard was removed. - Cycle-triggered resnap affected windows on other virtual desktops: the daemon's resnap pass after a cycle shortcut walked every tracked window instead of scoping to the active virtual desktop, so cycling on one VD could nudge windows on another VD that happened to share a layout. Now scoped to the active VD.
Installation
Arch Linux (AUR):
yay -S plasmazones # or plasmazones-binArch Linux (manual):
sudo pacman -U plasmazones-3.0.0-*-x86_64.pkg.tar.zstKDE Neon / Debian-based:
sudo dpkg -i plasmazones_3.0.0-*_amd64.deb
sudo apt-get install -f # Install dependencies if neededFedora (COPR):
sudo dnf copr enable fuddlesworth/PlasmaZones
sudo dnf install plasmazonesFedora (manual RPM):
# Fedora 43
sudo dnf install plasmazones-3.0.0-*.fc43.x86_64.rpm
# Fedora 44
sudo dnf install plasmazones-3.0.0-*.fc44.x86_64.rpmopenSUSE Tumbleweed (manual RPM):
sudo zypper install plasmazones-3.0.0-*.x86_64.rpmopenSUSE Tumbleweed (OBS):
sudo zypper addrepo https://download.opensuse.org/repositories/home:ilFrance/openSUSE_Tumbleweed/home:ilFrance.repo
sudo zypper refresh
sudo zypper install plasmazonesCommunity-maintained package by ilFrance
Universal Linux (AppDir):
For Fedora Atomic, Steam Deck, or non-root user installation:
tar xzf plasmazones-3.0.0-linux-x86_64.tar.gz
cd plasmazones-linux-x86_64
./install.shNixOS (flake):
# flake.nix inputs
plasmazones.url = "github:fuddlesworth/PlasmaZones";
# configuration.nix
programs.plasmazones.enable = true;NixOS (standalone):
Download plasmazones.nix from the release assets, then:
# configuration.nix
environment.systemPackages = [
(pkgs.callPackage ./plasmazones.nix {})
];Post-Installation
systemctl --user enable --now plasmazones.service
systemsettings kcm_plasmazones