sway(5)

๐Ÿ’– NAME ๐Ÿ’–

okay bestie, welcome to sway(5) โ€” the File Formats Manual page that's literally all about the sway config file and its commands. The main character here is sway: configuration file and commands. ๐Ÿซถโœจ

๐ŸŒธ DESCRIPTION ๐ŸŒธ

A sway configuration file is just a list of sway commands that sway executes on startup. Usually these commands are you setting your preferences and setting key bindings โ€” aka making your setup feel like you. Thereโ€™s likely an example config hanging out in /etc/sway/config for you to check out. ๐Ÿ‘‘

Lines in the configuration file can be extended through multiple lines by adding a \ character at the end of the line, like this:

bindsym Shift+XF86AudioRaiseVolume exec \
     pactl set-sink-volume @DEFAULT_SINK@ -1%

Commands can also be given as a block in the form command { <subcommands...> }. Anything before the opening { will be prepended to the lines inside the block. For example:

output eDP-1 {
     background ~/wallpaper.png fill
     resolution 1920x1080
}

is identical to

output eDP-1 background ~/wallpaper.png fill
output eDP-1 resolution 1920x1080

These commands can be executed in your config file, via swaymsg(1), or via the bindsym command. ๐Ÿ’…๐ŸŒฟ

๐ŸŽ€ COMMAND CONVENTIONS ๐ŸŽ€

Commands are split into several arguments using spaces. You can enclose arguments with quotation marks ("..." or '...') to add spaces to a single argument. You may also run several commands in order by separating each with , or ;. Criteria is retained across commands separated by ,, but will be reset (and allow for new criteria, if desired) for commands separated by ;. iykyk โ€” that distinction matters.

Throughout the documentation, | is used to distinguish between arguments for which you may only select one. [...] is used for optional arguments, and <...> for arguments where you are expected to supply some value. So when you see <...>, thatโ€™s your cue to fill in the blank, bestie. ๐Ÿฆ‹

โœจ COMMANDS โœจ

This section only lists general commands. For input and output commands, refer to sway-input(5) and sway-output(5). Noted and bookmarked. ๐Ÿ“Œ

๐Ÿฆ‹ Config only commands ๐Ÿฆ‹

The following commands may only be used in the configuration file.

  • bar [<bar-id>] <bar-subcommands...> โ€” For details on bar subcommands, see sway-bar(5).
  • default_orientation horizontal|vertical|auto โ€” Sets the default container layout for tiled containers.
  • include <paths...> โ€” Include files from paths. paths can include either a full path or a path relative to the parent config, and expands shell syntax (see wordexp(3) for details). The same include file can only be included once; subsequent attempts will be ignored.
  • swaybg_command <command> โ€” Executes custom background command. Default is swaybg. Refer to sway-output(5) for more information. It can be disabled by setting the command to a single dash: swaybg_command -.
  • swaynag_command <command> โ€” Executes custom command for swaynag. Default is swaynag. Additional arguments may be appended to the end. This should only be used to either direct sway to call swaynag from a custom path or to provide additional arguments. This should be placed at the top of the config for the best results. It can be disabled by setting the command to a single dash: swaynag_command -.
  • workspace_layout default|stacking|tabbed โ€” Specifies the initial layout for new containers in an empty workspace.
  • xwayland enable|disable|force โ€” Enables or disables Xwayland support, which allows X11 applications to be used. enable will lazily load Xwayland so Xwayland will not be launched until the first client attempts to connect. In some cases, such as slower machines, it may be desirable to have Xwayland started immediately by using force instead of enable.

๐Ÿ’€ Runtime only commands ๐Ÿ’€

The following commands cannot be used directly in the configuration file. They are expected to be used with bindsym or at runtime through swaymsg(1).

  • border none|normal|csd|pixel [<n>] โ€” Set border style for focused window. normal includes a border of thickness n and a title bar. pixel is a border without title bar n pixels thick. The title bar always shows in stacking or tabbed layouts. csd is short for client-side-decorations, which allows the client to draw its own decorations. Default is normal with border thickness 2.
  • border toggle โ€” Cycles through the available border styles.
  • exit โ€” Exit sway and end your Wayland session. dramatic, but valid. ๐Ÿ’€
  • floating enable|disable|toggle โ€” Make focused window floating, non-floating, or the opposite of what it is now.
  • <criteria> focus โ€” Moves focus to the container that matches the specified criteria.
  • focus up|right|down|left โ€” Moves focus to the next container in the specified direction.
  • focus prev|next [sibling] โ€” Moves focus to the previous or next container in the current layout. By default, the last active child of the newly focused container will be focused. The sibling option indicates not to immediately focus a child of the container.
  • focus child โ€” Moves focus to the last-focused child of the focused container.
  • focus parent โ€” Moves focus to the parent of the focused container.
  • focus output up|right|down|left โ€” Moves focus to the next output in the specified direction.
  • focus output <name> โ€” Moves focus to the named output.
  • focus tiling โ€” Sets focus to the last focused tiling container.
  • focus floating โ€” Sets focus to the last focused floating container.
  • focus mode_toggle โ€” Moves focus between the floating and tiled layers.
  • fullscreen [enable|disable|toggle] [global] โ€” Makes focused window fullscreen, non-fullscreen, or the opposite of what it is now. If no argument is given, it does the same as toggle. If global is specified, the window will be fullscreen across all outputs.
  • gaps inner|outer|horizontal|vertical|top|right|bottom|left all|current set|plus|minus|toggle <amount> โ€” Changes the inner or outer gaps for either all workspaces or the current workspace. outer gaps can be altered per side with top, right, bottom, and left or per direction with horizontal and vertical.
  • inhibit_idle focus|fullscreen|open|none|visible โ€” Set/unset an idle inhibitor for the window. focus will inhibit idle when the window is focused by any seat. fullscreen will inhibit idle when the view is fullscreen (or a descendant of a fullscreen container) and is visible. open will inhibit idle until the window is closed (or the inhibitor is unset/changed). visible will inhibit idle when the window is visible on any output. none will remove any existing idle inhibitor for the window. This can also be used with criteria to set an idle inhibitor for any existing window or with for_window to set idle inhibitors for future windows.
  • layout default|splith|splitv|stacking|tabbed โ€” Sets the layout mode of the focused container. When using the stacking layout, only the focused window in the container is displayed, with the opened windowsโ€™ list on the top of the container. The tabbed layout is similar to stacking, but the windowsโ€™ list is vertically split.
  • layout toggle [split|all] โ€” Cycles the layout mode of the focused container through a preset list of layouts. If no argument is given, then it cycles through stacking, tabbed and the last split layout. If split is given, then it cycles through splith and splitv. If all is given, then it cycles through every layout.
  • layout toggle [split|tabbed|stacking|splitv|splith] [split|tabbed|stacking|splitv|splith]... โ€” Cycles the layout mode of the focused container through a list of layouts.
  • max_render_time off|<msec> โ€” Controls when the relevant application is told to render this window, as a positive number of milliseconds before the next time sway composites the output. A smaller number leads to fresher rendered frames being composited by sway and lower perceived input latency, but if set too low, the application may not finish rendering before sway composites the output, leading to delayed frames.

When set to off, the relevant application is told to render this window immediately after display refresh. How much time is left for rendering before sway composites the output at that point depends on the output max_render_time setting.

To set this up for optimal latency:

  1. Set up output max_render_time (see sway-output(5)).
  2. Put the target application in full-screen and have it continuously render something.
  3. Start by setting max_render_time 1. If the application drops frames, increment by 1.

This setting only has an effect if a per-output max_render_time is in effect on the output the window is currently on. See sway-output(5) for further details.

  • allow_tearing yes|no โ€” Allows or disallows screen tearing as a result of immediate page flips for a fullscreen application. When this option is not set, the tearing hints provided by the application determine whether tearing is allowed. When yes is specified, the application allows tearing regardless of the tearing hints. When no is specified, tearing will never be allowed on the application, regardless of the tearing hints. This setting only has an effect if tearing is allowed on the output through the per-output allow_tearing setting. See sway-output(5) for further details.
  • move left|right|up|down [<px> px] โ€” Moves the focused container in the direction specified. The optional px argument specifies how many pixels to move the container. If unspecified, the default is 10 pixels. Pixels are ignored when moving tiled containers.
  • move [absolute] position <pos_x> [px|ppt] <pos_y> [px|ppt] โ€” Moves the focused container to the specified position in the workspace. The position can be specified in pixels or percentage points, omitting the unit defaults to pixels. If absolute is used, the position is relative to all outputs. absolute can not be used with percentage points.
  • move [absolute] position center โ€” Moves the focused container to be centered on the workspace. If absolute is used, it is moved to the center of all outputs.
  • move position cursor|mouse|pointer โ€” Moves the focused container to be centered on the cursor.
  • move [container|window] [to] mark <mark> โ€” Moves the focused container to the specified mark.
  • move [--no-auto-back-and-forth] [container|window] [to] workspace [number] <name> โ€” Moves the focused container to the specified workspace. The string number is optional and is used to match a workspace with the same number, even if it has a different name.

move [container|window] [to] workspace prev|next|current

okay so this one yeets the focused container over to the previous, next, or current workspace on this output โ€” and if there aren't any workspaces left to move to, it hops to the previous or next output instead. it's giving "no vacancy, try next door" ๐Ÿ’…

move [container|window] [to] workspace prev_on_output|next_on_output

same energy but it stays locked to this output โ€” previous or next workspace, and it wraps around if you're already sitting on the first or last one. no escaping, bestie ๐ŸŒ€

move [container|window] [to] workspace back_and_forth

sends the focused container back to whichever workspace you were on before. the "undo" of workspace jumps fr fr โ†ฉ๏ธ

move [container|window] [to] output <name-or-id>|current

moves the focused container to the output you name (by name or id), or to current if you're feeling lazy about it.

move [container|window] [to] output up|right|down|left

directional vibes โ€” sends the focused container to the next output in whichever direction you point at. arrows only, no coordinates ๐Ÿงญ

move [container|window] [to] scratchpad

into the scratchpad it goes. the container is now in timeout ๐Ÿ˜Œ

move workspace [to] output <name-or-id>|current

heads up: this one moves the whole workspace, not a single container. point it at an output name/id, or current.

move workspace to [output] <name-or-id>|current

literally the exact same thing as above, just with to before [output]. same destination, different word order ๐ŸŽ€

move workspace [to] output up|right|down|left

whole workspace, next output, in the direction you point. slay.

move workspace to [output] up|right|down|left

again โ€” same as the one above, just reordered. the grammar is flexible, the behavior isn't ๐Ÿ’–

nop <comment>

a literal no-operation command. it does nothing, which is the whole point โ€” you use it to override default behaviour. the optional comment argument is ignored but gets logged for debugging purposes. so it's a note-to-self that also blocks whatever would've happened otherwise ๐Ÿ“

reload

reloads the sway config file and applies any changes. where does it look? at the path given in the command line arguments when sway was started, otherwise according to the priority stated in sway(1). refresh button, but make it fashion โœจ

rename workspace [<old_name>] to <new_name>

renames either old_name or the focused workspace to new_name. pick a name, any name ๐Ÿท๏ธ

resize shrink|grow up|right|down|left|width|height [<amount> [px|ppt]]

resizes the currently focused container by amount, in pixels or percentage points.

  • if you omit the units: floating containers resize in px and tiled containers resize by ppt
  • if you omit amount: it defaults to 10

for tiled containers, space is taken from / given to the container in the specified direction. but if you say width or height, then the space is taken/given from all the other containers instead. choose wisely ๐Ÿ’…

resize set height <height> [px|ppt]

sets the container's height to height, in pixels or percentage points. no units? floating containers resize in px, tiled by ppt. if height is 0, the container will not be resized, no cap. for tiling containers, space comes from / goes to all other containers ๐Ÿ“

resize set [width] <width> [px|ppt]

sets the width to width, px or ppt, same unit rules as ever (floating โ†’ px, tiled โ†’ ppt). if width is 0, no resize on that axis, periodt. tiling containers take/give space from all the other containers ๐Ÿซถ

resize set [width] <width> [px|ppt] [height] <height> [px|ppt]

both axes at once, iconic. width and height, px or ppt, same rules: units omitted โ†’ floating containers in px, tiled containers by ppt. if width or height is 0, the container just won't be resized on that axis. tiling containers take/give space from all the other containers. two birds, one command ๐Ÿฆ‹

scratchpad show

shows a window from the scratchpad. keep hitting it and it'll cycle through the windows in the scratchpad. it's a carousel, basically ๐ŸŽ 

shortcuts_inhibitor enable|disable

enables or disables whether clients can inhibit keyboard shortcuts for a window. mainly useful for virtualization and remote desktop software.

it affects either the currently focused window, or a set of windows picked out by criteria. and the disable subcommand additionally deactivates any active inhibitors for the given window(s).

criteria are especially useful with the for_window command, so you can configure a class of windows differently from the per-seat defaults established by the seat subcommand of the same name. see sway-input(5) for more ways to affect inhibitors. very much a "read the other doc too" situation ๐Ÿ“š

split vertical|v|horizontal|h|none|n|toggle|t

splits the current container, vertically or horizontally.

  • none โ†’ the effect of a previous split is undone, if the current container is the only child of a split parent
  • toggle โ†’ the current container is split opposite to the parent container's layout

short names v, h, n, t all work too. choose your fighter โš”๏ธ

splith

equivalent to split horizontal. that's it. that's the whole command ๐Ÿ’–

splitv

equivalent to split vertical. shortest entry in the whole page and honestly? respect.

splitt

equivalent to split toggle. ๐ŸŽ€

sticky enable|disable|toggle

"sticks" a floating window to the current output so it shows up on all workspaces. it follows you around like a loyal little ghost ๐Ÿ‘ป

swap container with id|con_id|mark <arg>

swaps the position, geometry, and fullscreen status of two containers.

  • the first container is selected by criteria or by focus
  • the second container is selected by id, con_id, or mark
  • id can only be used with xwayland windows

about focus: if the first container has focus, it keeps focus โ€” unless it's moved to a different workspace, or the second container becomes fullscreen on the same workspace as the first. in either of those cases, the second container gains focus. swap responsibly ๐Ÿ”„

title_format <format>

sets the format of window titles. the following placeholders may be used:

  • %title โ€” the title supplied by the window
  • %app_id โ€” the wayland app ID (applicable to wayland windows only)
  • %class โ€” the X11 classname (applicable to xwayland windows only)
  • %instance โ€” the X11 instance (applicable to xwayland windows only)
  • %shell โ€” the protocol the window is using (typically xwayland or xdg_shell)
  • %sandbox_engine โ€” the associated sandbox engine
  • %sandbox_app_id โ€” the app ID provided by the associated sandbox engine
  • %sandbox_instance_id โ€” the instance ID provided by the associated sandbox engine

this command is typically used with for_window criteria. for example:

for_window [title="."] title_format "<b>%title</b> (%app_id)"

note that markup requires pango to be enabled via the font command. the default format is "%title". โœจ


๐ŸŒธ Config or runtime commands ๐ŸŒธ

these bad boys can be used either in the config file or at runtime. flexible queens ๐Ÿ’…

assign <criteria> [โ†’] [workspace] [number] <workspace>

assigns windows matching criteria (see CRITERIA for details) to workspace. that โ†’ (U+2192) is optional and purely cosmetic โ€” it's just there to look cute. this command is equivalent to:

for_window <criteria> move container to workspace <workspace>

assign <criteria> [โ†’] output left|right|up|down|<name>

assigns windows matching criteria (see CRITERIA for details) to the specified output. again, โ†’ (U+2192) is optional and cosmetic. equivalent to:

for_window <criteria> move container to output <output>

bindsym [--whole-window] [--border] [--exclude-titlebar] [--release] [--locked] [--to-code] [--input-device=<device>] [--no-warn] [--no-repeat] [--inhibited] [Group<1-4>+]<key combo> <command>

binds key combo to run the sway command command when pressed. the big one ๐Ÿ‘‘

you can use XKB key names here โ€” wev(1) is a good tool for discovering those, highly recommend.

  • with --release, the command runs when the key combo is released
  • if input-device is given, the binding only runs for that input device, and it runs instead of any binding generic to all devices
  • if a group number is given, the binding is only available for that group
  • by default, if you overwrite a binding, swaynag warns you. to silence that, use --no-warn ๐Ÿคซ

for specifying modifier keys, you can use the XKB modifier names Shift, Lock (for Caps Lock), Control, Mod1 (for Alt), Mod2 (for Num Lock), Mod3 (for XKB modifier Mod3), Mod4 (for the Logo key), and Mod5 (for AltGr). plus you can use the aliases Ctrl (for Control), Alt (for Alt), and Super (for the Logo key). so many nicknames ๐ŸŽ€

unless --locked is set, the command will not run when a screen locking program is active. if there's a matching binding both with and without --locked, the one with it is preferred when locked, and the one without it is preferred when unlocked. and if there are matching bindings where one has both --input-device and --locked and the other has neither, the former is preferred even when unlocked. yes, the preference logic is sending me too ๐Ÿ˜ญ

unless --inhibited is set, the command will not run when a keyboard shortcuts inhibitor is active for the currently focused window. remote desktop and virtualization software usually request these inhibitors so the user can send keyboard shortcuts to the remote or virtual session. --inhibited lets you define bindings exempt from that pass-through. same preference logic as --locked applies ๐Ÿซถ

unless --no-repeat is set, the command runs repeatedly while the key is held, according to the repeat settings in your input configuration. hold and pray, bestie ๐Ÿ”

bindings to keysyms are layout-dependent. you can change that with --to-code, in which case the keysyms get translated into the corresponding keycodes in the first configured layout.

mouse bindings operate on the container under the cursor instead of the container that has focus. mouse buttons can be given as button[1-9] or by the name of the event code (ex BTN_LEFT or BTN_RIGHT).

  • for the numbered form, buttons map to their X11 values: 1=left, 2=middle, 3=right, 4=scroll up, 5=scroll down, 6=scroll left, 7=scroll right, 8=back, 9=forward
  • for the named form, you can find event names using libinput debug-events

the priority for matching bindings is as follows: input device, group, and locked state. that's the whole hierarchy, memorize it for the quiz ๐Ÿ“–โœจ

okay so picking up right where we left off ๐Ÿ’… โ€” the mouse-only trio is --whole-window, --border, and --exclude-titlebar, and they change the region where mouse bindings can actually be triggered. By default, mouse bindings are only triggered when you're over the title bar. With the --border option, the border of the window gets included in that region. With the --whole-window option, the cursor can be anywhere over a window โ€” title, border, and content all count. And --exclude-titlebar can be used in conjunction with any other option to say โ€œbestie, leave the titlebar out of the region of consideration.โ€

If --whole-window is given, the command can be triggered when the cursor is over an empty workspace. Using a mouse binding over a layer surface's exclusive region is not currently possible. iykyk ๐Ÿฆ‹

Example:

# Execute firefox when alt, shift, and f are pressed together
bindsym Mod1+Shift+f exec firefox

bindcode is also available for binding with key/button codes instead of key/button names:

bindcode [--whole-window] [--border] [--exclude-titlebar]
[--release] [--locked] [--input-device=<device>] [--no-warn] [--no-repeat]
[--inhibited] [Group<1-4>+]<code> <command>

bindswitch โ€” synopsis:

bindswitch [--locked] [--no-warn] [--reload] <switch>:<state> <command>

This binds <switch> to execute the sway command command on state changes. Supported switches are lid (laptop lid), tablet (tablet mode), and keypad_slide (whether the device keypad is exposed or not). Valid values for state are on, off, and toggle. These switches are on when the device lid is shut, when tablet mode is active, and when the keypad is exposed respectively. toggle is also supported to run a command both when the switch is toggled on or off. periodt โœจ

Unless the flag --locked is set, the command will not be run when a screen locking program is active. If there is a matching binding with and without --locked, the one with will be preferred when locked and the one without will be preferred when unlocked.

If the --reload flag is given, the binding will also be executed when the config is reloaded. toggle bindings will not be executed on reload. The --locked flag will operate as normal, so if the config is reloaded while locked and --locked is not given, the binding will not be executed.

By default, if you overwrite a binding, swaynag will give you a warning. To silence this, use the --no-warn flag. no cap ๐Ÿซถ

Example:

# Show the virtual keyboard when tablet mode is entered.
bindswitch tablet:on busctl call --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 SetVisible b true

# Log a message when the laptop lid is opened or closed.
bindswitch lid:toggle exec echo "Lid moved"

bindgesture โ€” synopsis:

bindgesture [--exact] [--input-device=<device>] [--no-warn]
<gesture>[:<fingers>][:directions] <command>

This binds gesture to execute the sway command command when detected. Currently supports the hold, pinch, or swipe gesture. Optionally it can be limited to bind to a certain number of fingers or, for a pinch or swipe gesture, to certain directions.

The gesture type / fingers / direction situation is literally:

  • hold โ€” fingers 1 - 5; direction none
  • swipe โ€” fingers 3 - 5; direction up, down, left, right
  • pinch โ€” fingers 2 - 5; direction all above + inward, outward, clockwise, counterclockwise

The fingers can be limited to any sensible number or left empty to accept any finger counts. Valid directions are up, down, left, and right, as well as inward, outward, clockwise, counterclockwise for the pinch gesture. Multiple directions can be combined by a plus.

If an input-device is given, the binding will only be executed for that input device and will be executed instead of any binding that is generic to all devices. By default, if you overwrite a binding, swaynag will give you a warning. To silence this, use the --no-warn flag.

The --exact flag can be used to ensure a binding only matches when exactly all specified directions are matched and nothing more. If there is a matching binding with --exact, it will be preferred. the way that priority works ๐Ÿ’œ

The priority for matching bindings is as follows: input device, then exact matches followed by matches with the highest number of matching directions.

Gestures executed while the pointer is above a bar are not handled by sway. See the respective documentation, e.g. bindgesture in sway-bar(5).

Example:

# Allow switching between workspaces with left and right swipes
bindgesture swipe:right workspace prev
bindgesture swipe:left workspace next

# Allow container movements by pinching them
bindgesture pinch:inward+up move up
bindgesture pinch:inward+down move down
bindgesture pinch:inward+left move left
bindgesture pinch:inward+right move right

client.background โ€” synopsis:

client.background <color>

This command is ignored and is only present for i3 compatibility. not me being a compatibility icon ๐Ÿ™ˆ


client.<class> โ€” synopsis:

client.<class> <border> <background> <text> [<indicator> [<child_border>]]

Configures the color of window borders and title bars. The first three colors are required. When omitted, indicator will use a sane default and child_border will use the color set for background. Colors may be specified in hex, either as #RRGGBB or #RRGGBBAA.

The available classes are:

  • client.focused โ€” The window that has focus.
  • client.focused_inactive โ€” The most recently focused window within a container which is not focused.
  • client.focused_tab_title โ€” A window that has focused descendant container. Tab or stack container title that is the parent of the focused container but is not directly focused. Defaults to focused_inactive if not specified and does not use the indicator and child_border colors.
  • client.placeholder โ€” Ignored (present for i3 compatibility).
  • client.unfocused โ€” A window that does not have focus.
  • client.urgent โ€” A window with an urgency hint. Note: Native Wayland windows do not support urgency. Urgency only works for Xwayland windows. important caveat bestie ๐Ÿ’€

The meaning of each color is:

  • border โ€” The border around the title bar.
  • background โ€” The background of the title bar.
  • text โ€” The text color of the title bar.
  • indicator โ€” The color used to indicate where a new window will open. In a tiled container, this would paint the right border of the current window if a new window would be opened to the right.
  • child_border โ€” The border around the window itself.

The default colors are: ๐ŸŽ€

  • background โ€” border n/a; background #ffffff; text n/a; indicator n/a; child_border n/a
  • focused โ€” border #4c7899; background #285577; text #ffffff; indicator #2e9ef4; child_border #285577
  • focused_inactive โ€” border #333333; background #5f676a; text #ffffff; indicator #484e50; child_border #5f676a
  • focused_tab_title โ€” border #333333; background #5f676a; text #ffffff; indicator n/a; child_border n/a
  • unfocused โ€” border #333333; background #222222; text #888888; indicator #292d2e; child_border #222222
  • urgent โ€” border #2f343a; background #900000; text #ffffff; indicator #900000; child_border #900000
  • placeholder โ€” border #000000; background #0c0c0c; text #ffffff; indicator #000000; child_border #0c0c0c

default_border normal|none|pixel [<n>]

Bestie, this sets the default border style for new tiled windows. And when I say new, I mean new โ€” a config reload won't retroactively glow-up the windows you already have open, only the freshly created ones after the reload. Main character energy only for the newbies โœจ

default_floating_border normal|none|pixel [<n>]

Same deal but for new floating windows ๐ŸŽ€ And pay attention here: this only applies to windows that are spawned in floating mode. If a window was tiled and then becomes floating later? Not covered, babes. It keeps its old border situation.

exec <shell command>

Runs shell command with sh. That's it. That's the whole vibe ๐Ÿซถ

exec_always <shell command>

Exactly like exec, except the shell command gets executed again after reload. So if you've got something that needs to re-run every time you tweak your config, this is your girl ๐Ÿ’…

floating_maximum_size <width> x <height>

Sets the maximum size of floating windows ๐Ÿ“ Fancy -1 x -1 removes the upper limit entirely โ€” go wild, no cap. The default is 0 x 0, which lowkey means "just use the width and height of the entire output layout as the maximums."

floating_minimum_size <width> x <height>

Sets the minimum size of floating windows. The default is 75 x 50. Don't let them shrink into oblivion ๐Ÿฅบ

floating_modifier <modifier> [normal|inverse]

Okay so when the modifier key is held down, you can hold left click to move windows and right click to resize them. Iconic mouse behavior, honestly.

  • Set modifier to none and the whole feature is disabled.
  • If you throw in inverse, the clicks swap: left click is for resizing and right click is for moving.

focus_follows_mouse yes|no|always

  • yes โ€” moving your mouse over a window will focus that window. Cursor says jump, window says how high.
  • always โ€” the window under the cursor is always focused, even after you switch between workspaces. No escape ๐Ÿ˜ญ

focus_on_window_activation smart|urgent|focus|none

This one decides what happens when a client requests window activation ๐Ÿ‘‘

  • urgent โ€” the urgent state gets set for that window.
  • focus โ€” the window just becomes focused, periodt.
  • smart โ€” the window becomes focused only if it's already visible; otherwise the urgent state gets set.
  • none โ€” presumably nothing happens, bestie.

Default is urgent.

focus_wrapping yes|no|force|workspace

What do we do when you try to focus over the edge of a container? Great question, here's the tea:

  • no โ€” the focused container retains focus if there are no other containers in that direction.
  • yes โ€” focus wraps to the opposite edge of the container, if there are no other containers in the direction.
  • force โ€” focus wraps to the opposite edge of the container even if there are other containers in the direction. Chaotic. Love it.
  • workspace โ€” wraps like the yes case, and additionally wraps when moving outside of workspace boundaries.

Default is yes โœจ

font [pango:]<font>

Sets the font used for title bars. To enable support for pango markup, preface the font name with pango: ๐ŸŽจ

For example, monospace 10 is the default font. To enable pango markup support, you'd use pango:monospace 10 instead. And regardless of whether pango markup is enabled, font should be specified as a pango font description. For more info on those, the original points you here:

https://docs.gtk.org/Pango/type_func.FontDescription.from_string.html#description

force_display_urgency_hint <timeout> [ms]

Okay so picture this: an app on another workspace sets an urgency hint. You switch to that workspace and it may immediately focus the app โ€” which also means the window decoration color gets immediately reset to client.focused. Which makes it unnecessarily hard to tell which window originally raised the event ๐Ÿ’€

This option lets you set a timeout in ms to delay the urgency hint reset. Problem solved, we love a fix.

titlebar_border_thickness <thickness>

Thickness of the titlebar border, in pixels. Simple, clean, iconic ๐Ÿ’…

titlebar_padding <horizontal> [<vertical>]

Padding of the text in the titlebar.

  • The horizontal value affects the horizontal padding of the text.
  • The vertical value affects the vertical padding โ€” that's the space above and below the text.

Heads up bestie: padding includes titlebar borders, so their value should be greater than titlebar_border_thickness. And if you don't specify a vertical value, it's set to the horizontal value. Convenient ๐ŸŽ€

for_window <criteria> <command>

Whenever a window matching criteria appears, run that list of commands. See CRITERIA for the details โ€” go off, automate your life ๐ŸŒˆ

gaps inner|outer|horizontal|vertical|top|right|bottom|left <amount>

Sets the default amount in pixels of inner or outer gap, where:

  • inner affects the spacing around each window ๐ŸชŸ
  • outer affects the spacing around each workspace ๐ŸŒ

Outer gaps are in addition to inner gaps. And to reduce or remove outer gaps, outer gaps can be set to a negative value โ€” yes, negative, we're breaking the rules ๐Ÿ’€

Outer gaps can also be specified per side with top, right, bottom, and left, or per direction with horizontal and vertical.

This affects new workspaces only, and it's used when the workspace doesn't have its own gaps settings (see: workspace <ws> gaps ...).

hide_edge_borders [--i3] none|vertical|horizontal|both|smart|smart_no_gaps

Hides window borders adjacent to the screen edges. Default is none.

The --i3 option enables i3-compatible behavior to hide the title bar on tabbed and stacked containers with one child. And heads up: the smart|smart_no_gaps options are equivalent to setting smart_borders smart|no_gaps and hide_edge_borders none. iykyk โœจ

input <input_device> <input-subcommands...>

For the details on the input subcommands, go read sway-input(5) ๐Ÿ“–

Oh and โ€” * may be used in lieu of a specific device name to configure all input devices. Get the list of input device names via:

swaymsg -t get_inputs

seat <seat> <seat-subcommands...>

For the details on the seat subcommands, see sway-input(5) again. Same bestie, different section ๐Ÿซถ

kill

Kills (closes) the currently focused container and all of its children. Brutal but efficient ๐Ÿ’€

smart_borders on|no_gaps|off

  • If smart_borders is on, borders are only enabled if the workspace has more than one visible child.
  • If it's set to no_gaps, borders are only enabled if the workspace has more than one visible child and gaps equal to zero.

Smart, right? ๐Ÿง 

smart_gaps on|off|toggle|inverse_outer

  • on โ€” gaps are only enabled if a workspace has more than one child.
  • inverse_outer โ€” outer gaps are only enabled if a workspace has exactly one child. Weirdly specific and honestly kind of iconic.
  • Plus off and toggle, because sometimes you just gotta flip it.

mark --add|--replace [--toggle] <identifier>

Marks are arbitrary labels used to identify certain windows and then jump to them later ๐ŸŽฏ Each identifier can only be set on a single window at a time, since they act as a unique identifier โ€” no sharing, babes.

By default, mark sets identifier as the only mark on a window. Then:

  • --add will instead add identifier to the list of current marks for that window.
  • --toggle โ€” if specified, mark will remove identifier if it's already marked.

mode <mode>

Switches to the specified mode. The default mode is default. Slay, you're in default mode ๐ŸŽ€

mode [--pango_markup] <mode> <mode-subcommands...>

The only valid mode-subcommands... are bindsym, bindcode, bindswitch, and set. And if --pango_markup is given, then mode will be interpreted as pango markup โœจ

mouse_warping output|container|none

  • output โ€” the mouse moves to new outputs as you move focus between them.
  • container โ€” the mouse moves to the middle of the container on switch.
  • none โ€” mouse stays put, I guess. Respect.

Default is output ๐Ÿ–ฑ๏ธ

no_focus <criteria>

Prevents windows matching criteria from being focused automatically when they're created ๐Ÿšซ Big fan of this one. Fair warning though: this has no effect on the first window in a workspace โ€” that one's always the main character.

output <output_name> <output-subcommands...>

Details on the output subcommands live in sway-output(5) ๐Ÿ“บ

Also: * may be used in lieu of a specific output name to configure all outputs. Get your list of output names with:

swaymsg -t get_outputs

What do we do when a fullscreen window opens a dialog? The drama ๐Ÿ˜ญ

  • smart (the default) โ€” the dialog will be displayed.
  • ignore โ€” the dialog will not be rendered. Rude, but okay.
  • leave_fullscreen โ€” the window will exit fullscreen mode and the dialog will be rendered.

primary_selection enabled|disabled

Enable or disable the primary selection clipboard. May only be configured at launch โ€” so no mid-session glow-ups. Default is enabled ๐Ÿ’–

set $<name> <value>

Sets variable $name to value. You can use that new variable in the arguments of future commands โ€” iconic, honestly.

When the variable is used, it can be escaped with an additional $ (i.e. $$name) to have the replacement happen at run time instead of when reading the config. But ngl, it doesn't always make sense for the variable to be replaced at run time, since some arguments do need to be known at config time. Think before you $$, bestie ๐Ÿง 

show_marks yes|no

If show_marks is yes, marks will be displayed in the window borders โœจ But any mark starting with an underscore will not be drawn, even if show_marks is yes โ€” sneaky hidden marks, we love. The default is yes.

opacity [set|plus|minus] <value>

Adjusts the opacity of the window between 0 (completely transparent) and 1 (completely opaque) ๐Ÿซง

If the operation is omitted, set will be used. Simple as that.

tiling_drag enable|disable|toggle

Sets whether or not tiling containers can be dragged with the mouse ๐Ÿ–ฑ๏ธ

  • If enabled (the default), the floating_mod can be used to drag tiling, as well as floating, containers.
  • Using the left mouse button on title bars without the floating_mod will also allow the container to be dragged.
toggle should not be used in the config file. Just... don't, bestie ๐Ÿ˜ญ

tiling_drag_threshold <threshold>

Sets the threshold that must be exceeded for a container to be dragged by its titlebar ๐Ÿ“

  • This has no effect if floating_mod is used, or if tiling_drag is set to disable.
  • Once the threshold has been exceeded once, the drag starts and the cursor can come back inside the threshold without stopping the drag. Nice, right?
  • threshold is multiplied by the scale of the output that the cursor is on.
  • The default is 9.

title_align left|center|right

Sets the title alignment. And heads up: if right is selected and show_marks is set to yes, the marks will be shown on the left side instead of the right side. Plot twist ๐ŸŒ€

unbindswitch <switch>:<state>

Removes a binding for when switch changes to state. Clean, surgical, done ๐Ÿ’…

unbindgesture [--exact] [--input-device=<device>] <gesture>[:<fingers>][:directions]

Removes a binding for the specified gesture, fingers and directions combination. Swipe away, babes ๐Ÿ–๏ธ

unbindsym [--whole-window] [--border] [--exclude-titlebar] [--release] [--locked] [--to-code] [--input-device=<device>] <key combo>

Removes the binding for key combo that was previously bound with the given flags ๐ŸŽน

And if input-device is given, only the binding for that input device will be unbound. Specificity is a love language ๐Ÿ’œ

  • unbindcode [--whole-window] [--border] [--exclude-titlebar] [--release] [--locked] [--input-device=<device>] <code> โ€” literally unbind but you're feeding it raw key/button codes instead of the cute key/button names. Same options, same energy ๐ŸŽ€
  • unmark [<identifier>] โ€” takes identifier off the list of current marks on a window. Leave it out and it nukes every mark on that window. Clean slate era ๐Ÿ’…
  • urgent enable|disable|allow|deny โ€” okay so enable / disable manually set or unset the window's urgent state (you're the one deciding, main character energy ๐Ÿ‘‘). allow / deny control whether the window is even allowed to set itself urgent. And the default? Windows are allowed to set their own urgency, no cap.
  • workspace [--no-auto-back-and-forth] [number] <[num:]name> โ€” jumps you to the workspace you asked for. The num: bit of the name is optional and it's just there for ordering purposes. If you don't give a num: and name happens to be a number, then that number doubles as the ordering value. iykyk โœจ

