1
0
Fork 0
forked from wry/wry

docs: add book

This commit is contained in:
Claude 2026-03-20 19:14:07 +01:00 committed by Julian Orth
parent c9d6fb9e40
commit d14105eb1a
43 changed files with 7254 additions and 1204 deletions

View file

@ -0,0 +1,76 @@
# Environment Variables
Jay can set environment variables that are inherited by all programs it spawns.
## Setting environment variables at startup
Use the `[env]` table in your config to define variables that apply to every
application launched by the compositor:
```toml
[env]
GTK_THEME = "Adwaita:dark"
QT_QPA_PLATFORM = "wayland"
MOZ_ENABLE_WAYLAND = "1"
```
These variables are set when the config is loaded. Programs started after that
point will inherit them.
## Changing variables at runtime
### set-env
Use the `set-env` action to add or update environment variables while the
compositor is running. This affects all programs started **after** the action
runs:
```toml
[shortcuts]
alt-F11 = {
type = "set-env",
env = { GTK_THEME = "Adwaita:dark" },
}
alt-F12 = {
type = "set-env",
env = { GTK_THEME = "Adwaita" },
}
```
### unset-env
Use the `unset-env` action to remove environment variables:
```toml
[shortcuts]
alt-F10 = { type = "unset-env", env = ["GTK_THEME"] }
```
You can unset multiple variables at once with an array:
```toml
[shortcuts]
alt-F10 = {
type = "unset-env",
env = ["GTK_THEME", "QT_QPA_PLATFORM"],
}
```
## Per-process environment variables
When using the table form of the `exec` action, you can set environment
variables that apply only to that specific process:
```toml
[shortcuts]
alt-Return = {
type = "exec",
exec = {
prog = "alacritty",
env = { TERM = "xterm-256color" },
},
}
```
These per-process variables are merged with (and override) the global
environment for that single execution.

View file

