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

@ -1,521 +0,0 @@
# Configuration
Jay can be configured via
- a declarative TOML file or
- a shared library that gets injected into the compositor.
## Shared Library Configuration
This is described in the [rustdoc](https://docs.rs/jay-config) of the configuration crate.
## TOML Configuration
The configuration file is stored under `$HOME/.config/jay/config.toml`.
If you don't have such a file, the default configuration will be used.
The full format of this file is described in the auto-generated file [spec.generated.md](../toml-spec/spec/spec.generated.md).
You can also get auto completion with the auto-generated JSON Schema linked from that document.
The following code block contains the annotated default configuration.
Below that we will describe individual usecases.
```toml
# The keymap that is used for shortcuts and also sent to clients.
keymap = """
xkb_keymap {
xkb_keycodes { include "evdev+aliases(qwerty)" };
xkb_types { include "complete" };
xkb_compat { include "complete" };
xkb_symbols { include "pc+us+inet(evdev)" };
};
"""
# An action that will be executed when the GPU has been initialized.
on-graphics-initialized = [
{ type = "exec", exec = "mako" },
{ type = "exec", exec = "wl-tray-bridge" },
]
# Shortcuts that are processed by the compositor.
# The left hand side should be a key, possibly prefixed with modifiers.
# The right hand side should be an action.
[shortcuts]
# The focus-X actions move the keyboard focus to next window on the X.
alt-h = "focus-left"
alt-j = "focus-down"
alt-k = "focus-up"
alt-l = "focus-right"
# The move-X actions move window that has the keyboard focus to the X.
alt-shift-h = "move-left"
alt-shift-j = "move-down"
alt-shift-k = "move-up"
alt-shift-l = "move-right"
# The split-X action places the currently focused window in a container
# and sets the split direction of the container to X.
alt-d = "split-horizontal"
alt-v = "split-vertical"
# The toggle-split action changes the split direction of the current
# container.
alt-t = "toggle-split"
# The toggle-mono action changes whether the current container shows
# a single window or all windows next to each other.
alt-m = "toggle-mono"
# The toggle-fullscreen action toggles the current window between
# windowed and fullscreen.
alt-u = "toggle-fullscreen"
# The focus-parent action moves the keyboard focus to the parent of
# the currently focused window.
alt-f = "focus-parent"
# The open-control-center action opens the control center.
alt-c = "open-control-center"
# The close action requests the currently focused window to close.
alt-shift-c = "close"
# The toggle-floating action changes the currently focused window between
# floating and tiled.
alt-shift-f = "toggle-floating"
# All actions above are so-called simple actions that are identified by
# a string. More complex actions take parameters and are written as a table.
# For example, the exec action spawns an application and has the exec field
# that describes how to spawn the application.
Super_L = { type = "exec", exec = "alacritty" }
alt-p = { type = "exec", exec = "bemenu-run" }
# The quit action terminates the compositor.
alt-q = "quit"
# The reload-config-toml action reloads the TOML configuration file.
alt-shift-r = "reload-config-toml"
# The switch-to-vt action switches to a different virtual terminal.
ctrl-alt-F1 = { type = "switch-to-vt", num = 1 }
ctrl-alt-F2 = { type = "switch-to-vt", num = 2 }
ctrl-alt-F3 = { type = "switch-to-vt", num = 3 }
ctrl-alt-F4 = { type = "switch-to-vt", num = 4 }
ctrl-alt-F5 = { type = "switch-to-vt", num = 5 }
ctrl-alt-F6 = { type = "switch-to-vt", num = 6 }
ctrl-alt-F7 = { type = "switch-to-vt", num = 7 }
ctrl-alt-F8 = { type = "switch-to-vt", num = 8 }
ctrl-alt-F9 = { type = "switch-to-vt", num = 9 }
ctrl-alt-F10 = { type = "switch-to-vt", num = 10 }
ctrl-alt-F11 = { type = "switch-to-vt", num = 11 }
ctrl-alt-F12 = { type = "switch-to-vt", num = 12 }
# The show-workspace action switches to a workspace. If the workspace is not
# currently being used, it is created on the output that contains the pointer.
alt-F1 = { type = "show-workspace", name = "1" }
alt-F2 = { type = "show-workspace", name = "2" }
alt-F3 = { type = "show-workspace", name = "3" }
alt-F4 = { type = "show-workspace", name = "4" }
alt-F5 = { type = "show-workspace", name = "5" }
alt-F6 = { type = "show-workspace", name = "6" }
alt-F7 = { type = "show-workspace", name = "7" }
alt-F8 = { type = "show-workspace", name = "8" }
alt-F9 = { type = "show-workspace", name = "9" }
alt-F10 = { type = "show-workspace", name = "10" }
alt-F11 = { type = "show-workspace", name = "11" }
alt-F12 = { type = "show-workspace", name = "12" }
# The move-to-workspace action moves the currently focused window to a workspace.
alt-shift-F1 = { type = "move-to-workspace", name = "1" }
alt-shift-F2 = { type = "move-to-workspace", name = "2" }
alt-shift-F3 = { type = "move-to-workspace", name = "3" }
alt-shift-F4 = { type = "move-to-workspace", name = "4" }
alt-shift-F5 = { type = "move-to-workspace", name = "5" }
alt-shift-F6 = { type = "move-to-workspace", name = "6" }
alt-shift-F7 = { type = "move-to-workspace", name = "7" }
alt-shift-F8 = { type = "move-to-workspace", name = "8" }
alt-shift-F9 = { type = "move-to-workspace", name = "9" }
alt-shift-F10 = { type = "move-to-workspace", name = "10" }
alt-shift-F11 = { type = "move-to-workspace", name = "11" }
alt-shift-F12 = { type = "move-to-workspace", name = "12" }
```
### Configuring Keymaps and Repeat Rates
The keymap can be configured via the top-level `keymap` field.
```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)" };
};
"""
```
The format is described in the ArchWiki: https://wiki.archlinux.org/title/X_keyboard_extension
If you want to use multiple keymaps, you can assign names to them:
```toml
keymap.name = "laptop"
[[keymaps]]
name = "laptop"
path = "./laptop-keymap.xkb"
[[keymaps]]
name = "external"
path = "./external-keymap.xkb"
```
Such paths are relative to the configuration file.
You can also write the map inline in this format:
```toml
[[keymaps]]
name = "external"
map = "..."
```
If you want to switch the keymap with a shortcut, use the `set-keymap` action:
```toml
[shortcuts]
alt-j = { type = "set-keymap", keymap.name = "laptop" }
alt-k = { type = "set-keymap", keymap.name = "external" }
```
The keyboard repeat rate is configured via the top-level `repeat-rate` field.
```toml
repeat-rate = { rate = 25, delay = 250 }
```
You can change this at runtime with the `set-repeat-rate` action:
```toml
[shortcuts]
alt-x = { type = "set-repeat-rate", rate = { rate = 25, delay = 250 } }
```
Note that you can change all of this from the command line with the `jay input` command.
### Configuring Shortcuts
Shortcuts are configured in the top-level `shortcuts` table.
```toml
[shortcuts]
alt-h = "focus-left"
```
The left-hand side should be a key that can optionally be prefixed with modifiers.
The right-hand side should be an action.
See [spec.generated.md](../toml-spec/spec/spec.generated.md) for a full list of actions.
### Complex Shortcuts
If you need more control over shortcut execution, you can use the `complex-shortcuts` table.
```toml
[complex-shortcuts.alt-x]
action = { type = "exec", exec = ["pactl", "set-sink-mute", "0", "1"] }
latch = { type = "exec", exec = ["pactl", "set-sink-mute", "0", "0"] }
```
This mutes the audio output while the key is pressed and un-mutes once the `x` key is released.
The order in which `alt` and `x` are released does not matter for this.
This can also be used to implement push to talk.
See the specification for more details.
### Running Multiple Actions
In every place that accepts an action, you can also run multiple actions by wrapping them
in an array:
```toml
[shortcuts]
alt-h = ["focus-left", "focus-up"]
```
### Spawning Applications
You can spawn applications by using the `exec` action:
```toml
Super_L = { type = "exec", exec = "alacritty" }
```
The `exec` field can be either a string, an array of strings, or a table.
When a string is used, it should be the name of the application.
When an array is used, it should be the name of the application followed by arguments.
```toml
Super_L = { type = "exec", exec = ["alacritty", "-e", "date"] }
```
When a table is used, you can additionally specify
- environment variables to pass to the application,
- whether the application should have access to privileged protocols.
See the specification for more details.
### Running an Action at Startup
If you want to run an action at startup, you can use the top-level `on-graphics-initialized`
field:
```toml
on-graphics-initialized = [
{ type = "exec", exec = "mako" },
{ type = "exec", exec = "wl-tray-bridge" },
]
```
### Setting Environment Variables
You can set environment variables with the the top level `env` table.
```toml
[env]
GTK_THEME = "Adwaita:dark"
```
These environment variables are passed to all applications started afterwards.
You can also use the `set-env` action to modify these variables:
```toml
[shortcuts]
alt-l = { type = "set-env", env.GTK_THEME = "Adwaita:dark" }
```
The `unset-env` action is similar.
See the specification for more details.
### Using a Status Program
You can configure a status program with the top-level `status` table.
```toml
[status]
format = "i3bar"
exec = "i3status"
```
The `format` field specifies the format used by the status program.
Possible values are `plain`, `pango`, and `i3bar`.
The `exec` field specifies how to start the status program.
Note that i3status will not automatically use i3bar format when started this way.
You have to explicitly opt into i3bar format in your i3status configuration.
See the specification for more details.
### Configuring Idle Timeout and Actions
You can configure the idle timeout with the top-level `idle` table.
```toml
idle.minutes = 10
```
If you want to lock the screen when this timeout happens, you can use the `on-idle` table.
```toml
on-idle = { type = "exec", exec = { prog = "swaylock", privileged = true } }
```
See the specification for more details.
### Configuring GPUs
You can configure GPUs with the top-level `drm-devices` array.
```toml
[[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"
```
For each device, you can configure the following properties:
- Whether direct scanout is enabled on monitors connected to this device.
- Which API to use for this device (OpenGL or Vulkan).
You can assign names to these device to refer to them elsewhere.
The `match` field is used to identify the device.
Unless you have two identical graphics cards installed, using the pci-vendor and model
fields is usually the best choice.
You can get these values by running `jay randr`.
You can select the device used for rendering the desktop with the top-level `render-device` field.
```toml
render-device.name = "dedicated"
```
You can modify the render device and configure GPUs at runtime with the `set-render-device`
and `configure-drm-device` actions.
You can use the top-level `gfx-api` field to set the default API used (unless overwritten for specific device).
```toml
gfx-api = "Vulkan"
```
See the specification for more details.
### Configuring Monitors
You can configure monitors with the top-level `outputs` field.
```toml
[[outputs]]
name = "left"
match.serial-number = "33K03894SL0"
x = 0
y = 0
[[outputs]]
name = "right"
match.serial-number = "ETW1M02062SL0"
x = 1920
y = 0
```
For each output, you can configure the following properties:
- The x, y coordinates in global compositor space.
- The scale to use for the monitor.
- The transformation to apply to the content (rotation, mirroring).
- The mode to use for the monitor.
You can query the available modes and modify these properties from the command line with
the `jay randr` command.
The `match` field selects the monitors the configuration applies to.
The serial number is usually a good unique identifier.
You can assign a name to monitors to refer to them in other places.
You can use the `configure-output` action to change this configuration at runtime.
See the specification for more details.
### Configuring Connectors
Connectors are the physical ports at the back of your GPU.
You can configure them with the top-level `connectors` array.
```toml
[[connectors]]
name = "eDP-1"
enabled = false
```
Currently you can only use this to disable or enable connectors.
This is useful to disable the internal monitor of a laptop when the laptop is closed.
You can use the `configure-connector` action to change this configuration at runtime.
See the specification for more details.
### Disabling Connectors of Closed Laptops
If a laptop has a switch that is signaled when the laptop is closed, you can configure
the built-in connector to be disabled automatically:
```toml
[[inputs]]
match.name = "<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 } }
```
See the specification for more details.
### Configuring Input Devices
You can configure input devices with the top-level `inputs` array.
```toml
[[inputs]]
tag = "mice"
match.is-pointer = true
left-handed = true
transform-matrix = [[0.35, 0], [0, 0.35]]
tap-enabled = true
```
For each input device you can configure the following properties:
- The libinput acceleration profile.
- The libinput acceleration speed.
- The libinput tap setting.
- The libinput tap-drag setting.
- The libinput tap-drag-lock setting.
- The libinput left-handed setting.
- The libinput natural-scrolling setting.
- The number of pixels to scroll per scroll-wheel dedent.
- A transformation matrix to apply to relative movements.
You can inspect and modify these settings from the command line with the `jay input` command.
The `match` field selects the input devices to operate on.
You can assign a `tag` to input devices to refer to them elsewhere.
You can use the `configure-input` action to change these settings at runtime.
See the specification for more details.
### Mapping Tablets to Outputs
You can map tablets to outputs using the `output` property:
```toml
[[outputs]]
name = "left"
match.serial-number = "33K03894SL0"
[[inputs]]
match.name = "Wacom Bamboo Comic 2FG Pen"
output.name = "left"
```
See the specification for more details.
### Theming
You can configure the colors, sizes, and fonts used by the compositor with the top-level `theme` table.
```toml
[theme]
bg-color = "#ff000"
```
See the specification for more details.
### Tray Icons and Menus
The default configuration will try to start [wl-tray-bridge] to give you access to tray
icons and menus.
[wl-tray-bridge]: https://github.com/mahkoh/wl-tray-bridge
### Window and Client Rules
This is described in [window-and-client-rules.md](window-and-client-rules.md).

View file

@ -1,229 +0,0 @@
# Features
## Configuration
Jay can be configured via
- a declarative TOML file or
- a shared library that gets injected into the compositor.
See [config.md](config.md) for more details.
## i3 Look and Feel
Jay's appearance is based on the default i3 look and feel.
Colors, sizes, and fonts can be customized.
## Stability
Jay has been stable for a long time.
Crashes and incorrect behavior in released versions are very rare.
Jay also aims to be forward and backward compatible for existing setups, allowing you to
upgrade or downgrade the compositor without having to adjust your configuration.
There is a small but growing integration test suite that is used to ensure this.
## CLI
Jay has a CLI that can be used to configure the compositor at runtime.
```
~$ jay
A wayland compositor
Usage: jay [OPTIONS] <COMMAND>
Commands:
run Run the compositor
config Create/modify the toml config
generate-completion Generate shell completion scripts for jay
log Open the log file
set-log-level Sets the log level
quit Stop the compositor
unlock Unlocks the compositor
screenshot Take a screenshot
idle Inspect/modify the idle (screensaver) settings
run-privileged Run a privileged program
run-tagged Run a program with a connection tag
seat-test Tests the events produced by a seat
portal Run the desktop portal
randr Inspect/modify graphics card and connector settings
input Inspect/modify input settings
xwayland Inspect/modify xwayland settings
color-management Inspect/modify the color-management settings
clients Inspect/manipulate the connected clients
tree Inspect the surface tree
control-center Opens the control center
version Prints the Jay version and exits
pid Prints the Jay PID and exits
help Print this message or the help of the given subcommand(s)
Options:
--log-level <LOG_LEVEL> The log level [default: info] [possible values: trace, debug, info, warn, error, off]
-h, --help Print help
```
## Multi-Monitor Support
Jay can be used with multiple monitors with hot-plug and hot-unplug support.
When a monitor is unplugged, all workspaces are automatically moved one of the remaining
monitors.
When the monitor is plugged in again, these workspaces are restored.
## Multi-GPU Support
Jay can be used with multiple GPUs and monitors connected to different GPUs.
One GPU is always used for rendering the desktop.
You can change this GPU at runtime.
## Screen Sharing
Jay supports screen sharing via xdg-desktop-portal.
There are three supported modes:
- Window capture
- Output capture
- Workspace capture which is like output capture except that only one workspace will be
shown.
## Screen Locking
Jay can automatically lock your screen and disable outputs after inactivity.
## Notifications
Jay supports the zwlr_layer_shell_v1 protocol used by notification daemons.
## Fractional Scaling
Jay supports per-monitor fractional scaling.
## OpenGL and Vulkan
Jay can use either OpenGL or Vulkan for rendering.
Vulkan offers better performance and memory usage but OpenGL is still provided for
older hardware.
You can change the API at runtime without restarting the compositor.
## Explicit Sync
Jay supports explicit sync for compatibility with Nvidia hardware.
## Clipboard Managers
Jay supports clipboard managers via `zwlr_data_control_manager_v1`.
## Privilege Separation
Jay splits protocols into unprivileged and privileged protocols.
By default, applications only have access to unprivileged protocols.
You can explicitly opt into giving applications access to privileged protocols via the Jay CLI or shortcuts.
## Push to Talk
Jay's shortcut system allows you to execute an action when a key is pressed and to execute a different action when the key is released.
## VR
Jay supports leasing VR headsets to applications.
## Adaptive Sync
Jay supports adaptive sync with configurable cursor refresh rates.
## Tearing
Jay supports tearing presentation for games.
## Low Input Latency
Jay uses frame scheduling to achieve input latency as low as 1.5 ms.
## Color Management & HDR
Jay supports the color management protocol and HDR10.
## Night Light
Jay supports night-light applications via `zwlr_gamma_control_manager_v1`.
## Window and Client Rules
Jay supports powerful window and client rules.
See [window-and-client-rules.md](window-and-client-rules.md) for more details.
## Protocol Support
Jay supports the following wayland protocols:
| Global | Version | Privileged |
|------------------------------------------------------|:----------------|---------------|
| ext_data_control_manager_v1 | 1 | Yes |
| ext_foreign_toplevel_image_capture_source_manager_v1 | 1 | |
| ext_foreign_toplevel_list_v1 | 1 | Yes |
| ext_idle_notifier_v1 | 2 | Yes |
| ext_image_copy_capture_manager_v1 | 1[^composited] | Yes |
| ext_output_image_capture_source_manager_v1 | 1 | |
| ext_session_lock_manager_v1 | 1 | Yes |
| ext_transient_seat_manager_v1 | 1[^ts_rejected] | Yes |
| ext_workspace_manager_v1 | 1 | Yes |
| jay_popup_ext_manager_v1 | 1 | |
| jay_tray_v1 | 1 | |
| org_kde_kwin_server_decoration_manager | 1 | |
| wl_compositor | 7 | |
| wl_data_device_manager | 4 | |
| wl_drm | 2 | |
| wl_fixes | 1 | |
| wl_output | 4 | |
| wl_seat | 10 | |
| wl_shm | 2 | |
| wl_subcompositor | 1 | |
| wp_alpha_modifier_v1 | 1 | |
| wp_color_manager_v1 | 2 | |
| wp_color_representation_manager_v1 | 1 | |
| wp_commit_timing_manager_v1 | 1 | |
| wp_content_type_manager_v1 | 1 | |
| wp_cursor_shape_manager_v1 | 2 | |
| wp_drm_lease_device_v1 | 1 | |
| wp_fifo_manager_v1 | 1 | |
| wp_fractional_scale_manager_v1 | 1 | |
| wp_linux_drm_syncobj_manager_v1 | 1 | |
| wp_pointer_warp_v1 | 1 | |
| wp_presentation | 2 | |
| wp_security_context_manager_v1 | 1 | |
| wp_single_pixel_buffer_manager_v1 | 1 | |
| wp_tearing_control_manager_v1 | 1 | |
| wp_viewporter | 1 | |
| xdg_activation_v1 | 1 | |
| xdg_toplevel_drag_manager_v1 | 1 | |
| xdg_toplevel_tag_manager_v1 | 1 | |
| xdg_wm_base | 7 | |
| xdg_wm_dialog_v1 | 1 | |
| zwlr_data_control_manager_v1 | 2 | Yes |
| zwlr_foreign_toplevel_manager_v1 | 3 | Yes |
| zwlr_gamma_control_manager_v1 | 1 | Yes |
| zwlr_layer_shell_v1 | 5 | No[^lsaccess] |
| zwlr_output_manager_v1 | 4 | Yes |
| zwlr_screencopy_manager_v1 | 3 | Yes |
| zwlr_virtual_pointer_manager_v1 | 2 | Yes |
| zwp_idle_inhibit_manager_v1 | 1 | |
| zwp_input_method_manager_v2 | 1 | Yes |
| zwp_linux_dmabuf_v1 | 5 | |
| zwp_pointer_constraints_v1 | 1 | |
| zwp_pointer_gestures_v1 | 3 | |
| zwp_primary_selection_device_manager_v1 | 1 | |
| zwp_relative_pointer_manager_v1 | 1 | |
| zwp_tablet_manager_v2 | 2 | |
| zwp_text_input_manager_v3 | 1 | |
| zwp_virtual_keyboard_manager_v1 | 1 | Yes |
| zxdg_decoration_manager_v1 | 2 | |
| zxdg_output_manager_v1 | 3 | |
[^lsaccess]: Sandboxes can restrict access to this protocol.
[^ts_rejected]: Seat creation is always rejected.
[^composited]: Cursors are always composited.

View file

@ -1,53 +0,0 @@
# Mouse Interactions
Jay supports a number of mouse-based interactions that might be hard to discover. This
file documents all of them.
- Inside a tiled container, the tiles can be resized by dragging the separators.
- Floating windows can be resized by dragging the borders.
- Floating windows can be moved by dragging the title.
- Tiles inside containers can be moved by dragging the title.
- Dragging them onto an existing workspace moves them to that workspace.
- Dragging them onto the bar outside an existing workspace creates a new workspace.
- Workspaces can be moved by dragging their titles with the mouse.
- In a container in mono layout, scrolling over the title switches between tiles.
- Scrolling over the bar switches between workspaces.
- Double clicking on a tile title/floating window title switches between floating and
tiling.
- Right clicking on any title in a container switches the container between mono and tiled
layout.
- Right clicking on the title of a floating window pins/unpins the window. (Pinned windows
are visible on all workspaces.)
- When the pin icon is visible on a floating window, left clicking the icon pins/unpins
the window.
- When selecting a toplevel (noticeable by the purple overlay), right clicking on the
title of any tile in a container selects that container.
- Any long running mouse interaction can be canceled by pressing escape.
## Window Management Mode
Window-management mode makes more interactions available. See the configurable
`window-management-key`.
- In window-management mode, floating windows, tiles, and popups can be resized by
dragging their contents with the right mouse button.
- In window-management mode, floating windows, tiles, popups, and fullscreen windows can
be moved by dragging their contents with the left mouse button.
- Entering window-management mode disables all pointer constraints and can therefore be
used to move the pointer out of windows that have grabbed the pointer.

View file

@ -1,127 +0,0 @@
# Building
## Compile-time Dependencies
The following libraries must be installed before compiling Jay:
- libinput.so
- libgbm.so
- libudev.so
- libpangocairo-1.0.so
- libfontconfig.so
You must also have a C compiler (GCC or Clang) and the latest version of rust installed.
You can install rust with [rustup](https://rustup.rs/).
## Runtime Dependencies
Most of these dependencies are optional and will enable additional features.
- Linux 6.7: Required for explicit sync.
- Xwayland: Required for running X applications.
- Pipewire: Required for screen sharing.
- logind (part of systemd): Required when running Jay from a virtual terminal.
- libEGL.so and libGLESv2.so: Required for the OpenGL renderer.
- libvulkan.so: Required for the Vulkan renderer.
Note that Jay will not work if neither the OpenGL nor the Vulkan renderer are available.
## Compiling
To compile the latest stable version of Jay, run
```
cargo install --locked jay-compositor
```
This will install Jay under `$HOME/.cargo/bin/jay`.
If you want to use the latest version from git, run
```
cargo install --locked --git https://github.com/mahkoh/jay.git jay-compositor
```
If you only want to build Jay without installing it, run the following command from within this repository:
```
cargo build --release
```
The binary is then available under `./target/release/jay`.
## Running with CAP_SYS_NICE
Jay supports being started with CAP_SYS_NICE capabilities. For example, such
capabilities can be added to the binary via
```shell
~# setcap cap_sys_nice=p jay
```
If CAP_SYS_NICE is available, Jay will, by default, elevate its scheduler to
SCHED_RR and create Vulkan queues with the highest available priority. This can
improve responsiveness if the CPU or GPU are under high load.
If Jay is started with the environment variable `JAY_NO_REALTIME=1` or a
`config.so` exists, then Jay will not elevate its scheduler but will still
create elevated Vulkan queues.
Jay will drop all capabilities almost immediately after being started. Before
that, it will spawn a dedicated thread that retains the CAP_SYS_NICE capability
to create elevated Vulkan queues later.
If Jay has elevated its scheduler to SCHED_RR, then it will refuse to load
`config.so` configurations. Otherwise unprivileged applications would be able
to run arbitrary code with SCHED_RR by crafting a dedicated `config.so`. This
behavior can be overridden by compiling Jay with
`JAY_ALLOW_REALTIME_CONFIG_SO=1`.
# Setup
## Configuration
See [config.md](./config.md).
## Screen Sharing
This step is only required to enable screen sharing.
1. Copy `../etc/jay.portal` to `/usr/share/xdg-desktop-portal/portals/jay.portal`.
2. Copy `../etc/jay-portals.conf` to `/usr/share/xdg-desktop-portal/jay-portals.conf`.
Then restart `xdg-deskop-portal`.
## Recommended Applications
- [xdg-desktop-portal-gtk4](https://github.com/mahkoh/xdg-desktop-portal-gtk4)
Provides a file-picker portal that supports thumbnails. It will be used
automatically if it is installed.
- [wl-tray-bridge](https://github.com/mahkoh/wl-tray-bridge)
Shows applications using the D-Bus StatusNotifierItem protocol as tray icons.
- [window-to-tray](https://github.com/mahkoh/wl-proxy/tree/master/apps/window-to-tray)
Allows you to run most wayland applications as tray applications. For example,
to get a quick-access volume mixer in the tray:
```shell
~$ window-to-tray pavucontrol-qt
```
# Mouse Interactions
See [mouse-interactions.md](./mouse-interactions.md).
# Running
1. Switch to a virtual terminal by pressing `ctrl-alt-F2` (or F3, F4, ...).
2. Run `jay run`.
If you have not yet changed the default configuration, you can
- quit Jay by pressing `alt-q`,
- start Alacritty by pressing the left Windows key.

View file

@ -1,261 +0,0 @@
# Window and Client Rules
Jay supports powerful window and client rules similar to i3.
## Example
```toml
# Move spotify to workspace 3 and fullscreen it.
[[windows]]
match.client.sandbox-app-id = "com.spotify.Client"
action = [
{ type = "move-to-workspace", name = "3" },
"enter-fullscreen",
]
# Spawn the Chromium screen sharing window, the GIMP splash screen, and the
# JetBrains splash screen floating and without focus stealing.
[[windows]]
match.any = [
{ title-regex = 'is sharing (your screen|a window)\.$', client.comm = "chromium" },
{ title = "GIMP Startup", app-id = "gimp" },
{ title = "splash", x-class-regex = "^jetbrains-(clion|rustrover)$" }
]
initial-tile-state = "floating"
auto-focus = false
# Spawn the JetBrains project selector floating.
[[windows]]
match.title-regex = "^Welcome to (RustRover|CLion)$"
match.x-class-regex = "^jetbrains-(clion|rustrover)$"
initial-tile-state = "floating"
```
## General Principles
Each rule consists of three components:
1. Criteria that determine which clients/windows the rule applies to.
2. An action to execute when a client/window starts matching the rule.
3. An action to execute when a client/window stops matching the rule.
Each rule can be assigned a name which allows other rules to refer to it.
Additionally, rules have ad-hoc properties for things that are not easily
expressed via actions, such as whether a window should be mapped floating or
tiled.
```toml
[[windows]]
name = "..." # the rule name
match = { } # the rule criteria
action = "..." # the action to run on start
latch = "..." # the action to run on stop
```
Rules are re-evaluated whenever any of the referenced criteria changes. That is,
if you have the following rule
```toml
[[windows]]
match.title = "VIM"
action = "enter-fullscreen"
```
then the window will enter fullscreen whenever title changes from something that
is not `VIM` to `VIM`. For window rules, if you only want to match windows that
have just been mapped, you can set the `just-mapped` criterion to `true`:
```toml
[[windows]]
match.title = "VIM"
match.just-mapped = true
action = "enter-fullscreen"
```
This is similar to the `initial-title` criterion found in some other
compositors.
Rules can trigger each other. For example:
```toml
[[windows]]
match.fullscreen = false
action = "enter-fullscreen"
[[windows]]
match.fullscreen = true
action = "exit-fullscreen"
```
This causes an infinite repetition of switching between windowed and fullscreen.
Jay prevents such loops from locking up the compositor by never performing more
than 1000 action callbacks before yielding to other work. However, they will
still cause the compositor to use 100% CPU and will likely cause affected
clients to be killed, since they won't be able to receive wayland messages fast
enough.
## Combining Criteria
Criteria can be combined with the following operations:
- `any` - match if any of a number of criteria match
- `all` - match if all of a number of criteria match
- `not` - match if a criterion does not match
- `exactly` - match if an exact number of criteria match
- `name` - match if another window rule with that name matches
```toml
# match windows that have the title `chromium` or `spotify`
match.any = [
{ title = "chromium" },
{ title = "spotify" },
]
# match windows whose title match both `chro` and `mium`
match.all = [
{ title-regex = "chro" },
{ title-regex = "mium" },
]
# match windows whose title is not `firefox`
match.not.title = "firefox"
# match windows whose title is `VIM` or whose clients are sandboxed, but not
# both
match.exactly.num = 1
match.exactly.list = [
{ title = "VIM" },
{ client.sandboxed = true },
]
# match if another rule called `another-rule-name` matches
match.name = "another-rule-name"
```
A criterion object has multiple fields, for example
```toml
match.title = "abc"
match.app-id = "xyz"
```
These fields are implicitly combined with `all` operator. That is, this behaves
just like
```toml
match.all = [
{ title = "abc" },
{ app-id = "xyz" },
]
```
## Finding Criteria Values
To determine which values to use in criteria, the `jay` executable provides the
subcommands `jay clients` and `jay tree` to inspect currently active clients and
open windows. For example
```text
~$ jay tree query select-window
- xdg-toplevel:
id: 258ae697663a1b8abc7e4da9570ad36f
pos: 1920x36 + 1920x1044
client:
id: 15
uid: 1000
pid: 2159136
comm: chromium
exe: /usr/lib/chromium/chromium
title: YouTube - Chromium
app-id: chromium
workspace: 2
visible
```
In this case, `select-window` allows you to interactively select a window and
then prints its properties.
## Client Rules
```toml
# start executable `b` whenever a client with executable `A` connects
[[clients]]
match.exe = "A"
action = { type = "exec", exec = "b" }
```
All properties that can be referred to in client criteria are currently
constant over the lifetime of the client.
### Client Criteria
The full specification of client criteria can be found in
[spec.generated.md](../toml-spec/spec/spec.generated.md).
- `sandboxed` - Matches clients that are/aren't sandboxed.
- `sandbox-engine`, `sandbox-engine-regex` - Matches the sandbox engine that was
used to wrap this client. Usually `org.flatpak`.
- `sandbox-app-id`, `sandbox-app-id-regex` - Matches the app-id provided by the
sandbox engine
- `sandbox-instance-id-id`, `sandbox-instance-id-regex` - Matches the
instance-id provided by the sandbox engine
- `uid`, `pid` - Matches the UID/PID of the client.
- `is-xwayland` - Matches if the client is/isn't Xwayland.
- `comm`, `comm-regex` - Matches the `/proc/self/comm` of the client.
- `exe`, `exe-regex` - Matches the `/proc/self/exe` of the client.
- `tag`, `tag-regex` - Matches the tag of the client.
## Window Rules
## Ad-hoc Window Rules
Rule actions are evaluated asynchronously. For window rules, this means that
they are evaluated after the window has been mapped but before it is displayed
for the first time. This makes them ill-suited for things that need to be fixed
during the mapping process. Ad-hoc window rules can be used to bridge this gap:
```toml
[[windows]]
match.title = "chromium"
initial-tile-state = "floating"
auto-focus = false
```
The `initial-tile-state` rule can be used to define whether the window is mapped
tiled or floating. If no such rule exists, this is determined via heuristics.
If multiple such rules exist and match a window, the compositor picks one at
random.
The `auto-focus` rule determines if the window is automatically focused when it
is mapped. If no such rule exists, newly mapped windows always get the keyboard
focus except in some cases involving Xwayland. If multiple such rules exist and
match a window, then the window _does not_ get the focus if _any_ of them is set
to `false`.
## Window Criteria
The full specification of window criteria can be found in
[spec.generated.md](../toml-spec/spec/spec.generated.md).
- `types` - Matches the type of a window. Currently there are four types:
containers, placeholders, xdg toplevels, and X windows. If the rule does not
contain such a criterion, the rule will only match windows created by clients,
that is, xdg toplevels and X windows.
- `client` - This is a client criterion. See above.
- `title`, `title-regex` - Matches the title of the window.
- `app-id`, `app-id-regex` - Matches the XDG app-id of the window.
- `floating` - Matches if the window is/isn't floating.
- `visible` - Matches if the window is/isn't visible.
- `urgent` - Matches if the window wants/doesn't want attentions.
- `focused` - Matches if the window is/isn't focused.
- `fullscreen` - Matches if the window is/isn't fullscreen.
- `just-mapped` - Matches if the window has/hasn't just been mapped. This is
true for a single frame after the window has been mapped.
- `tag`, `tag-regex` - Matches the XDG toplevel tag of the window.
- `x-class`, `x-class-regex` - Matches the X class of the window.
- `x-instance`, `x-instance-regex` - Matches the X instance of the window.
- `x-role`, `x-role-regex` - Matches the X role of the window.
- `workspace`, `workspace-regex` - Matches the workspace of the window.
- `content-types` - Matches the content type of a window. Currently there are
three types: photos, videos, and games.