If the no-auto-back-and-forth option is in play, this command will not do the back-and-forth thing when the workspace is already focused and workspace_auto_back_and_forth is enabled.

And if you specify the number keyword and a workspace with that number already exists, then the workspace with that number gets used. If there's no workspace with that number yet, a brand new workspace is created with the name name. ๐Ÿฆ‹

  • workspace prev|next โ€” switches to the next workspace on the current output โ€” or onto the next output if you're already chillin' on the last workspace.
  • workspace prev_on_output|next_on_output โ€” switches to the next workspace on the current output, and nowhere else. Stay in your lane bestie ๐ŸŒธ
  • workspace back_and_forth โ€” switches to the workspace you were focused on previously. The classic "wait, go back" ๐Ÿ˜ญ
  • workspace <name> gaps inner|outer|horizontal|vertical|top|right|bottom|left <amount> โ€” says that workspace name should get these gaps settings when it's created.
Heads up: this does not touch existing workspaces. If you wanna change gaps on a workspace that already exists, use the gaps command instead, okay?
  • workspace <name> output <outputs...> โ€” says workspace name should be shown on the outputs you list. You can list multiple outputs and the first available one gets used. And if the workspace lands on an output further down the list and a higher-priority output becomes available later, the workspace gets moved up to that higher priority output. Glow-up in real time ๐Ÿ”ฅ