@ -0,0 +1,293 @@
# GPUs
Jay configures graphics cards (DRM devices) through the `[[drm-devices]]`
array. This is primarily useful on multi-GPU systems for selecting the render
device, choosing a graphics API, and tuning per-device settings.
> [!NOTE]
> DRM device configuration in `config.toml` is only applied when a device is
> first discovered after the configuration is loaded. To change settings at
> runtime, use `jay randr` or the `configure-drm-device` action.
## Matching GPUs
Every `[[drm-devices]]` entry requires a `match` field. When `match` is a
**table**, all specified fields must match (AND). When `match` is an **array**,
any entry matching is sufficient (OR).
### By PCI vendor and model (recommended)
PCI IDs are stable, unique identifiers. Use `jay randr` to find them:
```shell
~$ jay randr
```
```toml
[[drm-devices]]
match = {
pci-vendor = 0x1002,
pci-model = 0x73ff,
}
gfx-api = "Vulkan"
```
### By vendor or model name
```toml
[[drm-devices]]
match.vendor = "Advanced Micro Devices, Inc. [AMD/ATI]"
```
```toml
[[drm-devices]]
match.model = "Raphael"
```
### By syspath or devnode
The `syspath` is usually stable across reboots:
```toml
[[drm-devices]]
match.syspath = "/sys/devices/pci0000:00/0000:00:08.1/0000:14:00.0"
```
The `devnode` (e.g. `/dev/dri/card0`) is typically not stable.
## Naming GPUs
Assign a `name` to reference a device from other parts of the config:
```toml
[[drm-devices]]
name = "dedicated"
match = {
pci-vendor = 0x1002,
pci-model = 0x73ff,
}
[[drm-devices]]
name = "integrated"
match = {
pci-vendor = 0x1002,
pci-model = 0x164e,
}
```
Names can then be used in `render-device`, shortcuts, and actions:
```toml
render-device.name = "dedicated"
```
```toml
[shortcuts]
alt-v = {
type = "configure-drm-device",
dev = {
match.name = "dedicated",
gfx-api = "Vulkan",
},
}
alt-o = {
type = "configure-drm-device",
dev = {
match.name = "dedicated",
gfx-api = "OpenGl",
},
}
```
## Graphics API
Jay supports two rendering backends per device:
`Vulkan`
: Uses libvulkan. The primary renderer -- use this unless you have a specific
reason not to. Required for HDR. All devices in the system must support DRM
format modifiers (most do, except AMD GPUs older than RX 5000).
`OpenGl`
: Uses libEGL + libGLESv2. Maintained for backwards compatibility only. No new
features will be added to this renderer.
### Per-device API
```toml
[[drm-devices]]
match = {
pci-vendor = 0x1002,
pci-model = 0x73ff,
}
gfx-api = "Vulkan"
```
### Default API for all devices
Set the top-level `gfx-api` to apply to any device without a per-device
override:
```toml
gfx-api = "Vulkan"
```
This only takes effect for devices discovered after the config is loaded.
## Direct scanout
Direct scanout lets the compositor hand a client's buffer directly to the
display hardware, bypassing composition. This can reduce latency and power
usage, but may cause visual glitches with some hardware or applications.
### Per-device
```toml
[[drm-devices]]
match = {
pci-vendor = 0x1002,
pci-model = 0x73ff,
}
direct-scanout = false
```
### Global toggle
```toml
direct-scanout = false
```
## Flip margin
The flip margin is the time (in milliseconds) between the compositor
initiating a page flip and the output's vertical blank event. It determines
the minimum achievable input latency. The default is 1.5 ms.
```toml
[[drm-devices]]
match = {
pci-vendor = 0x1002,
pci-model = 0x73ff,
}
flip-margin-ms = 2.0
```
If the margin is set too small, the compositor will dynamically increase it to
avoid missed frames.
## Explicit sync
Explicit sync coordinates buffer access between the compositor and GPU drivers.
It is enabled by default and generally should not be disabled:
```toml
explicit-sync = true
```
> [!WARNING]
> This setting cannot be changed after the compositor has started. It can only
> be set in `config.toml` before launching Jay.
## Render device
On multi-GPU systems, select which GPU performs compositing with the
`render-device` field. The first matching device is used:
```toml
render-device.name = "dedicated"
[[drm-devices]]
name = "dedicated"
match = {
pci-vendor = 0x1002,
pci-model = 0x73ff,
}
[[drm-devices]]
name = "integrated"
match = {
pci-vendor = 0x1002,
pci-model = 0x164e,
}
gfx-api = "OpenGl"
```
You can also match directly without naming:
```toml
render-device = {
pci-vendor = 0x1002,
pci-model = 0x73ff,
}
```
> [!NOTE]
> Changing the render device at runtime (via the `set-render-device` action)
> may cause windows to become invisible until they are resized or otherwise
> redrawn.
## Runtime changes
### Listing GPUs
```shell
~$ jay randr
```
This shows all DRM devices with their PCI IDs, vendor/model names, current
API, and other settings.
### Changing settings at runtime
Use `jay randr` subcommands:
```shell
~$ jay randr card <card> api vulkan
~$ jay randr card <card> direct-scanout enable
~$ jay randr card <card> primary
```
### Using shortcuts
The `configure-drm-device` action applies settings from a keybinding:
```toml
[shortcuts]
alt-F5 = {
type = "configure-drm-device",
dev = {
match.name = "dedicated",
gfx-api = "Vulkan",
},
}
alt-F6 = {
type = "configure-drm-device",
dev = {
match.name = "dedicated",
gfx-api = "OpenGl",
},
}
```
The `set-render-device` action switches the compositing GPU:
```toml
[shortcuts]
alt-F7 = { type = "set-render-device", dev.name = "dedicated" }
alt-F8 = { type = "set-render-device", dev.name = "integrated" }
```
## Hardware cursor
The `use-hardware-cursor` top-level setting controls whether the hardware cursor
plane is used. Disabling this forces software cursor rendering, which can be
useful for debugging.
```toml
use-hardware-cursor = true # default
```
## Full reference
For the exhaustive list of all DRM device fields, match criteria, and related
types, see the [auto-generated specification](https://github.com/mahkoh/jay/blob/master/toml-spec/spec/spec.generated.md).

View file

@ -0,0 +1,186 @@
# Idle & Screen Locking
Jay can detect when the system is idle and automatically run an action -- most
commonly launching a screen locker. The idle timeout, grace period, and
on-idle action are all configurable.
## Idle timeout
Set how long the system must be idle before the on-idle action fires. Specify
`minutes` and/or `seconds`:
```toml
idle.minutes = 10
```
```toml
idle = { minutes = 5, seconds = 30 }
```
If all values are explicitly set to 0, the idle timeout is disabled entirely:
```toml
idle = { minutes = 0 }
```
> [!NOTE]
> The idle timeout defined in `config.toml` cannot be changed by reloading the
> configuration. Use `jay idle` or the `configure-idle` action to change it at
> runtime.
## Grace period
The grace period is a warning phase between the timeout expiring and the actual
idle event. During the grace period, the screen goes black but outputs are not
yet disabled and the `on-idle` action has not yet fired. Any input during this
period cancels the idle transition.
The default grace period is 5 seconds. Configure it with:
```toml
idle.grace-period.seconds = 3
```
```toml
idle.grace-period = { minutes = 0, seconds = 10 }
```
Set both values to 0 to disable the grace period (immediately fire the on-idle
action when the timeout expires):
```toml
idle.grace-period = { seconds = 0 }
```
## On-idle action
The `on-idle` field defines what happens when the idle timeout (plus grace
period) elapses. The most common use is launching a screen locker:
```toml
on-idle = {
type = "exec",
exec = {
prog = "swaylock",
privileged = true,
},
}
```
> [!IMPORTANT]
> Screen lockers that use the Wayland session lock protocol (like swaylock)
> need `privileged = true` in the exec configuration. This grants the process
> the necessary permissions to lock the session.
You can also combine multiple actions:
```toml
on-idle = [
{
type = "exec",
exec = {
prog = "swaylock",
privileged = true,
},
},
{ type = "exec", exec = ["notify-send", "System locked"] },
]
```
## Complete example
A typical idle and screen-locking setup:
```toml
idle = {
minutes = 10,
grace-period = { seconds = 5 },
}
on-idle = {
type = "exec",
exec = {
prog = "swaylock",
privileged = true,
},
}
```
This means:
1. After 10 minutes of inactivity, the screen goes black (grace period begins).
2. If no input occurs within 5 seconds, swaylock is launched and outputs are
disabled.
3. Any input during the grace period cancels the transition and restores the
display.
## Runtime changes
### Checking idle status
```shell
~$ jay idle status
```
### Changing the idle timeout
```shell
~$ jay idle set 5m
~$ jay idle set 1m30s
~$ jay idle set disabled
```
### Changing the grace period
```shell
~$ jay idle set-grace-period 10s
~$ jay idle set-grace-period 0s
```
### Duration format
The CLI accepts durations in a flexible format:
| Example | Meaning |
|----------------------|------------------------|
| `1m` | 1 minute |
| `1m5s` | 1 minute 5 seconds |
| `1min 5sec` | 1 minute 5 seconds |
| `90s` | 90 seconds |
| `disabled` | Disable the timeout |
### Unlocking
If the compositor is locked (e.g. the screen locker crashed), you can unlock
it from another TTY or by SSH-ing into the machine. You must set
`WAYLAND_DISPLAY` to the socket of the Jay compositor, since you are running
the command outside the compositor session:
```shell
~$ WAYLAND_DISPLAY=wayland-1 jay unlock
```
Use `jay pid` with the same `WAYLAND_DISPLAY` value to verify you are
targeting the correct compositor instance.
### Using shortcuts
The `configure-idle` action lets you change idle settings from a keybinding:
```toml
[shortcuts]
alt-F9 = {
type = "configure-idle",
idle = {
minutes = 5,
grace-period = { seconds = 3 },
},
}
alt-F10 = {
type = "configure-idle",
idle = { minutes = 0 },
}
```
## Full reference
For the exhaustive list of all idle-related fields and types, see the
[auto-generated specification](https://github.com/mahkoh/jay/blob/master/toml-spec/spec/spec.generated.md).

View file

@ -0,0 +1,130 @@
# Configuration Overview
Jay is configured through a single TOML file located at:
```
~/.config/jay/config.toml
```
If this file does not exist, Jay uses built-in defaults that provide a
reasonable starting configuration with common shortcuts, a US QWERTY keymap,
and other sensible settings.
> [!WARNING]
> Once `config.toml` exists, the **entire** built-in default configuration is
> replaced -- not merged. Even a completely empty file means no shortcuts, no
> startup actions, nothing. Always start from a full config rather than writing
> one from scratch.
## Initializing the config
The easiest way to get started is to let Jay write the defaults for you:
```shell
~$ jay config init
```
This creates `~/.config/jay/config.toml` pre-populated with the full default
configuration. You can then edit it to suit your needs.
If you already have a config file and want to reset it:
```shell
~$ jay config init --overwrite
```
The old file will be backed up to `config.toml.1` (or `.2`, `.3`, etc.) before
being replaced.
## Other config subcommands
Print the path to the config file:
```shell
~$ jay config path
```
Open the config directory in your file manager:
```shell
~$ jay config open-dir
```
## Reloading the configuration
By default, Jay does not automatically reload `config.toml` when it changes on
disk. To apply changes, trigger a reload manually:
- Press `alt-shift-r` (the default shortcut), or
- Use the `reload-config-toml` action in any other action context (e.g. a named
action or a window rule).
Most settings take effect immediately on reload. A few exceptions (like
`log-level`, `explicit-sync`, and initial `drm-devices` settings) only apply
at compositor startup.
### Automatic reloading
To have Jay watch `config.toml` for changes and reload automatically, add:
```toml
auto-reload = true
```
When enabled, Jay uses inotify to monitor the config file and its parent
directories. Changes are debounced — the config is reloaded 400 ms after the
last write, so rapid successive saves don't cause multiple reloads. If the file
contents haven't actually changed, the reload is skipped.
Setting `auto-reload = false` will stop the watcher. Removing the key entirely
leaves the watcher state unchanged (if it was running, it keeps running until
the compositor restarts).
## Named actions
You can define reusable actions in the `[actions]` table and reference them
anywhere an action is accepted by prefixing the name with `$`:
```toml
[actions]
launch-terminal = { type = "exec", exec = "alacritty" }
launch-browser = { type = "exec", exec = "firefox" }
[shortcuts]
alt-Return = "$launch-terminal"
alt-b = "$launch-browser"
```
Named actions can reference other named actions. The `max-action-depth` setting
controls the maximum recursion depth to prevent infinite loops (default: 16):
```toml
max-action-depth = 32
```
## Composable actions
Anywhere an action is accepted, you can use an **array of actions** instead.
This applies to shortcuts, startup hooks, named actions, and any other action
field:
```toml
[shortcuts]
alt-q = [
{ type = "exec", exec = ["notify-send", "Goodbye!"] },
"quit",
]
```
## Advanced: shared library configuration
For users who need programmatic configuration beyond what TOML offers, Jay also
supports configuration via a compiled Rust shared library using the
[jay-config](https://docs.rs/jay-config) crate. This is an advanced option --
the TOML config is sufficient for the vast majority of use cases.
## Full specification
This book covers the most common configuration options with explanations and
examples. For an exhaustive listing of every field, type, and action, see the
[auto-generated specification](https://github.com/mahkoh/jay/blob/master/toml-spec/spec/spec.generated.md).

View file

@ -0,0 +1,336 @@
# Input Devices
Jay configures input devices through the `[[inputs]]` array. Each entry matches
one or more devices and applies settings such as acceleration, tap behavior,
and device-to-output mapping.
> [!NOTE]
> Input configuration defined in `config.toml` is only applied to devices
> connected after the configuration is loaded. To change settings for
> already-connected devices, use `jay input` or the `configure-input` action.
## Matching input devices
Every `[[inputs]]` entry requires a `match` field. When `match` is a
**table**, all specified fields must match (AND logic). When `match` is an
**array**, any entry matching is sufficient (OR logic).
### By device name
```toml
[[inputs]]
match.name = "Logitech G300s Optical Gaming Mouse"
left-handed = true
```
Run `jay input` to see the names of all connected input devices.
### By device type
Match all devices of a given type using boolean flags:
```toml
[[inputs]]
match.is-pointer = true
natural-scrolling = true
```
Available type flags: `is-keyboard`, `is-pointer`, `is-touch`,
`is-tablet-tool`, `is-tablet-pad`, `is-gesture`, `is-switch`.
### By syspath or devnode
The `syspath` is usually stable across reboots and useful when you have
multiple identical devices:
```toml
[[inputs]]
match.syspath = "/sys/devices/pci0000:00/0000:00:08.1/0000:14:00.4/usb5/5-1/5-1.1/5-1.1.2/5-1.1.2:1.0"
left-handed = true
```
The `devnode` (e.g. `/dev/input/event4`) is typically not stable across
reboots.
### Combining criteria
AND -- all fields in a single table must match:
```toml
[[inputs]]
match = { name = "SynPS/2 Synaptics TouchPad", is-pointer = true }
tap-enabled = true
```
OR -- any entry in an array may match:
```toml
[[inputs]]
match = [
{ name = "Logitech G300s Optical Gaming Mouse" },
{ name = "Razer DeathAdder V2" },
]
left-handed = true
```
## Tagging devices
Assign a `tag` to reference a device from shortcuts or actions:
```toml
[[inputs]]
tag = "mouse"
match.is-pointer = true
[shortcuts]
alt-l = {
type = "configure-input",
input = {
match.tag = "mouse",
left-handed = true,
},
}
alt-r = {
type = "configure-input",
input = {
match.tag = "mouse",
left-handed = false,
},
}
```
Tags work similarly to output names -- they let you refer to matched devices
elsewhere in the configuration.
## Libinput settings
These settings map directly to libinput device options. See the
[libinput documentation](https://wayland.freedesktop.org/libinput/doc/latest/)
for detailed explanations of each.
### Acceleration
```toml
[[inputs]]
match.is-pointer = true
accel-profile = "Flat"
accel-speed = 0.0
```
| Field | Values | Description |
|----------------|----------------------------|----------------------------------------|
| `accel-profile`| `Flat` or `Adaptive` | Pointer acceleration curve |
| `accel-speed` | `-1.0` to `1.0` | Speed within the selected profile |
### Tap and click
```toml
[[inputs]]
match.is-pointer = true
tap-enabled = true
tap-drag-enabled = true
tap-drag-lock-enabled = false
click-method = "clickfinger"
```
| Field | Values | Description |
|-------------------------|--------------------------------------------|-------------------------------------------|
| `tap-enabled` | `true` / `false` | Tap-to-click on touchpads |
| `tap-drag-enabled` | `true` / `false` | Tap-and-drag on touchpads |
| `tap-drag-lock-enabled` | `true` / `false` | Keep drag active after lifting finger |
| `click-method` | `none`, `button-areas`, `clickfinger` | How physical clicks are interpreted |
### Other libinput options
```toml
[[inputs]]
match.is-pointer = true
left-handed = true
natural-scrolling = true
middle-button-emulation = true
```
`left-handed`
: Swap left and right buttons
`natural-scrolling`
: Reverse scroll direction ("macOS-style")
`middle-button-emulation`
: Simultaneous left+right click produces a middle click
## Scroll speed
Control how many pixels each scroll wheel detent produces:
```toml
[[inputs]]
match.is-pointer = true
px-per-wheel-scroll = 30
```
This setting maps to the legacy `wl_pointer.axis` event that is mostly unused
nowadays. It has no effect on applications that don't use this event.
## Transform matrix
Apply a 2x2 matrix to relative motion events. This is useful for adjusting
pointer speed independently of libinput acceleration:
```toml
[[inputs]]
match.is-pointer = true
transform-matrix = [[0.35, 0], [0, 0.35]]
```
The example above reduces pointer speed to 35% of normal. The identity matrix
is `[[1, 0], [0, 1]]`.
## Calibration matrix
A 2x3 matrix for absolute input devices (touchscreens). This is passed
directly to libinput:
```toml
[[inputs]]
match.is-touch = true
calibration-matrix = [[0, 1, 0], [-1, 0, 1]]
```
The example above rotates touch input by 90 degrees.
## Per-device keymap
Override the global keymap for a specific keyboard:
```toml
[[inputs]]
match.name = "ZSA Technology Labs Inc ErgoDox EZ"
keymap.rmlvo = {
layout = "us",
options = "compose:ralt",
}
```
The override becomes active when a key is pressed on that device. See the
[Keymaps & Repeat Rate](keymaps.md) chapter for the full range of keymap
options.
## Mapping to outputs
Map tablets and touchscreens to a specific output so that the input area
corresponds to the correct display:
```toml
[[outputs]]
name = "left"
match.serial-number = "33K03894SL0"
[[inputs]]
match.name = "Wacom Bamboo Comic 2FG Pen"
output.name = "left"
```
You can also map by connector:
```toml
[[inputs]]
match.name = "Wacom Bamboo Comic 2FG Pen"
output.connector = "DP-1"
```
To remove a mapping at runtime, use the `remove-mapping` field in a
`configure-input` action:
```toml
[shortcuts]
alt-x = {
type = "configure-input",
input = {
match.tag = "wacom",
remove-mapping = true,
},
}
```
## Lid switch events
Lid switch devices report when a laptop lid is opened or closed. Use the
`on-lid-closed` and `on-lid-opened` fields to trigger actions. These fields
only work in the top-level `[[inputs]]` array:
```toml
[[inputs]]
match.name = "<lid switch name>"
on-lid-closed = {
type = "configure-connector",
connector = {
match.name = "eDP-1",
enabled = false,
},
}
on-lid-opened = {
type = "configure-connector",
connector = {
match.name = "eDP-1",
enabled = true,
},
}
```
Run `jay input` to find the name of your lid switch device.
## Convertible (2-in-1) events
For convertible laptops that switch between laptop and tablet form factors:
```toml
[[inputs]]
match.name = "<switch name>"
on-converted-to-laptop = "$enable-keyboard"
on-converted-to-tablet = "$disable-keyboard"
```
These fields only work in the top-level `[[inputs]]` array.
## Runtime changes
### Listing devices
```shell
~$ jay input
```
This shows all connected input devices with their names, syspaths, devnodes,
type flags, and current settings.
### Changing settings at runtime
```shell
~$ jay input device <id> set-accel-profile flat
~$ jay input device <id> set-accel-speed 0.5
~$ jay input device <id> set-tap-enabled true
~$ jay input device <id> set-left-handed true
~$ jay input device <id> set-natural-scrolling true
~$ jay input device <id> set-transform-matrix 0.35 0 0 0.35
```
### Using shortcuts
The `configure-input` action applies settings from a keybinding:
```toml
[shortcuts]
alt-n = {
type = "configure-input",
input = {
match.tag = "touchpad",
natural-scrolling = true,
},
}
```
## Full reference
For the exhaustive list of all input fields, match criteria, and related types,
see the [auto-generated specification](https://github.com/mahkoh/jay/blob/master/toml-spec/spec/spec.generated.md).

View file

@ -0,0 +1,144 @@
# Keymaps & Repeat Rate
Jay uses XKB keymaps for keyboard layout configuration. The default keymap is
US QWERTY.
## Setting the keymap
There are several ways to define a keymap.
### Using RMLVO names (recommended)
The simplest approach is to specify the layout using RMLVO (Rules, Model,
Layout, Variants, Options) names:
```toml
keymap.rmlvo = { layout = "de" }
```
You can specify any combination of RMLVO fields:
```toml
keymap.rmlvo = {
layout = "us,de",
variants = "dvorak,",
options = "grp:ctrl_space_toggle",
}
```
All fields are optional. When a field is omitted, Jay checks the corresponding
environment variable, then falls back to a default:
| Field | Environment Variable | Default |
|------------|--------------------------|----------|
| `rules` | `XKB_DEFAULT_RULES` | `evdev` |
| `model` | `XKB_DEFAULT_MODEL` | `pc105` |
| `layout` | `XKB_DEFAULT_LAYOUT` | `us` |
| `variants` | `XKB_DEFAULT_VARIANTS` | *(none)* |
| `options` | `XKB_DEFAULT_OPTIONS` | *(none)* |
### Using a raw XKB string
You can provide a complete XKB keymap as a multi-line string. See the
[ArchWiki XKB guide](https://wiki.archlinux.org/title/X_keyboard_extension)
for background on the format.
```toml
keymap = """
xkb_keymap {
xkb_keycodes { include "evdev+aliases(qwerty)" };
xkb_types { include "complete" };
xkb_compat { include "complete" };
xkb_symbols { include "pc+us+inet(evdev)" };
};
"""
```
### Loading from a file
Point to an XKB file. Relative paths are resolved from the config directory
(`~/.config/jay/`):
```toml
keymap.path = "./my-keymap.xkb"
```
## Named keymaps
You can define multiple named keymaps and switch between them at runtime.
Define them with the `[[keymaps]]` array, then select the default with
`keymap.name`:
```toml
keymap.name = "laptop"
[[keymaps]]
name = "laptop"
rmlvo = { layout = "us" }
[[keymaps]]
name = "external"
rmlvo = { layout = "de", options = "compose:ralt" }
```
Each entry in `[[keymaps]]` must have a `name` and exactly one of `map`,
`path`, or `rmlvo`.
### Switching keymaps at runtime
Use the `set-keymap` action to switch between named keymaps:
```toml
[shortcuts]
alt-F9 = { type = "set-keymap", keymap.name = "laptop" }
alt-F10 = { type = "set-keymap", keymap.name = "external" }
```
You can also switch keymaps from the command line:
```shell
~$ jay input seat default set-keymap-from-names --layout de
```
## Repeat rate
The repeat rate controls how keys behave when held down. It has two parameters:
- `rate` -- number of key repeats per second
- `delay` -- milliseconds to wait before repeating begins
```toml
repeat-rate = { rate = 25, delay = 250 }
```
### Changing repeat rate at runtime
Use the `set-repeat-rate` action:
```toml
[shortcuts]
alt-F11 = {
type = "set-repeat-rate",
rate = { rate = 40, delay = 200 },
}
```
Or from the command line:
```shell
~$ jay input seat default set-repeat-rate 40 200
```
## Per-device keymaps
You can override the keymap for specific input devices using the `[[inputs]]`
array. For example, to use a different layout for an external keyboard:
```toml
[[inputs]]
match.name = "My External Keyboard"
keymap.rmlvo = { layout = "de" }
```
See the [Input Devices](inputs.md) chapter for more on matching and configuring
individual devices.

View file

@ -0,0 +1,207 @@
# Miscellaneous
This chapter covers smaller configuration options that don't warrant their own
chapter.
## Color Management
The Wayland color management protocol lets applications communicate color space
information to the compositor. It is disabled by default.
```toml
[color-management]
enabled = true
```
> [!NOTE]
> Changing this setting has no effect on applications that are already running.
The CLI and control center (**Color Management** pane) can also toggle it:
```shell
~$ jay color-management enable
~$ jay color-management disable
~$ jay color-management status
```
See [HDR & Color Management](../hdr.md) for a complete guide to HDR output and
the color management protocol.
## Libei
[libei](https://gitlab.freedesktop.org/libinput/libei) allows applications to
emulate input events. By default, applications can only access libei through
the portal (which prompts the user for permission). Setting `enable-socket`
exposes an unauthenticated socket that any application can use without a prompt.
```toml
libei.enable-socket = false # default
```
## UI Drag
Controls whether workspaces and tiles can be dragged with the mouse, and how
far the pointer must move before a drag begins.
```toml
ui-drag = { enabled = true, threshold = 10 } # defaults
```
Set `enabled = false` to disable drag-and-drop rearrangement entirely. Increase
`threshold` if you find yourself accidentally starting drags.
## Floating Window Pin Icon
Floating windows can show a small pin icon. This is hidden by default.
```toml
[float]
show-pin-icon = true
```
## Workspace Capture
Controls whether newly created workspaces can be captured (e.g. for screen
sharing). The default is `true`.
```toml
workspace-capture = false
```
## Simple Input Method
Jay includes a built-in XCompose-based input method. It is enabled by default
but only activates when no external input method is running.
```toml
[simple-im]
enabled = true # default
```
Related actions for use in shortcuts:
`enable-simple-im`
: Enable the built-in input method
`disable-simple-im`
: Disable the built-in input method
`toggle-simple-im-enabled`
: Toggle the built-in input method
`reload-simple-im`
: Reload XCompose files without restarting
`enable-unicode-input`
: Start Unicode codepoint input (requires active IM)
## Log Level
Sets the compositor's log verbosity. Valid values: `trace`, `debug`, `info`,
`warn`, `error`.
```toml
log-level = "info"
```
This setting **cannot** be changed by reloading the configuration. Use the CLI
instead:
```shell
~$ jay set-log-level debug
```
## Focus Follows Mouse
When enabled, moving the pointer over a window automatically gives it keyboard
focus.
```toml
focus-follows-mouse = true # default
```
## Window Management Key
Designates a key that, while held, enables window management mode. In this
mode, the left mouse button moves floating windows and the right mouse button
resizes any window.
```toml
window-management-key = "Alt_L"
```
The value should be a keysym name (see the
[xkbcommon keysym list](https://github.com/xkbcommon/libxkbcommon/blob/master/include/xkbcommon/xkbcommon-keysyms.h)
with the `XKB_KEY_` prefix removed).
## Middle-Click Paste
Controls whether middle-clicking pastes the primary selection. Changing this
has no effect on running applications.
```toml
middle-click-paste = true # default
```
## Pointer Revert Key
Pressing this key cancels any active grabs, drags, or selections, returning the
pointer to its default state. The default is `Escape`.
```toml
pointer-revert-key = "Escape" # default
```
Set it to `NoSymbol` to disable this functionality entirely:
```toml
pointer-revert-key = "NoSymbol"
```
## Fallback Output Mode
Determines which output is used when no particular output is specified -- for
example, when placing a newly opened window or choosing which workspace to move
with `move-to-output`.
`cursor`
: Use the output the cursor is on (default)
`focus`
: Use the output the focused window is on
```toml
fallback-output-mode = "cursor" # default
```
## Focus History
Configures the behavior of the `focus-prev` and `focus-next` actions.
`only-visible`
: Only cycle to windows that are already visible. Default: `false`.
`same-workspace`
: Only cycle to windows on the current workspace. Default: `false`.
If `only-visible` is `false`, switching to a non-visible window will make it
visible first.
```toml
[focus-history]
only-visible = true
same-workspace = true
```
## Control Center Fonts
The `[egui]` table configures fonts used by the control center (an egui-based
GUI).
```toml
[egui]
proportional-fonts = ["sans-serif", "Noto Sans", "Noto Color Emoji"] # default
monospace-fonts = ["monospace", "Noto Sans Mono", "Noto Color Emoji"] # default
```
Override these lists to use your preferred fonts in the control center UI.

View file

@ -0,0 +1,472 @@
# Outputs (Monitors)
Jay configures monitors through the `[[outputs]]` array. Each entry matches
one or more connected displays and applies settings such as position, scale,
mode, and color management.
> [!NOTE]
> Output configuration defined in `config.toml` is only applied the first time
> a matching output is connected after the compositor starts. To change
> settings at runtime, use `jay randr` or the `configure-output` action.
## Matching outputs
Every `[[outputs]]` entry requires a `match` field that selects which monitors
the settings apply to. You can match by serial number, connector name,
manufacturer, or model.
When `match` is a **table**, all specified fields must match (AND logic). When
`match` is an **array**, any entry matching is sufficient (OR logic).
### By serial number (recommended)
The serial number is a unique identifier that stays the same regardless of
which port the monitor is plugged into:
```toml
[[outputs]]
match.serial-number = "33K03894SL0"
scale = 1.5
```
Run `jay randr` to find the serial number of your connected displays.
### By connector name
```toml
[[outputs]]
match.connector = "DP-1"
scale = 1.25
```
Connector names (like `DP-1`, `HDMI-A-1`, `eDP-1`) can change if you move
cables between ports.
### By manufacturer and model
```toml
[[outputs]]
match = { manufacturer = "BNQ", model = "BenQ GW2480" }
scale = 1.25
```
When multiple fields appear in a single table, all must match.
### Combining criteria (OR)
Use an array to match any of several outputs with the same settings:
```toml
[[outputs]]
match = [
{ serial-number = "33K03894SL0" },
{ serial-number = "ETW1M02062SL0" },
]
scale = 2.0
```
## Naming outputs
Assign a `name` to reference an output from other parts of the config -- for
example, when mapping a tablet to a specific monitor or using shortcuts to
reconfigure outputs at runtime:
```toml
[[outputs]]
name = "left"
match.serial-number = "33K03894SL0"
x = 0
y = 0
[[outputs]]
name = "right"
match.serial-number = "ETW1M02062SL0"
x = 1920
y = 0
```
Other rules can then reference these names:
```toml
# Map a drawing tablet to the left monitor
[[inputs]]
match.name = "Wacom Intuos Pro M Pen"
output.name = "left"
```
```toml
# Rotate a named output with a shortcut
[shortcuts]
alt-r = {
type = "configure-output",
output = {
match.name = "right",
transform = "rotate-90",
},
}
```
## Position
The `x` and `y` fields place outputs in compositor space. Coordinates are
integers >= 0 and represent the top-left corner of the output:
```toml
[[outputs]]
match.serial-number = "33K03894SL0"
x = 0
y = 0
[[outputs]]
match.serial-number = "ETW1M02062SL0"
x = 2560
y = 0
```
> [!TIP]
> The control center (`alt-c` by default) includes a visual output arrangement
> editor where you can drag monitors into position.
## Scale
Set fractional scaling with a number greater than 0:
```toml
[[outputs]]
match.serial-number = "33K03894SL0"
scale = 1.5
```
Common values: `1.0` (no scaling), `1.25`, `1.5`, `2.0`.
## Transform
Rotate or flip the output. The available values are:
`none`
: No transformation
`rotate-90`
: Rotate 90 degrees counter-clockwise
`rotate-180`
: Rotate 180 degrees
`rotate-270`
: Rotate 270 degrees counter-clockwise
`flip`
: Flip around the vertical axis
`flip-rotate-90`
: Flip vertically, then rotate 90 degrees counter-clockwise
`flip-rotate-180`
: Flip vertically, then rotate 180 degrees
`flip-rotate-270`
: Flip vertically, then rotate 270 degrees counter-clockwise
```toml
[[outputs]]
match.serial-number = "33K03894SL0"
transform = "rotate-90"
```
## Mode
Set the resolution and refresh rate with the `mode` field. If `refresh-rate` is
omitted, the first available mode with the specified resolution is used:
```toml
[[outputs]]
match.serial-number = "33K03894SL0"
mode = {
width = 2560,
height = 1440,
refresh-rate = 144.0,
}
```
Use `jay randr` to see all available modes for each output:
```shell
~$ jay randr show --modes
```
## Variable Refresh Rate (VRR)
VRR (also known as FreeSync or Adaptive Sync) allows the display to vary its
refresh rate to match the content being rendered, reducing stuttering and
tearing.
Configure VRR with the `vrr` field:
```toml
[[outputs]]
match.serial-number = "33K03894SL0"
vrr = { mode = "variant1", cursor-hz = 90 }
```
### VRR modes
`never`
: VRR is always off (default)
`always`
: VRR is always on
`variant1`
: VRR is on when one or more applications are displayed fullscreen
`variant2`
: VRR is on when exactly one application is displayed fullscreen
`variant3`
: VRR is on when a single application is displayed fullscreen and describes its
content type as video or game via the `wp_content_type_v1` protocol
### Cursor refresh rate
When VRR is active, cursor movement can cause the screen to spike to maximum
refresh rate. The `cursor-hz` field limits cursor-triggered updates:
```toml
vrr = { mode = "always", cursor-hz = 90 }
```
Set `cursor-hz = "none"` for unbounded cursor updates (the default). A numeric
value means the cursor is updated at that rate in Hz, or faster if the
application is already driving updates above that rate.
You can also set default VRR settings for all outputs at the top level:
```toml
vrr = { mode = "variant1", cursor-hz = 90 }
```
Per-output settings override the top-level default.
## Tearing
Tearing allows frames to be presented immediately instead of waiting for
vertical blank, reducing input latency at the cost of visible tearing
artifacts.
```toml
[[outputs]]
match.serial-number = "33K03894SL0"
tearing.mode = "variant3"
```
### Tearing modes
`never`
: Tearing is never enabled
`always`
: Tearing is always enabled
`variant1`
: Tearing is enabled when one or more applications are displayed fullscreen
`variant2`
: Tearing is enabled when a single application is displayed fullscreen
`variant3`
: Tearing is enabled when a single application is displayed and has requested tearing (default)
The default tearing mode is `variant3`. Like VRR, per-output settings override
top-level defaults:
```toml
tearing.mode = "never"
```
## Framebuffer format
The default framebuffer format is `xrgb8888`. You can change it to any DRM
fourcc format:
```toml
[[outputs]]
match.serial-number = "33K03894SL0"
format = "rgb565"
```
Common formats include `xrgb8888`, `argb8888`, `xbgr8888`, `abgr8888`,
`rgb565`, and many others. See the
[auto-generated specification](https://github.com/mahkoh/jay/blob/master/toml-spec/spec/spec.generated.md) for the full list.
## HDR and color management
Jay supports HDR output through color space, transfer function, and brightness
settings. These require the Vulkan renderer. For a conceptual overview and
step-by-step guide, see [HDR & Color Management](../hdr.md).
### Color space
```toml
[[outputs]]
match.serial-number = "33K03894SL0"
color-space = "bt2020"
```
Values: `default` (usually sRGB) or `bt2020`.
### Transfer function (EOTF)
```toml
[[outputs]]
match.serial-number = "33K03894SL0"
transfer-function = "pq"
```
Values: `default` (usually gamma 2.2) or `pq` (Perceptual Quantizer, used for
HDR10).
### Brightness
Set SDR content brightness in cd/m^2 or use `"default"`:
```toml
[[outputs]]
match.serial-number = "33K03894SL0"
brightness = 80
```
The default depends on the transfer function:
- With `default` EOTF: the maximum brightness of the display, anchored at
80 cd/m^2. Setting a value below 80 creates HDR headroom.
- With `pq`: 203 cd/m^2.
This setting has no effect unless the Vulkan renderer is in use.
## Blend space
Controls how colors are blended when compositing overlapping surfaces:
```toml
[[outputs]]
match.serial-number = "33K03894SL0"
blend-space = "linear"
```
`srgb`
: Classic desktop blending in sRGB space (default)
`linear`
: Physically correct blending in linear light -- produces brighter results
## Native gamut
By default, Jay assumes displays use sRGB primaries (matching the behavior of
most other compositors). In reality, many displays have a wider gamut.
Setting `use-native-gamut = true` tells Jay to use the primaries advertised in
the display's EDID. This can produce more accurate colors and allows
color-managed applications to use the full gamut:
```toml
[[outputs]]
match.serial-number = "33K03894SL0"
use-native-gamut = true
```
This has no effect when the display is explicitly operating in a wide color
space (e.g. BT.2020).
## Connector configuration
The `[[connectors]]` array lets you enable or disable physical display
connectors. This is useful for permanently disabling a port:
```toml
[[connectors]]
match.name = "eDP-1"
enabled = false
```
Connector configuration is applied when the connector is first discovered by
the compositor, which typically happens only at startup.
## Lid switch (auto-disable laptop screen)
On laptops, you can automatically disable the built-in display when the lid is
closed using the `[[inputs]]` array. The lid switch is an input device:
```toml
[[inputs]]
match.name = "<lid switch name>"
on-lid-closed = {
type = "configure-connector",
connector = {
match.name = "eDP-1",
enabled = false,
},
}
on-lid-opened = {
type = "configure-connector",
connector = {
match.name = "eDP-1",
enabled = true,
},
}
```
Run `jay input` to find the name of your lid switch device. See the
[Input Devices](inputs.md) chapter for more details.
## Runtime changes
Output settings in `config.toml` are only applied when a display is first
connected after compositor startup. For runtime changes, use the `jay randr`
CLI or the `configure-output` action.
### Listing outputs
```shell
~$ jay randr
```
This shows all connected outputs with their connector names, serial numbers,
current modes, scales, transforms, and available modes.
### Changing settings at runtime
```shell
~$ jay randr output <name-or-connector> scale 1.5
~$ jay randr output <name-or-connector> mode 2560 1440 144.0
~$ jay randr output <name-or-connector> position 1920 0
~$ jay randr output <name-or-connector> transform rotate-90
~$ jay randr output <name-or-connector> enable
~$ jay randr output <name-or-connector> disable
```
### Using shortcuts
The `configure-output` action lets you change output settings from a
keybinding:
```toml
[shortcuts]
alt-F7 = {
type = "configure-output",
output = {
match.name = "right",
transform = "none",
},
}
alt-F8 = {
type = "configure-output",
output = {
match.name = "right",
transform = "rotate-90",
},
}
```
## Full reference
For the exhaustive list of all output fields, match criteria, and related
types, see the [auto-generated specification](https://github.com/mahkoh/jay/blob/master/toml-spec/spec/spec.generated.md).

View file

@ -0,0 +1,505 @@
# Shortcuts
Shortcuts bind key combinations to actions. They are the primary way to
interact with Jay.
## Basic syntax
Shortcuts are defined in the `[shortcuts]` table. The left side is a key
combination; the right side is an action:
```toml
[shortcuts]
alt-q = "quit"
alt-Return = { type = "exec", exec = "alacritty" }
alt-shift-c = "close"
```
### Key format
Key combinations follow the pattern `MODIFIER-MODIFIER-KEYSYM`:
```
(MOD-)*KEYSYM
```
**Keysym names** are unmodified XKB keysym names from [xkbcommon-keysyms.h](https://github.com/xkbcommon/libxkbcommon/blob/master/include/xkbcommon/xkbcommon-keysyms.h)
with the `XKB_KEY_` prefix removed. Use the unmodified keysym -- write
`shift-q`, not `shift-Q`.
### Modifiers
The available modifiers are:
`shift`
: Shift key
`ctrl`
: Control key
`alt`
: Alt key
`logo`
: Super/Meta/Windows key
`lock`
: Lock modifier
`caps`
: Caps Lock
`num`
: Num Lock
`mod1`
: Mod1 (typically Alt)
`mod2`
: Mod2 (typically Num Lock)
`mod3`
: Mod3
`mod4`
: Mod4 (typically Super)
`mod5`
: Mod5
`release`
: Fire on key **release** instead of press
The `release` modifier is special: it causes the action to trigger when the key
is released rather than when it is pressed.
## Simple actions
Simple actions are written as plain strings. Here are the most commonly used
ones:
**Focus and movement:**
```toml
[shortcuts]
alt-h = "focus-left"
alt-j = "focus-down"
alt-k = "focus-up"
alt-l = "focus-right"
alt-shift-h = "move-left"
alt-shift-j = "move-down"
alt-shift-k = "move-up"
alt-shift-l = "move-right"
```
**Layout:**
```toml
[shortcuts]
alt-d = "split-horizontal"
alt-v = "split-vertical"
alt-t = "toggle-split"
alt-m = "toggle-mono"
alt-f = "focus-parent"
```
**Window management:**
```toml
[shortcuts]
alt-u = "toggle-fullscreen"
alt-shift-f = "toggle-floating"
alt-shift-c = "close"
```
**Compositor control:**
```toml
[shortcuts]
alt-q = "quit"
alt-shift-r = "reload-config-toml"
```
**Other useful simple actions:**
- `consume` -- consume the key event (prevent it from reaching applications).
Key-press events that trigger shortcuts are consumed by default; key-release
events are forwarded by default. Consuming key-release events can cause keys
to get stuck in the focused application.
- `forward` -- forward the key event to the focused application (the inverse
of `consume`)
- `none` -- unbind this key combination (useful for overriding defaults or
inherited mode bindings)
- `disable-pointer-constraint` -- release a pointer lock/confinement
- `focus-parent` -- move focus to the parent container
- `toggle-bar`, `show-bar`, `hide-bar` -- control the status bar
- `open-control-center` -- open the Jay control center GUI
- `warp-mouse-to-focus` -- warp the cursor to the center of the focused window
- `kill-client` -- forcefully disconnect a client (in a window rule, kills the
window's client; in a client rule, kills the matched client; has no effect
in plain shortcuts)
- `focus-below`, `focus-above` -- move focus to the layer below or above the
current layer
- `focus-tiles` -- focus the tile layer
- `create-mark`, `jump-to-mark` -- interactively create or jump to a mark
(the next pressed key identifies the mark). See [Marks](#marks) below.
- `enable-window-management`, `disable-window-management` -- programmatically
enable or disable [window management mode](../floating.md#window-management-mode)
- `reload-config-so` -- reload the shared-library configuration (`config.so`)
See the [specification](https://github.com/mahkoh/jay/blob/master/toml-spec/spec/spec.generated.md) for the full list of simple
actions.
## Parameterized actions
Actions that need arguments are written as tables with a `type` field:
### Launching programs
```toml
[shortcuts]
alt-Return = { type = "exec", exec = "alacritty" }
alt-p = { type = "exec", exec = "bemenu-run" }
```
### Switching virtual terminals
```toml
[shortcuts]
ctrl-alt-F1 = { type = "switch-to-vt", num = 1 }
ctrl-alt-F2 = { type = "switch-to-vt", num = 2 }
```
### Workspaces
```toml
[shortcuts]
alt-F1 = { type = "show-workspace", name = "1" }
alt-F2 = { type = "show-workspace", name = "2" }
alt-shift-F1 = { type = "move-to-workspace", name = "1" }
alt-shift-F2 = { type = "move-to-workspace", name = "2" }
```
### Moving workspaces to outputs
```toml
[shortcuts]
logo-ctrl-shift-Right = {
type = "move-to-output",
direction = "right",
}
logo-ctrl-shift-Left = {
type = "move-to-output",
direction = "left",
}
```
### Other parameterized actions
- `set-keymap` -- change the active keymap
- `set-repeat-rate` -- change the keyboard repeat rate
- `set-env` -- set environment variables for future spawned programs
- `unset-env` -- remove environment variables
- `configure-connector` -- enable/disable a monitor
- `configure-input` -- change input device settings
- `configure-output` -- change output settings
- `configure-idle` -- change the idle timeout
- `configure-direct-scanout` -- enable or disable direct scanout
- `configure-drm-device` -- apply settings to a DRM device
- `set-theme` -- change theme settings
- `set-log-level` -- change the compositor log level
- `set-gfx-api` -- set the graphics API for new DRM devices (usually only
effective at startup)
- `set-render-device` -- set the render device for compositing
- `define-action` -- define or redefine a named action at runtime
- `undefine-action` -- remove a named action
- `create-mark` -- create a mark with an explicit ID (see [Marks](#marks))
- `jump-to-mark` -- jump to a mark with an explicit ID
- `copy-mark` -- copy a mark from one ID to another
- `create-virtual-output` -- create a virtual output
- `remove-virtual-output` -- remove a virtual output
See the [specification](https://github.com/mahkoh/jay/blob/master/toml-spec/spec/spec.generated.md) for the complete list.
## Running multiple actions
Use an array to run several actions from a single shortcut:
```toml
[shortcuts]
alt-q = [
{ type = "exec", exec = ["notify-send", "Goodbye!"] },
"quit",
]
```
## The exec action in detail
The `exec` field accepts three forms:
**A simple string** -- the program name with no arguments:
```toml
alt-Return = { type = "exec", exec = "alacritty" }
```
**An array of strings** -- the program name followed by arguments:
```toml
alt-n = { type = "exec", exec = ["notify-send", "Hello", "World"] }
```
**A table** -- full control over execution. Exactly one of `prog` or `shell`
must be specified:
```toml
# Using prog + args
alt-n = {
type = "exec",
exec = {
prog = "notify-send",
args = ["Hello"],
env = { LANG = "en_US.UTF-8" },
},
}
# Using shell (runs as: $SHELL -c "command")
alt-s = {
type = "exec",
exec = {
shell = "grim - | wl-copy",
privileged = true,
},
}
```
Table fields:
`prog`
: Program to execute (mutually exclusive with `shell`)
`shell`
: Shell command to run via `$SHELL -c` (mutually exclusive with `prog`)
`args`
: Arguments array (only with `prog`)
`env`
: Per-process environment variables
`privileged`
: If `true`, grants access to privileged Wayland protocols (default: `false`)
`tag`
: Tag to apply to all Wayland connections spawned by this process
### Practical examples
Volume control with `pactl`:
```toml
[shortcuts]
XF86AudioRaiseVolume = {
type = "exec",
exec = ["pactl", "set-sink-volume", "0", "+5%"],
}
XF86AudioLowerVolume = {
type = "exec",
exec = ["pactl", "set-sink-volume", "0", "-5%"],
}
XF86AudioMute = {
type = "exec",
exec = ["pactl", "set-sink-mute", "0", "toggle"],
}
```
Taking a screenshot and copying to clipboard:
```toml
[shortcuts]
Print = {
type = "exec",
exec = {
shell = "grim - | wl-copy",
privileged = true,
},
}
```
## Complex shortcuts
Complex shortcuts provide additional control via the `[complex-shortcuts]`
table. They support:
- **`mod-mask`** -- controls which modifiers are considered when matching.
Set to `""` to ignore all modifiers.
- **`action`** -- the action to run on key press (defaults to `"none"`).
- **`latch`** -- an action to run when the key is **released**.
### Volume keys regardless of modifiers
The volume keys should work whether or not Alt, Shift, etc. are held:
```toml
[complex-shortcuts.XF86AudioRaiseVolume]
mod-mask = ""
action = {
type = "exec",
exec = ["pactl", "set-sink-volume", "0", "+5%"],
}
[complex-shortcuts.XF86AudioLowerVolume]
mod-mask = ""
action = {
type = "exec",
exec = ["pactl", "set-sink-volume", "0", "-5%"],
}
```
### Push-to-talk
Unmute audio while a key is held, mute on release:
```toml
[complex-shortcuts.alt-x]
action = {
type = "exec",
exec = ["pactl", "set-sink-mute", "0", "0"],
}
latch = {
type = "exec",
exec = ["pactl", "set-sink-mute", "0", "1"],
}
```
The `latch` action fires when the triggering key (`x` in this case) is
released, regardless of any other keys pressed at that time.
## Marks
Marks let you tag a window and quickly jump back to it later, similar to marks
in Vim.
### Interactive marks
The simplest way to use marks is interactively. Bind `create-mark` and
`jump-to-mark` as simple string actions:
```toml
[shortcuts]
alt-m = "create-mark"
alt-apostrophe = "jump-to-mark"
```
When you press `alt-m`, Jay waits for the next key press (e.g. `a`) and
assigns the mark to the currently focused window. When you press
`alt-apostrophe` followed by `a`, Jay focuses the marked window.
### Hard-coded marks
You can skip the interactive step by specifying a mark ID directly:
```toml
[shortcuts]
alt-shift-1 = { type = "create-mark", id.key = "1" }
alt-1 = { type = "jump-to-mark", id.key = "1" }
```
Mark IDs can be identified by a key name (`id.key`) or by an arbitrary string
(`id.name`):
```toml
[shortcuts]
alt-shift-b = { type = "create-mark", id.name = "browser" }
alt-b = { type = "jump-to-mark", id.name = "browser" }
```
Key names use Linux input event code names with the `KEY_` prefix removed, all
lowercase (see the [Linux input event codes](https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h)).
### Copying marks
The `copy-mark` action copies a mark from one ID to another:
```toml
[shortcuts]
alt-c = { type = "copy-mark", src.key = "a", dst.name = "backup" }
```
## Named actions
Named actions provide another layer of reuse. Define them in the `[actions]`
table and reference them with `$name`:
```toml
[actions]
my-layout = [
"split-horizontal",
{ type = "exec", exec = "alacritty" },
]
[shortcuts]
alt-l = "$my-layout"
```
You can redefine named actions at runtime using the `define-action` and
`undefine-action` parameterized actions:
```toml
[shortcuts]
alt-shift-q = {
type = "define-action",
name = "my-layout",
action = "quit",
}
```
## Virtual outputs
Virtual outputs can be created and removed via actions. A virtual output has
the connector name `VO-{name}` and the serial number `{name}`. A newly created
virtual output is initially disabled.
```toml
[shortcuts]
alt-shift-v = {
type = "create-virtual-output",
name = "screen-share",
}
alt-shift-x = {
type = "remove-virtual-output",
name = "screen-share",
}
```
You can pre-configure the virtual output using connector and output match
rules:
```toml
[[connectors]]
match.name = "VO-screen-share"
enabled = true
[[outputs]]
match.connector = "VO-screen-share"
mode = {
width = 1920,
height = 1080,
refresh-rate = 120.0,
}
```
## Actions in window rules
When certain simple actions are used inside a [window rule](../window-rules.md),
they apply to the **matched window** instead of the focused window. The
affected actions are: `move-left`, `move-down`, `move-up`, `move-right`,
`split-horizontal`, `split-vertical`, `toggle-split`, `tile-horizontal`,
`tile-vertical`, `show-single`, `show-all`, `toggle-fullscreen`,
`enter-fullscreen`, `exit-fullscreen`, `close`, `toggle-floating`, `float`,
`tile`, `toggle-float-pinned`, `pin-float`, and `unpin-float`.
Similarly, `kill-client` applies to the matched window's client in a window
rule, or to the matched client in a client rule.

View file

@ -0,0 +1,104 @@
# Startup Actions
Jay provides hooks that run actions at specific points during compositor
startup and during idle transitions.
## on-graphics-initialized
This hook runs after the GPU has been initialized and the compositor is ready
to display graphical content. It is the right place to start **graphical
applications** such as notification daemons, system tray bridges, status bars,
and similar programs.
```toml
on-graphics-initialized = { type = "exec", exec = "mako" }
```
To start multiple programs, use an array of actions:
```toml
on-graphics-initialized = [
{ type = "exec", exec = "mako" },
{ type = "exec", exec = "wl-tray-bridge" },
]
```
> [!NOTE]
> The built-in default configuration starts [mako](https://github.com/emersion/mako)
> (notification daemon) and [wl-tray-bridge](https://github.com/mahkoh/wl-tray-bridge)
> (system tray bridge) in `on-graphics-initialized`. Once you create a config
> file, these defaults are replaced -- include them in your config if you want
> to keep them.
This hook runs when the config is first loaded after compositor startup. It
does **not** re-run on config reload.
## on-startup
This hook runs as early as possible when the compositor starts -- **before**
graphics are initialized. Do not start graphical applications here; they will
likely fail to connect to the display.
Use `on-startup` for tasks like setting environment variables or other
non-graphical initialization:
```toml
on-startup = {
type = "set-env",
env = { XDG_CURRENT_DESKTOP = "jay" },
}
```
This hook has **no effect on config reload** -- it only runs once when the
compositor first starts.
## on-idle
This hook runs when the compositor transitions to the idle state (i.e., after
the configured idle timeout expires with no user input). The most common use
case is starting a screen locker.
```toml
on-idle = {
type = "exec",
exec = {
prog = "swaylock",
privileged = true,
},
}
```
> [!NOTE]
> Screen lockers need `privileged = true` to access the privileged Wayland
> protocols required for locking the session.
You can combine idle with a grace period. The idle timeout and grace period are
configured separately in the `[idle]` section (see [Idle & Screen
Locking](idle.md)):
```toml
idle = { minutes = 10 }
on-idle = {
type = "exec",
exec = {
prog = "swaylock",
privileged = true,
},
}
```
Like the other hooks, `on-idle` accepts arrays of actions:
```toml
on-idle = [
{ type = "exec", exec = ["notify-send", "Going idle..."] },
{
type = "exec",
exec = {
prog = "swaylock",
privileged = true,
},
},
]
```

View file

@ -0,0 +1,97 @@
# Status Bar
Jay includes a built-in bar that displays workspace tabs, status text, tray
icons (via [wl-tray-bridge](https://github.com/mahkoh/wl-tray-bridge)), and a
clock. The status text is provided by an external program that you configure
in the `[status]` table.
## Configuring a Status Program
The `[status]` table has three fields:
`format`
: Message format: `plain`, `pango`, or `i3bar`. Optional.
`exec`
: How to start the program (string, array, or table). Required.
`i3bar-separator`
: Separator between i3bar components (default `" | "`). Optional.
### Format
`plain`
: Plain text output
`pango`
: Output containing Pango markup
`i3bar`
: JSON output in i3bar protocol format
### Exec
The `exec` field accepts the same forms used elsewhere in the configuration:
- **String** -- the program name: `exec = "i3status"`
- **Array** -- program and arguments: `exec = ["i3status", "-c", "~/.config/i3status/config"]`
- **Table** -- full control over program, arguments, and environment (see the
spec for details)
## Example: i3status
[i3status](https://i3wm.org/i3status/) is a popular status line generator.
```toml
[status]
format = "i3bar"
exec = "i3status"
```
> [!NOTE]
> i3status defaults to plain-text output. You must explicitly configure it to
> use i3bar format by adding `output_format = "i3bar"` to your
> `~/.config/i3status/config`:
>
> ```
> general {
> output_format = "i3bar"
> }
> ```
## Example: Custom Script
A simple shell script that prints the date every second:
```toml
[status]
format = "plain"
exec = { shell = "while true; do date '+%Y-%m-%d %H:%M:%S'; sleep 1; done" }
```
## Changing the Status Program at Runtime
The `set-status` action lets you switch the status program from a shortcut.
Omit the `status` field to reset the status text to empty.
```toml
[shortcuts]
# Switch to i3status
alt-F10 = {
type = "set-status",
status = {
format = "i3bar",
exec = "i3status",
},
}
# Clear the status text
alt-F11 = { type = "set-status" }
```
## Bar Appearance
The bar's visual appearance (height, background color, text color, position, and
font) is configured in the `[theme]` table. See the
[Theme & Appearance](theme.md) chapter for details. The bar can be shown or
hidden with the `show-bar` top-level setting or the `toggle-bar` action.

View file

@ -0,0 +1,205 @@
# Theme & Appearance
Jay's visual appearance -- colors, fonts, sizes, and layout -- is controlled by
the `[theme]` table and a handful of top-level toggles. Every setting described
here can also be adjusted at runtime from the control center's **Look and Feel**
pane, which provides color pickers and live preview.
## Colors
Colors are specified as hex strings in one of four formats:
`#rgb` (e.g. `#f00`)
: Short RGB
`#rrggbb` (e.g. `#ff0000`)
: Full RGB
`#rgba` (e.g. `#f008`)
: Short RGB + alpha
`#rrggbbaa` (e.g. `#ff000080`)
: Full RGB + alpha
The available color keys in the `[theme]` table are:
`bg-color`
: Desktop background
`bar-bg-color`
: Bar background
`bar-status-text-color`
: Status text in the bar
`border-color`
: Borders between tiled windows
`focused-title-bg-color`
: Background of the focused window's title
`focused-title-text-color`
: Text color of the focused window's title
`unfocused-title-bg-color`
: Background of unfocused window titles
`unfocused-title-text-color`
: Text color of unfocused window titles
`focused-inactive-title-bg-color`
: Background of focused-but-inactive titles
`focused-inactive-title-text-color`
: Text color of focused-but-inactive titles
`attention-requested-bg-color`
: Background of titles that have requested attention
`captured-focused-title-bg-color`
: Background of focused titles that are being recorded
`captured-unfocused-title-bg-color`
: Background of unfocused titles that are being recorded
`separator-color`
: Separator between title bars and window content
`highlight-color`
: Accent color used to highlight parts of the UI
"Focused-inactive" refers to a window that was most recently focused in its
container but whose container is not the active one. The "captured" colors apply
when a window is being recorded (e.g. via screen sharing).
### Example
```toml
[theme]
bg-color = "#1e1e2e"
bar-bg-color = "#181825"
bar-status-text-color = "#cdd6f4"
border-color = "#313244"
focused-title-bg-color = "#89b4fa"
focused-title-text-color = "#1e1e2e"
unfocused-title-bg-color = "#313244"
unfocused-title-text-color = "#cdd6f4"
attention-requested-bg-color = "#f38ba8"
highlight-color = "#f5c2e7"
```
## Sizes
`border-width`
: Width of borders between windows (px)
`title-height`
: Height of window title tabs (px)
`bar-height`
: Height of the bar (px). Defaults to the same as `title-height`.
`bar-separator-width`
: Width of the bar's bottom separator (px). Default: `1`.
```toml
[theme]
border-width = 2
title-height = 24
bar-height = 28
```
## Fonts
`font`
: General font for the compositor
`title-font`
: Font used in window title bars. Defaults to the same as `font`.
`bar-font`
: Font used in the status bar. Defaults to the same as `font`.
```toml
[theme]
font = "JetBrains Mono 10"
title-font = "Inter 10"
bar-font = "Inter 10"
```
## Bar Position
The `bar-position` field controls whether the bar appears at the top or bottom
of each output. The default is `top`.
```toml
[theme]
bar-position = "bottom"
```
## Changing the Theme at Runtime
Use the `set-theme` action in a shortcut to change theme properties on the fly:
```toml
[shortcuts]
alt-F9 = { type = "set-theme", theme.bg-color = "#000000" }
```
Only the fields you include are changed; everything else stays the same.
## Showing and Hiding UI Elements
These top-level settings control whether the bar and title bars are visible:
`show-bar`
: Show the built-in status bar. Default: `true`.
`show-titles`
: Show window title bars. Default: `true`.
```toml
show-bar = false
show-titles = false
```
Corresponding actions let you toggle these at runtime:
`show-bar`
: Shows the bar
`hide-bar`
: Hides the bar
`toggle-bar`
: Toggles bar visibility
`show-titles`
: Shows title bars
`hide-titles`
: Hides title bars
`toggle-titles`
: Toggles title bars
```toml
[shortcuts]
alt-b = "toggle-bar"
alt-t = "toggle-titles"
```
## Workspace Display Order
The `workspace-display-order` top-level setting controls how workspace tabs
appear in the bar:
`manual`
: Workspaces can be reordered by dragging (default)
`sorted`
: Workspaces are displayed in alphabetical order
```toml
workspace-display-order = "sorted"
```

View file

@ -0,0 +1,91 @@
# Xwayland
Xwayland provides compatibility with legacy X11 applications inside a Wayland
session. Jay starts Xwayland automatically by default.
## Configuration
The `[xwayland]` table controls Xwayland behavior:
`enabled`
: Whether Xwayland is started. Default: `true`.
`scaling-mode`
: How X11 windows are scaled on HiDPI outputs. Default: `default`.
```toml
[xwayland]
enabled = true
scaling-mode = "default"
```
### Scaling Modes
`default`
: Render at the lowest scale, then upscale to other outputs
`downscaled`
: Render at the highest integer scale, then downscale to match each output
The `downscaled` mode produces sharper text and UI on HiDPI monitors but has a
significant performance cost. For example, on a 3840x2160 output at 1.5x scale,
a fullscreen X11 window would be rendered at 5120x2880 (integer scale 2) and
then downscaled -- roughly doubling the pixel count. This mode also requires
X11 applications to handle scaling themselves (e.g. `GDK_SCALE=2`).
## CLI
You can inspect and change Xwayland settings from the command line:
```shell
~$ jay xwayland status
~$ jay xwayland set-scaling-mode default
~$ jay xwayland set-scaling-mode downscaled
```
Xwayland settings are also available in the control center's **Xwayland** pane.
## Disabling Xwayland
If you don't need X11 compatibility, disabling Xwayland avoids starting the
X server entirely:
```toml
[xwayland]
enabled = false
```
## Matching X11 Windows in Rules
Window rules can target X11 windows using properties that only exist on X
clients. These fields are available in the `match` table of `[[windows]]`
rules:
`x-class` / `x-class-regex`
: Match the X11 WM_CLASS class (verbatim or regex)
`x-instance` / `x-instance-regex`
: Match the X11 WM_CLASS instance (verbatim or regex)
`x-role` / `x-role-regex`
: Match the X11 WM_WINDOW_ROLE (verbatim or regex)
For example, to float all GIMP tool windows:
```toml
[[windows]]
match.x-class = "Gimp"
match.x-role-regex = "gimp-(toolbox|dock)"
initial-tile-state = "floating"
```
### Matching at the Client Level
Client rules support the `is-xwayland` field to match (or exclude) the
Xwayland client itself:
```toml
[[clients]]
match.is-xwayland = true
# ... grant capabilities, etc.
```