Sweets
Configuration

General

The sweets.general block — modifier key, background, and workspace behavior.

sweets.general{ ... } sets global compositor behavior: the modifier key, the desktop background, and how workspaces 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

KeyTypeDefaultDescription
mod_keystringSUPERModifier the MOD token expands to in binds
backgroundstring#12121cEmpty-desktop fill color, #RRGGBB[AA]
workspace_modestringsharedHow workspaces relate to monitors: shared or per_monitor
workspace_countint10Number of usable workspaces, 110
workspace_move_followboolfalseFollow a window to its new workspace after workspace_move
focus_cross_monitorbooltrueDirectional focus can cross to the next monitor
move_cross_monitorbooltrueDirectional movement can cross to the next monitor
drag_center_cursorbooltrueA MOD + drag recenters the window under the cursor
allow_tearingboolfalsePermit tearing page-flips for fullscreen games
explicit_syncbooltrueAdvertise linux-drm-syncobj explicit GPU sync

mod_key

Accepts SUPER (a.k.a. LOGO / MOD4), ALT (MOD1), CTRL, or SHIFT. The MOD token in your bindings expands to this.

background

The solid color drawn where no window or wallpaper covers the screen. It spans the whole output layout and updates on reload.

workspace_mode

Picks the multi-monitor workspace model.

shared (default) — one global set of workspaces. Each appears on at most one monitor at a time.

  • Switching to a visible workspace moves focus to its monitor.
  • Switching to a hidden workspace that has windows returns it to its home monitor.
  • A hidden, empty workspace appears on the current monitor.
  • On startup each monitor opens on a distinct workspace.

per_monitor (dwm-style) — every monitor owns an independent set of workspaces. MOD + N switches the current monitor to its own workspace N.

A monitor pin (see sweets.workspace) sets a fixed home in either mode. Change workspace_mode on a fresh start. Switching it via reload keeps windows but only guarantees each monitor lands on a distinct workspace.

workspace_count

Limits how many workspaces are usable, 1 to 10. Requests above the limit are ignored, whether they come from a binding, IPC, or a panel. Workspaces above the limit are hidden from ext-workspace clients, so status bars stop showing them.

The count and your bindings are independent. Dropping the count to 5 does not delete the MOD+6MOD+0 binds — they become no-ops. 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)
end

Lowering the count on a reload is safe. Windows on a disabled workspace move to the last enabled one, so nothing is stranded.

workspace_move_follow

Controls what happens after workspace_move. With false (default) the window moves and you stay put. With true focus follows the window — and in shared mode, to that workspace's monitor.

focus_cross_monitor

Controls focus_left, focus_right, focus_up, and focus_down. On by default. When the current monitor has no window aligned in that direction, focus moves to the adjacent monitor. Turn it off to keep focus on one monitor.

"Aligned" means the candidate window overlaps the travel axis. With a side-by-side master and stack, focus_right from the master lands on the stack. When the master spans the full width, the stack sits above or below it, so focus_right/focus_left prefer the neighbouring monitor first.

Crossing to another monitor restores its last-focused window, unless that window is a poor landing for the direction. Entering a monitor whose master column is on the far side lands on the nearest stacked window instead.

move_cross_monitor

Controls move_left, move_right, move_up, and move_down. Moving a tiled window swaps it with its neighbor. With no neighbor that way and this on (default), the window crosses to the adjacent monitor and lands on the edge it entered from. Moving right makes it the master 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 unaffected.

Focus follows the mouse. The window under the pointer gains keyboard focus, including across monitors and workspaces. Hovering empty space or a panel keeps the last window focused, and it never steals focus from a launcher.

allow_tearing

Master switch for screen tearing, off by default. Tearing sends a frame to the screen the instant it is ready instead of waiting for the next refresh. This trims input latency for games running without vsync, at the cost of a visible horizontal seam.

With it on, Sweets tears for a fullscreen window when either:

  • it asks through tearing-control-v1 (games expose this as "tearing" or "immediate / uncapped"), or
  • it tags itself a game through content-type-v1.

The driver must also accept a tearing page-flip for that frame. Anything else uses a normal vsynced flip.

It pairs well with adaptive_sync. VRR removes tearing inside the refresh window; tearing covers frames that miss it.

Tearing only happens on the DRM/KMS backend, so there is nothing to see when running Sweets nested.

explicit_sync

On by default. When the GPU and backend support DRM synchronization timelines, Sweets advertises linux-drm-syncobj-v1. Clients then hand it explicit buffer-ready and buffer-release fences instead of relying on implicit sync.

This improves correctness and latency. It is strongly recommended on NVIDIA, where implicit sync is prone to flicker.

Set it to false where explicit sync misbehaves. Sweets falls back to implicit sync, which is solid on Mesa (Intel/AMD). The log then shows explicit sync disabled by config at startup.

Intel Arc (DG2) on i915: explicit sync triggers a visible glitch. Windows flash and stretch while resizing, and the log fills with connector …: … cannot be scanned out. Set explicit_sync = false on an Arc GPU. AMD and NVIDIA are unaffected.

This is decided once at startup, so changes take effect next session. A hot reload will not create or remove the global.

On this page