Again, this does not affect existing workspaces. To move one that already exists, use the move command together with the workspace criteria (non-empty workspaces only), or the workspace command to switch to the workspace before moving.
  • workspace_auto_back_and_forth yes|no โ€” when it's yes, repeating a workspace switch command switches you back to the prior workspace. Example time: you're on workspace 1, you switch to workspace 2, then you invoke that workspace 2 command again โ€” boom, you're back on workspace 1. Default is no. ๐Ÿ”

๐ŸŽฏ CRITERIA ๐ŸŽฏ

A criteria is a lil string shaped like this, for example:

[app_id="some-application" title="[Rr]egex.*"]

It contains one or more attribute/value pairs, space separated. Some commands use criteria to pick which windows to run their action on. All the attributes have to match for the criteria to match โ€” no partial credit, sorry ๐Ÿซถ

Criteria is retained across commands separated by a ,, but it gets reset (and you can add new criteria if you want) for commands separated by a ;. Slay, punctuation matters.

Criteria can be used with either the for_window or assign commands to say what operations to perform on new windows. A criteria can also be used to run specific commands (the ones that'd normally act on one window) on all the windows that match. For example:

Focus on a window with the mark "IRC":

[con_mark="IRC"] focus

Kill all windows where the title contains "Emacs":

[title="Emacs"] kill

Several attributes let you use regular expressions. Those are Perl-compatible regular expressions (PCRE2), documented in pcre2pattern(3) and summarized in pcre2syntax(3). For example, this moves all windows with titles ending in "sway" or "Sway" to workspace 1:

[title="[Ss]way$"] move workspace 1

You may like to use swaymsg -t get_tree to find the actual values of these properties for your applications in practice. Fr fr, it's the move ๐Ÿ’–

The following attributes may be matched with:

  • all โ€” matches all windows. Every single one, no notes.
  • app_id โ€” compares the value against the app id. Can be a regular expression. If the value is __focused__, then the app id has to be the same as the currently focused window's. app_id is specific to Wayland applications. ๐Ÿฆ‹
  • class โ€” compares the value against the window class. Can be a regular expression. If the value is __focused__, then the window class has to match the currently focused window's. class is specific to X11 applications and requires XWayland.
  • con_id โ€” compares against the internal container ID, which you can find via IPC. If the value is __focused__, the id has to match the currently focused window's.
  • con_mark โ€” compares against the window marks. Can be a regular expression.
  • floating โ€” matches floating windows.
  • id โ€” compares the value against the X11 window ID. Must be numeric. id is specific to X11 applications and requires XWayland.
  • instance โ€” compares the value against the window instance. Can be a regular expression. If the value is __focused__, then the window instance has to match the currently focused window's. instance is specific to X11 applications and requires XWayland.
  • pid โ€” compares the value against the window's process ID. Must be numeric.
  • shell โ€” compares the value against the window shell, like "xdg_shell" or "xwayland". Can be a regular expression. If the value is __focused__, then the shell has to match the currently focused window's.
  • tag โ€” compares the value against the tag. tag is specific to Wayland applications.
  • tiling โ€” matches tiling windows.
  • title โ€” compares against the window title. Can be a regular expression. If the value is __focused__, then the window title has to match the currently focused window's.
  • urgent โ€” compares the urgent state of the window. Can be first, last, latest, newest, oldest or recent.
  • window_role โ€” compares against the window role (WM_WINDOW_ROLE). Can be a regular expression. If the value is __focused__, then the window role has to match the currently focused window's. window_role is specific to X11 applications and requires XWayland.
  • window_type โ€” compares against the window type (_NET_WM_WINDOW_TYPE). Possible values are normal, dialog, utility, toolbar, splash, menu, dropdown_menu, popup_menu, tooltip and notification. window_type is specific to X11 applications and requires XWayland.
  • workspace โ€” compares against the workspace name for this window. Can be a regular expression. If the value is __focused__, then all the windows on the currently focused workspace match. ๐Ÿ‘‘
  • sandbox_engine โ€” compares against the associated sandbox engine. Can be a regular expression. If the value is __focused__, then the sandbox engine has to match the currently focused window's.
  • sandbox_app_id โ€” compares against the app ID provided by the associated sandbox engine. Can be a regular expression. If the value is __focused__, then the sandbox app ID has to match the currently focused window's.
  • sandbox_instance_id โ€” compares against the instance ID provided by the associated sandbox engine. Can be a regular expression. If the value is __focused__, then the sandbox instance ID has to match the currently focused window's.

๐Ÿ‘€ SEE ALSO ๐Ÿ‘€

sway(1) sway-input(5) sway-output(5) sway-bar(5) sway-ipc(7) pcre2pattern(3) pcre2syntax(3)


And that's the whole page bestie, you ate that ๐Ÿ“ This is sway(5) โ€” dated 2026-04-26, so go forth and tile, mwah ๐Ÿ’œโœจ

๐Ÿ“ฆ where this page comes from