General
The sweets.general block — modifier key, background, and workspace behavior.
sweets.general{ ... } sets the global behavior of the compositor: the modifier
key bindings expand to, the empty-desktop background, and how workspaces and
directional actions behave across monitors.
sweets.general {
mod_key = "SUPER",
background = "#12121c",
workspace_mode = "shared",
workspace_count = 10,
workspace_move_follow = false,
focus_cross_monitor = true,
move_cross_monitor = true,
drag_center_cursor = true,
allow_tearing = false,
explicit_sync = true,
}Options
| Key | Type | Default | Description |
|---|---|---|---|
mod_key | string | SUPER | Modifier the MOD token expands to in binds |
background | string | #12121c | Empty-desktop fill color, #RRGGBB[AA] |
workspace_mode | string | shared | How workspaces relate to monitors: shared or per_monitor |
workspace_count | int | 10 | Number of usable workspaces, 1–10. Switching to or moving a window past this is ignored |
workspace_move_follow | bool | false | Follow a window to its new workspace after workspace_move |
focus_cross_monitor | bool | true | Directional focus crosses into the next monitor when there is no window that way on the current one |
move_cross_monitor | bool | true | Directional window movement crosses into the next monitor when the window is at the edge |
drag_center_cursor | bool | true | A started MOD + drag recenters the window under the cursor |
allow_tearing | bool | false | Permit tearing page-flips for a fullscreen window that requests async presentation or tags itself a game (lower latency for games) |
explicit_sync | bool | true | Advertise linux-drm-syncobj explicit GPU sync when supported; set false to work around flaky driver page-flip timing |
mod_key
Accepts SUPER (a.k.a. LOGO / MOD4), ALT (MOD1), CTRL, or SHIFT.
This is the modifier the MOD token expands to in your key bindings.
background
The solid color drawn behind everything where no window or wallpaper client covers the screen. It spans the whole output layout and updates on reload.
workspace_mode
Chooses the multi-monitor workspace model:
shared(default): one global set of workspaces, each shown on at most one monitor at a time. Switching to a workspace that is already visible on another monitor just moves focus to that monitor. Switching to a hidden workspace that still has windows returns it — and focus — to its home monitor (the one its windows live on); a hidden workspace with no windows appears on the current monitor instead. On startup each monitor opens on a distinct workspace (monitor 1 → 1, monitor 2 → 2, …).per_monitor(dwm-style): every monitor owns an independent set of workspaces, andMOD+Nswitches the current monitor to its own workspaceN.
A monitor pin (see sweets.workspace) acts as a fixed home in either mode.
Changing workspace_mode takes effect cleanly on a fresh start; switching it
on a running compositor via reload keeps existing windows but only guarantees
that each monitor lands on a distinct workspace.
workspace_count
Limits how many of the ten workspaces are usable, from 1 to 10 (default
10). Switching to — or moving a window to — a workspace above the limit is
ignored, whether the request comes from a key binding, the IPC workspace
command, or a panel. Workspaces above the limit are also marked hidden to
ext-workspace clients, so status bars stop showing them.
The count and your key bindings are independent: dropping the count to 5 does
not delete the MOD+6…MOD+0 binds — they simply become no-ops. For a clean
setup, set workspace_count and shorten the bind loop to match:
sweets.general { workspace_count = 5 }
for i = 1, 5 do
sweets.bind("MOD+" .. i, "workspace", i)
sweets.bind("MOD+Shift+" .. i, "workspace_move", i)
endLowering the count on a running compositor via reload is safe: any windows left on a now-disabled workspace are moved onto the last enabled one, so nothing is stranded out of reach.
workspace_move_follow
Controls what happens after the workspace_move action. By default (false)
the focused window moves to the target workspace and you stay where you are.
With true, focus follows the window to its new workspace (and, in shared
mode, to that workspace's monitor), so the moved window stays focused — like
Hyprland's movetoworkspace versus movetoworkspacesilent.
focus_cross_monitor
Controls the directional focus actions (focus_left, focus_right, focus_up,
focus_down). With it on (default), pressing a direction when there is no window
that way on the current monitor moves focus to the adjacent monitor in that
direction and activates it. With it off, directional focus stays within the
current monitor.
When focus crosses to another monitor it restores the last-focused window on that monitor's active workspace, unless that window is not a sensible landing for the travel direction — for example, entering a monitor whose master column is on the far side lands on the nearest stacked window (topmost) rather than jumping past it to the master. If the last-focused window was already the nearest one for that direction, it is restored exactly.
move_cross_monitor
Controls the directional move actions (move_left, move_right, move_up,
move_down). Moving a tiled window swaps it with its neighbor in that direction.
When there is no neighbor that way (the window is at the edge of the layout) and
this is on (default), the window crosses to the adjacent monitor in that
direction and lands on the edge it entered from — moving right makes it the
master/front of the next monitor, moving left appends it to the far end. With it
off, a window at the edge stays put. The window keeps focus and the destination
monitor becomes active. Floating windows are not moved by these actions.
Focus follows the mouse: the window under the pointer always gains keyboard focus as you move it, including across monitors and workspaces. Hovering empty space or a panel keeps the last window focused, and it never steals the keyboard from a launcher like rofi.
allow_tearing
Master switch for screen tearing, off by default. Tearing lets a frame reach the screen the instant it is ready instead of waiting for the next refresh, which trims input latency for games that run with vsync off — at the cost of a visible horizontal seam when frames change mid-scan.
With it on, Sweets tears for a fullscreen window when either it asks through the
tearing-control-v1 protocol (most games expose this as a "tearing" or "immediate
/ uncapped" option) or it tags itself as a game through content-type-v1 — and only
when the driver accepts a tearing page-flip for that frame. Anything else falls back
to a normal vsynced flip. It pairs naturally with
adaptive_sync: VRR removes
tearing inside the refresh window, and tearing covers frames that miss it.
Tearing page-flips only happen on the DRM/KMS backend, so there is nothing to see when running Sweets nested inside another compositor.
explicit_sync
On by default. When the GPU and backend support DRM synchronization timelines,
Sweets advertises linux-drm-syncobj-v1 so clients can hand it explicit
buffer-ready and buffer-release fences instead of relying on implicit sync. This
improves correctness and latency and is strongly recommended on NVIDIA, where
implicit sync is prone to flicker.
Set it to false as a workaround on GPU/driver combinations where explicit sync
misbehaves. Turning it off makes Sweets fall back to implicit sync, which is solid
on Mesa (Intel/AMD). When disabled, the log shows explicit sync disabled by config at startup.
Intel Arc (DG2) on the i915 driver: explicit sync currently triggers a
visible glitch — windows flash and stretch while being resized, and the log
fills with connector …: … cannot be scanned out. It comes from the
direct-scanout path rejecting the client buffer format every frame. If you see
this on an Arc GPU, set explicit_sync = false. AMD and NVIDIA are unaffected;
this is specific to Arc + i915 + Mesa.
This is decided once at startup, so changing it takes effect on the next session (a hot reload will not create or remove the global).