Styles
The plugin only hands picom numbers. The animation itself is a picom animation script, so it can look however you like. Each style is one file, and one line in picom.conf picks it. Change the name and save; picom reloads by itself.
A picom plugin that tells your animation scripts which way a workspace switch went, which monitor the workspace is on, and where each workspace lies. Windows slide the right way, stay on their own monitor, and can show the workspaces a switch passes.
Workspace transitions are the smaller part of this project, and the part I'd ask picom about first. The plugin reads only the standard window manager properties (EWMH), so it isn't tied to i3. Every switch style needs five changes to picom: plugin variables (proposed as #1550), a small xrender fix (#1551), three fixes to script expressions, functions such as min, max, sin and cos, and the state an interrupted animation left. The last three are written and tested, not proposed yet. The 3D styles also need windows in perspective, and the overview and the switches that pass workspaces a few more general hooks. See the backlog.
For now it needs the picom fork; see Install. The source is on GitHub. The code was written with AI; see a note before you read on.
The plugin only hands picom numbers. The animation itself is a picom animation script, so it can look however you like. Each style is one file, and one line in picom.conf picks it. Change the name and save; picom reloads by itself.
The new workspace pushes the old one out.
@include "ws-direction/slide.conf"
The new workspace slides in over the old one, which drifts back, like a card put on a stack.
@include "ws-direction/push.conf"
The old workspace folds into one edge while the new one unfolds from the other, like a flat cube turning.
@include "ws-direction/fold.conf"
The workspaces are the sides of a box that turns, seen in perspective. A switch that passes workspaces turns past them.
@include "ws-direction/cube.conf"
The workspace turns over like a card, with the new one on its back.
@include "ws-direction/flip.conf"
The old workspace slides out in one piece; the new windows follow one after another and land together.
@include "ws-direction/cascade.conf"
The old workspace sinks into a point on one side of the middle of the monitor; then the new one bursts out of a point on the other side.
@include "ws-direction/warp.conf"
The view zooms out, pans to the new workspace and zooms back in, as if the workspaces were tiles side by side.
@include "ws-direction/zoom-pan.conf"
The old windows drain into blocks of their own colour, which fade; the new ones come as blocks, and their content comes out of the middle. New, not in a release yet.
@include "ws-direction/ink.conf"
The workspace slides away like a sheet of paper on a desk, leaning into the way it goes, and the new one slides in behind it. New, not in a release yet.
@include "ws-direction/paper.conf"
The old windows shrink into their middles and fade; the new ones pop out of theirs. New, not in a release yet.
@include "ws-direction/pop.conf"
The old windows spin out with a quarter turn as they shrink and fade; the new ones spin in, the same way round. New, not in a release yet.
@include "ws-direction/twirl.conf"
Nothing moves: an edge sweeps across the monitor and uncovers the new workspace.
@include "ws-direction/wipe.conf"
Recorded at 60 fps on my real screen, on a 16:9 monitor beside a vertical one, each window in a colour of its own: the vertical monitor switches to another workspace and back, then the landscape one. Pauses between switches are trimmed to the same length; the animations themselves are unedited.
Each style sets var-length, in seconds; make it larger for a slower switch. By default the workspaces lie along the short side of each monitor: up and down on a landscape monitor, sideways on a portrait one.
Not recorded yet. Each is picked the same way, by its name in the @include line. In every switch style, a switch that passes workspaces shows them on the way: going from 1 to 4, the windows of 2 and 3 come by.
pass-slide, pass-zoom-panvar-length, so a long switch doesn't become a blur.pass-zoom-cascadeCube, flip, paper and twirl are best with picom's glx or egl backend. xrender draws them too, but slower, and squeezed text can shimmer.
A key unfolds the monitor's workspaces into a strip of tiles that fits on the monitor. The arrow keys move through them, and a click on a window picks it. There are two overview styles: wall, which zooms out along the strip and dims the workspaces you aren't on, and unfold, which opens cube's box up into a flat strip. An overview style goes in a second rule, next to the switch style:
rules = ({
match = "!override_redirect && window_type = 'normal'";
@include "ws-direction/pass-zoom-pan.conf"
}, {
match = "!override_redirect && window_type = 'normal'";
@include "ws-direction/wall.conf"
});
The ws-direction command opens and closes it, from a key in i3. The lines are on the Install page.
The plugin adds variables that scripts read like window-width. picom asks the plugin for their values when an animation starts, and only for scripts that use them.
plugin-ws-direction-directionplugin-ws-direction-distanceplugin-ws-direction-monitor-x, -y, -width, -height-faces, -face, -index, -shown-selected, -placed, -unfolded, -backdrop-monitor-width-mm, -monitor-height-mmThe plugin also starts three animation triggers of its own: ws-pass on every window of a monitor at a switch, so the workspaces in between can move too, and ws-unfold and ws-fold when the overview opens and closes.
A simplified part of the slide style, for a window on a landscape monitor:
# Start one monitor height away, on the side the switch
# came from, and move back to 0 in a quarter second.
var-pos = {
duration = 0.25;
start = "plugin-ws-direction-direction";
end = 0;
};
offset-y = "var-pos * plugin-ws-direction-monitor-height";
# Cut the window off at the edges of its own monitor,
# so it never slides onto the other one.
crop-x = "plugin-ws-direction-monitor-x";
crop-y = "plugin-ws-direction-monitor-y";
crop-width = "plugin-ws-direction-monitor-width";
crop-height = "plugin-ws-direction-monitor-height";
The full list, and how to write a style, are in the README. Every style file explains how it works.
picom knows when a window shows or hides, but not why. The plugin fills that gap from outside picom. It reads the window manager's EWMH properties (_NET_CURRENT_DESKTOP, _NET_DESKTOP_NAMES and _NET_DESKTOP_VIEWPORT on the root window, _NET_WM_DESKTOP on each window) and the monitors from RandR, and it remembers the recent switches of every monitor.
Window managers don't follow a fixed order when they change these properties and show or hide windows. So the plugin doesn't guess from single events: when a window shows or hides, it matches that to a recent switch on the window's monitor. It reads the root window at most once per picom update, however many windows start an animation in it.
To draw workspaces that aren't shown, as cube and the overview do, picom keeps the last picture of each hidden window. After picom starts, it has none until a workspace has been shown once; ws-direction warm shows each one briefly to fill them in.
unredir-if-possible), it drops the kept pictures, and a switch made then has no animation. Set unredir-if-possible = false for the styles that draw hidden workspaces.use-damage = false.